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 🙏

© 2024 – Pkg Stats / Ryan Hefner

dnd-kit-sortable-tree

v0.1.73

Published

[![npm version](https://badge.fury.io/js/dnd-kit-sortable-tree.svg)](https://www.npmjs.org/package/dnd-kit-sortable-tree) [![npm](https://img.shields.io/npm/dt/dnd-kit-sortable-tree.svg)](https://www.npmjs.org/package/dnd-kit-sortable-tree) [![MIT](https:

Downloads

32,851

Readme

dnd-kit-sortable-tree

npm version npm MIT

This is a Tree component extracted from dndkit examples and abstracted a bit. Here's how it could look like (visuals are completely customizable via css though) img.png

Play around in examples to check the API and see what it can do.

Install

npm install dnd-kit-sortable-tree @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities

How-to use

Check out the Storybook for code samples and play around. You could also play with it on playcode

Shortly, you need to render:

<SortableTree
  items={/* array of your tree items */}
  onItemsChanged={/* callback when items are reordered */}
  TreeItemComponent={/* component that renders a single tree item */}
/>

And TreeItemComponent is usually your data wrapped in SimpleTreeItemWrapper or FolderTreeItemWrapper:

React.forwardRef((props, ref) => (
  <SimpleTreeItemWrapper {...props} ref={ref}>
    <div>{props.item.value}</div>
  </SimpleTreeItemWrapper>
));

Note that wrapping in forwardRef and passing ref to SimpleTreeItemWrapper is very important!

Examples

  1. Here's the very minimal code to add a Sortable Tree. You shouldn't use it as is in your project, but it could be easier to grasp what's going on.

    export const Minimal = () => {
      const [items, setItems] = useState(initialMinimalData);
      return (
        <SortableTree
          items={items}
          onItemsChanged={setItems}
          {
            /*
             * You need to pass the component rendering a single item via TreeItemComponent props.
             * This component will receive the data via `props.item`.
             * In this example we inline the component, but in reality you should extract it into a const.
             */ ...{}
          }
          TreeItemComponent={React.forwardRef((props, ref) => (
            <SimpleTreeItemWrapper {...props} ref={ref}>
              {/* HERE GOES THE ACTUAL CONTENT OF YOUR COMPONENT */}
              <div>{props.item.id}</div>
            </SimpleTreeItemWrapper>
          ))}
        />
      );
    };
    /*
     * Configure the tree data.
     */
    const initialMinimalData = [
      { id: '1', children: [{ id: '4' }, { id: '5' }] },
      { id: '2' },
      { id: '3' },
    ];
  2. Here's the minimal viable example that you could potentially copy&paste to your project to start from.

    export const MinimalViable = () => {
      const [items, setItems] = useState(initialViableMinimalData);
      return (
        <SortableTree
          items={items}
          onItemsChanged={setItems}
          TreeItemComponent={MinimalTreeItemComponent}
        />
      );
    };
    type MinimalTreeItemData = {
      value: string;
    };
    /*
     * Here's the component that will render a single row of your tree
     */
    const MinimalTreeItemComponent = React.forwardRef<
      HTMLDivElement,
      TreeItemComponentProps<MinimalTreeItemData>
    >((props, ref) => (
      /* you could also use FolderTreeItemWrapper if you want to show vertical lines.  */
      <SimpleTreeItemWrapper {...props} ref={ref}>
        <div>{props.item.value}</div>
      </SimpleTreeItemWrapper>
    ));
    
    /*
     * Configure the tree data.
     */
    const initialViableMinimalData: TreeItems<MinimalTreeItemData> = [
      {
        id: '1',
        value: 'Jane',
        children: [
          { id: '4', value: 'John' },
          { id: '5', value: 'Sally' },
        ],
      },
      { id: '2', value: 'Fred', children: [{ id: '6', value: 'Eugene' }] },
      { id: '3', value: 'Helen', canHaveChildren: false },
    ];

API

Data configuration (each TreeItem element could define them):

  • canHaveChildren - Default: true.

    If set to false, prevents any node from being dragged into the current one.

    Also accepts a function: (dragItem) => bool which could conditionally determine if a certain item could be a children of a node

  • disableSorting - Default: false. If set to true, prevents node from being dragged (i.e. it can't be sorted or moved to another node)

Tree configuration (props of <SortableTree>)

  • items - mandatory, items shown in a tree

  • onItemsChanged - mandatory, callback that is called when dragging of certain item is finished. You should preserve new state and adjust the value of items prop as needed.

  • TreeItemComponent - mandatory, component that renders a single tree row.

  • indentationWidth - optional, padding used for children

  • pointerSensorOptions - optional, configures the condition when item dragging starts. Defaults to:

    {
      "activationConstraint": {
        "distance": 3
      }
    }
  • disableSorting - optional, you could set this to true to completely disable the sorting

  • keepGhostInPlace - optional, you could set this to true to keep the Node that you are dragging in it's original place in a Tree. Check VSCode sample to see it in action.

  • dndContextProps - optional, override any prop of underlying DndContext.

  • sortableProps - optional, override any prop that is passed to underlying useSortable hook.

TreeItemWrapper configuration (props of <SimpleTreeItemWrapper> and <FolderTreeItemWrapper>)

  • manualDrag - Default: false. Set to true if you want tree item to be draggable ONLY from dragHandle.
  • showDragHandle - optional, set to false if you want to hide default dragHandle and show your own instead. Use <div {...props.handleProps}>DRAG_ME</div> for your own drag handle.

FAQ

  1. If you want to disable animation completely, you need to do the following:
    1. Pass null as dropAnimation prop (this disables the actual 'drop' animation for the Node that was dragged).
    2. Pass { animateLayoutChanges: () => false } to sortableProps (this disables the animation of all other nodes that were not dragged)

Troubleshooting

  1. If your dragged item is shown at the end of a list, make sure you that:
    1. You wrapped your TreeItem component in React.forwardRef and passing the ref to SimpleTreeItemWrapper
    2. You pass the styles prop from TreeItem to SimpleTreeItemWrapper