npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@edux-design/tree-select

v0.2.1

Published

TreeSelect renders hierarchical data with expand/collapse controls, optional inline editing, optional add-item actions, and drag-and-drop reordering. The component is controlled: you own the tree data and receive updates via callbacks.

Readme

@edux-design/tree-select

TreeSelect renders hierarchical data with expand/collapse controls, optional inline editing, optional add-item actions, and drag-and-drop reordering. The component is controlled: you own the tree data and receive updates via callbacks.


Installation

pnpm add @edux-design/tree-select @edux-design/forms @edux-design/buttons @edux-design/icons @edux-design/tooltips @dnd-kit/core @dnd-kit/sortable
# or
npm install @edux-design/tree-select @edux-design/forms @edux-design/buttons @edux-design/icons @edux-design/tooltips @dnd-kit/core @dnd-kit/sortable

Peer deps include react@^19.1.0 and react-dom@^19.1.0.


Data shape

Each node must have a stable id. Children are optional.

const data = [
  {
    id: "docs",
    label: "Documentation",
    children: [
      { id: "intro", label: "Introduction" },
      { id: "install", label: "Installation" },
    ],
  },
];
  • id is required and must be unique within the tree.
  • label is displayed; when missing the id is used.
  • children is an array of child nodes.

Usage

Basic

import { TreeSelect } from "@edux-design/tree-select";

export function Example() {
  return <TreeSelect data={data} />;
}

Drag and drop

export function DragExample() {
  const [tree, setTree] = useState(data);

  return (
    <TreeSelect
      data={tree}
      allowDragAndDrop
      onDataChange={setTree}
    />
  );
}

Multi-select drag

export function MultiDragExample() {
  const [tree, setTree] = useState(data);

  return (
    <TreeSelect
      data={tree}
      allowDragAndDrop
      allowMultiDrag
      onDataChange={setTree}
    />
  );
}
  • Hold CMD (Mac) or CTRL (Windows) to select multiple adjacent siblings.
  • Hold SHIFT to select a range of adjacent siblings.
  • Multi-select only works within the same sibling group and must stay contiguous.

Editable labels and add actions

export function EditableExample() {
  const [tree, setTree] = useState(data);

  return (
    <TreeSelect
      data={tree}
      isEditable
      maxDepth={3}
      addChildTooltip="Add a child item"
      addSiblingTooltip="Add a sibling item"
      onDataChange={setTree}
    />
  );
}

Chevron toggle

export function ChevronExample() {
  return <TreeSelect data={data} useChevron />;
}

Props

data (array, required)

Tree data to render. This component is controlled; updates are emitted through onDataChange.

onDataChange (function)

Called with the updated tree when edits, add actions, or drag-and-drop reordering occur.

onLabelChange (function)

Called with (id, nextLabel) when a label edit is committed. When provided, label edits do not emit onDataChange.

allowDragAndDrop (boolean, default false)

Enables drag-and-drop. When false, drag handles are hidden and items cannot be reordered.

allowMultiDrag (boolean, default false)

Allows multi-select drag using CMD/CTRL or SHIFT. Selection is restricted to adjacent siblings.

isEditable (boolean, default false)

Enables inline label editing and add-item controls.

allowDelete (boolean, default false)

Shows a delete action for each item and removes the node (plus descendants).

actionButtonsPosition ("start" | "end", default "start")

Positions the action buttons within a row. "end" pushes the actions to the end of the row.

maxLabelLength (number)

Limits label width by character count and truncates with an ellipsis when exceeded.

useChevron (boolean, default false)

Uses a chevron control for expand/collapse instead of the checkbox toggle.

defaultExpanded ("all" | number | string[] | Set<string | number>)

Defines the initial expansion state. Use "all" to expand every node with children, a number to expand up to that level (1 expands top-level nodes), or an array/set of ids to expand specific items.

expanded ("all" | number | string[] | Set<string | number>)

Controlled expansion state. When provided, the tree expansion is driven by this value.

onExpandedChange (function)

Called with a Set of expanded ids when the user toggles expansion in controlled mode.

maxDepth (number)

Limits how deep new items can be added. For example, maxDepth={3} allows at most 3 levels.

addChildTooltip (string)

Tooltip copy for the add-child button.

addSiblingTooltip (string)

Tooltip copy for the add-sibling button.

deleteTooltip (string)

Tooltip copy for the delete button.

levelConfig (object)

Per-level configuration for editing, actions, and tooltips. Use default for global settings and levels to override by depth. Values in levelConfig override isEditable, allowDelete, and tooltip props for the matching depth.

levelConfig={{
  default: {
    editable: true,
    actions: { addChild: true, addSibling: true, delete: false },
    tooltips: {
      addChild: "Add child",
      addSibling: "Add sibling",
      delete: "Delete item",
    },
  },
  levels: {
    0: {
      editable: false,
      tooltips: { addChild: "Add chapter" },
    },
  },
}}

Behaviour details

  • Nodes with children render an expand/collapse control.
  • Leaf nodes do not render a checkbox/chevron toggle.
  • Expansion only controls visibility of children.
  • When useChevron is false, the toggle uses the Checkbox plus/indeterminate states.
  • defaultExpanded only seeds the initial state; use expanded for controlled expansion.
  • When expanded is provided, onExpandedChange is called with the next set of expanded ids.
  • Deleting a node removes the entire subtree and clears any selected/expanded state for those ids.
  • levelConfig can override editability, actions, and tooltips per depth.
  • Drag-and-drop supports reordering within a level and moving items between levels.
  • Drag handle alignment is set so child handles align under the parent toggle.

Development

pnpm --filter @edux-design/tree-select lint
pnpm --filter @edux-design/tree-select check-types
pnpm --filter @edux-design/tree-select build

Storybook examples live in src/demos/TreeSelect.stories.jsx.