Giter VIP home page Giter VIP logo

react-grid-dnd's Introduction

A demo showing views being swiped left and right.

react-grid-dnd

npm package Follow on Twitter

Grid style drag and drop, built with React. See a live example on codesandbox. You can also see it in action here.

Features

  • Supports dragging between arbitrary number of lists.
  • Built with react-gesture-responder to enable better control over gesture delegation.
  • Disable drop targets or dragging altogether
  • Animated with react-spring

Install

Install react-grid-dnd and react-gesture-responder using yarn or npm.

yarn add react-grid-dnd react-gesture-responder

Usage

Because GridItem components are rendered with absolute positioning, you need to ensure that GridDropZone has a specified height or flex, like in the example below.

import {
  GridContextProvider,
  GridDropZone,
  GridItem,
  swap
} from "react-grid-dnd";

function Example() {
  const [items, setItems] = React.useState([1, 2, 3, 4]); // supply your own state

  // target id will only be set if dragging from one dropzone to another.
  function onChange(sourceId, sourceIndex, targetIndex, targetId) {
    const nextState = swap(items, sourceIndex, targetIndex);
    setItems(nextState);
  }

  return (
    <GridContextProvider onChange={onChange}>
      <GridDropZone
        id="items"
        boxesPerRow={4}
        rowHeight={100}
        style={{ height: "400px" }}
      >
        {items.map(item => (
          <GridItem key={item}>
            <div
              style={{
                width: "100%",
                height: "100%"
              }}
            >
              {item}
            </div>
          </GridItem>
        ))}
      </GridDropZone>
    </GridContextProvider>
  );
}

Dragging between lists

You can see this example in action on codesandbox.

import {
  GridContextProvider,
  GridDropZone,
  GridItem,
  swap,
  move
} from "react-grid-dnd";

function App() {
  const [items, setItems] = React.useState({
    left: [
      { id: 1, name: "ben" },
      { id: 2, name: "joe" },
      { id: 3, name: "jason" },
      { id: 4, name: "chris" },
      { id: 5, name: "heather" },
      { id: 6, name: "Richard" }
    ],
    right: [
      { id: 7, name: "george" },
      { id: 8, name: "rupert" },
      { id: 9, name: "alice" },
      { id: 10, name: "katherine" },
      { id: 11, name: "pam" },
      { id: 12, name: "katie" }
    ]
  });

  function onChange(sourceId, sourceIndex, targetIndex, targetId) {
    if (targetId) {
      const result = move(
        items[sourceId],
        items[targetId],
        sourceIndex,
        targetIndex
      );
      return setItems({
        ...items,
        [sourceId]: result[0],
        [targetId]: result[1]
      });
    }

    const result = swap(items[sourceId], sourceIndex, targetIndex);
    return setItems({
      ...items,
      [sourceId]: result
    });
  }

  return (
    <GridContextProvider onChange={onChange}>
      <div className="container">
        <GridDropZone
          className="dropzone left"
          id="left"
          boxesPerRow={4}
          rowHeight={70}
        >
          {items.left.map(item => (
            <GridItem key={item.name}>
              <div className="grid-item">
                <div className="grid-item-content">
                  {item.name[0].toUpperCase()}
                </div>
              </div>
            </GridItem>
          ))}
        </GridDropZone>
        <GridDropZone
          className="dropzone right"
          id="right"
          boxesPerRow={4}
          rowHeight={70}
        >
          {items.right.map(item => (
            <GridItem key={item.name}>
              <div className="grid-item">
                <div className="grid-item-content">
                  {item.name[0].toUpperCase()}
                </div>
              </div>
            </GridItem>
          ))}
        </GridDropZone>
      </div>
    </GridContextProvider>
  );
}

react-grid-dnd's People

Contributors

bmcmahen avatar danidz96 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

react-grid-dnd's Issues

Boxes with multiple sizes

Are any ways to create GridItem with custom size. Now it's just 1x1. Can I create GridItem with 2x3 size for example?

Delete element?

Is it possible to delete elements using your api? For example, pressing on 'x' causing the element to be removed without refreshing the whole page? Also, when delete happens, I would like the nice animation when it happens.

Animation doesn't work

In my React 18 dnd animation doesn't work, although I see that the state is being updated.

*I solved this by changing the React version to 17

disableDrop not working as intended

Hey!

While writing a program using that library I noticed that if the disableDrop is set, you can drag any item, which will move whole array and can be drop only on the last index. It does not work if the item (from the first GridDropZone) is dropped into another GridDropZone.

Example here:
https://codesandbox.io/s/reactgriddnd-example-bxpo7

How to repoduce:

  1. Drag any element n-1
  2. The list should move (but shoudn't)
  3. If you drop it, will land on the last index always.

Desired behaviour:
I think, the dragged element should go back to the index, where was dragged from.

Regards,
TheAifam5

Drag and Drop not working on mobile screen

Drag and Drop works perfectly on the Desktop screen but not on the mobile screen, Some other similar packages mentioned using the CSS touch-action CSS property set to none for fixing this issue .. but the reordering doesn't work properly if the touch-action is set to none.
I believe this is because of how scrolling works on mobile screen vs the Desktop screen but there seems to be no working fix for this.

has anyone found a fix for this? Or faced the same issue or found a workaround for this ?

API improvements

Force children to be of GridItem type, and use React.Children.map to iterate and provide coordinates to children, which we then render using cloneElement.

Allow GridItem to have a child of render callback, which allows the user to provide their own element instead of GridItem's default element. Only crap thing is they'd need to using react-spring's animated components. I guess we could supply that through the callback too.

Could not resolve dependency when installing

I am trying to use this on [email protected] and is throwing an error:

Could not resolve dependency:
peer react@"^16.8.6" from [email protected]
node_modules/react-grid-dnd
  react-grid-dnd@"*" from the root project

Fix the upstream dependency conflict, or retry
this command with --force, or --legacy-peer-deps
to accept an incorrect (and potentially broken) dependency resolution.

I am trying not to use --force or --legacy-peer-deps because it breaks other things. Is there a version that will work with React 17?

Thank you.

Unable to customize the first image grid

Unable to customize the first image grid: The desired behavior is for the first item to have a col-span-2 and row-span-2, but this functionality is currently not functioning as expected. While using custom CSS, I can adjust the width and height, but this causes other items to overflow.

<GridContextProvider onChange={onChange}> <GridDropZone id="image-grid" boxesPerRow={5} rowHeight={280} style={{ height: 280 * Math.ceil(images.length / 4) }} className="grid grid-cols-5 gap-4" > {images.map((image, index) => ( <GridItem className=" cursor-grab" key={image.src} index={index}> <div className={${
index == 0 ? "col-span-2 row-span-2 bg-green-400" : ""
} relative group} > <input type="checkbox" disabled={loading} checked={checkedImages.includes(image)} onChange={() => handleCheckboxChange(image)} className={absolute top-5 left-5 transform scale-150 cursor-pointer group-hover:opacity-100 ${
checkedImages.includes(image) ? "opacity-100" : "opacity-0"
} z-10} /> <img src={image.src} alt="image" draggable="false" className={border shadow-sm rounded-lg w-full h-full m-auto transition-opacity duration-300 ${
checkedImages.includes(image) ? "opacity-60" : ""
}} /> <div className={bg-black rounded-lg absolute top-0 left-0 w-full h-full transition-opacity duration-300 ${
checkedImages.includes(image)
? "opacity-10"
: "opacity-0 group-hover:opacity-40"
}} ></div> </div> </GridItem> ))} </GridDropZone> </GridContextProvider>

When moving item between lists

So I'm using two GridDropZone but when I'm moving items from one to the other I get the following warning.

Warning: Cannot update a component from inside the function body of a different component.

Using react 16.13.1 and react-grid-dnd 2.1.2

console. | @ | index.js:1 |
-- | -- | -- | --
  | overrideMethod | @ | react_devtools_backend.js:2273
  | printWarning | @ | react-dom.development.js:88
  | error | @ | react-dom.development.js:60
  | warnAboutRenderPhaseUpdatesInDEV | @ | react-dom.development.js:23260
  | scheduleUpdateOnFiber | @ | react-dom.development.js:21196
  | dispatchAction | @ | react-dom.development.js:15682
  | endTraverse | @ | GridContext.js:153
  | (anonymous) | @ | GridItem.js:21
  | callProp | @ | web.js:195
  | (anonymous) | @ | web.js:1478
  | fillArray | @ | web.js:254
  | (anonymous) | @ | web.js:1476
  | mountMemo | @ | react-dom.development.js:15464
  | useMemo | @ | react-dom.development.js:15760
  | useMemo | @ | react.development.js:1521
  | useSprings | @ | web.js:1476
  | useSpring | @ | web.js:1557
  | GridItem | @ | GridItem.js:16
  | renderWithHooks | @ | react-dom.development.js:14825
  | mountIndeterminateComponent | @ | react-dom.development.js:17505
  | beginWork | @ | react-dom.development.js:18629
  | beginWork$1 | @ | react-dom.development.js:23210
  | performUnitOfWork | @ | react-dom.development.js:22185
  | workLoopSync | @ | react-dom.development.js:22161
  | performSyncWorkOnRoot | @ | react-dom.development.js:21787
  | (anonymous) | @ | react-dom.development.js:11111
  | unstable_runWithPriority | @ | scheduler.development.js:653
  | runWithPriority$1 | @ | react-dom.development.js:11061
  | flushSyncCallbackQueueImpl | @ | react-dom.development.js:11106
  | flushSyncCallbackQueue | @ | react-dom.development.js:11094
  | scheduleUpdateOnFiber | @ | react-dom.development.js:21230
  | dispatchAction | @ | react-dom.development.js:15682
  | onChange | @ | index.jsx:113
  | onSwitch | @ | GridContext.js:182
  | onEnd | @ | GridDropZone.js:105
  | handleEnd | @ | GridItem.js:56
  | onRelease | @ | index.js:223
  | handleEnd | @ | index.js:101
  | handleEndMouse | @ | index.js:266

There's a whole issue talking about it, however I don't get to fix it facebook/react#18178

GridItem throwing error in react

index.js:226 Uncaught TypeError: Object(...) is not a function
at new AnimatedStyle (index.js:226)
at createAnimatedStyle (index.js:260)
at new AnimatedProps (index.js:325)
at index.js:339
at renderWithHooks (react-dom.development.js:15108)
at updateForwardRef (react-dom.development.js:16746)
at beginWork$1 (react-dom.development.js:18522)
at HTMLUnknownElement.callCallback (react-dom.development.js:347)
at Object.invokeGuardedCallbackDev (react-dom.development.js:397)
at invokeGuardedCallback (react-dom.development.js:454)
at beginWork$$1 (react-dom.development.js:23217)
at performUnitOfWork (react-dom.development.js:22211)
at workLoopSync (react-dom.development.js:22185)
at renderRoot (react-dom.development.js:21878)
at runRootCallback (react-dom.development.js:21554)
at react-dom.development.js:11353
at unstable_runWithPriority (scheduler.development.js:643)
at runWithPriority$2 (react-dom.development.js:11305)
at flushSyncCallbackQueueImpl (react-dom.development.js:11349)
at flushSyncCallbackQueue (react-dom.development.js:11338)
at scheduleUpdateOnFiber (react-dom.development.js:21431)
at dispatchAction (react-dom.development.js:15816)
at ResizeObserver. (use-measure.js:16)

index.js:2178 The above error occurred in the component:
in ForwardRef (created by GridItem)
in GridItem (at ListResources.jsx:386)
in div (created by GridDropZone)
in GridDropZone (at ListResources.jsx:379)
in GridContextProvider (at ListResources.jsx:378)
in ListResources (created by Connect(ListResources))
in Connect(ListResources) (at Resources.jsx:183)
in div (at Resources.jsx:182)
in Resources (created by Connect(Resources))
in Connect(Resources) (created by Route)
in Route (at App.jsx:57)
in Switch (at App.jsx:54)
in div (at App.jsx:125)
in div (at App.jsx:123)
in div (at App.jsx:119)
in div (at App.jsx:118)
in div (at App.jsx:117)
in Router (at App.jsx:114)
in App (created by Connect(App))
in Connect(App) (at src/index.js:10)
in Provider (at src/index.js:9)

Uncaught TypeError: Object(...) is not a function
at new AnimatedStyle (index.js:226)
at createAnimatedStyle (index.js:260)
at new AnimatedProps (index.js:325)
at index.js:339
at renderWithHooks (react-dom.development.js:15108)
at updateForwardRef (react-dom.development.js:16746)
at beginWork$1 (react-dom.development.js:18522)
at HTMLUnknownElement.callCallback (react-dom.development.js:347)
at Object.invokeGuardedCallbackDev (react-dom.development.js:397)
at invokeGuardedCallback (react-dom.development.js:454)
at beginWork$$1 (react-dom.development.js:23217)
at performUnitOfWork (react-dom.development.js:22211)
at workLoopSync (react-dom.development.js:22185)
at renderRoot (react-dom.development.js:21878)
at runRootCallback (react-dom.development.js:21554)
at react-dom.development.js:11353
at unstable_runWithPriority (scheduler.development.js:643)
at runWithPriority$2 (react-dom.development.js:11305)
at flushSyncCallbackQueueImpl (react-dom.development.js:11349)
at flushSyncCallbackQueue (react-dom.development.js:11338)
at scheduleUpdateOnFiber (react-dom.development.js:21431)
at dispatchAction (react-dom.development.js:15816)
at ResizeObserver. (use-measure.js:16)

Above three errors popped up when integrated library in to an existing project, this is thrown when GridItem component renders.

Dependencies

"@axetroy/react-download": "^1.1.1",
"autoprefixer": "7.1.6",
"babel-core": "^6.26.3",
"babel-eslint": "7.2.3",
"babel-jest": "20.0.3",
"babel-loader": "7.1.2",
"babel-preset-react-app": "^3.1.1",
"babel-runtime": "6.26.0",
"bootstrap": "^4.1.1",
"case-sensitive-paths-webpack-plugin": "2.1.1",
"chalk": "1.1.3",
"create-react-class": "^15.6.3",
"css-loader": "^0.28.7",
"dotenv": "4.0.0",
"dotenv-expand": "4.2.0",
"draft-js": "^0.10.5",
"draftjs-to-html": "^0.8.4",
"eslint": "4.10.0",
"eslint-config-react-app": "^2.1.0",
"eslint-loader": "1.9.0",
"eslint-plugin-flowtype": "2.39.1",
"eslint-plugin-import": "2.8.0",
"eslint-plugin-jsx-a11y": "5.1.1",
"eslint-plugin-react": "7.4.0",
"extract-text-webpack-plugin": "3.0.2",
"file-loader": "1.1.5",
"fs-extra": "3.0.1",
"history": "^4.6.3",
"html-webpack-plugin": "2.29.0",
"jest": "20.0.4",
"js-file-download": "^0.4.1",
"lodash.flow": "^3.5.0",
"moment": "^2.22.2",
"object-assign": "4.1.1",
"postcss-flexbugs-fixes": "3.2.0",
"postcss-loader": "^2.0.8",
"promise": "8.0.1",
"raf": "3.4.0",
"react": "^16.9.0",
"react-avatar-edit": "^0.8.2",
"react-avatar-editor": "^11.0.4",
"react-avatar-image-cropper": "^1.1.7",
"react-beautiful-dnd": "^8.0.7",
"react-bootstrap": "^0.32.1",
"react-bootstrap-date-picker": "^5.1.0",
"react-circular-progressbar": "^0.8.0",
"react-content-loader": "^3.1.2",
"react-cropper": "^1.0.1",
"react-cropperjs": "^1.2.5",
"react-d3-components": "^0.9.1",
"react-datepicker": "^1.5.0",
"react-dev-utils": "^5.0.1",
"react-dnd": "^2.6.0",
"react-dnd-html5-backend": "^2.6.0",
"react-dom": "^16.9.0",
"react-draft-wysiwyg": "^1.12.13",
"react-dropzone": "^4.2.11",
"react-gesture-responder": "^2.1.0",
"react-grid-dnd": "^2.1.0",
"react-image-cropper": "^1.3.0",
"react-image-lightbox": "^5.1.0",
"react-items-carousel": "^2.3.5",
"react-lightbox-component": "^1.2.1",
"react-modal": "^3.4.5",
"react-number-format": "^3.5.0",
"react-paginate": "^6.3.0",
"react-pdf": "^3.0.5",
"react-redux": "^5.0.7",
"react-responsive-modal": "^3.0.3",
"react-router": "^4.2.0",
"react-router-dom": "^4.1.2",
"react-slick": "^0.24.0",
"react-sliding-pane": "^2.0.2",
"react-sortable": "^2.0.0",
"react-sortable-hoc": "^0.8.3",
"reactstrap": "^5.0.0",
"redux": "^3.7.2",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0",
"resolve": "1.6.0",
"style-loader": "^0.19.0",
"superagent": "^3.8.3",
"sw-precache-webpack-plugin": "0.11.4",
"url-loader": "0.6.2",
"webfontloader": "^1.6.28",
"webpack": "3.8.1",
"webpack-dev-server": "2.9.4",
"webpack-manifest-plugin": "1.3.2",
"whatwg-fetch": "2.0.3"

Some feature requests

Hey! It's first library which works for me :D Other just crashing with HMR or something else and I'm getting really annoyed. Thank you for that library!

I want to propose some features like:

  1. Automatically wrap childrens in GridItem.
  2. Allow to define in GridItem:
  • disableDrag
  • disableDrop
  1. Layout persistence
  2. Breakpoints
  3. Dynamic columns (based on breakpoints) - boxesPerRow
  4. Consider to remove id from GridDropZone - could be set internally.
  5. Allow to style GridItem.

About 2 - It's because of that last element.
image

Regards,
TheAifam5

Cannot update a component (`GridContextProvider`) while rendering a different component (`GridItem`)

I'm receiving this error when trying to drag from one drop zone to another, but does not seem to be a consistent error.
I have a single static drop zone, and then another that is being rendered multiple times as separate tabs. Only my last drop zone that is being rendered multiple times has a recognised target id (also an issue, but may possibly be related to this error), and then when dragging from the static drop zone to this one is when I receive this error.

Dragging from the static drop zone to one of the multiple rendered drop zones updates a state which is an array of arrays. Each of these arrays holds a number of images, and when updating one of these the entire state gets updated.

Any assistance on this matter would be greatly appreciated!

Fix for images

I don't know if this has been addressed but it took me an hour to figure out. If you want to use images in the grid items you have to add onDragStart={(e) => {e.preventDefault()}} to the img element.

Help to make onChange function that sends item to the end everytime

function onChange(sourceId, sourceIndex, targetIndex, targetId) {
        if (targetId) {
          const result = move(
            tileState[sourceId],
            tileState[targetId],
            sourceIndex,
            targetIndex
          );
          return setTileState({
            ...tileState,
            [sourceId]: result[0],
            [targetId]: result[1]
          });
        }
    
        const result = swap(tileState[sourceId], sourceIndex, targetIndex);
        return setTileState({
          ...tileState,
          [sourceId]: result
        });
      }

Here is my current onChange function and it works, but I want it to always put the item at the end when dragged rather than swapping with an element it collides with while dragged when released like it currently does. How would I write that?

onHoverDropZone

Thanks so much for this amazing library. I want to mimic files and folders drag experience. Files can be dragged into a folder.

image

I have the functionality working, I just want to improve the experience by adding a visual feedback for when the file is dragged on top of the folder drop zone so the user knows then to let go. Sometimes when I drag the file over the folder and let go the file would snap back to place.

Thanks again.
Gar

don't rely on resize observer

we should probably measurer any time we initiate a drag b/c resize observer doesn't take into account things like parent transforms.

Support for React 18

When I try to install it by running npm i react-grid-dnd I get this error about the dependency tree

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! While resolving: [email protected]       
npm ERR! Found: [email protected]
npm ERR! node_modules/react
npm ERR!   react@"^18.3.1" from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^16.8.6" from [email protected]
npm ERR! node_modules/react-grid-dnd
npm ERR!   react-grid-dnd@"*" from the root project

Lag, Stutters, and dragging between zones.

Hello,
I've literally copied the exact same code from the code-sandbox example, but it lags so much which makes it unusable, as well as the dragged item becoming invisible while dragging to a new drop zone.
It's such a shame, this library is literally exactly what I need.
Would love for an answer!

Dnd area can't be scrolled

On mobile scroll depends on drag. Since the library and the scroll depend on drag, screen isn't scrollable. Is there a way to solve it. Perhaps Dnd should require a short period of holding/grabbing first.

stop click event propagation after dragging

i wanted to do a separated function when we click on the element , i added it, so after dragging elements the onclick event is called also, and there is no event in the onchange method to prevent propagation of the event

Can't perform a React state update

In dev mode "ve got error in browser console

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
GridDropZone@webpack-internal:///./node_modules/react-grid-dnd/esm/GridDropZone.js:19:14

In server console I see another error

Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://reactjs.org/link/uselayouteffect-ssr for common fixes.
at GridDropZone (/home/netsh102093/frontend/app/node_modules/react-grid-dnd/cjs/index.js:326:17)

How to fix this?

2.1.2 GridItem className not set

In 2.1.2 the className which is added to each GridItem, along with 'dragging' or 'disabled' is no longer functioning due to a jumbled ternary

This can be seen by taking the codesandbox demo from this repo's README, and bumping the react-grid-dnd version number up to 2.1.2, then inspect the div element wrapping each grid item (as seen here). You will see that the div now has a className of 'undefined', and when dragging, the 'dragging' class is not appended
image

I have created a pull request #28 with an example fix for this.

Support column-first grids

It would be nice to support grids where the default ordering is
1 4 7
2 5 8
3 6 9

and dragging 9 to the 2 position would create

1 3 6
9 4 7
2 5 8

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.