@brycks/core-front 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/data/List/List.cjs +1 -1
- package/dist/components/data/List/List.cjs.map +1 -1
- package/dist/components/data/List/List.js +68 -148
- package/dist/components/data/List/List.js.map +1 -1
- package/dist/components/data/Table/Table.cjs +1 -1
- package/dist/components/data/Table/Table.cjs.map +1 -1
- package/dist/components/data/Table/Table.js +142 -224
- package/dist/components/data/Table/Table.js.map +1 -1
- package/dist/components/data/TreeView/TreeView.cjs +1 -1
- package/dist/components/data/TreeView/TreeView.cjs.map +1 -1
- package/dist/components/data/TreeView/TreeView.js +141 -182
- package/dist/components/data/TreeView/TreeView.js.map +1 -1
- package/dist/components/feedback/Drawer/Drawer.cjs +1 -22
- package/dist/components/feedback/Drawer/Drawer.cjs.map +1 -1
- package/dist/components/feedback/Drawer/Drawer.js +84 -184
- package/dist/components/feedback/Drawer/Drawer.js.map +1 -1
- package/dist/components/feedback/Modal/Modal.cjs +1 -1
- package/dist/components/feedback/Modal/Modal.cjs.map +1 -1
- package/dist/components/feedback/Modal/Modal.js +65 -150
- package/dist/components/feedback/Modal/Modal.js.map +1 -1
- package/dist/components/feedback/Toast/Toast.cjs +1 -10
- package/dist/components/feedback/Toast/Toast.cjs.map +1 -1
- package/dist/components/feedback/Toast/Toast.js +94 -187
- package/dist/components/feedback/Toast/Toast.js.map +1 -1
- package/dist/components/form/Checkbox/Checkbox.cjs +1 -1
- package/dist/components/form/Checkbox/Checkbox.js +11 -11
- package/dist/components/form/Combobox/Combobox.cjs +1 -6
- package/dist/components/form/Combobox/Combobox.cjs.map +1 -1
- package/dist/components/form/Combobox/Combobox.js +187 -283
- package/dist/components/form/Combobox/Combobox.js.map +1 -1
- package/dist/components/form/Input/Input.cjs +1 -1
- package/dist/components/form/Input/Input.cjs.map +1 -1
- package/dist/components/form/Input/Input.js +38 -133
- package/dist/components/form/Input/Input.js.map +1 -1
- package/dist/components/form/Select/Select.cjs +1 -1
- package/dist/components/form/Select/Select.cjs.map +1 -1
- package/dist/components/form/Select/Select.js +36 -82
- package/dist/components/form/Select/Select.js.map +1 -1
- package/dist/components/form/TagInput/TagInput.cjs +1 -1
- package/dist/components/form/TagInput/TagInput.js +8 -8
- package/dist/components/form/Textarea/Textarea.cjs +1 -1
- package/dist/components/form/Textarea/Textarea.cjs.map +1 -1
- package/dist/components/form/Textarea/Textarea.js +61 -95
- package/dist/components/form/Textarea/Textarea.js.map +1 -1
- package/dist/components/navigation/ContextMenu/ContextMenu.cjs +1 -1
- package/dist/components/navigation/ContextMenu/ContextMenu.js +9 -9
- package/dist/components/navigation/Menu/Menu.cjs +1 -1
- package/dist/components/navigation/Menu/Menu.cjs.map +1 -1
- package/dist/components/navigation/Menu/Menu.js +70 -135
- package/dist/components/navigation/Menu/Menu.js.map +1 -1
- package/dist/components/navigation/Pagination/Pagination.cjs +1 -1
- package/dist/components/navigation/Pagination/Pagination.cjs.map +1 -1
- package/dist/components/navigation/Pagination/Pagination.js +87 -157
- package/dist/components/navigation/Pagination/Pagination.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeView.cjs","sources":["../../../../src/components/data/TreeView/TreeView.tsx"],"sourcesContent":["/**\n * TreeView Component\n *\n * A hierarchical tree structure for displaying nested data.\n * Supports selection, expansion, and keyboard navigation.\n *\n * @module components/data/TreeView\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n useMemo,\n type CSSProperties,\n type ReactNode,\n type KeyboardEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\nimport { spacing, fontSizes, durations, easings } from '../../../design-system'\nimport { componentPaddingY, iconSizes } from '../../../design-system/primitives'\n\nexport interface TreeNode {\n /** Unique identifier */\n id: string\n /** Display label */\n label: string\n /** Optional icon */\n icon?: ReactNode\n /** Child nodes */\n children?: TreeNode[]\n /** Whether the node is disabled */\n disabled?: boolean\n /** Additional data */\n data?: unknown\n}\n\nexport type TreeViewSize = 'sm' | 'md' | 'lg'\n\nexport interface TreeViewProps {\n /** Tree data */\n data: TreeNode[]\n /** Selected node IDs (controlled) */\n selectedIds?: string[]\n /** Default selected node IDs (uncontrolled) */\n defaultSelectedIds?: string[]\n /** Expanded node IDs (controlled) */\n expandedIds?: string[]\n /** Default expanded node IDs (uncontrolled) */\n defaultExpandedIds?: string[]\n /** Callback when selection changes */\n onSelectionChange?: (selectedIds: string[]) => void\n /** Callback when expansion changes */\n onExpansionChange?: (expandedIds: string[]) => void\n /** Callback when a node is clicked */\n onNodeClick?: (node: TreeNode) => void\n /** Whether to allow multi-selection */\n multiSelect?: boolean\n /** Component size */\n size?: TreeViewSize\n /** Whether to show connecting lines */\n showLines?: boolean\n /** Custom node renderer */\n renderNode?: (node: TreeNode, isSelected: boolean, isExpanded: boolean) => ReactNode\n /** Label for accessibility */\n 'aria-label'?: string\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nconst sizeConfig: Record<TreeViewSize, { fontSize: number; iconSize: number; padding: number; indent: number }> = {\n sm: { fontSize: fontSizes.sm, iconSize: iconSizes.xs, padding: componentPaddingY.xs, indent: spacing[4] },\n md: { fontSize: fontSizes.base, iconSize: iconSizes.sm, padding: componentPaddingY.sm, indent: spacing[5] },\n lg: { fontSize: fontSizes.md, iconSize: iconSizes.md, padding: componentPaddingY.md, indent: spacing[6] },\n}\n\nfunction ChevronIcon({ expanded }: { expanded: boolean }) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n style={{\n transform: expanded ? 'rotate(90deg)' : 'rotate(0)',\n transition: `transform ${durations.fast}ms ${easings.easeOut}`,\n }}\n >\n <path d=\"M6 4l4 4-4 4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\ninterface TreeNodeItemProps {\n node: TreeNode\n level: number\n config: typeof sizeConfig.md\n isSelected: boolean\n isExpanded: boolean\n showLines: boolean\n onToggle: (id: string) => void\n onSelect: (id: string, multi: boolean) => void\n renderNode?: TreeViewProps['renderNode']\n selectedIds: string[]\n expandedIds: string[]\n multiSelect: boolean\n}\n\nfunction TreeNodeItem({\n node,\n level,\n config,\n isSelected,\n isExpanded,\n showLines,\n onToggle,\n onSelect,\n renderNode,\n selectedIds,\n expandedIds,\n multiSelect,\n}: TreeNodeItemProps) {\n const hasChildren = node.children && node.children.length > 0\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n if (node.disabled) return\n onSelect(node.id, e.ctrlKey || e.metaKey)\n },\n [node.id, node.disabled, onSelect]\n )\n\n const handleToggle = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n if (hasChildren) {\n onToggle(node.id)\n }\n },\n [node.id, hasChildren, onToggle]\n )\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n if (node.disabled) return\n\n switch (e.key) {\n case 'Enter':\n case ' ':\n e.preventDefault()\n onSelect(node.id, e.ctrlKey || e.metaKey)\n break\n case 'ArrowRight':\n e.preventDefault()\n if (hasChildren && !isExpanded) {\n onToggle(node.id)\n }\n break\n case 'ArrowLeft':\n e.preventDefault()\n if (hasChildren && isExpanded) {\n onToggle(node.id)\n }\n break\n }\n },\n [node.id, node.disabled, hasChildren, isExpanded, onToggle, onSelect]\n )\n\n const itemStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: spacing[1.5],\n padding: `${config.padding}px ${spacing[2]}px`,\n paddingLeft: spacing[2] + level * config.indent,\n fontSize: config.fontSize,\n color: node.disabled ? 'var(--brycks-foreground-disabled)' : 'var(--brycks-foreground-default)',\n backgroundColor: isSelected ? 'var(--brycks-primary-muted)' : 'transparent',\n borderRadius: 'var(--brycks-radius-md)',\n cursor: node.disabled ? 'not-allowed' : 'pointer',\n userSelect: 'none',\n transition: `background-color ${durations.fast}ms ${easings.easeOut}`,\n position: 'relative',\n }\n\n const toggleStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: config.iconSize,\n height: config.iconSize,\n color: 'var(--brycks-foreground-muted)',\n cursor: 'pointer',\n flexShrink: 0,\n }\n\n const iconStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: config.iconSize,\n height: config.iconSize,\n color: isSelected ? 'var(--brycks-primary-default)' : 'var(--brycks-foreground-muted)',\n flexShrink: 0,\n }\n\n const lineStyle: CSSProperties = showLines && level > 0 ? {\n position: 'absolute',\n left: spacing[2] + (level - 1) * config.indent + config.iconSize / 2,\n top: 0,\n bottom: 0,\n width: 1,\n backgroundColor: 'var(--brycks-border-default)',\n } : {}\n\n return (\n <li role=\"treeitem\" aria-selected={isSelected} aria-expanded={hasChildren ? isExpanded : undefined}>\n <div\n tabIndex={node.disabled ? -1 : 0}\n style={itemStyle}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n onMouseEnter={(e) => {\n if (!node.disabled && !isSelected) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n if (!isSelected) {\n e.currentTarget.style.backgroundColor = 'transparent'\n }\n }}\n >\n {showLines && level > 0 && <span style={lineStyle} aria-hidden=\"true\" />}\n <span style={toggleStyle} onClick={handleToggle}>\n {hasChildren && <ChevronIcon expanded={isExpanded} />}\n </span>\n {node.icon && <span style={iconStyle}>{node.icon}</span>}\n {renderNode ? (\n renderNode(node, isSelected, isExpanded)\n ) : (\n <span style={{ flex: 1 }}>{node.label}</span>\n )}\n </div>\n {hasChildren && isExpanded && (\n <ul role=\"group\" style={{ listStyle: 'none', margin: 0, padding: 0 }}>\n {node.children!.map((child) => (\n <TreeNodeItem\n key={child.id}\n node={child}\n level={level + 1}\n config={config}\n isSelected={selectedIds.includes(child.id)}\n isExpanded={expandedIds.includes(child.id)}\n showLines={showLines}\n onToggle={onToggle}\n onSelect={onSelect}\n renderNode={renderNode}\n selectedIds={selectedIds}\n expandedIds={expandedIds}\n multiSelect={multiSelect}\n />\n ))}\n </ul>\n )}\n </li>\n )\n}\n\nexport const TreeView = forwardRef<HTMLUListElement, TreeViewProps>(function TreeView(\n {\n data,\n selectedIds: controlledSelectedIds,\n defaultSelectedIds = [],\n expandedIds: controlledExpandedIds,\n defaultExpandedIds = [],\n onSelectionChange,\n onExpansionChange,\n onNodeClick,\n multiSelect = false,\n size = 'md',\n showLines = false,\n renderNode,\n 'aria-label': ariaLabel = 'Tree',\n className,\n testId,\n },\n ref\n) {\n const [internalSelectedIds, setInternalSelectedIds] = useState<string[]>(defaultSelectedIds)\n const [internalExpandedIds, setInternalExpandedIds] = useState<string[]>(defaultExpandedIds)\n\n const selectedIds = controlledSelectedIds !== undefined ? controlledSelectedIds : internalSelectedIds\n const expandedIds = controlledExpandedIds !== undefined ? controlledExpandedIds : internalExpandedIds\n const config = sizeConfig[size]\n\n // Flatten all nodes for keyboard navigation\n const flatNodes = useMemo(() => {\n const flatten = (nodes: TreeNode[], result: TreeNode[] = []): TreeNode[] => {\n nodes.forEach((node) => {\n result.push(node)\n if (node.children && expandedIds.includes(node.id)) {\n flatten(node.children, result)\n }\n })\n return result\n }\n return flatten(data)\n }, [data, expandedIds])\n\n const handleToggle = useCallback(\n (id: string) => {\n const newExpandedIds = expandedIds.includes(id)\n ? expandedIds.filter((eid) => eid !== id)\n : [...expandedIds, id]\n\n if (controlledExpandedIds === undefined) {\n setInternalExpandedIds(newExpandedIds)\n }\n onExpansionChange?.(newExpandedIds)\n },\n [expandedIds, controlledExpandedIds, onExpansionChange]\n )\n\n const handleSelect = useCallback(\n (id: string, additive: boolean) => {\n const node = flatNodes.find((n) => n.id === id)\n if (node) {\n onNodeClick?.(node)\n }\n\n let newSelectedIds: string[]\n if (multiSelect && additive) {\n newSelectedIds = selectedIds.includes(id)\n ? selectedIds.filter((sid) => sid !== id)\n : [...selectedIds, id]\n } else {\n newSelectedIds = selectedIds.includes(id) && selectedIds.length === 1 ? [] : [id]\n }\n\n if (controlledSelectedIds === undefined) {\n setInternalSelectedIds(newSelectedIds)\n }\n onSelectionChange?.(newSelectedIds)\n },\n [flatNodes, multiSelect, selectedIds, controlledSelectedIds, onSelectionChange, onNodeClick]\n )\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLUListElement>) => {\n const currentIndex = flatNodes.findIndex((n) => selectedIds.includes(n.id))\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const nextIndex = currentIndex < flatNodes.length - 1 ? currentIndex + 1 : 0\n handleSelect(flatNodes[nextIndex].id, false)\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prevIndex = currentIndex > 0 ? currentIndex - 1 : flatNodes.length - 1\n handleSelect(flatNodes[prevIndex].id, false)\n break\n }\n case 'Home':\n e.preventDefault()\n if (flatNodes.length > 0) {\n handleSelect(flatNodes[0].id, false)\n }\n break\n case 'End':\n e.preventDefault()\n if (flatNodes.length > 0) {\n handleSelect(flatNodes[flatNodes.length - 1].id, false)\n }\n break\n }\n },\n [flatNodes, selectedIds, handleSelect]\n )\n\n const containerStyle: CSSProperties = {\n listStyle: 'none',\n margin: 0,\n padding: spacing[1],\n outline: 'none',\n }\n\n return (\n <ul\n ref={ref}\n role=\"tree\"\n aria-label={ariaLabel}\n aria-multiselectable={multiSelect}\n tabIndex={0}\n className={cx('brycks-treeview', `brycks-treeview--${size}`, className)}\n style={containerStyle}\n data-testid={testId}\n onKeyDown={handleKeyDown}\n >\n {data.map((node) => (\n <TreeNodeItem\n key={node.id}\n node={node}\n level={0}\n config={config}\n isSelected={selectedIds.includes(node.id)}\n isExpanded={expandedIds.includes(node.id)}\n showLines={showLines}\n onToggle={handleToggle}\n onSelect={handleSelect}\n renderNode={renderNode}\n selectedIds={selectedIds}\n expandedIds={expandedIds}\n multiSelect={multiSelect}\n />\n ))}\n </ul>\n )\n})\n\nTreeView.displayName = 'TreeView'\n"],"names":["sizeConfig","fontSizes","iconSizes","componentPaddingY","spacing","ChevronIcon","expanded","jsx","durations","easings","TreeNodeItem","node","level","config","isSelected","isExpanded","showLines","onToggle","onSelect","renderNode","selectedIds","expandedIds","multiSelect","hasChildren","handleClick","useCallback","e","handleToggle","handleKeyDown","itemStyle","toggleStyle","iconStyle","lineStyle","jsxs","child","TreeView","forwardRef","data","controlledSelectedIds","defaultSelectedIds","controlledExpandedIds","defaultExpandedIds","onSelectionChange","onExpansionChange","onNodeClick","size","ariaLabel","className","testId","ref","internalSelectedIds","setInternalSelectedIds","useState","internalExpandedIds","setInternalExpandedIds","flatNodes","useMemo","flatten","nodes","result","id","newExpandedIds","eid","handleSelect","additive","n","newSelectedIds","sid","currentIndex","nextIndex","prevIndex","containerStyle","cx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TreeView.cjs","sources":["../../../../src/components/data/TreeView/TreeView.tsx"],"sourcesContent":["/**\n * TreeView Component\n *\n * A hierarchical tree structure for displaying nested data.\n * Supports selection, expansion, and keyboard navigation.\n *\n * @module components/data/TreeView\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n useMemo,\n type CSSProperties,\n type ReactNode,\n type KeyboardEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\nimport { spacing, fontSizes, durations, easings } from '../../../design-system'\nimport { componentPaddingY, iconSizes } from '../../../design-system/primitives'\n\nexport interface TreeNode {\n /** Unique identifier */\n id: string\n /** Display label */\n label: string\n /** Optional icon */\n icon?: ReactNode\n /** Child nodes */\n children?: TreeNode[]\n /** Whether the node is disabled */\n disabled?: boolean\n /** Additional data */\n data?: unknown\n}\n\nexport type TreeViewSize = 'sm' | 'md' | 'lg'\n\nexport interface TreeViewProps {\n /** Tree data */\n data: TreeNode[]\n /** Selected node IDs (controlled) */\n selectedIds?: string[]\n /** Default selected node IDs (uncontrolled) */\n defaultSelectedIds?: string[]\n /** Expanded node IDs (controlled) */\n expandedIds?: string[]\n /** Default expanded node IDs (uncontrolled) */\n defaultExpandedIds?: string[]\n /** Callback when selection changes */\n onSelectionChange?: (selectedIds: string[]) => void\n /** Callback when expansion changes */\n onExpansionChange?: (expandedIds: string[]) => void\n /** Callback when a node is clicked */\n onNodeClick?: (node: TreeNode) => void\n /** Whether to allow multi-selection */\n multiSelect?: boolean\n /** Component size */\n size?: TreeViewSize\n /** Whether to show connecting lines */\n showLines?: boolean\n /** Custom node renderer */\n renderNode?: (node: TreeNode, isSelected: boolean, isExpanded: boolean) => ReactNode\n /** Label for accessibility */\n 'aria-label'?: string\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nconst sizeConfig: Record<TreeViewSize, { fontSize: number; iconSize: number; padding: number; indent: number }> = {\n sm: { fontSize: fontSizes.sm, iconSize: iconSizes.xs, padding: componentPaddingY.xs, indent: spacing[4] },\n md: { fontSize: fontSizes.base, iconSize: iconSizes.sm, padding: componentPaddingY.sm, indent: spacing[5] },\n lg: { fontSize: fontSizes.md, iconSize: iconSizes.md, padding: componentPaddingY.md, indent: spacing[6] },\n}\n\nfunction ChevronIcon({ expanded }: { expanded: boolean }) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n style={{\n transform: expanded ? 'rotate(90deg)' : 'rotate(0)',\n transition: `transform ${durations.fast}ms ${easings.easeOut}`,\n }}\n >\n <path d=\"M6 4l4 4-4 4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\ninterface TreeNodeItemProps {\n node: TreeNode\n level: number\n config: typeof sizeConfig.md\n isSelected: boolean\n isExpanded: boolean\n showLines: boolean\n onToggle: (id: string) => void\n onSelect: (id: string, multi: boolean) => void\n renderNode?: TreeViewProps['renderNode']\n selectedIds: string[]\n expandedIds: string[]\n multiSelect: boolean\n}\n\nfunction TreeNodeItem({\n node,\n level,\n config,\n isSelected,\n isExpanded,\n showLines,\n onToggle,\n onSelect,\n renderNode,\n selectedIds,\n expandedIds,\n multiSelect,\n}: TreeNodeItemProps) {\n const hasChildren = node.children && node.children.length > 0\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n if (node.disabled) return\n onSelect(node.id, e.ctrlKey || e.metaKey)\n },\n [node.id, node.disabled, onSelect]\n )\n\n const handleToggle = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n if (hasChildren) {\n onToggle(node.id)\n }\n },\n [node.id, hasChildren, onToggle]\n )\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n if (node.disabled) return\n\n switch (e.key) {\n case 'Enter':\n case ' ':\n e.preventDefault()\n onSelect(node.id, e.ctrlKey || e.metaKey)\n break\n case 'ArrowRight':\n e.preventDefault()\n if (hasChildren && !isExpanded) {\n onToggle(node.id)\n }\n break\n case 'ArrowLeft':\n e.preventDefault()\n if (hasChildren && isExpanded) {\n onToggle(node.id)\n }\n break\n }\n },\n [node.id, node.disabled, hasChildren, isExpanded, onToggle, onSelect]\n )\n\n // Only the depth-based horizontal offset is dynamic (computed from `level`\n // and the per-size indent); everything else is class-driven.\n const itemStyle: CSSProperties = {\n paddingLeft: spacing[2] + level * config.indent,\n }\n\n // Connecting line offset is also depth-based.\n const lineStyle: CSSProperties = {\n left: spacing[2] + (level - 1) * config.indent + config.iconSize / 2,\n }\n\n return (\n <li role=\"treeitem\" aria-selected={isSelected} aria-expanded={hasChildren ? isExpanded : undefined}>\n <div\n tabIndex={node.disabled ? -1 : 0}\n className={cx(\n 'brycks-treeview__item',\n isSelected && 'brycks-treeview__item--selected',\n node.disabled && 'brycks-treeview__item--disabled'\n )}\n style={itemStyle}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n >\n {showLines && level > 0 && (\n <span className=\"brycks-treeview__line\" style={lineStyle} aria-hidden=\"true\" />\n )}\n <span className=\"brycks-treeview__toggle\" onClick={handleToggle}>\n {hasChildren && <ChevronIcon expanded={isExpanded} />}\n </span>\n {node.icon && <span className=\"brycks-treeview__icon\">{node.icon}</span>}\n {renderNode ? (\n renderNode(node, isSelected, isExpanded)\n ) : (\n <span className=\"brycks-treeview__label\">{node.label}</span>\n )}\n </div>\n {hasChildren && isExpanded && (\n <ul role=\"group\" className=\"brycks-treeview__group\">\n {node.children!.map((child) => (\n <TreeNodeItem\n key={child.id}\n node={child}\n level={level + 1}\n config={config}\n isSelected={selectedIds.includes(child.id)}\n isExpanded={expandedIds.includes(child.id)}\n showLines={showLines}\n onToggle={onToggle}\n onSelect={onSelect}\n renderNode={renderNode}\n selectedIds={selectedIds}\n expandedIds={expandedIds}\n multiSelect={multiSelect}\n />\n ))}\n </ul>\n )}\n </li>\n )\n}\n\nexport const TreeView = forwardRef<HTMLUListElement, TreeViewProps>(function TreeView(\n {\n data,\n selectedIds: controlledSelectedIds,\n defaultSelectedIds = [],\n expandedIds: controlledExpandedIds,\n defaultExpandedIds = [],\n onSelectionChange,\n onExpansionChange,\n onNodeClick,\n multiSelect = false,\n size = 'md',\n showLines = false,\n renderNode,\n 'aria-label': ariaLabel = 'Tree',\n className,\n testId,\n },\n ref\n) {\n const [internalSelectedIds, setInternalSelectedIds] = useState<string[]>(defaultSelectedIds)\n const [internalExpandedIds, setInternalExpandedIds] = useState<string[]>(defaultExpandedIds)\n\n const selectedIds = controlledSelectedIds !== undefined ? controlledSelectedIds : internalSelectedIds\n const expandedIds = controlledExpandedIds !== undefined ? controlledExpandedIds : internalExpandedIds\n const config = sizeConfig[size]\n\n // Flatten all nodes for keyboard navigation\n const flatNodes = useMemo(() => {\n const flatten = (nodes: TreeNode[], result: TreeNode[] = []): TreeNode[] => {\n nodes.forEach((node) => {\n result.push(node)\n if (node.children && expandedIds.includes(node.id)) {\n flatten(node.children, result)\n }\n })\n return result\n }\n return flatten(data)\n }, [data, expandedIds])\n\n const handleToggle = useCallback(\n (id: string) => {\n const newExpandedIds = expandedIds.includes(id)\n ? expandedIds.filter((eid) => eid !== id)\n : [...expandedIds, id]\n\n if (controlledExpandedIds === undefined) {\n setInternalExpandedIds(newExpandedIds)\n }\n onExpansionChange?.(newExpandedIds)\n },\n [expandedIds, controlledExpandedIds, onExpansionChange]\n )\n\n const handleSelect = useCallback(\n (id: string, additive: boolean) => {\n const node = flatNodes.find((n) => n.id === id)\n if (node) {\n onNodeClick?.(node)\n }\n\n let newSelectedIds: string[]\n if (multiSelect && additive) {\n newSelectedIds = selectedIds.includes(id)\n ? selectedIds.filter((sid) => sid !== id)\n : [...selectedIds, id]\n } else {\n newSelectedIds = selectedIds.includes(id) && selectedIds.length === 1 ? [] : [id]\n }\n\n if (controlledSelectedIds === undefined) {\n setInternalSelectedIds(newSelectedIds)\n }\n onSelectionChange?.(newSelectedIds)\n },\n [flatNodes, multiSelect, selectedIds, controlledSelectedIds, onSelectionChange, onNodeClick]\n )\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLUListElement>) => {\n const currentIndex = flatNodes.findIndex((n) => selectedIds.includes(n.id))\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const nextIndex = currentIndex < flatNodes.length - 1 ? currentIndex + 1 : 0\n handleSelect(flatNodes[nextIndex].id, false)\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prevIndex = currentIndex > 0 ? currentIndex - 1 : flatNodes.length - 1\n handleSelect(flatNodes[prevIndex].id, false)\n break\n }\n case 'Home':\n e.preventDefault()\n if (flatNodes.length > 0) {\n handleSelect(flatNodes[0].id, false)\n }\n break\n case 'End':\n e.preventDefault()\n if (flatNodes.length > 0) {\n handleSelect(flatNodes[flatNodes.length - 1].id, false)\n }\n break\n }\n },\n [flatNodes, selectedIds, handleSelect]\n )\n\n return (\n <ul\n ref={ref}\n role=\"tree\"\n aria-label={ariaLabel}\n aria-multiselectable={multiSelect}\n tabIndex={0}\n className={cx('brycks-treeview', `brycks-treeview--${size}`, className)}\n data-testid={testId}\n onKeyDown={handleKeyDown}\n >\n {data.map((node) => (\n <TreeNodeItem\n key={node.id}\n node={node}\n level={0}\n config={config}\n isSelected={selectedIds.includes(node.id)}\n isExpanded={expandedIds.includes(node.id)}\n showLines={showLines}\n onToggle={handleToggle}\n onSelect={handleSelect}\n renderNode={renderNode}\n selectedIds={selectedIds}\n expandedIds={expandedIds}\n multiSelect={multiSelect}\n />\n ))}\n </ul>\n )\n})\n\nTreeView.displayName = 'TreeView'\n"],"names":["sizeConfig","fontSizes","iconSizes","componentPaddingY","spacing","ChevronIcon","expanded","jsx","durations","easings","TreeNodeItem","node","level","config","isSelected","isExpanded","showLines","onToggle","onSelect","renderNode","selectedIds","expandedIds","multiSelect","hasChildren","handleClick","useCallback","e","handleToggle","handleKeyDown","itemStyle","lineStyle","jsxs","cx","child","TreeView","forwardRef","data","controlledSelectedIds","defaultSelectedIds","controlledExpandedIds","defaultExpandedIds","onSelectionChange","onExpansionChange","onNodeClick","size","ariaLabel","className","testId","ref","internalSelectedIds","setInternalSelectedIds","useState","internalExpandedIds","setInternalExpandedIds","flatNodes","useMemo","flatten","nodes","result","id","newExpandedIds","eid","handleSelect","additive","n","newSelectedIds","sid","currentIndex","nextIndex","prevIndex"],"mappings":"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"}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { forwardRef as
|
|
3
|
-
import { cx as
|
|
4
|
-
import { spacing as
|
|
5
|
-
import { componentPaddingY as
|
|
6
|
-
import { fontSizes as
|
|
7
|
-
import { durations as
|
|
8
|
-
const
|
|
9
|
-
sm: { fontSize:
|
|
10
|
-
md: { fontSize:
|
|
11
|
-
lg: { fontSize:
|
|
1
|
+
import { jsx as l, jsxs as T } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as U, useState as V, useMemo as W, useCallback as v } from "react";
|
|
3
|
+
import { cx as $ } from "../../../utils/styles.js";
|
|
4
|
+
import { spacing as _ } from "../../../design-system/tokens/spacing.js";
|
|
5
|
+
import { componentPaddingY as A, iconSizes as j } from "../../../design-system/primitives/sizing.js";
|
|
6
|
+
import { fontSizes as L } from "../../../design-system/tokens/typography.js";
|
|
7
|
+
import { durations as Y, easings as q } from "../../../design-system/tokens/motion.js";
|
|
8
|
+
const F = {
|
|
9
|
+
sm: { fontSize: L.sm, iconSize: j.xs, padding: A.xs, indent: _[4] },
|
|
10
|
+
md: { fontSize: L.base, iconSize: j.sm, padding: A.sm, indent: _[5] },
|
|
11
|
+
lg: { fontSize: L.md, iconSize: j.md, padding: A.md, indent: _[6] }
|
|
12
12
|
};
|
|
13
|
-
function
|
|
14
|
-
return /* @__PURE__ */
|
|
13
|
+
function G({ expanded: e }) {
|
|
14
|
+
return /* @__PURE__ */ l(
|
|
15
15
|
"svg",
|
|
16
16
|
{
|
|
17
17
|
width: "16",
|
|
@@ -21,236 +21,195 @@ function Q({ expanded: e }) {
|
|
|
21
21
|
"aria-hidden": "true",
|
|
22
22
|
style: {
|
|
23
23
|
transform: e ? "rotate(90deg)" : "rotate(0)",
|
|
24
|
-
transition: `transform ${
|
|
24
|
+
transition: `transform ${Y.fast}ms ${q.easeOut}`
|
|
25
25
|
},
|
|
26
|
-
children: /* @__PURE__ */
|
|
26
|
+
children: /* @__PURE__ */ l("path", { d: "M6 4l4 4-4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
27
27
|
}
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
|
-
function
|
|
30
|
+
function M({
|
|
31
31
|
node: e,
|
|
32
|
-
level:
|
|
33
|
-
config:
|
|
34
|
-
isSelected:
|
|
35
|
-
isExpanded:
|
|
32
|
+
level: u,
|
|
33
|
+
config: f,
|
|
34
|
+
isSelected: y,
|
|
35
|
+
isExpanded: n,
|
|
36
36
|
showLines: x,
|
|
37
|
-
onToggle:
|
|
38
|
-
onSelect:
|
|
39
|
-
renderNode:
|
|
40
|
-
selectedIds:
|
|
41
|
-
expandedIds:
|
|
42
|
-
multiSelect:
|
|
37
|
+
onToggle: o,
|
|
38
|
+
onSelect: h,
|
|
39
|
+
renderNode: w,
|
|
40
|
+
selectedIds: b,
|
|
41
|
+
expandedIds: g,
|
|
42
|
+
multiSelect: D
|
|
43
43
|
}) {
|
|
44
|
-
const
|
|
45
|
-
(
|
|
46
|
-
e.disabled ||
|
|
44
|
+
const c = e.children && e.children.length > 0, I = v(
|
|
45
|
+
(t) => {
|
|
46
|
+
e.disabled || h(e.id, t.ctrlKey || t.metaKey);
|
|
47
47
|
},
|
|
48
|
-
[e.id, e.disabled,
|
|
49
|
-
),
|
|
50
|
-
(
|
|
51
|
-
|
|
48
|
+
[e.id, e.disabled, h]
|
|
49
|
+
), z = v(
|
|
50
|
+
(t) => {
|
|
51
|
+
t.stopPropagation(), c && o(e.id);
|
|
52
52
|
},
|
|
53
|
-
[e.id,
|
|
54
|
-
),
|
|
55
|
-
(
|
|
53
|
+
[e.id, c, o]
|
|
54
|
+
), K = v(
|
|
55
|
+
(t) => {
|
|
56
56
|
if (!e.disabled)
|
|
57
|
-
switch (
|
|
57
|
+
switch (t.key) {
|
|
58
58
|
case "Enter":
|
|
59
59
|
case " ":
|
|
60
|
-
|
|
60
|
+
t.preventDefault(), h(e.id, t.ctrlKey || t.metaKey);
|
|
61
61
|
break;
|
|
62
62
|
case "ArrowRight":
|
|
63
|
-
|
|
63
|
+
t.preventDefault(), c && !n && o(e.id);
|
|
64
64
|
break;
|
|
65
65
|
case "ArrowLeft":
|
|
66
|
-
|
|
66
|
+
t.preventDefault(), c && n && o(e.id);
|
|
67
67
|
break;
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
|
-
[e.id, e.disabled,
|
|
71
|
-
),
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
color: e.disabled ? "var(--brycks-foreground-disabled)" : "var(--brycks-foreground-default)",
|
|
79
|
-
backgroundColor: m ? "var(--brycks-primary-muted)" : "transparent",
|
|
80
|
-
borderRadius: "var(--brycks-radius-md)",
|
|
81
|
-
cursor: e.disabled ? "not-allowed" : "pointer",
|
|
82
|
-
userSelect: "none",
|
|
83
|
-
transition: `background-color ${P.fast}ms ${B.easeOut}`,
|
|
84
|
-
position: "relative"
|
|
85
|
-
}, $ = {
|
|
86
|
-
display: "flex",
|
|
87
|
-
alignItems: "center",
|
|
88
|
-
justifyContent: "center",
|
|
89
|
-
width: i.iconSize,
|
|
90
|
-
height: i.iconSize,
|
|
91
|
-
color: "var(--brycks-foreground-muted)",
|
|
92
|
-
cursor: "pointer",
|
|
93
|
-
flexShrink: 0
|
|
94
|
-
}, j = {
|
|
95
|
-
display: "flex",
|
|
96
|
-
alignItems: "center",
|
|
97
|
-
justifyContent: "center",
|
|
98
|
-
width: i.iconSize,
|
|
99
|
-
height: i.iconSize,
|
|
100
|
-
color: m ? "var(--brycks-primary-default)" : "var(--brycks-foreground-muted)",
|
|
101
|
-
flexShrink: 0
|
|
102
|
-
}, T = x && f > 0 ? {
|
|
103
|
-
position: "absolute",
|
|
104
|
-
left: h[2] + (f - 1) * i.indent + i.iconSize / 2,
|
|
105
|
-
top: 0,
|
|
106
|
-
bottom: 0,
|
|
107
|
-
width: 1,
|
|
108
|
-
backgroundColor: "var(--brycks-border-default)"
|
|
109
|
-
} : {};
|
|
110
|
-
return /* @__PURE__ */ V("li", { role: "treeitem", "aria-selected": m, "aria-expanded": d ? s : void 0, children: [
|
|
111
|
-
/* @__PURE__ */ V(
|
|
70
|
+
[e.id, e.disabled, c, n, o, h]
|
|
71
|
+
), N = {
|
|
72
|
+
paddingLeft: _[2] + u * f.indent
|
|
73
|
+
}, S = {
|
|
74
|
+
left: _[2] + (u - 1) * f.indent + f.iconSize / 2
|
|
75
|
+
};
|
|
76
|
+
return /* @__PURE__ */ T("li", { role: "treeitem", "aria-selected": y, "aria-expanded": c ? n : void 0, children: [
|
|
77
|
+
/* @__PURE__ */ T(
|
|
112
78
|
"div",
|
|
113
79
|
{
|
|
114
80
|
tabIndex: e.disabled ? -1 : 0,
|
|
115
|
-
|
|
81
|
+
className: $(
|
|
82
|
+
"brycks-treeview__item",
|
|
83
|
+
y && "brycks-treeview__item--selected",
|
|
84
|
+
e.disabled && "brycks-treeview__item--disabled"
|
|
85
|
+
),
|
|
86
|
+
style: N,
|
|
116
87
|
onClick: I,
|
|
117
|
-
onKeyDown:
|
|
118
|
-
onMouseEnter: (r) => {
|
|
119
|
-
!e.disabled && !m && (r.currentTarget.style.backgroundColor = "var(--brycks-background-muted)");
|
|
120
|
-
},
|
|
121
|
-
onMouseLeave: (r) => {
|
|
122
|
-
m || (r.currentTarget.style.backgroundColor = "transparent");
|
|
123
|
-
},
|
|
88
|
+
onKeyDown: K,
|
|
124
89
|
children: [
|
|
125
|
-
x &&
|
|
126
|
-
/* @__PURE__ */
|
|
127
|
-
e.icon && /* @__PURE__ */
|
|
128
|
-
|
|
90
|
+
x && u > 0 && /* @__PURE__ */ l("span", { className: "brycks-treeview__line", style: S, "aria-hidden": "true" }),
|
|
91
|
+
/* @__PURE__ */ l("span", { className: "brycks-treeview__toggle", onClick: z, children: c && /* @__PURE__ */ l(G, { expanded: n }) }),
|
|
92
|
+
e.icon && /* @__PURE__ */ l("span", { className: "brycks-treeview__icon", children: e.icon }),
|
|
93
|
+
w ? w(e, y, n) : /* @__PURE__ */ l("span", { className: "brycks-treeview__label", children: e.label })
|
|
129
94
|
]
|
|
130
95
|
}
|
|
131
96
|
),
|
|
132
|
-
|
|
133
|
-
|
|
97
|
+
c && n && /* @__PURE__ */ l("ul", { role: "group", className: "brycks-treeview__group", children: e.children.map((t) => /* @__PURE__ */ l(
|
|
98
|
+
M,
|
|
134
99
|
{
|
|
135
|
-
node:
|
|
136
|
-
level:
|
|
137
|
-
config:
|
|
138
|
-
isSelected:
|
|
139
|
-
isExpanded:
|
|
100
|
+
node: t,
|
|
101
|
+
level: u + 1,
|
|
102
|
+
config: f,
|
|
103
|
+
isSelected: b.includes(t.id),
|
|
104
|
+
isExpanded: g.includes(t.id),
|
|
140
105
|
showLines: x,
|
|
141
|
-
onToggle:
|
|
142
|
-
onSelect:
|
|
143
|
-
renderNode:
|
|
144
|
-
selectedIds:
|
|
145
|
-
expandedIds:
|
|
146
|
-
multiSelect:
|
|
106
|
+
onToggle: o,
|
|
107
|
+
onSelect: h,
|
|
108
|
+
renderNode: w,
|
|
109
|
+
selectedIds: b,
|
|
110
|
+
expandedIds: g,
|
|
111
|
+
multiSelect: D
|
|
147
112
|
},
|
|
148
|
-
|
|
113
|
+
t.id
|
|
149
114
|
)) })
|
|
150
115
|
] });
|
|
151
116
|
}
|
|
152
|
-
const
|
|
153
|
-
data:
|
|
154
|
-
selectedIds:
|
|
155
|
-
defaultSelectedIds:
|
|
156
|
-
expandedIds:
|
|
117
|
+
const J = U(function({
|
|
118
|
+
data: u,
|
|
119
|
+
selectedIds: f,
|
|
120
|
+
defaultSelectedIds: y = [],
|
|
121
|
+
expandedIds: n,
|
|
157
122
|
defaultExpandedIds: x = [],
|
|
158
|
-
onSelectionChange:
|
|
159
|
-
onExpansionChange:
|
|
160
|
-
onNodeClick:
|
|
161
|
-
multiSelect:
|
|
162
|
-
size:
|
|
163
|
-
showLines:
|
|
164
|
-
renderNode:
|
|
123
|
+
onSelectionChange: o,
|
|
124
|
+
onExpansionChange: h,
|
|
125
|
+
onNodeClick: w,
|
|
126
|
+
multiSelect: b = !1,
|
|
127
|
+
size: g = "md",
|
|
128
|
+
showLines: D = !1,
|
|
129
|
+
renderNode: c,
|
|
165
130
|
"aria-label": I = "Tree",
|
|
166
|
-
className:
|
|
167
|
-
testId:
|
|
168
|
-
},
|
|
169
|
-
const [
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
}),
|
|
173
|
-
return
|
|
174
|
-
}, [
|
|
175
|
-
(
|
|
176
|
-
const
|
|
177
|
-
|
|
131
|
+
className: z,
|
|
132
|
+
testId: K
|
|
133
|
+
}, N) {
|
|
134
|
+
const [S, t] = V(y), [P, R] = V(x), d = f !== void 0 ? f : S, p = n !== void 0 ? n : P, B = F[g], s = W(() => {
|
|
135
|
+
const i = (a, r = []) => (a.forEach((m) => {
|
|
136
|
+
r.push(m), m.children && p.includes(m.id) && i(m.children, r);
|
|
137
|
+
}), r);
|
|
138
|
+
return i(u);
|
|
139
|
+
}, [u, p]), H = v(
|
|
140
|
+
(i) => {
|
|
141
|
+
const a = p.includes(i) ? p.filter((r) => r !== i) : [...p, i];
|
|
142
|
+
n === void 0 && R(a), h?.(a);
|
|
178
143
|
},
|
|
179
|
-
[
|
|
180
|
-
),
|
|
181
|
-
(
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
let
|
|
185
|
-
|
|
144
|
+
[p, n, h]
|
|
145
|
+
), k = v(
|
|
146
|
+
(i, a) => {
|
|
147
|
+
const r = s.find((C) => C.id === i);
|
|
148
|
+
r && w?.(r);
|
|
149
|
+
let m;
|
|
150
|
+
b && a ? m = d.includes(i) ? d.filter((C) => C !== i) : [...d, i] : m = d.includes(i) && d.length === 1 ? [] : [i], f === void 0 && t(m), o?.(m);
|
|
186
151
|
},
|
|
187
|
-
[
|
|
188
|
-
),
|
|
189
|
-
(
|
|
190
|
-
const
|
|
191
|
-
switch (
|
|
152
|
+
[s, b, d, f, o, w]
|
|
153
|
+
), O = v(
|
|
154
|
+
(i) => {
|
|
155
|
+
const a = s.findIndex((r) => d.includes(r.id));
|
|
156
|
+
switch (i.key) {
|
|
192
157
|
case "ArrowDown": {
|
|
193
|
-
|
|
194
|
-
const
|
|
195
|
-
|
|
158
|
+
i.preventDefault();
|
|
159
|
+
const r = a < s.length - 1 ? a + 1 : 0;
|
|
160
|
+
k(s[r].id, !1);
|
|
196
161
|
break;
|
|
197
162
|
}
|
|
198
163
|
case "ArrowUp": {
|
|
199
|
-
|
|
200
|
-
const
|
|
201
|
-
|
|
164
|
+
i.preventDefault();
|
|
165
|
+
const r = a > 0 ? a - 1 : s.length - 1;
|
|
166
|
+
k(s[r].id, !1);
|
|
202
167
|
break;
|
|
203
168
|
}
|
|
204
169
|
case "Home":
|
|
205
|
-
|
|
170
|
+
i.preventDefault(), s.length > 0 && k(s[0].id, !1);
|
|
206
171
|
break;
|
|
207
172
|
case "End":
|
|
208
|
-
|
|
173
|
+
i.preventDefault(), s.length > 0 && k(s[s.length - 1].id, !1);
|
|
209
174
|
break;
|
|
210
175
|
}
|
|
211
176
|
},
|
|
212
|
-
[
|
|
213
|
-
)
|
|
214
|
-
|
|
215
|
-
margin: 0,
|
|
216
|
-
padding: h[1],
|
|
217
|
-
outline: "none"
|
|
218
|
-
};
|
|
219
|
-
return /* @__PURE__ */ o(
|
|
177
|
+
[s, d, k]
|
|
178
|
+
);
|
|
179
|
+
return /* @__PURE__ */ l(
|
|
220
180
|
"ul",
|
|
221
181
|
{
|
|
222
|
-
ref:
|
|
182
|
+
ref: N,
|
|
223
183
|
role: "tree",
|
|
224
184
|
"aria-label": I,
|
|
225
|
-
"aria-multiselectable":
|
|
185
|
+
"aria-multiselectable": b,
|
|
226
186
|
tabIndex: 0,
|
|
227
|
-
className:
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
H,
|
|
187
|
+
className: $("brycks-treeview", `brycks-treeview--${g}`, z),
|
|
188
|
+
"data-testid": K,
|
|
189
|
+
onKeyDown: O,
|
|
190
|
+
children: u.map((i) => /* @__PURE__ */ l(
|
|
191
|
+
M,
|
|
233
192
|
{
|
|
234
|
-
node:
|
|
193
|
+
node: i,
|
|
235
194
|
level: 0,
|
|
236
|
-
config:
|
|
237
|
-
isSelected:
|
|
238
|
-
isExpanded:
|
|
239
|
-
showLines:
|
|
240
|
-
onToggle:
|
|
241
|
-
onSelect:
|
|
242
|
-
renderNode:
|
|
243
|
-
selectedIds:
|
|
244
|
-
expandedIds:
|
|
245
|
-
multiSelect:
|
|
195
|
+
config: B,
|
|
196
|
+
isSelected: d.includes(i.id),
|
|
197
|
+
isExpanded: p.includes(i.id),
|
|
198
|
+
showLines: D,
|
|
199
|
+
onToggle: H,
|
|
200
|
+
onSelect: k,
|
|
201
|
+
renderNode: c,
|
|
202
|
+
selectedIds: d,
|
|
203
|
+
expandedIds: p,
|
|
204
|
+
multiSelect: b
|
|
246
205
|
},
|
|
247
|
-
|
|
206
|
+
i.id
|
|
248
207
|
))
|
|
249
208
|
}
|
|
250
209
|
);
|
|
251
210
|
});
|
|
252
|
-
|
|
211
|
+
J.displayName = "TreeView";
|
|
253
212
|
export {
|
|
254
|
-
|
|
213
|
+
J as TreeView
|
|
255
214
|
};
|
|
256
215
|
//# sourceMappingURL=TreeView.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeView.js","sources":["../../../../src/components/data/TreeView/TreeView.tsx"],"sourcesContent":["/**\n * TreeView Component\n *\n * A hierarchical tree structure for displaying nested data.\n * Supports selection, expansion, and keyboard navigation.\n *\n * @module components/data/TreeView\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n useMemo,\n type CSSProperties,\n type ReactNode,\n type KeyboardEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\nimport { spacing, fontSizes, durations, easings } from '../../../design-system'\nimport { componentPaddingY, iconSizes } from '../../../design-system/primitives'\n\nexport interface TreeNode {\n /** Unique identifier */\n id: string\n /** Display label */\n label: string\n /** Optional icon */\n icon?: ReactNode\n /** Child nodes */\n children?: TreeNode[]\n /** Whether the node is disabled */\n disabled?: boolean\n /** Additional data */\n data?: unknown\n}\n\nexport type TreeViewSize = 'sm' | 'md' | 'lg'\n\nexport interface TreeViewProps {\n /** Tree data */\n data: TreeNode[]\n /** Selected node IDs (controlled) */\n selectedIds?: string[]\n /** Default selected node IDs (uncontrolled) */\n defaultSelectedIds?: string[]\n /** Expanded node IDs (controlled) */\n expandedIds?: string[]\n /** Default expanded node IDs (uncontrolled) */\n defaultExpandedIds?: string[]\n /** Callback when selection changes */\n onSelectionChange?: (selectedIds: string[]) => void\n /** Callback when expansion changes */\n onExpansionChange?: (expandedIds: string[]) => void\n /** Callback when a node is clicked */\n onNodeClick?: (node: TreeNode) => void\n /** Whether to allow multi-selection */\n multiSelect?: boolean\n /** Component size */\n size?: TreeViewSize\n /** Whether to show connecting lines */\n showLines?: boolean\n /** Custom node renderer */\n renderNode?: (node: TreeNode, isSelected: boolean, isExpanded: boolean) => ReactNode\n /** Label for accessibility */\n 'aria-label'?: string\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nconst sizeConfig: Record<TreeViewSize, { fontSize: number; iconSize: number; padding: number; indent: number }> = {\n sm: { fontSize: fontSizes.sm, iconSize: iconSizes.xs, padding: componentPaddingY.xs, indent: spacing[4] },\n md: { fontSize: fontSizes.base, iconSize: iconSizes.sm, padding: componentPaddingY.sm, indent: spacing[5] },\n lg: { fontSize: fontSizes.md, iconSize: iconSizes.md, padding: componentPaddingY.md, indent: spacing[6] },\n}\n\nfunction ChevronIcon({ expanded }: { expanded: boolean }) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n style={{\n transform: expanded ? 'rotate(90deg)' : 'rotate(0)',\n transition: `transform ${durations.fast}ms ${easings.easeOut}`,\n }}\n >\n <path d=\"M6 4l4 4-4 4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\ninterface TreeNodeItemProps {\n node: TreeNode\n level: number\n config: typeof sizeConfig.md\n isSelected: boolean\n isExpanded: boolean\n showLines: boolean\n onToggle: (id: string) => void\n onSelect: (id: string, multi: boolean) => void\n renderNode?: TreeViewProps['renderNode']\n selectedIds: string[]\n expandedIds: string[]\n multiSelect: boolean\n}\n\nfunction TreeNodeItem({\n node,\n level,\n config,\n isSelected,\n isExpanded,\n showLines,\n onToggle,\n onSelect,\n renderNode,\n selectedIds,\n expandedIds,\n multiSelect,\n}: TreeNodeItemProps) {\n const hasChildren = node.children && node.children.length > 0\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n if (node.disabled) return\n onSelect(node.id, e.ctrlKey || e.metaKey)\n },\n [node.id, node.disabled, onSelect]\n )\n\n const handleToggle = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n if (hasChildren) {\n onToggle(node.id)\n }\n },\n [node.id, hasChildren, onToggle]\n )\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n if (node.disabled) return\n\n switch (e.key) {\n case 'Enter':\n case ' ':\n e.preventDefault()\n onSelect(node.id, e.ctrlKey || e.metaKey)\n break\n case 'ArrowRight':\n e.preventDefault()\n if (hasChildren && !isExpanded) {\n onToggle(node.id)\n }\n break\n case 'ArrowLeft':\n e.preventDefault()\n if (hasChildren && isExpanded) {\n onToggle(node.id)\n }\n break\n }\n },\n [node.id, node.disabled, hasChildren, isExpanded, onToggle, onSelect]\n )\n\n const itemStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: spacing[1.5],\n padding: `${config.padding}px ${spacing[2]}px`,\n paddingLeft: spacing[2] + level * config.indent,\n fontSize: config.fontSize,\n color: node.disabled ? 'var(--brycks-foreground-disabled)' : 'var(--brycks-foreground-default)',\n backgroundColor: isSelected ? 'var(--brycks-primary-muted)' : 'transparent',\n borderRadius: 'var(--brycks-radius-md)',\n cursor: node.disabled ? 'not-allowed' : 'pointer',\n userSelect: 'none',\n transition: `background-color ${durations.fast}ms ${easings.easeOut}`,\n position: 'relative',\n }\n\n const toggleStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: config.iconSize,\n height: config.iconSize,\n color: 'var(--brycks-foreground-muted)',\n cursor: 'pointer',\n flexShrink: 0,\n }\n\n const iconStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: config.iconSize,\n height: config.iconSize,\n color: isSelected ? 'var(--brycks-primary-default)' : 'var(--brycks-foreground-muted)',\n flexShrink: 0,\n }\n\n const lineStyle: CSSProperties = showLines && level > 0 ? {\n position: 'absolute',\n left: spacing[2] + (level - 1) * config.indent + config.iconSize / 2,\n top: 0,\n bottom: 0,\n width: 1,\n backgroundColor: 'var(--brycks-border-default)',\n } : {}\n\n return (\n <li role=\"treeitem\" aria-selected={isSelected} aria-expanded={hasChildren ? isExpanded : undefined}>\n <div\n tabIndex={node.disabled ? -1 : 0}\n style={itemStyle}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n onMouseEnter={(e) => {\n if (!node.disabled && !isSelected) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n if (!isSelected) {\n e.currentTarget.style.backgroundColor = 'transparent'\n }\n }}\n >\n {showLines && level > 0 && <span style={lineStyle} aria-hidden=\"true\" />}\n <span style={toggleStyle} onClick={handleToggle}>\n {hasChildren && <ChevronIcon expanded={isExpanded} />}\n </span>\n {node.icon && <span style={iconStyle}>{node.icon}</span>}\n {renderNode ? (\n renderNode(node, isSelected, isExpanded)\n ) : (\n <span style={{ flex: 1 }}>{node.label}</span>\n )}\n </div>\n {hasChildren && isExpanded && (\n <ul role=\"group\" style={{ listStyle: 'none', margin: 0, padding: 0 }}>\n {node.children!.map((child) => (\n <TreeNodeItem\n key={child.id}\n node={child}\n level={level + 1}\n config={config}\n isSelected={selectedIds.includes(child.id)}\n isExpanded={expandedIds.includes(child.id)}\n showLines={showLines}\n onToggle={onToggle}\n onSelect={onSelect}\n renderNode={renderNode}\n selectedIds={selectedIds}\n expandedIds={expandedIds}\n multiSelect={multiSelect}\n />\n ))}\n </ul>\n )}\n </li>\n )\n}\n\nexport const TreeView = forwardRef<HTMLUListElement, TreeViewProps>(function TreeView(\n {\n data,\n selectedIds: controlledSelectedIds,\n defaultSelectedIds = [],\n expandedIds: controlledExpandedIds,\n defaultExpandedIds = [],\n onSelectionChange,\n onExpansionChange,\n onNodeClick,\n multiSelect = false,\n size = 'md',\n showLines = false,\n renderNode,\n 'aria-label': ariaLabel = 'Tree',\n className,\n testId,\n },\n ref\n) {\n const [internalSelectedIds, setInternalSelectedIds] = useState<string[]>(defaultSelectedIds)\n const [internalExpandedIds, setInternalExpandedIds] = useState<string[]>(defaultExpandedIds)\n\n const selectedIds = controlledSelectedIds !== undefined ? controlledSelectedIds : internalSelectedIds\n const expandedIds = controlledExpandedIds !== undefined ? controlledExpandedIds : internalExpandedIds\n const config = sizeConfig[size]\n\n // Flatten all nodes for keyboard navigation\n const flatNodes = useMemo(() => {\n const flatten = (nodes: TreeNode[], result: TreeNode[] = []): TreeNode[] => {\n nodes.forEach((node) => {\n result.push(node)\n if (node.children && expandedIds.includes(node.id)) {\n flatten(node.children, result)\n }\n })\n return result\n }\n return flatten(data)\n }, [data, expandedIds])\n\n const handleToggle = useCallback(\n (id: string) => {\n const newExpandedIds = expandedIds.includes(id)\n ? expandedIds.filter((eid) => eid !== id)\n : [...expandedIds, id]\n\n if (controlledExpandedIds === undefined) {\n setInternalExpandedIds(newExpandedIds)\n }\n onExpansionChange?.(newExpandedIds)\n },\n [expandedIds, controlledExpandedIds, onExpansionChange]\n )\n\n const handleSelect = useCallback(\n (id: string, additive: boolean) => {\n const node = flatNodes.find((n) => n.id === id)\n if (node) {\n onNodeClick?.(node)\n }\n\n let newSelectedIds: string[]\n if (multiSelect && additive) {\n newSelectedIds = selectedIds.includes(id)\n ? selectedIds.filter((sid) => sid !== id)\n : [...selectedIds, id]\n } else {\n newSelectedIds = selectedIds.includes(id) && selectedIds.length === 1 ? [] : [id]\n }\n\n if (controlledSelectedIds === undefined) {\n setInternalSelectedIds(newSelectedIds)\n }\n onSelectionChange?.(newSelectedIds)\n },\n [flatNodes, multiSelect, selectedIds, controlledSelectedIds, onSelectionChange, onNodeClick]\n )\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLUListElement>) => {\n const currentIndex = flatNodes.findIndex((n) => selectedIds.includes(n.id))\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const nextIndex = currentIndex < flatNodes.length - 1 ? currentIndex + 1 : 0\n handleSelect(flatNodes[nextIndex].id, false)\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prevIndex = currentIndex > 0 ? currentIndex - 1 : flatNodes.length - 1\n handleSelect(flatNodes[prevIndex].id, false)\n break\n }\n case 'Home':\n e.preventDefault()\n if (flatNodes.length > 0) {\n handleSelect(flatNodes[0].id, false)\n }\n break\n case 'End':\n e.preventDefault()\n if (flatNodes.length > 0) {\n handleSelect(flatNodes[flatNodes.length - 1].id, false)\n }\n break\n }\n },\n [flatNodes, selectedIds, handleSelect]\n )\n\n const containerStyle: CSSProperties = {\n listStyle: 'none',\n margin: 0,\n padding: spacing[1],\n outline: 'none',\n }\n\n return (\n <ul\n ref={ref}\n role=\"tree\"\n aria-label={ariaLabel}\n aria-multiselectable={multiSelect}\n tabIndex={0}\n className={cx('brycks-treeview', `brycks-treeview--${size}`, className)}\n style={containerStyle}\n data-testid={testId}\n onKeyDown={handleKeyDown}\n >\n {data.map((node) => (\n <TreeNodeItem\n key={node.id}\n node={node}\n level={0}\n config={config}\n isSelected={selectedIds.includes(node.id)}\n isExpanded={expandedIds.includes(node.id)}\n showLines={showLines}\n onToggle={handleToggle}\n onSelect={handleSelect}\n renderNode={renderNode}\n selectedIds={selectedIds}\n expandedIds={expandedIds}\n multiSelect={multiSelect}\n />\n ))}\n </ul>\n )\n})\n\nTreeView.displayName = 'TreeView'\n"],"names":["sizeConfig","fontSizes","iconSizes","componentPaddingY","spacing","ChevronIcon","expanded","jsx","durations","easings","TreeNodeItem","node","level","config","isSelected","isExpanded","showLines","onToggle","onSelect","renderNode","selectedIds","expandedIds","multiSelect","hasChildren","handleClick","useCallback","e","handleToggle","handleKeyDown","itemStyle","toggleStyle","iconStyle","lineStyle","jsxs","child","TreeView","forwardRef","data","controlledSelectedIds","defaultSelectedIds","controlledExpandedIds","defaultExpandedIds","onSelectionChange","onExpansionChange","onNodeClick","size","ariaLabel","className","testId","ref","internalSelectedIds","setInternalSelectedIds","useState","internalExpandedIds","setInternalExpandedIds","flatNodes","useMemo","flatten","nodes","result","id","newExpandedIds","eid","handleSelect","additive","n","newSelectedIds","sid","currentIndex","nextIndex","prevIndex","containerStyle","cx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TreeView.js","sources":["../../../../src/components/data/TreeView/TreeView.tsx"],"sourcesContent":["/**\n * TreeView Component\n *\n * A hierarchical tree structure for displaying nested data.\n * Supports selection, expansion, and keyboard navigation.\n *\n * @module components/data/TreeView\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n useMemo,\n type CSSProperties,\n type ReactNode,\n type KeyboardEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\nimport { spacing, fontSizes, durations, easings } from '../../../design-system'\nimport { componentPaddingY, iconSizes } from '../../../design-system/primitives'\n\nexport interface TreeNode {\n /** Unique identifier */\n id: string\n /** Display label */\n label: string\n /** Optional icon */\n icon?: ReactNode\n /** Child nodes */\n children?: TreeNode[]\n /** Whether the node is disabled */\n disabled?: boolean\n /** Additional data */\n data?: unknown\n}\n\nexport type TreeViewSize = 'sm' | 'md' | 'lg'\n\nexport interface TreeViewProps {\n /** Tree data */\n data: TreeNode[]\n /** Selected node IDs (controlled) */\n selectedIds?: string[]\n /** Default selected node IDs (uncontrolled) */\n defaultSelectedIds?: string[]\n /** Expanded node IDs (controlled) */\n expandedIds?: string[]\n /** Default expanded node IDs (uncontrolled) */\n defaultExpandedIds?: string[]\n /** Callback when selection changes */\n onSelectionChange?: (selectedIds: string[]) => void\n /** Callback when expansion changes */\n onExpansionChange?: (expandedIds: string[]) => void\n /** Callback when a node is clicked */\n onNodeClick?: (node: TreeNode) => void\n /** Whether to allow multi-selection */\n multiSelect?: boolean\n /** Component size */\n size?: TreeViewSize\n /** Whether to show connecting lines */\n showLines?: boolean\n /** Custom node renderer */\n renderNode?: (node: TreeNode, isSelected: boolean, isExpanded: boolean) => ReactNode\n /** Label for accessibility */\n 'aria-label'?: string\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nconst sizeConfig: Record<TreeViewSize, { fontSize: number; iconSize: number; padding: number; indent: number }> = {\n sm: { fontSize: fontSizes.sm, iconSize: iconSizes.xs, padding: componentPaddingY.xs, indent: spacing[4] },\n md: { fontSize: fontSizes.base, iconSize: iconSizes.sm, padding: componentPaddingY.sm, indent: spacing[5] },\n lg: { fontSize: fontSizes.md, iconSize: iconSizes.md, padding: componentPaddingY.md, indent: spacing[6] },\n}\n\nfunction ChevronIcon({ expanded }: { expanded: boolean }) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n style={{\n transform: expanded ? 'rotate(90deg)' : 'rotate(0)',\n transition: `transform ${durations.fast}ms ${easings.easeOut}`,\n }}\n >\n <path d=\"M6 4l4 4-4 4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\ninterface TreeNodeItemProps {\n node: TreeNode\n level: number\n config: typeof sizeConfig.md\n isSelected: boolean\n isExpanded: boolean\n showLines: boolean\n onToggle: (id: string) => void\n onSelect: (id: string, multi: boolean) => void\n renderNode?: TreeViewProps['renderNode']\n selectedIds: string[]\n expandedIds: string[]\n multiSelect: boolean\n}\n\nfunction TreeNodeItem({\n node,\n level,\n config,\n isSelected,\n isExpanded,\n showLines,\n onToggle,\n onSelect,\n renderNode,\n selectedIds,\n expandedIds,\n multiSelect,\n}: TreeNodeItemProps) {\n const hasChildren = node.children && node.children.length > 0\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n if (node.disabled) return\n onSelect(node.id, e.ctrlKey || e.metaKey)\n },\n [node.id, node.disabled, onSelect]\n )\n\n const handleToggle = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n if (hasChildren) {\n onToggle(node.id)\n }\n },\n [node.id, hasChildren, onToggle]\n )\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n if (node.disabled) return\n\n switch (e.key) {\n case 'Enter':\n case ' ':\n e.preventDefault()\n onSelect(node.id, e.ctrlKey || e.metaKey)\n break\n case 'ArrowRight':\n e.preventDefault()\n if (hasChildren && !isExpanded) {\n onToggle(node.id)\n }\n break\n case 'ArrowLeft':\n e.preventDefault()\n if (hasChildren && isExpanded) {\n onToggle(node.id)\n }\n break\n }\n },\n [node.id, node.disabled, hasChildren, isExpanded, onToggle, onSelect]\n )\n\n // Only the depth-based horizontal offset is dynamic (computed from `level`\n // and the per-size indent); everything else is class-driven.\n const itemStyle: CSSProperties = {\n paddingLeft: spacing[2] + level * config.indent,\n }\n\n // Connecting line offset is also depth-based.\n const lineStyle: CSSProperties = {\n left: spacing[2] + (level - 1) * config.indent + config.iconSize / 2,\n }\n\n return (\n <li role=\"treeitem\" aria-selected={isSelected} aria-expanded={hasChildren ? isExpanded : undefined}>\n <div\n tabIndex={node.disabled ? -1 : 0}\n className={cx(\n 'brycks-treeview__item',\n isSelected && 'brycks-treeview__item--selected',\n node.disabled && 'brycks-treeview__item--disabled'\n )}\n style={itemStyle}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n >\n {showLines && level > 0 && (\n <span className=\"brycks-treeview__line\" style={lineStyle} aria-hidden=\"true\" />\n )}\n <span className=\"brycks-treeview__toggle\" onClick={handleToggle}>\n {hasChildren && <ChevronIcon expanded={isExpanded} />}\n </span>\n {node.icon && <span className=\"brycks-treeview__icon\">{node.icon}</span>}\n {renderNode ? (\n renderNode(node, isSelected, isExpanded)\n ) : (\n <span className=\"brycks-treeview__label\">{node.label}</span>\n )}\n </div>\n {hasChildren && isExpanded && (\n <ul role=\"group\" className=\"brycks-treeview__group\">\n {node.children!.map((child) => (\n <TreeNodeItem\n key={child.id}\n node={child}\n level={level + 1}\n config={config}\n isSelected={selectedIds.includes(child.id)}\n isExpanded={expandedIds.includes(child.id)}\n showLines={showLines}\n onToggle={onToggle}\n onSelect={onSelect}\n renderNode={renderNode}\n selectedIds={selectedIds}\n expandedIds={expandedIds}\n multiSelect={multiSelect}\n />\n ))}\n </ul>\n )}\n </li>\n )\n}\n\nexport const TreeView = forwardRef<HTMLUListElement, TreeViewProps>(function TreeView(\n {\n data,\n selectedIds: controlledSelectedIds,\n defaultSelectedIds = [],\n expandedIds: controlledExpandedIds,\n defaultExpandedIds = [],\n onSelectionChange,\n onExpansionChange,\n onNodeClick,\n multiSelect = false,\n size = 'md',\n showLines = false,\n renderNode,\n 'aria-label': ariaLabel = 'Tree',\n className,\n testId,\n },\n ref\n) {\n const [internalSelectedIds, setInternalSelectedIds] = useState<string[]>(defaultSelectedIds)\n const [internalExpandedIds, setInternalExpandedIds] = useState<string[]>(defaultExpandedIds)\n\n const selectedIds = controlledSelectedIds !== undefined ? controlledSelectedIds : internalSelectedIds\n const expandedIds = controlledExpandedIds !== undefined ? controlledExpandedIds : internalExpandedIds\n const config = sizeConfig[size]\n\n // Flatten all nodes for keyboard navigation\n const flatNodes = useMemo(() => {\n const flatten = (nodes: TreeNode[], result: TreeNode[] = []): TreeNode[] => {\n nodes.forEach((node) => {\n result.push(node)\n if (node.children && expandedIds.includes(node.id)) {\n flatten(node.children, result)\n }\n })\n return result\n }\n return flatten(data)\n }, [data, expandedIds])\n\n const handleToggle = useCallback(\n (id: string) => {\n const newExpandedIds = expandedIds.includes(id)\n ? expandedIds.filter((eid) => eid !== id)\n : [...expandedIds, id]\n\n if (controlledExpandedIds === undefined) {\n setInternalExpandedIds(newExpandedIds)\n }\n onExpansionChange?.(newExpandedIds)\n },\n [expandedIds, controlledExpandedIds, onExpansionChange]\n )\n\n const handleSelect = useCallback(\n (id: string, additive: boolean) => {\n const node = flatNodes.find((n) => n.id === id)\n if (node) {\n onNodeClick?.(node)\n }\n\n let newSelectedIds: string[]\n if (multiSelect && additive) {\n newSelectedIds = selectedIds.includes(id)\n ? selectedIds.filter((sid) => sid !== id)\n : [...selectedIds, id]\n } else {\n newSelectedIds = selectedIds.includes(id) && selectedIds.length === 1 ? [] : [id]\n }\n\n if (controlledSelectedIds === undefined) {\n setInternalSelectedIds(newSelectedIds)\n }\n onSelectionChange?.(newSelectedIds)\n },\n [flatNodes, multiSelect, selectedIds, controlledSelectedIds, onSelectionChange, onNodeClick]\n )\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLUListElement>) => {\n const currentIndex = flatNodes.findIndex((n) => selectedIds.includes(n.id))\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const nextIndex = currentIndex < flatNodes.length - 1 ? currentIndex + 1 : 0\n handleSelect(flatNodes[nextIndex].id, false)\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prevIndex = currentIndex > 0 ? currentIndex - 1 : flatNodes.length - 1\n handleSelect(flatNodes[prevIndex].id, false)\n break\n }\n case 'Home':\n e.preventDefault()\n if (flatNodes.length > 0) {\n handleSelect(flatNodes[0].id, false)\n }\n break\n case 'End':\n e.preventDefault()\n if (flatNodes.length > 0) {\n handleSelect(flatNodes[flatNodes.length - 1].id, false)\n }\n break\n }\n },\n [flatNodes, selectedIds, handleSelect]\n )\n\n return (\n <ul\n ref={ref}\n role=\"tree\"\n aria-label={ariaLabel}\n aria-multiselectable={multiSelect}\n tabIndex={0}\n className={cx('brycks-treeview', `brycks-treeview--${size}`, className)}\n data-testid={testId}\n onKeyDown={handleKeyDown}\n >\n {data.map((node) => (\n <TreeNodeItem\n key={node.id}\n node={node}\n level={0}\n config={config}\n isSelected={selectedIds.includes(node.id)}\n isExpanded={expandedIds.includes(node.id)}\n showLines={showLines}\n onToggle={handleToggle}\n onSelect={handleSelect}\n renderNode={renderNode}\n selectedIds={selectedIds}\n expandedIds={expandedIds}\n multiSelect={multiSelect}\n />\n ))}\n </ul>\n )\n})\n\nTreeView.displayName = 'TreeView'\n"],"names":["sizeConfig","fontSizes","iconSizes","componentPaddingY","spacing","ChevronIcon","expanded","jsx","durations","easings","TreeNodeItem","node","level","config","isSelected","isExpanded","showLines","onToggle","onSelect","renderNode","selectedIds","expandedIds","multiSelect","hasChildren","handleClick","useCallback","e","handleToggle","handleKeyDown","itemStyle","lineStyle","jsxs","cx","child","TreeView","forwardRef","data","controlledSelectedIds","defaultSelectedIds","controlledExpandedIds","defaultExpandedIds","onSelectionChange","onExpansionChange","onNodeClick","size","ariaLabel","className","testId","ref","internalSelectedIds","setInternalSelectedIds","useState","internalExpandedIds","setInternalExpandedIds","flatNodes","useMemo","flatten","nodes","result","id","newExpandedIds","eid","handleSelect","additive","n","newSelectedIds","sid","currentIndex","nextIndex","prevIndex"],"mappings":"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"}
|