@atlaskit/pragmatic-drag-and-drop 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +209 -0
- package/LICENSE.md +13 -0
- package/README.md +43 -0
- package/__perf__/add-example.todo +1 -0
- package/adapter/element/package.json +15 -0
- package/adapter/file/package.json +15 -0
- package/addon/cancel-unhandled/package.json +15 -0
- package/constellation/index/about.mdx +329 -0
- package/constellation/index/props.mdx +3 -0
- package/dist/cjs/adapter/element-adapter.js +151 -0
- package/dist/cjs/adapter/file-adapter.js +98 -0
- package/dist/cjs/addon/cancel-unhandled.js +50 -0
- package/dist/cjs/entry-point/adapter/element.js +24 -0
- package/dist/cjs/entry-point/adapter/file.js +18 -0
- package/dist/cjs/entry-point/addon/cancel-unhandled.js +12 -0
- package/dist/cjs/entry-point/experimental/cross-with-element-adapter.js +30 -0
- package/dist/cjs/entry-point/types.js +5 -0
- package/dist/cjs/entry-point/util/combine.js +12 -0
- package/dist/cjs/entry-point/util/disable-native-drag-preview.js +12 -0
- package/dist/cjs/entry-point/util/once.js +12 -0
- package/dist/cjs/entry-point/util/reorder.js +12 -0
- package/dist/cjs/entry-point/util/scroll-just-enough-into-view.js +12 -0
- package/dist/cjs/entry-point/util/set-custom-native-drag-preview.js +12 -0
- package/dist/cjs/experimental/cross-window-element-adapter.js +131 -0
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/internal-types.js +5 -0
- package/dist/cjs/ledger/dispatch-consumer-event.js +132 -0
- package/dist/cjs/ledger/lifecycle-manager.js +335 -0
- package/dist/cjs/ledger/usage-ledger.js +37 -0
- package/dist/cjs/make-adapter/make-adapter.js +59 -0
- package/dist/cjs/make-adapter/make-drop-target.js +271 -0
- package/dist/cjs/make-adapter/make-monitor.js +100 -0
- package/dist/cjs/util/add-attribute.js +14 -0
- package/dist/cjs/util/combine.js +17 -0
- package/dist/cjs/util/disable-native-drag-preview.js +36 -0
- package/dist/cjs/util/entering-and-leaving-the-window.js +162 -0
- package/dist/cjs/util/fix-post-drag-pointer-bug.js +114 -0
- package/dist/cjs/util/get-input.js +20 -0
- package/dist/cjs/util/once.js +22 -0
- package/dist/cjs/util/reorder.js +26 -0
- package/dist/cjs/util/scroll-just-enough-into-view.js +17 -0
- package/dist/cjs/util/set-custom-native-drag-preview.js +109 -0
- package/dist/cjs/version.json +5 -0
- package/dist/es2019/adapter/element-adapter.js +143 -0
- package/dist/es2019/adapter/file-adapter.js +90 -0
- package/dist/es2019/addon/cancel-unhandled.js +43 -0
- package/dist/es2019/entry-point/adapter/element.js +1 -0
- package/dist/es2019/entry-point/adapter/file.js +1 -0
- package/dist/es2019/entry-point/addon/cancel-unhandled.js +1 -0
- package/dist/es2019/entry-point/experimental/cross-with-element-adapter.js +1 -0
- package/dist/es2019/entry-point/types.js +1 -0
- package/dist/es2019/entry-point/util/combine.js +1 -0
- package/dist/es2019/entry-point/util/disable-native-drag-preview.js +1 -0
- package/dist/es2019/entry-point/util/once.js +1 -0
- package/dist/es2019/entry-point/util/reorder.js +1 -0
- package/dist/es2019/entry-point/util/scroll-just-enough-into-view.js +1 -0
- package/dist/es2019/entry-point/util/set-custom-native-drag-preview.js +1 -0
- package/dist/es2019/experimental/cross-window-element-adapter.js +121 -0
- package/dist/es2019/index.js +7 -0
- package/dist/es2019/internal-types.js +1 -0
- package/dist/es2019/ledger/dispatch-consumer-event.js +128 -0
- package/dist/es2019/ledger/lifecycle-manager.js +333 -0
- package/dist/es2019/ledger/usage-ledger.js +32 -0
- package/dist/es2019/make-adapter/make-adapter.js +55 -0
- package/dist/es2019/make-adapter/make-drop-target.js +233 -0
- package/dist/es2019/make-adapter/make-monitor.js +80 -0
- package/dist/es2019/util/add-attribute.js +7 -0
- package/dist/es2019/util/combine.js +6 -0
- package/dist/es2019/util/disable-native-drag-preview.js +31 -0
- package/dist/es2019/util/entering-and-leaving-the-window.js +159 -0
- package/dist/es2019/util/fix-post-drag-pointer-bug.js +110 -0
- package/dist/es2019/util/get-input.js +14 -0
- package/dist/es2019/util/once.js +13 -0
- package/dist/es2019/util/reorder.js +17 -0
- package/dist/es2019/util/scroll-just-enough-into-view.js +12 -0
- package/dist/es2019/util/set-custom-native-drag-preview.js +106 -0
- package/dist/es2019/version.json +5 -0
- package/dist/esm/adapter/element-adapter.js +142 -0
- package/dist/esm/adapter/file-adapter.js +90 -0
- package/dist/esm/addon/cancel-unhandled.js +43 -0
- package/dist/esm/entry-point/adapter/element.js +1 -0
- package/dist/esm/entry-point/adapter/file.js +1 -0
- package/dist/esm/entry-point/addon/cancel-unhandled.js +1 -0
- package/dist/esm/entry-point/experimental/cross-with-element-adapter.js +1 -0
- package/dist/esm/entry-point/types.js +1 -0
- package/dist/esm/entry-point/util/combine.js +1 -0
- package/dist/esm/entry-point/util/disable-native-drag-preview.js +1 -0
- package/dist/esm/entry-point/util/once.js +1 -0
- package/dist/esm/entry-point/util/reorder.js +1 -0
- package/dist/esm/entry-point/util/scroll-just-enough-into-view.js +1 -0
- package/dist/esm/entry-point/util/set-custom-native-drag-preview.js +1 -0
- package/dist/esm/experimental/cross-window-element-adapter.js +120 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/internal-types.js +1 -0
- package/dist/esm/ledger/dispatch-consumer-event.js +125 -0
- package/dist/esm/ledger/lifecycle-manager.js +328 -0
- package/dist/esm/ledger/usage-ledger.js +31 -0
- package/dist/esm/make-adapter/make-adapter.js +53 -0
- package/dist/esm/make-adapter/make-drop-target.js +264 -0
- package/dist/esm/make-adapter/make-monitor.js +93 -0
- package/dist/esm/util/add-attribute.js +8 -0
- package/dist/esm/util/combine.js +11 -0
- package/dist/esm/util/disable-native-drag-preview.js +30 -0
- package/dist/esm/util/entering-and-leaving-the-window.js +156 -0
- package/dist/esm/util/fix-post-drag-pointer-bug.js +108 -0
- package/dist/esm/util/get-input.js +14 -0
- package/dist/esm/util/once.js +16 -0
- package/dist/esm/util/reorder.js +19 -0
- package/dist/esm/util/scroll-just-enough-into-view.js +11 -0
- package/dist/esm/util/set-custom-native-drag-preview.js +104 -0
- package/dist/esm/version.json +5 -0
- package/dist/types/adapter/element-adapter.d.ts +42 -0
- package/dist/types/adapter/file-adapter.d.ts +18 -0
- package/dist/types/addon/cancel-unhandled.d.ts +7 -0
- package/dist/types/entry-point/adapter/element.d.ts +2 -0
- package/dist/types/entry-point/adapter/file.d.ts +2 -0
- package/dist/types/entry-point/addon/cancel-unhandled.d.ts +1 -0
- package/dist/types/entry-point/experimental/cross-with-element-adapter.d.ts +1 -0
- package/dist/types/entry-point/types.d.ts +1 -0
- package/dist/types/entry-point/util/combine.d.ts +1 -0
- package/dist/types/entry-point/util/disable-native-drag-preview.d.ts +1 -0
- package/dist/types/entry-point/util/once.d.ts +1 -0
- package/dist/types/entry-point/util/reorder.d.ts +1 -0
- package/dist/types/entry-point/util/scroll-just-enough-into-view.d.ts +1 -0
- package/dist/types/entry-point/util/set-custom-native-drag-preview.d.ts +1 -0
- package/dist/types/experimental/cross-window-element-adapter.d.ts +17 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/internal-types.d.ts +275 -0
- package/dist/types/ledger/dispatch-consumer-event.d.ts +26 -0
- package/dist/types/ledger/lifecycle-manager.d.ts +16 -0
- package/dist/types/ledger/usage-ledger.d.ts +5 -0
- package/dist/types/make-adapter/make-adapter.d.ts +14 -0
- package/dist/types/make-adapter/make-drop-target.d.ts +5 -0
- package/dist/types/make-adapter/make-monitor.d.ts +8 -0
- package/dist/types/util/add-attribute.d.ts +5 -0
- package/dist/types/util/combine.d.ts +3 -0
- package/dist/types/util/disable-native-drag-preview.d.ts +3 -0
- package/dist/types/util/entering-and-leaving-the-window.d.ts +6 -0
- package/dist/types/util/fix-post-drag-pointer-bug.d.ts +14 -0
- package/dist/types/util/get-input.d.ts +2 -0
- package/dist/types/util/once.d.ts +2 -0
- package/dist/types/util/reorder.d.ts +9 -0
- package/dist/types/util/scroll-just-enough-into-view.d.ts +7 -0
- package/dist/types/util/set-custom-native-drag-preview.d.ts +52 -0
- package/experimental/cross-window-element-adapter/package.json +15 -0
- package/package.json +87 -0
- package/report.api.md +35 -0
- package/tmp/api-report-tmp.d.ts +13 -0
- package/types/package.json +15 -0
- package/util/combine/package.json +15 -0
- package/util/disable-native-drag-preview/package.json +15 -0
- package/util/once/package.json +15 -0
- package/util/reorder/package.json +15 -0
- package/util/scroll-just-enough-into-view/package.json +15 -0
- package/util/set-custom-native-drag-preview/package.json +15 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { monitorForElements } from '../adapter/element-adapter';
|
|
2
|
+
|
|
3
|
+
/** A function to remove the element that has been added to the `container`.
|
|
4
|
+
* @example () => ReactDOM.unmountComponentAtNode(container)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** A function that will render a preview element into a `container` `HTMLElement` */
|
|
8
|
+
|
|
9
|
+
/** Any valid CSS string value
|
|
10
|
+
* @example `calc(var(--grid) * 2)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Where to place the custom drag preview
|
|
15
|
+
*
|
|
16
|
+
* `type: 'center'`: Place the center of the drag preview user the users pointer
|
|
17
|
+
*
|
|
18
|
+
* `type: 'offset-from-pointer'`: Shift the drag preview away from the users pointer
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
function setImage({
|
|
22
|
+
container,
|
|
23
|
+
placement,
|
|
24
|
+
nativeSetDragImage
|
|
25
|
+
}) {
|
|
26
|
+
if ((placement === null || placement === void 0 ? void 0 : placement.type) === 'center') {
|
|
27
|
+
const box = container.getBoundingClientRect();
|
|
28
|
+
nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, box.width / 2, box.height / 2);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if ((placement === null || placement === void 0 ? void 0 : placement.type) === 'offset-from-pointer') {
|
|
32
|
+
// Using a transparent border to push the drag preview away
|
|
33
|
+
// from the user's pointer.
|
|
34
|
+
// In Chrome and Safari we could use `padding`:
|
|
35
|
+
// padding: 'var(--grid)',
|
|
36
|
+
// But it does not work in Firefox which trims the padding (or inner margin)
|
|
37
|
+
Object.assign(container.style, {
|
|
38
|
+
borderLeft: `${placement.x} solid transparent`,
|
|
39
|
+
borderTop: `${placement.y} solid transparent`
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, 0, 0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** This function provides the ability to mount an element for it to be used as the native drag preview
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* draggable({
|
|
49
|
+
* onGenerateDragPreview: ({ nativeSetDragImage }) => {
|
|
50
|
+
* setCustomNativeDragPreview({
|
|
51
|
+
* render: ({ container }) => {
|
|
52
|
+
* ReactDOM.render(<Preview item={item} />, container);
|
|
53
|
+
* return () => ReactDOM.unmountComponentAtNode(container);
|
|
54
|
+
* },
|
|
55
|
+
* nativeSetDragImage,
|
|
56
|
+
* });
|
|
57
|
+
* },
|
|
58
|
+
* });
|
|
59
|
+
*/
|
|
60
|
+
export function setCustomNativeDragPreview({
|
|
61
|
+
render,
|
|
62
|
+
nativeSetDragImage,
|
|
63
|
+
placement
|
|
64
|
+
}) {
|
|
65
|
+
const container = document.createElement('div');
|
|
66
|
+
Object.assign(container.style, {
|
|
67
|
+
// Ensuring we don't cause reflow when adding the element to the page
|
|
68
|
+
// Using `position:fixed` rather than `position:absolute` so we are
|
|
69
|
+
// positioned on the current viewport.
|
|
70
|
+
// `position:fixed` also creates a new stacking context, so we don't need to do that here
|
|
71
|
+
position: 'fixed',
|
|
72
|
+
top: 0,
|
|
73
|
+
left: 0,
|
|
74
|
+
// Using maximum possible z-index so that this element will always be on top
|
|
75
|
+
// https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index
|
|
76
|
+
// Did not use `layers` in `@atlaskit/theme` because:
|
|
77
|
+
// 1. This element is not a 'layer' in the conventional sense, as this element
|
|
78
|
+
// is only created for a single frame for the browser to take a photo of it,
|
|
79
|
+
// and then it is destroyed
|
|
80
|
+
// 2. Did not want to add a dependency onto `@atlaskit/theme`
|
|
81
|
+
// 3. Want to always be on top of product UI which might have higher z-index's
|
|
82
|
+
zIndex: 2147483647,
|
|
83
|
+
// Avoiding any additional events caused by the new element (being super safe)
|
|
84
|
+
pointerEvents: 'none'
|
|
85
|
+
});
|
|
86
|
+
document.body.append(container);
|
|
87
|
+
const unmount = render({
|
|
88
|
+
container
|
|
89
|
+
});
|
|
90
|
+
setImage({
|
|
91
|
+
container,
|
|
92
|
+
placement,
|
|
93
|
+
nativeSetDragImage
|
|
94
|
+
});
|
|
95
|
+
function cleanup() {
|
|
96
|
+
unbindMonitor();
|
|
97
|
+
unmount === null || unmount === void 0 ? void 0 : unmount();
|
|
98
|
+
document.body.removeChild(container);
|
|
99
|
+
}
|
|
100
|
+
const unbindMonitor = monitorForElements({
|
|
101
|
+
// Remove portal in the dragstart event so that the user will never see it
|
|
102
|
+
onDragStart: cleanup,
|
|
103
|
+
// Backup: remove portal when the drop finishes (this would be an error case)
|
|
104
|
+
onDrop: cleanup
|
|
105
|
+
});
|
|
106
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { bind } from 'bind-event-listener';
|
|
2
|
+
import { makeAdapter } from '../make-adapter/make-adapter';
|
|
3
|
+
import { addAttribute } from '../util/add-attribute';
|
|
4
|
+
import { combine } from '../util/combine';
|
|
5
|
+
import { getInput } from '../util/get-input';
|
|
6
|
+
var draggableRegistry = new WeakMap();
|
|
7
|
+
function addToRegistry(args) {
|
|
8
|
+
draggableRegistry.set(args.element, args);
|
|
9
|
+
return function cleanup() {
|
|
10
|
+
draggableRegistry.delete(args.element);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
var adapter = makeAdapter({
|
|
14
|
+
typeKey: 'element',
|
|
15
|
+
defaultDropEffect: 'move',
|
|
16
|
+
mount: function mount(api) {
|
|
17
|
+
return bind(window, {
|
|
18
|
+
type: 'dragstart',
|
|
19
|
+
listener: function listener(event) {
|
|
20
|
+
var _entry$dragHandle, _entry$dragHandle2, _entry$getInitialData, _entry$getInitialData2;
|
|
21
|
+
if (!api.canStart(event)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
// the closest parent that is a draggable element will be marked as
|
|
25
|
+
// the `event.target` for the event
|
|
26
|
+
var target = event.target;
|
|
27
|
+
|
|
28
|
+
// this source is only for elements
|
|
29
|
+
// Note: only HTMLElements can have the "draggable" attribute
|
|
30
|
+
if (!(target instanceof HTMLElement)) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// see if the thing being dragged is owned by us
|
|
35
|
+
var entry = draggableRegistry.get(target);
|
|
36
|
+
|
|
37
|
+
// no matching element found
|
|
38
|
+
// → dragging an element with `draggable="true"` that is not controlled by us
|
|
39
|
+
if (!entry) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
var input = getInput(event);
|
|
43
|
+
var feedback = {
|
|
44
|
+
element: entry.element,
|
|
45
|
+
dragHandle: (_entry$dragHandle = entry.dragHandle) !== null && _entry$dragHandle !== void 0 ? _entry$dragHandle : null,
|
|
46
|
+
input: input
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Check: does the draggable want to allow dragging?
|
|
50
|
+
if (entry.canDrag && !entry.canDrag(feedback)) {
|
|
51
|
+
// cancel drag operation if we cannot drag
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Check: is there a drag handle and is the user using it?
|
|
57
|
+
if (entry.dragHandle) {
|
|
58
|
+
var over = document.elementFromPoint(input.clientX, input.clientY);
|
|
59
|
+
|
|
60
|
+
// if we are not dragging from the drag handle (or something inside the drag handle)
|
|
61
|
+
// then we will cancel the active drag
|
|
62
|
+
if (!entry.dragHandle.contains(over)) {
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Must set any media type for iOS15 to work
|
|
69
|
+
// Doing this will fail in firefox though, so we
|
|
70
|
+
// wrap the operation in a try/catch
|
|
71
|
+
try {
|
|
72
|
+
var _event$dataTransfer;
|
|
73
|
+
(_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.setData('application/vnd.pdnd', '');
|
|
74
|
+
} catch (e) {}
|
|
75
|
+
var payload = {
|
|
76
|
+
element: entry.element,
|
|
77
|
+
dragHandle: (_entry$dragHandle2 = entry.dragHandle) !== null && _entry$dragHandle2 !== void 0 ? _entry$dragHandle2 : null,
|
|
78
|
+
data: (_entry$getInitialData = (_entry$getInitialData2 = entry.getInitialData) === null || _entry$getInitialData2 === void 0 ? void 0 : _entry$getInitialData2.call(entry, feedback)) !== null && _entry$getInitialData !== void 0 ? _entry$getInitialData : {}
|
|
79
|
+
};
|
|
80
|
+
var makeDragType = {
|
|
81
|
+
key: 'element',
|
|
82
|
+
startedFrom: 'internal',
|
|
83
|
+
payload: payload
|
|
84
|
+
};
|
|
85
|
+
api.start({
|
|
86
|
+
event: event,
|
|
87
|
+
dragInterface: makeDragType
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
dispatchEventToSource: function dispatchEventToSource(_ref) {
|
|
93
|
+
var _draggableRegistry$ge, _draggableRegistry$ge2;
|
|
94
|
+
var eventName = _ref.eventName,
|
|
95
|
+
payload = _ref.payload;
|
|
96
|
+
// During a drag operation, a draggable can be:
|
|
97
|
+
// - remounted with different functions
|
|
98
|
+
// - removed completely
|
|
99
|
+
// So we need to get the latest entry from the registry in order
|
|
100
|
+
// to call the latest event functions
|
|
101
|
+
|
|
102
|
+
(_draggableRegistry$ge = draggableRegistry.get(payload.source.element)) === null || _draggableRegistry$ge === void 0 ? void 0 : (_draggableRegistry$ge2 = _draggableRegistry$ge[eventName]) === null || _draggableRegistry$ge2 === void 0 ? void 0 : _draggableRegistry$ge2.call(_draggableRegistry$ge,
|
|
103
|
+
// I cannot seem to get the types right here.
|
|
104
|
+
// TS doesn't seem to like that one event can need `nativeSetDragImage`
|
|
105
|
+
// @ts-expect-error
|
|
106
|
+
payload);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
export var dropTargetForElements = adapter.dropTarget;
|
|
110
|
+
export var monitorForElements = adapter.monitor;
|
|
111
|
+
export function draggable(args) {
|
|
112
|
+
// Guardrail: warn if the drag handle is not contained in draggable element
|
|
113
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
114
|
+
if (args.dragHandle && !args.element.contains(args.dragHandle)) {
|
|
115
|
+
// eslint-disable-next-line no-console
|
|
116
|
+
console.warn('Drag handle element must be contained in draggable element', {
|
|
117
|
+
element: args.element,
|
|
118
|
+
dragHandle: args.dragHandle
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Guardrail: warn if the draggable element is already registered
|
|
123
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
124
|
+
var existing = draggableRegistry.get(args.element);
|
|
125
|
+
if (existing) {
|
|
126
|
+
// eslint-disable-next-line no-console
|
|
127
|
+
console.warn('You have already registered a `draggable` on the same element', {
|
|
128
|
+
existing: existing,
|
|
129
|
+
proposed: args
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return combine(
|
|
134
|
+
// making the draggable register the adapter rather than drop targets
|
|
135
|
+
// this is because you *must* have a draggable element to start a drag
|
|
136
|
+
// but you _might_ not have any drop targets immediately
|
|
137
|
+
// (You might create drop targets async)
|
|
138
|
+
adapter.registerUsage(), addToRegistry(args), addAttribute(args.element, {
|
|
139
|
+
attribute: 'draggable',
|
|
140
|
+
value: 'true'
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { bind } from 'bind-event-listener';
|
|
2
|
+
import { makeAdapter } from '../make-adapter/make-adapter';
|
|
3
|
+
import { combine } from '../util/combine';
|
|
4
|
+
import { isEnteringWindow } from '../util/entering-and-leaving-the-window';
|
|
5
|
+
function getFileItems(event) {
|
|
6
|
+
if (event.dataTransfer == null) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
// filtering out anything that is not a file
|
|
10
|
+
var items = event.dataTransfer.items;
|
|
11
|
+
for (var i = 0; i < items.length; i++) {
|
|
12
|
+
var item = items[i];
|
|
13
|
+
if (item.kind !== 'file') {
|
|
14
|
+
items.remove(i);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return items;
|
|
18
|
+
}
|
|
19
|
+
var adapter = makeAdapter({
|
|
20
|
+
typeKey: 'file',
|
|
21
|
+
defaultDropEffect: 'copy',
|
|
22
|
+
mount: function mount(api) {
|
|
23
|
+
return bind(window, {
|
|
24
|
+
type: 'dragenter',
|
|
25
|
+
listener: function listener(event) {
|
|
26
|
+
if (!api.canStart(event)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// already cancelled by something else
|
|
31
|
+
if (event.defaultPrevented) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (!isEnteringWindow({
|
|
35
|
+
dragEnter: event
|
|
36
|
+
})) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (event.dataTransfer == null) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Checking if we are dragging any files
|
|
44
|
+
// This check works in Chrome, Firefox and Chrome
|
|
45
|
+
if (!event.dataTransfer.types.includes('Files')) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
var dragInterface = {
|
|
49
|
+
key: 'file',
|
|
50
|
+
startedFrom: 'external',
|
|
51
|
+
payload: {
|
|
52
|
+
// Not giving `.items` initially as it cannot be safely and consistently
|
|
53
|
+
// accessed across browsers
|
|
54
|
+
// Not giving `.types` as the consumer already knows a file is being dragged
|
|
55
|
+
items: null
|
|
56
|
+
},
|
|
57
|
+
getDropPayload: function getDropPayload(event) {
|
|
58
|
+
return {
|
|
59
|
+
items: getFileItems(event)
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
api.start({
|
|
64
|
+
event: event,
|
|
65
|
+
dragInterface: dragInterface
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Some events don't make sense for external files
|
|
73
|
+
//
|
|
74
|
+
// onGenerateDragPreview: drag preview is always generated by the browser
|
|
75
|
+
// type WithoutUselessEvents<T> = Omit<T, 'onDragStart' | 'onGenerateDragPreview'>;
|
|
76
|
+
//
|
|
77
|
+
// onDragStart: an external file can never start from inside a drop target
|
|
78
|
+
// (it will always come from outside and we never let a file drag start in a drop target)
|
|
79
|
+
// We remove `onDragStart` from drop targets, but monitors can still listen for a start
|
|
80
|
+
export var dropTargetForFiles = function dropTargetForFiles(args) {
|
|
81
|
+
return combine(
|
|
82
|
+
// at least one drop target required before we will start listening for file events
|
|
83
|
+
adapter.registerUsage(),
|
|
84
|
+
// note: not removing unsupported events from args; just leaning on the type system
|
|
85
|
+
adapter.dropTarget(args));
|
|
86
|
+
};
|
|
87
|
+
export var monitorForFiles = function monitorForFiles(args) {
|
|
88
|
+
// note: not removing unsupported events from args; just leaning on the type system
|
|
89
|
+
return adapter.monitor(args);
|
|
90
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { bindAll } from 'bind-event-listener';
|
|
2
|
+
function cancel(event) {
|
|
3
|
+
// if `@atlaskit/pragmatic-drag-and-drop` has already prevented the event
|
|
4
|
+
// we don't need to do anything
|
|
5
|
+
if (event.defaultPrevented) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
// Using "move" as the drop effect as that uses the standard
|
|
9
|
+
// cursor. Doing this so the user doesn't think they are dropping
|
|
10
|
+
// on the page
|
|
11
|
+
// Note: using "none" will not allow a drop to occur, so we are using "move"
|
|
12
|
+
if (event.dataTransfer) {
|
|
13
|
+
event.dataTransfer.dropEffect = 'move';
|
|
14
|
+
}
|
|
15
|
+
// cancel the default browser behaviour
|
|
16
|
+
// doing this will tell the browser that we have handled the drop
|
|
17
|
+
event.preventDefault();
|
|
18
|
+
}
|
|
19
|
+
var unbindEvents = null;
|
|
20
|
+
/**
|
|
21
|
+
* Block drag operations outside of `@atlaskit/pragmatic-drag-and-drop`
|
|
22
|
+
*/
|
|
23
|
+
export var cancelUnhandled = {
|
|
24
|
+
start: function start() {
|
|
25
|
+
var _unbindEvents;
|
|
26
|
+
(_unbindEvents = unbindEvents) === null || _unbindEvents === void 0 ? void 0 : _unbindEvents();
|
|
27
|
+
unbindEvents = bindAll(window, [{
|
|
28
|
+
type: 'dragover',
|
|
29
|
+
listener: cancel
|
|
30
|
+
}, {
|
|
31
|
+
type: 'dragenter',
|
|
32
|
+
listener: cancel
|
|
33
|
+
}, {
|
|
34
|
+
type: 'drop',
|
|
35
|
+
listener: cancel
|
|
36
|
+
}]);
|
|
37
|
+
},
|
|
38
|
+
stop: function stop() {
|
|
39
|
+
var _unbindEvents2;
|
|
40
|
+
(_unbindEvents2 = unbindEvents) === null || _unbindEvents2 === void 0 ? void 0 : _unbindEvents2();
|
|
41
|
+
unbindEvents = null;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { draggable, dropTargetForElements, monitorForElements } from '../../adapter/element-adapter';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { monitorForFiles, dropTargetForFiles } from '../../adapter/file-adapter';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { cancelUnhandled } from '../../addon/cancel-unhandled';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { setCrossWindowData, extractCrossWindowResult, dropTargetForCrossWindowElements, monitorForCrossWindowElements } from '../../experimental/cross-window-element-adapter';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { combine } from '../../util/combine';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { disableNativeDragPreview } from '../../util/disable-native-drag-preview';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { once } from '../../util/once';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { reorder } from '../../util/reorder';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { scrollJustEnoughIntoView } from '../../util/scroll-just-enough-into-view';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { setCustomNativeDragPreview } from '../../util/set-custom-native-drag-preview';
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { bindAll } from 'bind-event-listener';
|
|
2
|
+
import { makeAdapter } from '../make-adapter/make-adapter';
|
|
3
|
+
import { combine } from '../util/combine';
|
|
4
|
+
import { isEnteringWindow } from '../util/entering-and-leaving-the-window';
|
|
5
|
+
var storage = function () {
|
|
6
|
+
var dataKey = 'private-pdnd-data';
|
|
7
|
+
var resultKey = 'private-pdnd-result';
|
|
8
|
+
function tryParse(raw) {
|
|
9
|
+
if (raw == null) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
return JSON.parse(raw);
|
|
14
|
+
} catch (e) {
|
|
15
|
+
// failed to parse
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function setData(data) {
|
|
20
|
+
// clearing a result when we set data
|
|
21
|
+
clearStorage();
|
|
22
|
+
localStorage.setItem(dataKey, JSON.stringify(data));
|
|
23
|
+
}
|
|
24
|
+
function findData() {
|
|
25
|
+
return tryParse(localStorage.getItem(dataKey));
|
|
26
|
+
}
|
|
27
|
+
function setResult(result) {
|
|
28
|
+
localStorage.setItem(resultKey, result);
|
|
29
|
+
}
|
|
30
|
+
function findResult() {
|
|
31
|
+
var raw = localStorage.getItem(resultKey);
|
|
32
|
+
if (raw == null) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// TODO: improve type
|
|
37
|
+
return raw;
|
|
38
|
+
}
|
|
39
|
+
function clearStorage() {
|
|
40
|
+
localStorage.removeItem(dataKey);
|
|
41
|
+
localStorage.removeItem(resultKey);
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
clearStorage: clearStorage,
|
|
45
|
+
setData: setData,
|
|
46
|
+
findData: findData,
|
|
47
|
+
setResult: setResult,
|
|
48
|
+
findResult: findResult
|
|
49
|
+
};
|
|
50
|
+
}();
|
|
51
|
+
var adapter = makeAdapter({
|
|
52
|
+
typeKey: 'experimental-cross-window-element',
|
|
53
|
+
defaultDropEffect: 'move',
|
|
54
|
+
mount: function mount(api) {
|
|
55
|
+
return combine(bindAll(window, [{
|
|
56
|
+
type: 'dragenter',
|
|
57
|
+
listener: function listener(event) {
|
|
58
|
+
if (!api.canStart(event)) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// already cancelled by something else
|
|
63
|
+
if (event.defaultPrevented) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (!isEnteringWindow({
|
|
67
|
+
dragEnter: event
|
|
68
|
+
})) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// we only care about when the window is being first entered
|
|
73
|
+
if (event.relatedTarget != null) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
var data = storage.findData();
|
|
77
|
+
if (data == null) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
var dragInterface = {
|
|
81
|
+
key: 'experimental-cross-window-element',
|
|
82
|
+
startedFrom: 'external',
|
|
83
|
+
payload: {
|
|
84
|
+
data: data
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
api.start({
|
|
88
|
+
event: event,
|
|
89
|
+
dragInterface: dragInterface
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
// always clear a external drag result from another window before a drag starts
|
|
94
|
+
{
|
|
95
|
+
type: 'dragstart',
|
|
96
|
+
listener: storage.clearStorage,
|
|
97
|
+
options: {
|
|
98
|
+
capture: true
|
|
99
|
+
}
|
|
100
|
+
}]), adapter.monitor({
|
|
101
|
+
onDrop: function onDrop(payload) {
|
|
102
|
+
var result = payload.location.current.dropTargets.length > 0 ? 'moved' : 'none';
|
|
103
|
+
storage.setResult(result);
|
|
104
|
+
}
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
export function setCrossWindowData(_ref) {
|
|
109
|
+
var data = _ref.data;
|
|
110
|
+
storage.setData(data);
|
|
111
|
+
}
|
|
112
|
+
export function extractCrossWindowResult() {
|
|
113
|
+
return storage.findResult();
|
|
114
|
+
}
|
|
115
|
+
export var dropTargetForCrossWindowElements = function dropTargetForCrossWindowElements(args) {
|
|
116
|
+
return combine(
|
|
117
|
+
// at least one drop target required before we will start listening for cross element dragging
|
|
118
|
+
adapter.registerUsage(), adapter.dropTarget(args));
|
|
119
|
+
};
|
|
120
|
+
export var monitorForCrossWindowElements = adapter.monitor;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import rafSchd from 'raf-schd';
|
|
2
|
+
var scheduleOnDrag = rafSchd(function (fn) {
|
|
3
|
+
return fn();
|
|
4
|
+
});
|
|
5
|
+
var dragStart = function () {
|
|
6
|
+
var scheduled = null;
|
|
7
|
+
function schedule(fn) {
|
|
8
|
+
var frameId = requestAnimationFrame(function () {
|
|
9
|
+
scheduled = null;
|
|
10
|
+
fn();
|
|
11
|
+
});
|
|
12
|
+
scheduled = {
|
|
13
|
+
frameId: frameId,
|
|
14
|
+
fn: fn
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function flush() {
|
|
18
|
+
if (scheduled) {
|
|
19
|
+
cancelAnimationFrame(scheduled.frameId);
|
|
20
|
+
scheduled.fn();
|
|
21
|
+
scheduled = null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
schedule: schedule,
|
|
26
|
+
flush: flush
|
|
27
|
+
};
|
|
28
|
+
}();
|
|
29
|
+
export function makeDispatch(_ref) {
|
|
30
|
+
var source = _ref.source,
|
|
31
|
+
initial = _ref.initial,
|
|
32
|
+
dispatchEvent = _ref.dispatchEvent;
|
|
33
|
+
var previous = {
|
|
34
|
+
dropTargets: []
|
|
35
|
+
};
|
|
36
|
+
function safeDispatch(args) {
|
|
37
|
+
dispatchEvent(args);
|
|
38
|
+
previous = {
|
|
39
|
+
dropTargets: args.payload.location.current.dropTargets
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
var dispatch = {
|
|
43
|
+
start: function start(_ref2) {
|
|
44
|
+
var nativeSetDragImage = _ref2.nativeSetDragImage;
|
|
45
|
+
// Ensuring that both `onGenerateDragPreview` and `onDragStart` get the same location.
|
|
46
|
+
// We do this so that `previous` is`[]` in `onDragStart` (which is logical)
|
|
47
|
+
var location = {
|
|
48
|
+
current: initial,
|
|
49
|
+
previous: previous,
|
|
50
|
+
initial: initial
|
|
51
|
+
};
|
|
52
|
+
// a `onGenerateDragPreview` does _not_ add another entry for `previous`
|
|
53
|
+
// onDragPreview
|
|
54
|
+
safeDispatch({
|
|
55
|
+
eventName: 'onGenerateDragPreview',
|
|
56
|
+
payload: {
|
|
57
|
+
source: source,
|
|
58
|
+
location: location,
|
|
59
|
+
nativeSetDragImage: nativeSetDragImage
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
dragStart.schedule(function () {
|
|
63
|
+
safeDispatch({
|
|
64
|
+
eventName: 'onDragStart',
|
|
65
|
+
payload: {
|
|
66
|
+
source: source,
|
|
67
|
+
location: location
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
},
|
|
72
|
+
dragUpdate: function dragUpdate(_ref3) {
|
|
73
|
+
var current = _ref3.current;
|
|
74
|
+
dragStart.flush();
|
|
75
|
+
scheduleOnDrag.cancel();
|
|
76
|
+
safeDispatch({
|
|
77
|
+
eventName: 'onDropTargetChange',
|
|
78
|
+
payload: {
|
|
79
|
+
source: source,
|
|
80
|
+
location: {
|
|
81
|
+
initial: initial,
|
|
82
|
+
previous: previous,
|
|
83
|
+
current: current
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
},
|
|
88
|
+
drag: function drag(_ref4) {
|
|
89
|
+
var current = _ref4.current;
|
|
90
|
+
scheduleOnDrag(function () {
|
|
91
|
+
dragStart.flush();
|
|
92
|
+
var location = {
|
|
93
|
+
initial: initial,
|
|
94
|
+
previous: previous,
|
|
95
|
+
current: current
|
|
96
|
+
};
|
|
97
|
+
safeDispatch({
|
|
98
|
+
eventName: 'onDrag',
|
|
99
|
+
payload: {
|
|
100
|
+
source: source,
|
|
101
|
+
location: location
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
drop: function drop(_ref5) {
|
|
107
|
+
var current = _ref5.current,
|
|
108
|
+
updatedSourcePayload = _ref5.updatedExternalPayload;
|
|
109
|
+
dragStart.flush();
|
|
110
|
+
scheduleOnDrag.cancel();
|
|
111
|
+
safeDispatch({
|
|
112
|
+
eventName: 'onDrop',
|
|
113
|
+
payload: {
|
|
114
|
+
source: updatedSourcePayload !== null && updatedSourcePayload !== void 0 ? updatedSourcePayload : source,
|
|
115
|
+
location: {
|
|
116
|
+
current: current,
|
|
117
|
+
previous: previous,
|
|
118
|
+
initial: initial
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
return dispatch;
|
|
125
|
+
}
|