@atlaskit/pragmatic-drag-and-drop 1.7.2 → 1.7.4

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,43 @@
1
1
  # @atlaskit/pragmatic-drag-and-drop
2
2
 
3
+ ## 1.7.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#174472](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/174472)
8
+ [`fda983a832f81`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/fda983a832f81) -
9
+ On Android `pointerOutsideOfPreview` will now also center the drag preview under the users
10
+ pointer. Technically this was already existing observed behaviour as Android always centers the
11
+ drag preview under the users pointer. We now make this behaviour explicit in the code, and call
12
+ this out behaviour in jsdoc and documentation.
13
+
14
+ ## 1.7.3
15
+
16
+ ### Patch Changes
17
+
18
+ - [#173859](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/173859)
19
+ [`d6f17206f8859`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/d6f17206f8859) -
20
+ In order to provide the best experience for iOS, the optional function `pointerOutsideOfPreview`
21
+ will now center the drag preview under the users pointer on iOS.
22
+
23
+ Some more detail (in case you are interested):
24
+
25
+ **Borders**
26
+
27
+ _(Existing behaviour)_
28
+
29
+ In `pointerOutsideOfPreview` we use transparent borders to push the preview away from the users
30
+ pointer. On iOS these borders will always be black. So we don't use transparent border on iOS.
31
+
32
+ **Placement**
33
+
34
+ _(Improvement)_
35
+
36
+ During a drag on iOS the drag preview will shift under the center of the users pointer, even if we
37
+ start the drag with the users pointer on the top left or top right corner of the drag preview. So
38
+ now `pointerOutsideOfPreview` will always put the preview under the center of the users pointer in
39
+ order to avoid the drag preview position shifting as the drag is starting.
40
+
3
41
  ## 1.7.2
4
42
 
5
43
  ### Patch Changes
@@ -4,7 +4,9 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.pointerOutsideOfPreview = pointerOutsideOfPreview;
7
+ var _android = require("../../../util/android");
7
8
  var _isSafariOnIos = require("../../../util/is-safari-on-ios");
9
+ var _centerUnderPointer = require("./center-under-pointer");
8
10
  /** Any valid CSS string value
9
11
  * @example `calc(var(--grid) * 2)
10
12
  */
@@ -26,15 +28,13 @@ var _isSafariOnIos = require("../../../util/is-safari-on-ios");
26
28
  * The direction will be calculated based on the direction (`dir`) being applied to the `container`
27
29
  * element (which will be a child of the `body` element).
28
30
  *
29
- * **iOS**
31
+ * **iOS, iPadOS and Android**
30
32
  *
31
- * This function will not push the preview away from the users pointer on iOS due to platform limitations.
32
- * On iOS the preview will start the drag on the top left corner (or top right corner for right to left interfaces).
33
- * While dragging, iOS will shift the drag preview under the center of the users pointer, so the "pushing away"
34
- * is short lived on iOS.
33
+ * The drag preview will be centered under the users pointer rather than
34
+ * pushed away on iOS due to platform limitations.
35
35
  */
36
36
  function pointerOutsideOfPreview(point) {
37
- return function (_ref) {
37
+ return function getOffset(_ref) {
38
38
  var container = _ref.container;
39
39
  /**
40
40
  * **Approach: transparent borders.**
@@ -42,27 +42,55 @@ function pointerOutsideOfPreview(point) {
42
42
  * The only reliable cross browser technique found to push a
43
43
  * drag preview away from the cursor is to use transparent borders on the container.
44
44
  *
45
- * **🙅📱 Not pushing the preview away on iOS**
45
+ * **🙅📱 Not pushing the preview away on touch devices**
46
46
  *
47
- * On iOS, the browser will set the transparent border color to be black. We can provide a
48
- * more polished experience not using the transparent border on iOS.
47
+ * _On iOS_
49
48
  *
50
- * While dragging, iOS will shift the drag preview under the center of the users pointer,
51
- * so the "pushing away" of the preview is short lived on iOS anyway.
49
+ * Safari will set the transparent border color to be black
52
50
  *
53
- * Notes:
54
- *
55
- * - Tested on `iOS@18.4.1` on May 7th 2025
51
+ * `iOS@18.4.1` on May 7th 2025:
56
52
  * - If you set the background color on the `container` the border color will be that
57
- * - Setting a transparent background color on the `container` still results in a black border
53
+ * - Setting a transparent background color on the `container` still results in a
54
+ * black border
58
55
  * - The `<body>` text or background color does not change the black border color
56
+ *
57
+ * While dragging, the drag preview will shift under the center of the users pointer.
58
+ * So if you start at {x: 0, y: 0} (top left), almost immediately the preview will move
59
+ * to be under the middle of the users pointer.
60
+ *
61
+ * _On Android_
62
+ *
63
+ * Chrome will put the center of the drag preview under the users pointer immediately.
64
+ *
65
+ * Tested on `Chrome@137` on `Android 14` on June 20th 2025
66
+ *
67
+ * _What we do_
68
+ *
69
+ * We don't add the transparent border
70
+ *
71
+ * - Avoid the black color on iOS
72
+ * - It isn't needed on Android anyway as the preview will be under the center
73
+ * of the users pointer
74
+ *
75
+ * We put the center of the drag preview under the users pointer
76
+ *
77
+ * - Avoids the drag preview quickly moving from a top corner to be centered under
78
+ * the users pointer on iOS
79
+ * - It will be under the center on Android no matter what we do
80
+ *
81
+ * We previously had a isTouchDevice() check, but it felt safer for now
82
+ * to have a more targeted check, as these are the devices that have been
83
+ * tested on.
59
84
  */
60
- if (!(0, _isSafariOnIos.isSafariOnIOS)()) {
61
- Object.assign(container.style, {
62
- borderInlineStart: "".concat(point.x, " solid transparent"),
63
- borderTop: "".concat(point.y, " solid transparent")
85
+ if ((0, _isSafariOnIos.isSafariOnIOS)() || (0, _android.isAndroid)()) {
86
+ return (0, _centerUnderPointer.centerUnderPointer)({
87
+ container: container
64
88
  });
65
89
  }
90
+ Object.assign(container.style, {
91
+ borderInlineStart: "".concat(point.x, " solid transparent"),
92
+ borderTop: "".concat(point.y, " solid transparent")
93
+ });
66
94
 
67
95
  // Unfortunate that we need to use `getComputedStyle`,
68
96
  // but it's only a single call when the drag is starting.
@@ -7,8 +7,25 @@ exports.preserveOffsetOnSource = preserveOffsetOnSource;
7
7
  function preserveOffsetOnSource(_ref) {
8
8
  var element = _ref.element,
9
9
  input = _ref.input;
10
- return function (_ref2) {
10
+ return function getOffset(_ref2) {
11
11
  var container = _ref2.container;
12
+ /**
13
+ * **Android**
14
+ *
15
+ * This function won't do anything 😅.
16
+ * The drag preview will _always_ be under the center of the users pointer.
17
+ * There is no harm in calling this function though 🧘.
18
+ *
19
+ * **iOS and iPadOS**
20
+ *
21
+ * The drag preview is lifted in the expected position and then slides under
22
+ * the users pointer.
23
+ * This is more pleasing than immediately putting the center of the drag preview
24
+ * under the users pointer.
25
+ * With this function the drag preview looks like it is popping out
26
+ * of the UI and then it shifts under the users pointer as the drag is occurring ✨
27
+ */
28
+
12
29
  var sourceRect = element.getBoundingClientRect();
13
30
  var containerRect = container.getBoundingClientRect();
14
31
  var offsetX = Math.min(
@@ -5,7 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.isAndroid = exports.androidFallbackText = void 0;
7
7
  var _once = require("../public-utils/once");
8
- // using `cache` as our `isAndroid()` result will not change in a browser
8
+ // Using `once` as the value won't change in a browser
9
+
9
10
  var isAndroid = exports.isAndroid = (0, _once.once)(function isAndroid() {
10
11
  return navigator.userAgent.toLocaleLowerCase().includes('android');
11
12
  });
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.isSafariOnIOS = void 0;
7
7
  var _once = require("../public-utils/once");
8
8
  var _isSafari = require("./is-safari");
9
- // Using `cache` as our `isIOS()` result will not change in a browser
9
+ // Using `once` as the value won't change in a browser
10
10
 
11
11
  /**
12
12
  * **Notes**
@@ -1,4 +1,6 @@
1
+ import { isAndroid } from '../../../util/android';
1
2
  import { isSafariOnIOS } from '../../../util/is-safari-on-ios';
3
+ import { centerUnderPointer } from './center-under-pointer';
2
4
 
3
5
  /** Any valid CSS string value
4
6
  * @example `calc(var(--grid) * 2)
@@ -21,44 +23,70 @@ import { isSafariOnIOS } from '../../../util/is-safari-on-ios';
21
23
  * The direction will be calculated based on the direction (`dir`) being applied to the `container`
22
24
  * element (which will be a child of the `body` element).
23
25
  *
24
- * **iOS**
26
+ * **iOS, iPadOS and Android**
25
27
  *
26
- * This function will not push the preview away from the users pointer on iOS due to platform limitations.
27
- * On iOS the preview will start the drag on the top left corner (or top right corner for right to left interfaces).
28
- * While dragging, iOS will shift the drag preview under the center of the users pointer, so the "pushing away"
29
- * is short lived on iOS.
28
+ * The drag preview will be centered under the users pointer rather than
29
+ * pushed away on iOS due to platform limitations.
30
30
  */
31
31
  export function pointerOutsideOfPreview(point) {
32
- return ({
32
+ return function getOffset({
33
33
  container
34
- }) => {
34
+ }) {
35
35
  /**
36
36
  * **Approach: transparent borders.**
37
37
  *
38
38
  * The only reliable cross browser technique found to push a
39
39
  * drag preview away from the cursor is to use transparent borders on the container.
40
40
  *
41
- * **🙅📱 Not pushing the preview away on iOS**
41
+ * **🙅📱 Not pushing the preview away on touch devices**
42
42
  *
43
- * On iOS, the browser will set the transparent border color to be black. We can provide a
44
- * more polished experience not using the transparent border on iOS.
43
+ * _On iOS_
45
44
  *
46
- * While dragging, iOS will shift the drag preview under the center of the users pointer,
47
- * so the "pushing away" of the preview is short lived on iOS anyway.
45
+ * Safari will set the transparent border color to be black
48
46
  *
49
- * Notes:
50
- *
51
- * - Tested on `iOS@18.4.1` on May 7th 2025
47
+ * `iOS@18.4.1` on May 7th 2025:
52
48
  * - If you set the background color on the `container` the border color will be that
53
- * - Setting a transparent background color on the `container` still results in a black border
49
+ * - Setting a transparent background color on the `container` still results in a
50
+ * black border
54
51
  * - The `<body>` text or background color does not change the black border color
52
+ *
53
+ * While dragging, the drag preview will shift under the center of the users pointer.
54
+ * So if you start at {x: 0, y: 0} (top left), almost immediately the preview will move
55
+ * to be under the middle of the users pointer.
56
+ *
57
+ * _On Android_
58
+ *
59
+ * Chrome will put the center of the drag preview under the users pointer immediately.
60
+ *
61
+ * Tested on `Chrome@137` on `Android 14` on June 20th 2025
62
+ *
63
+ * _What we do_
64
+ *
65
+ * We don't add the transparent border
66
+ *
67
+ * - Avoid the black color on iOS
68
+ * - It isn't needed on Android anyway as the preview will be under the center
69
+ * of the users pointer
70
+ *
71
+ * We put the center of the drag preview under the users pointer
72
+ *
73
+ * - Avoids the drag preview quickly moving from a top corner to be centered under
74
+ * the users pointer on iOS
75
+ * - It will be under the center on Android no matter what we do
76
+ *
77
+ * We previously had a isTouchDevice() check, but it felt safer for now
78
+ * to have a more targeted check, as these are the devices that have been
79
+ * tested on.
55
80
  */
56
- if (!isSafariOnIOS()) {
57
- Object.assign(container.style, {
58
- borderInlineStart: `${point.x} solid transparent`,
59
- borderTop: `${point.y} solid transparent`
81
+ if (isSafariOnIOS() || isAndroid()) {
82
+ return centerUnderPointer({
83
+ container
60
84
  });
61
85
  }
86
+ Object.assign(container.style, {
87
+ borderInlineStart: `${point.x} solid transparent`,
88
+ borderTop: `${point.y} solid transparent`
89
+ });
62
90
 
63
91
  // Unfortunate that we need to use `getComputedStyle`,
64
92
  // but it's only a single call when the drag is starting.
@@ -2,9 +2,26 @@ export function preserveOffsetOnSource({
2
2
  element,
3
3
  input
4
4
  }) {
5
- return ({
5
+ return function getOffset({
6
6
  container
7
- }) => {
7
+ }) {
8
+ /**
9
+ * **Android**
10
+ *
11
+ * This function won't do anything 😅.
12
+ * The drag preview will _always_ be under the center of the users pointer.
13
+ * There is no harm in calling this function though 🧘.
14
+ *
15
+ * **iOS and iPadOS**
16
+ *
17
+ * The drag preview is lifted in the expected position and then slides under
18
+ * the users pointer.
19
+ * This is more pleasing than immediately putting the center of the drag preview
20
+ * under the users pointer.
21
+ * With this function the drag preview looks like it is popping out
22
+ * of the UI and then it shifts under the users pointer as the drag is occurring ✨
23
+ */
24
+
8
25
  const sourceRect = element.getBoundingClientRect();
9
26
  const containerRect = container.getBoundingClientRect();
10
27
  const offsetX = Math.min(
@@ -1,6 +1,7 @@
1
1
  import { once } from '../public-utils/once';
2
2
 
3
- // using `cache` as our `isAndroid()` result will not change in a browser
3
+ // Using `once` as the value won't change in a browser
4
+
4
5
  export const isAndroid = once(function isAndroid() {
5
6
  return navigator.userAgent.toLocaleLowerCase().includes('android');
6
7
  });
@@ -1,7 +1,7 @@
1
1
  import { once } from '../public-utils/once';
2
2
  import { isSafari } from './is-safari';
3
3
 
4
- // Using `cache` as our `isIOS()` result will not change in a browser
4
+ // Using `once` as the value won't change in a browser
5
5
 
6
6
  /**
7
7
  * **Notes**
@@ -1,4 +1,6 @@
1
+ import { isAndroid } from '../../../util/android';
1
2
  import { isSafariOnIOS } from '../../../util/is-safari-on-ios';
3
+ import { centerUnderPointer } from './center-under-pointer';
2
4
 
3
5
  /** Any valid CSS string value
4
6
  * @example `calc(var(--grid) * 2)
@@ -21,15 +23,13 @@ import { isSafariOnIOS } from '../../../util/is-safari-on-ios';
21
23
  * The direction will be calculated based on the direction (`dir`) being applied to the `container`
22
24
  * element (which will be a child of the `body` element).
23
25
  *
24
- * **iOS**
26
+ * **iOS, iPadOS and Android**
25
27
  *
26
- * This function will not push the preview away from the users pointer on iOS due to platform limitations.
27
- * On iOS the preview will start the drag on the top left corner (or top right corner for right to left interfaces).
28
- * While dragging, iOS will shift the drag preview under the center of the users pointer, so the "pushing away"
29
- * is short lived on iOS.
28
+ * The drag preview will be centered under the users pointer rather than
29
+ * pushed away on iOS due to platform limitations.
30
30
  */
31
31
  export function pointerOutsideOfPreview(point) {
32
- return function (_ref) {
32
+ return function getOffset(_ref) {
33
33
  var container = _ref.container;
34
34
  /**
35
35
  * **Approach: transparent borders.**
@@ -37,27 +37,55 @@ export function pointerOutsideOfPreview(point) {
37
37
  * The only reliable cross browser technique found to push a
38
38
  * drag preview away from the cursor is to use transparent borders on the container.
39
39
  *
40
- * **🙅📱 Not pushing the preview away on iOS**
40
+ * **🙅📱 Not pushing the preview away on touch devices**
41
41
  *
42
- * On iOS, the browser will set the transparent border color to be black. We can provide a
43
- * more polished experience not using the transparent border on iOS.
42
+ * _On iOS_
44
43
  *
45
- * While dragging, iOS will shift the drag preview under the center of the users pointer,
46
- * so the "pushing away" of the preview is short lived on iOS anyway.
44
+ * Safari will set the transparent border color to be black
47
45
  *
48
- * Notes:
49
- *
50
- * - Tested on `iOS@18.4.1` on May 7th 2025
46
+ * `iOS@18.4.1` on May 7th 2025:
51
47
  * - If you set the background color on the `container` the border color will be that
52
- * - Setting a transparent background color on the `container` still results in a black border
48
+ * - Setting a transparent background color on the `container` still results in a
49
+ * black border
53
50
  * - The `<body>` text or background color does not change the black border color
51
+ *
52
+ * While dragging, the drag preview will shift under the center of the users pointer.
53
+ * So if you start at {x: 0, y: 0} (top left), almost immediately the preview will move
54
+ * to be under the middle of the users pointer.
55
+ *
56
+ * _On Android_
57
+ *
58
+ * Chrome will put the center of the drag preview under the users pointer immediately.
59
+ *
60
+ * Tested on `Chrome@137` on `Android 14` on June 20th 2025
61
+ *
62
+ * _What we do_
63
+ *
64
+ * We don't add the transparent border
65
+ *
66
+ * - Avoid the black color on iOS
67
+ * - It isn't needed on Android anyway as the preview will be under the center
68
+ * of the users pointer
69
+ *
70
+ * We put the center of the drag preview under the users pointer
71
+ *
72
+ * - Avoids the drag preview quickly moving from a top corner to be centered under
73
+ * the users pointer on iOS
74
+ * - It will be under the center on Android no matter what we do
75
+ *
76
+ * We previously had a isTouchDevice() check, but it felt safer for now
77
+ * to have a more targeted check, as these are the devices that have been
78
+ * tested on.
54
79
  */
55
- if (!isSafariOnIOS()) {
56
- Object.assign(container.style, {
57
- borderInlineStart: "".concat(point.x, " solid transparent"),
58
- borderTop: "".concat(point.y, " solid transparent")
80
+ if (isSafariOnIOS() || isAndroid()) {
81
+ return centerUnderPointer({
82
+ container: container
59
83
  });
60
84
  }
85
+ Object.assign(container.style, {
86
+ borderInlineStart: "".concat(point.x, " solid transparent"),
87
+ borderTop: "".concat(point.y, " solid transparent")
88
+ });
61
89
 
62
90
  // Unfortunate that we need to use `getComputedStyle`,
63
91
  // but it's only a single call when the drag is starting.
@@ -1,8 +1,25 @@
1
1
  export function preserveOffsetOnSource(_ref) {
2
2
  var element = _ref.element,
3
3
  input = _ref.input;
4
- return function (_ref2) {
4
+ return function getOffset(_ref2) {
5
5
  var container = _ref2.container;
6
+ /**
7
+ * **Android**
8
+ *
9
+ * This function won't do anything 😅.
10
+ * The drag preview will _always_ be under the center of the users pointer.
11
+ * There is no harm in calling this function though 🧘.
12
+ *
13
+ * **iOS and iPadOS**
14
+ *
15
+ * The drag preview is lifted in the expected position and then slides under
16
+ * the users pointer.
17
+ * This is more pleasing than immediately putting the center of the drag preview
18
+ * under the users pointer.
19
+ * With this function the drag preview looks like it is popping out
20
+ * of the UI and then it shifts under the users pointer as the drag is occurring ✨
21
+ */
22
+
6
23
  var sourceRect = element.getBoundingClientRect();
7
24
  var containerRect = container.getBoundingClientRect();
8
25
  var offsetX = Math.min(
@@ -1,6 +1,7 @@
1
1
  import { once } from '../public-utils/once';
2
2
 
3
- // using `cache` as our `isAndroid()` result will not change in a browser
3
+ // Using `once` as the value won't change in a browser
4
+
4
5
  export var isAndroid = once(function isAndroid() {
5
6
  return navigator.userAgent.toLocaleLowerCase().includes('android');
6
7
  });
@@ -1,7 +1,7 @@
1
1
  import { once } from '../public-utils/once';
2
2
  import { isSafari } from './is-safari';
3
3
 
4
- // Using `cache` as our `isIOS()` result will not change in a browser
4
+ // Using `once` as the value won't change in a browser
5
5
 
6
6
  /**
7
7
  * **Notes**
@@ -20,12 +20,10 @@ type CSSValue = string;
20
20
  * The direction will be calculated based on the direction (`dir`) being applied to the `container`
21
21
  * element (which will be a child of the `body` element).
22
22
  *
23
- * **iOS**
23
+ * **iOS, iPadOS and Android**
24
24
  *
25
- * This function will not push the preview away from the users pointer on iOS due to platform limitations.
26
- * On iOS the preview will start the drag on the top left corner (or top right corner for right to left interfaces).
27
- * While dragging, iOS will shift the drag preview under the center of the users pointer, so the "pushing away"
28
- * is short lived on iOS.
25
+ * The drag preview will be centered under the users pointer rather than
26
+ * pushed away on iOS due to platform limitations.
29
27
  */
30
28
  export declare function pointerOutsideOfPreview(point: {
31
29
  x: CSSValue;
@@ -20,12 +20,10 @@ type CSSValue = string;
20
20
  * The direction will be calculated based on the direction (`dir`) being applied to the `container`
21
21
  * element (which will be a child of the `body` element).
22
22
  *
23
- * **iOS**
23
+ * **iOS, iPadOS and Android**
24
24
  *
25
- * This function will not push the preview away from the users pointer on iOS due to platform limitations.
26
- * On iOS the preview will start the drag on the top left corner (or top right corner for right to left interfaces).
27
- * While dragging, iOS will shift the drag preview under the center of the users pointer, so the "pushing away"
28
- * is short lived on iOS.
25
+ * The drag preview will be centered under the users pointer rather than
26
+ * pushed away on iOS due to platform limitations.
29
27
  */
30
28
  export declare function pointerOutsideOfPreview(point: {
31
29
  x: CSSValue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/pragmatic-drag-and-drop",
3
- "version": "1.7.2",
3
+ "version": "1.7.4",
4
4
  "description": "The core package for Pragmatic drag and drop - enabling fast drag and drop for any experience on any tech stack",
5
5
  "repository": "https://github.com/atlassian/pragmatic-drag-and-drop",
6
6
  "author": "Atlassian Pty Ltd",