Core
The core package for Pragmatic drag and drop - enabling fast drag and drop for any experience on any tech stack
yarn add @atlaskit/pragmatic-drag-and-drop
The core package for Pragmatic drag and drop - enabling fast drag and drop for any experience on any tech stack
yarn add @atlaskit/pragmatic-drag-and-drop
#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:
<iframe>
(for example - when resizing)<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,
}),
);
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
.#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
.
58941fa1d332a
-
All react
unit tests will now run against react@16
and react@18
on CI.#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
MouseEvent
s (eg "mouseenter"
and "mouseleave"
) during a
drag (which is a violation of the
drag and drop specification):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.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.#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.
"drop"
is caused by non Pragmatic drag and drop code on the page, then we will no
longer cancel the "drop"
event.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.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 😅.c8d2e32f5071
-
Minor internal refactor of code concerning entering / leaving a window140fc0d20c02
-
Fixing our Safari workaround in setCustomNativeDragPreview()
for a
Safari drag preview bug so that it works
correctly for react@18+
usage.35fd5ed8e1d7
-
Upgrading internal dependency bind-event-listener
to @^3.0.0
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.#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
#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.
35148e092790
-
Adding warning for test environments to let people know if DragEvents have not been setup
correctly.#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
#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.
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.#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,
});
},
});
#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,
});
},
});
#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 monitorBaseEventPayload<DragType extends AllDragTypes>
: the shared properties in all events#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()
returnsfalse
Result:[]
Stickiness is no longer maintained when a sticky drop start states it is no longer sticky
Scenario:
[A(sticky)]
→[]
+A:getIsSticky()
returnsfalse
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 stickinessDropTargetRecord
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;
};
#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,
});
},
});
#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.
2e01c9c74b5
- DUMMY
remove before merging to master; dupe adf-schema via adf-utils#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)
#30879
2582df26509
- Fixing a
browser bug where after a drag finishes, a unrelated element can be entered into by the browser
#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.
#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
#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: () => {},
});
#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 draggable
s on a page not
controlled by @atlaskit/drag-and-drop
6455cf006b3
- Builds
for this package now pass through a tokens babel plugin, removing runtime invocations of the
tokens() function and improving performance.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.17950433a70
- Touching
package to release re-release previous version. The previous (now deprecated) version did not have
it's entry points built correctly4d739042b04
-
Improving jsdoc auto complete information for GetFeedbackArgs
#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!'),
});
#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