### Install and Run Hugo Starter Site Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/README.md Clone the repository, rename the project, install dependencies, and start the Hugo development server. ```sh git clone https://github.com/jameskerr/hugo-starter mv hugo-starter my-cool-site # rename to something you want cd my-cool-site yarn hugo server ``` -------------------------------- ### Run Local Development Server Source: https://github.com/jameskerr/react-arborist/blob/main/CONTRIBUTING.md Follow these steps to clone the repository and start the local development server. ```bash yarn && yarn start ``` -------------------------------- ### Install React Arborist Source: https://context7.com/jameskerr/react-arborist/llms.txt Install the package using npm or yarn to add React Arborist to your project. ```bash npm install react-arborist # or yarn add react-arborist ``` -------------------------------- ### Install React Arborist with npm Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Use this command to add react-arborist to your project using npm. ```bash npm install react-arborist ``` -------------------------------- ### Run Development Server Source: https://github.com/jameskerr/react-arborist/blob/main/modules/showcase/README.md Use this command to start the development server for the Next.js application. Open http://localhost:3000 in your browser to view the result. ```bash npm run dev # or yarn dev ``` -------------------------------- ### Install React Arborist with Yarn Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Use this command to add react-arborist to your project using Yarn. ```bash yarn add react-arborist ``` -------------------------------- ### Run Tests for Individual Modules Source: https://github.com/jameskerr/react-arborist/blob/main/CONTRIBUTING.md Navigate into a specific module directory and run tests using this command. Example for react-arborist module. ```bash cd modules/react-arborist && yarn test ``` -------------------------------- ### Define Tree Data Structure Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/content/_index.md Example of a nested data structure representing files and directories, suitable for tree rendering. ```js const data = { name: 'code', path: '/users/jk', files: [ { name: 'react-arborist', path: '/users/jk/code', files: [ { name: 'package.json', path: '/users/jk/code/react-arborist' }, { name: '.prettierrc', path: '/users/jk/code/react-arborist' } ] } ] }; ``` -------------------------------- ### Define Tree Data Structure Source: https://github.com/jameskerr/react-arborist/blob/main/README.md This is an example of the data structure expected by the Tree component. It supports nested children. ```javascript const data = [ { id: "1", name: "Unread" }, { id: "2", name: "Threads" }, { id: "3", name: "Chat Rooms", children: [ { id: "c1", name: "General" }, { id: "c2", name: "Random" }, { id: "c3", name: "Open Source Projects" }, ], }, { id: "4", name: "Direct Messages", children: [ { id: "d1", name: "Alice" }, { id: "d2", name: "Bob" }, { id: "d3", name: "Charlie" }, ], }, ]; ``` -------------------------------- ### Manage Tree Selection with External/Internal Changes Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/content/_index.md This example shows how to integrate external selection management with React Arborist's `useMultiSelection` hook. The `onChange` callback within the `selection` prop is designed to trigger only for internal changes, preventing infinite loops when selection is updated programmatically. ```jsx const selection = useMultiSelection(); return ( { // Now we will include all the relevant information // to perform side effects in here. // This will run if changed internally, // This will not run if changed externally selection.set(e.target.value); } }} /> ); ``` -------------------------------- ### Custom Node Renderer with Tree Line Prefix Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Example of a custom node renderer that uses getTreeLinePrefix to display tree connector lines. Wrap the prefix in a monospace span for correct alignment. ```tsx import { Tree, getTreeLinePrefix } from "react-arborist"; function Node({ node, style }) { return (
{getTreeLinePrefix(node)} {node.data.name}
); } ``` -------------------------------- ### Change Tree Selection Externally Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/content/_index.md This example shows how to programmatically change the tree's selection using the `useSelection` hook and `useEffect`. It selects a single node based on `chatId` and ensures the tree scrolls to the center of the selected node. ```jsx const chatId = useCurrentChatId(); const selection = useSelection(); useEffect(() => { selection.selectOne(chatId, {scroll: 'center'}); }, [chatId]); return ( ); ``` -------------------------------- ### Build Demo Site Source: https://github.com/jameskerr/react-arborist/blob/main/CONTRIBUTING.md Build the demo site for deployment. The output is located in the showcase/out directory. ```bash yarn build ``` -------------------------------- ### Build and Run All Tests Source: https://github.com/jameskerr/react-arborist/blob/main/CONTRIBUTING.md Execute this command from the repository root to build the project and run all tests. ```bash yarn build && yarn test ``` -------------------------------- ### Implement Select All Functionality Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/content/_index.md This snippet demonstrates how to configure keybindings in React Arborist to implement a 'select all' functionality using 'cmd+a'. It also shows basic configuration for nodes, selection, and opens, along with custom renderers. ```jsx const tree = useTree(data, { nodes: { id: (d) => d.path, children: (d) => d.items, searchTerm: 'hi', searchFilter: leavesOnly }, selection: { id: (data) => select(Current.getPath) }, opens: { id: (d) => d.path, isOpen: (d) => d.isOpen }, keybindings: (defaults) => { return { ...defaults(), "cmd+a": () => tree.thisThat() "up": () => tree.focus.up() } } }); return ( {} row: () => {} cursor: () => {} }} /> ); ``` -------------------------------- ### Dynamic Tree Sizing with Resize Observer Source: https://context7.com/jameskerr/react-arborist/llms.txt Implement responsive tree layouts by dynamically sizing the tree component based on its container dimensions using the `useResizeObserver` hook. This ensures the tree adapts to available space. ```tsx import { Tree } from 'react-arborist'; import useResizeObserver from 'use-resize-observer'; function ResponsiveTree() { const { ref, width = 300, height = 400 } = useResizeObserver(); const data = [ { id: "1", name: "Folder 1", children: [ { id: "1-1", name: "File A" }, { id: "1-2", name: "File B" }, ]}, { id: "2", name: "Folder 2", children: [] }, ]; return (
); } ``` -------------------------------- ### Dynamic Sizing Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Details how to implement dynamic sizing for the Tree component by integrating with the `ZeeCoder/use-resize-observer` hook to pass parent dimensions. ```APIDOC ### Dynamic sizing You can add a ref to it with this package [ZeeCoder/use-resize-observer](https://github.com/ZeeCoder/use-resize-observer) That hook will return the height and width of the parent whenever it changes. You then pass these numbers to the Tree. ```js const { ref, width, height } = useResizeObserver();
``` ``` -------------------------------- ### Custom Rendering Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Explains how to fully customize the rendering of tree elements using props like `renderRow`, `renderDragPreview`, `renderCursor`, and by providing a custom `MyNode` component. ```APIDOC ### Custom Rendering Render every single piece of the tree yourself. See the API reference for the props passed to each renderer. ```jsx function App() { return ( {/* The inner element that shows the indentation and data */} {MyNode} ); } ``` ``` -------------------------------- ### Simplest Tree Implementation Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Renders a tree using default settings. The `initialData` prop makes it an uncontrolled component, handling data modifications internally. ```jsx import { Tree } from 'react-arborist'; function App() { return ; } ``` -------------------------------- ### Customizing Data Property Names Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Demonstrates how to use `idAccessor` and `childrenAccessor` props to specify custom property names for node IDs and children in your data structure. ```APIDOC ### Data with Different Property Names The _idAccessor_ and _childrenAccessor_ props allow you to specify the children and id fields in your data. ```jsx function App() { const data = [ { category: "Food", subCategories: [{ category: "Restaurants" }, { category: "Groceries" }], }, ]; return ( d.subCategories} /> ); } ``` ``` -------------------------------- ### Tree Filtering with useNodes Hook Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/content/_index.md Demonstrates how to implement tree filtering directly within the `useNodes` hook by providing `searchTerm` and `searchMatch` options. `searchMatch` can be set to `leafs`, `leavesAndInternal`, or a custom function for flexible filtering. ```jsx const nodes = useNodes({ searchTerm: '', searchMatch: leafs | leavesAndInternal | custom }); ``` -------------------------------- ### Handle Tree Interactions with Event Callbacks Source: https://context7.com/jameskerr/react-arborist/llms.txt Implement various event handlers to respond to user interactions such as node activation, selection changes, focus shifts, and folder toggles. These callbacks allow for custom logic execution based on tree events. Note that `onScroll` provides scroll offset information, and `onClick`/`onContextMenu` can handle events on the tree container itself. ```tsx import { Tree, NodeApi } from 'react-arborist'; import { ListOnScrollProps } from 'react-window'; function TreeWithEvents() { const data = [ { id: "1", name: "Folder A", children: [ { id: "1-1", name: "File 1" }, { id: "1-2", name: "File 2" }, ]}, { id: "2", name: "Folder B", children: [] }, ]; // Called when a node is double-clicked or activated via keyboard const onActivate = (node: NodeApi) => { console.log("Activated:", node.data.name); if (node.isLeaf) { // Open file in editor } }; // Called when selection changes (single or multi-select) const onSelect = (nodes: NodeApi[]) => { console.log("Selected:", nodes.map(n => n.data.name)); }; // Called when a node receives focus const onFocus = (node: NodeApi) => { console.log("Focused:", node.data.name); }; // Called when a folder is opened or closed const onToggle = (id: string) => { console.log("Toggled folder:", id); }; // Called during scroll for implementing features like sticky headers const onScroll = (props: ListOnScrollProps) => { console.log("Scroll offset:", props.scrollOffset); }; // Mouse event handlers on the tree container const onClick = (e: React.MouseEvent) => { // Handle clicks on empty space }; const onContextMenu = (e: React.MouseEvent) => { e.preventDefault(); // Show custom context menu }; return ( ); } ``` -------------------------------- ### Visibility Control API Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Manage the open and closed states of nodes and their parents. ```APIDOC ## Tree API Reference - Visibility ### Description Methods for controlling and querying the visibility (open/closed state) of nodes. ### Methods - **`tree.open(id)`**: Open the node with _id_. - **`tree.close(id)`**: Close the node with _id_. - **`tree.toggle(id)`**: Toggle the open state of the node with _id_. - **`tree.openParents(id)`**: Open all parents of the node with _id_. - **`tree.openSiblings(id)`**: Open all siblings of the node with _id_. - **`tree.openAll()`**: Open all internal nodes. - **`tree.closeAll()`**: Close all internal nodes. - **`tree.isOpen(id)`**: _boolean_ - Returns true if the node with _id_ is open. ``` -------------------------------- ### Node API Reference Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Reference for the Node API, detailing state properties, accessors, selection methods, activation methods, and open/close methods. ```APIDOC ## Node API Reference ### State Properties All these properties on the node instance return booleans related to the state of the node. - `node.isRoot`: Returns true if this is the root node. The root node is added internally by react-arborist and not shown in the UI. - `node.isLeaf`: Returns true if the children property is not an array. - `node.isInternal`: Returns true if the children property is an array. - `node.isOpen`: Returns true if node is internal and in an open state. - `node.isEditing`: Returns true if this node is currently being edited. Use this property in the NodeRenderer to render the rename form. - `node.isSelected`: Returns true if node is selected. - `node.isSelectedStart`: Returns true if node is the first of a contiguous group of selected nodes. Useful for styling. - `node.isSelectedEnd`: Returns true if node is the last of a contiguous group of selected nodes. Useful for styling. - `node.isOnlySelection`: Returns true if node is the only node selected in the tree. - `node.isFocused`: Returns true if node is focused. - `node.isDragging`: Returns true if node is being dragged. - `node.willReceiveDrop`: Returns true if node is internal and the user is hovering a dragged node over it. - `node.state`: Returns an object with all the above properties as keys and boolean values. Useful for adding class names to an element with a library like [clsx](https://github.com/lukeed/clsx) or [classnames](https://github.com/JedWatson/classnames). ```ts type NodeState = { isEditing: boolean; isDragging: boolean; isSelected: boolean; isSelectedStart: boolean; isSelectedEnd: boolean; isFocused: boolean; isOpen: boolean; isClosed: boolean; isLeaf: boolean; isInternal: boolean; willReceiveDrop: boolean; }; ``` ### Accessors - `node.childIndex`: Returns the node's index in relation to its siblings. - `node.next`: Returns the next visible node. The node directly under this node in the tree component. Returns null if none exist. - `node.prev`: Returns the previous visible node. The node directly above this node in the tree component. Returns null if none exist. - `node.nextSibling`: Returns the next sibling in the data of this node. Returns null if none exist. ### Selection Methods - `node.select()`: Select only this node. - `node.deselect()`: Deselect this node. Other nodes may still be selected. - `node.selectMulti()`: Select this node while maintaining all other selections. - `node.selectContiguous()`: Deselect all nodes from the anchor node to the last selected node, the select all nodes from the anchor node to this node. The anchor changes to the focused node after calling `select()` or `selectMulti()`. ### Activation Methods - `node.activate()`: Runs the Tree props' `onActivate` callback passing in this node. - `node.focus()`: Focus this node. ### Open/Close Methods - `node.open()`: Opens the node if it is an internal node. - `node.close()`: Closes the node if it is an internal node. - `node.toggle()`: Toggles the open/closed state of the node if it is an internal node. - `node.openParents()`: Opens all the parents of this node. ### Editing Methods - `node.edit()`: Moves this node into the editing state. Calling `node.isEditing` will return true. - `node.submit(newName)`: Submits `newName` string to the `onRename` handler. Moves this node out of the editing state. - `node.reset()`: Moves this node out of the editing state without submitting a new name. ``` -------------------------------- ### Basic Tree Component Usage Source: https://context7.com/jameskerr/react-arborist/llms.txt Renders a virtualized tree view with drag-and-drop, selection, and editing. Define your tree data with id, name, and optional children. ```tsx import { Tree } from 'react-arborist'; // Define your tree data with id, name, and optional children const data = [ { id: "1", name: "Documents" }, { id: "2", name: "Downloads" }, { id: "3", name: "Projects", children: [ { id: "3-1", name: "react-app" }, { id: "3-2", name: "node-server" }, { id: "3-3", name: "mobile", children: [ { id: "3-3-1", name: "ios" }, { id: "3-3-2", name: "android" }, ], }, ], }, { id: "4", name: "Pictures", children: [ { id: "4-1", name: "vacation.jpg" }, { id: "4-2", name: "profile.png" }, ], }, ]; function App() { return ( ); } ``` -------------------------------- ### Access Tree API Instance via Ref Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Provides access to the Tree's API methods (e.g., `selectAll`) through a `useRef` hook, allowing programmatic control of the tree. ```jsx function App() { const treeRef = useRef(); useEffect(() => { const tree = treeRef.current; tree.selectAll(); /* See the Tree API reference for all you can do with it. */ }, []); return ; } ``` -------------------------------- ### Node API Reference Source: https://context7.com/jameskerr/react-arborist/llms.txt The Node API provides methods and properties for individual tree nodes, including state information, selection methods, and navigation helpers. ```APIDOC ## Node API Reference The Node API provides methods and properties for individual tree nodes, including state information, selection methods, and navigation helpers. ### State Properties (all boolean) - **isRoot** (boolean) - Is the root node (hidden) - **isLeaf** (boolean) - Has no children array - **isInternal** (boolean) - Has children array (folder) - **isOpen** (boolean) - Is expanded - **isClosed** (boolean) - Is collapsed - **isEditing** (boolean) - Currently being renamed - **isSelected** (boolean) - Is selected - **isSelectedStart** (boolean) - First in contiguous selection - **isSelectedEnd** (boolean) - Last in contiguous selection - **isOnlySelection** (boolean) - Only selected node - **isFocused** (boolean) - Has focus - **isDragging** (boolean) - Being dragged - **willReceiveDrop** (boolean) - Drop target highlight ### Accessors - **childIndex** (number) - Index among siblings - **nextNode** (NodeApi) - Next visible node - **prevNode** (NodeApi) - Previous visible node - **sibling** (NodeApi) - Next sibling in data - **parent** (NodeApi) - Parent node - **children** (Array) - Child nodes array - **data** (Object) - Original data object - **level** (number) - Nesting depth - **rowIndex** (number) - Index in visible list ### State Object - **state** (Object) - Get all state as an object (useful for className libraries) - Contains: isEditing, isDragging, isSelected, isSelectedStart, isSelectedEnd, isFocused, isOpen, isClosed, isLeaf, isInternal, willReceiveDrop ### Selection Methods - **select()** - Select only this node - **deselect()** - Deselect this node - **selectMulti()** - Add to selection (Cmd+click) - **selectContiguous()** - Range select (Shift+click) ### Other Methods - **activate()** - Trigger onActivate callback - **focus()** - Focus this node - **toggle()** - Toggle open/closed - **open()** - Open if internal - **close()** - Close if internal - **openParents()** - Open all ancestor nodes - **edit()** - Enter edit mode (returns Promise) - **submit(newName)** - Submit rename - **reset()** - Cancel edit mode ### Built-in Click Handler - **handleClick** - Standard selection behavior ``` -------------------------------- ### Control Expanded/Collapsed State with useOpens Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/content/_index.md Manages the expanded and collapsed state of tree nodes. Can either extract open state from data or use a separate state object. ```jsx // If you keep the open data within your tree data, // you can extract it with the useOpens hook. const [opens, setOpens] = useOpens(data, { id: (d) => d.path isOpen = (d) => d.isOpen }) // Otherwise, you can provide your own object // to keep track of it. const [opens, setOpens] = useState({}) setOpens(newValue) }} /> ``` -------------------------------- ### Integrate Tree State with External Data Store Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/content/_index.md Provides callbacks for common tree operations like moving, editing, creating, deleting, and fetching children. Enables synchronization with backend data stores. ```jsx const nodes = useNodes(data) api.move(args)} onEdit={(args) => api.edit(args)} onCreate={() => api.create(args)} onDelete={() => api.destroy(args)} onOpen={(args) => { nodes.addChild(id, {loading: true}) api.fetchChildren(id) }} onSelect={} onFocus={} nodes={{ value: nodes.value, onChange: nodes.set }} selection={{ value: selection.value, onChange: selection.set }} opens={{ value: opens.value, onChange: opens.set }} focus={{ value: focus.value, onChange: focus.set }} dnd={{ value: dnd.value, onChange: dnd.set }} treeState={{ value: state.value, onChange: state.set }} /> ``` -------------------------------- ### Control Tree State with Tree API Source: https://context7.com/jameskerr/react-arborist/llms.txt Use the Tree API via a ref to programmatically control selection, focus, visibility, and scrolling. Ensure the tree ref is available before calling methods. ```tsx import { Tree, TreeApi } from 'react-arborist'; import { useRef, useEffect } from 'react'; type Item = { id: string; name: string; children?: Item[] }; function TreeWithControls() { const treeRef = useRef>(); useEffect(() => { const tree = treeRef.current; if (!tree) return; // Selection methods tree.selectAll(); // Select all visible nodes tree.deselectAll(); // Clear selection tree.select("node-1"); // Select a specific node tree.selectMulti("node-2"); // Add to selection tree.selectContiguous("node-5"); // Shift-select range // Focus and navigation tree.focus("node-1"); // Focus a node tree.pageUp(); // Move focus up one page tree.pageDown(); // Move focus down one page // Node visibility tree.open("folder-1"); // Open a folder tree.close("folder-1"); // Close a folder tree.toggle("folder-1"); // Toggle open/closed tree.openAll(); // Expand all folders tree.closeAll(); // Collapse all folders tree.openParents("nested-node"); // Open all ancestors // Scrolling tree.scrollTo("node-id", "center"); // Scroll node into view // Node access const first = tree.firstNode; // First visible node const last = tree.lastNode; // Last visible node const focused = tree.focusedNode; // Currently focused node const selected = tree.selectedNodes; // Array of selected nodes const node = tree.get("node-id"); // Get node by ID const atIndex = tree.at(5); // Get node at index // State checks const isOpen = tree.isOpen("id"); const isSelected = tree.isSelected("id"); const isFiltered = tree.isFiltered; const isEditing = tree.isEditing; }, []); return ( ); } ``` -------------------------------- ### Create Nodes from Data with useNodes Hook Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/content/_index.md A hook-based approach to convert data into nodes for the Tree component. Simplifies state management for node data. ```jsx // #APPROVED const nodes = useNodes(myRandomData, { id: (d) => d.path, name: (d) => d.name, children: (d) => d.files, isLeaf: (d) => !('files' in d), sort: (a, b) => a.name - b.name, isVisible: (node) => true // not sure about his yet }); ``` -------------------------------- ### Dynamic Sizing with use-resize-observer in React Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Integrate with the `use-resize-observer` hook to dynamically set the `height` and `width` of the Tree component based on its parent container's size. This ensures the tree adapts to available space. ```js const { ref, width, height } = useResizeObserver();
``` -------------------------------- ### Handle Internal vs. External Input Changes Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/content/_index.md This pattern demonstrates how to manage input values in React, ensuring that the onChange handler only fires for user-initiated changes, not for programmatic state updates. ```jsx const [value, setValue] = useState('hello world'); return setValue(e.target.value)} />; ``` -------------------------------- ### Custom Row, Cursor, and Drag Preview Renderers Source: https://context7.com/jameskerr/react-arborist/llms.txt Defines custom components for rendering rows with hover effects and context menus, a drop cursor with custom styling, and a drag preview that displays the number of items being dragged. These are passed to the Tree component via props like `renderRow`, `renderCursor`, and `renderDragPreview`. ```tsx import { Tree, RowRendererProps, CursorProps, DragPreviewProps } from 'react-arborist'; // Custom row with hover effects and context menu function CustomRow({ node, attrs, innerRef, children }: RowRendererProps) { return (
{ e.preventDefault(); // Show context menu }} > {children}
); } // Custom drop cursor with different styling function CustomCursor({ top, left, indent }: CursorProps) { return (
); } // Custom drag preview showing multiple items function CustomDragPreview({ dragIds, isDragging, offset }: DragPreviewProps) { if (!isDragging || !offset) return null; return (
Moving {dragIds.length} item{dragIds.length > 1 ? "s" : ""}
); } function FullyCustomTree() { const data = [ { id: "1", name: "Custom Tree", children: [ { id: "1-1", name: "With custom renderers" }, ]}, ]; return ( ); } ``` -------------------------------- ### Manage Selection State with useMultiSelection Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/content/_index.md Handles the selection state of tree nodes, allowing external control and synchronization. Useful for integrating with other parts of the application. ```jsx const id = useSelector(Current.fileId) const selection = useMultiSelection(id) useEffect(() => { selection.only(id) }, [id]) ``` -------------------------------- ### Accessing Node State and Data in React Arborist Source: https://context7.com/jameskerr/react-arborist/llms.txt Demonstrates how to access various state properties (e.g., isSelected, isOpen) and data accessors (e.g., parent, children, data) for a tree node. Useful for rendering custom node UIs and logic. ```tsx import { Tree, NodeRendererProps, NodeApi } from 'react-arborist'; function NodeDetails({ node }: NodeRendererProps) { // State properties (all boolean) const { isRoot, // Is the root node (hidden) isLeaf, // Has no children array isInternal, // Has children array (folder) isOpen, // Is expanded isClosed, // Is collapsed isEditing, // Currently being renamed isSelected, // Is selected isSelectedStart, // First in contiguous selection isSelectedEnd, // Last in contiguous selection isOnlySelection, // Only selected node isFocused, // Has focus isDragging, // Being dragged willReceiveDrop, // Drop target highlight } = node; // Accessors const childIndex = node.childIndex; // Index among siblings const nextNode = node.next; // Next visible node const prevNode = node.prev; // Previous visible node const sibling = node.nextSibling; // Next sibling in data const parent = node.parent; // Parent node const children = node.children; // Child nodes array const data = node.data; // Original data object const level = node.level; // Nesting depth const rowIndex = node.rowIndex; // Index in visible list // Get all state as an object (useful for className libraries) const state = node.state; // { isEditing, isDragging, isSelected, isSelectedStart, isSelectedEnd, // isFocused, isOpen, isClosed, isLeaf, isInternal, willReceiveDrop } // Selection methods const handleSelect = () => { node.select(); // Select only this node node.deselect(); // Deselect this node node.selectMulti(); // Add to selection (Cmd+click) node.selectContiguous();// Range select (Shift+click) }; // Other methods const handleActions = () => { node.activate(); // Trigger onActivate callback node.focus(); // Focus this node node.toggle(); // Toggle open/closed node.open(); // Open if internal node.close(); // Close if internal node.openParents(); // Open all ancestor nodes node.edit(); // Enter edit mode (returns Promise) node.submit("newName"); // Submit rename node.reset(); // Cancel edit mode }; // Built-in click handler with standard selection behavior return
{node.data.name}
; } ``` -------------------------------- ### Node Event Handlers Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Handles click events on nodes, with logic for multi-selection and contiguous selection. ```APIDOC ## Node Event Handlers ### Description Handles click events on a node, implementing selection logic based on modifier keys. ### Event Handler - **`_node_.handleClick(_event_)`**: Useful for using the standard selection methods when a node is clicked. If the meta key is down, call _multiSelect()_. If the shift key is down, call _selectContiguous()_. Otherwise, call _select()_ and _activate(). ``` -------------------------------- ### Create Nodes from Data with createNodes Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/content/_index.md Converts arbitrary data into a format usable by the Tree component. Requires defining how to extract id, name, children, and leaf status from your data. ```jsx // #APPROVED const [data, setData] = useState(myRandomData); const nodes = createNodes(data, { id: (d) => d.path, name: (d) => d.name, children: (d) => d.files, isLeaf: (d) => !('files' in d), sort: (a, b) => a.name - b.name, isVisible: (node) => true // not sure about his yet }); setData(nodes.handleChange(e)) }} > ``` -------------------------------- ### Customize Tree Appearance and Behavior Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Allows customization of tree dimensions, node rendering, and various rendering-related props like `openByDefault`, `width`, `height`, `indent`, `rowHeight`, `overscanCount`, and `padding`. ```jsx function App() { return ( {Node} ); } function Node({ node, style, dragHandle }) { /* This node instance can do many things. See the API reference. */ return (
{node.isLeaf ? "🍁" : "🗀"} {node.data.name}
); } ``` -------------------------------- ### Synchronize Tree Selection with External State Source: https://context7.com/jameskerr/react-arborist/llms.txt Use the `selection` prop to link the tree's selected node to an external state variable. The tree will automatically update its selection and scroll to the specified node when the state changes. The `onActivate` callback can be used to update the external state when a node is interacted with. ```tsx import { Tree, NodeApi } from 'react-arborist'; import { useState } from 'react'; function SyncedSelection() { const [currentFile, setCurrentFile] = useState("file-2"); const data = [ { id: "folder-1", name: "Components", children: [ { id: "file-1", name: "Button.tsx" }, { id: "file-2", name: "Input.tsx" }, { id: "file-3", name: "Modal.tsx" }, ]}, { id: "folder-2", name: "Hooks", children: [ { id: "file-4", name: "useAuth.ts" }, { id: "file-5", name: "useForm.ts" }, ]}, ]; const handleActivate = (node: NodeApi) => { // Update external state when a node is activated setCurrentFile(node.id); console.log(`Opened: ${node.data.name}`); }; return (

File Browser

External Controls

Current file: {currentFile}

); } ``` -------------------------------- ### getTreeLinePrefix Function Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Generates a tree-line prefix string using Unix `tree`-style box-drawing characters. This is useful for custom node renderers where you need to display connector lines. ```APIDOC ## getTreeLinePrefix ### Description Generates a tree-line prefix string (using Unix `tree`-style box-drawing characters like `├`, `└`, `│`) for a given node. Useful when you want ASCII/Unicode connector lines in a custom node renderer. ### Function Signature ```ts function getTreeLinePrefix( node: NodeApi, chars?: Partial ): string; type TreeLineChars = { last: string; // default: "└ " middle: string; // default: "├ " pipe: string; // default: "│ " blank: string; // default: "\u3000 " }; ``` ### Usage Example Wrap the prefix in a monospace span so the connectors line up: ```tsx import { Tree, getTreeLinePrefix } from "react-arborist"; function Node({ node, style }) { return (
{getTreeLinePrefix(node)} {node.data.name}
); } ``` ### Customization Pass a partial `chars` object to override any of the default characters (e.g. for an ASCII-only style). ```tsx // Example for ASCII-only style const asciiChars = { last: "`-", middle: "+-", pipe: "| ", blank: " " }; // Usage within a component {getTreeLinePrefix(node, asciiChars)} ``` ``` -------------------------------- ### Render Menu by ID in Hugo Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/layouts/partials/menu.html Renders a menu for a given menu ID. Requires the current page context and the menu ID. Use this partial to display navigation menus. ```html {{- /* Renders a menu for the given menu ID. @context {page} page The current page. @context {string} menuID The menu ID. @example: {{ partial "menu.html" (dict "menuID" "main" "page" .) }} */ -}} {{- $page := .page }} {{- $menuID := .menuID }} {{- with index site.Menus $menuID }} {{- partial "inline/menu/walk.html" (dict "page" $page "menuEntries" .) }} {{- end }} ``` -------------------------------- ### Render Tree Component with Nodes Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/content/_index.md Passes the generated nodes to the Tree component for rendering. The `Node` component is expected to be provided as a child. ```jsx setNodes(newValue) }} > {Node} ``` -------------------------------- ### Walk Menu Entries in Hugo Source: https://github.com/jameskerr/react-arborist/blob/main/modules/docs/layouts/partials/menu.html Recursively walks through menu entries to render them. It determines the active state of menu items based on the current page. This partial is used for hierarchical menu display. ```html {{- define "partials/inline/menu/walk.html" }} {{- $page := .page }} {{- range .menuEntries }} {{- $attrs := dict "href" .URL }} {{- if $page.IsMenuCurrent .Menu . }} {{- $attrs = merge $attrs (dict "class" "active" "aria-current" "page") }} {{- else if $page.HasMenuCurrent .Menu .}} {{- $attrs = merge $attrs (dict "class" "ancestor" "aria-current" "true") }} {{- end }} {{- $name := .Name }} {{- with .Identifier }} {{- with T . }} {{- $name = . }} {{- end }} {{- end }} * {{ $name }} {{- with .Children }} {{- partial "inline/menu/walk.html" (dict "page" $page "menuEntries" .) }} {{- end }} {{- end }} {{- end }} ``` -------------------------------- ### Selection Management API Source: https://github.com/jameskerr/react-arborist/blob/main/README.md Control and query node selection states, including single, multiple, and contiguous selections. ```APIDOC ## Tree API Reference - Selection Methods ### Description Provides methods for managing and querying node selections within the tree. ### Properties - **`tree.selectedIds`**: _Set_ - Returns a set of ids that are selected. - **`tree.selectedNodes`**: _NodeApi[]_ - Returns an array of nodes that are selected. - **`tree.hasNoSelection`**: _boolean_ - Returns true if nothing is selected in the tree. - **`tree.hasSingleSelection`**: _boolean_ - Returns true if there is only one selection. - **`tree.hasMultipleSelections`**: _boolean_ - Returns true if there is more than one selection. ### Methods - **`tree.isSelected(id)`**: _boolean_ - Returns true if the node with _id_ is selected. - **`tree.select(id, [opts])`**: Select only the node with _id_. Accepts an optional options object: `{ align?: "auto" | "smart" | "center" | "end" | "start"; focus?: boolean }`. `align` is forwarded to the scroll behavior; passing `focus: false` suppresses the focus change and the `onFocus` callback. - **`tree.deselect(id)`**: Deselect the node with _id_. - **`tree.selectMulti(id, [opts])`**: Add to the selection the node with _id_. Accepts the same options object as `select`. - **`tree.selectContiguous(id)`**: Deselected nodes between the anchor and the last selected node, then select the nodes between the anchor and the node with _id_. - **`tree.deselectAll()`**: Deselect all nodes. - **`tree.selectAll()`**: Select all nodes. ``` -------------------------------- ### Tree API Methods Source: https://context7.com/jameskerr/react-arborist/llms.txt The Tree API provides methods for various tree operations including selection, focus, visibility, and scrolling. ```APIDOC ## Tree API Reference Access the Tree API via a ref to programmatically control the tree's selection, focus, visibility, and scrolling. The API provides methods for all tree operations. ### Selection Methods - `selectAll()`: Select all visible nodes. - `deselectAll()`: Clear selection. - `select(nodeId)`: Select a specific node. - `selectMulti(nodeId)`: Add a node to the current selection. - `selectContiguous(nodeId)`: Shift-select a range of nodes. ### Focus and Navigation - `focus(nodeId)`: Focus a specific node. - `pageUp()`: Move focus up one page. - `pageDown()`: Move focus down one page. ### Node Visibility - `open(nodeId)`: Open a folder node. - `close(nodeId)`: Close a folder node. - `toggle(nodeId)`: Toggle the open/closed state of a folder node. - `openAll()`: Expand all folder nodes. - `closeAll()`: Collapse all folder nodes. - `openParents(nodeId)`: Open all ancestor nodes of a given node. ### Scrolling - `scrollTo(nodeId, alignment)`: Scroll a node into view. `alignment` can be 'auto', 'center', 'start', or 'end'. ### Node Access - `firstNode`: Get the first visible node. - `lastNode`: Get the last visible node. - `focusedNode`: Get the currently focused node. - `selectedNodes`: Get an array of all selected nodes. - `get(nodeId)`: Get a node by its ID. - `at(index)`: Get the node at a specific index. ### State Checks - `isOpen(nodeId)`: Check if a node is open. - `isSelected(nodeId)`: Check if a node is selected. - `isFiltered`: Check if the tree is currently filtered. - `isEditing`: Check if the tree is in editing mode. ```