You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
2.1 KiB
TypeScript
74 lines
2.1 KiB
TypeScript
// frontend/components/tasks/TreeNode.tsx
|
|
"use client";
|
|
import { Icon } from "@/components/Icon";
|
|
import { cx } from "@/lib/cx";
|
|
import type { Project } from "@/lib/types";
|
|
|
|
interface Props {
|
|
node: Project;
|
|
depth: number;
|
|
sel: string;
|
|
onSelect: (id: string) => void;
|
|
expanded: Record<string, boolean>;
|
|
onToggle: (id: string) => void;
|
|
onPin: (id: string) => void;
|
|
counts: Record<string, number>;
|
|
}
|
|
|
|
export function TreeNode({ node, depth, sel, onSelect, expanded, onToggle, onPin, counts }: Props) {
|
|
const hasCh = node.children.length > 0;
|
|
const open = !!expanded[node.id];
|
|
return (
|
|
<>
|
|
<div
|
|
className={cx("tree-row", sel === node.id && "on")}
|
|
style={{ paddingLeft: 8 + depth * 15 }}
|
|
onClick={() => onSelect(node.id)}
|
|
>
|
|
{hasCh ? (
|
|
<button
|
|
className={cx("tree-chev", open && "open")}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
onToggle(node.id);
|
|
}}
|
|
aria-label="펼치기"
|
|
>
|
|
<Icon name="chev" />
|
|
</button>
|
|
) : (
|
|
<span className="tree-chev-spacer" />
|
|
)}
|
|
<span className="tree-dot" style={{ background: `var(--${node.tone})` }} />
|
|
<span className="tree-name">{node.name}</span>
|
|
{counts[node.id] > 0 && <span className="tree-count">{counts[node.id]}</span>}
|
|
<button
|
|
className={cx("tree-pin", node.pinned && "on")}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
onPin(node.id);
|
|
}}
|
|
aria-label="즐겨찾기"
|
|
>
|
|
<Icon name="star" w={node.pinned ? 0 : 1.9} fill={node.pinned ? "currentColor" : "none"} />
|
|
</button>
|
|
</div>
|
|
{hasCh &&
|
|
open &&
|
|
node.children.map((c) => (
|
|
<TreeNode
|
|
key={c.id}
|
|
node={c}
|
|
depth={depth + 1}
|
|
sel={sel}
|
|
onSelect={onSelect}
|
|
expanded={expanded}
|
|
onToggle={onToggle}
|
|
onPin={onPin}
|
|
counts={counts}
|
|
/>
|
|
))}
|
|
</>
|
|
);
|
|
}
|