bough 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/lib/primitives/useTree.ts","../src/lib/primitives/useTreeItem.ts","../src/lib/primitives/context.ts","../src/lib/primitives/Tree.tsx","../src/lib/primitives/utils.ts","../src/lib/utils/cn.ts"],"sourcesContent":["import { useCallback, useMemo, useRef, useState } from \"react\";\nimport type {\n TreeNode,\n TreeState,\n UseTreeProps,\n UseTreeReturn,\n} from \"./types\";\n\ninterface NodeInfo<T = unknown> {\n node: TreeNode<T>;\n parentId: string | null;\n}\n\n/**\n * Headless hook for managing tree state.\n * Handles focus, selection, expansion, and keyboard navigation.\n * \n * @example\n * ```tsx\n * const { state, getRootProps, handleKeyDown, treeRef } = useTree({\n * onSelect: (node) => console.log('Selected:', node),\n * defaultExpandedIds: ['node-1'],\n * });\n * \n * return (\n * <div {...getRootProps()} ref={treeRef} onKeyDown={handleKeyDown}>\n * {nodes.map(node => <TreeItem key={node.id} node={node} />)}\n * </div>\n * );\n * ```\n */\nexport function useTree<T = unknown>({\n defaultExpandedIds = [],\n expandedIds: controlledExpandedIds,\n onExpandedIdsChange,\n selectedId: controlledSelectedId,\n onSelect,\n onExpandChange,\n}: UseTreeProps<T> = {}): UseTreeReturn<T> {\n // Internal state\n const [focusedId, setFocusedId] = useState<string | null>(null);\n const [internalSelectedId, setInternalSelectedId] = useState<string | null>(null);\n const [internalExpandedIds, setInternalExpandedIds] = useState<Set<string>>(\n () => new Set(defaultExpandedIds)\n );\n\n // Determine if we're controlled or uncontrolled\n const isExpandedControlled = controlledExpandedIds !== undefined;\n const expandedIds = isExpandedControlled ? controlledExpandedIds : internalExpandedIds;\n const selectedId = controlledSelectedId ?? internalSelectedId;\n\n // Node registry for navigation\n const nodeRegistry = useRef<Map<string, NodeInfo<T>>>(new Map());\n const [firstNodeId, setFirstNodeId] = useState<string | null>(null);\n const visibleNodeIdsRef = useRef<string[]>([]);\n const treeRef = useRef<HTMLDivElement>(null);\n\n // Type-ahead state\n const typeaheadBuffer = useRef<string>(\"\");\n const typeaheadTimeout = useRef<ReturnType<typeof setTimeout>>();\n\n // Update expanded IDs (internal or via callback)\n const updateExpandedIds = useCallback((updater: (prev: Set<string>) => Set<string>) => {\n if (isExpandedControlled) {\n const newIds = updater(expandedIds);\n onExpandedIdsChange?.(newIds);\n } else {\n setInternalExpandedIds(updater);\n }\n }, [isExpandedControlled, expandedIds, onExpandedIdsChange]);\n\n // Register a node\n const registerNode = useCallback((nodeId: string, node: TreeNode<T>, parentId: string | null) => {\n nodeRegistry.current.set(nodeId, { node, parentId });\n if (parentId === null) {\n setFirstNodeId((current) => current ?? nodeId);\n }\n }, []);\n\n // Unregister a node\n const unregisterNode = useCallback((nodeId: string) => {\n nodeRegistry.current.delete(nodeId);\n }, []);\n\n // Get parent node ID\n const getParentId = useCallback((nodeId: string): string | null => {\n return nodeRegistry.current.get(nodeId)?.parentId ?? null;\n }, []);\n\n // Get node info\n const getNode = useCallback((nodeId: string): TreeNode<T> | null => {\n return nodeRegistry.current.get(nodeId)?.node ?? null;\n }, []);\n\n // Check if a node is expanded\n const isExpanded = useCallback((nodeId: string): boolean => {\n return expandedIds.has(nodeId);\n }, [expandedIds]);\n\n // Check if a node is selected\n const isSelected = useCallback((nodeId: string): boolean => {\n return selectedId === nodeId;\n }, [selectedId]);\n\n // Check if a node is focused\n const isFocused = useCallback((nodeId: string): boolean => {\n return focusedId === nodeId;\n }, [focusedId]);\n\n // Toggle expansion\n const toggleExpanded = useCallback((nodeId: string, node: TreeNode<T>) => {\n updateExpandedIds((prev) => {\n const next = new Set(prev);\n const willBeExpanded = !next.has(nodeId);\n if (willBeExpanded) {\n next.add(nodeId);\n } else {\n next.delete(nodeId);\n }\n onExpandChange?.(node, willBeExpanded);\n return next;\n });\n }, [updateExpandedIds, onExpandChange]);\n\n // Expand a node\n const expand = useCallback((nodeId: string) => {\n updateExpandedIds((prev) => {\n if (prev.has(nodeId)) return prev;\n const next = new Set(prev);\n next.add(nodeId);\n const nodeInfo = nodeRegistry.current.get(nodeId);\n if (nodeInfo) {\n onExpandChange?.(nodeInfo.node, true);\n }\n return next;\n });\n }, [updateExpandedIds, onExpandChange]);\n\n // Collapse a node\n const collapse = useCallback((nodeId: string) => {\n updateExpandedIds((prev) => {\n if (!prev.has(nodeId)) return prev;\n const next = new Set(prev);\n next.delete(nodeId);\n const nodeInfo = nodeRegistry.current.get(nodeId);\n if (nodeInfo) {\n onExpandChange?.(nodeInfo.node, false);\n }\n return next;\n });\n }, [updateExpandedIds, onExpandChange]);\n\n // Expand all nodes\n const expandAll = useCallback(() => {\n updateExpandedIds(() => {\n const allIds = new Set<string>();\n nodeRegistry.current.forEach((info, nodeId) => {\n if (info.node.children && info.node.children.length > 0) {\n allIds.add(nodeId);\n }\n });\n return allIds;\n });\n }, [updateExpandedIds]);\n\n // Collapse all nodes\n const collapseAll = useCallback(() => {\n updateExpandedIds(() => new Set());\n }, [updateExpandedIds]);\n\n // Select a node\n const selectNode = useCallback((nodeId: string, node: TreeNode<T>) => {\n setInternalSelectedId(nodeId);\n onSelect?.(node);\n }, [onSelect]);\n\n // Get visible node IDs from DOM\n const getVisibleNodeIds = useCallback((): string[] => {\n if (!treeRef.current) return [];\n const treeitems = treeRef.current.querySelectorAll('[role=\"treeitem\"]');\n const ids: string[] = [];\n treeitems.forEach((item) => {\n const id = item.getAttribute(\"data-node-id\");\n if (id) {\n const isVisible = !item.closest('[role=\"group\"][aria-hidden=\"true\"]');\n if (isVisible) {\n ids.push(id);\n }\n }\n });\n visibleNodeIdsRef.current = ids;\n return ids;\n }, []);\n\n // Focus a specific node\n const focusNode = useCallback((nodeId: string) => {\n setFocusedId(nodeId);\n const element = treeRef.current?.querySelector(`[data-node-id=\"${nodeId}\"]`);\n if (element instanceof HTMLElement) {\n element.focus();\n }\n }, []);\n\n // Navigate to node\n const navigateToNode = useCallback((direction: \"next\" | \"prev\" | \"first\" | \"last\", currentId?: string | null) => {\n const visibleIds = getVisibleNodeIds();\n if (visibleIds.length === 0) return;\n\n let effectiveFocusedId = currentId ?? focusedId;\n if (!effectiveFocusedId && document.activeElement) {\n effectiveFocusedId = (document.activeElement as HTMLElement).getAttribute?.(\"data-node-id\");\n }\n\n let targetIndex: number;\n const currentIndex = effectiveFocusedId ? visibleIds.indexOf(effectiveFocusedId) : -1;\n\n switch (direction) {\n case \"next\":\n targetIndex = currentIndex < visibleIds.length - 1 ? currentIndex + 1 : currentIndex;\n break;\n case \"prev\":\n targetIndex = currentIndex > 0 ? currentIndex - 1 : 0;\n break;\n case \"first\":\n targetIndex = 0;\n break;\n case \"last\":\n targetIndex = visibleIds.length - 1;\n break;\n }\n\n const targetId = visibleIds[targetIndex];\n if (targetId) {\n focusNode(targetId);\n }\n }, [focusedId, getVisibleNodeIds, focusNode]);\n\n // Handle type-ahead search\n const handleTypeahead = useCallback((char: string) => {\n if (typeaheadTimeout.current) {\n clearTimeout(typeaheadTimeout.current);\n }\n\n typeaheadBuffer.current += char.toLowerCase();\n\n typeaheadTimeout.current = setTimeout(() => {\n typeaheadBuffer.current = \"\";\n }, 500);\n\n const visibleIds = getVisibleNodeIds();\n const currentIndex = focusedId ? visibleIds.indexOf(focusedId) : -1;\n\n for (let i = 0; i < visibleIds.length; i++) {\n const searchIndex = (currentIndex + 1 + i) % visibleIds.length;\n const nodeId = visibleIds[searchIndex];\n const nodeInfo = nodeRegistry.current.get(nodeId);\n if (nodeInfo?.node.name.toLowerCase().startsWith(typeaheadBuffer.current)) {\n focusNode(nodeId);\n break;\n }\n }\n }, [focusedId, getVisibleNodeIds, focusNode]);\n\n // Keyboard handler\n const handleKeyDown = useCallback((event: React.KeyboardEvent) => {\n const { key } = event;\n\n if (!treeRef.current?.contains(document.activeElement)) {\n return;\n }\n\n let currentFocusedId = focusedId;\n if (!currentFocusedId && document.activeElement) {\n const nodeId = (document.activeElement as HTMLElement).getAttribute?.(\"data-node-id\");\n if (nodeId) {\n currentFocusedId = nodeId;\n setFocusedId(nodeId);\n }\n }\n\n switch (key) {\n case \"ArrowDown\":\n event.preventDefault();\n navigateToNode(\"next\", currentFocusedId);\n break;\n\n case \"ArrowUp\":\n event.preventDefault();\n navigateToNode(\"prev\", currentFocusedId);\n break;\n\n case \"ArrowRight\": {\n event.preventDefault();\n if (!currentFocusedId) break;\n const nodeInfo = nodeRegistry.current.get(currentFocusedId);\n if (!nodeInfo) break;\n\n const hasChildren = nodeInfo.node.children && nodeInfo.node.children.length > 0;\n if (hasChildren) {\n if (isExpanded(currentFocusedId)) {\n navigateToNode(\"next\", currentFocusedId);\n } else {\n toggleExpanded(currentFocusedId, nodeInfo.node);\n }\n }\n break;\n }\n\n case \"ArrowLeft\": {\n event.preventDefault();\n if (!currentFocusedId) break;\n const nodeInfo = nodeRegistry.current.get(currentFocusedId);\n if (!nodeInfo) break;\n\n const hasChildren = nodeInfo.node.children && nodeInfo.node.children.length > 0;\n if (hasChildren && isExpanded(currentFocusedId)) {\n toggleExpanded(currentFocusedId, nodeInfo.node);\n } else if (nodeInfo.parentId) {\n focusNode(nodeInfo.parentId);\n }\n break;\n }\n\n case \"Home\":\n event.preventDefault();\n navigateToNode(\"first\", currentFocusedId);\n break;\n\n case \"End\":\n event.preventDefault();\n navigateToNode(\"last\", currentFocusedId);\n break;\n\n case \"Enter\":\n case \" \": {\n event.preventDefault();\n if (!currentFocusedId) break;\n const nodeInfo = nodeRegistry.current.get(currentFocusedId);\n if (nodeInfo) {\n selectNode(currentFocusedId, nodeInfo.node);\n }\n break;\n }\n\n default:\n if (key.length === 1 && !event.ctrlKey && !event.altKey && !event.metaKey) {\n handleTypeahead(key);\n }\n break;\n }\n }, [focusedId, isExpanded, toggleExpanded, navigateToNode, focusNode, selectNode, handleTypeahead]);\n\n // Build state object\n const state = useMemo<TreeState<T>>(() => ({\n focusedId,\n selectedId,\n expandedIds,\n firstNodeId,\n setFocusedId,\n selectNode,\n toggleExpanded,\n expand,\n collapse,\n expandAll,\n collapseAll,\n isExpanded,\n isSelected,\n isFocused,\n registerNode,\n unregisterNode,\n getParentId,\n getNode,\n }), [\n focusedId,\n selectedId,\n expandedIds,\n firstNodeId,\n selectNode,\n toggleExpanded,\n expand,\n collapse,\n expandAll,\n collapseAll,\n isExpanded,\n isSelected,\n isFocused,\n registerNode,\n unregisterNode,\n getParentId,\n getNode,\n ]);\n\n // Get props for root element\n const getRootProps = useCallback((props: Record<string, unknown> = {}) => ({\n role: \"tree\",\n ...props,\n }), []);\n\n return {\n state,\n getRootProps,\n handleKeyDown,\n treeRef,\n };\n}\n\nexport default useTree;\n\n","import { useCallback, useEffect, useMemo } from \"react\";\nimport type { TreeNode, TreeState, UseTreeItemProps, UseTreeItemReturn } from \"./types\";\n\n/**\n * Headless hook for managing individual tree item state and behavior.\n * Handles registration, ARIA props, and interaction handlers.\n * \n * @example\n * ```tsx\n * function MyTreeItem({ node, level, posinset, setsize, parentId }) {\n * const {\n * isExpanded,\n * isSelected,\n * isFocused,\n * hasChildren,\n * getItemProps,\n * getContentProps,\n * getGroupProps,\n * toggle,\n * select,\n * } = useTreeItem({ node, level, posinset, setsize, parentId }, treeState);\n * \n * return (\n * <div {...getItemProps()}>\n * <div {...getContentProps()}>\n * {hasChildren && <ChevronIcon open={isExpanded} />}\n * {node.name}\n * </div>\n * {hasChildren && (\n * <div {...getGroupProps()}>\n * {node.children?.map(...)}\n * </div>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function useTreeItem<T = unknown>(\n { node, level, posinset, setsize, parentId }: UseTreeItemProps<T>,\n state: TreeState<T>\n): UseTreeItemReturn {\n // Generate stable node ID\n const nodeId = node.id ?? `${parentId ?? \"root\"}-${level}-${posinset}-${node.name}`;\n const groupId = `tree-group-${nodeId}`;\n\n const hasChildren = Boolean(node.children && node.children.length > 0);\n const isExpanded = hasChildren && state.isExpanded(nodeId);\n const isSelected = state.isSelected(nodeId);\n const isFocused = state.isFocused(nodeId);\n const isFirstFocusable = state.focusedId === null && parentId === null && posinset === 1;\n const tabIndex = isFocused || isFirstFocusable ? 0 : -1;\n\n // Register/unregister node\n useEffect(() => {\n state.registerNode(nodeId, node as TreeNode<T>, parentId);\n return () => state.unregisterNode(nodeId);\n }, [nodeId, node, parentId, state]);\n\n // Toggle expansion\n const toggle = useCallback(() => {\n if (hasChildren) {\n state.toggleExpanded(nodeId, node as TreeNode<T>);\n }\n }, [hasChildren, nodeId, node, state]);\n\n // Select this item\n const select = useCallback(() => {\n state.selectNode(nodeId, node as TreeNode<T>);\n }, [nodeId, node, state]);\n\n // Get props for the item wrapper element\n const getItemProps = useCallback((props: Record<string, unknown> = {}) => ({\n role: \"treeitem\",\n \"aria-expanded\": hasChildren ? isExpanded : undefined,\n \"aria-selected\": isSelected,\n \"aria-level\": level,\n \"aria-setsize\": setsize,\n \"aria-posinset\": posinset,\n \"aria-owns\": hasChildren ? groupId : undefined,\n \"data-node-id\": nodeId,\n \"data-expanded\": hasChildren ? isExpanded : undefined,\n \"data-selected\": isSelected || undefined,\n \"data-focused\": isFocused || undefined,\n tabIndex,\n onFocus: (event: React.FocusEvent) => {\n event.stopPropagation();\n state.setFocusedId(nodeId);\n (props.onFocus as ((e: React.FocusEvent) => void) | undefined)?.(event);\n },\n ...props,\n }), [hasChildren, isExpanded, isSelected, isFocused, level, setsize, posinset, groupId, nodeId, tabIndex, state]);\n\n // Get props for the content/trigger element\n const getContentProps = useCallback((props: Record<string, unknown> = {}) => ({\n onClick: (event: React.MouseEvent) => {\n event.stopPropagation();\n if (hasChildren) {\n toggle();\n }\n select();\n (props.onClick as ((e: React.MouseEvent) => void) | undefined)?.(event);\n },\n ...props,\n }), [hasChildren, toggle, select]);\n\n // Get props for the group/children container\n const getGroupProps = useCallback((props: Record<string, unknown> = {}) => ({\n id: groupId,\n role: \"group\",\n \"aria-hidden\": !isExpanded,\n \"data-state\": isExpanded ? \"open\" : \"closed\",\n ...props,\n }), [groupId, isExpanded]);\n\n return useMemo(() => ({\n nodeId,\n isExpanded,\n isSelected,\n isFocused,\n isFirstFocusable,\n hasChildren,\n tabIndex,\n getItemProps,\n getContentProps,\n getGroupProps,\n toggle,\n select,\n }), [\n nodeId,\n isExpanded,\n isSelected,\n isFocused,\n isFirstFocusable,\n hasChildren,\n tabIndex,\n getItemProps,\n getContentProps,\n getGroupProps,\n toggle,\n select,\n ]);\n}\n\nexport default useTreeItem;\n\n","import { createContext, useContext } from \"react\";\nimport type { TreeContextValue, UseTreeItemReturn } from \"./types\";\n\n/**\n * Context for sharing tree state across nested components.\n */\nexport const TreeContext = createContext<TreeContextValue | null>(null);\n\n/**\n * Hook to access tree context.\n * Must be used within a Tree.Root component.\n */\nexport function useTreeContext<T = unknown>(): TreeContextValue<T> {\n const context = useContext(TreeContext);\n if (!context) {\n throw new Error(\"useTreeContext must be used within a Tree.Root component\");\n }\n return context as TreeContextValue<T>;\n}\n\n/**\n * Context for sharing tree item state within an item.\n */\nexport const TreeItemContext = createContext<UseTreeItemReturn | null>(null);\n\n/**\n * Hook to access tree item context.\n * Must be used within a Tree.Item component.\n */\nexport function useTreeItemContext(): UseTreeItemReturn {\n const context = useContext(TreeItemContext);\n if (!context) {\n throw new Error(\"useTreeItemContext must be used within a Tree.Item component\");\n }\n return context;\n}\n\n","import React, { forwardRef, useMemo } from \"react\";\nimport type {\n TreeNode,\n TreeRootProps,\n TreeItemProps,\n TreeItemContentProps,\n TreeChevronProps,\n TreeGroupProps,\n TreeContextValue,\n UseTreeProps,\n} from \"./types\";\nimport { useTree } from \"./useTree\";\nimport { useTreeItem } from \"./useTreeItem\";\nimport { TreeContext, TreeItemContext, useTreeContext, useTreeItemContext } from \"./context\";\n\n/**\n * Tree.Root - The root container for a tree.\n * Provides context and keyboard navigation for all nested items.\n * \n * @example\n * ```tsx\n * <Tree.Root aria-label=\"File explorer\">\n * {nodes.map(node => (\n * <Tree.Item key={node.id} node={node} level={1} posinset={idx + 1} setsize={nodes.length} parentId={null}>\n * ...\n * </Tree.Item>\n * ))}\n * </Tree.Root>\n * ```\n */\nfunction TreeRoot<T = unknown>({\n children,\n className,\n style,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n ...props\n}: TreeRootProps & UseTreeProps<T>) {\n const { state, getRootProps, handleKeyDown, treeRef } = useTree<T>(props);\n\n const contextValue = useMemo(() => ({ state, treeRef }), [state, treeRef]);\n\n return (\n <TreeContext.Provider value={contextValue as TreeContextValue}>\n <div\n ref={treeRef as React.RefObject<HTMLDivElement>}\n {...getRootProps()}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n className={className}\n style={style}\n onKeyDown={handleKeyDown}\n >\n {children}\n </div>\n </TreeContext.Provider>\n );\n}\n\n/**\n * Tree.Item - A single item in the tree.\n * Handles ARIA attributes and registration with the tree.\n * \n * @example\n * ```tsx\n * <Tree.Item node={node} level={1} posinset={1} setsize={3} parentId={null}>\n * {({ isExpanded, isSelected, hasChildren }) => (\n * <>\n * <Tree.ItemContent>\n * {hasChildren && <Tree.Chevron />}\n * <span>{node.name}</span>\n * </Tree.ItemContent>\n * {hasChildren && (\n * <Tree.Group>\n * {node.children.map(...)}\n * </Tree.Group>\n * )}\n * </>\n * )}\n * </Tree.Item>\n * ```\n */\nfunction TreeItem<T = unknown>({\n node,\n level,\n posinset,\n setsize,\n parentId,\n children,\n className,\n style,\n}: TreeItemProps<T>) {\n const { state } = useTreeContext<T>();\n const itemState = useTreeItem({ node, level, posinset, setsize, parentId }, state);\n\n const content = typeof children === \"function\" ? children(itemState) : children;\n\n return (\n <TreeItemContext.Provider value={itemState}>\n <div\n {...itemState.getItemProps()}\n className={className}\n style={style}\n >\n {content}\n </div>\n </TreeItemContext.Provider>\n );\n}\n\n/**\n * Tree.ItemContent - The clickable content area of a tree item.\n * Handles click events for selection and expansion.\n * \n * @example\n * ```tsx\n * <Tree.ItemContent className=\"flex items-center gap-2\">\n * <Tree.Chevron />\n * <span>{node.name}</span>\n * </Tree.ItemContent>\n * ```\n */\nconst TreeItemContent = forwardRef<HTMLDivElement, TreeItemContentProps>(\n function TreeItemContent({ children, className, style, onClick, ...props }, ref) {\n const itemState = useTreeItemContext();\n const contentProps = itemState.getContentProps();\n\n const handleClick = onClick ?? contentProps.onClick;\n\n return (\n <div\n ref={ref}\n {...props}\n className={className}\n style={style}\n onClick={handleClick as React.MouseEventHandler<HTMLDivElement>}\n >\n {children}\n </div>\n );\n }\n);\n\n/**\n * Default chevron SVG icon\n */\nfunction DefaultChevron({ open }: { open: boolean }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n style={{\n width: \"0.75rem\",\n height: \"0.75rem\",\n flexShrink: 0,\n transition: \"transform 200ms\",\n transform: open ? \"rotate(180deg)\" : \"rotate(0deg)\",\n }}\n >\n <polyline points=\"18 15 12 9 6 15\" />\n </svg>\n );\n}\n\n/**\n * Tree.Chevron - Expand/collapse indicator for tree items.\n * Only renders if the item has children.\n * \n * @example\n * ```tsx\n * // Default chevron\n * <Tree.Chevron />\n * \n * // Custom chevron\n * <Tree.Chevron>\n * {isExpanded ? <MinusIcon /> : <PlusIcon />}\n * </Tree.Chevron>\n * ```\n */\nfunction TreeChevron({\n children,\n className,\n style,\n openClassName,\n closedClassName,\n}: TreeChevronProps) {\n const { isExpanded, hasChildren } = useTreeItemContext();\n\n if (!hasChildren) {\n // Return a spacer to maintain alignment\n return (\n <span\n style={{ width: \"0.75rem\", height: \"0.75rem\", flexShrink: 0, ...style }}\n className={className}\n aria-hidden=\"true\"\n />\n );\n }\n\n const stateClassName = isExpanded ? openClassName : closedClassName;\n const combinedClassName = [className, stateClassName].filter(Boolean).join(\" \") || undefined;\n\n if (children) {\n return (\n <span className={combinedClassName} style={style} aria-hidden=\"true\">\n {children}\n </span>\n );\n }\n\n return (\n <span className={combinedClassName} style={style}>\n <DefaultChevron open={isExpanded} />\n </span>\n );\n}\n\n/**\n * Tree.Group - Container for child items.\n * Handles visibility based on expansion state.\n * \n * @example\n * ```tsx\n * <Tree.Group className=\"ml-4\">\n * {node.children.map((child, idx) => (\n * <Tree.Item key={child.id} node={child} level={level + 1} ... />\n * ))}\n * </Tree.Group>\n * ```\n */\nfunction TreeGroup({ children, className, style }: TreeGroupProps) {\n const itemState = useTreeItemContext();\n const groupProps = itemState.getGroupProps();\n\n if (!itemState.hasChildren) {\n return null;\n }\n\n return (\n <div\n {...groupProps}\n className={className}\n style={style}\n >\n {children}\n </div>\n );\n}\n\n/**\n * Utility component to recursively render tree nodes.\n * Optional helper for common use cases.\n */\ninterface TreeNodesProps<T = unknown> {\n nodes: TreeNode<T>[];\n level?: number;\n parentId?: string | null;\n renderItem: (props: {\n node: TreeNode<T>;\n level: number;\n posinset: number;\n setsize: number;\n parentId: string | null;\n }) => React.ReactNode;\n}\n\nfunction TreeNodes<T = unknown>({\n nodes,\n level = 1,\n parentId = null,\n renderItem,\n}: TreeNodesProps<T>) {\n return (\n <>\n {nodes.map((node, index) => \n renderItem({\n node,\n level,\n posinset: index + 1,\n setsize: nodes.length,\n parentId,\n })\n )}\n </>\n );\n}\n\n/**\n * Props for Tree.Recursive component\n */\ninterface TreeRecursiveProps<T = unknown> {\n /** Array of root-level nodes */\n nodes: TreeNode<T>[];\n /** Component to render each node's content */\n renderContent: React.ComponentType<TreeNode<T>>;\n /** \n * Whether to apply default CSS classes (tree__row, tree__chevron, etc.)\n * Set to false to go fully unstyled. Defaults to true.\n */\n styled?: boolean;\n /** Additional class name for each row (appended to defaults if styled=true) */\n rowClassName?: string;\n /** Additional class name for the children container */\n groupClassName?: string;\n /** Additional class name for the chevron */\n chevronClassName?: string;\n}\n\n/**\n * Tree.Recursive - Handles recursive rendering of tree nodes.\n * \n * This is a convenience component that handles all the recursive complexity\n * while still giving you control over how each node's content is rendered.\n * \n * By default, applies the library's CSS classes (tree__row, tree__chevron, etc.)\n * Set styled={false} to render without any default classes.\n * \n * @example\n * ```tsx\n * // Simple usage - default styles applied\n * <Tree.Root aria-label=\"Files\" className=\"tree__root\">\n * <Tree.Recursive\n * nodes={nodes}\n * renderContent={({ name }) => <span>{name}</span>}\n * />\n * </Tree.Root>\n * ```\n * \n * @example\n * ```tsx\n * // Unstyled (for custom styling)\n * <Tree.Root aria-label=\"Files\">\n * <Tree.Recursive\n * nodes={nodes}\n * styled={false}\n * renderContent={({ name }) => <span>{name}</span>}\n * />\n * </Tree.Root>\n * ```\n */\nfunction TreeRecursive<T = unknown>({\n nodes,\n renderContent: NodeContent,\n styled = true,\n rowClassName,\n groupClassName,\n chevronClassName,\n}: TreeRecursiveProps<T>) {\n return (\n <>\n {nodes.map((node, index) => (\n <TreeRecursiveItem<T>\n key={node.id ?? `${node.name}-${index}`}\n node={node}\n level={1}\n posinset={index + 1}\n setsize={nodes.length}\n parentId={null}\n NodeContent={NodeContent}\n styled={styled}\n rowClassName={rowClassName}\n groupClassName={groupClassName}\n chevronClassName={chevronClassName}\n />\n ))}\n </>\n );\n}\n\ninterface TreeRecursiveItemProps<T = unknown> {\n node: TreeNode<T>;\n level: number;\n posinset: number;\n setsize: number;\n parentId: string | null;\n NodeContent: React.ComponentType<TreeNode<T>>;\n styled: boolean;\n rowClassName?: string;\n groupClassName?: string;\n chevronClassName?: string;\n}\n\nfunction TreeRecursiveItem<T = unknown>({\n node,\n level,\n posinset,\n setsize,\n parentId,\n NodeContent,\n styled,\n rowClassName,\n groupClassName,\n chevronClassName,\n}: TreeRecursiveItemProps<T>) {\n const hasChildren = Boolean(node.children && node.children.length > 0);\n\n return (\n <TreeItem<T>\n node={node}\n level={level}\n posinset={posinset}\n setsize={setsize}\n parentId={parentId}\n >\n {({ isExpanded, isSelected, isFocused, nodeId }) => {\n // Build class names with defaults when styled=true\n const rowClasses = styled\n ? [\n \"tree__row\",\n isSelected && \"tree__row--selected\",\n isFocused && \"tree__row--focused\",\n rowClassName,\n ].filter(Boolean).join(\" \")\n : rowClassName;\n\n const groupClasses = styled\n ? [\n \"tree__children\",\n isExpanded && \"tree__children--open\",\n groupClassName,\n ].filter(Boolean).join(\" \")\n : groupClassName;\n\n const chevronClasses = styled\n ? [\"tree__chevron\", chevronClassName].filter(Boolean).join(\" \")\n : chevronClassName;\n\n const chevronOpenClass = styled ? \"tree__chevron--open\" : undefined;\n\n return (\n <>\n <TreeItemContent className={rowClasses}>\n <TreeChevron \n className={chevronClasses} \n openClassName={chevronOpenClass} \n />\n <NodeContent {...node} />\n </TreeItemContent>\n {hasChildren && (\n <TreeGroup className={groupClasses}>\n <div className={styled ? \"tree__children-inner\" : undefined}>\n {node.children!.map((childNode, index) => (\n <TreeRecursiveItem<T>\n key={childNode.id ?? `${childNode.name}-${index}`}\n node={childNode as TreeNode<T>}\n level={level + 1}\n posinset={index + 1}\n setsize={node.children!.length}\n parentId={nodeId}\n NodeContent={NodeContent}\n styled={styled}\n rowClassName={rowClassName}\n groupClassName={groupClassName}\n chevronClassName={chevronClassName}\n />\n ))}\n </div>\n </TreeGroup>\n )}\n </>\n );\n }}\n </TreeItem>\n );\n}\n\n/**\n * Tree compound component for building accessible trees.\n * \n * @example\n * ```tsx\n * import { Tree } from 'your-library/primitives';\n * \n * function FileTree({ files }) {\n * return (\n * <Tree.Root aria-label=\"Files\">\n * {files.map((file, idx) => (\n * <Tree.Item key={file.id} node={file} level={1} posinset={idx + 1} setsize={files.length} parentId={null}>\n * {({ isExpanded, hasChildren }) => (\n * <>\n * <Tree.ItemContent className=\"flex items-center gap-2 p-1 hover:bg-gray-100 rounded\">\n * <Tree.Chevron />\n * <span>{file.name}</span>\n * </Tree.ItemContent>\n * {hasChildren && (\n * <Tree.Group className=\"ml-4\">\n * {file.children.map((child, cidx) => (\n * <Tree.Item key={child.id} ... />\n * ))}\n * </Tree.Group>\n * )}\n * </>\n * )}\n * </Tree.Item>\n * ))}\n * </Tree.Root>\n * );\n * }\n * ```\n */\n/**\n * Tree compound component for building accessible trees.\n * \n * @example\n * ```tsx\n * // Simple usage with Tree.Recursive (handles recursion for you)\n * <Tree.Root aria-label=\"Files\">\n * <Tree.Recursive\n * nodes={nodes}\n * renderContent={({ name }) => <span>{name}</span>}\n * />\n * </Tree.Root>\n * ```\n * \n * @example\n * ```tsx\n * // Full control with primitives\n * <Tree.Root aria-label=\"Files\">\n * {nodes.map((node, idx) => (\n * <Tree.Item key={node.id} node={node} level={1} posinset={idx + 1} setsize={nodes.length} parentId={null}>\n * {({ isExpanded, hasChildren }) => (\n * <>\n * <Tree.ItemContent>\n * <Tree.Chevron />\n * <span>{node.name}</span>\n * </Tree.ItemContent>\n * {hasChildren && (\n * <Tree.Group>\n * {node.children.map(...)}\n * </Tree.Group>\n * )}\n * </>\n * )}\n * </Tree.Item>\n * ))}\n * </Tree.Root>\n * ```\n */\nexport const Tree = {\n Root: TreeRoot,\n Item: TreeItem,\n ItemContent: TreeItemContent,\n Chevron: TreeChevron,\n Group: TreeGroup,\n Nodes: TreeNodes,\n Recursive: TreeRecursive,\n};\n\n// Named exports for individual components\nexport {\n TreeRoot,\n TreeItem,\n TreeItemContent,\n TreeChevron,\n TreeGroup,\n TreeNodes,\n TreeRecursive,\n};\n\nexport default Tree;\n\n","import type { TreeNode, TreeNodeInternal } from \"./types\";\n\n/**\n * Options for flattening a tree\n */\nexport interface FlattenTreeOptions {\n /** Starting level (default: 1) */\n startLevel?: number;\n /** Filter function to exclude nodes */\n filter?: (node: TreeNode) => boolean;\n /** Whether to include collapsed nodes' children (default: true) */\n includeCollapsedChildren?: boolean;\n /** Set of expanded node IDs (used when includeCollapsedChildren is false) */\n expandedIds?: Set<string>;\n}\n\n/**\n * Flattens a tree structure into a flat array with computed properties.\n * Useful for virtualized rendering or when you need positional information.\n * \n * @example\n * ```tsx\n * const nodes = [{ name: 'Root', children: [{ name: 'Child' }] }];\n * const flat = flattenTree(nodes);\n * // Returns array with level, posinset, setsize for each node\n * ```\n */\nexport function flattenTree<T = unknown>(\n nodes: TreeNode<T>[],\n options: FlattenTreeOptions = {}\n): TreeNodeInternal<T>[] {\n const {\n startLevel = 1,\n filter,\n includeCollapsedChildren = true,\n expandedIds,\n } = options;\n\n const result: TreeNodeInternal<T>[] = [];\n\n function processNodes(\n items: TreeNode<T>[],\n level: number,\n parentId: string | null\n ) {\n const filteredItems = filter ? items.filter(filter) : items;\n\n filteredItems.forEach((node, index) => {\n const nodeId = node.id ?? `${parentId ?? \"root\"}-${level}-${index + 1}-${node.name}`;\n const hasChildren = Boolean(node.children && node.children.length > 0);\n \n const internalNode: TreeNodeInternal<T> = {\n ...node,\n nodeId,\n level,\n posinset: index + 1,\n setsize: filteredItems.length,\n parentId,\n hasChildren,\n };\n\n result.push(internalNode);\n\n // Process children if they exist and should be included\n if (hasChildren && node.children) {\n const shouldIncludeChildren = includeCollapsedChildren || \n (expandedIds && expandedIds.has(nodeId));\n \n if (shouldIncludeChildren) {\n processNodes(node.children as TreeNode<T>[], level + 1, nodeId);\n }\n }\n });\n }\n\n processNodes(nodes, startLevel, null);\n return result;\n}\n\n/**\n * Options for building a tree from flat data\n */\nexport interface BuildTreeOptions<T, R> {\n /** Function to get the parent ID from a record */\n getParentId: (record: R) => string | null;\n /** Function to get the ID from a record */\n getId: (record: R) => string;\n /** Function to transform a record into a TreeNode */\n transform: (record: R) => Omit<TreeNode<T>, \"children\">;\n}\n\n/**\n * Builds a tree structure from flat data.\n * Useful when working with database records that have parent references.\n * \n * @example\n * ```tsx\n * const records = [\n * { id: '1', name: 'Root', parentId: null },\n * { id: '2', name: 'Child', parentId: '1' },\n * ];\n * \n * const tree = buildTree(records, {\n * getId: r => r.id,\n * getParentId: r => r.parentId,\n * transform: r => ({ id: r.id, name: r.name }),\n * });\n * ```\n */\nexport function buildTree<T, R>(\n records: R[],\n options: BuildTreeOptions<T, R>\n): TreeNode<T>[] {\n const { getId, getParentId, transform } = options;\n \n // Build lookup map and identify roots\n const nodeMap = new Map<string, TreeNode<T>>();\n const roots: TreeNode<T>[] = [];\n\n // First pass: create all nodes\n records.forEach((record) => {\n const id = getId(record);\n const node: TreeNode<T> = {\n ...transform(record),\n children: [],\n };\n nodeMap.set(id, node);\n });\n\n // Second pass: build tree structure\n records.forEach((record) => {\n const id = getId(record);\n const parentId = getParentId(record);\n const node = nodeMap.get(id)!;\n\n if (parentId === null) {\n roots.push(node);\n } else {\n const parent = nodeMap.get(parentId);\n if (parent) {\n parent.children = parent.children || [];\n parent.children.push(node);\n } else {\n // Orphan node - treat as root\n roots.push(node);\n }\n }\n });\n\n // Clean up empty children arrays\n function cleanChildren(nodes: TreeNode<T>[]) {\n nodes.forEach((node) => {\n if (node.children && node.children.length === 0) {\n delete node.children;\n } else if (node.children) {\n cleanChildren(node.children);\n }\n });\n }\n\n cleanChildren(roots);\n return roots;\n}\n\n/**\n * Options for filtering a tree\n */\nexport interface FilterTreeOptions<T> {\n /** Keep ancestors of matching nodes (default: true) */\n keepAncestors?: boolean;\n /** Keep descendants of matching nodes (default: false) */\n keepDescendants?: boolean;\n}\n\n/**\n * Filters a tree structure, optionally keeping ancestors/descendants.\n * \n * @example\n * ```tsx\n * const filtered = filterTree(nodes, \n * node => node.name.includes('search'),\n * { keepAncestors: true }\n * );\n * ```\n */\nexport function filterTree<T = unknown>(\n nodes: TreeNode<T>[],\n predicate: (node: TreeNode<T>) => boolean,\n options: FilterTreeOptions<T> = {}\n): TreeNode<T>[] {\n const { keepAncestors = true, keepDescendants = false } = options;\n\n function filterNodes(items: TreeNode<T>[]): TreeNode<T>[] {\n const result: TreeNode<T>[] = [];\n\n items.forEach((node) => {\n const matches = predicate(node);\n let filteredChildren: TreeNode<T>[] = [];\n\n if (node.children && node.children.length > 0) {\n if (matches && keepDescendants) {\n // Keep all descendants as-is\n filteredChildren = node.children;\n } else {\n // Recursively filter children\n filteredChildren = filterNodes(node.children);\n }\n }\n\n if (matches) {\n // Node matches - include it\n result.push({\n ...node,\n children: filteredChildren.length > 0 ? filteredChildren : undefined,\n });\n } else if (keepAncestors && filteredChildren.length > 0) {\n // Node doesn't match but has matching descendants\n result.push({\n ...node,\n children: filteredChildren,\n });\n }\n });\n\n return result;\n }\n\n return filterNodes(nodes);\n}\n\n/**\n * Options for searching a tree\n */\nexport interface SearchTreeOptions {\n /** Case-insensitive search (default: true) */\n ignoreCase?: boolean;\n /** Search in additional fields (default: only name) */\n searchFields?: string[];\n /** Minimum characters to trigger search (default: 1) */\n minLength?: number;\n}\n\n/**\n * Searches a tree for nodes matching a query string.\n * Returns a filtered tree with ancestors preserved.\n * \n * @example\n * ```tsx\n * const results = searchTree(nodes, 'component', { ignoreCase: true });\n * ```\n */\nexport function searchTree<T = unknown>(\n nodes: TreeNode<T>[],\n query: string,\n options: SearchTreeOptions = {}\n): TreeNode<T>[] {\n const { ignoreCase = true, searchFields = [], minLength = 1 } = options;\n\n if (!query || query.length < minLength) {\n return nodes;\n }\n\n const searchQuery = ignoreCase ? query.toLowerCase() : query;\n\n const matches = (node: TreeNode<T>): boolean => {\n const name = ignoreCase ? node.name.toLowerCase() : node.name;\n if (name.includes(searchQuery)) {\n return true;\n }\n\n // Check additional fields in data\n if (node.data && searchFields.length > 0) {\n const data = node.data as Record<string, unknown>;\n return searchFields.some((field) => {\n const value = data[field];\n if (typeof value === \"string\") {\n const fieldValue = ignoreCase ? value.toLowerCase() : value;\n return fieldValue.includes(searchQuery);\n }\n return false;\n });\n }\n\n return false;\n };\n\n return filterTree(nodes, matches, { keepAncestors: true, keepDescendants: false });\n}\n\n/**\n * Finds a node by ID in a tree structure.\n */\nexport function findNodeById<T = unknown>(\n nodes: TreeNode<T>[],\n id: string\n): TreeNode<T> | null {\n for (const node of nodes) {\n if (node.id === id) {\n return node;\n }\n if (node.children) {\n const found = findNodeById(node.children, id);\n if (found) {\n return found;\n }\n }\n }\n return null;\n}\n\n/**\n * Gets the path from root to a node by ID.\n * Returns array of node IDs from root to target.\n */\nexport function getNodePath<T = unknown>(\n nodes: TreeNode<T>[],\n targetId: string\n): string[] {\n function findPath(items: TreeNode<T>[], path: string[]): string[] | null {\n for (const node of items) {\n const nodeId = node.id ?? node.name;\n const currentPath = [...path, nodeId];\n \n if (nodeId === targetId) {\n return currentPath;\n }\n \n if (node.children) {\n const found = findPath(node.children, currentPath);\n if (found) {\n return found;\n }\n }\n }\n return null;\n }\n\n return findPath(nodes, []) ?? [];\n}\n\n/**\n * Gets all node IDs in a tree (for expand all functionality).\n */\nexport function getAllNodeIds<T = unknown>(nodes: TreeNode<T>[]): string[] {\n const ids: string[] = [];\n\n function collectIds(items: TreeNode<T>[], parentId: string | null, level: number) {\n items.forEach((node, index) => {\n const nodeId = node.id ?? `${parentId ?? \"root\"}-${level}-${index + 1}-${node.name}`;\n ids.push(nodeId);\n if (node.children) {\n collectIds(node.children, nodeId, level + 1);\n }\n });\n }\n\n collectIds(nodes, null, 1);\n return ids;\n}\n\n/**\n * Gets all expandable node IDs (nodes with children).\n */\nexport function getExpandableNodeIds<T = unknown>(nodes: TreeNode<T>[]): string[] {\n const ids: string[] = [];\n\n function collectIds(items: TreeNode<T>[], parentId: string | null, level: number) {\n items.forEach((node, index) => {\n const nodeId = node.id ?? `${parentId ?? \"root\"}-${level}-${index + 1}-${node.name}`;\n if (node.children && node.children.length > 0) {\n ids.push(nodeId);\n collectIds(node.children, nodeId, level + 1);\n }\n });\n }\n\n collectIds(nodes, null, 1);\n return ids;\n}\n\n","/**\n * Utility function to combine CSS class names.\n * Filters out falsy values and joins the rest with spaces.\n */\nexport function cn(\n ...inputs: (string | undefined | null | false)[]\n): string {\n return inputs.filter(Boolean).join(\" \");\n}\n\n"],"names":["useTree","defaultExpandedIds","controlledExpandedIds","onExpandedIdsChange","controlledSelectedId","onSelect","onExpandChange","focusedId","setFocusedId","useState","internalSelectedId","setInternalSelectedId","internalExpandedIds","setInternalExpandedIds","isExpandedControlled","expandedIds","selectedId","nodeRegistry","useRef","firstNodeId","setFirstNodeId","visibleNodeIdsRef","treeRef","typeaheadBuffer","typeaheadTimeout","updateExpandedIds","useCallback","updater","newIds","registerNode","nodeId","node","parentId","current","unregisterNode","getParentId","_a","getNode","isExpanded","isSelected","isFocused","toggleExpanded","prev","next","willBeExpanded","expand","nodeInfo","collapse","expandAll","allIds","info","collapseAll","selectNode","getVisibleNodeIds","treeitems","ids","item","id","focusNode","element","navigateToNode","direction","currentId","visibleIds","effectiveFocusedId","_b","targetIndex","currentIndex","targetId","handleTypeahead","char","i","searchIndex","handleKeyDown","event","key","currentFocusedId","_c","state","useMemo","getRootProps","props","useTreeItem","level","posinset","setsize","groupId","hasChildren","isFirstFocusable","tabIndex","useEffect","toggle","select","getItemProps","getContentProps","getGroupProps","TreeContext","createContext","useTreeContext","context","useContext","TreeItemContext","useTreeItemContext","TreeRoot","children","className","style","ariaLabel","ariaLabelledby","contextValue","jsx","TreeItem","itemState","content","TreeItemContent","forwardRef","onClick","ref","contentProps","handleClick","DefaultChevron","open","TreeChevron","openClassName","closedClassName","combinedClassName","TreeGroup","groupProps","TreeNodes","nodes","renderItem","index","TreeRecursive","NodeContent","styled","rowClassName","groupClassName","chevronClassName","Fragment","TreeRecursiveItem","rowClasses","groupClasses","chevronClasses","jsxs","childNode","Tree","flattenTree","options","startLevel","filter","includeCollapsedChildren","result","processNodes","items","filteredItems","internalNode","buildTree","records","getId","transform","nodeMap","roots","record","parent","cleanChildren","filterTree","predicate","keepAncestors","keepDescendants","filterNodes","matches","filteredChildren","searchTree","query","ignoreCase","searchFields","minLength","searchQuery","data","field","value","findNodeById","found","getNodePath","findPath","path","currentPath","getAllNodeIds","collectIds","getExpandableNodeIds","cn","inputs"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ .tree{--tree-text-color: inherit;--tree-text-muted: #6b7280;--tree-hover-bg: rgba(0, 0, 0, .05);--tree-focus-ring: #3b82f6;--tree-focus-ring-offset: #ffffff;--tree-selected-bg: rgba(59, 130, 246, .1);--tree-gap: 2px;--tree-indent: 1.5rem;--tree-row-radius: .25rem;--tree-transition-duration: .2s;--tree-collapse-easing: cubic-bezier(.4, 0, .2, 1);--tree-chevron-size: .75rem;--tree-chevron-color: currentColor;color:var(--tree-text-color)}.tree__root{display:flex;flex-direction:column;gap:var(--tree-gap)}.tree__root:focus{outline:none}.tree__row{display:flex;align-items:center;justify-content:flex-start;gap:.5rem;padding:.25rem .5rem;border-radius:var(--tree-row-radius);border:2px solid transparent;cursor:pointer;transition:background-color var(--tree-transition-duration),border-color var(--tree-transition-duration),box-shadow var(--tree-transition-duration);outline:none}.tree__row:hover{background-color:var(--tree-hover-bg)}.tree__row--focused{box-shadow:0 0 0 2px var(--tree-focus-ring-offset),0 0 0 4px var(--tree-focus-ring)}.tree__row--selected,.tree__row--selected:hover{background-color:var(--tree-selected-bg)}.tree__chevron{width:var(--tree-chevron-size);height:var(--tree-chevron-size);color:var(--tree-chevron-color);transition:transform var(--tree-transition-duration);flex-shrink:0}.tree__chevron--open{transform:rotate(180deg)}.tree__children{display:grid;margin-left:var(--tree-indent);transition:grid-template-rows var(--tree-transition-duration) var(--tree-collapse-easing);grid-template-rows:0fr}.tree__children--open{grid-template-rows:1fr}.tree__children-inner{overflow:hidden;display:flex;flex-direction:column;gap:var(--tree-gap)}.tree--dark{--tree-text-muted: #9ca3af;--tree-hover-bg: rgba(255, 255, 255, .1);--tree-focus-ring: #60a5fa;--tree-focus-ring-offset: #1f2937;--tree-selected-bg: rgba(96, 165, 250, .15)}@media (forced-colors: active){.tree__row{border:2px solid transparent}.tree__row--focused{outline:3px solid Highlight;outline-offset:2px;box-shadow:none}.tree__row--selected{background-color:Highlight;color:HighlightText}.tree__row:hover{background-color:transparent;border-color:CanvasText}.tree__chevron{color:CanvasText}}@media (prefers-reduced-motion: reduce){.tree__row,.tree__chevron,.tree__children{transition:none}}
package/dist/vite.svg ADDED
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
package/package.json ADDED
@@ -0,0 +1,85 @@
1
+ {
2
+ "name": "bough",
3
+ "version": "0.1.0",
4
+ "description": "A flexible, accessible tree component for React",
5
+ "keywords": [
6
+ "react",
7
+ "tree",
8
+ "treeview",
9
+ "tree-view",
10
+ "bough",
11
+ "file-tree",
12
+ "component",
13
+ "accessible",
14
+ "composable"
15
+ ],
16
+ "author": "Paul Newsam",
17
+ "license": "MIT",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/pnewsam/bough"
21
+ },
22
+ "homepage": "https://github.com/pnewsam/bough#readme",
23
+ "bugs": {
24
+ "url": "https://github.com/pnewsam/bough/issues"
25
+ },
26
+ "type": "module",
27
+ "main": "./dist/index.cjs",
28
+ "module": "./dist/index.mjs",
29
+ "types": "./dist/index.d.ts",
30
+ "exports": {
31
+ ".": {
32
+ "import": {
33
+ "types": "./dist/index.d.ts",
34
+ "default": "./dist/index.mjs"
35
+ },
36
+ "require": {
37
+ "types": "./dist/index.d.ts",
38
+ "default": "./dist/index.cjs"
39
+ }
40
+ },
41
+ "./styles.css": "./dist/styles.css"
42
+ },
43
+ "files": [
44
+ "dist"
45
+ ],
46
+ "sideEffects": [
47
+ "*.css"
48
+ ],
49
+ "scripts": {
50
+ "dev": "vite",
51
+ "build": "vite build",
52
+ "build:lib": "vite build --mode lib",
53
+ "preview": "vite preview",
54
+ "lint": "eslint .",
55
+ "prepublishOnly": "npm run build:lib"
56
+ },
57
+ "peerDependencies": {
58
+ "react": "^18.0.0 || ^19.0.0",
59
+ "react-dom": "^18.0.0 || ^19.0.0"
60
+ },
61
+ "devDependencies": {
62
+ "@eslint/js": "^9.13.0",
63
+ "prism-react-renderer": "^2.4.1",
64
+ "react-router-dom": "^7.11.0",
65
+ "@tailwindcss/postcss": "^4.1.18",
66
+ "@types/react": "^18.3.12",
67
+ "@types/react-dom": "^18.3.1",
68
+ "@vitejs/plugin-react": "^4.3.3",
69
+ "ajv": "^8.17.1",
70
+ "autoprefixer": "^10.4.23",
71
+ "eslint": "^9.13.0",
72
+ "eslint-plugin-react-hooks": "^5.0.0",
73
+ "eslint-plugin-react-refresh": "^0.4.14",
74
+ "globals": "^15.11.0",
75
+ "postcss": "^8.5.6",
76
+ "prettier": "^3.3.3",
77
+ "react": "^18.3.1",
78
+ "react-dom": "^18.3.1",
79
+ "tailwindcss": "^4.1.18",
80
+ "typescript": "~5.6.2",
81
+ "typescript-eslint": "^8.11.0",
82
+ "vite": "^5.4.10",
83
+ "vite-plugin-dts": "^4.3.0"
84
+ }
85
+ }