@atlaskit/pragmatic-drag-and-drop 0.18.2 → 0.20.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/constellation/index/about.mdx +75 -12
  3. package/dist/cjs/entry-point/util/center-under-pointer.js +12 -0
  4. package/dist/cjs/entry-point/util/offset-from-pointer.js +12 -0
  5. package/dist/cjs/entry-point/util/set-custom-native-drag-preview.js +1 -1
  6. package/dist/cjs/make-adapter/make-drop-target.js +46 -20
  7. package/dist/cjs/util/custom-native-drag-preview/center-under-pointer.js +15 -0
  8. package/dist/cjs/util/custom-native-drag-preview/offset-from-pointer.js +25 -0
  9. package/dist/cjs/util/{set-custom-native-drag-preview.js → custom-native-drag-preview/set-custom-native-drag-preview.js} +15 -42
  10. package/dist/cjs/util/custom-native-drag-preview/types.js +5 -0
  11. package/dist/cjs/version.json +1 -1
  12. package/dist/es2019/entry-point/util/center-under-pointer.js +1 -0
  13. package/dist/es2019/entry-point/util/offset-from-pointer.js +1 -0
  14. package/dist/es2019/entry-point/util/set-custom-native-drag-preview.js +1 -1
  15. package/dist/es2019/make-adapter/make-drop-target.js +47 -20
  16. package/dist/es2019/util/custom-native-drag-preview/center-under-pointer.js +9 -0
  17. package/dist/es2019/util/custom-native-drag-preview/offset-from-pointer.js +20 -0
  18. package/dist/es2019/util/{set-custom-native-drag-preview.js → custom-native-drag-preview/set-custom-native-drag-preview.js} +11 -40
  19. package/dist/es2019/util/custom-native-drag-preview/types.js +1 -0
  20. package/dist/es2019/version.json +1 -1
  21. package/dist/esm/entry-point/util/center-under-pointer.js +1 -0
  22. package/dist/esm/entry-point/util/offset-from-pointer.js +1 -0
  23. package/dist/esm/entry-point/util/set-custom-native-drag-preview.js +1 -1
  24. package/dist/esm/make-adapter/make-drop-target.js +46 -20
  25. package/dist/esm/util/custom-native-drag-preview/center-under-pointer.js +8 -0
  26. package/dist/esm/util/custom-native-drag-preview/offset-from-pointer.js +19 -0
  27. package/dist/esm/util/{set-custom-native-drag-preview.js → custom-native-drag-preview/set-custom-native-drag-preview.js} +15 -42
  28. package/dist/esm/util/custom-native-drag-preview/types.js +1 -0
  29. package/dist/esm/version.json +1 -1
  30. package/dist/types/entry-point/util/center-under-pointer.d.ts +1 -0
  31. package/dist/types/entry-point/util/offset-from-pointer.d.ts +1 -0
  32. package/dist/types/entry-point/util/set-custom-native-drag-preview.d.ts +1 -1
  33. package/dist/types/internal-types.d.ts +2 -4
  34. package/dist/types/util/custom-native-drag-preview/center-under-pointer.d.ts +2 -0
  35. package/dist/types/util/custom-native-drag-preview/offset-from-pointer.d.ts +10 -0
  36. package/dist/{types-ts4.5/util → types/util/custom-native-drag-preview}/set-custom-native-drag-preview.d.ts +4 -21
  37. package/dist/types/util/custom-native-drag-preview/types.d.ts +16 -0
  38. package/dist/types-ts4.5/entry-point/util/center-under-pointer.d.ts +1 -0
  39. package/dist/types-ts4.5/entry-point/util/offset-from-pointer.d.ts +1 -0
  40. package/dist/types-ts4.5/entry-point/util/set-custom-native-drag-preview.d.ts +1 -1
  41. package/dist/types-ts4.5/internal-types.d.ts +2 -4
  42. package/dist/types-ts4.5/util/custom-native-drag-preview/center-under-pointer.d.ts +2 -0
  43. package/dist/types-ts4.5/util/custom-native-drag-preview/offset-from-pointer.d.ts +10 -0
  44. package/dist/{types/util → types-ts4.5/util/custom-native-drag-preview}/set-custom-native-drag-preview.d.ts +4 -21
  45. package/dist/types-ts4.5/util/custom-native-drag-preview/types.d.ts +16 -0
  46. package/package.json +3 -2
  47. package/util/center-under-pointer/package.json +15 -0
  48. package/util/offset-from-pointer/package.json +15 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,112 @@
1
1
  # @atlaskit/pragmatic-drag-and-drop
2
2
 
3
+ ## 0.20.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`554a6d8cc34`](https://bitbucket.org/atlassian/atlassian-frontend/commits/554a6d8cc34) - ### Stickiness algorithm improvement
8
+
9
+ 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.
10
+
11
+ Stickiness is no longer maintained when a sticky drop target states it cannot be dropped on
12
+
13
+ > Scenario: `[A(sticky)]` → `[]` + `A:canDrop()` returns `false`
14
+ > Result: `[]`
15
+
16
+ Stickiness is no longer maintained when a sticky drop start states it is no longer sticky
17
+
18
+ > Scenario: `[A(sticky)]` → `[]` + `A:getIsSticky()` returns `false`
19
+ > Result: `[]`
20
+
21
+ Stickiness is no longer maintained when a sticky drop start is unmounted
22
+
23
+ > Scenario: `[A(sticky)]` → `[]` + `A` is unmounted
24
+ > Result: `[]`
25
+
26
+ To help facilitate this change:
27
+
28
+ - `getIsSticky()` is now only called when an _drop target_ is a potential candidate for stickiness (previously it was called repeatedly)
29
+ - `getIsSticky()` and `canDrop()` are called on _drop targets_ that are no longer being dragged over, but are candidates for stickiness
30
+
31
+ ### Change to `DropTargetRecord` `type`
32
+
33
+ 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.
34
+
35
+ 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.
36
+
37
+ ```diff
38
+ type DropTargetRecord = {
39
+ element: Element;
40
+ data: Record<string | symbol, unknown>;
41
+ dropEffect: DataTransfer['dropEffect'];
42
+ - sticky: boolean;
43
+ + isActiveDueToStickiness: boolean;
44
+ };
45
+ ```
46
+
47
+ ## 0.19.0
48
+
49
+ ### Minor Changes
50
+
51
+ - [`8c301a251e4`](https://bitbucket.org/atlassian/atlassian-frontend/commits/8c301a251e4) - We have changed the API of `setCustomNativeDragPreview()` to allow increased control and slightly lower bundles as well.
52
+
53
+ We have removed the `placement` argument, and replaced it with `getOffset()`.
54
+
55
+ ```diff
56
+ - placement: { type: 'center' } | { type: 'offset-from-pointer'; x: CSSValue; y: CSSValue };
57
+ + getOffset: (args: { container: HTMLElement }) => {x: number, y: number}
58
+ ```
59
+
60
+ `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!
61
+
62
+ `placement: { type: 'offset-from-pointer' }` has been replaced by `offsetFromPointer()`
63
+
64
+ ```diff
65
+ import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
66
+ + import { offsetFromPointer } from '@atlaskit/pragmatic-drag-and-drop/util/offset-from-pointer;
67
+
68
+ draggable({
69
+ element: myElement,
70
+ onGenerateDragPreview: ({ nativeSetDragImage }) => {
71
+ setCustomNativeDragPreview({
72
+ - placement: { type: 'offset-from-pointer', x: '16px', y: '8px' }
73
+ + getOffset: offsetFromPointer({x: '16px', y: '8px'}),
74
+ render: function render({ container }) {
75
+ ReactDOM.render(<Preview item={item} />, container);
76
+ return function cleanup() {
77
+ ReactDOM.unmountComponentAtNode(container);
78
+ };
79
+ },
80
+ nativeSetDragImage,
81
+ });
82
+ },
83
+ });
84
+ ```
85
+
86
+ `placement: { type: 'center' }` has been replaced by `centerUnderPointer()`
87
+
88
+ ```diff
89
+ import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
90
+ + import { centerUnderPointer } from '@atlaskit/pragmatic-drag-and-drop/util/center-under-pointer-pointer;
91
+
92
+ draggable({
93
+ element: myElement,
94
+ onGenerateDragPreview: ({ nativeSetDragImage }) => {
95
+ setCustomNativeDragPreview({
96
+ - placement: { type: 'center' }
97
+ + getOffset: centerUnderPointer,
98
+ render: function render({ container }) {
99
+ ReactDOM.render(<Preview item={item} />, container);
100
+ return function cleanup() {
101
+ ReactDOM.unmountComponentAtNode(container);
102
+ };
103
+ },
104
+ nativeSetDragImage,
105
+ });
106
+ },
107
+ });
108
+ ```
109
+
3
110
  ## 0.18.2
4
111
 
5
112
  ### Patch Changes
@@ -4,8 +4,6 @@ order: 0
4
4
 
5
5
  import SectionMessage from '@atlaskit/section-message';
6
6
 
7
- <!-- I'd like to change this section to be called Drag-and-drop or something, not Core, but still mulling it over. -->
8
-
9
7
  This package contains the essential pieces of the system, and is not tied to any JavaScript framework.
10
8
 
11
9
  - The [element adapter](/components/pragmatic-drag-and-drop/adapter/element-adapter) powers drag operations of elements.
@@ -176,10 +174,6 @@ You can use `setCustomNativeDragPreview` to mount a new element to the page to b
176
174
 
177
175
  `setCustomNativeDragPreview` has been designed to work with any view abstraction
178
176
 
179
- ```ts
180
- import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
181
- ```
182
-
183
177
  #### Usage example: `react` portals
184
178
 
185
179
  This technique requires your component to be re-rendered, but maintains the current `react` `context`
@@ -234,7 +228,6 @@ function Item() {
234
228
 
235
229
  This technique requires no re-rendering of your component, but does not maintain the current `react` `context`
236
230
 
237
-
238
231
  ```tsx
239
232
  import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
240
233
 
@@ -254,12 +247,33 @@ draggable({
254
247
  });
255
248
  ```
256
249
 
257
- #### Placement
250
+ #### Offset
251
+
252
+ You can control where the custom native drag preview is placed by using the `getOffset()` argument.
253
+
254
+ You can return an `{x: number, y: number}` object from `getOffset()` which will control where the native drag preview is rendered relative to the users pointer. `{x: 0, y: 0}` represents having the users pointer user the top left corner of the drag preview.
255
+
256
+ For clarity:
257
+
258
+ > `const rect = container.getBoundingClientRect()`
259
+
260
+ - `{x: 0, y: 0}` → top left of the `container` will be under the users pointer **(default)**
261
+ - `{x: rect.width, y: 0}` top right of the `container` will be under the users pointer
262
+ - `{x: rect.width, y: rect.height}` bottom right of the `container` will be under the users pointer
263
+ - `{x: 0, y: rect.height}` bottom left of the `container` will be under the users pointer
264
+
265
+
266
+ ```ts
267
+ type GetOffsetFn = (args: { container: HTMLElement }) => {x: number, y: number};
268
+ ```
269
+
270
+ Notes:
258
271
 
259
- You can control where the custom native drag preview is placed by using the `placement` argument:
272
+ - `GetOffsetFn` needs to return `x` and `y` as numbers as that is what the platform requires
273
+ - You cannot use negative values (not supported by browsers). If you want to push the drag preview away from the users pointer, use `offsetFromPointer` (see below)
274
+ - The max offset value for an axis is the `border-box`. Values greater than the `border-box` get trimmed to be the `border-box` value
260
275
 
261
- - `type: 'center'`: Place the center of the drag preview user the users pointer
262
- - `type: 'offset-from-pointer'`: Shift the drag preview away from the users pointer
276
+ `{x: rect.width + 1, y: rect.height + 1}` effectively becomes `{x: rect.width, y: rect.height}`.
263
277
 
264
278
  ```tsx
265
279
  import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
@@ -268,7 +282,11 @@ draggable({
268
282
  element: myElement,
269
283
  onGenerateDragPreview: ({ nativeSetDragImage }) => {
270
284
  setCustomNativeDragPreview({
271
- placement: { type: 'offset-from-pointer', x: '16px', y: '8px' },
285
+ // place the (near) top middle of the `container` under the users pointer
286
+ getOffset: () => {
287
+ const rect = container.getBoundingClientRect();
288
+ return { x: rect.width / 2, y: 16 };
289
+ },
272
290
  render: function render({ container }) {
273
291
  ReactDOM.render(<Preview item={item} />, container);
274
292
  return function cleanup() {
@@ -281,6 +299,51 @@ draggable({
281
299
  });
282
300
  ```
283
301
 
302
+ We have `getOffset()` helpers for `setCustomnativeDragPreview()`:
303
+
304
+ 1. `centerUnderPointer`: centers the custom native drag preview under the users cursor
305
+
306
+ ```ts
307
+ import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
308
+ import { centerUnderPointer } from '@atlaskit/pragmatic-drag-and-drop/util/center-under-pointer';
309
+
310
+ draggable({
311
+ element: myElement,
312
+ onGenerateDragPreview: ({ nativeSetDragImage }) => {
313
+ setCustomNativeDragPreview({
314
+ getOffset: centerUnderPointer,
315
+ render: function render({ container }) {
316
+ /* ... */
317
+ },
318
+ nativeSetDragImage,
319
+ });
320
+ },
321
+ });
322
+ ```
323
+
324
+ 2. `offsetFromPointer`: a cross browser mechanism to push the drag preview away from the users pointer
325
+
326
+ ```ts
327
+ import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
328
+ import { offsetFromPointer } from '@atlaskit/pragmatic-drag-and-drop/util/offset-from-pointer';
329
+
330
+ draggable({
331
+ element: myElement,
332
+ onGenerateDragPreview: ({ nativeSetDragImage }) => {
333
+ setCustomNativeDragPreview({
334
+ // `x` and `y` can be any CSS value
335
+ getOffset: offsetFromPointer({ x: '8px', y: 'calc(var(--grid) * 2)' }),
336
+ render: function render({ container }) {
337
+ /* ... */
338
+ },
339
+ nativeSetDragImage,
340
+ });
341
+ },
342
+ });
343
+ ```
344
+
345
+ Note: if you are using css variables inside of your `getOffset()` you need to be sure your css variables are available at the `<body>` element, as the `container` is temporarily mounted as a child of `<body>`
346
+
284
347
  ### Disable native drag preview
285
348
 
286
349
  In some situations, you might want to disable the native drag preview. The `disableNativeDragPreview` utility does this for all supported browsers and platforms.
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "centerUnderPointer", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _centerUnderPointer.centerUnderPointer;
10
+ }
11
+ });
12
+ var _centerUnderPointer = require("../../util/custom-native-drag-preview/center-under-pointer");
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "offsetFromPointer", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _offsetFromPointer.offsetFromPointer;
10
+ }
11
+ });
12
+ var _offsetFromPointer = require("../../util/custom-native-drag-preview/offset-from-pointer");
@@ -9,4 +9,4 @@ Object.defineProperty(exports, "setCustomNativeDragPreview", {
9
9
  return _setCustomNativeDragPreview.setCustomNativeDragPreview;
10
10
  }
11
11
  });
12
- var _setCustomNativeDragPreview = require("../../util/set-custom-native-drag-preview");
12
+ var _setCustomNativeDragPreview = require("../../util/custom-native-drag-preview/set-custom-native-drag-preview");
@@ -47,7 +47,7 @@ function makeDropTarget(_ref) {
47
47
  }), addToRegistry(args));
48
48
  }
49
49
  function getActualDropTargets(_ref2) {
50
- var _args$getData, _args$getData2, _args$getDropEffect, _args$getDropEffect2, _args$getIsSticky;
50
+ var _args$getData, _args$getData2, _args$getDropEffect, _args$getDropEffect2;
51
51
  var source = _ref2.source,
52
52
  target = _ref2.target,
53
53
  input = _ref2.input,
@@ -85,14 +85,17 @@ function makeDropTarget(_ref) {
85
85
  result: result
86
86
  });
87
87
  }
88
+
89
+ // calculate our new record
88
90
  var data = (_args$getData = (_args$getData2 = args.getData) === null || _args$getData2 === void 0 ? void 0 : _args$getData2.call(args, feedback)) !== null && _args$getData !== void 0 ? _args$getData : {};
89
91
  var dropEffect = (_args$getDropEffect = (_args$getDropEffect2 = args.getDropEffect) === null || _args$getDropEffect2 === void 0 ? void 0 : _args$getDropEffect2.call(args, feedback)) !== null && _args$getDropEffect !== void 0 ? _args$getDropEffect : defaultDropEffect;
90
- var sticky = Boolean((_args$getIsSticky = args.getIsSticky) === null || _args$getIsSticky === void 0 ? void 0 : _args$getIsSticky.call(args, feedback));
91
92
  var record = {
92
93
  data: data,
93
94
  element: args.element,
94
95
  dropEffect: dropEffect,
95
- sticky: sticky
96
+ // we are collecting _actual_ drop targets, so these are
97
+ // being applied _not_ due to stickiness
98
+ isActiveDueToStickiness: false
96
99
  };
97
100
  return getActualDropTargets({
98
101
  source: source,
@@ -219,6 +222,7 @@ function makeDropTarget(_ref) {
219
222
  var actualCaptureOrdered = copyReverse(actual);
220
223
  var resultCaptureOrdered = [];
221
224
  for (var index = 0; index < lastCaptureOrdered.length; index++) {
225
+ var _argsForLast$getIsSti;
222
226
  var last = lastCaptureOrdered[index];
223
227
  var fresh = actualCaptureOrdered[index];
224
228
 
@@ -232,29 +236,51 @@ function makeDropTarget(_ref) {
232
236
  // At this point we have no drop target in the old spot
233
237
  // Check to see if we can use a previous sticky drop target
234
238
 
235
- // stickiness is based on relationships to a parent
236
- // so if we hit a drop target that is not sticky we
237
- // can finish our search
238
- if (!last.sticky) {
239
- break;
240
- }
241
-
242
- // We only want the previous sticky item to 'stick' if
243
- // the parent of the sticky item is unchanged
244
-
245
239
  // The "parent" is the one inside of `resultCaptureOrdered`
246
240
  // (the parent might be a drop target that was sticky)
247
241
  var parent = resultCaptureOrdered[index - 1];
248
242
  var lastParent = lastCaptureOrdered[index - 1];
249
243
 
250
- // parents are the same (might both be undefined for index == 0)
251
- // we can add the last entry and keep searching
252
- if ((parent === null || parent === void 0 ? void 0 : parent.element) === (lastParent === null || lastParent === void 0 ? void 0 : lastParent.element)) {
253
- resultCaptureOrdered.push(last);
254
- continue;
244
+ // Stickiness is based on parent relationships, so if the parent relationship has change
245
+ // then we can stop our search
246
+ if ((parent === null || parent === void 0 ? void 0 : parent.element) !== (lastParent === null || lastParent === void 0 ? void 0 : lastParent.element)) {
247
+ break;
248
+ }
249
+
250
+ // We need to check whether the old drop target can still be dropped on
251
+
252
+ var argsForLast = registry.get(last.element);
253
+
254
+ // We cannot drop on a drop target that is no longer mounted
255
+ if (!argsForLast) {
256
+ break;
255
257
  }
256
- // parents are not the same, we can exit our search
257
- break;
258
+ var feedback = {
259
+ input: input,
260
+ source: source,
261
+ element: argsForLast.element
262
+ };
263
+
264
+ // We cannot drop on a drop target that no longer allows being dropped on
265
+ if (argsForLast.canDrop && !argsForLast.canDrop(feedback)) {
266
+ break;
267
+ }
268
+
269
+ // We cannot drop on a drop target that is no longer sticky
270
+ if (!((_argsForLast$getIsSti = argsForLast.getIsSticky) !== null && _argsForLast$getIsSti !== void 0 && _argsForLast$getIsSti.call(argsForLast, feedback))) {
271
+ break;
272
+ }
273
+
274
+ // Note: intentionally not recollecting `getData()` or `getDropEffect()`
275
+ // Previous values for `data` and `dropEffect` will be borrowed
276
+ // This is to prevent things like the 'closest edge' changing when
277
+ // no longer over a drop target.
278
+ // We could change our mind on this behaviour in the future
279
+
280
+ resultCaptureOrdered.push(_objectSpread(_objectSpread({}, last), {}, {
281
+ // making it clear to consumers this drop target is active due to stickiness
282
+ isActiveDueToStickiness: true
283
+ }));
258
284
  }
259
285
 
260
286
  // return bubble ordered result
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.centerUnderPointer = void 0;
7
+ var centerUnderPointer = function centerUnderPointer(_ref) {
8
+ var container = _ref.container;
9
+ var rect = container.getBoundingClientRect();
10
+ return {
11
+ x: rect.width / 2,
12
+ y: rect.height / 2
13
+ };
14
+ };
15
+ exports.centerUnderPointer = centerUnderPointer;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.offsetFromPointer = offsetFromPointer;
7
+ /** Any valid CSS string value
8
+ * @example `calc(var(--grid) * 2)
9
+ */
10
+
11
+ function offsetFromPointer(point) {
12
+ return function (_ref) {
13
+ var container = _ref.container;
14
+ // Only reliable cross browser technique found to push a
15
+ // drag preview away from the cursor is to use transparent borders on the container
16
+ Object.assign(container.style, {
17
+ borderLeft: "".concat(point.x, " solid transparent"),
18
+ borderTop: "".concat(point.y, " solid transparent")
19
+ });
20
+ return {
21
+ x: 0,
22
+ y: 0
23
+ };
24
+ };
25
+ }
@@ -4,46 +4,19 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.setCustomNativeDragPreview = setCustomNativeDragPreview;
7
- var _elementAdapter = require("../adapter/element-adapter");
7
+ var _elementAdapter = require("../../adapter/element-adapter");
8
8
  /** A function to remove the element that has been added to the `container`.
9
9
  * @example () => ReactDOM.unmountComponentAtNode(container)
10
10
  */
11
11
 
12
12
  /** A function that will render a preview element into a `container` `HTMLElement` */
13
13
 
14
- /** Any valid CSS string value
15
- * @example `calc(var(--grid) * 2)
16
- */
17
-
18
- /**
19
- * Where to place the custom drag preview
20
- *
21
- * `type: 'center'`: Place the center of the drag preview user the users pointer
22
- *
23
- * `type: 'offset-from-pointer'`: Shift the drag preview away from the users pointer
24
- */
25
-
26
- function setImage(_ref) {
27
- var container = _ref.container,
28
- placement = _ref.placement,
29
- nativeSetDragImage = _ref.nativeSetDragImage;
30
- if ((placement === null || placement === void 0 ? void 0 : placement.type) === 'center') {
31
- var box = container.getBoundingClientRect();
32
- nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, box.width / 2, box.height / 2);
33
- return;
34
- }
35
- if ((placement === null || placement === void 0 ? void 0 : placement.type) === 'offset-from-pointer') {
36
- // Using a transparent border to push the drag preview away
37
- // from the user's pointer.
38
- // In Chrome and Safari we could use `padding`:
39
- // padding: 'var(--grid)',
40
- // But it does not work in Firefox which trims the padding (or inner margin)
41
- Object.assign(container.style, {
42
- borderLeft: "".concat(placement.x, " solid transparent"),
43
- borderTop: "".concat(placement.y, " solid transparent")
44
- });
45
- }
46
- nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, 0, 0);
14
+ /** By default we use the build in values for the native drag preview: {x: 0, y: 0} */
15
+ function defaultOffset() {
16
+ return {
17
+ x: 0,
18
+ y: 0
19
+ };
47
20
  }
48
21
 
49
22
  /** This function provides the ability to mount an element for it to be used as the native drag preview
@@ -61,10 +34,11 @@ function setImage(_ref) {
61
34
  * },
62
35
  * });
63
36
  */
64
- function setCustomNativeDragPreview(_ref2) {
65
- var render = _ref2.render,
66
- nativeSetDragImage = _ref2.nativeSetDragImage,
67
- placement = _ref2.placement;
37
+ function setCustomNativeDragPreview(_ref) {
38
+ var render = _ref.render,
39
+ nativeSetDragImage = _ref.nativeSetDragImage,
40
+ _ref$getOffset = _ref.getOffset,
41
+ getOffset = _ref$getOffset === void 0 ? defaultOffset : _ref$getOffset;
68
42
  var container = document.createElement('div');
69
43
  Object.assign(container.style, {
70
44
  // Ensuring we don't cause reflow when adding the element to the page
@@ -90,11 +64,10 @@ function setCustomNativeDragPreview(_ref2) {
90
64
  var unmount = render({
91
65
  container: container
92
66
  });
93
- setImage({
94
- container: container,
95
- placement: placement,
96
- nativeSetDragImage: nativeSetDragImage
67
+ var previewOffset = getOffset({
68
+ container: container
97
69
  });
70
+ nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, previewOffset.x, previewOffset.y);
98
71
  function cleanup() {
99
72
  unbindMonitor();
100
73
  unmount === null || unmount === void 0 ? void 0 : unmount();
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/pragmatic-drag-and-drop",
3
- "version": "0.18.2",
3
+ "version": "0.20.0",
4
4
  "sideEffects": false
5
5
  }
@@ -0,0 +1 @@
1
+ export { centerUnderPointer } from '../../util/custom-native-drag-preview/center-under-pointer';
@@ -0,0 +1 @@
1
+ export { offsetFromPointer } from '../../util/custom-native-drag-preview/offset-from-pointer';
@@ -1 +1 @@
1
- export { setCustomNativeDragPreview } from '../../util/set-custom-native-drag-preview';
1
+ export { setCustomNativeDragPreview } from '../../util/custom-native-drag-preview/set-custom-native-drag-preview';
@@ -37,7 +37,7 @@ export function makeDropTarget({
37
37
  input,
38
38
  result = []
39
39
  }) {
40
- var _args$getData, _args$getData2, _args$getDropEffect, _args$getDropEffect2, _args$getIsSticky;
40
+ var _args$getData, _args$getData2, _args$getDropEffect, _args$getDropEffect2;
41
41
  if (!(target instanceof Element)) {
42
42
  return result;
43
43
  }
@@ -70,14 +70,17 @@ export function makeDropTarget({
70
70
  result
71
71
  });
72
72
  }
73
+
74
+ // calculate our new record
73
75
  const data = (_args$getData = (_args$getData2 = args.getData) === null || _args$getData2 === void 0 ? void 0 : _args$getData2.call(args, feedback)) !== null && _args$getData !== void 0 ? _args$getData : {};
74
76
  const dropEffect = (_args$getDropEffect = (_args$getDropEffect2 = args.getDropEffect) === null || _args$getDropEffect2 === void 0 ? void 0 : _args$getDropEffect2.call(args, feedback)) !== null && _args$getDropEffect !== void 0 ? _args$getDropEffect : defaultDropEffect;
75
- const sticky = Boolean((_args$getIsSticky = args.getIsSticky) === null || _args$getIsSticky === void 0 ? void 0 : _args$getIsSticky.call(args, feedback));
76
77
  const record = {
77
78
  data,
78
79
  element: args.element,
79
80
  dropEffect,
80
- sticky
81
+ // we are collecting _actual_ drop targets, so these are
82
+ // being applied _not_ due to stickiness
83
+ isActiveDueToStickiness: false
81
84
  };
82
85
  return getActualDropTargets({
83
86
  source,
@@ -181,6 +184,7 @@ export function makeDropTarget({
181
184
  const actualCaptureOrdered = copyReverse(actual);
182
185
  const resultCaptureOrdered = [];
183
186
  for (let index = 0; index < lastCaptureOrdered.length; index++) {
187
+ var _argsForLast$getIsSti;
184
188
  const last = lastCaptureOrdered[index];
185
189
  const fresh = actualCaptureOrdered[index];
186
190
 
@@ -194,29 +198,52 @@ export function makeDropTarget({
194
198
  // At this point we have no drop target in the old spot
195
199
  // Check to see if we can use a previous sticky drop target
196
200
 
197
- // stickiness is based on relationships to a parent
198
- // so if we hit a drop target that is not sticky we
199
- // can finish our search
200
- if (!last.sticky) {
201
- break;
202
- }
203
-
204
- // We only want the previous sticky item to 'stick' if
205
- // the parent of the sticky item is unchanged
206
-
207
201
  // The "parent" is the one inside of `resultCaptureOrdered`
208
202
  // (the parent might be a drop target that was sticky)
209
203
  const parent = resultCaptureOrdered[index - 1];
210
204
  const lastParent = lastCaptureOrdered[index - 1];
211
205
 
212
- // parents are the same (might both be undefined for index == 0)
213
- // we can add the last entry and keep searching
214
- if ((parent === null || parent === void 0 ? void 0 : parent.element) === (lastParent === null || lastParent === void 0 ? void 0 : lastParent.element)) {
215
- resultCaptureOrdered.push(last);
216
- continue;
206
+ // Stickiness is based on parent relationships, so if the parent relationship has change
207
+ // then we can stop our search
208
+ if ((parent === null || parent === void 0 ? void 0 : parent.element) !== (lastParent === null || lastParent === void 0 ? void 0 : lastParent.element)) {
209
+ break;
210
+ }
211
+
212
+ // We need to check whether the old drop target can still be dropped on
213
+
214
+ const argsForLast = registry.get(last.element);
215
+
216
+ // We cannot drop on a drop target that is no longer mounted
217
+ if (!argsForLast) {
218
+ break;
217
219
  }
218
- // parents are not the same, we can exit our search
219
- break;
220
+ const feedback = {
221
+ input,
222
+ source,
223
+ element: argsForLast.element
224
+ };
225
+
226
+ // We cannot drop on a drop target that no longer allows being dropped on
227
+ if (argsForLast.canDrop && !argsForLast.canDrop(feedback)) {
228
+ break;
229
+ }
230
+
231
+ // We cannot drop on a drop target that is no longer sticky
232
+ if (!((_argsForLast$getIsSti = argsForLast.getIsSticky) !== null && _argsForLast$getIsSti !== void 0 && _argsForLast$getIsSti.call(argsForLast, feedback))) {
233
+ break;
234
+ }
235
+
236
+ // Note: intentionally not recollecting `getData()` or `getDropEffect()`
237
+ // Previous values for `data` and `dropEffect` will be borrowed
238
+ // This is to prevent things like the 'closest edge' changing when
239
+ // no longer over a drop target.
240
+ // We could change our mind on this behaviour in the future
241
+
242
+ resultCaptureOrdered.push({
243
+ ...last,
244
+ // making it clear to consumers this drop target is active due to stickiness
245
+ isActiveDueToStickiness: true
246
+ });
220
247
  }
221
248
 
222
249
  // return bubble ordered result
@@ -0,0 +1,9 @@
1
+ export const centerUnderPointer = function centerUnderPointer({
2
+ container
3
+ }) {
4
+ const rect = container.getBoundingClientRect();
5
+ return {
6
+ x: rect.width / 2,
7
+ y: rect.height / 2
8
+ };
9
+ };