@darksnow-ui/node-tree-react
Version:
Ready-to-use React component for node-tree-headless
1 lines • 28.6 kB
Source Map (JSON)
{"version":3,"sources":["../src/components/NodeTree.tsx","../src/components/TreeNode.tsx","../src/components/NodeWrapper.tsx","../src/components/ContextMenu.tsx"],"sourcesContent":["import {\n useNodeTree,\n useNodeTreeState,\n useContextMenu,\n NodeRow,\n Node\n} from \"@darksnow-ui/node-tree-headless\";\nimport { TreeNode } from \"./TreeNode\";\nimport { ContextMenu } from \"./ContextMenu\";\nimport { useState, useCallback } from \"react\";\nimport { clsx } from \"clsx\";\n\nexport interface NodeTreeProps {\n className?: string;\n style?: React.CSSProperties;\n renderNode?: (props: { row: any }) => React.ReactNode;\n renderEmptyState?: () => React.ReactNode;\n onContextMenuAction?: (action: string, nodeId: string) => void;\n indentSize?: number;\n showContextMenu?: boolean;\n contextMenuClassName?: string;\n emptyStateClassName?: string;\n showRootDropArea?: boolean;\n rootDropAreaClassName?: string;\n renderRootDropArea?: (isDragOver: boolean) => React.ReactNode;\n resolveIcon?: (node: Node, isExpanded: boolean) => string;\n}\n\nexport function NodeTree({\n className,\n style,\n renderNode,\n renderEmptyState,\n onContextMenuAction,\n indentSize = 20,\n showContextMenu = true,\n contextMenuClassName,\n emptyStateClassName,\n showRootDropArea = true,\n rootDropAreaClassName,\n renderRootDropArea,\n resolveIcon,\n}: NodeTreeProps) {\n const context = useNodeTree();\n const indexedNodes = useNodeTreeState((state) => state.indexedNodes);\n const nodes = useNodeTreeState((state) => state.nodes);\n const dragOverId = useNodeTreeState((state) => state.dragOverId);\n const dragStartId = useNodeTreeState((state) => state.dragStartId);\n const { contextMenu, closeContextMenu } = useContextMenu();\n const [hasFocus, setHasFocus] = useState(false);\n\n const defaultRenderNode = useCallback(\n (row: NodeRow) => {\n const node = nodes.get(row.id);\n if (!node) return null;\n\n const state = context.services.store.getState();\n const enhancedRow = {\n ...row,\n node,\n selected: state.selectedNodes.has(row.id),\n expanded: state.expandedNodes.has(row.id),\n visible: true,\n isCursor: state.cursorId === row.id,\n isFocus: state.focusId === row.id,\n };\n\n return (\n <TreeNode\n key={row.id}\n row={enhancedRow}\n indentSize={indentSize}\n resolveIcon={resolveIcon}\n />\n );\n },\n [nodes, context.services.store, indentSize],\n );\n\n const defaultRenderEmptyState = () => (\n <div\n className={\n emptyStateClassName ||\n \"text-center py-8 text-gray-500 dark:text-gray-400\"\n }\n >\n No nodes to display\n </div>\n );\n\n const defaultRenderRootDropArea = (isDragOver: boolean) => (\n <div\n className={clsx(\n rootDropAreaClassName || \"node-tree-root-drop-area\",\n isDragOver && \"drag-over\",\n )}\n style={{\n flex: 1,\n minHeight: \"20px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.2s ease\",\n cursor: \"pointer\",\n }}\n />\n );\n\n return (\n <>\n <div\n ref={context.elementRef}\n tabIndex={0}\n className={clsx(\n \"node-tree-container\",\n hasFocus && \"has-focus\",\n className,\n )}\n style={{\n ...style,\n display: \"flex\",\n flexDirection: \"column\",\n height: \"100%\",\n }}\n onFocus={() => setHasFocus(true)}\n onBlur={() => setHasFocus(false)}\n >\n <div className=\"node-tree-content\" style={{ flexShrink: 0 }}>\n {indexedNodes && indexedNodes.length > 0\n ? indexedNodes.map((row: NodeRow) => {\n if (renderNode) {\n const node = nodes.get(row.id);\n if (!node) return null;\n\n const state = context.services.store.getState();\n const enhancedRow = {\n ...row,\n node,\n selected: state.selectedNodes.has(row.id),\n expanded: state.expandedNodes.has(row.id),\n visible: true,\n isCursor: state.cursorId === row.id,\n isFocus: state.focusId === row.id,\n };\n\n return renderNode({ row: enhancedRow });\n }\n return defaultRenderNode(row);\n })\n : renderEmptyState\n ? renderEmptyState()\n : defaultRenderEmptyState()}\n </div>\n\n {/* Root Drop Area - sempre visível quando houver nodes e showRootDropArea for true */}\n {showRootDropArea && indexedNodes && indexedNodes.length > 0 && (\n <div\n {...context.handlers.rootDropProps}\n style={{ flex: 1, display: \"flex\" }}\n >\n {renderRootDropArea\n ? renderRootDropArea(dragOverId === \"root\")\n : defaultRenderRootDropArea(dragOverId === \"root\")}\n </div>\n )}\n </div>\n\n {showContextMenu && contextMenu && (\n <ContextMenu\n x={contextMenu.x}\n y={contextMenu.y}\n nodeId={contextMenu.nodeId}\n containerElementRef={contextMenu.containerElementRef}\n onClose={closeContextMenu}\n className={contextMenuClassName}\n onAction={onContextMenuAction}\n />\n )}\n </>\n );\n}\n","import {\n useNodeTreeState,\n Node,\n NodeRow,\n} from \"@darksnow-ui/node-tree-headless\";\nimport { ChevronRight, ChevronDown } from \"lucide-react\";\nimport { clsx } from \"clsx\";\nimport { NodeWrapper } from \"./NodeWrapper\";\n\ninterface EnhancedNodeRow extends NodeRow {\n node: Node;\n selected: boolean;\n expanded: boolean;\n visible: boolean;\n isCursor?: boolean;\n isFocus?: boolean;\n}\n\ninterface TreeNodeProps {\n row: EnhancedNodeRow;\n renderLabel?: (node: Node) => React.ReactNode;\n renderIcon?: (node: Node, isExpanded: boolean) => React.ReactNode;\n indentSize?: number;\n}\n\ninterface TreeNodeProps {\n row: EnhancedNodeRow;\n renderLabel?: (node: Node) => React.ReactNode;\n resolveIcon?: (node: Node, isExpanded: boolean) => string;\n indentSize?: number;\n}\n\nexport function TreeNode({\n row,\n renderLabel,\n resolveIcon,\n indentSize = 20,\n}: TreeNodeProps) {\n const { node } = row;\n const isExpanded = useNodeTreeState((s) => s.expandedNodes.has(node.id));\n const isSelected = useNodeTreeState((s) => s.selectedNodes.has(node.id));\n const isCursor = useNodeTreeState((s) => s.cursorId === node.id);\n const isFocus = useNodeTreeState((s) => s.focusId === node.id);\n const isDragOver = useNodeTreeState((s) => s.dragOverId === node.id);\n\n // Default icon resolver\n const defaultIconResolver = (node: Node, isExpanded: boolean) => {\n if (!node.expandable) {\n const ext = node.label.split(\".\").pop()?.toLowerCase();\n switch (ext) {\n case \"ts\":\n return \"typescript\";\n case \"tsx\":\n return \"react_ts\";\n case \"js\":\n return \"javascript\";\n case \"jsx\":\n return \"react\";\n case \"json\":\n return \"json\";\n case \"md\":\n return \"markdown\";\n default:\n return \"file\";\n }\n }\n return isExpanded ? \"folder-open\" : \"folder\";\n };\n\n const iconName = resolveIcon\n ? resolveIcon(node, isExpanded)\n : defaultIconResolver(node, isExpanded);\n\n return (\n <NodeWrapper\n id={node.id}\n className={clsx(\n \"group flex items-center px-2 cursor-pointer relative\",\n \"hover:bg-vscode-list-hoverBackground\",\n isSelected && \"bg-vscode-list-activeSelectionBackground\",\n isCursor && \"outline outline-1 outline-vscode-focusBorder\",\n isDragOver && \"bg-vscode-list-dropBackground\",\n node.expandable && \"expandable\",\n )}\n >\n {/* Indent spacer */}\n <div style={{ width: `${row.level * indentSize}px` }} />\n\n {/* Expander */}\n <div className=\"flex items-center justify-center w-5 h-5\">\n {node.expandable ? (\n <span\n className={clsx(\n \"flex items-center justify-center w-full h-full\",\n \"hover:bg-vscode-border/50 rounded transition-colors\",\n )}\n aria-expanded={isExpanded}\n >\n {isExpanded ? (\n <ChevronDown className=\"w-3 h-3\" />\n ) : (\n <ChevronRight className=\"w-3 h-3\" />\n )}\n </span>\n ) : null}\n </div>\n\n {/* Icon usando classe CSS */}\n <div className=\"flex-shrink-0 mr-2\">\n <i className={`icon icon-${iconName}`} />\n </div>\n\n {/* Label */}\n <span\n className={clsx(\n \"flex-1 text-sm truncate\",\n isSelected\n ? \"text-vscode-list-activeSelectionForeground\"\n : \"text-vscode-foreground\",\n // isFocus && \"font-semibold\",\n )}\n aria-selected={isSelected}\n >\n {renderLabel ? renderLabel(node) : node.label}\n </span>\n </NodeWrapper>\n );\n}\n","import { useNodeTree, useNodeTreeState } from \"@darksnow-ui/node-tree-headless\";\nimport { memo, useMemo } from \"react\";\nimport { clsx } from \"clsx\";\n\ninterface NodeWrapperProps {\n id: string;\n children: React.ReactNode;\n className?: string;\n}\n\nexport const NodeWrapper = memo(\n ({ id, children, className }: NodeWrapperProps) => {\n const { handlers } = useNodeTree();\n\n // Get ALL necessary handlers from the system\n const wrapperProps = useMemo(\n () => handlers.wrapperProps(id),\n [handlers, id],\n );\n\n // Get visual states\n const isSelected = useNodeTreeState((s) => s.selectedNodes.has(id));\n const isFocused = useNodeTreeState((s) => s.focusId === id);\n const isCursor = useNodeTreeState((s) => s.cursorId === id);\n const isDragOver = useNodeTreeState((s) => s.dragOverId === id);\n const isDragging = useNodeTreeState((s) => s.dragStartId === id);\n\n return (\n <div\n {...wrapperProps}\n data-node-id={id}\n className={clsx(\n \"node-wrapper\",\n className,\n isSelected && \"selected\",\n isFocused && \"focused\",\n isCursor && \"cursor\",\n isDragOver && \"drag-over\",\n isDragging && \"dragging\",\n )}\n >\n {children}\n </div>\n );\n },\n);\n\nNodeWrapper.displayName = \"NodeWrapper\";\n","import { useNodeTree } from \"@darksnow-ui/node-tree-headless\";\nimport { useEffect, useRef } from \"react\";\nimport {\n FolderPlus,\n FilePlus,\n Trash2,\n Edit2,\n Copy,\n Scissors,\n Clipboard,\n FolderOpen,\n FolderClosed,\n} from \"lucide-react\";\n\nexport interface ContextMenuProps {\n x: number;\n y: number;\n nodeId: string;\n containerElementRef?: React.RefObject<HTMLDivElement>;\n onClose: () => void;\n className?: string;\n onAction?: (action: string, nodeId: string) => void;\n}\n\nexport function ContextMenu({\n x,\n y,\n nodeId,\n containerElementRef,\n onClose,\n className,\n onAction,\n}: ContextMenuProps) {\n const { services, controller } = useNodeTree();\n const menuRef = useRef<HTMLDivElement>(null);\n const nodes = services.store.getState().nodes;\n const isRoot = nodeId === \"root\" || !nodeId;\n const node = isRoot ? null : nodes.get(nodeId);\n const isExpanded = !isRoot && services.store.getState().expandedNodes.has(nodeId);\n\n // Focus management\n useEffect(() => {\n // Focus the menu when it opens\n menuRef.current?.focus();\n\n // Return focus to tree when menu closes\n return () => {\n containerElementRef?.current?.focus();\n };\n }, [containerElementRef]);\n\n // Handle escape key\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n onClose();\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [onClose]);\n\n const handleAction = async (\n action: () => void | Promise<void>,\n actionName?: string,\n ) => {\n await action();\n if (actionName && onAction) {\n onAction(actionName, nodeId);\n }\n onClose();\n };\n\n // Menu específico para root\n if (isRoot) {\n return (\n <div\n ref={menuRef}\n className={className || \"context-menu\"}\n style={{ left: x, top: y }}\n onClick={(e) => e.stopPropagation()}\n tabIndex={-1}\n >\n <button\n className=\"context-menu-item\"\n onClick={() =>\n handleAction(async () => {\n const name = prompt(\"New folder name:\");\n if (name) {\n await controller.createNode(undefined, name); // undefined = root\n }\n }, \"create-folder\")\n }\n >\n <FolderPlus className=\"w-4 h-4\" />\n <span>New Folder</span>\n </button>\n <button\n className=\"context-menu-item\"\n onClick={() =>\n handleAction(async () => {\n const name = prompt(\"New file name:\");\n if (name) {\n await controller.createNode(undefined, name); // undefined = root\n }\n }, \"create-file\")\n }\n >\n <FilePlus className=\"w-4 h-4\" />\n <span>New File</span>\n </button>\n {services.store.getState().clipboardNodes?.length > 0 && (\n <>\n <div className=\"context-menu-divider\" />\n <button\n className=\"context-menu-item\"\n onClick={() =>\n handleAction(async () => {\n await controller.pasteNodes(undefined); // undefined = root\n }, \"paste\")\n }\n >\n <Clipboard className=\"w-4 h-4\" />\n <span>Paste</span>\n </button>\n </>\n )}\n </div>\n );\n }\n\n // Se não é root e não tem node, retorna null\n if (!node) return null;\n\n return (\n <div\n ref={menuRef}\n className={className || \"context-menu\"}\n style={{ left: x, top: y }}\n onClick={(e) => e.stopPropagation()}\n tabIndex={-1}\n >\n {/* Expand/Collapse for folders */}\n {node.expandable && (\n <>\n <button\n className=\"context-menu-item\"\n onClick={() =>\n handleAction(\n () => {\n if (isExpanded) {\n services.navigationService.collapseNode(nodeId);\n } else {\n services.navigationService.expandNode(nodeId);\n }\n },\n isExpanded ? \"collapse\" : \"expand\",\n )\n }\n >\n {isExpanded ? (\n <>\n <FolderClosed className=\"w-4 h-4\" />\n <span>Collapse</span>\n </>\n ) : (\n <>\n <FolderOpen className=\"w-4 h-4\" />\n <span>Expand</span>\n </>\n )}\n </button>\n <div className=\"context-menu-divider\" />\n </>\n )}\n\n {/* Create actions for folders */}\n {node.expandable && (\n <>\n <button\n className=\"context-menu-item\"\n onClick={() =>\n handleAction(async () => {\n const name = prompt(\"New folder name:\");\n if (name) {\n await controller.createNode(nodeId, name);\n }\n }, \"create-folder\")\n }\n >\n <FolderPlus className=\"w-4 h-4\" />\n <span>New Folder</span>\n </button>\n <button\n className=\"context-menu-item\"\n onClick={() =>\n handleAction(async () => {\n const name = prompt(\"New file name:\");\n if (name) {\n await controller.createNode(nodeId, name);\n }\n }, \"create-file\")\n }\n >\n <FilePlus className=\"w-4 h-4\" />\n <span>New File</span>\n </button>\n <div className=\"context-menu-divider\" />\n </>\n )}\n\n {/* Common actions */}\n <button\n className=\"context-menu-item\"\n onClick={() =>\n handleAction(() => {\n controller.copyNodes([nodeId]);\n }, \"copy\")\n }\n >\n <Copy className=\"w-4 h-4\" />\n <span>Copy</span>\n </button>\n <button\n className=\"context-menu-item\"\n onClick={() =>\n handleAction(() => {\n controller.cutNodes([nodeId]);\n }, \"cut\")\n }\n >\n <Scissors className=\"w-4 h-4\" />\n <span>Cut</span>\n </button>\n {node.expandable && (\n <button\n className=\"context-menu-item\"\n onClick={() =>\n handleAction(async () => {\n await controller.pasteNodes(nodeId);\n }, \"paste\")\n }\n >\n <Clipboard className=\"w-4 h-4\" />\n <span>Paste</span>\n </button>\n )}\n\n <div className=\"context-menu-divider\" />\n\n <button\n className=\"context-menu-item\"\n onClick={() =>\n handleAction(async () => {\n await controller.renameNode(nodeId);\n }, \"rename\")\n }\n >\n <Edit2 className=\"w-4 h-4\" />\n <span>Rename</span>\n </button>\n\n <button\n className=\"context-menu-item context-menu-item-danger\"\n onClick={() =>\n handleAction(async () => {\n await controller.deleteNodes([nodeId]);\n }, \"delete\")\n }\n >\n <Trash2 className=\"w-4 h-4\" />\n <span>Delete</span>\n </button>\n </div>\n );\n}\n"],"mappings":"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","names":["useNodeTree","useNodeTreeState","useNodeTreeState","clsx","jsx","useNodeTreeState","node","isExpanded","clsx","useNodeTree","jsx","jsxs","clsx","Fragment","jsx","jsxs","useNodeTree","useNodeTreeState"]}