Code Monkey home page Code Monkey logo

pragmatic-drag-and-drop's Introduction

Fast drag and drop for any experience on any tech stack

๐Ÿ“– Documentation | ๐Ÿคน Examples | ๐ŸŽฅ How it works

Show case of some examples


About

Pragmatic drag and drop is a low level drag and drop toolchain that enables safe and successful usage of the browsers built in drag and drop functionality. Pragmatic drag and drop can be used with any view layer (react, svelte, vue, angular and so on). Pragmatic drag and drop is powering some of the biggest products on the web, including Trello, Jira and Confluence.

Capabilities

Pragmatic drag and drop consists of a few high level pieces:

  1. Low level drag and drop behavior

Pragmatic drag and drop contains a core package, and a number of optional packages, that provide you the pieces to create any drag and drop experience.

These pieces are unopinionated about visual language or accessibility, and have no dependency on the Atlassian Design System.

  • Tiny: ~4.7kB core
  • Incremental: Only use the pieces that you need
  • Headless: Full rendering and style control
  • Framework agnostic: Works with any frontend framework
  • Deferred compatible: Delay the loading the core packages and optional packages in order to further improve page load speeds
  • Flexible: create any experience you want, make any changes you want during a drag operation.
  • Works everywhere: Full feature support in Firefox, Safari, and Chrome, iOS and Android
  • Virtualization support: create any virtual experience you want!
  1. Optional visual outputs

We have created optional visual outputs (eg our drop indicator) to make it super fast for us to build consistent Atlassian user experiences. Non Atlassian consumers are welcome to use these outputs, create their own that copy the visual styling, or go a totally different direction.

  1. Optional assistive technology controls

Not all users can achieve pointer based drag and drop experiences. In order to achieve fantastic experiences for assistive technology users, we provide a toolchain to allow you to quickly wire up performant assistive technology friendly flows for any experience.

The optional assistive controls we provide are based on the Atlassian Design System. If you do not want to use the Atlassian Design System, you can use our guidelines and substitute our components with your own components, or you can go about accessibility in a different way if you choose.

What is this repository?

This repository is currently one way mirror from our internal monorepo that contains all the code for Pragmatic drag and drop.

Diagram of how the mirror works

The intention of this repository is to make public our code, but not to accept code contributions (at this stage). In the future we could explore setting up a two way mirror so that contributions to this repo can also make their way back to our monorepo. You are still welcome to raise issues or suggestions on this repository!

All documentation and npm packages are public and available for use by everyone

Can I use this with my own Design System?

Yep! Pragmatic drag and drop as a small core package, and then a range of optional packages. Some of the optional packages have dependencies on styling solutions (eg emotion), view libraries (eg react) or on some additional Atlassian outputs (eg @atlaskit/tokens). We have separated out optional packages that have other dependencies so they can be easily swapped with your own pieces that use your own tech stack and visual outputs.

Can I use my own design language?

Yep! We have created some design guidelines which embody how we want to achieve drag and drop in our products, and some of those decisions are embodied in some optional packages. However, you are free to use whatever design language you like, including ours!

What is @atlaskit?

The Pragmatic drag and drop packages are published under the @atlaskit namespace on npm

import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';

@atlaskit is the npm namespace that we publish all of our public packages on from inside our internal monorepo. We could look at creating a separate namespace in the future just for Pragmatic drag and drop. If we do that, we'll release some tooling to help folks automatically switch over.

Credits

Made with love by:

Pragmatic drag and drop stands on the shoulders of giants, including the folks who created the drag and drop specifications, implemented drag and drop in browsers, and the many drag and drop libraries that came before this.

pragmatic-drag-and-drop's People

Contributors

alexreardon 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  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

pragmatic-drag-and-drop's Issues

Accomodate iOS specific multi drag pattern

iOS lets you drag multiple elements at once, the library doesnโ€™t handle that correctly. Only the first element is actually moved after dropping.

Hereโ€™s a video that shows the problem.

RPReplay_Final1712460538.mp4

Not shown: cards already being dragged can be added multiple times to the stack. Any card being dragged should be made inert.

TypeScript: Cannot find module '@atlaskit/pragmatic-drag-and-drop/adapter/element-adapter'

When trying to experiment with pragmatic-drag-and-drop I stumbled upon this (what seems to me very basic) problem.

Environment: Node v21.7.3, NPM 10.5.2

To reproduce the issue I started a new vite project using the react-swc-ts template:

npm create vite@latest dnd-example -- --template react-swc-ts
cd dnd-example
npm install

The created project uses TypeScript ^5.2.2 and vite ^5.2.0.

Then I installed the pragmatic-drag-and-drop dependency:

npm install @atlaskit/pragmatic-drag-and-drop

and added the following import to the generated src/App.tsx file:

import {draggable} from "@atlaskit/pragmatic-drag-and-drop/adapter/element-adapter"

Running

npm run build

then prints this error message:

src/App.tsx:5:25 - error TS2307: Cannot find module '@atlaskit/pragmatic-drag-and-drop/adapter/element-adapter' or its corresponding type declarations.

5 import {draggable} from "@atlaskit/pragmatic-drag-and-drop/adapter/element-adapter"

Do I need to separately install some types for pragmatic-drag-and-drop?

Docs: Drag Preview

Hello there!

I was wondering the choice for the drag preview to use ReactDom.render() instead of the ReactDom.createRoot().render()

got a warning in react that it'll run in react 17 instead of react 18

// in the docs
    setCustomNativeDragPreview({
      render({ container }) {
        ReactDOM.render(<Preview item={item} />, container);
        return function cleanup() {
          ReactDOM.unmountComponentAtNode(container);
        };
      },
      nativeSetDragImage,
    });

vs

    setCustomNativeDragPreview({
    render: ({ container }) => {
      const root = ReactDOM.createRoot(container);
      root.render(<Preview item={item} />);
      return () => root.unmount();
    },
      nativeSetDragImage,
    });

thank you again for making a great tool!

Making a next.js Link element draggable.

Hi.

In the process of upgrading Next.js from 12 -> 14 we need to switch from react-dnd. We chose Pragmatic since it seems really nice! We have, however, run into an issue:

  const ref = useRef<HTMLDivElement | null>(null);

  const [isDragging, setIsDragging] = useState(false);

  useEffect(() => {
    const element = ref.current;
    invariant(element);

    return draggable({
      element,
      onDragStart: () => {
        setIsDragging(true);
      },
      onDrop: () => setIsDragging(false),
      getInitialData(): { index: number } {
        return { index };
      },
    });

  });

  return (
    <div ref={ref}>
      <Link href={"https://www.svt.se"}>{index}</Link>
    </div>
  );

The above code gives us a link element where the draggable doesn't seem to be registered. Is this working as intended? Have we missed anything? We have checked the documentation but alas cannot find anything that would help us. Creating a horrible hack sophisticated solution by using onMouseUp and onMouseDown and saving pointer state seems to defeat the whole point of using a drag and drop library.

Absence of handling events in capture phase: Design decision or just current scope?

Running into a case where handling drop events in the capture phase seems ideal, but though this is possible with native DnD API, it's not covered in PDnD.

Is that by design or just the current state of the library?

Example 1 --

Consider a board showing todos, workers and teams. Workers belong to teams. Todos must belong to teams and may belong to a worker on that team โ€” perhaps for 'reasons' a todo assignment to a worker must be prefaced (however immediately) by assignment to that worker's team.

An admin drags a todo from the Worker 1 on the Team 1 panel to Worker 1 on Team 2.

It seems preferable if the parent team-element's handler was narrowly and solely responsible for triggering team assignment during capture phase and, afterwards, the child worker element's drop handler was narrowly and solely responsible for worker assignment.

Handling the events in bubbling order means mixing team and worker assignment somewhere at some point or making under the hood changes to assignment logic, which smells funny.

Example 2 --

Consider a Risk-like board game with dudes on a map but with a deep nesting of countries, provinces, cities etc, and where moving dudes from one country's province's city to another country's province's city would require handling higher level boundary changes before the lower ones as they might interrupt the move. If the game is set in stone a master handler is probably fine, but if its life involves more churn ('interplanetary travel dlc incoming!'), more narrowly scoped top-down handling could be useful.

Examples are outdated

On your webpage you have examples listed:
Examples webpage

These examples run with react 16 which was released in 2019.

After upgrading to the latest react version you have a lot of error to fix to get it running:

  • After clicking two times on the drag-icon: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node. Still no idea how to fix this.
  • Dependency errors with the package tiny-invariant. You can only install this package with the force npm attribute
  • If you have typescript installed this rule // eslint-disable-next-line @atlaskit/design-system/no-banned-imports is prohibiting your code to run
  • Is Portal necessary? Portal is a performance killer, but I never worked with portals so maybe it is still needed.
  • ReactDOM.createPortal ist not supported in react18, use createPortal instead
  • ReactDOM.render ist not supported in react18 use createRoot (thanks buzzie-bee)

Maybe you can update your code to a more recent version. Thx

Feature: Make tree hitbox zones configurable

I've implemented a tree drag and drop and for business logic reasons certain items cannot be dropped onto other items.

I have implemented a 'make-child' block, but when dragging items over these blocked items the indicators are very janky, they flash in and out as the mouse moves. This is because the instruction is being set to 'instruction blocked' when the mouse is near the center of the items.

It would be nice for new users to be able to configure the zones via arguments, instead of having to clone the hitbox code and customise it yourself (which is straightforward enough once you're used to pragmatic-drag-and-drop).

I'm thinking it would be great to pass in some enabled/disabled flags along with percentage values for the different zones. This would allow users to remove zones for instructions which are blocked completely, i.e. only allow make child, only allow reorder-above/below, only have blocked, etc.

CSS transforms animations similar to react-beautiful-dnd

Hi,

Will it be possible to make animations for drag and drop within simple lists similar to react-beautiful-dnd, when dragging an item moves the other items around using css transforms ?

I acknowledge that this might not be the recommended approach due to potential user experience and performance concerns. Nonetheless, I'd like to know if there are any inherent limitations that might hinder someone from replicating an experience similar to what was offered by react-beautiful-dnd.

@atlaskit/pragmatic-drag-and-drop-react-accessibility has a peer dependency of react 16.8.0

I was checking out some of the optional packages that were suggested and got an error when I tried to install @atlaskit/pragmatic-drag-and-drop-react-accessibility, as it had React version ^16.8.0 as a peer dependency. This seems like it may be an error, though I noticed most of codesandbox examples are using React 16. Are newer versions of React supported?

Edit: It seemed to work fine in React 18. Also, I noticed the same peer dependency issue in several other packages (ex: @atlaskit/tokens).

canDrop = false not working on tree root element

I am trying to implement a 'tree' style drag and drop interface which will have different types of elements. For logical reasons, certain element types can only exist as children of other element types.

I have tried to implement a basic example using the 'section' and 'field' types. sections can be children of the root or of other sections, fields can only be children of sections.

I have added the dropTargetForElements adaptor to the root element, and configured it's 'canDrop' to only return true for 'section' type items, but 'field' type items can still be successfully dropped there.

I have slightly adjusted the tree example to include the type on the TreeItem, and to only return canDrop: true on the root element if the item.type === 'section'.

If you check the console.logs, the 'section' items return canDrop: true, and the field items return canDrop: false, yet the field items can still be dropped.

https://codesandbox.io/p/sandbox/tree-forked-83sfc7?file=%2Fexample.tsx%3A251%2C26

I assume this is a bug, as this behaviour does not match the typedoc for canDrop:

Used to conditionally block dropping. By default a drop target can be dropped on.

Return false if you want to block a drop.

If this is not a bug and is the intended behaviour of canDrop on the root elements, is there another way to achieve my goal?

๐ŸŽจ Share what you have made!

We would love to see what you create with Pragmatic drag and drop. Please feel free to post a screen recording of your experience in this issue โœจ

support drag and drop inside iframe

I tried to implement drag and drop in an iframe, but seems no event is firing. I tried with your example. I cannot find any iframe specific settings in it. but it clone the whole react app into iframe somehow, how and why this is happened, I have no idea(i did not find the code) ๐Ÿ˜ž

Here is my implementation

Works fine outside of iframe, but not working inside iframe.

In react-dnd I was doing this:

import {useContext, useEffect} from 'react';
import {DndContext} from 'react-dnd';
import {FrameContext} from 'react-frame-component';

const DndProviderWrapper = ({children}) => {
  const {dragDropManager} = useContext(DndContext);
  const {window} = useContext(FrameContext);

  useEffect(() => {
    // @ts-ignore
    dragDropManager.getBackend().addEventListeners(window);
  });

  return children;
};

export default DndProviderWrapper;

But I cannot figure out how to do this in pragmatic

Drag and drop with video element

Hi, congratulations on the release!

Im trying to make a simple example to work in vue 3 with video.
Im trying to copy the Grid example from the docs, and just making a simple swap work in a grid or list.

https://codesandbox.io/p/devbox/pragmatic-dnd-forked-nmlnsj

My issue is that it will replace the actual item, but the video does not seem to want to come along.
If I seek to 50% in the video from the "A" container, then drag it to "B" and drop, it will swap the items but the video that i was hoping would move to "B" is still left in "A" on 50%.

What am I doing wrong?

Out of view components are cropped when dragged

When dragging a component that is out of view (see left cards in image below) the dragged card is cropped and only displays what was shown in the view before. My board roughly follows the example board.

Screenshot 2024-04-06 at 15 20 13

The board in the examples does not have this issue, so I am missing something. Since my board doesn't follow the example strictly (I don't use Atlassian dependencies and persist the board in a DB) it is difficult to troubleshoot though. I've looked through the docs but can't find what is responsible to track the component UI when it is outside of the view.

Inconsistent drag preview opacity

I've noticed that there seems to be an inconsistent opacity in the drag preview. I cannot figure out why it occurs but I noticed it when making my own lists. You can also see it in the examples on the example page.

Example 1:
drag1

Example 2:
drag2

Is there a way to ensure an opacity of 100% for the drag preview? Is there a reason it would sometimes have a ~50% opacity?

Edit: I notice that the drag previews fade in. I think this may be a timing bug where sometimes they don't get faded in all the way.

In Tutorial on iOS (17.2+) the required press-and-hold-to-drag gesture can trigger image action state.

Not sure if this is a bug or as designed.

In the tutorial, the draggable ref is to an img but on iOS dragging requires press-and-hold which when performed on an img, can activate the OS's image action state if a move does not occur soon enough. On an actual device, when the finger obscures the visual draggable-state change, it's easy to hold 'too long'.

image-action-state.mp4

Question:
Should draggable be expected to produce consistent cross-platform behavior absent side effects like these by default or is it up to the developer to be aware of and handle these kinds of situations?

Broken links in documentation

Hello,

Thanks, hugs, love ya, etc. "What a library" - me.

I'm running into broken links pretty frequently in the documentation. Some examples:

Usually I'm able to find the new location based on the broken href but it's sort of annoying. Thanks for considering a fix!

Support: Windows touch screen

Trying out the examples in the documentation on a surface device with latest windows and edge, none of them seem to work with touch - pressing and holding does not start the drag and drop process.

@formkit/drag-and-drop

A few folks have linked me about @formkit/drag-and-drop as it is another recent drag and drop library, and so I thought I would create this issue containing my thoughts to link people to if they ask me about it.

I generally try to stay away from detailed public solution comparison for the things that I build, so I will be keeping my thoughts pretty high level. I want to encourage and celebrate anybody who puts something out there for people to use. The reality is that in open source software, that all projects are being inspired from the ones around them.

While not related to the code itself, the effort Formkit put into their branding and their website should be celebrated. It's really incredible!

@formkit/drag-and-drop appears to be a library that enables the quick setting up of single level sortable experiences, and a way to connect those sortable experiences together. It looks to be targeting a similar problem domain to Sortable

Pragmatic drag and drop is a lower level abstraction, and can be used to power any experience, including: sortable lists, connected sortable lists, boards, trees, tables, site builders, resizing, drawing, file dropping, text selection dragging, dragging into and out of iframes - and anything else that is possible on the web platform. Pragmatic drag and drop is a low level abstraction layer on the web platform itself. I suspect that (most of) the API and behaviour of @formkit/drag-and-drop could be built on top of Pragmatic drag and drop.

I hope this is helpful,

Cheers

Weird dragging behaviour.

I just don't know how to explain what is happening. Please refer to video attached.

pragmatic-dnd.mp4

Below is my typescript code for dragging on each task card.

useEffect(() => {
    const el = dndRef.current
    
    return draggable({
	    element: el!,
    })
}, [])

Support: Web components with shadow dom

Looking at the code in "element-adapter.js":

 var target = event.target;

 // see if the thing being dragged is owned by us
 var entry = draggableRegistry.get(target);

If the dragged element is contained within the shadow root of another web component then 'target' above won't be the element being dragged but will instead be the web component due to event re-targetting. The following code sandbox shows the issue:

https://codesandbox.io/p/sandbox/pdnd-web-components-forked-l8f6tv

Drag issue when dragging *new* item onto a tree.

I'm running into an issue that has been a challenge to debug. Basically, the drop target isn't being detected until the mouse moves off the window and then back onto the window.

We are using a the "tree" component and when reordering items in the tree everything works. However, we also want to support dragging a new item (from outside the tree but still in same window) into the tree and creating it. In that case, the drop targets are only found when the user moves cursor off the window and back on. Very strange.

Drag.issue.mov

System Info:

  System:
    OS: macOS 14.5
    CPU: (12) arm64 Apple M3 Pro
    Memory: 204.63 MB / 36.00 GB
    Shell: 5.9 - /bin/zsh
  Browsers:
    Chrome: 124.0.6367.61
    Safari: 17.5

Simpler examples without atlassian dependencies

This is a suggestion to implement some simpler examples without Atlassian dependencies.

The documentation for this project is very good, but the examples are all quite large with heavy dependencies on Atlassian components and tools.

The List Example is a great starting point for what I'd like to build, but it's overwhelming to try and recreate locally by copy pasting the example code.

It might be possible for prospective users to dig into the Atlassian code base to figure out how to replicate for example the Box component with plain jsx and their own styling, but with how many dependencies even the Box component is a major effort to try to understand what's going on.

It would very helpful to adopters of this package if we could have some versions of the examples using plain JSX elements and either plain css files or tailwind so it's easier to understand how to recreate the examples locally.

Ideally the examples should only have imports from React and pragmatic-drag-and-drop, and if you copy pasted them into a project with those dependencies installed it should just work.

Synchronise repo with commit messages (eg. --fast-forward)

At the moment all commit messages are "Synchronise latest changes".

I'm super curious to try out this lib, but since it's also in an early stage, seeing what's changing / fixed is important. Seeing only opaque commit messages is a bit scary, as we don't know what's happening

I think Seeing the commit changes would be super helpful :)
Would it be possible to have the bot make fast forward merges when syncing?

SUPER curious to try this out. It looks like a lot of care and engineering effort was done here!

IFrame Support

I'm interested in using Pragmatic Drag-and-Drop within an iframe component like react-frame-component. Is this supported?

I've seen some discussions online suggesting it might be possible with limitations, but I couldn't find any official documentation on this.

Remove `react-drop-indicator` dependency on `@emotion/react`

I'm excited to dig more into this library and so far I am loving the approach of a small core and small utility libraries around it. One thing that I think might get in the way for adoption is the dependency on @emotion/react for the drop indicator package.

Emotion is a great library that I have used for many years but it is quite large and it also doesn't work (well) with modern react features like streaming rendering or RSC.

Looking at the usage, it seems possible to provide an additional package that just uses a pre-compiled css file instead of emotion. Would you be open to that?

Change cursor while dragging

Hello! Is there a possibility to change the cursor during drag? Currently, when the drag action starts, the drag cursor is displayed. I'm developing an application to resize graphical elements and I want to use the 'nw-resize' cursor during resize, but I can't find a solution.
Here is an example:
Recording-2024-04-03-120017

Press and hold to drag is problematic in Grid example (iOS)

Currently for drag to start, you need to press and hold (this was not very obvious so I initially thought drag doesn't work in mobile).

The problem is when what you are trying to drag is an image - in that case iOS does this.

image

Is it possible to just drag instead of having to press and hold? Dndkit / formkit dnd etc works that way

Add `exports` to package.json

Hi,

I wanted to play around with the library, so I created a fresh Vite project npm create vite with React & TypeScript and started with such import

import { draggable } from "@atlaskit/pragmatic-drag-and-drop/adapter/element-adapter";

Unfortunately it was not resolved. I dug into the package.json and from what I saw only the main entry points are exposed (which contain nothing, since as per documentation we should import individual files).
Adding proper "exports" field to package.json with all files in dist/(esm|cjs|types) fixed the issue for me, but I'm now relying on patch-package lib and a git diff to keep it working.
This is the diff I applied:
@atlaskit+pragmatic-drag-and-drop+1.1.3.patch
and a preview of the file:

diff --git a/node_modules/@atlaskit/pragmatic-drag-and-drop/package.json b/node_modules/@atlaskit/pragmatic-drag-and-drop/package.json
index b270896..9454cc2 100644
--- a/node_modules/@atlaskit/pragmatic-drag-and-drop/package.json
+++ b/node_modules/@atlaskit/pragmatic-drag-and-drop/package.json
@@ -17,6 +17,340 @@
       ]
     }
   },
+  "type": "module",
+  "exports": {
+    "./package.json": "./package.json",
+    "./": {
+      "default": "./dist/esm/index.js",
+      "require": "./dist/cjs/index.js",
+      "types": "./dist/types/index.d.ts"
+    },
+    "./internal-types": {
+      "default": "./dist/esm/internal-types.js",
+      "require": "./dist/cjs/internal-types.js",
+      "types": "./dist/types/internal-types.d.ts"
+    },
+    "./adapter/element-adapter-native-data-key": {
+      "default": "./dist/esm/adapter/element-adapter-native-data-key.js",
+      "require": "./dist/cjs/adapter/element-adapter-native-data-key.js",
+      "types": "./dist/types/adapter/element-adapter-native-data-key.d.ts"
+    },
+    "./adapter/element-adapter": {
+      "default": "./dist/esm/adapter/element-adapter.js",
+      "require": "./dist/cjs/adapter/element-adapter.js",
+      "types": "./dist/types/adapter/element-adapter.d.ts"
+    },
+    "./adapter/external-adapter": {
+      "default": "./dist/esm/adapter/external-adapter.js",
+      "require": "./dist/cjs/adapter/external-adapter.js",
+      "types": "./dist/types/adapter/external-adapter.d.ts"
+    },
+    "./adapter/text-selection-adapter": {
+      "default": "./dist/esm/adapter/text-selection-adapter.js",
+      "require": "./dist/cjs/adapter/text-selection-adapter.js",
+      "types": "./dist/types/adapter/text-selection-adapter.d.ts"
+    },
+    "./entry-point/cancel-unhandled": {
+      "default": "./dist/esm/entry-point/cancel-unhandled.js",
+      "require": "./dist/cjs/entry-point/cancel-unhandled.js",
+      "types": "./dist/types/entry-point/cancel-unhandled.d.ts"
+    },
+    "./entry-point/combine": {
+      "default": "./dist/esm/entry-point/combine.js",
+      "require": "./dist/cjs/entry-point/combine.js",
+      "types": "./dist/types/entry-point/combine.d.ts"
+    },
+    "./entry-point/once": {
+      "default": "./dist/esm/entry-point/once.js",
+      "require": "./dist/cjs/entry-point/once.js",
+      "types": "./dist/types/entry-point/once.d.ts"
+    },
+    "./entry-point/prevent-unhandled": {
+      "default": "./dist/esm/entry-point/prevent-unhandled.js",
+      "require": "./dist/cjs/entry-point/prevent-unhandled.js",
+      "types": "./dist/types/entry-point/prevent-unhandled.d.ts"
+    },
...

Vertical trees

Hello, it would be great if there was a built-in way for making vertical trees

So that the hitboxes for "reorder above" would be on the left and hitboxes for "reorder below" -- on the right.

https://atlassian.design/components/pragmatic-drag-and-drop/optional-packages/hitbox/about#tree-item

Or another solution would be to add something like maxDetectionDistance parameter to attachClosestEdge() function to allow for detecting the hitbox of the container

EDIT:

For my use case I just patched the hitbox calculating function with pnpm patch (the code bellow also in /es2019 and /cjs directories):

diff --git a/dist/esm/tree-item.js b/dist/esm/tree-item.js
index 47356cf1b195747f52f47b73ee8c0dd8b7155f82..7ca74ff683bcfc12f33c41c87cddea2c9320a376 100644
--- a/dist/esm/tree-item.js
+++ b/dist/esm/tree-item.js
@@ -14,16 +14,16 @@ function getCenter(rect) {
 function standardHitbox(_ref) {
   var client = _ref.client,
     borderBox = _ref.borderBox;
-  var quarterOfHeight = borderBox.height / 4;
+  var quarterOfHeight = borderBox.width / 4;
 
   // In the top 1/4: reorder-above
   // On the line = in the top 1/4 to give this zone a bit more space
-  if (client.y <= borderBox.top + quarterOfHeight) {
+  if (client.x <= borderBox.left + quarterOfHeight) {
     return 'reorder-above';
   }
   // In the bottom 1/4: reorder-below
   // On the line = in the bottom 1/4 to give this zone a bit more space
-  if (client.y >= borderBox.bottom - quarterOfHeight) {
+  if (client.x >= borderBox.right - quarterOfHeight) {
     return 'reorder-below';
   }
   return 'make-child';

And then the drop indicator is hacked like this:

import { DropIndicator as TreeItemDropIndicator } from "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/tree-item";
import { DropIndicator as BoxDropIndicator } from "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box";


export type DropIndicatorProps = {
  instruction: Instruction;
  gap?: string;
};
export const DropIndicator = ({ instruction, gap }: DropIndicatorProps) => {
  if (instruction.type === "reorder-above") {
    return <BoxDropIndicator edge={"left"} gap={gap} />;
  }
  if (instruction.type === "reorder-below") {
    return <BoxDropIndicator edge={"right"} gap={gap} />;
  }
  return <TreeItemDropIndicator instruction={instruction} />;
};

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.