1.0.5 • Published 5 months ago

react-reorderable-list-fork v1.0.5

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

react-reorderable-list 📄

A simple UI framework friendly reorderable list component for React.

NPM JavaScript Style Guide Build Status Bundlephobia

Install

npm

npm install react-reorderable-list

yarn

yarn add react-reorderable-list

Features

  • Supports major browsers.
  • Can transfer items from one list to another.
  • Mobile and desktop devices supported.
  • Horizontal or vertical oriented lists supported. (Even grids)
  • UI framework friendly.
  • Control over what the dragged item looks like.
  • Customizable shadows when items are hovered on a list.

Examples

You can head over to our demo page to view usage with UI frameworks.

Supported Use Cases

There are 2 types of lists available for use. You can use an ungrouped list if you don't want to transfer items between lists or you can use a grouped list which gives you the ability to transfer data from one list to another by dragging and dropping the list item.

Below are supported use case scenarios for grouped and ungrouped lists.

Wrapped reorderable list group (Basic Usage)

A group of lists wrapped within a ReOrderableListGroup. Lists within the group can transfer data to each other. Provides less setup and a cleaner configuration for generic grouped lists.

Example

import React, { useState } from 'react'
import {
  ReOrderableItem,
  ReOrderableList,
  ReOrderableListGroup
} from 'react-reorderable-list'
import 'react-reorderable-list/dist/index.css'

export default function () {
  //sample data
  const [group, setGroup] = useState([
    [
      { id: 1, name: 'Test' },
      { id: 2, name: 'Hello' },
      { id: 3, name: 'World!' }
    ],
    [
      { id: 1, name: 'Item' },
      { id: 2, name: 'Name' }
    ]
  ])

  return (
    <div style={{ display: 'flex', gap: '20px' }}>
      <ReOrderableListGroup
        //The name for this group must be unique as this serves as the identifier
        //when validating if the item should be transfered to the list or not.
        //Items can only be transferred to the list with the same group name.
        name='uniqueGroupName'
        //group data
        group={group}
        //update list group
        onListGroupUpdate={(newList) => setGroup(newList)}
      >
        {group.map((list, index) => (
          <ReOrderableList key={`list-${index}`} style={{ width: '300px' }}>
            {list.map((data, index) => (
              <ReOrderableItem key={`item-${index}`}>
                <div style={{ border: '1px solid black' }}>{data.name}</div>
              </ReOrderableItem>
            ))}
          </ReOrderableList>
        ))}
      </ReOrderableListGroup>
    </div>
  )
}

Using the path property to access your list array.

import React, { useState } from 'react'
import {
  ReOrderableItem,
  ReOrderableList,
  ReOrderableListGroup
} from 'react-reorderable-list'
import 'react-reorderable-list/dist/index.css'

export default function () {
  //sample data
  const [groups, setGroup] = useState([
    {
      id: 1,
      name: 'test',
      tasks: [
        { id: 1, name: 'Test' },
        { id: 2, name: 'Hello' },
        { id: 3, name: 'World!' }
      ]
    },
    {
      id: 2,
      name: 'test2',
      tasks: [
        { id: 1, name: 'Item' },
        { id: 2, name: 'Name' }
      ]
    }
  ])

  return (
    <div style={{ display: 'flex', gap: '20px' }}>
      <ReOrderableListGroup
        //The name for this group must be unique as this serves as the identifier
        //when validating if the item should be transfered to the list or not.
        //Items can only be transferred to the list with the same group name.
        name='uniqueGroupName'
        //group data
        group={groups}
        //update list group
        onListGroupUpdate={(newList) => setGroup(newList)}
      >
        {groups.map((list, index) => (
          //here we use the path property to access the list array from the object
          <ReOrderableList
            key={`list-${index}`}
            path={`${index}.tasks`}
            style={{ width: '300px' }}
          >
            {list.tasks.map((data, index) => (
              <ReOrderableItem key={`item-${index}`}>
                <div style={{ border: '1px solid black' }}>{data.name}</div>
              </ReOrderableItem>
            ))}
          </ReOrderableList>
        ))}
      </ReOrderableListGroup>
    </div>
  )
}

Unwrapped reorderable list group

A group of lists not bound within a ReOrderableListGroup component. Useful for use cases where you need to put multiple reorderable lists into different components while still making them interactable with each other. A state management system such as Redux is required for managing app states for such scenarios.

import React, { useState } from 'react'
import { ReOrderableItem, ReOrderableList } from 'react-reorderable-list'
import 'react-reorderable-list/dist/index.css'

export default function () {
  //sample data
  const [group, setGroup] = useState([
    [
      { id: 1, name: 'Ayy ' },
      { id: 2, name: 'This ' },
      { id: 3, name: 'One' },
      { id: 4, name: 'Is' }
    ],
    [
      { id: 1, name: 'An example of' },
      { id: 2, name: 'A non wrapped' },
      { id: 3, name: 'list group' }
    ]
  ])

  return (
    <div style={{ display: 'flex', gap: '20px' }}>
      <ReOrderableList
        //The name for this group must be unique as this serves as the identifier
        //when validating if the item should be transfered to the list or not.
        //Items can only be transferred to the list with the same group name.
        name='list3'
        //group data
        group={group}
        //The object path that tells our component where to access the actual array for our list.
        //For lists not embedded within an object simply use the index for our list.
        //The path below retrieves the 1st list from our group.
        path={0}
        //our list update callback
        onListUpdate={(newList) => setGroup(newList)}
        style={{
          width: '300px'
        }}
      >
        {group[0].map((data, index) => (
          <ReOrderableItem key={`item-${index}`}>
            <div
              style={{
                border: '1px solid black'
              }}
            >
              {data.name}
            </div>
          </ReOrderableItem>
        ))}
      </ReOrderableList>

      <ReOrderableList
        //The name for this group must be unique as this serves as the identifier
        //when validating if the item should be transfered to the list or not.
        //Items can only be transferred to the list with the same group name.
        name='list3'
        group={group}
        //The object path that tells our component where to access the actual array for our list.
        //For lists not embedded within an object simply use the index for our list.
        //The path below retrieves the 2nd list from our group.
        path={1}
        //our list update callback
        onListUpdate={(newList) => setGroup(newList)}
        style={{
          width: '300px'
        }}
      >
        {group[1].map((data, index) => (
          <ReOrderableItem key={`item-${index}`}>
            <div
              style={{
                border: '1px solid black'
              }}
            >
              {data.name}
            </div>
          </ReOrderableItem>
        ))}
      </ReOrderableList>
    </div>
  )
}

Ungrouped list

Ungrouped lists cannot transfer and recieve items from other lists. You can only reorder items from within the list.

Example

import React, { useState } from 'react'
import { ReOrderableItem, ReOrderableList } from 'react-reorderable-list'
import 'react-reorderable-list/dist/index.css'

export default function () {
  //sample data
  const [list, setList] = useState([
    { id: 1, name: 'This' },
    { id: 2, name: 'list' },
    { id: 2, name: 'is restricted' },
    { id: 2, name: 'to itself' }
  ])

  return (
    <div style={{ display: 'flex', gap: '20px' }}>
      <ReOrderableList
        //The unique identifier for this list. Should be unique from other lists and list groups.
        name='list2'
        //your list data
        list={list}
        //the list update callback
        onListUpdate={(newList) => setList(newList)}
        style={{
          width: '300px'
        }}
      >
        {list.map((data, index) => (
          <ReOrderableItem key={`item-${index}`}>
            <div
              style={{
                border: '1px solid black'
              }}
            >
              {data.name}
            </div>
          </ReOrderableItem>
        ))}
      </ReOrderableList>
    </div>
  )
}

Components

Below are the primary components used when making lists along with the available properties for the respective component.

ReOrderableListGroup

PropertyTypeDescriptionDefault
name (Required)StringThe identifier when validating transferred items. This must be unique from other list groups.undefined
group (Required)ArrayThe array of lists for this group.null
onListGroupUpdate (Required)FunctionThe callback function which passes the new value for group as parameter.undefined

ReOrderableList

PropertyTypeDescriptionDefault
name (Required)StringThe identifier when validating transferred items. This must be unique from other list groups.undefined
group (Required when the list is not wrapped within a ReOrderableListGroup component, otherwise Optional)ArrayThe array of lists for this group.null
list (Required when this list is ungrouped, otherwise Optional)ArrayThe data for this list. This is automatically set when wrapped within a ReOrderableListGroup.[]
onListUpdate (Required)FunctionThe callback function which passes the new value for group.undefined
path (Optional)String | NumberThe index or object path needed to access the list array from the group. This property is automatically set when wrapped within a ReOrderableListGroup using the index as the accessor the to the list array.0
component (Optional)String | ComponentDefine a custom component for this list.div
componentProps (Optional)ObjectThe props for the component.null
orientation (Optional)StringThe orientation for this list. Use vertical for vertically oriented lists, otherwise use horizontal.vertical
placeholder (Optional)FunctionA function that returns a Component or HTMLElement to be used as placeholder when an item is being hovered on the list. Passes the currently dragged ReOrderableItem as parameter.(item) => <div style={{ width: `${item.rect.width}px`, height: `${item.rect.height}px`, backgroundColor: 'rgba(0, 0, 0, 0.1)' }} />

ReOrderableItem

PropertyTypeDescriptionDefault
drag (Optional)StringA function that returns a Component or HTMLElement to be used as graphic when dragging an item. Manually setting the width and height styles is required before returning the element or component. Passes the currently dragged ReOrderableItem as parameter.A clone of the item element.
component (Optional)String | ComponentThe component to be used for this item.div
componentProps (Optional)ObjectThe props for the component.null
itemIndex (Optional)NumberThe index for this item on the list. This property is automatically set by the ReOrderableList component but can be manually overridden..0
itemData (Optional)ObjectThe data for this item. This property is automatically set by the ReOrderableList component but can be manually overridden.null
onItemDragStart (Optional)FunctionEvent triggered on item drag start. Passes an object with the following properties { item, //the currently dragged item component. dragX, //the calculated drag coordinate for the X axis. dragY, //the calculated drag coordinate for the Y axis. pageX, //the page coordinate for the X axis. pageY, //the page coordinate for the Y axis. clientX, //the client viewport coordinate for the X axis. clientY //the client viewport coordinate for the Y axis.}null
onItemDrag (Optional)FunctionEvent triggered on item drag. Passes an object with the following properties { item, //the currently dragged item component. dragX, //the calculated drag coordinate for the X axis. dragY, //the calculated drag coordinate for the Y axis. pageX, //the page coordinate for the X axis. pageY, //the page coordinate for the Y axis. clientX, //the client viewport coordinate for the X axis. clientY //the client viewport coordinate for the Y axis.}null
onItemDragEnd (Optional)FunctionEvent triggered on item drag end. Passes an object with the following properties { item, //the currently dragged item component. pageX, //the page coordinate for the X axis. pageY, //the page coordinate for the Y axis. clientX, //the client viewport coordinate for the X axis. clientY //the client viewport coordinate for the Y axis.}null

API

ReOrderableItem

PropertyTypeDescription
instanceIDStringThe instance ID for this reorderable item.
modelObjectAn model with the following properties. { data, //the data for this item. index, //the index for this item on the list. instanceID, //the instance id for this item.}
draggedElementHTMLElementThe element being dragged. This is basically a copy of the item element but is used as graphic when dragging the item.
listComponentReOrderableListThe ReOrderableList component this item belongs to.
overlappingListElementHTMLElementThe currently overlapping list container element.
clonedItemElementHTMLElementA clone of the item element.
rectClientRectThe bounding client rect of the item element.

Issues and Suggestions

Hi! Your feedback for using this library is very valuable and if you have any issues or suggestions feel free to file them on the Issues page.

License

MIT © samceracas