@atlaskit/pragmatic-drag-and-drop 0.24.0 → 0.25.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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # @atlaskit/pragmatic-drag-and-drop
2
2
 
3
+ ## 0.25.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#59458](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/59458) [`7d6a69cfa61c`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/7d6a69cfa61c) - Adding workaround for Safari bug.
8
+
9
+ In Safari (and iOS) if the element used for generating a native drag preview has opacity applied, then the native drag preview can include elements underneath the drag preview element.
10
+
11
+ Pragmatic drag and drop now includes a workaround for this Safari bug.
12
+
3
13
  ## 0.24.0
4
14
 
5
15
  ### Minor Changes
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.setCustomNativeDragPreview = setCustomNativeDragPreview;
7
7
  var _elementAdapter = require("../../adapter/element-adapter");
8
+ var _isSafari = require("../is-safari");
8
9
  /** A function to remove the element that has been added to the `container`.
9
10
  * @example () => ReactDOM.unmountComponentAtNode(container)
10
11
  */
@@ -46,6 +47,13 @@ function setCustomNativeDragPreview(_ref) {
46
47
  // positioned on the current viewport.
47
48
  // `position:fixed` also creates a new stacking context, so we don't need to do that here
48
49
  position: 'fixed',
50
+ // According to `mdn`, the element can be offscreen:
51
+ // https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage#imgelement
52
+ //
53
+ // However, that information does not appear in the specs:
54
+ // https://html.spec.whatwg.org/multipage/dnd.html#dom-datatransfer-setdragimage-dev
55
+ //
56
+ // If the element is _completely_ offscreen, Safari@17.1 will cancel the drag
49
57
  top: 0,
50
58
  left: 0,
51
59
  // Using maximum possible z-index so that this element will always be on top
@@ -67,6 +75,32 @@ function setCustomNativeDragPreview(_ref) {
67
75
  var previewOffset = getOffset({
68
76
  container: container
69
77
  });
78
+
79
+ /**
80
+ * **Problem**
81
+ * On `Safari@17.1` if a drag preview element has some opacity,
82
+ * Safari will include elements behind the drag preview element
83
+ * in the drag preview.
84
+ *
85
+ * **Fix**
86
+ * We push the drag preview so it is _almost_ completely offscreen so that
87
+ * there won't be any elements behind the drag preview element.
88
+ * If the element is _completely_ offscreen, then the drag is cancelled by Safari.
89
+ *
90
+ * Using `-0.0001` so that any potential "see through" on the drag preview element
91
+ * is effectively invisible 👻
92
+ *
93
+ * **Unsuccessful alternatives**
94
+ * Setting a background color (eg "white") on the `container`
95
+ * → Wrecks the opacity of the drag preview element
96
+ *
97
+ * Adding a parent element of the `container` with a background color (eg "white")
98
+ * → Wrecks the opacity of the drag preview element
99
+ */
100
+ if ((0, _isSafari.isSafari)()) {
101
+ var rect = container.getBoundingClientRect();
102
+ container.style.left = "-".concat(rect.width - 0.0001, "px");
103
+ }
70
104
  nativeSetDragImage === null || nativeSetDragImage === void 0 || nativeSetDragImage(container, previewOffset.x, previewOffset.y);
71
105
  function cleanup() {
72
106
  unbindMonitor();
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.isEnteringWindow = isEnteringWindow;
7
7
  exports.isLeavingWindow = isLeavingWindow;
8
8
  var _bindEventListener = require("bind-event-listener");
9
+ var _isSafari = require("./is-safari");
9
10
  // *Usually* to detect if you are entering / leaving a window you can
10
11
  // use the `event.relatedTarget` property:
11
12
 
@@ -75,10 +76,7 @@ function isLeavingWindow(_ref2) {
75
76
  if (process.env.NODE_ENV === 'test') {
76
77
  return;
77
78
  }
78
- var _navigator = navigator,
79
- userAgent = _navigator.userAgent;
80
- var isSafari = userAgent.includes('AppleWebKit') && !userAgent.includes('Chrome');
81
- if (!isSafari) {
79
+ if (!(0, _isSafari.isSafari)()) {
82
80
  return;
83
81
  }
84
82
  safariFix.isSafari = true;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isSafari = isSafari;
7
+ // Once we know we are in Safari or not, we don't need to do the check again
8
+ var cache = null;
9
+
10
+ /**
11
+ * Returns `true` if a `Safari` browser.
12
+ * Returns `true` if the browser is running on iOS (they are all Safari).
13
+ * */
14
+ function isSafari() {
15
+ if (typeof cache === 'boolean') {
16
+ return cache;
17
+ }
18
+ var _navigator = navigator,
19
+ userAgent = _navigator.userAgent;
20
+ cache = userAgent.includes('AppleWebKit') && !userAgent.includes('Chrome');
21
+ return cache;
22
+ }
@@ -1,4 +1,5 @@
1
1
  import { monitorForElements } from '../../adapter/element-adapter';
2
+ import { isSafari } from '../is-safari';
2
3
 
3
4
  /** A function to remove the element that has been added to the `container`.
4
5
  * @example () => ReactDOM.unmountComponentAtNode(container)
@@ -41,6 +42,13 @@ export function setCustomNativeDragPreview({
41
42
  // positioned on the current viewport.
42
43
  // `position:fixed` also creates a new stacking context, so we don't need to do that here
43
44
  position: 'fixed',
45
+ // According to `mdn`, the element can be offscreen:
46
+ // https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage#imgelement
47
+ //
48
+ // However, that information does not appear in the specs:
49
+ // https://html.spec.whatwg.org/multipage/dnd.html#dom-datatransfer-setdragimage-dev
50
+ //
51
+ // If the element is _completely_ offscreen, Safari@17.1 will cancel the drag
44
52
  top: 0,
45
53
  left: 0,
46
54
  // Using maximum possible z-index so that this element will always be on top
@@ -62,6 +70,32 @@ export function setCustomNativeDragPreview({
62
70
  const previewOffset = getOffset({
63
71
  container
64
72
  });
73
+
74
+ /**
75
+ * **Problem**
76
+ * On `Safari@17.1` if a drag preview element has some opacity,
77
+ * Safari will include elements behind the drag preview element
78
+ * in the drag preview.
79
+ *
80
+ * **Fix**
81
+ * We push the drag preview so it is _almost_ completely offscreen so that
82
+ * there won't be any elements behind the drag preview element.
83
+ * If the element is _completely_ offscreen, then the drag is cancelled by Safari.
84
+ *
85
+ * Using `-0.0001` so that any potential "see through" on the drag preview element
86
+ * is effectively invisible 👻
87
+ *
88
+ * **Unsuccessful alternatives**
89
+ * Setting a background color (eg "white") on the `container`
90
+ * → Wrecks the opacity of the drag preview element
91
+ *
92
+ * Adding a parent element of the `container` with a background color (eg "white")
93
+ * → Wrecks the opacity of the drag preview element
94
+ */
95
+ if (isSafari()) {
96
+ const rect = container.getBoundingClientRect();
97
+ container.style.left = `-${rect.width - 0.0001}px`;
98
+ }
65
99
  nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, previewOffset.x, previewOffset.y);
66
100
  function cleanup() {
67
101
  unbindMonitor();
@@ -1,4 +1,5 @@
1
1
  import { bindAll } from 'bind-event-listener';
2
+ import { isSafari } from './is-safari';
2
3
 
3
4
  // *Usually* to detect if you are entering / leaving a window you can
4
5
  // use the `event.relatedTarget` property:
@@ -71,11 +72,7 @@ export function isLeavingWindow({
71
72
  if (process.env.NODE_ENV === 'test') {
72
73
  return;
73
74
  }
74
- const {
75
- userAgent
76
- } = navigator;
77
- const isSafari = userAgent.includes('AppleWebKit') && !userAgent.includes('Chrome');
78
- if (!isSafari) {
75
+ if (!isSafari()) {
79
76
  return;
80
77
  }
81
78
  safariFix.isSafari = true;
@@ -0,0 +1,17 @@
1
+ // Once we know we are in Safari or not, we don't need to do the check again
2
+ let cache = null;
3
+
4
+ /**
5
+ * Returns `true` if a `Safari` browser.
6
+ * Returns `true` if the browser is running on iOS (they are all Safari).
7
+ * */
8
+ export function isSafari() {
9
+ if (typeof cache === 'boolean') {
10
+ return cache;
11
+ }
12
+ const {
13
+ userAgent
14
+ } = navigator;
15
+ cache = userAgent.includes('AppleWebKit') && !userAgent.includes('Chrome');
16
+ return cache;
17
+ }
@@ -1,4 +1,5 @@
1
1
  import { monitorForElements } from '../../adapter/element-adapter';
2
+ import { isSafari } from '../is-safari';
2
3
 
3
4
  /** A function to remove the element that has been added to the `container`.
4
5
  * @example () => ReactDOM.unmountComponentAtNode(container)
@@ -41,6 +42,13 @@ export function setCustomNativeDragPreview(_ref) {
41
42
  // positioned on the current viewport.
42
43
  // `position:fixed` also creates a new stacking context, so we don't need to do that here
43
44
  position: 'fixed',
45
+ // According to `mdn`, the element can be offscreen:
46
+ // https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage#imgelement
47
+ //
48
+ // However, that information does not appear in the specs:
49
+ // https://html.spec.whatwg.org/multipage/dnd.html#dom-datatransfer-setdragimage-dev
50
+ //
51
+ // If the element is _completely_ offscreen, Safari@17.1 will cancel the drag
44
52
  top: 0,
45
53
  left: 0,
46
54
  // Using maximum possible z-index so that this element will always be on top
@@ -62,6 +70,32 @@ export function setCustomNativeDragPreview(_ref) {
62
70
  var previewOffset = getOffset({
63
71
  container: container
64
72
  });
73
+
74
+ /**
75
+ * **Problem**
76
+ * On `Safari@17.1` if a drag preview element has some opacity,
77
+ * Safari will include elements behind the drag preview element
78
+ * in the drag preview.
79
+ *
80
+ * **Fix**
81
+ * We push the drag preview so it is _almost_ completely offscreen so that
82
+ * there won't be any elements behind the drag preview element.
83
+ * If the element is _completely_ offscreen, then the drag is cancelled by Safari.
84
+ *
85
+ * Using `-0.0001` so that any potential "see through" on the drag preview element
86
+ * is effectively invisible 👻
87
+ *
88
+ * **Unsuccessful alternatives**
89
+ * Setting a background color (eg "white") on the `container`
90
+ * → Wrecks the opacity of the drag preview element
91
+ *
92
+ * Adding a parent element of the `container` with a background color (eg "white")
93
+ * → Wrecks the opacity of the drag preview element
94
+ */
95
+ if (isSafari()) {
96
+ var rect = container.getBoundingClientRect();
97
+ container.style.left = "-".concat(rect.width - 0.0001, "px");
98
+ }
65
99
  nativeSetDragImage === null || nativeSetDragImage === void 0 || nativeSetDragImage(container, previewOffset.x, previewOffset.y);
66
100
  function cleanup() {
67
101
  unbindMonitor();
@@ -1,4 +1,5 @@
1
1
  import { bindAll } from 'bind-event-listener';
2
+ import { isSafari } from './is-safari';
2
3
 
3
4
  // *Usually* to detect if you are entering / leaving a window you can
4
5
  // use the `event.relatedTarget` property:
@@ -69,10 +70,7 @@ export function isLeavingWindow(_ref2) {
69
70
  if (process.env.NODE_ENV === 'test') {
70
71
  return;
71
72
  }
72
- var _navigator = navigator,
73
- userAgent = _navigator.userAgent;
74
- var isSafari = userAgent.includes('AppleWebKit') && !userAgent.includes('Chrome');
75
- if (!isSafari) {
73
+ if (!isSafari()) {
76
74
  return;
77
75
  }
78
76
  safariFix.isSafari = true;
@@ -0,0 +1,16 @@
1
+ // Once we know we are in Safari or not, we don't need to do the check again
2
+ var cache = null;
3
+
4
+ /**
5
+ * Returns `true` if a `Safari` browser.
6
+ * Returns `true` if the browser is running on iOS (they are all Safari).
7
+ * */
8
+ export function isSafari() {
9
+ if (typeof cache === 'boolean') {
10
+ return cache;
11
+ }
12
+ var _navigator = navigator,
13
+ userAgent = _navigator.userAgent;
14
+ cache = userAgent.includes('AppleWebKit') && !userAgent.includes('Chrome');
15
+ return cache;
16
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Returns `true` if a `Safari` browser.
3
+ * Returns `true` if the browser is running on iOS (they are all Safari).
4
+ * */
5
+ export declare function isSafari(): boolean;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Returns `true` if a `Safari` browser.
3
+ * Returns `true` if the browser is running on iOS (they are all Safari).
4
+ * */
5
+ export declare function isSafari(): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/pragmatic-drag-and-drop",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "description": "The core Pragmatic drag and drop framework, enabling flexible and fast drag and drop for any experience on any tech stack",
5
5
  "repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
6
6
  "author": "Atlassian Pty Ltd",
@@ -1,13 +0,0 @@
1
- ## API Report File for "@atlaskit/pragmatic-drag-and-drop"
2
-
3
- > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
4
-
5
- ```ts
6
-
7
- // @public (undocumented)
8
- const _default: {};
9
- export default _default;
10
-
11
- // (No @packageDocumentation comment for this package)
12
-
13
- ```