react-nestable

repository·master·Indexed 42 days ago

https://github.com/primetwig/react-nestable

A React component for creating draggable, nestable hierarchical lists. Version 3.0.2 allows users to reorder items and change nesting depth through drag-and-drop interactions, featuring customizable item rendering via `renderItem`, programmatic collapse control, and configurable nesting depth.

Tokens
4K
Snippets
11
Records
17
Agent score
51%

What's inside react-nestable

  1. Configure Nestable component options

    master

    The Nestable component accepts several props to control its behavior, data structure, and rendering.

    Data and Structure

    • items (array): The array of items to render. Each item must have a unique ID.
    • idProp (string): The name of the property used for the unique ID (default: "id").
    • childrenProp (string): The name of the property used for children (default: "children").
    • maxDepth (number): Maximum allowed nesting level (default: 10).
    • group (string | number): A unique identifier for the nestable instance, useful for styling portal instances when multiple components exist on one page.

    Drag and Drop Behavior

    • disableDrag (boolean | function): Disables dragging. If a function is passed, it receives { item, index, depth } to determine if a specific item can be dragged.
    • confirmChange (function): A callback (dragItem, destinationParent) => boolean. Return false to cancel a move. destinationParent is null if moving to the root.
    • threshold (number): Horizontal pixel movement required to change nesting level (default: 30).
    • onDragStart (function): Triggered when dragging starts. Receives { dragItem }.
    • onDragEnd (function): Triggered when dragging ends (via drop or cancel).

    Rendering and UI

    • renderItem (function): The primary way to render items. Receives { item, index, depth, collapseIcon, handler, isDraggable }.
    • renderCollapseIcon (function): Customizes the collapse icon. Receives { isCollapsed, item }.
    • handler (node): A node that will be wrapped with drag handlers and passed to renderItem via the handler key.
    • className (string): Extra class name for the root element.
    • collapsed (boolean): If true, groups are collapsed by default.
    • disableCollapse (boolean): Disables the ability to toggle collapsed states.

    Callbacks

    • onChange (function): Triggered when an item's position changes. Receives { items, dragItem, targetPath }. targetPath is an array of indices representing the path to the new location.
    • onCollapseChange (function): Triggered when items are opened/closed. Receives { openIds } (if collapsed is true) or { closedIds } (if collapsed is false).
  2. Basic usage of the Nestable component

    master

    To use react-nestable, import the Nestable component and its required CSS. Every item in your items array must have a unique id property to allow the component to distinguish between elements. You must provide a renderItem function to define how each item is displayed.

    import Nestable from 'react-nestable';
    import 'react-nestable/dist/styles/index.css';
    
    // Every item must have a unique `id`
    const items = [
      { id: 0, text: 'Andy' },
      {
        id: 1, text: 'Harry',
        children: [
          { id: 2, text: 'David' }
        ]
      },
      { id: 3, text: 'Lisa' }
    ];
    
    const renderItem = ({ item }) => item.text;
    
    const Example = () => (
      <Nestable
        items={items}
        renderItem={renderItem}
      />
    );
    import Nestable from 'react-nestable';
    
    // this usually goes once
    // to the entry point of the whole app
    // (e.g. src/index.js)
    import 'react-nestable/dist/styles/index.css';
    
    // every item must have a unique `id`
    // in order to distinguish elements
    const items = [
      { id: 0, text: 'Andy' },
      {
        id: 1, text: 'Harry',
        children: [
          { id: 2, text: 'David' }
        ]
      },
      { id: 3, text: 'Lisa' }
    ];
    
    const renderItem = ({ item }) => item.text;
    
    const Example = () => (
      <Nestable
        items={items}
        renderItem={renderItem}
      />
    );
  3. Use Nestable public methods

    master

    The Nestable component provides a collapse method to programmatically control the expansion state of groups.

    • collapse("NONE"): Expands all groups.
    • collapse("ALL"): Collapses all groups.
    • collapse(array): Collapses specific groups by passing an array of their IDs.
  4. Configure the Nestable component props

    master

    The Nestable component accepts several props to control its behavior, data structure, and event handling.

    Key configuration options include:

    • items: The array of data representing the tree structure.
    • idProp: The property name used to uniquely identify each item (defaults to 'id').
    • childrenProp: The property name used to hold the array of child items (defaults to 'children').
    • maxDepth: The maximum allowed nesting depth (defaults to 10).
    • group: A string used to namespace the component's CSS classes, useful when multiple nestables exist on one page (defaults to a random string).
    • confirmChange: A callback function (args: { dragItem: Item, destinationParent: Item | null }) => boolean that allows you to intercept and validate a move before it is applied. Return false to cancel the move.
    • onChange: A callback triggered when a drag operation is successfully completed. It returns { items: Item[], dragItem: Item, targetPath: number[] }.
  5. Configure drag and collapse behavior in NestableItem

    master

    The NestableItem behavior is controlled via the options object. Key properties for controlling interaction include:

    • disableDrag: A function (args: { item: Item, index: number, depth: number }) => boolean that returns true to prevent dragging, or a boolean value. If it is a function, it allows for conditional drag disabling based on item properties.
    • disableCollapse: A boolean that, when true, prevents the user from toggling the visibility of an item's children.
    • onToggleCollapse: A callback function (item: Item) => void triggered when the collapse icon is clicked.
    • onMouseEnter: A callback (e: MouseEvent, item: Item) => void triggered when hovering over a dragging item.
    • onDragStart: A callback (e: MouseEvent, item: Item) => void triggered when a drag operation begins.
    • renderCollapseIcon: A function ({ isCollapsed: boolean, item: Item }) => React.ReactNode to customize the appearance of the collapse/expand icon.
  6. Intercept changes with ConfirmChange

    master

    The confirmChange prop allows you to validate a drag operation before it is applied to the state. It receives:

    • dragItem: The Item being moved.
    • destinationParent: The Item that the dragItem is being dropped into (or null if dropped at the root).

    Return true to accept the change, or false to cancel it.

    import { NestableProps } from 'react-nestable';
    
    const confirmChange: NestableProps['confirmChange'] = ({ dragItem, destinationParent }) => {
      if (destinationParent?.type === 'restricted') {
        return false;
      }
      return true;
    };
  7. Import the Nestable component

    master

    The Nestable component is the primary entry point for the library. It is exported as the default export from the package. Use it to render a nestable tree structure by providing the required data and configuration props.

    import Nestable from 'react-nestable';
    
    // Use <Nestable /> in your component tree
  8. Implement conditional drag disabling with DisableDragFn

    master

    To prevent specific items from being dragged, pass a function to the disableDrag prop. The function receives:

    • item: The Item being evaluated.
    • index: The index of the item.
    • depth: The depth of the item.

    Return true to disable dragging for that item.

    import { NestableProps, DisableDragFn } from 'react-nestable';
    
    const disableDrag: DisableDragFn = ({ item, index, depth }) => {
      // Disable dragging if the item is at the root level or has a specific property
      return depth === 0 || item.isLocked;
    };
    
    // Usage in component
    // <Nestable disableDrag={disableDrag} ... />
  9. Collapse or expand items using the collapse() method

    master

    The Nestable component exposes a public collapse method that can be called via a React ref. This method allows you to programmatically control which items are collapsed.

    Arguments for collapse(itemIds):

    • 'NONE': Collapses all items if they were previously expanded, or expands all if they were collapsed.
    • 'ALL': Toggles the collapse state of the entire tree.
    • Array<id>: A specific list of item IDs to toggle. The behavior depends on the current collapsed prop state: it will filter the list so that the provided IDs match the desired state (either being in the collapsedItems list or not).
    // Example usage via ref
    // <Nestable ref={nestableRef} ... />
    
    // Collapse all items
    nestableRef.current.collapse('ALL');
    
    // Collapse specific items
    nestableRef.current.collapse(['item-1', 'item-2']);
    
    // Expand everything
    nestableRef.current.collapse('NONE');
  10. Configure the Nestable component with NestableProps

    master

    The NestableProps interface defines the configuration for the main component. Key props include:

    • items: An array of Item objects representing the tree structure.
    • childrenProp: The key in your Item objects that contains the array of child items.
    • idProp: The key in your Item objects used to uniquely identify the item.
    • onChange: Callback triggered when the tree structure changes.
    • onDragStart / onDragEnd: Callbacks for drag lifecycle events.
    • renderItem: A function to customize how each item is rendered.
    • renderCollapseIcon: A function to customize the collapse/expand icon.
    • disableDrag: Can be a boolean or a function DisableDragFn to conditionally disable dragging for specific items.
    • confirmChange: A function ConfirmChange used to intercept and allow/deny a drag operation.
    import { NestableProps } from 'react-nestable';
    
    const props: NestableProps = {
      items: myItems,
      childrenProp: 'children',
      idProp: 'id',
      onChange: ({ items, dragItem, targetPath }) => {
        console.log('New items:', items);
      },
      renderItem: ({ item, index, depth, isDraggable, collapseIcon, handler }) => (
        <div>
          {handler}
          {collapseIcon}
          <span>{item.name}</span>
        </div>
      )
    };