react-drag-drop-zones
TypeScript icon, indicating that this package has built-in type declarations

0.1.2 • Public • Published

react-drag-drop-zones

This is a library for creating custom drop-zones. Elements that are inside those drop-zones are draggable and Dropzone into other ones.

🌈 SUPPORTED LANGUAGES

  1. JavaScript
  2. TypeScript

🌈 AVAILABLE COMPONENTS

  • DragDropProvider
  • DropZone

🌈 REQUIREMENTS

  1. Works in React.js applications
  2. Prop states(array of objects: [{state: , setState: }, {...}, ...]) needs to be present on DragDropProvider component
  import { DropZone, DragDropProvider } from 'react-drag-drop-zones';
  import { useState } from 'react';

  export type ElementType = {
    id: number;
    title: string;
  };

  function App() {
    const [elements_0, setElements_0] = useState<ElementType[]>([
      { id: 1, title: "Element 1" },
      { id: 2, title: "Element 2" },
    ]);
    const [elements_1, setElements_1] = useState<ElementType[]>([
      { id: 3, title: "Element 3" },
      { id: 4, title: "Element 4" },
    ]);
    const [elements_2, setElements_2] = useState<ElementType[]>([
      { id: 5, title: "Element 5" },
      { id: 6, title: "Element 6" },
    ]);

    const states = [
      { state: elements_0, setState: setElements_0 },
      { state: elements_1, setState: setElements_1 },
      { state: elements_2, setState: setElements_2 },
    ];

    return (
      <DragDropProvider states={states}>
        <DropZone>
          {elements_0.map(el => (<div key={el.id}>{el.title}</div>) )}    
        </DropZone>
        <DropZone>
          {elements_1.map(el => (<div key={el.id}>{el.title}</div>) )}    
        </DropZone>
        <DropZone>
          {elements_2.map(el => (<div key={el.id}>{el.title}</div>) )}    
        </DropZone>
      </DragDropProvider>
    );
  }
  export default App;

🌈 STYLING

  1. CSS native:
  • Inline styling. Passing a style(object)
  • as a prop to any component provided by library
  • as an attribute to any draggable element provided by user
  • Passing className(string)
  • as a prop to any component provided by this library
  • as an attribute to any draggable element provided by user
  • styles by selectors in .css file
  • Tailwind, SCSS or any other styling library acceptable.

🌈 STYLING EXAMPLE

const inlineCSS = {
  display: "flex",
  flexDirection: "column",
  gap: "1rem",
  backgroundColor: "red",
  // ...
}

<DragDropProvider className="flex flex-col gap-3 bg-green-500 ..." > // styling by tailwind clasNames

    <DropZone className="flex flex-col gap-2 bg-blue-300 ..."> // styling by tailwind clasNames
      {elements_0.map(el => (<div key={el.id}>{el.title}</div>) )} 
    </DropZone>

    <DropZone style={inlineCSS}> // styling by inline CSS 
      {elements_1.map(el => (<div key={el.id}>{el.title}</div>) )} 
    </DropZone>

    <DropZone className="customClassDropZone"> // styling by custom css
     {elements_2.map(el => (<div key={el.id}>{el.title}</div>) )} 
    </DropZone>

  </DragDropProvider>

🌈 AFTER DROP FUNCTIONALITY

  1. afterDrop function (optional) that will be executed after element is droped in one of the DropZone's * Function afterDrop receives one argument (object of type: AfterDropType ) that contains information(indexes) about dragged and dropped element and it's Dropzone. It contains:
    • indexes of source and destination Dropzone (relatively to it's parent-DragDropProvider)
    • index of dragged element where it was dragged from (relatively to it's parent- sourceDropzone)
    • index(position) of dragged element where it was dropped into (relatively to destination Dropzone). If you drop element between elements with indexes 1 and 2 so index of a dropped element will be 2 (distance between elements starts and ends in the middle of them)
  export type AfterDropType = {
    sourceDropzoneIndex: number;
    destinationDropzoneIndex: number;
    draggedElementIndex: number;
    positionDestinationIndex: number;
  };
  function customAfter(data: AfterDropType) { /*logic*/ }
  • sourceDropzoneIndex : Index of Dropzone component (relatively to it's parent :DragDropProvider) where element was dragged from
  • destinationDropzoneIndex : Index of Dropzone component (relatively to it's parent :DragDropProvider) where element was dropped into
  • draggedElementIndex : Index of a dragged element (relatively to it's parent : source Dropzone) where it was dragged from
  • positionDestinationIndex : Index of a dropped element (relatively to it's parent : destination Dropzone) where it was dropped into

Steps and example :

  • Import AfterDropType:
  • afterDrop prop => DragDropProvider
  • create customAfter function and associate it to the afterDrop prop
  import { DropZone, DragDropProvider, AfterDropType } from 'react-drag-drop-zones';

  function App() {
    // ...
    const customAfter = (data: AfterDropType) => {/*logic*/}

    return (
      <DragDropProvider 
        afterDrop={customAfter} 
        states={states}
      >
        {/* DropZones logic */}
      </DragDropProvider>
    );
  }
  export default App;
  1. customStatesManipulation(optional) prop(of type boolean) in DragDropProvider * If prop is passed to DragDropProvider as true the sates will remain unchanged and it is up to the user to make proper states manipulation thanks to an object that afterDrop receives. Example:
  import { DropZone, DragDropProvider, AfterDropType } from 'react-drag-drop-zones';

  function App() {
    // ...
    const customAfter = (data: AfterDropType) => {/*logic*/}

    return (
      <DragDropProvider 
        customStatesManipulation = {true}
        afterDrop={customAfter} 
        states={states}
      >
        {/* DropZones logic */}
      </DragDropProvider>
    );
  }
  export default App;

🌈 FULL EXAMPLE

  import { DropZone, DragDropProvider, AfterDropType } from 'react-drag-drop-zones';
  import { useState } from 'react';

  export type ElementType = {
    id: number;
    title: string;
  };

  function App() {
    const [elements_0, setElements_0] = useState<ElementType[]>([
      { id: 1, title: "Element 1" },
      { id: 2, title: "Element 2" },
    ]);
    const [elements_1, setElements_1] =  useState<ElementType[]>([
      { id: 3, title: "Element 3" },
      { id: 4, title: "Element 4" },
    ]);
    const [elements_2, setElements_2] = useState<ElementType[]>([
      { id: 5, title: "Element 5" },
      { id: 6, title: "Element 6" },
    ]);

    const states = [
      { state: elements_0, setState: setElements_0 },
      { state: elements_1, setState: setElements_1 },
      { state: elements_2, setState: setElements_2 },
    ];

    const afterDrop = (data: AfterDropType) => {
      console.log(data)
      /*after drop logic if needed*/
      /*for example states manipulation 
        if `customStatesManipulation` is `true` and is passed to `DragDropProvider`
      */
    }

    return (
      <DragDropProvider
        afterDrop={customAfter} 
        // customStatesManipulation = {true}
        // style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }} // inline CSS
        className='flex gap-5 p-5 flex-col'  // tailwind
        states={states}
      >
        <DropZone className="flex flex-col gap-2 bg-blue-300 ..."> // styling by tailwind clasNames
          {elements_0.map(el => (<div key={el.id}>{el.title}</div>) )} 
        </DropZone>

        <DropZone style={inlineCSS}> // styling by inline CSS 
          {elements_1.map(el => (<div key={el.id}>{el.title}</div>) )} 
        </DropZone>

        <DropZone className="customClassDropZone"> // styling by custom css
        {elements_2.map(el => (<div key={el.id}>{el.title}</div>) )} 
        </DropZone>

      </DragDropProvider>
    );
  }
  export default App;

API

  • DragDropProvider Props

    prop optional description
    states no An array of state objects. Each object should have a state and setState property
    afterDrop yes A function that is executed at the end of a drag & drop action. It receives an argument(object of type AfterDropType) containing information about the drop
    customStatesManipulation yes A boolean flag. If set to true, the drop action will not modify the states, and it's up to the user to handle state modifications in the afterDrop function
  • types

    • AfterDropType
      type description
      sourceDropzoneIndex Index of Dropzone component (relatively to it's parent :DragDropProvider) where element was dragged from
      destinationDropzoneIndex Index of Dropzone component (relatively to it's parent :DragDropProvider) where element was dropped into
      draggedElementIndex Index of a dragged element (relatively to it's parent : source Dropzone) where it was dragged from
      positionDestinationIndex Index of a dropped element (relatively to it's parent : destination Dropzone) where it was dropped into
  • DragDropProvider and Dropzone Props

    prop optional description
    className yes A string representing the a className for the DragDropProvider component
    style yes An object containing CSS properties to inline style the DragDropProvider and DropZone components

This project is licensed under the MIT License - see the LICENSE file for details.

Hope it will be usefull for you !!!

Readme

Keywords

none

Package Sidebar

Install

npm i react-drag-drop-zones

Weekly Downloads

1

Version

0.1.2

License

MIT

Unpacked Size

58.5 kB

Total Files

9

Last publish

Collaborators

  • lukasz_grzegorzewski