Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@atlaskit/pragmatic-drag-and-drop

atlassian1.1mApache-2.01.7.2TypeScript support: included

The core package for Pragmatic drag and drop - enabling fast drag and drop for any experience on any tech stack

readme

Pragmatic drag and drop

Fast drag and drop for any experience on any tech stack

The core package for Pragmatic drag and drop.

📖 Documentation

changelog

@atlaskit/pragmatic-drag-and-drop

1.7.2

Patch Changes

  • #164244 65021fc0267e2 - The cleanup functions returned by the following utilities now only work on the first call. This was done to prevent unexpected side effects of calling a cleanup function multiple times.

    • @atlaskit/pragmatic-drag-and-drop/adapter/element
      • draggable
      • dropTargetForElements
      • monitorForElements
    • @atlaskit/pragmatic-drag-and-drop/adapter/text-selection
      • dropTargetForTextSelection
      • monitorForTextSelection
    • @atlaskit/pragmatic-drag-and-drop/adapter/external
      • dropTargetForExternal
      • monitorForExternal
    • @atlaskit/pragmatic-drag-and-drop-auto-scroll/element
      • autoScrollForElements
      • autoScrollWindowForElements
    • @atlaskit/pragmatic-drag-and-drop-auto-scroll/external
      • autoScrollForExternal
      • autoScrollWindowForExternal
    • @atlaskit/pragmatic-drag-and-drop-auto-scroll/text-selection
      • autoScrollForTextSelection
      • autoScrollWindowForTextSelection

1.7.1

Patch Changes

  • #162456 f916af5aab898 - Removes @atlaskit/platform-feature-flags as a dependency. Removes @atlaskit/link as a runtime dependency, although it is still used in examples.

1.7.0

Minor Changes

  • #157071 a149a0b1559ec - We are testing the migration to the ADS Link component behind a feature flag. If this fix is successful it will be available in a later release.

Patch Changes

  • Updated dependencies

1.6.1

Patch Changes

  • #150602 f83b03a3b239e - pointerOutsideOfPreview will no longer push the preview away from the users pointer on iOS due to platform limitations. On iOS the preview will start the drag on the top left corner (or top right corner for right to left interfaces). While dragging, iOS will shift the drag preview under the center of the users pointer, so the "pushing away" is short lived on iOS.

1.6.0

Minor Changes

  • #146341 ef9d1cdc6ea92 - The pointerOutsideOfPreview() utility will now correctly push the preview forward in right to left layouts.

    • Left to right (ltr): preview on right hand side of pointer
    • Right to left (rtl): preview on left hand side of pointer (new improvement)

1.5.3

Patch Changes

1.5.2

Patch Changes

  • #128775 7a47573fb87cd - The optional reorder utility is helpful for returning a new reordered array, without modifying the original array. Previously the original array was returned unmodified if an invalid startIndex or finishIndex was provided. reorder now always returns a new array, even when an invalid startIndex or finishIndex is provided for consistency.

    We consider this a bug fix as the reorder function claimed that it returned a new array. Now it always does that.

    Here is how things continue to work for reorder with valid arguments:

    import { reorder } from '@atlaskit/pragmatic-drag-and-drop/reorder';
    
    const original = ['A', 'B'];
    
    const result = reorder({
        list: original,
        // Grab A
        startIndex: 0,
        // Move it to where B is
        finishIndex: 1,
    });
    
    console.log(result); // ['B', 'A']
    console.log(result === original); // false - we got a new array back

    Things were a little different when an invalid startIndex or finishIndex was provided:

    import { reorder } from '@atlaskit/pragmatic-drag-and-drop/reorder';
    
    const original = ['A', 'B'];
    
    const result = reorder({
        list: original,
        startIndex: -1, // invalid start index
        finishIndex: 1,
    });
    
    console.log(result); // ['A', 'B'] (array not reordered)
    
    // Original array was returned for this error case
    console.log(result === original); // true

    When an invalid startIndex or finishIndex is provided, reorder will now return a new array

    import { reorder } from '@atlaskit/pragmatic-drag-and-drop/reorder';
    
    const original = ['A', 'B'];
    
    const result = reorder({
        list: original,
        startIndex: -1, // invalid start index
        finishIndex: 1,
    });
    
    console.log(result); // ['A', 'B'] (array not reordered - unchanged)
    
    // We now return a new array in this case
    console.log(result === original); // false

    In addition to this improvement, we have also improved the clarity of documentation and jsdoc for reorder

1.5.1

Patch Changes

  • #125185 423e7b65d4846 - Fixing an incorrectly exported type name from our external adapter.

    - import type { ElementDropTargetEventBasePayload } from '@atlaskit/pragmatic-drag-and-drop/external/adapter';
    + import type { ExternalDropTargetEventBasePayload } from '@atlaskit/pragmatic-drag-and-drop/external/adapter';

1.5.0

Minor Changes

1.4.0

Minor Changes

  • #145232 04641b5e6ed55 - Adding new optional utility for element dragging: blockDraggingToIFrames which disables the ability for a user to drag into an <iframe> element.

    Scenarios where this can be helpful:

    • When you are shifting the interface around in reponse to a drag operation and you don't want the drag to enter into an <iframe> (for example - when resizing)
    • When you don't want the user to be able to drag into a <iframe> on the page (there could be lots of reasons why!)
    import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
    import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
    import { blockDraggingToIFrames } from '@atlaskit/pragmatic-drag-and-drop/element/block-dragging-to-iframes';
    
    const cleanup = combine(
        blockDraggingToIFrames({ element }),
        draggable({
            element,
        }),
    );

1.3.1

Patch Changes

1.3.0

Minor Changes

  • #128458 71c5224450c8a - Adding workaround for a bug in Firefox. The external adpater optional URL utilities containsURLs and getURLs will now correctly recognize URLs dragged from the Firefox address bar or bookmarks in to a Firefox window.

1.2.3

Patch Changes

  • #123738 abd0776a2a2d5 - Improving react@18 support for setCustomNativeDragPreview. Fixes a bug where preserveOffsetOnSource would always position the top left drag preview under the user's pointer.

    getOffset is now called in the next microtask after setCustomNativeDragPreview:render. This helps ensure that the drag preview element has finished rendering into the container before getOffset is called. Some frameworks like react@18 won't render the element to be used for the drag preview into the container until the next microtask.

1.2.2

Patch Changes

1.2.1

Patch Changes

1.2.0

Minor Changes

  • #116572 98c65e7ff719c - 🍯 Introducing "the honey pot fix" which is an improved workaround for a painful browser bug.

    Background

    The browser bug causes the browser to think the users pointer is continually depressed at the point that the user started a drag. This could lead to incorrect events being triggered, and incorrect styles being applied to elements that the user is not currently over during a drag.

    Outcomes

    • Elements will no longer receive MouseEvents (eg "mouseenter" and "mouseleave") during a drag (which is a violation of the drag and drop specification)
    • Elements will no longer apply :hover or :active styles during a drag. Previously consumers would need to disable these style rules during a drag to prevent these styles being applied.
    • Dramatically improved post drop performance. Our prior solution could require a noticeable delay due to a large style recalculation after a drop.

1.1.12

Patch Changes

1.1.11

Patch Changes

  • #107751 ac9352b7e0ce - Fixing timing issue with preventUnhandled() introduced in the prior release. preventUnhandled.stop() called inside of onDrop() will now correctly cancel a native "drop" event.

1.1.10

Patch Changes

  • #105574 2f5d213b2613 - These fixes only impact situations were you have native drag and drop code in addition to Pragmatic drag and drop running on your page.

    • Fix: if a "drop" is caused by non Pragmatic drag and drop code on the page, then we will no longer cancel the "drop" event.
    • Fix: No longer exposing external adapter data (source.items) in onDrop if not dropping on a Pragmatic drag and drop drop target. Previously, if some non Pragmatic drag and drop code accepted a drop then source.items would be populated. Now all unsuccessful (or un managed) drops are handled consistently.

1.1.9

Patch Changes

1.1.8

Patch Changes

  • #100196 da322bbbe7f5 - Setting sideEffects: true in package.json as a few essential files in core have side effects. Unfortunately we require side effects to work around browser bugs and strangeness 😅.

1.1.7

Patch Changes

  • #95385 c8d2e32f5071 - Minor internal refactor of code concerning entering / leaving a window

1.1.6

Patch Changes

1.1.5

Patch Changes

1.1.4

Patch Changes

1.1.3

Patch Changes

1.1.2

Patch Changes

  • #84047 72a86ac4a940 - Removing experimental DropData from onDrop(). Exposing the native dropEffect turned out to problematic, as you will always get a "none" drop effect if dropping externally if the original draggable was removed (a native "dragend" event is targetted at the original draggable). This made the weak signal of dropEffect for even weaker and more problematic. In order to not create footguns for folks, we have decided to remove this experimental API for now. We can explore adding the API back in the future if folks think it would be valuable.

1.1.1

Patch Changes

  • #83702 4d9e25ab4eaa - Updating the descriptions of Pragmatic drag and drop packages, so they each provide a consistent description to various consumers, and so they are consistently formed amongst each other.

    • package.json description
    • README.md
    • Website documentation

1.1.0

Minor Changes

  • #82653 136d8da5542d - Experimental: Adding additional information to onDrop() events to expose what the final dropEffect was for a drag operation (now removed)

    Fixing a bug where preventUnhandled.start() would prevent unhandled drag operations forever. It now only prevents unhandled drag operations for the current drag operation. preventUnhandled.stop() is now optional, as preventUnhandled.start() now tidies up itself. You can still leverage preventUnhandled.stop() to stop preventing unhandled drag operations during a drag.

    Tightening the getDropEffect() function on drop targets slightly so that "none" cannot be provided. Using "none" as the drop effect would break the expected behaviour for nested drop targets.

1.0.2

Patch Changes

1.0.1

Patch Changes

  • #76476 35148e092790 - Adding warning for test environments to let people know if DragEvents have not been setup correctly.

1.0.0

Major Changes

  • #70616 42e57ea65fee - This is our first major release (1.0) for all Pragmatic drag and drop packages.

    For a detailed explanation of these changes, and how to upgrade (automatically) to 1.0 please see our 1.0 upgrade guide

0.25.0

Minor Changes

  • #59458 7d6a69cfa61c - Adding workaround for Safari bug.

    In Safari (and iOS) if the element used for generating a native drag preview has opacity applied, then the native drag preview can include elements underneath the drag preview element.

    Pragmatic drag and drop now includes a workaround for this Safari bug.

0.24.0

Minor Changes

  • #39935 03b91562fec - Exposing AllDragTypes type. This was previously an internal type, but it provided helpful to expose for our new auto scroller. AllDragTypes is helpful if you need a function to work with either element or file drag operations.

0.23.0

Minor Changes

  • #38713 3da89e29dfc - We have renamed and tweaked the recently added setCustomNativeDragPreview getOffset utility preserveOffsetFromPointer to be a bit easier to understand what it is doing.

    - import { preserveOffsetFromPointer } from '@atlaskit/pragmatic-drag-and-drop/util/preserve-offset-from-pointer';
    + import { preserveOffsetOnSource } from '@atlaskit/pragmatic-drag-and-drop/util/preserve-offset-on-source';
    
    draggable({
      element: myElement,
      onGenerateDragPreview: ({ nativeSetDragImage, location, source }) => {
        setCustomNativeDragPreview({
    -      getOffset: preserveOffsetFromPointer({
    +      'preserveOffsetOnSource' is a more accurate description of what is being achieved
    +      getOffset: preserveOffsetOnSource({
    -        sourceElement: source.element,
    +        // no longer including 'source' in argument name
    +        // as it is implied by the function name
    +        element: source.element,
            input: location.current.input,
          }),
          render: function render({ container }) {
            /* ... */
          },
          nativeSetDragImage,
        });
      },
    });

0.22.0

Minor Changes

  • #38397 d644a68ddf6 - Added a new setCustomNativeDragPreview getOffset utility: preserveOffsetFromPointer. preserveOffsetFromPointer mimics the default behaviour for non custom drag previews when starting a drag: the initial cursor position offset is preserved for a seamless drag and drop experience.

    import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
    import { preserveOffsetFromPointer } from '@atlaskit/pragmatic-drag-and-drop/util/preserve-offset-from-pointer';
    
    draggable({
        element: myElement,
        onGenerateDragPreview: ({ nativeSetDragImage, location, source }) => {
            setCustomNativeDragPreview({
                getOffset: preserveOffsetFromPointer({
                    sourceElement: source.element,
                    input: location.current.input,
                }),
                render: function render({ container }) {
                    /* ... */
                },
                nativeSetDragImage,
            });
        },
    });

0.21.0

Minor Changes

  • #38525 de7463c7096 - Exposing some additional TypeScript types. These can be helpful when creating helper packages.

    import type {
        // These types are not needed for consumers
        // They are mostly helpful for other packages
        AllDragTypes,
        MonitorArgs,
        BaseEventPayload,
    } from '@atlaskit/pragmatic-drag-and-drop/types';
    • AllDragTypes: representation of all entities types in the system (eg element and file)
    • MonitorArgs<DragType extends AllDragTypes>: the arguments that can be passed to a monitor
    • BaseEventPayload<DragType extends AllDragTypes>: the shared properties in all events

0.20.0

Minor Changes

  • #38453 554a6d8cc34 - ### Stickiness algorithm improvement

    We have made some improvements to the drop target stickiness algorithm to allow sticky drop targets that are no longer dragged over to cancel their stickiness.

    Stickiness is no longer maintained when a sticky drop target states it cannot be dropped on

    Scenario: [A(sticky)][] + A:canDrop() returns false Result: []

    Stickiness is no longer maintained when a sticky drop start states it is no longer sticky

    Scenario: [A(sticky)][] + A:getIsSticky() returns false Result: []

    Stickiness is no longer maintained when a sticky drop start is unmounted

    Scenario: [A(sticky)][] + A is unmounted Result: []

    To help facilitate this change:

    • getIsSticky() is now only called when an drop target is a potential candidate for stickiness (previously it was called repeatedly)
    • getIsSticky() and canDrop() are called on drop targets that are no longer being dragged over, but are candidates for stickiness

    Change to DropTargetRecord type

    Previously, the DropTargetRecord type had a property called sticky which would represent whether the drop target was registering itself as sticky via getIsSticky(). Knowing sticky is not overly helpful given that we now regularly recompute stickiness and a drop target can change disable stickiness after it is applied.

    What is helpful, is knowing whether a drop target is active because of stickiness. So we have removed sticky and added isActiveDueToStickiness to the DropTargetRecord type.

    type DropTargetRecord = {
      element: Element;
      data: Record<string | symbol, unknown>;
      dropEffect: DataTransfer['dropEffect'];
    -  sticky: boolean;
    +  isActiveDueToStickiness: boolean;
    };

0.19.0

Minor Changes

  • #35574 8c301a251e4 - We have changed the API of setCustomNativeDragPreview() to allow increased control and slightly lower bundles as well.

    We have removed the placement argument, and replaced it with getOffset().

    - placement: { type: 'center' } | { type: 'offset-from-pointer'; x: CSSValue; y: CSSValue };
    + getOffset: (args: { container: HTMLElement }) => {x: number, y: number}

    getOffset() allows unlimited control over how to place the custom native drag preview relative to the users pointer. Please see our updated documentation for detailed information about the new getOffset() API. Our new getOffset() approach means that we also no longer need to bake in all placement options into the bundle - consumers now only pay for what they use!

    placement: { type: 'offset-from-pointer' } has been replaced by offsetFromPointer()

    import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
    + import { offsetFromPointer } from '@atlaskit/pragmatic-drag-and-drop/util/offset-from-pointer;
    
    draggable({
      element: myElement,
      onGenerateDragPreview: ({ nativeSetDragImage }) => {
        setCustomNativeDragPreview({
    -      placement: { type: 'offset-from-pointer', x: '16px', y: '8px' }
    +      getOffset: offsetFromPointer({x: '16px', y: '8px'}),
          render: function render({ container }) {
            ReactDOM.render(<Preview item={item} />, container);
            return function cleanup() {
              ReactDOM.unmountComponentAtNode(container);
            };
          },
          nativeSetDragImage,
        });
      },
    });

    placement: { type: 'center' } has been replaced by centerUnderPointer()

    import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
    + import { centerUnderPointer } from '@atlaskit/pragmatic-drag-and-drop/util/center-under-pointer-pointer;
    
    draggable({
      element: myElement,
      onGenerateDragPreview: ({ nativeSetDragImage }) => {
        setCustomNativeDragPreview({
    -      placement: { type: 'center' }
    +      getOffset: centerUnderPointer,
          render: function render({ container }) {
            ReactDOM.render(<Preview item={item} />, container);
            return function cleanup() {
              ReactDOM.unmountComponentAtNode(container);
            };
          },
          nativeSetDragImage,
        });
      },
    });

0.18.2

Patch Changes

0.18.1

Patch Changes

0.18.0

Minor Changes

0.17.0

Minor Changes

  • #33262 34ed7b2ec63 - We have changed the name of our drag and drop packages to align on the single name of "Pragmatic drag and drop"

    - @atlaskit/drag-and-drop
    + @atlaskit/pragmatic-drag-and-drop
    
    - @atlaskit/drag-and-drop-autoscroll
    + @atlaskit/pragmatic-drag-and-drop-autoscroll
    
    - @atlaskit/drag-and-drop-hitbox
    + @atlaskit/pragmatic-drag-and-drop-hitbox
    
    - @atlaskit/drag-and-drop-indicator
    + @atlaskit/pragmatic-drag-and-drop-react-indicator
    # Note: `react` was added to this package name as our indicator package is designed for usage with `react`.
    
    - @atlaskit/drag-and-drop-live-region
    + @atlaskit/pragmatic-drag-and-drop-live-region
    
    - @atlaskit/drag-and-drop-react-beautiful-dnd-migration
    + @atlaskit/pragmatic-drag-and-drop-react-beautiful-dnd-migration
    
    - @atlaskit/drag-and-drop-docs
    + @atlaskit/pragmatic-drag-and-drop-docs

    The new @atlaskit/pragmatic-drag-and-drop* packages will start their initial versions from where the @atlaskit/drag-and-drop*` packages left off. Doing this will make it easier to look back on changelogs and see how the packages have progressed.

0.16.0

Minor Changes

0.15.1

Patch Changes

  • #32424 2e01c9c74b5 - DUMMY remove before merging to master; dupe adf-schema via adf-utils

0.15.0

Minor Changes

0.14.0

Minor Changes

  • #31794 eab6d26451d - Improving the resilience of our workaround for a Browser bug where after a drag finishes, an unrelated element can be entered into.
  • ba7ea570aee - > Both of these changes should not impact most consumers as they are targeted at edge cases.

    • Fix: We no longer extract user input (eg clientX) from native "dragleave" events due to a Bug with Chrome we discovered. Due to this bug, it was possible for location.current.input to be incorrectly set in onDropTargetChange and onDrop when a user was cancelling a drag or dropping or no drop targets.

    • Fix: location.previous.dropTargets should always point to the location.current.dropTargets value from the previous event (exception: onGenerateDragPreview and onDragStart have the same location.previous and location.current values). Previously, the location.previous.dropTargets value did not match the last events location.current.dropTargets value in onDrop. onDrop() would incorrectly use the location.current and location.previous values from the last event rather than creating a new location.current entry. Now, onDrop(), location.previous.dropTargets points to the location.current.dropTargets from the last event (same as all other events) and location.current.dropTargets points to what the previous drop target was as well (no change)

0.13.0

Minor Changes

0.12.0

Minor Changes

  • #30953 90901f5bbe0 - Replace default entry point of undefined with {}.

    NOTE: Importing from the default entry point isn't supported. Please use individual entry points in order to always obtain minimum kbs.

0.11.0

Minor Changes

  • #30668 1ecbb19d450 - Adding a new function to make creating custom native drag previews safe and easy: setCustomNativeDragPreview

    import { setCustomNativeDragPreview } from '@atlaskit/drag-and-drop/util/set-custom-native-drag-preview';
    
    draggable({
        element: myElement,
        onGenerateDragPreview: ({ nativeSetDragImage }) => {
            setCustomNativeDragPreview({
                render: function render({ container }) {
                    ReactDOM.render(<Preview item={item} />, container);
                    return function cleanup() {
                        ReactDOM.unmountComponentAtNode(container);
                    };
                },
                nativeSetDragImage,
            });
        },
    });

    Please see our element adapter documentation for more detailed usage information

0.10.0

Minor Changes

  • #29951 9c0975e2fab - Bug fix: A monitor should not be called after it is removed. Previously, if a monitor (monitor 1) removed another monitor (monitor 2) for the same event, then the second monitor (monitor 2) would still be called. This has been fixed

    const cleanupMonitor1 = monitorForElements({
        onDragStart: () => {
            cleanupMonitor2();
        },
    });
    const cleanupMonitor2 = monitorForElements({
        // Previously this `onDragStart` would have been called during `onDragStart` even though it was unbound by the first monitor
        onDragStart: () => {},
    });

0.9.0

Minor Changes

  • #29651 03e0aa5ae85 - @atlaskit/drag-and-drop adds event listeners to the window during a drag operation. These drag operation event listeners were bubble phase event listeners, but they are now capture phase event listeners to be more resliant against external code (incorrectly) stopping events.

    This does not impact the ability of a consumer to have their own draggables on a page not controlled by @atlaskit/drag-and-drop

0.8.1

Patch Changes

  • #28324 6455cf006b3 - Builds for this package now pass through a tokens babel plugin, removing runtime invocations of the tokens() function and improving performance.

0.8.0

Minor Changes

  • #26317 1e3f9743e57 - A monitor that is added during an event (eg onDragStart) will no longer be called for the current event. This is to prevent the accidental creation of infinite loops. This behaviour matches native EventTargets where an event listener cannot add another event listener during an active event to the same event target in the same event phase.

0.7.1

Patch Changes

0.7.0

Minor Changes

0.6.0

Minor Changes

0.5.0

Minor Changes

  • #25007 17950433a70 - Touching package to release re-release previous version. The previous (now deprecated) version did not have it's entry points built correctly

0.4.0

Minor Changes

0.3.0

Minor Changes

  • #24810 52403a2c11f - Adding a canMonitor() function to monitors to allow a monitor to conditionally apply to a drag operation.

    monitorForElements({
        canMonitor: ({ source }) => source.data.type === 'card',
        onDragStart: () => console.log('I will only be activated when dragging a card!'),
    });

0.2.0

Minor Changes

  • #24613 1cf9e484b4b - We have improved our naming consistency across our drag and drop packages.

    • @atlaskit/drag-and-drop/util/cancel-unhandled has been renamed to @atlaskit/drag-and-drop/addon/cancel-unhandled

0.1.0

Minor Changes

0.0.1

Patch Changes