49 lines
1.3 KiB
TypeScript
49 lines
1.3 KiB
TypeScript
"use client";
|
||
|
||
import { useEffect, useState } from "react";
|
||
import type { ReactNode } from "react";
|
||
|
||
export function snippetCommentCountEvent(snippetId: number) {
|
||
return `j13:snippet:${snippetId}:comment-count`;
|
||
}
|
||
|
||
/**
|
||
* 片段详情顶部的评论计数 chip:
|
||
* 初始值来自 SSR,评论区增删后通过 window CustomEvent 同步。
|
||
*/
|
||
export default function SnippetCommentCountChip({
|
||
snippetId,
|
||
initial,
|
||
icon,
|
||
label,
|
||
}: {
|
||
snippetId: number;
|
||
initial: number;
|
||
icon: ReactNode;
|
||
label: string;
|
||
}) {
|
||
const [count, setCount] = useState(initial);
|
||
|
||
useEffect(() => {
|
||
const handler = (e: Event) => {
|
||
const next = (e as CustomEvent<number>).detail;
|
||
if (typeof next === "number") setCount(next);
|
||
};
|
||
const name = snippetCommentCountEvent(snippetId);
|
||
window.addEventListener(name, handler);
|
||
return () => window.removeEventListener(name, handler);
|
||
}, [snippetId]);
|
||
|
||
return (
|
||
<span
|
||
className="inline-flex items-center gap-1.5 h-7 px-2.5 rounded-full text-[11.5px] tabular-nums"
|
||
style={{ background: "var(--panel-2)", color: "var(--ink-3)", border: "1px solid var(--line)" }}
|
||
title={`${count} ${label}`}
|
||
>
|
||
<span style={{ color: "var(--ink-3)" }}>{icon}</span>
|
||
{count}
|
||
<span className="hidden sm:inline">{label}</span>
|
||
</span>
|
||
);
|
||
}
|