UNPKG

@atlaskit/pragmatic-drag-and-drop-docs

Version:

This package holds the documentation for Pragmatic drag and drop in one place. It is not intended to be consumed directly by consumers. The package is used by other tools for sharing examples

193 lines (155 loc) 4.86 kB
--- title: Reconciliation description: How Pragmatic drag and drop reconciles pieces. order: 0 --- ## Drop targets The `key` for a _drop target_ is the element. At any one time, only a single _drop target_ for a particular entity type (eg files) can be attached to the same element. ```ts // ✅ Using the same element as a drop target for elements and for files const cleanup = combine( dropTargetForElements({ element: myElement, }), dropTargetForExternal({ element: myElement, }), ); ``` ```ts // ❌ Using the same element for two drop targets of the same entity type is not allowed const cleanup = combine( dropTargetForElements({ element: myElement, }), // ⚠️ A warning will be logged if this is detected dropTargetForElements({ element: myElement, }), ); ``` During a drag operation, if a _drop target_ is removed and readded on the same `element`, then `@atlaskit/pragmatic-drag-and-drop` will treat the added _drop target_ as if it was the same _drop target_. ```ts const monitor = monitorForElements({ onDragStart: () => console.log('monitor:start'), onDropTargetChange: () => console.log('monitor:change'), onDrop: () => console.log('monitor:drop'), }); const cleanup1 = dropTargetForElements({ element: A, onDragStart: () => console.log('A1:start'), onDropTargetChange: () => console.log('A1:change'), onDrop: () => console.log('A1:drop'), }); // a drag starts // console.log → 'A1:start', 'monitor:start' // drop target is removed during a drag cleanup1(); // console.log not called (no change event is fired) const cleanup2 = dropTargetForElements({ element: A, onDragStart: () => console.log('A2:start'), onDropTargetChange: () => console.log('A2:change'), onDrop: () => console.log('A2:drop'), }); // a dragover occurs // console.log → 'A2:drag', 'monitor:drag' // 👆 note: no 'change' event occured, A2 is treated as A1 ``` ## Draggables The `key` for a `draggable` is the element. An element can only be used for a single `draggable`. ```ts // ❌ Using the same element for two draggables draggable({ element: myElement, }), // ⚠️ A warning will be logged if this is detected draggable({ element: myElement, }), ); ``` During a drag operation, if the dragging `draggable` is removed and readded on the same `element`, then `@atlaskit/pragmatic-drag-and-drop` will treat the added `draggable` as if it was the original `draggable`. ```ts const monitor = monitorForElements({ onDragStart: () => console.log('monitor:start'), onDrop: () => console.log('monitor:drop'), }); const cleanup1 = draggable({ element: A, onDragStart: () => console.log('A1:start'), onDrop: () => console.log('A1:drop'), }); // a drag starts // console.log → 'A1:start', 'monitor:start' // drop target is removed during a drag cleanup1(); // console.log not called (no change event is fired) const cleanup2 = dropTargetForElements({ element: A, onDragStart: () => console.log('A2:start'), onDrop: () => console.log('A2:drop'), }); // a drop occurs // console.log → 'A2:drop', 'monitor:drop' // 👆 note: the drop event occured on 'A2' even though it was not the same `draggable()` as the original drag ``` Remounting a `draggable` common in `react` where you _might_ do something like this: ```tsx function Card() { const ref = useRef(); const [dragCount, setCount] = useState(0); useEffect(() => { return draggable({ element, onDragStart: () => setCount(dragCount + 1), }); // when dragCount changes our `draggable` will be remounted }, [dragCount]); return <div ref={ref}>I have been dragged {dragCount} times</div>; } ``` This is a contrived example, because you _could_ avoid the remounting in this case by doing this: ```tsx function Card() { const ref = useRef(); const [dragCount, setCount] = useState(0); useEffect(() => { return draggable({ element, onDragStart: () => setCount((current) => current + 1), }); // no longer need to remount when `dragCount` changes }, []); return <div ref={ref}>I have been dragged {dragCount} times</div>; } ``` ## Monitors Each call to create a _monitor_ will create a new monitor, even if the monitor definition is shared. There is no `key` for _monitors_. ```ts import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter'; const args = { onGenerateDragPreview: () => console.log('monitor:preview'), }; // these two monitors are sharing the same `args` reference // but they will both create an independent monitor const cleanup1 = monitorForElements(args); const cleanup2 = monitorForElements(args); // → A drag starts // console.log: // - 'monitor:preview' // - 'monitor:preview' // → A drag finishes // removing one monitor cleanup1(); // → Another drag starts // console.log: // - 'monitor:preview' // 👆 one monitor is still active ```