@atlaskit/pragmatic-drag-and-drop 1.7.10 → 1.8.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 +17 -0
- package/dist/cjs/honey-pot-fix/make-honey-pot-fix.js +28 -11
- package/dist/cjs/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js +41 -12
- package/dist/cjs/util/popover-reset-styles.js +29 -0
- package/dist/cjs/util/supports-popover.js +21 -0
- package/dist/es2019/honey-pot-fix/make-honey-pot-fix.js +26 -8
- package/dist/es2019/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js +34 -9
- package/dist/es2019/util/popover-reset-styles.js +23 -0
- package/dist/es2019/util/supports-popover.js +16 -0
- package/dist/esm/honey-pot-fix/make-honey-pot-fix.js +28 -11
- package/dist/esm/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js +40 -12
- package/dist/esm/util/popover-reset-styles.js +23 -0
- package/dist/esm/util/supports-popover.js +16 -0
- package/dist/types/util/popover-reset-styles.d.ts +16 -0
- package/dist/types/util/supports-popover.d.ts +10 -0
- package/dist/types-ts4.5/util/popover-reset-styles.d.ts +16 -0
- package/dist/types-ts4.5/util/supports-popover.d.ts +10 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @atlaskit/pragmatic-drag-and-drop
|
|
2
2
|
|
|
3
|
+
## 1.8.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`28c6a19284541`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/28c6a19284541) -
|
|
8
|
+
Moving to `popover="manual"` for "on top" rendering logic. Elements that need to render above all
|
|
9
|
+
other content (honey pot fix, custom native drag previews) now use the browser's top layer via the
|
|
10
|
+
Popover API instead of `z-index: 2147483647`.
|
|
11
|
+
|
|
12
|
+
Falls back to the previous `z-index` approach when the Popover API is not available.
|
|
13
|
+
|
|
14
|
+
Minimum browser versions with `popover="manual"` support:
|
|
15
|
+
- Chrome 114+
|
|
16
|
+
- Edge 114+
|
|
17
|
+
- Firefox 125+
|
|
18
|
+
- Safari 17+
|
|
19
|
+
|
|
3
20
|
## 1.7.10
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -8,6 +8,8 @@ exports.makeHoneyPotFix = makeHoneyPotFix;
|
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
9
|
var _bindEventListener = require("bind-event-listener");
|
|
10
10
|
var _maxZIndex = require("../util/max-z-index");
|
|
11
|
+
var _popoverResetStyles = require("../util/popover-reset-styles");
|
|
12
|
+
var _supportsPopover = require("../util/supports-popover");
|
|
11
13
|
var _honeyPotDataAttribute = require("./honey-pot-data-attribute");
|
|
12
14
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
13
15
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
@@ -136,33 +138,48 @@ function mountHoneyPot(_ref4) {
|
|
|
136
138
|
var element = document.createElement('div');
|
|
137
139
|
element.setAttribute(_honeyPotDataAttribute.honeyPotDataAttribute, 'true');
|
|
138
140
|
|
|
141
|
+
// Using popover="manual" to place the element in the browser's top layer.
|
|
142
|
+
// This ensures the honey pot is visually on top of everything else,
|
|
143
|
+
// including elements using z-index and other stacking contexts.
|
|
144
|
+
// "manual" means no light dismiss — we manage the lifecycle ourselves.
|
|
145
|
+
// Falls back to position:fixed + maxZIndex when the popover API is not available.
|
|
146
|
+
if ((0, _supportsPopover.supportsPopover)()) {
|
|
147
|
+
element.setAttribute('popover', 'manual');
|
|
148
|
+
}
|
|
149
|
+
|
|
139
150
|
// can shift during the drag thanks to Firefox
|
|
140
151
|
var clientRect = getHoneyPotRectFor({
|
|
141
152
|
client: initial
|
|
142
153
|
});
|
|
143
154
|
Object.assign(element.style, _objectSpread(_objectSpread({
|
|
155
|
+
position: 'fixed'
|
|
156
|
+
}, (0, _supportsPopover.supportsPopover)() ?
|
|
157
|
+
// needs to come first as it has 'inset: unset' which
|
|
158
|
+
// needs to be overridden by our top / left values
|
|
159
|
+
_popoverResetStyles.popoverResetUserAgentStyles : {
|
|
160
|
+
// Fallback: using maximum possible z-index so that this element
|
|
161
|
+
// will always be on top of other positioned content.
|
|
162
|
+
zIndex: _maxZIndex.maxZIndex
|
|
163
|
+
}), {}, {
|
|
144
164
|
// Setting a background color explicitly to avoid any inherited styles.
|
|
145
165
|
// Looks like this could be `opacity: 0`, but worried that _might_
|
|
146
166
|
// cause the element to be ignored on some platforms.
|
|
147
167
|
// When debugging, set backgroundColor to something like "red".
|
|
148
168
|
backgroundColor: 'transparent',
|
|
149
|
-
position: 'fixed',
|
|
150
169
|
// Being explicit to avoid inheriting styles
|
|
151
170
|
padding: 0,
|
|
152
171
|
margin: 0,
|
|
153
|
-
boxSizing: 'border-box'
|
|
154
|
-
}, getRectStyles({
|
|
155
|
-
clientRect: clientRect
|
|
156
|
-
})), {}, {
|
|
172
|
+
boxSizing: 'border-box',
|
|
157
173
|
// We want this element to absorb pointer events,
|
|
158
174
|
// it's kind of the whole point 😉
|
|
159
|
-
pointerEvents: 'auto'
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
zIndex: _maxZIndex.maxZIndex
|
|
164
|
-
}));
|
|
175
|
+
pointerEvents: 'auto'
|
|
176
|
+
}, getRectStyles({
|
|
177
|
+
clientRect: clientRect
|
|
178
|
+
})));
|
|
165
179
|
document.body.appendChild(element);
|
|
180
|
+
if ((0, _supportsPopover.supportsPopover)()) {
|
|
181
|
+
element.showPopover();
|
|
182
|
+
}
|
|
166
183
|
|
|
167
184
|
/**
|
|
168
185
|
* 🦊 In firefox we can get `"pointermove"` events after the drag
|
package/dist/cjs/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
3
4
|
Object.defineProperty(exports, "__esModule", {
|
|
4
5
|
value: true
|
|
5
6
|
});
|
|
6
7
|
exports.setCustomNativeDragPreview = setCustomNativeDragPreview;
|
|
8
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
7
9
|
var _elementAdapter = require("../../../adapter/element-adapter");
|
|
8
10
|
var _isSafari = require("../../../util/is-safari");
|
|
9
11
|
var _maxZIndex = require("../../../util/max-z-index");
|
|
12
|
+
var _popoverResetStyles = require("../../../util/popover-reset-styles");
|
|
13
|
+
var _supportsPopover = require("../../../util/supports-popover");
|
|
14
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
15
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
10
16
|
/** A function to remove the element that has been added to the `container`.
|
|
11
17
|
* @example () => ReactDOM.unmountComponentAtNode(container)
|
|
12
18
|
*/
|
|
@@ -42,12 +48,33 @@ function setCustomNativeDragPreview(_ref) {
|
|
|
42
48
|
_ref$getOffset = _ref.getOffset,
|
|
43
49
|
getOffset = _ref$getOffset === void 0 ? defaultOffset : _ref$getOffset;
|
|
44
50
|
var container = document.createElement('div');
|
|
45
|
-
|
|
51
|
+
|
|
52
|
+
// Using popover="manual" to place the element in the browser's top layer.
|
|
53
|
+
// This ensures the drag preview container is visually on top of everything else,
|
|
54
|
+
// including elements using z-index and other stacking contexts.
|
|
55
|
+
// "manual" means no light dismiss — we manage the lifecycle ourselves.
|
|
56
|
+
// This element is only created for a single frame for the browser to take a
|
|
57
|
+
// photo of it, and then it is destroyed.
|
|
58
|
+
// Falls back to position:fixed + maxZIndex when the popover API is not available.
|
|
59
|
+
// Note: the popover attribute must be set before the element is in the DOM.
|
|
60
|
+
// `.showPopover()` is called further below after the element is appended to the body.
|
|
61
|
+
if ((0, _supportsPopover.supportsPopover)()) {
|
|
62
|
+
container.setAttribute('popover', 'manual');
|
|
63
|
+
}
|
|
64
|
+
Object.assign(container.style, _objectSpread(_objectSpread({
|
|
46
65
|
// Ensuring we don't cause reflow when adding the element to the page
|
|
47
66
|
// Using `position:fixed` rather than `position:absolute` so we are
|
|
48
67
|
// positioned on the current viewport.
|
|
49
68
|
// `position:fixed` also creates a new stacking context, so we don't need to do that here
|
|
50
|
-
position: 'fixed'
|
|
69
|
+
position: 'fixed'
|
|
70
|
+
}, (0, _supportsPopover.supportsPopover)() ?
|
|
71
|
+
// needs to come first as it has 'inset: unset' which
|
|
72
|
+
// needs to be overridden by our top / left values
|
|
73
|
+
_popoverResetStyles.popoverResetUserAgentStyles : {
|
|
74
|
+
// Fallback: using maximum possible z-index so that this element
|
|
75
|
+
// will always be on top of other positioned content.
|
|
76
|
+
zIndex: _maxZIndex.maxZIndex
|
|
77
|
+
}), {}, {
|
|
51
78
|
// According to `mdn`, the element can be offscreen:
|
|
52
79
|
// https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage#imgelement
|
|
53
80
|
//
|
|
@@ -57,19 +84,15 @@ function setCustomNativeDragPreview(_ref) {
|
|
|
57
84
|
// If the element is _completely_ offscreen, Safari@17.1 will cancel the drag
|
|
58
85
|
top: 0,
|
|
59
86
|
left: 0,
|
|
60
|
-
// Using maximum possible z-index so that this element will always be on top
|
|
61
|
-
// https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index
|
|
62
|
-
// Did not use `layers` in `@atlaskit/theme` because:
|
|
63
|
-
// 1. This element is not a 'layer' in the conventional sense, as this element
|
|
64
|
-
// is only created for a single frame for the browser to take a photo of it,
|
|
65
|
-
// and then it is destroyed
|
|
66
|
-
// 2. Did not want to add a dependency onto `@atlaskit/theme`
|
|
67
|
-
// 3. Want to always be on top of product UI which might have higher z-index's
|
|
68
|
-
zIndex: _maxZIndex.maxZIndex,
|
|
69
87
|
// Avoiding any additional events caused by the new element (being super safe)
|
|
70
88
|
pointerEvents: 'none'
|
|
71
|
-
});
|
|
89
|
+
}));
|
|
72
90
|
document.body.append(container);
|
|
91
|
+
|
|
92
|
+
// `.showPopover()` must be called after the element is in the DOM.
|
|
93
|
+
if ((0, _supportsPopover.supportsPopover)()) {
|
|
94
|
+
container.showPopover();
|
|
95
|
+
}
|
|
73
96
|
var unmount = render({
|
|
74
97
|
container: container
|
|
75
98
|
});
|
|
@@ -107,6 +130,10 @@ function setCustomNativeDragPreview(_ref) {
|
|
|
107
130
|
* Adding a parent element of the `container` with a background color (eg "white")
|
|
108
131
|
* → Wrecks the opacity of the drag preview element
|
|
109
132
|
*/
|
|
133
|
+
/**
|
|
134
|
+
* Update: this bug fix is no longer needed in `Safari@26.4` (and maybe earlier)
|
|
135
|
+
* We can remove it in a future release
|
|
136
|
+
*/
|
|
110
137
|
if ((0, _isSafari.isSafari)()) {
|
|
111
138
|
var rect = container.getBoundingClientRect();
|
|
112
139
|
|
|
@@ -119,6 +146,8 @@ function setCustomNativeDragPreview(_ref) {
|
|
|
119
146
|
nativeSetDragImage === null || nativeSetDragImage === void 0 || nativeSetDragImage(container, previewOffset.x, previewOffset.y);
|
|
120
147
|
});
|
|
121
148
|
function cleanup() {
|
|
149
|
+
// No need to call `.hidePopover()`.
|
|
150
|
+
// Removing the element from the DOM dismisses the popover
|
|
122
151
|
unbindMonitor();
|
|
123
152
|
unmount === null || unmount === void 0 || unmount();
|
|
124
153
|
document.body.removeChild(container);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.popoverResetUserAgentStyles = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Resets user agent styles for `[popover]` elements.
|
|
9
|
+
*
|
|
10
|
+
* Browsers apply these defaults to popovers (per the WHATWG HTML spec rendering section):
|
|
11
|
+
* - `inset: 0` + `margin: auto` → centers the popover in the viewport
|
|
12
|
+
* - `border: solid` → visible border
|
|
13
|
+
* - `padding: 0.25em` → internal spacing
|
|
14
|
+
* - `overflow: auto` → scrollbars when content overflows
|
|
15
|
+
* - `color: CanvasText` + `background-color: Canvas` → system theme colors
|
|
16
|
+
*
|
|
17
|
+
* This object neutralizes those defaults so the popover behaves like a plain
|
|
18
|
+
* positioned element. `width` and `height` (UA default: `fit-content`) are not
|
|
19
|
+
* reset here because consumers set their own dimensions.
|
|
20
|
+
*/
|
|
21
|
+
var popoverResetUserAgentStyles = exports.popoverResetUserAgentStyles = {
|
|
22
|
+
inset: 'unset',
|
|
23
|
+
border: 'none',
|
|
24
|
+
padding: 0,
|
|
25
|
+
margin: 0,
|
|
26
|
+
overflow: 'visible',
|
|
27
|
+
color: 'inherit',
|
|
28
|
+
background: 'transparent'
|
|
29
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.supportsPopover = void 0;
|
|
7
|
+
var _once = require("../public-utils/once");
|
|
8
|
+
// Using `once` as the value won't change in a browser
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Returns `true` if the browser supports the Popover API (top-layer).
|
|
12
|
+
*
|
|
13
|
+
* When supported, elements with `popover="manual"` can be promoted to the
|
|
14
|
+
* browser's top layer via `element.showPopover()`, which is more reliable
|
|
15
|
+
* than `z-index` for ensuring an element renders above everything else.
|
|
16
|
+
*
|
|
17
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Popover_API
|
|
18
|
+
*/
|
|
19
|
+
var supportsPopover = exports.supportsPopover = (0, _once.once)(function supportsPopover() {
|
|
20
|
+
return typeof HTMLElement !== 'undefined' && typeof HTMLElement.prototype.showPopover === 'function';
|
|
21
|
+
});
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { bind, bindAll } from 'bind-event-listener';
|
|
2
2
|
import { maxZIndex } from '../util/max-z-index';
|
|
3
|
+
import { popoverResetUserAgentStyles } from '../util/popover-reset-styles';
|
|
4
|
+
import { supportsPopover } from '../util/supports-popover';
|
|
3
5
|
import { honeyPotDataAttribute } from './honey-pot-data-attribute';
|
|
4
6
|
const honeyPotSize = 2;
|
|
5
7
|
const halfHoneyPotSize = honeyPotSize / 2;
|
|
@@ -130,33 +132,49 @@ function mountHoneyPot({
|
|
|
130
132
|
const element = document.createElement('div');
|
|
131
133
|
element.setAttribute(honeyPotDataAttribute, 'true');
|
|
132
134
|
|
|
135
|
+
// Using popover="manual" to place the element in the browser's top layer.
|
|
136
|
+
// This ensures the honey pot is visually on top of everything else,
|
|
137
|
+
// including elements using z-index and other stacking contexts.
|
|
138
|
+
// "manual" means no light dismiss — we manage the lifecycle ourselves.
|
|
139
|
+
// Falls back to position:fixed + maxZIndex when the popover API is not available.
|
|
140
|
+
if (supportsPopover()) {
|
|
141
|
+
element.setAttribute('popover', 'manual');
|
|
142
|
+
}
|
|
143
|
+
|
|
133
144
|
// can shift during the drag thanks to Firefox
|
|
134
145
|
let clientRect = getHoneyPotRectFor({
|
|
135
146
|
client: initial
|
|
136
147
|
});
|
|
137
148
|
Object.assign(element.style, {
|
|
149
|
+
position: 'fixed',
|
|
150
|
+
...(supportsPopover() ?
|
|
151
|
+
// needs to come first as it has 'inset: unset' which
|
|
152
|
+
// needs to be overridden by our top / left values
|
|
153
|
+
popoverResetUserAgentStyles : {
|
|
154
|
+
// Fallback: using maximum possible z-index so that this element
|
|
155
|
+
// will always be on top of other positioned content.
|
|
156
|
+
zIndex: maxZIndex
|
|
157
|
+
}),
|
|
138
158
|
// Setting a background color explicitly to avoid any inherited styles.
|
|
139
159
|
// Looks like this could be `opacity: 0`, but worried that _might_
|
|
140
160
|
// cause the element to be ignored on some platforms.
|
|
141
161
|
// When debugging, set backgroundColor to something like "red".
|
|
142
162
|
backgroundColor: 'transparent',
|
|
143
|
-
position: 'fixed',
|
|
144
163
|
// Being explicit to avoid inheriting styles
|
|
145
164
|
padding: 0,
|
|
146
165
|
margin: 0,
|
|
147
166
|
boxSizing: 'border-box',
|
|
148
|
-
...getRectStyles({
|
|
149
|
-
clientRect
|
|
150
|
-
}),
|
|
151
167
|
// We want this element to absorb pointer events,
|
|
152
168
|
// it's kind of the whole point 😉
|
|
153
169
|
pointerEvents: 'auto',
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
zIndex: maxZIndex
|
|
170
|
+
...getRectStyles({
|
|
171
|
+
clientRect
|
|
172
|
+
})
|
|
158
173
|
});
|
|
159
174
|
document.body.appendChild(element);
|
|
175
|
+
if (supportsPopover()) {
|
|
176
|
+
element.showPopover();
|
|
177
|
+
}
|
|
160
178
|
|
|
161
179
|
/**
|
|
162
180
|
* 🦊 In firefox we can get `"pointermove"` events after the drag
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { monitorForElements } from '../../../adapter/element-adapter';
|
|
2
2
|
import { isSafari } from '../../../util/is-safari';
|
|
3
3
|
import { maxZIndex } from '../../../util/max-z-index';
|
|
4
|
+
import { popoverResetUserAgentStyles } from '../../../util/popover-reset-styles';
|
|
5
|
+
import { supportsPopover } from '../../../util/supports-popover';
|
|
4
6
|
|
|
5
7
|
/** A function to remove the element that has been added to the `container`.
|
|
6
8
|
* @example () => ReactDOM.unmountComponentAtNode(container)
|
|
@@ -37,12 +39,33 @@ export function setCustomNativeDragPreview({
|
|
|
37
39
|
getOffset = defaultOffset
|
|
38
40
|
}) {
|
|
39
41
|
const container = document.createElement('div');
|
|
42
|
+
|
|
43
|
+
// Using popover="manual" to place the element in the browser's top layer.
|
|
44
|
+
// This ensures the drag preview container is visually on top of everything else,
|
|
45
|
+
// including elements using z-index and other stacking contexts.
|
|
46
|
+
// "manual" means no light dismiss — we manage the lifecycle ourselves.
|
|
47
|
+
// This element is only created for a single frame for the browser to take a
|
|
48
|
+
// photo of it, and then it is destroyed.
|
|
49
|
+
// Falls back to position:fixed + maxZIndex when the popover API is not available.
|
|
50
|
+
// Note: the popover attribute must be set before the element is in the DOM.
|
|
51
|
+
// `.showPopover()` is called further below after the element is appended to the body.
|
|
52
|
+
if (supportsPopover()) {
|
|
53
|
+
container.setAttribute('popover', 'manual');
|
|
54
|
+
}
|
|
40
55
|
Object.assign(container.style, {
|
|
41
56
|
// Ensuring we don't cause reflow when adding the element to the page
|
|
42
57
|
// Using `position:fixed` rather than `position:absolute` so we are
|
|
43
58
|
// positioned on the current viewport.
|
|
44
59
|
// `position:fixed` also creates a new stacking context, so we don't need to do that here
|
|
45
60
|
position: 'fixed',
|
|
61
|
+
...(supportsPopover() ?
|
|
62
|
+
// needs to come first as it has 'inset: unset' which
|
|
63
|
+
// needs to be overridden by our top / left values
|
|
64
|
+
popoverResetUserAgentStyles : {
|
|
65
|
+
// Fallback: using maximum possible z-index so that this element
|
|
66
|
+
// will always be on top of other positioned content.
|
|
67
|
+
zIndex: maxZIndex
|
|
68
|
+
}),
|
|
46
69
|
// According to `mdn`, the element can be offscreen:
|
|
47
70
|
// https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage#imgelement
|
|
48
71
|
//
|
|
@@ -52,19 +75,15 @@ export function setCustomNativeDragPreview({
|
|
|
52
75
|
// If the element is _completely_ offscreen, Safari@17.1 will cancel the drag
|
|
53
76
|
top: 0,
|
|
54
77
|
left: 0,
|
|
55
|
-
// Using maximum possible z-index so that this element will always be on top
|
|
56
|
-
// https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index
|
|
57
|
-
// Did not use `layers` in `@atlaskit/theme` because:
|
|
58
|
-
// 1. This element is not a 'layer' in the conventional sense, as this element
|
|
59
|
-
// is only created for a single frame for the browser to take a photo of it,
|
|
60
|
-
// and then it is destroyed
|
|
61
|
-
// 2. Did not want to add a dependency onto `@atlaskit/theme`
|
|
62
|
-
// 3. Want to always be on top of product UI which might have higher z-index's
|
|
63
|
-
zIndex: maxZIndex,
|
|
64
78
|
// Avoiding any additional events caused by the new element (being super safe)
|
|
65
79
|
pointerEvents: 'none'
|
|
66
80
|
});
|
|
67
81
|
document.body.append(container);
|
|
82
|
+
|
|
83
|
+
// `.showPopover()` must be called after the element is in the DOM.
|
|
84
|
+
if (supportsPopover()) {
|
|
85
|
+
container.showPopover();
|
|
86
|
+
}
|
|
68
87
|
const unmount = render({
|
|
69
88
|
container
|
|
70
89
|
});
|
|
@@ -102,6 +121,10 @@ export function setCustomNativeDragPreview({
|
|
|
102
121
|
* Adding a parent element of the `container` with a background color (eg "white")
|
|
103
122
|
* → Wrecks the opacity of the drag preview element
|
|
104
123
|
*/
|
|
124
|
+
/**
|
|
125
|
+
* Update: this bug fix is no longer needed in `Safari@26.4` (and maybe earlier)
|
|
126
|
+
* We can remove it in a future release
|
|
127
|
+
*/
|
|
105
128
|
if (isSafari()) {
|
|
106
129
|
const rect = container.getBoundingClientRect();
|
|
107
130
|
|
|
@@ -114,6 +137,8 @@ export function setCustomNativeDragPreview({
|
|
|
114
137
|
nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, previewOffset.x, previewOffset.y);
|
|
115
138
|
});
|
|
116
139
|
function cleanup() {
|
|
140
|
+
// No need to call `.hidePopover()`.
|
|
141
|
+
// Removing the element from the DOM dismisses the popover
|
|
117
142
|
unbindMonitor();
|
|
118
143
|
unmount === null || unmount === void 0 ? void 0 : unmount();
|
|
119
144
|
document.body.removeChild(container);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resets user agent styles for `[popover]` elements.
|
|
3
|
+
*
|
|
4
|
+
* Browsers apply these defaults to popovers (per the WHATWG HTML spec rendering section):
|
|
5
|
+
* - `inset: 0` + `margin: auto` → centers the popover in the viewport
|
|
6
|
+
* - `border: solid` → visible border
|
|
7
|
+
* - `padding: 0.25em` → internal spacing
|
|
8
|
+
* - `overflow: auto` → scrollbars when content overflows
|
|
9
|
+
* - `color: CanvasText` + `background-color: Canvas` → system theme colors
|
|
10
|
+
*
|
|
11
|
+
* This object neutralizes those defaults so the popover behaves like a plain
|
|
12
|
+
* positioned element. `width` and `height` (UA default: `fit-content`) are not
|
|
13
|
+
* reset here because consumers set their own dimensions.
|
|
14
|
+
*/
|
|
15
|
+
export const popoverResetUserAgentStyles = {
|
|
16
|
+
inset: 'unset',
|
|
17
|
+
border: 'none',
|
|
18
|
+
padding: 0,
|
|
19
|
+
margin: 0,
|
|
20
|
+
overflow: 'visible',
|
|
21
|
+
color: 'inherit',
|
|
22
|
+
background: 'transparent'
|
|
23
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { once } from '../public-utils/once';
|
|
2
|
+
|
|
3
|
+
// Using `once` as the value won't change in a browser
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns `true` if the browser supports the Popover API (top-layer).
|
|
7
|
+
*
|
|
8
|
+
* When supported, elements with `popover="manual"` can be promoted to the
|
|
9
|
+
* browser's top layer via `element.showPopover()`, which is more reliable
|
|
10
|
+
* than `z-index` for ensuring an element renders above everything else.
|
|
11
|
+
*
|
|
12
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Popover_API
|
|
13
|
+
*/
|
|
14
|
+
export const supportsPopover = once(function supportsPopover() {
|
|
15
|
+
return typeof HTMLElement !== 'undefined' && typeof HTMLElement.prototype.showPopover === 'function';
|
|
16
|
+
});
|
|
@@ -3,6 +3,8 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
|
|
|
3
3
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
4
|
import { bind, bindAll } from 'bind-event-listener';
|
|
5
5
|
import { maxZIndex } from '../util/max-z-index';
|
|
6
|
+
import { popoverResetUserAgentStyles } from '../util/popover-reset-styles';
|
|
7
|
+
import { supportsPopover } from '../util/supports-popover';
|
|
6
8
|
import { honeyPotDataAttribute } from './honey-pot-data-attribute';
|
|
7
9
|
var honeyPotSize = 2;
|
|
8
10
|
var halfHoneyPotSize = honeyPotSize / 2;
|
|
@@ -129,33 +131,48 @@ function mountHoneyPot(_ref4) {
|
|
|
129
131
|
var element = document.createElement('div');
|
|
130
132
|
element.setAttribute(honeyPotDataAttribute, 'true');
|
|
131
133
|
|
|
134
|
+
// Using popover="manual" to place the element in the browser's top layer.
|
|
135
|
+
// This ensures the honey pot is visually on top of everything else,
|
|
136
|
+
// including elements using z-index and other stacking contexts.
|
|
137
|
+
// "manual" means no light dismiss — we manage the lifecycle ourselves.
|
|
138
|
+
// Falls back to position:fixed + maxZIndex when the popover API is not available.
|
|
139
|
+
if (supportsPopover()) {
|
|
140
|
+
element.setAttribute('popover', 'manual');
|
|
141
|
+
}
|
|
142
|
+
|
|
132
143
|
// can shift during the drag thanks to Firefox
|
|
133
144
|
var clientRect = getHoneyPotRectFor({
|
|
134
145
|
client: initial
|
|
135
146
|
});
|
|
136
147
|
Object.assign(element.style, _objectSpread(_objectSpread({
|
|
148
|
+
position: 'fixed'
|
|
149
|
+
}, supportsPopover() ?
|
|
150
|
+
// needs to come first as it has 'inset: unset' which
|
|
151
|
+
// needs to be overridden by our top / left values
|
|
152
|
+
popoverResetUserAgentStyles : {
|
|
153
|
+
// Fallback: using maximum possible z-index so that this element
|
|
154
|
+
// will always be on top of other positioned content.
|
|
155
|
+
zIndex: maxZIndex
|
|
156
|
+
}), {}, {
|
|
137
157
|
// Setting a background color explicitly to avoid any inherited styles.
|
|
138
158
|
// Looks like this could be `opacity: 0`, but worried that _might_
|
|
139
159
|
// cause the element to be ignored on some platforms.
|
|
140
160
|
// When debugging, set backgroundColor to something like "red".
|
|
141
161
|
backgroundColor: 'transparent',
|
|
142
|
-
position: 'fixed',
|
|
143
162
|
// Being explicit to avoid inheriting styles
|
|
144
163
|
padding: 0,
|
|
145
164
|
margin: 0,
|
|
146
|
-
boxSizing: 'border-box'
|
|
147
|
-
}, getRectStyles({
|
|
148
|
-
clientRect: clientRect
|
|
149
|
-
})), {}, {
|
|
165
|
+
boxSizing: 'border-box',
|
|
150
166
|
// We want this element to absorb pointer events,
|
|
151
167
|
// it's kind of the whole point 😉
|
|
152
|
-
pointerEvents: 'auto'
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
zIndex: maxZIndex
|
|
157
|
-
}));
|
|
168
|
+
pointerEvents: 'auto'
|
|
169
|
+
}, getRectStyles({
|
|
170
|
+
clientRect: clientRect
|
|
171
|
+
})));
|
|
158
172
|
document.body.appendChild(element);
|
|
173
|
+
if (supportsPopover()) {
|
|
174
|
+
element.showPopover();
|
|
175
|
+
}
|
|
159
176
|
|
|
160
177
|
/**
|
|
161
178
|
* 🦊 In firefox we can get `"pointermove"` events after the drag
|
package/dist/esm/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
1
4
|
import { monitorForElements } from '../../../adapter/element-adapter';
|
|
2
5
|
import { isSafari } from '../../../util/is-safari';
|
|
3
6
|
import { maxZIndex } from '../../../util/max-z-index';
|
|
7
|
+
import { popoverResetUserAgentStyles } from '../../../util/popover-reset-styles';
|
|
8
|
+
import { supportsPopover } from '../../../util/supports-popover';
|
|
4
9
|
|
|
5
10
|
/** A function to remove the element that has been added to the `container`.
|
|
6
11
|
* @example () => ReactDOM.unmountComponentAtNode(container)
|
|
@@ -37,12 +42,33 @@ export function setCustomNativeDragPreview(_ref) {
|
|
|
37
42
|
_ref$getOffset = _ref.getOffset,
|
|
38
43
|
getOffset = _ref$getOffset === void 0 ? defaultOffset : _ref$getOffset;
|
|
39
44
|
var container = document.createElement('div');
|
|
40
|
-
|
|
45
|
+
|
|
46
|
+
// Using popover="manual" to place the element in the browser's top layer.
|
|
47
|
+
// This ensures the drag preview container is visually on top of everything else,
|
|
48
|
+
// including elements using z-index and other stacking contexts.
|
|
49
|
+
// "manual" means no light dismiss — we manage the lifecycle ourselves.
|
|
50
|
+
// This element is only created for a single frame for the browser to take a
|
|
51
|
+
// photo of it, and then it is destroyed.
|
|
52
|
+
// Falls back to position:fixed + maxZIndex when the popover API is not available.
|
|
53
|
+
// Note: the popover attribute must be set before the element is in the DOM.
|
|
54
|
+
// `.showPopover()` is called further below after the element is appended to the body.
|
|
55
|
+
if (supportsPopover()) {
|
|
56
|
+
container.setAttribute('popover', 'manual');
|
|
57
|
+
}
|
|
58
|
+
Object.assign(container.style, _objectSpread(_objectSpread({
|
|
41
59
|
// Ensuring we don't cause reflow when adding the element to the page
|
|
42
60
|
// Using `position:fixed` rather than `position:absolute` so we are
|
|
43
61
|
// positioned on the current viewport.
|
|
44
62
|
// `position:fixed` also creates a new stacking context, so we don't need to do that here
|
|
45
|
-
position: 'fixed'
|
|
63
|
+
position: 'fixed'
|
|
64
|
+
}, supportsPopover() ?
|
|
65
|
+
// needs to come first as it has 'inset: unset' which
|
|
66
|
+
// needs to be overridden by our top / left values
|
|
67
|
+
popoverResetUserAgentStyles : {
|
|
68
|
+
// Fallback: using maximum possible z-index so that this element
|
|
69
|
+
// will always be on top of other positioned content.
|
|
70
|
+
zIndex: maxZIndex
|
|
71
|
+
}), {}, {
|
|
46
72
|
// According to `mdn`, the element can be offscreen:
|
|
47
73
|
// https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage#imgelement
|
|
48
74
|
//
|
|
@@ -52,19 +78,15 @@ export function setCustomNativeDragPreview(_ref) {
|
|
|
52
78
|
// If the element is _completely_ offscreen, Safari@17.1 will cancel the drag
|
|
53
79
|
top: 0,
|
|
54
80
|
left: 0,
|
|
55
|
-
// Using maximum possible z-index so that this element will always be on top
|
|
56
|
-
// https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index
|
|
57
|
-
// Did not use `layers` in `@atlaskit/theme` because:
|
|
58
|
-
// 1. This element is not a 'layer' in the conventional sense, as this element
|
|
59
|
-
// is only created for a single frame for the browser to take a photo of it,
|
|
60
|
-
// and then it is destroyed
|
|
61
|
-
// 2. Did not want to add a dependency onto `@atlaskit/theme`
|
|
62
|
-
// 3. Want to always be on top of product UI which might have higher z-index's
|
|
63
|
-
zIndex: maxZIndex,
|
|
64
81
|
// Avoiding any additional events caused by the new element (being super safe)
|
|
65
82
|
pointerEvents: 'none'
|
|
66
|
-
});
|
|
83
|
+
}));
|
|
67
84
|
document.body.append(container);
|
|
85
|
+
|
|
86
|
+
// `.showPopover()` must be called after the element is in the DOM.
|
|
87
|
+
if (supportsPopover()) {
|
|
88
|
+
container.showPopover();
|
|
89
|
+
}
|
|
68
90
|
var unmount = render({
|
|
69
91
|
container: container
|
|
70
92
|
});
|
|
@@ -102,6 +124,10 @@ export function setCustomNativeDragPreview(_ref) {
|
|
|
102
124
|
* Adding a parent element of the `container` with a background color (eg "white")
|
|
103
125
|
* → Wrecks the opacity of the drag preview element
|
|
104
126
|
*/
|
|
127
|
+
/**
|
|
128
|
+
* Update: this bug fix is no longer needed in `Safari@26.4` (and maybe earlier)
|
|
129
|
+
* We can remove it in a future release
|
|
130
|
+
*/
|
|
105
131
|
if (isSafari()) {
|
|
106
132
|
var rect = container.getBoundingClientRect();
|
|
107
133
|
|
|
@@ -114,6 +140,8 @@ export function setCustomNativeDragPreview(_ref) {
|
|
|
114
140
|
nativeSetDragImage === null || nativeSetDragImage === void 0 || nativeSetDragImage(container, previewOffset.x, previewOffset.y);
|
|
115
141
|
});
|
|
116
142
|
function cleanup() {
|
|
143
|
+
// No need to call `.hidePopover()`.
|
|
144
|
+
// Removing the element from the DOM dismisses the popover
|
|
117
145
|
unbindMonitor();
|
|
118
146
|
unmount === null || unmount === void 0 || unmount();
|
|
119
147
|
document.body.removeChild(container);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resets user agent styles for `[popover]` elements.
|
|
3
|
+
*
|
|
4
|
+
* Browsers apply these defaults to popovers (per the WHATWG HTML spec rendering section):
|
|
5
|
+
* - `inset: 0` + `margin: auto` → centers the popover in the viewport
|
|
6
|
+
* - `border: solid` → visible border
|
|
7
|
+
* - `padding: 0.25em` → internal spacing
|
|
8
|
+
* - `overflow: auto` → scrollbars when content overflows
|
|
9
|
+
* - `color: CanvasText` + `background-color: Canvas` → system theme colors
|
|
10
|
+
*
|
|
11
|
+
* This object neutralizes those defaults so the popover behaves like a plain
|
|
12
|
+
* positioned element. `width` and `height` (UA default: `fit-content`) are not
|
|
13
|
+
* reset here because consumers set their own dimensions.
|
|
14
|
+
*/
|
|
15
|
+
export var popoverResetUserAgentStyles = {
|
|
16
|
+
inset: 'unset',
|
|
17
|
+
border: 'none',
|
|
18
|
+
padding: 0,
|
|
19
|
+
margin: 0,
|
|
20
|
+
overflow: 'visible',
|
|
21
|
+
color: 'inherit',
|
|
22
|
+
background: 'transparent'
|
|
23
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { once } from '../public-utils/once';
|
|
2
|
+
|
|
3
|
+
// Using `once` as the value won't change in a browser
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns `true` if the browser supports the Popover API (top-layer).
|
|
7
|
+
*
|
|
8
|
+
* When supported, elements with `popover="manual"` can be promoted to the
|
|
9
|
+
* browser's top layer via `element.showPopover()`, which is more reliable
|
|
10
|
+
* than `z-index` for ensuring an element renders above everything else.
|
|
11
|
+
*
|
|
12
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Popover_API
|
|
13
|
+
*/
|
|
14
|
+
export var supportsPopover = once(function supportsPopover() {
|
|
15
|
+
return typeof HTMLElement !== 'undefined' && typeof HTMLElement.prototype.showPopover === 'function';
|
|
16
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CSSProperties } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Resets user agent styles for `[popover]` elements.
|
|
4
|
+
*
|
|
5
|
+
* Browsers apply these defaults to popovers (per the WHATWG HTML spec rendering section):
|
|
6
|
+
* - `inset: 0` + `margin: auto` → centers the popover in the viewport
|
|
7
|
+
* - `border: solid` → visible border
|
|
8
|
+
* - `padding: 0.25em` → internal spacing
|
|
9
|
+
* - `overflow: auto` → scrollbars when content overflows
|
|
10
|
+
* - `color: CanvasText` + `background-color: Canvas` → system theme colors
|
|
11
|
+
*
|
|
12
|
+
* This object neutralizes those defaults so the popover behaves like a plain
|
|
13
|
+
* positioned element. `width` and `height` (UA default: `fit-content`) are not
|
|
14
|
+
* reset here because consumers set their own dimensions.
|
|
15
|
+
*/
|
|
16
|
+
export declare const popoverResetUserAgentStyles: CSSProperties;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns `true` if the browser supports the Popover API (top-layer).
|
|
3
|
+
*
|
|
4
|
+
* When supported, elements with `popover="manual"` can be promoted to the
|
|
5
|
+
* browser's top layer via `element.showPopover()`, which is more reliable
|
|
6
|
+
* than `z-index` for ensuring an element renders above everything else.
|
|
7
|
+
*
|
|
8
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Popover_API
|
|
9
|
+
*/
|
|
10
|
+
export declare const supportsPopover: () => boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CSSProperties } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Resets user agent styles for `[popover]` elements.
|
|
4
|
+
*
|
|
5
|
+
* Browsers apply these defaults to popovers (per the WHATWG HTML spec rendering section):
|
|
6
|
+
* - `inset: 0` + `margin: auto` → centers the popover in the viewport
|
|
7
|
+
* - `border: solid` → visible border
|
|
8
|
+
* - `padding: 0.25em` → internal spacing
|
|
9
|
+
* - `overflow: auto` → scrollbars when content overflows
|
|
10
|
+
* - `color: CanvasText` + `background-color: Canvas` → system theme colors
|
|
11
|
+
*
|
|
12
|
+
* This object neutralizes those defaults so the popover behaves like a plain
|
|
13
|
+
* positioned element. `width` and `height` (UA default: `fit-content`) are not
|
|
14
|
+
* reset here because consumers set their own dimensions.
|
|
15
|
+
*/
|
|
16
|
+
export declare const popoverResetUserAgentStyles: CSSProperties;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns `true` if the browser supports the Popover API (top-layer).
|
|
3
|
+
*
|
|
4
|
+
* When supported, elements with `popover="manual"` can be promoted to the
|
|
5
|
+
* browser's top layer via `element.showPopover()`, which is more reliable
|
|
6
|
+
* than `z-index` for ensuring an element renders above everything else.
|
|
7
|
+
*
|
|
8
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Popover_API
|
|
9
|
+
*/
|
|
10
|
+
export declare const supportsPopover: () => boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/pragmatic-drag-and-drop",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
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",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@af/integration-testing": "workspace:^",
|
|
45
|
-
"@atlaskit/link": "^3.
|
|
46
|
-
"@atlassian/a11y-jest-testing": "^0.
|
|
45
|
+
"@atlaskit/link": "^3.4.0",
|
|
46
|
+
"@atlassian/a11y-jest-testing": "^0.11.0",
|
|
47
47
|
"@emotion/react": "^11.7.1",
|
|
48
48
|
"@testing-library/dom": "^10.1.0",
|
|
49
49
|
"@testing-library/react": "^16.3.0",
|