4.2 KiB
4.2 KiB
Tasks: enterprise-react-tree-view
Change ID: enterprise-react-tree-view
Package: @suaveplan/react-tree-view
Target path: react/ui/react-tree-view
Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/react-translate, @suaveplan/react-virtual
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- Create directory tree per proposal layout.
- Write
package.jsonat0.1.0with"sideEffects": false, exports map. - Dependencies:
@suaveplan/error workspace:^,@suaveplan/react-translate workspace:^,@suaveplan/react-virtual workspace:^,zod catalog:forms,tslib catalog:build. - Write
tsconfig.json,vitest.config.ts, scripts.
2. Types and errors
- Define
TreeViewErrorextendingSuaveplanError; code:TREE_VIEW_CONTEXT_MISSING. - Define
TreeNode<T>:{ id: string; label: string; children?: TreeNode<T>[]; data?: T; disabled?: boolean }. - Define
TreeViewProps<T>,UseTreeStateOptions,UseTreeStateReturn.
3. Utils (src/utils/tree-utils/)
- Implement
flattenTree<T>(root)— DFS traversal, returns flat array. - Implement
filterTree<T>(root, predicate)— returns subtree containing matching nodes;nullif no match. - Implement
collectAllIds<T>(root)— returns allidvalues. - Write
tree-utils.test.ts(≤500 lines): flat tree, nested tree, filter no-match, filter partial-match, collectAllIds deep.{ timeout: 5000 }. - Write
tree-utils.md.
4. Hook — useTreeState
- Manages
expandedIds: Set<string>inuseState. - Exposes
toggle(id),expand(id),collapse(id),expandAll(tree),collapseAll(),isExpanded(id). - Controlled mode: accepts
expandedIds+onExpandedChangeprops; uncontrolled: manages internally. - Activates
@suaveplan/react-virtualuseVirtualListwhenflattenTree(root).length > 100. - Write
use-tree-state.test.ts: toggle, expand, collapse, expandAll, collapseAll, controlled mode, uncontrolled mode.{ timeout: 5000 }. - Write
use-tree-state.md.
5. Components
TreeNodeComponent
- Renders arrow indicator (collapsed/expanded), indent per
depth, optionalshowLines,renderNodeslot for custom node markup. - Keyboard:
ArrowRightexpands,ArrowLeftcollapses (or moves to parent when already collapsed),ArrowDown/ArrowUpmoves focus to next/prev visible node. aria-expanded,aria-selected,role="treeitem",tabIndexmanagement.- Write test, stories (default, with-custom-render, playground), md.
TreeView
- Top-level controlled/uncontrolled tree: optional search input (
showSearchprop) usinguseTranslationfor placeholder; filters viafilterTreeon input change. - Renders
TreeNodeComponentfor each visible node; uses virtual list when node count > 100. role="tree",aria-labelfrom i18n.- Write test, stories (default, large-tree 500 nodes, with-search, keyboard-nav, playground), md.
6. E2E
e2e/tree-view.spec.ts— Playwright:- Render tree, click expand arrow, verify children visible.
- Keyboard: Tab into tree,
ArrowRightto expand,ArrowDownto move focus,ArrowLeftto collapse. - Type in search box, verify filtered nodes only.
7. Verify and publish
bunx turbo lint typecheck test --filter=@suaveplan/react-tree-view— green.bunx turbo test:coverage --filter=@suaveplan/react-tree-view— 100%.bun scripts/publish.ts --package @suaveplan/react-tree-view.- Archive change folder.