{"id":13412409,"url":"https://github.com/brimdata/react-arborist","last_synced_at":"2025-05-14T08:05:17.277Z","repository":{"id":37080543,"uuid":"402492488","full_name":"brimdata/react-arborist","owner":"brimdata","description":"The complete tree view component for React","archived":false,"fork":false,"pushed_at":"2025-02-13T17:52:33.000Z","size":18575,"stargazers_count":3284,"open_issues_count":118,"forks_count":156,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-05-14T08:04:29.559Z","etag":null,"topics":["arborist","react","tree","treeview","treeview-component"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brimdata.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-09-02T16:37:55.000Z","updated_at":"2025-05-11T11:33:15.000Z","dependencies_parsed_at":"2023-12-12T18:36:27.766Z","dependency_job_id":"8860d5bb-7900-49b4-ae06-d7039b526854","html_url":"https://github.com/brimdata/react-arborist","commit_stats":{"total_commits":149,"total_committers":18,"mean_commits":8.277777777777779,"dds":0.4563758389261745,"last_synced_commit":"3cee71c318c8cb1c3c490ffa977c1b6d2f0264d2"},"previous_names":[],"tags_count":45,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brimdata%2Freact-arborist","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brimdata%2Freact-arborist/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brimdata%2Freact-arborist/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brimdata%2Freact-arborist/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brimdata","download_url":"https://codeload.github.com/brimdata/react-arborist/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254101588,"owners_count":22014907,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arborist","react","tree","treeview","treeview-component"],"created_at":"2024-07-30T20:01:24.334Z","updated_at":"2025-05-14T08:05:17.248Z","avatar_url":"https://github.com/brimdata.png","language":"TypeScript","readme":"![Logo](https://user-images.githubusercontent.com/3460638/161630636-3512fe81-41c2-4ee5-8f7e-adaad07033b6.svg)\n\n\u003ch1\u003eReact Arborist\u003c/h1\u003e\n\n[See the Demos](https://react-arborist.netlify.app/)\n\nThe tree view is ubiquitous in software applications. This library provides the React ecosystem with a complete solution to build the equivalent of a VSCode sidebar, Mac Finder, Windows Explorer, or Sketch/Figma layers panel.\n\nHere is a Gmail sidebar clone built with react-arborist.\n\n\u003cimg src=\"https://user-images.githubusercontent.com/3460638/197306119-59fe59e6-50ae-4bc2-8cb9-3faa2bc52cd2.gif\" width=\"270px\" alt=\"Gmail sidebar clone built with react-arborist\" /\u003e\n\n## Features\n\n- Drag and drop sorting\n- Open/close folders\n- Inline renaming\n- Virtualized rendering\n- Custom styling\n- Keyboard navigation\n- Aria attributes\n- Tree filtering\n- Selection synchronization\n- Callbacks (onScroll, onActivate, onSelect)\n- Controlled or uncontrolled trees\n\n## Installation\n\n```\nyarn add react-arborist\n```\n\n```\nnpm install react-arborist\n```\n\n## Examples\n\nAssume our data is this:\n\n```js\nconst data = [\n  { id: \"1\", name: \"Unread\" },\n  { id: \"2\", name: \"Threads\" },\n  {\n    id: \"3\",\n    name: \"Chat Rooms\",\n    children: [\n      { id: \"c1\", name: \"General\" },\n      { id: \"c2\", name: \"Random\" },\n      { id: \"c3\", name: \"Open Source Projects\" },\n    ],\n  },\n  {\n    id: \"4\",\n    name: \"Direct Messages\",\n    children: [\n      { id: \"d1\", name: \"Alice\" },\n      { id: \"d2\", name: \"Bob\" },\n      { id: \"d3\", name: \"Charlie\" },\n    ],\n  },\n];\n```\n\n### The Simplest Tree\n\nUse all the defaults. The _initialData_ prop makes the tree an uncontrolled component. Create, move, rename, and delete will be handled internally.\n\n```jsx\nimport { Tree } from 'react-arborist';\n\nfunction App() {\n  return \u003cTree initialData={data} /\u003e;\n}\n```\n\n\u003cimg width=\"214\" alt=\"image\" src=\"https://user-images.githubusercontent.com/3460638/198098015-d7dc6400-6391-4094-9f66-0f56a99433e9.png\"\u003e\n\n[Demo](https://codesandbox.io/s/the-simplest-tree-7tbedw)\n\n### Customize the Appearance\n\nWe provide our own dimensions and our own `Node` component.\n\n```jsx\nfunction App() {\n  return (\n    \u003cTree\n      initialData={data}\n      openByDefault={false}\n      width={600}\n      height={1000}\n      indent={24}\n      rowHeight={36}\n      overscanCount={1}\n      paddingTop={30}\n      paddingBottom={10}\n      padding={25 /* sets both */}\n    \u003e\n      {Node}\n    \u003c/Tree\u003e\n  );\n}\n\nfunction Node({ node, style, dragHandle }) {\n  /* This node instance can do many things. See the API reference. */\n  return (\n    \u003cdiv style={style} ref={dragHandle}\u003e\n      {node.isLeaf ? \"🍁\" : \"🗀\"}\n      {node.data.name}\n    \u003c/div\u003e\n  );\n}\n```\n\n\u003cimg width=\"166\" alt=\"image\" src=\"https://user-images.githubusercontent.com/3460638/198100281-594a492d-2ea0-4ff0-883d-1dd79dbb5acd.png\"\u003e\n\n[Demo](https://codesandbox.io/s/customize-appearance-f4g15v?file=/src/App.tsx)\n\n### Control the Tree data\n\nHere we use the _data_ prop to make the tree a controlled component. We must handle all the data modifications ourselves using the props below.\n\n```jsx\nfunction App() {\n  /* Handle the data modifications outside the tree component */\n  const onCreate = ({ parentId, index, type }) =\u003e {};\n  const onRename = ({ id, name }) =\u003e {};\n  const onMove = ({ dragIds, parentId, index }) =\u003e {};\n  const onDelete = ({ ids }) =\u003e {};\n\n  return (\n    \u003cTree\n      data={data}\n      onCreate={onCreate}\n      onRename={onRename}\n      onMove={onMove}\n      onDelete={onDelete}\n    /\u003e\n  );\n}\n```\n\n### Tree Filtering\n\nProviding a non-empty _searchTerm_ will only show nodes that match. If a child matches, all its parents also match. Internal nodes are opened when filtering. You can provide your own _searchMatch_ function, or use the default.\n\n```jsx\nfunction App() {\n  const term = useSearchTermString()\n  \u003cTree\n    data={data}\n    searchTerm={term}\n    searchMatch={\n      (node, term) =\u003e node.data.name.toLowerCase().includes(term.toLowerCase())\n    }\n  /\u003e\n}\n```\n\n### Sync the Selection\n\nIt's common to open something elsewhere in the app, but have the tree reflect the new selection.\n\nPassing an id to the _selection_ prop will select and scroll to that node whenever that id changes.\n\n```jsx\nfunction App() {\n  const chatId = useCurrentChatId();\n\n  /* \n    Whenever the currentChatRoomId changes, \n    the tree will automatically select it and scroll to it. \n  */\n\n  return \u003cTree initialData={data} selection={chatId} /\u003e;\n}\n```\n\n### Use the Tree Api Instance\n\nYou can access the Tree Api in the parent component by giving a ref to the tree.\n\n```jsx\nfunction App() {\n  const treeRef = useRef();\n\n  useEffect(() =\u003e {\n    const tree = treeRef.current;\n    tree.selectAll();\n    /* See the Tree API reference for all you can do with it. */\n  }, []);\n\n  return \u003cTree initialData={data} ref={treeRef} /\u003e;\n}\n```\n\n### Data with Different Property Names\n\nThe _idAccessor_ and _childrenAccessor_ props allow you to specify the children and id fields in your data.\n\n```jsx\nfunction App() {\n  const data = [\n    {\n      category: \"Food\",\n      subCategories: [{ category: \"Restaurants\" }, { category: \"Groceries\" }],\n    },\n  ];\n  return (\n    \u003cTree\n      data={data}\n      /* An accessor can provide a string property name */\n      idAccessor=\"category\"\n      /* or a function with the data as the argument */\n      childrenAccessor={(d) =\u003e d.subCategories}\n    /\u003e\n  );\n}\n```\n\n### Custom Rendering\n\nRender every single piece of the tree yourself. See the API reference for the props passed to each renderer.\n\n```jsx\nfunction App() {\n  return (\n    \u003cTree\n      data={data}\n      /* The outer most element in the list */\n      renderRow={MyRow}\n      /* The \"ghost\" element that follows the mouse as you drag */\n      renderDragPreview={MyDragPreview}\n      /* The line that shows where an element will be dropped */\n      renderCursor={MyCursor}\n    \u003e\n      {/* The inner element that shows the indentation and data */}\n      {MyNode}\n    \u003c/Tree\u003e\n  );\n}\n```\n\n### Dynamic sizing\n\nYou can add a ref to it with this package [ZeeCoder/use-resize-observer](https://github.com/ZeeCoder/use-resize-observer)\n \nThat hook will return the height and width of the parent whenever it changes. You then pass these numbers to the Tree.\n\n```js\nconst { ref, width, height } = useResizeObserver();\n \n\u003cdiv className=\"parent\" ref={ref}\u003e\n  \u003cTree height={height} width={width} /\u003e\n\u003c/div\u003e\n```\n\n## API Reference\n\n- Components\n  - [Tree Component Props](#tree-component-props)\n  - [Row Component Props](#row-component-props)\n  - [Node Component Props](#node-component-props)\n  - [DragPreview Component Props](#dragpreview-component-props)\n  - [Cursor Component Props](#cursor-component-props)\n- Interfaces\n  - [Node API](#node-api-reference)\n  - [Tree API](#tree-api-reference)\n\n## Tree Component Props\n\nThese are all the props you can pass to the Tree component.\n\n```ts\ninterface TreeProps\u003cT\u003e {\n  /* Data Options */\n  data?: readonly T[];\n  initialData?: readonly T[];\n\n  /* Data Handlers */\n  onCreate?: handlers.CreateHandler\u003cT\u003e;\n  onMove?: handlers.MoveHandler\u003cT\u003e;\n  onRename?: handlers.RenameHandler\u003cT\u003e;\n  onDelete?: handlers.DeleteHandler\u003cT\u003e;\n\n  /* Renderers*/\n  children?: ElementType\u003crenderers.NodeRendererProps\u003cT\u003e\u003e;\n  renderRow?: ElementType\u003crenderers.RowRendererProps\u003cT\u003e\u003e;\n  renderDragPreview?: ElementType\u003crenderers.DragPreviewProps\u003e;\n  renderCursor?: ElementType\u003crenderers.CursorProps\u003e;\n  renderContainer?: ElementType\u003c{}\u003e;\n\n  /* Sizes */\n  rowHeight?: number;\n  overscanCount?: number;\n  width?: number | string;\n  height?: number;\n  indent?: number;\n  paddingTop?: number;\n  paddingBottom?: number;\n  padding?: number;\n\n  /* Config */\n  childrenAccessor?: string | ((d: T) =\u003e T[] | null);\n  idAccessor?: string | ((d: T) =\u003e string);\n  openByDefault?: boolean;\n  selectionFollowsFocus?: boolean;\n  disableMultiSelection?: boolean;\n  disableEdit?: string | boolean | BoolFunc\u003cT\u003e;\n  disableDrag?: string | boolean | BoolFunc\u003cT\u003e;\n  disableDrop?:\n    | string\n    | boolean\n    | ((args: {\n        parentNode: NodeApi\u003cT\u003e;\n        dragNodes: NodeApi\u003cT\u003e[];\n        index: number;\n      }) =\u003e boolean);\n\n  /* Event Handlers */\n  onActivate?: (node: NodeApi\u003cT\u003e) =\u003e void;\n  onSelect?: (nodes: NodeApi\u003cT\u003e[]) =\u003e void;\n  onScroll?: (props: ListOnScrollProps) =\u003e void;\n  onToggle?: (id: string) =\u003e void;\n  onFocus?: (node: NodeApi\u003cT\u003e) =\u003e void;\n\n  /* Selection */\n  selection?: string;\n\n  /* Open State */\n  initialOpenState?: OpenMap;\n\n  /* Search */\n  searchTerm?: string;\n  searchMatch?: (node: NodeApi\u003cT\u003e, searchTerm: string) =\u003e boolean;\n\n  /* Extra */\n  className?: string | undefined;\n  rowClassName?: string | undefined;\n\n  dndRootElement?: globalThis.Node | null;\n  onClick?: MouseEventHandler;\n  onContextMenu?: MouseEventHandler;\n  dndManager?: DragDropManager;\n}\n```\n\n## Row Component Props\n\nThe _\\\u003cRowRenderer\\\u003e_ is responsible for attaching the drop ref, the row style (top, height) and the aria-attributes. The default should work fine for most use cases, but it can be replaced by your own component if you need. See the _renderRow_ prop in the _\\\u003cTree\\\u003e_ component.\n\n```ts\ntype RowRendererProps\u003cT\u003e = {\n  node: NodeApi\u003cT\u003e;\n  innerRef: (el: HTMLDivElement | null) =\u003e void;\n  attrs: HTMLAttributes\u003cany\u003e;\n  children: ReactElement;\n};\n```\n\n## Node Component Props\n\nThe _\\\u003cNodeRenderer\\\u003e_ is responsible for attaching the drag ref, the node style (padding for indentation), the visual look of the node, the edit input of the node, and anything else you can dream up.\n\nThere is a default renderer, but it's only there as a placeholder to get started. You'll want to create your own component for this. It is passed as the _\\\u003cTree\\\u003e_ components only child.\n\n```ts\nexport type NodeRendererProps\u003cT\u003e = {\n  style: CSSProperties;\n  node: NodeApi\u003cT\u003e;\n  tree: TreeApi\u003cT\u003e;\n  dragHandle?: (el: HTMLDivElement | null) =\u003e void;\n  preview?: boolean;\n};\n```\n\n## DragPreview Component Props\n\nThe _\\\u003cDragPreview\\\u003e_ is responsible for showing a \"ghost\" version of the node being dragged. The default is a semi-transparent version of the NodeRenderer and should work fine for most people. To customize it, pass your new component to the _renderDragPreview_ prop.\n\n```ts\ntype DragPreviewProps = {\n  offset: XYCoord | null;\n  mouse: XYCoord | null;\n  id: string | null;\n  dragIds: string[];\n  isDragging: boolean;\n};\n```\n\n## Cursor Component Props\n\nThe _\\\u003cCursor\\\u003e_ is responsible for showing a line that indicates where the node will move to when it's dropped. The default is a blue line with circle on the left side. You may want to customize this. Pass your own component to the _renderCursor_ prop.\n\n```ts\nexport type CursorProps = {\n  top: number;\n  left: number;\n  indent: number;\n};\n```\n\n## Node API Reference\n\n### State Properties\n\nAll these properties on the node instance return booleans related to the state of the node.\n\n_node_.**isRoot**\n\nReturns true if this is the root node. The root node is added internally by react-arborist and not shown in the UI.\n\n_node_.**isLeaf**\n\nReturns true if the children property is not an array.\n\n_node_.**isInternal**\n\nReturns true if the children property is an array.\n\n_node_.**isOpen**\n\nReturns true if node is internal and in an open state.\n\n_node_.**isEditing**\n\nReturns true if this node is currently being edited. Use this property in the NodeRenderer to render the rename form.\n\n_node_.**isSelected**\n\nReturns true if node is selected.\n\n_node_.**isSelectedStart**\n\nReturns true if node is the first of a contiguous group of selected nodes. Useful for styling.\n\n_node_.**isSelectedEnd**\n\nReturns true if node is the last of a contiguous group of selected nodes. Useful for styling.\n\n_node_.**isOnlySelection**\n\nReturns true if node is the only node selected in the tree.\n\n_node_.**isFocused**\n\nReturns true if node is focused.\n\n_node_.**isDragging**\n\nReturns true if node is being dragged.\n\n_node_.**willReceiveDrop**\n\nReturns true if node is internal and the user is hovering a dragged node over it.\n\n_node_.**state**\n\nReturns 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).\n\n```ts\ntype NodeState = {\n  isEditing: boolean;\n  isDragging: boolean;\n  isSelected: boolean;\n  isSelectedStart: boolean;\n  isSelectedEnd: boolean;\n  isFocused: boolean;\n  isOpen: boolean;\n  isClosed: boolean;\n  isLeaf: boolean;\n  isInternal: boolean;\n  willReceiveDrop: boolean;\n};\n```\n\n### Accessors\n\n_node_.**childIndex**\n\nReturns the node's index in relation to its siblings.\n\n_node_.**next**\n\nReturns the next visible node. The node directly under this node in the tree component. Returns null if none exist.\n\n_node_.**prev**\n\nReturns the previous visible node. The node directly above this node in the tree component. Returns null if none exist.\n\n_node_.**nextSibling**\n\nReturns the next sibling in the data of this node. Returns null if none exist.\n\n### Selection Methods\n\n_node_.**select**()\n\nSelect only this node.\n\n_node_.**deselect**()\n\nDeselect this node. Other nodes may still be selected.\n\n_node_.**selectMulti**()\n\nSelect this node while maintaining all other selections.\n\n_node_.**selectContiguous**()\n\nDeselect 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()_.\n\n### Activation Methods\n\n_node_.**activate**()\n\nRuns the Tree props' onActivate callback passing in this node.\n\n_node_.**focus**()\n\nFocus this node.\n\n### Open/Close Methods\n\n_node_.**open**()\n\nOpens the node if it is an internal node.\n\n_node_.**close**()\n\nCloses the node if it is an internal node.\n\n_node_.**toggle**()\n\nToggles the open/closed state of the node if it is an internal node.\n\n_node_.**openParents**()\n\nOpens all the parents of this node.\n\n_node_.**edit**()\n\nMoves this node into the editing state. Calling node._isEditing_ will return true.\n\n_node_.**submit**(_newName_)\n\nSubmits _newName_ string to the _onRename_ handler. Moves this node out of the editing state.\n\n_node_.**reset**()\n\nMoves this node out of the editing state without submitting a new name.\n\n### Event Handlers\n\n_node_.**handleClick**(_event_)\n\nUseful 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()_.\n\n## Tree API Reference\n\nThe tree api reference is stable across re-renders. It always has the most recent state and props.\n\n### Node Accessors\n\n_tree_.**get**(_id_) : _NodeApi | null_\n\nGet node by id from the _visibleNodes_ array.\n\n_tree_.**at**(_index_) : _NodeApi | null_\n\nGet node by index from the _visibleNodes_ array.\n\n_tree_.**visibleNodes** : _NodeApi[]_\n\nReturns an array of the visible nodes.\n\n_tree_.**firstNode** : _NodeApi | null_\n\nThe first node in the _visibleNodes_ array.\n\n_tree_.**lastNode** : _NodeApi | null_\n\nThe last node in the _visibleNodes_ array.\n\n_tree_.**focusedNode** : _NodeApi | null_\n\nThe currently focused node.\n\n_tree_.**mostRecentNode** : _NodeApi | null_\n\nThe most recently selected node.\n\n_tree_.**nextNode** : _NodeApi | null_\n\nThe node directly after the _focusedNode_ in the _visibleNodes_ array.\n\n_tree_.**prevNode** : _NodeApi | null_\n\nThe node directly before the _focusedNode_ in the _visibleNodes_ array.\n\n### Focus Methods\n\n_tree_.**hasFocus** : _boolean_\n\nReturns true if the the tree has focus somewhere within it.\n\n_tree_.**focus**(_id_)\n\nFocus on the node with _id_.\n\n_tree_.**isFocused**(_id_) : _boolean_\n\nCheck if the node with _id_ is focused.\n\n_tree_.**pageUp**()\n\nMove focus up one page.\n\n_tree_.**pageDown**()\n\nMove focus down one page.\n\n### Selection Methods\n\n_tree_.**selectedIds** : _Set\\\u003cstring\\\u003e_\n\nReturns a set of ids that are selected.\n\n_tree_.**selectedNodes** : _NodeApi[]_\n\nReturns an array of nodes that are selected.\n\n_tree_.**hasNoSelection** : boolean\n\nReturns true if nothing is selected in the tree.\n\n_tree_.**hasSingleSelection** : boolean\n\nReturns true if there is only one selection.\n\n_tree_.**hasMultipleSelections** : boolean\n\nReturns true if there is more than one selection.\n\n_tree_.**isSelected**(_id_) : _boolean_\n\nReturns true if the node with _id_ is selected.\n\n_tree_.**select**(_id_)\n\nSelect only the node with _id_.\n\n_tree_.**deselect**(_id_)\n\nDeselect the node with _id_.\n\n_tree_.**selectMulti**(_id_)\n\nAdd to the selection the node with _id_.\n\n_tree_.**selectContiguous**(_id_)\n\nDeselected nodes between the anchor and the last selected node, then select the nodes between the anchor and the node with _id_.\n\n_tree_.**deselectAll**()\n\nDeselect all nodes.\n\n_tree_.**selectAll**()\n\nSelect all nodes.\n\n### Visibility\n\n_tree_.**open**(_id_)\n\nOpen the node with _id_.\n\n_tree_.**close**(_id_)\n\nClose the node with _id_.\n\n_tree_.**toggle**(_id_)\n\nToggle the open state of the node with _id_.\n\n_tree_.**openParents**(_id_)\n\nOpen all parents of the node with _id_.\n\n_tree_.**openSiblings**(_id_)\n\nOpen all siblings of the node with _id_.\n\n_tree_.**openAll**()\n\nOpen all internal nodes.\n\n_tree_.**closeAll**()\n\nClose all internal nodes.\n\n_tree_.**isOpen**(_id_) : _boolean_\n\nReturns true if the node with _id_ is open.\n\n### Drag and Drop\n\n_tree_.**isDragging**(_id_) : _boolean_\n\nReturns true if the node with _id_ is being dragged.\n\n_tree_.**willReceiveDrop**(_id_) : _boolean_\n\nReturns true if the node with _id_ is internal and is under the dragged node.\n\n### Scrolling\n\n_tree_.**scrollTo**(_id_, _[align]_)\n\nScroll to the node with _id_. If this node is not visible, this method will open all its parents. The align argument can be _\"auto\" | \"smart\" | \"center\" | \"end\" | \"start\"_.\n\n### Properties\n\n_tree_.**isEditing** : _boolean_\n\nReturns true if the tree is editing a node.\n\n_tree_.**isFiltered** : _boolean_\n\nReturns true if the _searchTerm_ prop is not an empty string when trimmed.\n\n_tree_.**props** : _TreeProps_\n\nReturns all the props that were passed to the _\\\u003cTree\\\u003e_ component.\n\n_tree_.**root** : _NodeApi_\n\nReturns the root _NodeApi_ instance. Its children are the Node representations of the _data_ prop array.\n\n## Author\n\n[James Kerr](https://twitter.com/specialCaseDev) at [Brim Data](https://brimdata.io) for the [Zui desktop app](https://www.youtube.com/watch?v=I2y663n8d2A).\n","funding_links":[],"categories":["TypeScript","UI Components"],"sub_categories":["Tree"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrimdata%2Freact-arborist","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrimdata%2Freact-arborist","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrimdata%2Freact-arborist/lists"}