@atlaskit/pragmatic-drag-and-drop
Advanced tools
Comparing version 1.0.2 to 1.1.0
# @atlaskit/pragmatic-drag-and-drop | ||
## 1.1.0 | ||
### Minor Changes | ||
- [#82653](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/82653) [`136d8da5542d`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/136d8da5542d) - Adding additional information to `onDrop()` events to expose what the final `dropEffect` was for a drag operation. | ||
```ts | ||
type DropData = { | ||
dropEffect: DataTransfer['dropEffect']; | ||
}; | ||
monitorForElements({ | ||
onDrop(payload) { | ||
const drop: DropData = payload.drop; | ||
}, | ||
}); | ||
``` | ||
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 | ||
@@ -4,0 +26,0 @@ |
@@ -115,2 +115,3 @@ "use strict"; | ||
var current = _ref5.current, | ||
drop = _ref5.drop, | ||
updatedSourcePayload = _ref5.updatedSourcePayload; | ||
@@ -122,2 +123,3 @@ dragStart.flush(); | ||
payload: { | ||
drop: drop, | ||
source: updatedSourcePayload !== null && updatedSourcePayload !== void 0 ? updatedSourcePayload : source, | ||
@@ -124,0 +126,0 @@ location: { |
@@ -15,5 +15,7 @@ "use strict"; | ||
var _dispatchConsumerEvent = require("./dispatch-consumer-event"); | ||
var isActive = false; | ||
var globalState = { | ||
isActive: false | ||
}; | ||
function canStart() { | ||
return !isActive; | ||
return !globalState.isActive; | ||
} | ||
@@ -51,3 +53,2 @@ function getNativeSetDragImage(event) { | ||
} | ||
isActive = true; | ||
var initial = getStartLocation({ | ||
@@ -58,5 +59,9 @@ event: event, | ||
}); | ||
var current = initial; | ||
globalState.isActive = true; | ||
var state = { | ||
current: initial | ||
}; | ||
// Setting initial drop effect for the drag | ||
setDropEffect({ | ||
setDropEffectOnEvent({ | ||
event: event, | ||
@@ -73,3 +78,3 @@ current: initial.dropTargets | ||
var hasChanged = hasHierarchyChanged({ | ||
current: current.dropTargets, | ||
current: state.current.dropTargets, | ||
next: next.dropTargets | ||
@@ -81,6 +86,6 @@ }); | ||
// Consumers can get the latest data by using `onDrag` | ||
current = next; | ||
state.current = next; | ||
if (hasChanged) { | ||
dispatch.dragUpdate({ | ||
current: current | ||
current: state.current | ||
}); | ||
@@ -95,3 +100,3 @@ } | ||
source: dragType.payload, | ||
current: current.dropTargets | ||
current: state.current.dropTargets | ||
}); | ||
@@ -101,3 +106,3 @@ if (nextDropTargets.length) { | ||
event.preventDefault(); | ||
setDropEffect({ | ||
setDropEffectOnEvent({ | ||
event: event, | ||
@@ -112,18 +117,3 @@ current: nextDropTargets | ||
} | ||
function onDrop(args) { | ||
// When dropping something native, we need to extract the latest | ||
// `.items` from the "drop" event as it is now accessible | ||
if (args.type === 'success' && dragType.type === 'external') { | ||
dispatch.drop({ | ||
current: current, | ||
updatedSourcePayload: dragType.getDropPayload(args.event) | ||
}); | ||
return; | ||
} | ||
dispatch.drop({ | ||
current: current, | ||
updatedSourcePayload: null | ||
}); | ||
} | ||
function cancel() { | ||
function cancel(drop) { | ||
// The spec behaviour is that when a drag is cancelled, or when dropping on no drop targets, | ||
@@ -137,10 +127,12 @@ // a "dragleave" event is fired on the active drop target before a "dragend" event. | ||
if (current.dropTargets.length) { | ||
if (state.current.dropTargets.length) { | ||
updateDropTargets({ | ||
dropTargets: [], | ||
input: current.input | ||
input: state.current.input | ||
}); | ||
} | ||
onDrop({ | ||
type: 'cancel' | ||
dispatch.drop({ | ||
current: state.current, | ||
drop: drop, | ||
updatedSourcePayload: null | ||
}); | ||
@@ -150,3 +142,3 @@ finish(); | ||
function finish() { | ||
isActive = false; | ||
globalState.isActive = false; | ||
unbindEvents(); | ||
@@ -176,3 +168,3 @@ } | ||
dispatch.drag({ | ||
current: current | ||
current: state.current | ||
}); | ||
@@ -184,9 +176,2 @@ } | ||
}, { | ||
// This was the only reliable cross browser way I found to detect | ||
// when the user is leaving the `window`. | ||
// Internal drags: when we leave the `window` we want to clear any active drop targets, | ||
// but the drag is not yet over. The user could drag back into the window. | ||
// We only need to do this because of stickiness | ||
// External drags: when we leave the `window` the drag operation is over, | ||
// we will start another drag operation | ||
type: 'dragleave', | ||
@@ -200,23 +185,51 @@ listener: function listener(event) { | ||
// When a drag is ending without a drop target (or when the drag is cancelled), | ||
// All browsers fire: | ||
// 1. "drag" | ||
// 2. "dragleave" | ||
// These events have `event.relatedTarget == null` so this code path is also hit in those cases. | ||
// This is all good! We would be clearing the dropTargets in `cancel()` after the "dragend" | ||
/** | ||
* At this point we don't know if a drag is being cancelled, | ||
* or if a drag is leaving the `window`. | ||
* | ||
* Both have: | ||
* 1. "dragleave" (with `relatedTarget: null`) | ||
* 2. "dragend" (a "dragend" can occur when outside the `window`) | ||
* | ||
* **Clearing drop targets** | ||
* | ||
* For either case we are clearing the the drop targets | ||
* | ||
* - cancelling: we clear drop targets in `"dragend"` anyway | ||
* - leaving the `window`: we clear the drop targets (to clear stickiness) | ||
* | ||
* **Leaving the window and finishing the drag** | ||
* | ||
* _internal drags_ | ||
* | ||
* - The drag continues when the user is outside the `window` | ||
* and can resume if the user drags back over the `window`, | ||
* or end when the user drops in an external `window`. | ||
* - We will get a `"dragend"`, or we can listen for other | ||
* events to determine the drag is finished when the user re-enters the `window`). | ||
* | ||
* _external drags_ | ||
* | ||
* - We conclude the drag operation. | ||
* - We have no idea if the user will drag back over the `window`, | ||
* or if the drag ends elsewhere. | ||
* - We will create a new drag if the user re-enters the `window`. | ||
* | ||
* **Not updating `input`** | ||
* | ||
* 🐛 Bug[Chrome] the final `"dragleave"` has default input values (eg `clientX == 0`) | ||
* Workaround: intentionally not updating `input` in "dragleave" | ||
* rather than the users current input values | ||
* - [Conversation](https://twitter.com/alexandereardon/status/1642697633864241152) | ||
* - [Bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1429937) | ||
**/ | ||
// 🐛 Bug workaround: intentionally not updating `input` in "dragleave" | ||
// In Chrome, this final "dragleave" has default input values (eg clientX == 0) | ||
// rather than the users current input values | ||
// | ||
// - [Conversation](https://twitter.com/alexandereardon/status/1642697633864241152) | ||
// - [Bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1429937) | ||
updateDropTargets({ | ||
input: current.input, | ||
input: state.current.input, | ||
dropTargets: [] | ||
}); | ||
// End the drag operation if a native drag is leaving the window | ||
if (dragType.startedFrom === 'external') { | ||
cancel(); | ||
cancel({ | ||
dropEffect: 'none' | ||
}); | ||
} | ||
@@ -227,15 +240,24 @@ } | ||
listener: function listener(event) { | ||
var _event$dataTransfer$d, _event$dataTransfer; | ||
// A "drop" can only happen if the browser allowed the drop | ||
// Opting out of standard browser drop behaviour for the drag | ||
// Accepting drop operation. | ||
// Also: opting out of standard browser drop behaviour for the drag | ||
event.preventDefault(); | ||
// applying the latest drop effect to the event | ||
setDropEffect({ | ||
setDropEffectOnEvent({ | ||
event: event, | ||
current: current.dropTargets | ||
current: state.current.dropTargets | ||
}); | ||
onDrop({ | ||
type: 'success', | ||
event: event | ||
dispatch.drop({ | ||
current: state.current, | ||
drop: { | ||
// At this point the dropEffect has been set on the event | ||
// (if we have set it), so we can read it from there | ||
dropEffect: (_event$dataTransfer$d = (_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.dropEffect) !== null && _event$dataTransfer$d !== void 0 ? _event$dataTransfer$d : 'none' | ||
}, | ||
// When dropping something native, we need to extract the latest | ||
// `.items` from the "drop" event as it is now accessible | ||
updatedSourcePayload: dragType.type === 'external' ? dragType.getDropPayload(event) : null | ||
}); | ||
@@ -248,3 +270,3 @@ finish(); | ||
(0, _fixPostDragPointerBug.fixPostDragPointerBug)({ | ||
current: current | ||
current: state.current | ||
}); | ||
@@ -256,8 +278,20 @@ } | ||
// when the drag is finished. | ||
// "dragend" will fire after "drop"(if there was a successful drop) | ||
// "dragend" will fire after "drop" (if there was a successful drop) | ||
// "dragend" does not fire if the draggable source has been removed during the drag | ||
// or for external drag sources (eg files) | ||
// This "dragend" listener will not fire if there was a successful drop | ||
// as we will have already removed the event listener | ||
type: 'dragend', | ||
listener: function listener() { | ||
cancel(); | ||
listener: function listener(event) { | ||
var _event$dataTransfer$d2, _event$dataTransfer2; | ||
// The `dropEffect` will be: | ||
// - "none" if dropped on no drop targets | ||
// - "none" if cancelled locally | ||
// - "none" if cancelled externally | ||
// - "none" if `preventUnhandled` is used (and there is no drop target) | ||
// - [not "none"] if accepted externally | ||
cancel({ | ||
dropEffect: (_event$dataTransfer$d2 = (_event$dataTransfer2 = event.dataTransfer) === null || _event$dataTransfer2 === void 0 ? void 0 : _event$dataTransfer2.dropEffect) !== null && _event$dataTransfer$d2 !== void 0 ? _event$dataTransfer$d2 : 'none' | ||
}); | ||
@@ -268,3 +302,3 @@ // Applying this fix after `dispatch.drop` so that frameworks have the opportunity | ||
(0, _fixPostDragPointerBug.fixPostDragPointerBug)({ | ||
current: current | ||
current: state.current | ||
}); | ||
@@ -274,3 +308,7 @@ } | ||
}].concat((0, _toConsumableArray2.default)((0, _detectBrokenDrag.getBindingsForBrokenDrags)({ | ||
onDragEnd: cancel | ||
onDragEnd: function onDragEnd() { | ||
return cancel({ | ||
dropEffect: 'none' | ||
}); | ||
} | ||
}))), | ||
@@ -288,3 +326,3 @@ // Once we have started a managed drag operation it is important that we see / own all drag events | ||
} | ||
function setDropEffect(_ref3) { | ||
function setDropEffectOnEvent(_ref3) { | ||
var _current$; | ||
@@ -291,0 +329,0 @@ var event = _ref3.event, |
"use strict"; | ||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); | ||
Object.defineProperty(exports, "__esModule", { | ||
@@ -7,6 +8,7 @@ value: true | ||
exports.preventUnhandled = void 0; | ||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); | ||
var _bindEventListener = require("bind-event-listener"); | ||
function cancel(event) { | ||
// if `@atlaskit/pragmatic-drag-and-drop` has already prevented the event | ||
// we don't need to do anything | ||
var _detectBrokenDrag = require("../util/detect-broken-drag"); | ||
function acceptDrop(event) { | ||
// if the event is already prevented the event we don't need to do anything | ||
if (event.defaultPrevented) { | ||
@@ -18,3 +20,3 @@ return; | ||
// on the page | ||
// Note: using "none" will not allow a drop to occur, so we are using "move" | ||
// Note: using "none" will not allow a "drop" to occur, so we are using "move" | ||
if (event.dataTransfer) { | ||
@@ -31,22 +33,53 @@ event.dataTransfer.dropEffect = 'move'; | ||
*/ | ||
function start() { | ||
cleanup(); | ||
unbindEvents = (0, _bindEventListener.bindAll)(window, [{ | ||
type: 'dragover', | ||
listener: acceptDrop | ||
}, { | ||
type: 'dragenter', | ||
listener: acceptDrop | ||
}, { | ||
type: 'drop', | ||
listener: function listener(event) { | ||
// our lifecycle manager already prevents events, but just being super safe | ||
event.preventDefault(); | ||
// not setting dropEffect, as `drop.dropEffect` has already been published to the user | ||
// (lifecycle-manager binds events in the capture phase) | ||
// we don't need to wait for "dragend", and "dragend" might not even happen, | ||
// such as when the draggable has been removed during a drag. | ||
cleanup(); | ||
} | ||
}, { | ||
type: 'dragend', | ||
listener: cleanup | ||
}].concat((0, _toConsumableArray2.default)((0, _detectBrokenDrag.getBindingsForBrokenDrags)({ | ||
onDragEnd: cleanup | ||
}))), | ||
// being clear that these are added in the bubble phase | ||
{ | ||
capture: false | ||
}); | ||
} | ||
function cleanup() { | ||
var _unbindEvents; | ||
(_unbindEvents = unbindEvents) === null || _unbindEvents === void 0 || _unbindEvents(); | ||
unbindEvents = null; | ||
} | ||
/** | ||
* TODO: for next major, we could look at do the following: | ||
* | ||
* ```diff | ||
* - preventUnhandled.start(); | ||
* - preventUnhandled.stop(); | ||
* + const stop = preventUnhandled(); | ||
* ``` | ||
*/ | ||
var preventUnhandled = exports.preventUnhandled = { | ||
start: function start() { | ||
var _unbindEvents; | ||
(_unbindEvents = unbindEvents) === null || _unbindEvents === void 0 || _unbindEvents(); | ||
unbindEvents = (0, _bindEventListener.bindAll)(window, [{ | ||
type: 'dragover', | ||
listener: cancel | ||
}, { | ||
type: 'dragenter', | ||
listener: cancel | ||
}, { | ||
type: 'drop', | ||
listener: cancel | ||
}]); | ||
}, | ||
stop: function stop() { | ||
var _unbindEvents2; | ||
(_unbindEvents2 = unbindEvents) === null || _unbindEvents2 === void 0 || _unbindEvents2(); | ||
unbindEvents = null; | ||
} | ||
start: start, | ||
stop: cleanup | ||
}; |
@@ -110,2 +110,3 @@ import rafSchd from 'raf-schd'; | ||
current, | ||
drop, | ||
updatedSourcePayload | ||
@@ -118,2 +119,3 @@ }) { | ||
payload: { | ||
drop, | ||
source: updatedSourcePayload !== null && updatedSourcePayload !== void 0 ? updatedSourcePayload : source, | ||
@@ -120,0 +122,0 @@ location: { |
@@ -7,5 +7,7 @@ import { bindAll } from 'bind-event-listener'; | ||
import { makeDispatch } from './dispatch-consumer-event'; | ||
let isActive = false; | ||
const globalState = { | ||
isActive: false | ||
}; | ||
function canStart() { | ||
return !isActive; | ||
return !globalState.isActive; | ||
} | ||
@@ -45,3 +47,2 @@ function getNativeSetDragImage(event) { | ||
} | ||
isActive = true; | ||
const initial = getStartLocation({ | ||
@@ -52,5 +53,9 @@ event, | ||
}); | ||
let current = initial; | ||
globalState.isActive = true; | ||
const state = { | ||
current: initial | ||
}; | ||
// Setting initial drop effect for the drag | ||
setDropEffect({ | ||
setDropEffectOnEvent({ | ||
event, | ||
@@ -67,3 +72,3 @@ current: initial.dropTargets | ||
const hasChanged = hasHierarchyChanged({ | ||
current: current.dropTargets, | ||
current: state.current.dropTargets, | ||
next: next.dropTargets | ||
@@ -75,6 +80,6 @@ }); | ||
// Consumers can get the latest data by using `onDrag` | ||
current = next; | ||
state.current = next; | ||
if (hasChanged) { | ||
dispatch.dragUpdate({ | ||
current | ||
current: state.current | ||
}); | ||
@@ -89,3 +94,3 @@ } | ||
source: dragType.payload, | ||
current: current.dropTargets | ||
current: state.current.dropTargets | ||
}); | ||
@@ -95,3 +100,3 @@ if (nextDropTargets.length) { | ||
event.preventDefault(); | ||
setDropEffect({ | ||
setDropEffectOnEvent({ | ||
event, | ||
@@ -106,18 +111,3 @@ current: nextDropTargets | ||
} | ||
function onDrop(args) { | ||
// When dropping something native, we need to extract the latest | ||
// `.items` from the "drop" event as it is now accessible | ||
if (args.type === 'success' && dragType.type === 'external') { | ||
dispatch.drop({ | ||
current, | ||
updatedSourcePayload: dragType.getDropPayload(args.event) | ||
}); | ||
return; | ||
} | ||
dispatch.drop({ | ||
current, | ||
updatedSourcePayload: null | ||
}); | ||
} | ||
function cancel() { | ||
function cancel(drop) { | ||
// The spec behaviour is that when a drag is cancelled, or when dropping on no drop targets, | ||
@@ -131,10 +121,12 @@ // a "dragleave" event is fired on the active drop target before a "dragend" event. | ||
if (current.dropTargets.length) { | ||
if (state.current.dropTargets.length) { | ||
updateDropTargets({ | ||
dropTargets: [], | ||
input: current.input | ||
input: state.current.input | ||
}); | ||
} | ||
onDrop({ | ||
type: 'cancel' | ||
dispatch.drop({ | ||
current: state.current, | ||
drop, | ||
updatedSourcePayload: null | ||
}); | ||
@@ -144,3 +136,3 @@ finish(); | ||
function finish() { | ||
isActive = false; | ||
globalState.isActive = false; | ||
unbindEvents(); | ||
@@ -170,3 +162,3 @@ } | ||
dispatch.drag({ | ||
current | ||
current: state.current | ||
}); | ||
@@ -178,9 +170,2 @@ } | ||
}, { | ||
// This was the only reliable cross browser way I found to detect | ||
// when the user is leaving the `window`. | ||
// Internal drags: when we leave the `window` we want to clear any active drop targets, | ||
// but the drag is not yet over. The user could drag back into the window. | ||
// We only need to do this because of stickiness | ||
// External drags: when we leave the `window` the drag operation is over, | ||
// we will start another drag operation | ||
type: 'dragleave', | ||
@@ -194,23 +179,51 @@ listener(event) { | ||
// When a drag is ending without a drop target (or when the drag is cancelled), | ||
// All browsers fire: | ||
// 1. "drag" | ||
// 2. "dragleave" | ||
// These events have `event.relatedTarget == null` so this code path is also hit in those cases. | ||
// This is all good! We would be clearing the dropTargets in `cancel()` after the "dragend" | ||
/** | ||
* At this point we don't know if a drag is being cancelled, | ||
* or if a drag is leaving the `window`. | ||
* | ||
* Both have: | ||
* 1. "dragleave" (with `relatedTarget: null`) | ||
* 2. "dragend" (a "dragend" can occur when outside the `window`) | ||
* | ||
* **Clearing drop targets** | ||
* | ||
* For either case we are clearing the the drop targets | ||
* | ||
* - cancelling: we clear drop targets in `"dragend"` anyway | ||
* - leaving the `window`: we clear the drop targets (to clear stickiness) | ||
* | ||
* **Leaving the window and finishing the drag** | ||
* | ||
* _internal drags_ | ||
* | ||
* - The drag continues when the user is outside the `window` | ||
* and can resume if the user drags back over the `window`, | ||
* or end when the user drops in an external `window`. | ||
* - We will get a `"dragend"`, or we can listen for other | ||
* events to determine the drag is finished when the user re-enters the `window`). | ||
* | ||
* _external drags_ | ||
* | ||
* - We conclude the drag operation. | ||
* - We have no idea if the user will drag back over the `window`, | ||
* or if the drag ends elsewhere. | ||
* - We will create a new drag if the user re-enters the `window`. | ||
* | ||
* **Not updating `input`** | ||
* | ||
* 🐛 Bug[Chrome] the final `"dragleave"` has default input values (eg `clientX == 0`) | ||
* Workaround: intentionally not updating `input` in "dragleave" | ||
* rather than the users current input values | ||
* - [Conversation](https://twitter.com/alexandereardon/status/1642697633864241152) | ||
* - [Bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1429937) | ||
**/ | ||
// 🐛 Bug workaround: intentionally not updating `input` in "dragleave" | ||
// In Chrome, this final "dragleave" has default input values (eg clientX == 0) | ||
// rather than the users current input values | ||
// | ||
// - [Conversation](https://twitter.com/alexandereardon/status/1642697633864241152) | ||
// - [Bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1429937) | ||
updateDropTargets({ | ||
input: current.input, | ||
input: state.current.input, | ||
dropTargets: [] | ||
}); | ||
// End the drag operation if a native drag is leaving the window | ||
if (dragType.startedFrom === 'external') { | ||
cancel(); | ||
cancel({ | ||
dropEffect: 'none' | ||
}); | ||
} | ||
@@ -221,15 +234,24 @@ } | ||
listener(event) { | ||
var _event$dataTransfer$d, _event$dataTransfer; | ||
// A "drop" can only happen if the browser allowed the drop | ||
// Opting out of standard browser drop behaviour for the drag | ||
// Accepting drop operation. | ||
// Also: opting out of standard browser drop behaviour for the drag | ||
event.preventDefault(); | ||
// applying the latest drop effect to the event | ||
setDropEffect({ | ||
setDropEffectOnEvent({ | ||
event, | ||
current: current.dropTargets | ||
current: state.current.dropTargets | ||
}); | ||
onDrop({ | ||
type: 'success', | ||
event | ||
dispatch.drop({ | ||
current: state.current, | ||
drop: { | ||
// At this point the dropEffect has been set on the event | ||
// (if we have set it), so we can read it from there | ||
dropEffect: (_event$dataTransfer$d = (_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.dropEffect) !== null && _event$dataTransfer$d !== void 0 ? _event$dataTransfer$d : 'none' | ||
}, | ||
// When dropping something native, we need to extract the latest | ||
// `.items` from the "drop" event as it is now accessible | ||
updatedSourcePayload: dragType.type === 'external' ? dragType.getDropPayload(event) : null | ||
}); | ||
@@ -242,3 +264,3 @@ finish(); | ||
fixPostDragPointerBug({ | ||
current | ||
current: state.current | ||
}); | ||
@@ -250,8 +272,20 @@ } | ||
// when the drag is finished. | ||
// "dragend" will fire after "drop"(if there was a successful drop) | ||
// "dragend" will fire after "drop" (if there was a successful drop) | ||
// "dragend" does not fire if the draggable source has been removed during the drag | ||
// or for external drag sources (eg files) | ||
// This "dragend" listener will not fire if there was a successful drop | ||
// as we will have already removed the event listener | ||
type: 'dragend', | ||
listener() { | ||
cancel(); | ||
listener(event) { | ||
var _event$dataTransfer$d2, _event$dataTransfer2; | ||
// The `dropEffect` will be: | ||
// - "none" if dropped on no drop targets | ||
// - "none" if cancelled locally | ||
// - "none" if cancelled externally | ||
// - "none" if `preventUnhandled` is used (and there is no drop target) | ||
// - [not "none"] if accepted externally | ||
cancel({ | ||
dropEffect: (_event$dataTransfer$d2 = (_event$dataTransfer2 = event.dataTransfer) === null || _event$dataTransfer2 === void 0 ? void 0 : _event$dataTransfer2.dropEffect) !== null && _event$dataTransfer$d2 !== void 0 ? _event$dataTransfer$d2 : 'none' | ||
}); | ||
@@ -262,3 +296,3 @@ // Applying this fix after `dispatch.drop` so that frameworks have the opportunity | ||
fixPostDragPointerBug({ | ||
current | ||
current: state.current | ||
}); | ||
@@ -268,3 +302,5 @@ } | ||
}, ...getBindingsForBrokenDrags({ | ||
onDragEnd: cancel | ||
onDragEnd: () => cancel({ | ||
dropEffect: 'none' | ||
}) | ||
})], | ||
@@ -282,3 +318,3 @@ // Once we have started a managed drag operation it is important that we see / own all drag events | ||
} | ||
function setDropEffect({ | ||
function setDropEffectOnEvent({ | ||
event, | ||
@@ -285,0 +321,0 @@ current |
import { bindAll } from 'bind-event-listener'; | ||
function cancel(event) { | ||
// if `@atlaskit/pragmatic-drag-and-drop` has already prevented the event | ||
// we don't need to do anything | ||
import { getBindingsForBrokenDrags } from '../util/detect-broken-drag'; | ||
function acceptDrop(event) { | ||
// if the event is already prevented the event we don't need to do anything | ||
if (event.defaultPrevented) { | ||
@@ -11,3 +11,3 @@ return; | ||
// on the page | ||
// Note: using "none" will not allow a drop to occur, so we are using "move" | ||
// Note: using "none" will not allow a "drop" to occur, so we are using "move" | ||
if (event.dataTransfer) { | ||
@@ -24,22 +24,53 @@ event.dataTransfer.dropEffect = 'move'; | ||
*/ | ||
function start() { | ||
cleanup(); | ||
unbindEvents = bindAll(window, [{ | ||
type: 'dragover', | ||
listener: acceptDrop | ||
}, { | ||
type: 'dragenter', | ||
listener: acceptDrop | ||
}, { | ||
type: 'drop', | ||
listener(event) { | ||
// our lifecycle manager already prevents events, but just being super safe | ||
event.preventDefault(); | ||
// not setting dropEffect, as `drop.dropEffect` has already been published to the user | ||
// (lifecycle-manager binds events in the capture phase) | ||
// we don't need to wait for "dragend", and "dragend" might not even happen, | ||
// such as when the draggable has been removed during a drag. | ||
cleanup(); | ||
} | ||
}, { | ||
type: 'dragend', | ||
listener: cleanup | ||
}, ...getBindingsForBrokenDrags({ | ||
onDragEnd: cleanup | ||
})], | ||
// being clear that these are added in the bubble phase | ||
{ | ||
capture: false | ||
}); | ||
} | ||
function cleanup() { | ||
var _unbindEvents; | ||
(_unbindEvents = unbindEvents) === null || _unbindEvents === void 0 ? void 0 : _unbindEvents(); | ||
unbindEvents = null; | ||
} | ||
/** | ||
* TODO: for next major, we could look at do the following: | ||
* | ||
* ```diff | ||
* - preventUnhandled.start(); | ||
* - preventUnhandled.stop(); | ||
* + const stop = preventUnhandled(); | ||
* ``` | ||
*/ | ||
export const preventUnhandled = { | ||
start() { | ||
var _unbindEvents; | ||
(_unbindEvents = unbindEvents) === null || _unbindEvents === void 0 ? void 0 : _unbindEvents(); | ||
unbindEvents = bindAll(window, [{ | ||
type: 'dragover', | ||
listener: cancel | ||
}, { | ||
type: 'dragenter', | ||
listener: cancel | ||
}, { | ||
type: 'drop', | ||
listener: cancel | ||
}]); | ||
}, | ||
stop() { | ||
var _unbindEvents2; | ||
(_unbindEvents2 = unbindEvents) === null || _unbindEvents2 === void 0 ? void 0 : _unbindEvents2(); | ||
unbindEvents = null; | ||
} | ||
start, | ||
stop: cleanup | ||
}; |
@@ -108,2 +108,3 @@ import rafSchd from 'raf-schd'; | ||
var current = _ref5.current, | ||
drop = _ref5.drop, | ||
updatedSourcePayload = _ref5.updatedSourcePayload; | ||
@@ -115,2 +116,3 @@ dragStart.flush(); | ||
payload: { | ||
drop: drop, | ||
source: updatedSourcePayload !== null && updatedSourcePayload !== void 0 ? updatedSourcePayload : source, | ||
@@ -117,0 +119,0 @@ location: { |
@@ -8,5 +8,7 @@ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; | ||
import { makeDispatch } from './dispatch-consumer-event'; | ||
var isActive = false; | ||
var globalState = { | ||
isActive: false | ||
}; | ||
function canStart() { | ||
return !isActive; | ||
return !globalState.isActive; | ||
} | ||
@@ -44,3 +46,2 @@ function getNativeSetDragImage(event) { | ||
} | ||
isActive = true; | ||
var initial = getStartLocation({ | ||
@@ -51,5 +52,9 @@ event: event, | ||
}); | ||
var current = initial; | ||
globalState.isActive = true; | ||
var state = { | ||
current: initial | ||
}; | ||
// Setting initial drop effect for the drag | ||
setDropEffect({ | ||
setDropEffectOnEvent({ | ||
event: event, | ||
@@ -66,3 +71,3 @@ current: initial.dropTargets | ||
var hasChanged = hasHierarchyChanged({ | ||
current: current.dropTargets, | ||
current: state.current.dropTargets, | ||
next: next.dropTargets | ||
@@ -74,6 +79,6 @@ }); | ||
// Consumers can get the latest data by using `onDrag` | ||
current = next; | ||
state.current = next; | ||
if (hasChanged) { | ||
dispatch.dragUpdate({ | ||
current: current | ||
current: state.current | ||
}); | ||
@@ -88,3 +93,3 @@ } | ||
source: dragType.payload, | ||
current: current.dropTargets | ||
current: state.current.dropTargets | ||
}); | ||
@@ -94,3 +99,3 @@ if (nextDropTargets.length) { | ||
event.preventDefault(); | ||
setDropEffect({ | ||
setDropEffectOnEvent({ | ||
event: event, | ||
@@ -105,18 +110,3 @@ current: nextDropTargets | ||
} | ||
function onDrop(args) { | ||
// When dropping something native, we need to extract the latest | ||
// `.items` from the "drop" event as it is now accessible | ||
if (args.type === 'success' && dragType.type === 'external') { | ||
dispatch.drop({ | ||
current: current, | ||
updatedSourcePayload: dragType.getDropPayload(args.event) | ||
}); | ||
return; | ||
} | ||
dispatch.drop({ | ||
current: current, | ||
updatedSourcePayload: null | ||
}); | ||
} | ||
function cancel() { | ||
function cancel(drop) { | ||
// The spec behaviour is that when a drag is cancelled, or when dropping on no drop targets, | ||
@@ -130,10 +120,12 @@ // a "dragleave" event is fired on the active drop target before a "dragend" event. | ||
if (current.dropTargets.length) { | ||
if (state.current.dropTargets.length) { | ||
updateDropTargets({ | ||
dropTargets: [], | ||
input: current.input | ||
input: state.current.input | ||
}); | ||
} | ||
onDrop({ | ||
type: 'cancel' | ||
dispatch.drop({ | ||
current: state.current, | ||
drop: drop, | ||
updatedSourcePayload: null | ||
}); | ||
@@ -143,3 +135,3 @@ finish(); | ||
function finish() { | ||
isActive = false; | ||
globalState.isActive = false; | ||
unbindEvents(); | ||
@@ -169,3 +161,3 @@ } | ||
dispatch.drag({ | ||
current: current | ||
current: state.current | ||
}); | ||
@@ -177,9 +169,2 @@ } | ||
}, { | ||
// This was the only reliable cross browser way I found to detect | ||
// when the user is leaving the `window`. | ||
// Internal drags: when we leave the `window` we want to clear any active drop targets, | ||
// but the drag is not yet over. The user could drag back into the window. | ||
// We only need to do this because of stickiness | ||
// External drags: when we leave the `window` the drag operation is over, | ||
// we will start another drag operation | ||
type: 'dragleave', | ||
@@ -193,23 +178,51 @@ listener: function listener(event) { | ||
// When a drag is ending without a drop target (or when the drag is cancelled), | ||
// All browsers fire: | ||
// 1. "drag" | ||
// 2. "dragleave" | ||
// These events have `event.relatedTarget == null` so this code path is also hit in those cases. | ||
// This is all good! We would be clearing the dropTargets in `cancel()` after the "dragend" | ||
/** | ||
* At this point we don't know if a drag is being cancelled, | ||
* or if a drag is leaving the `window`. | ||
* | ||
* Both have: | ||
* 1. "dragleave" (with `relatedTarget: null`) | ||
* 2. "dragend" (a "dragend" can occur when outside the `window`) | ||
* | ||
* **Clearing drop targets** | ||
* | ||
* For either case we are clearing the the drop targets | ||
* | ||
* - cancelling: we clear drop targets in `"dragend"` anyway | ||
* - leaving the `window`: we clear the drop targets (to clear stickiness) | ||
* | ||
* **Leaving the window and finishing the drag** | ||
* | ||
* _internal drags_ | ||
* | ||
* - The drag continues when the user is outside the `window` | ||
* and can resume if the user drags back over the `window`, | ||
* or end when the user drops in an external `window`. | ||
* - We will get a `"dragend"`, or we can listen for other | ||
* events to determine the drag is finished when the user re-enters the `window`). | ||
* | ||
* _external drags_ | ||
* | ||
* - We conclude the drag operation. | ||
* - We have no idea if the user will drag back over the `window`, | ||
* or if the drag ends elsewhere. | ||
* - We will create a new drag if the user re-enters the `window`. | ||
* | ||
* **Not updating `input`** | ||
* | ||
* 🐛 Bug[Chrome] the final `"dragleave"` has default input values (eg `clientX == 0`) | ||
* Workaround: intentionally not updating `input` in "dragleave" | ||
* rather than the users current input values | ||
* - [Conversation](https://twitter.com/alexandereardon/status/1642697633864241152) | ||
* - [Bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1429937) | ||
**/ | ||
// 🐛 Bug workaround: intentionally not updating `input` in "dragleave" | ||
// In Chrome, this final "dragleave" has default input values (eg clientX == 0) | ||
// rather than the users current input values | ||
// | ||
// - [Conversation](https://twitter.com/alexandereardon/status/1642697633864241152) | ||
// - [Bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1429937) | ||
updateDropTargets({ | ||
input: current.input, | ||
input: state.current.input, | ||
dropTargets: [] | ||
}); | ||
// End the drag operation if a native drag is leaving the window | ||
if (dragType.startedFrom === 'external') { | ||
cancel(); | ||
cancel({ | ||
dropEffect: 'none' | ||
}); | ||
} | ||
@@ -220,15 +233,24 @@ } | ||
listener: function listener(event) { | ||
var _event$dataTransfer$d, _event$dataTransfer; | ||
// A "drop" can only happen if the browser allowed the drop | ||
// Opting out of standard browser drop behaviour for the drag | ||
// Accepting drop operation. | ||
// Also: opting out of standard browser drop behaviour for the drag | ||
event.preventDefault(); | ||
// applying the latest drop effect to the event | ||
setDropEffect({ | ||
setDropEffectOnEvent({ | ||
event: event, | ||
current: current.dropTargets | ||
current: state.current.dropTargets | ||
}); | ||
onDrop({ | ||
type: 'success', | ||
event: event | ||
dispatch.drop({ | ||
current: state.current, | ||
drop: { | ||
// At this point the dropEffect has been set on the event | ||
// (if we have set it), so we can read it from there | ||
dropEffect: (_event$dataTransfer$d = (_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.dropEffect) !== null && _event$dataTransfer$d !== void 0 ? _event$dataTransfer$d : 'none' | ||
}, | ||
// When dropping something native, we need to extract the latest | ||
// `.items` from the "drop" event as it is now accessible | ||
updatedSourcePayload: dragType.type === 'external' ? dragType.getDropPayload(event) : null | ||
}); | ||
@@ -241,3 +263,3 @@ finish(); | ||
fixPostDragPointerBug({ | ||
current: current | ||
current: state.current | ||
}); | ||
@@ -249,8 +271,20 @@ } | ||
// when the drag is finished. | ||
// "dragend" will fire after "drop"(if there was a successful drop) | ||
// "dragend" will fire after "drop" (if there was a successful drop) | ||
// "dragend" does not fire if the draggable source has been removed during the drag | ||
// or for external drag sources (eg files) | ||
// This "dragend" listener will not fire if there was a successful drop | ||
// as we will have already removed the event listener | ||
type: 'dragend', | ||
listener: function listener() { | ||
cancel(); | ||
listener: function listener(event) { | ||
var _event$dataTransfer$d2, _event$dataTransfer2; | ||
// The `dropEffect` will be: | ||
// - "none" if dropped on no drop targets | ||
// - "none" if cancelled locally | ||
// - "none" if cancelled externally | ||
// - "none" if `preventUnhandled` is used (and there is no drop target) | ||
// - [not "none"] if accepted externally | ||
cancel({ | ||
dropEffect: (_event$dataTransfer$d2 = (_event$dataTransfer2 = event.dataTransfer) === null || _event$dataTransfer2 === void 0 ? void 0 : _event$dataTransfer2.dropEffect) !== null && _event$dataTransfer$d2 !== void 0 ? _event$dataTransfer$d2 : 'none' | ||
}); | ||
@@ -261,3 +295,3 @@ // Applying this fix after `dispatch.drop` so that frameworks have the opportunity | ||
fixPostDragPointerBug({ | ||
current: current | ||
current: state.current | ||
}); | ||
@@ -267,3 +301,7 @@ } | ||
}].concat(_toConsumableArray(getBindingsForBrokenDrags({ | ||
onDragEnd: cancel | ||
onDragEnd: function onDragEnd() { | ||
return cancel({ | ||
dropEffect: 'none' | ||
}); | ||
} | ||
}))), | ||
@@ -281,3 +319,3 @@ // Once we have started a managed drag operation it is important that we see / own all drag events | ||
} | ||
function setDropEffect(_ref3) { | ||
function setDropEffectOnEvent(_ref3) { | ||
var _current$; | ||
@@ -284,0 +322,0 @@ var event = _ref3.event, |
@@ -0,5 +1,6 @@ | ||
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; | ||
import { bindAll } from 'bind-event-listener'; | ||
function cancel(event) { | ||
// if `@atlaskit/pragmatic-drag-and-drop` has already prevented the event | ||
// we don't need to do anything | ||
import { getBindingsForBrokenDrags } from '../util/detect-broken-drag'; | ||
function acceptDrop(event) { | ||
// if the event is already prevented the event we don't need to do anything | ||
if (event.defaultPrevented) { | ||
@@ -11,3 +12,3 @@ return; | ||
// on the page | ||
// Note: using "none" will not allow a drop to occur, so we are using "move" | ||
// Note: using "none" will not allow a "drop" to occur, so we are using "move" | ||
if (event.dataTransfer) { | ||
@@ -24,22 +25,53 @@ event.dataTransfer.dropEffect = 'move'; | ||
*/ | ||
function start() { | ||
cleanup(); | ||
unbindEvents = bindAll(window, [{ | ||
type: 'dragover', | ||
listener: acceptDrop | ||
}, { | ||
type: 'dragenter', | ||
listener: acceptDrop | ||
}, { | ||
type: 'drop', | ||
listener: function listener(event) { | ||
// our lifecycle manager already prevents events, but just being super safe | ||
event.preventDefault(); | ||
// not setting dropEffect, as `drop.dropEffect` has already been published to the user | ||
// (lifecycle-manager binds events in the capture phase) | ||
// we don't need to wait for "dragend", and "dragend" might not even happen, | ||
// such as when the draggable has been removed during a drag. | ||
cleanup(); | ||
} | ||
}, { | ||
type: 'dragend', | ||
listener: cleanup | ||
}].concat(_toConsumableArray(getBindingsForBrokenDrags({ | ||
onDragEnd: cleanup | ||
}))), | ||
// being clear that these are added in the bubble phase | ||
{ | ||
capture: false | ||
}); | ||
} | ||
function cleanup() { | ||
var _unbindEvents; | ||
(_unbindEvents = unbindEvents) === null || _unbindEvents === void 0 || _unbindEvents(); | ||
unbindEvents = null; | ||
} | ||
/** | ||
* TODO: for next major, we could look at do the following: | ||
* | ||
* ```diff | ||
* - preventUnhandled.start(); | ||
* - preventUnhandled.stop(); | ||
* + const stop = preventUnhandled(); | ||
* ``` | ||
*/ | ||
export var preventUnhandled = { | ||
start: function start() { | ||
var _unbindEvents; | ||
(_unbindEvents = unbindEvents) === null || _unbindEvents === void 0 || _unbindEvents(); | ||
unbindEvents = bindAll(window, [{ | ||
type: 'dragover', | ||
listener: cancel | ||
}, { | ||
type: 'dragenter', | ||
listener: cancel | ||
}, { | ||
type: 'drop', | ||
listener: cancel | ||
}]); | ||
}, | ||
stop: function stop() { | ||
var _unbindEvents2; | ||
(_unbindEvents2 = unbindEvents) === null || _unbindEvents2 === void 0 || _unbindEvents2(); | ||
unbindEvents = null; | ||
} | ||
start: start, | ||
stop: cleanup | ||
}; |
@@ -1,1 +0,1 @@ | ||
export type { DropTargetRecord, Position, Input, DragLocation, DragLocationHistory, CleanupFn, AllDragTypes, MonitorArgs, BaseEventPayload, ElementDragType, TextSelectionDragType, ExternalDragType, } from '../internal-types'; | ||
export type { DropTargetAllowedDropEffect, DropTargetRecord, Position, Input, DragLocation, DragLocationHistory, DropData, CleanupFn, AllDragTypes, MonitorArgs, BaseEventPayload, ElementDragType, TextSelectionDragType, ExternalDragType, } from '../internal-types'; |
export type CleanupFn = () => void; | ||
/** | ||
* Drop effects allowed to be passed to `getDropEffect()`. | ||
* Cannot use `"none"` as a `dropEffect` for drop targets as | ||
* it will opt out of accepting a drop for all nested drop targets. | ||
* Please use `canDrop()` to disable dropping for this drop target. | ||
*/ | ||
export type DropTargetAllowedDropEffect = Exclude<DataTransfer['dropEffect'], 'none'>; | ||
/** | ||
* Information about a drop target | ||
@@ -21,3 +28,3 @@ */ | ||
*/ | ||
dropEffect: DataTransfer['dropEffect']; | ||
dropEffect: DropTargetAllowedDropEffect; | ||
/** | ||
@@ -35,3 +42,3 @@ * Whether or not the drop target is active due to _stickiness_ | ||
}; | ||
export type StartedFrom = 'internal' | 'external'; | ||
export type Region = 'internal' | 'external'; | ||
export type ElementDragPayload = { | ||
@@ -191,2 +198,5 @@ element: HTMLElement; | ||
}; | ||
export type DropData = { | ||
dropEffect: DataTransfer['dropEffect']; | ||
}; | ||
export type EventPayloadMap<DragType extends AllDragTypes> = { | ||
@@ -227,3 +237,5 @@ /** | ||
*/ | ||
onDrop: BaseEventPayload<DragType>; | ||
onDrop: BaseEventPayload<DragType> & { | ||
drop: DropData; | ||
}; | ||
}; | ||
@@ -315,5 +327,5 @@ export type AllEvents<DragType extends AllDragTypes> = { | ||
* Optionally provide a _drop effect_ to be applied when | ||
* this drop target is the innermost drop target being dragged over | ||
* this drop target is the innermost drop target being dragged over. | ||
*/ | ||
getDropEffect?: (args: DropTargetGetFeedbackArgs<DragType>) => DataTransfer['dropEffect']; | ||
getDropEffect?: (args: DropTargetGetFeedbackArgs<DragType>) => DropTargetAllowedDropEffect; | ||
/** | ||
@@ -320,0 +332,0 @@ * Return `true` if you want your drop target to hold onto |
@@ -1,2 +0,2 @@ | ||
import { AllDragTypes, DragLocation, EventPayloadMap } from '../internal-types'; | ||
import { AllDragTypes, DragLocation, DropData, EventPayloadMap } from '../internal-types'; | ||
export declare function makeDispatch<DragType extends AllDragTypes>({ source, initial, dispatchEvent, }: { | ||
@@ -19,4 +19,5 @@ source: DragType['payload']; | ||
}): void; | ||
drop({ current, updatedSourcePayload, }: { | ||
drop({ current, drop, updatedSourcePayload, }: { | ||
current: DragLocation; | ||
drop: DropData; | ||
/** When dragging from an external source, we need to collect the | ||
@@ -23,0 +24,0 @@ drag source information again as it is often only available during |
@@ -1,6 +0,6 @@ | ||
import { AdapterAPI, AllDragTypes, CleanupFn, EventPayloadMap } from '../internal-types'; | ||
import { AdapterAPI, AllDragTypes, CleanupFn, DropTargetAllowedDropEffect, EventPayloadMap } from '../internal-types'; | ||
export declare function makeAdapter<DragType extends AllDragTypes>({ typeKey, mount, dispatchEventToSource, defaultDropEffect, }: { | ||
typeKey: DragType['type']; | ||
mount: (api: AdapterAPI<DragType>) => CleanupFn; | ||
defaultDropEffect: DataTransfer['dropEffect']; | ||
defaultDropEffect: DropTargetAllowedDropEffect; | ||
dispatchEventToSource?: <EventName extends keyof EventPayloadMap<DragType>>(args: { | ||
@@ -7,0 +7,0 @@ eventName: EventName; |
@@ -1,5 +0,5 @@ | ||
import { AllDragTypes, DropTargetAPI } from '../internal-types'; | ||
import { AllDragTypes, DropTargetAllowedDropEffect, DropTargetAPI } from '../internal-types'; | ||
export declare function makeDropTarget<DragType extends AllDragTypes>({ typeKey, defaultDropEffect, }: { | ||
typeKey: DragType['type']; | ||
defaultDropEffect: DataTransfer['dropEffect']; | ||
defaultDropEffect: DropTargetAllowedDropEffect; | ||
}): DropTargetAPI<DragType>; |
/** | ||
* Block drag operations outside of `@atlaskit/pragmatic-drag-and-drop` | ||
*/ | ||
declare function start(): void; | ||
declare function cleanup(): void; | ||
/** | ||
* TODO: for next major, we could look at do the following: | ||
* | ||
* ```diff | ||
* - preventUnhandled.start(); | ||
* - preventUnhandled.stop(); | ||
* + const stop = preventUnhandled(); | ||
* ``` | ||
*/ | ||
export declare const preventUnhandled: { | ||
start(): void; | ||
stop(): void; | ||
start: typeof start; | ||
stop: typeof cleanup; | ||
}; | ||
export {}; |
@@ -1,1 +0,1 @@ | ||
export type { DropTargetRecord, Position, Input, DragLocation, DragLocationHistory, CleanupFn, AllDragTypes, MonitorArgs, BaseEventPayload, ElementDragType, TextSelectionDragType, ExternalDragType, } from '../internal-types'; | ||
export type { DropTargetAllowedDropEffect, DropTargetRecord, Position, Input, DragLocation, DragLocationHistory, DropData, CleanupFn, AllDragTypes, MonitorArgs, BaseEventPayload, ElementDragType, TextSelectionDragType, ExternalDragType, } from '../internal-types'; |
export type CleanupFn = () => void; | ||
/** | ||
* Drop effects allowed to be passed to `getDropEffect()`. | ||
* Cannot use `"none"` as a `dropEffect` for drop targets as | ||
* it will opt out of accepting a drop for all nested drop targets. | ||
* Please use `canDrop()` to disable dropping for this drop target. | ||
*/ | ||
export type DropTargetAllowedDropEffect = Exclude<DataTransfer['dropEffect'], 'none'>; | ||
/** | ||
* Information about a drop target | ||
@@ -21,3 +28,3 @@ */ | ||
*/ | ||
dropEffect: DataTransfer['dropEffect']; | ||
dropEffect: DropTargetAllowedDropEffect; | ||
/** | ||
@@ -35,3 +42,3 @@ * Whether or not the drop target is active due to _stickiness_ | ||
}; | ||
export type StartedFrom = 'internal' | 'external'; | ||
export type Region = 'internal' | 'external'; | ||
export type ElementDragPayload = { | ||
@@ -191,2 +198,5 @@ element: HTMLElement; | ||
}; | ||
export type DropData = { | ||
dropEffect: DataTransfer['dropEffect']; | ||
}; | ||
export type EventPayloadMap<DragType extends AllDragTypes> = { | ||
@@ -227,3 +237,5 @@ /** | ||
*/ | ||
onDrop: BaseEventPayload<DragType>; | ||
onDrop: BaseEventPayload<DragType> & { | ||
drop: DropData; | ||
}; | ||
}; | ||
@@ -315,5 +327,5 @@ export type AllEvents<DragType extends AllDragTypes> = { | ||
* Optionally provide a _drop effect_ to be applied when | ||
* this drop target is the innermost drop target being dragged over | ||
* this drop target is the innermost drop target being dragged over. | ||
*/ | ||
getDropEffect?: (args: DropTargetGetFeedbackArgs<DragType>) => DataTransfer['dropEffect']; | ||
getDropEffect?: (args: DropTargetGetFeedbackArgs<DragType>) => DropTargetAllowedDropEffect; | ||
/** | ||
@@ -320,0 +332,0 @@ * Return `true` if you want your drop target to hold onto |
@@ -1,2 +0,2 @@ | ||
import { AllDragTypes, DragLocation, EventPayloadMap } from '../internal-types'; | ||
import { AllDragTypes, DragLocation, DropData, EventPayloadMap } from '../internal-types'; | ||
export declare function makeDispatch<DragType extends AllDragTypes>({ source, initial, dispatchEvent, }: { | ||
@@ -19,4 +19,5 @@ source: DragType['payload']; | ||
}): void; | ||
drop({ current, updatedSourcePayload, }: { | ||
drop({ current, drop, updatedSourcePayload, }: { | ||
current: DragLocation; | ||
drop: DropData; | ||
/** When dragging from an external source, we need to collect the | ||
@@ -23,0 +24,0 @@ drag source information again as it is often only available during |
@@ -1,6 +0,6 @@ | ||
import { AdapterAPI, AllDragTypes, CleanupFn, EventPayloadMap } from '../internal-types'; | ||
import { AdapterAPI, AllDragTypes, CleanupFn, DropTargetAllowedDropEffect, EventPayloadMap } from '../internal-types'; | ||
export declare function makeAdapter<DragType extends AllDragTypes>({ typeKey, mount, dispatchEventToSource, defaultDropEffect, }: { | ||
typeKey: DragType['type']; | ||
mount: (api: AdapterAPI<DragType>) => CleanupFn; | ||
defaultDropEffect: DataTransfer['dropEffect']; | ||
defaultDropEffect: DropTargetAllowedDropEffect; | ||
dispatchEventToSource?: <EventName extends keyof EventPayloadMap<DragType>>(args: { | ||
@@ -7,0 +7,0 @@ eventName: EventName; |
@@ -1,5 +0,5 @@ | ||
import { AllDragTypes, DropTargetAPI } from '../internal-types'; | ||
import { AllDragTypes, DropTargetAllowedDropEffect, DropTargetAPI } from '../internal-types'; | ||
export declare function makeDropTarget<DragType extends AllDragTypes>({ typeKey, defaultDropEffect, }: { | ||
typeKey: DragType['type']; | ||
defaultDropEffect: DataTransfer['dropEffect']; | ||
defaultDropEffect: DropTargetAllowedDropEffect; | ||
}): DropTargetAPI<DragType>; |
/** | ||
* Block drag operations outside of `@atlaskit/pragmatic-drag-and-drop` | ||
*/ | ||
declare function start(): void; | ||
declare function cleanup(): void; | ||
/** | ||
* TODO: for next major, we could look at do the following: | ||
* | ||
* ```diff | ||
* - preventUnhandled.start(); | ||
* - preventUnhandled.stop(); | ||
* + const stop = preventUnhandled(); | ||
* ``` | ||
*/ | ||
export declare const preventUnhandled: { | ||
start(): void; | ||
stop(): void; | ||
start: typeof start; | ||
stop: typeof cleanup; | ||
}; | ||
export {}; |
{ | ||
"name": "@atlaskit/pragmatic-drag-and-drop", | ||
"version": "1.0.2", | ||
"version": "1.1.0", | ||
"description": "Fast drag and drop for any experience on any tech stack", | ||
@@ -5,0 +5,0 @@ "repository": "https://github.com/atlassian/pragmatic-drag-and-drop", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
402502
9310