@atlaskit/top-layer 6.2.3 → 6.2.5
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 +18 -0
- package/dist/cjs/dialog/dialog-content.js +4 -3
- package/dist/cjs/dialog-scroll-lock/index.js +2 -2
- package/dist/cjs/internal/use-anchored-popover-at-point.js +2 -1
- package/dist/cjs/internal/use-anchored-popover.js +2 -1
- package/dist/cjs/internal/use-animated-visibility.js +3 -2
- package/dist/cjs/popover/popover.js +4 -3
- package/dist/cjs/testing/polyfill.js +144 -24
- package/dist/es2019/dialog/dialog-content.js +2 -1
- package/dist/es2019/dialog-scroll-lock/index.js +1 -1
- package/dist/es2019/internal/use-anchored-popover-at-point.js +2 -1
- package/dist/es2019/internal/use-anchored-popover.js +2 -1
- package/dist/es2019/internal/use-animated-visibility.js +2 -1
- package/dist/es2019/popover/popover.js +2 -1
- package/dist/es2019/testing/polyfill.js +140 -25
- package/dist/esm/dialog/dialog-content.js +2 -1
- package/dist/esm/dialog-scroll-lock/index.js +1 -1
- package/dist/esm/internal/use-anchored-popover-at-point.js +2 -1
- package/dist/esm/internal/use-anchored-popover.js +2 -1
- package/dist/esm/internal/use-animated-visibility.js +2 -1
- package/dist/esm/popover/popover.js +2 -1
- package/dist/esm/testing/polyfill.js +144 -24
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @atlaskit/top-layer
|
|
2
2
|
|
|
3
|
+
## 6.2.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`b82a5dc33d636`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/b82a5dc33d636) -
|
|
8
|
+
The testing polyfill now fires a cancelable cancel event when Escape targets a dialog. Unless
|
|
9
|
+
keydown or cancel is prevented, the dialog closes and emits its existing closing beforetoggle,
|
|
10
|
+
toggle and close events. Escape respects closedby and dialog/popover opening order.
|
|
11
|
+
|
|
12
|
+
## 6.2.4
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- [`4247678302a95`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/4247678302a95) -
|
|
17
|
+
Fixed server-side rendering errors and warnings in the top-layer popover, dialog and popper paths
|
|
18
|
+
(`platform-dst-top-layer`).
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
|
|
3
21
|
## 6.2.3
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
|
@@ -14,6 +14,7 @@ var _react2 = require("@compiled/react");
|
|
|
14
14
|
var _bindEventListener = require("bind-event-listener");
|
|
15
15
|
var _mergeRefs = _interopRequireDefault(require("@atlaskit/ds-lib/merge-refs"));
|
|
16
16
|
var _noop = _interopRequireDefault(require("@atlaskit/ds-lib/noop"));
|
|
17
|
+
var _useLayoutEffect = require("@atlaskit/ds-lib/use-layout-effect");
|
|
17
18
|
var _useNotifyOpenLayerObserver = require("@atlaskit/layering/use-notify-open-layer-observer");
|
|
18
19
|
var _useAnimatedVisibility = require("../internal/use-animated-visibility");
|
|
19
20
|
var _useFocusWrap = require("../internal/use-focus-wrap");
|
|
@@ -83,7 +84,7 @@ var Dialog = exports.Dialog = /*#__PURE__*/(0, _react.forwardRef)(function Dialo
|
|
|
83
84
|
var dismissedByRef = (0, _react.useRef)(dismissedBy);
|
|
84
85
|
var onCloseRef = (0, _react.useRef)(onClose);
|
|
85
86
|
// Keep native event handlers stable while ensuring they read the latest committed props.
|
|
86
|
-
(0,
|
|
87
|
+
(0, _useLayoutEffect.useLayoutEffect)(function () {
|
|
87
88
|
dismissedByRef.current = dismissedBy;
|
|
88
89
|
onCloseRef.current = onClose;
|
|
89
90
|
}, [dismissedBy, onClose]);
|
|
@@ -102,7 +103,7 @@ var Dialog = exports.Dialog = /*#__PURE__*/(0, _react.forwardRef)(function Dialo
|
|
|
102
103
|
// Ordering is important: bind native lifecycle listeners before the later
|
|
103
104
|
// layout effect calls showModal() or close(), because `beforetoggle` fires
|
|
104
105
|
// synchronously during those calls.
|
|
105
|
-
(0,
|
|
106
|
+
(0, _useLayoutEffect.useLayoutEffect)(function () {
|
|
106
107
|
if (!isMounted) {
|
|
107
108
|
return;
|
|
108
109
|
}
|
|
@@ -161,7 +162,7 @@ var Dialog = exports.Dialog = /*#__PURE__*/(0, _react.forwardRef)(function Dialo
|
|
|
161
162
|
// No-op: no current use case for programmatic close via OpenLayerObserver.
|
|
162
163
|
onClose: _noop.default
|
|
163
164
|
});
|
|
164
|
-
(0,
|
|
165
|
+
(0, _useLayoutEffect.useLayoutEffect)(function () {
|
|
165
166
|
var dialog = ownRef.current;
|
|
166
167
|
if (!dialog) {
|
|
167
168
|
return;
|
|
@@ -4,8 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.DialogScrollLock = DialogScrollLock;
|
|
7
|
-
var _react = require("react");
|
|
8
7
|
var _browserApis = require("@atlaskit/browser-apis");
|
|
8
|
+
var _useLayoutEffect = require("@atlaskit/ds-lib/use-layout-effect");
|
|
9
9
|
/**
|
|
10
10
|
* __DialogScrollLock__
|
|
11
11
|
*
|
|
@@ -37,7 +37,7 @@ var _browserApis = require("@atlaskit/browser-apis");
|
|
|
37
37
|
*/
|
|
38
38
|
function DialogScrollLock(_ref) {
|
|
39
39
|
var isOpen = _ref.isOpen;
|
|
40
|
-
(0,
|
|
40
|
+
(0, _useLayoutEffect.useLayoutEffect)(function () {
|
|
41
41
|
var _getDocument;
|
|
42
42
|
if (!isOpen) {
|
|
43
43
|
return;
|
|
@@ -8,6 +8,7 @@ exports.useAnchoredPopoverAtPoint = useAnchoredPopoverAtPoint;
|
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
9
|
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
|
|
10
10
|
var _react = require("react");
|
|
11
|
+
var _useLayoutEffect = require("@atlaskit/ds-lib/use-layout-effect");
|
|
11
12
|
var _useAnchoredPopover = require("./use-anchored-popover");
|
|
12
13
|
var _excluded = ["getPoint", "isEnabled"];
|
|
13
14
|
/**
|
|
@@ -97,7 +98,7 @@ function useAnchoredPopoverAtPoint(_ref2) {
|
|
|
97
98
|
// effect must not depend on anything the delegated effect does not: a dependency
|
|
98
99
|
// here alone re-creates the element without that hook writing an `anchor-name`
|
|
99
100
|
// onto it, and positioning silently dies.
|
|
100
|
-
(0,
|
|
101
|
+
(0, _useLayoutEffect.useLayoutEffect)(function () {
|
|
101
102
|
if (!isEnabled) {
|
|
102
103
|
return;
|
|
103
104
|
}
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.useAnchoredPopover = useAnchoredPopover;
|
|
7
7
|
var _react = require("react");
|
|
8
8
|
var _useId = require("@atlaskit/ds-lib/use-id");
|
|
9
|
+
var _useLayoutEffect = require("@atlaskit/ds-lib/use-layout-effect");
|
|
9
10
|
var _applyAnchorPositioning = require("./anchor-positioning/apply-anchor-positioning");
|
|
10
11
|
var _anchoredPopoverSize = require("./anchored-popover-size");
|
|
11
12
|
var _applyJavascriptFallbackPositioning = require("./javascript-fallback/apply-javascript-fallback-positioning");
|
|
@@ -214,7 +215,7 @@ function useAnchoredPopover(_ref3) {
|
|
|
214
215
|
// element (the point hook remounts its `<div>`).
|
|
215
216
|
var fallbackAnchorName = useNewAnchorName();
|
|
216
217
|
var stablePlacement = useStablePlacement(placement);
|
|
217
|
-
(0,
|
|
218
|
+
(0, _useLayoutEffect.useLayoutEffect)(function () {
|
|
218
219
|
if (!isEnabled) {
|
|
219
220
|
return;
|
|
220
221
|
}
|
|
@@ -8,6 +8,7 @@ exports.useAnimatedVisibility = useAnimatedVisibility;
|
|
|
8
8
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
9
9
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
10
10
|
var _react = require("react");
|
|
11
|
+
var _useLayoutEffect = require("@atlaskit/ds-lib/use-layout-effect");
|
|
11
12
|
var _isNativeElementOpen = require("./is-native-element-open");
|
|
12
13
|
var _reducedMotion = require("./reduced-motion");
|
|
13
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; }
|
|
@@ -208,7 +209,7 @@ function useAnimatedVisibility(_ref4) {
|
|
|
208
209
|
var onEnterFinishRef = (0, _react.useRef)(onEnterFinish);
|
|
209
210
|
var onExitFinishRef = (0, _react.useRef)(onExitFinish);
|
|
210
211
|
var willAnimateRef = (0, _react.useRef)(willAnimate);
|
|
211
|
-
(0,
|
|
212
|
+
(0, _useLayoutEffect.useLayoutEffect)(function () {
|
|
212
213
|
onEnterFinishRef.current = onEnterFinish;
|
|
213
214
|
onExitFinishRef.current = onExitFinish;
|
|
214
215
|
willAnimateRef.current = willAnimate;
|
|
@@ -324,7 +325,7 @@ function useAnimatedVisibility(_ref4) {
|
|
|
324
325
|
onSettled: settleExit
|
|
325
326
|
});
|
|
326
327
|
}, [elementRef, settleExit]);
|
|
327
|
-
(0,
|
|
328
|
+
(0, _useLayoutEffect.useLayoutEffect)(function () {
|
|
328
329
|
return function () {
|
|
329
330
|
// Prevent a pending animation or microtask from notifying after unmount.
|
|
330
331
|
cancelExitSettlementRef.current();
|
|
@@ -14,6 +14,7 @@ var _react2 = require("@compiled/react");
|
|
|
14
14
|
var _bindEventListener = require("bind-event-listener");
|
|
15
15
|
var _mergeRefs = _interopRequireDefault(require("@atlaskit/ds-lib/merge-refs"));
|
|
16
16
|
var _once = _interopRequireDefault(require("@atlaskit/ds-lib/once"));
|
|
17
|
+
var _useLayoutEffect = require("@atlaskit/ds-lib/use-layout-effect");
|
|
17
18
|
var _useNotifyOpenLayerObserver = require("@atlaskit/layering/use-notify-open-layer-observer");
|
|
18
19
|
var _isNativeElementOpen = require("../internal/is-native-element-open");
|
|
19
20
|
var _resolvePlacement2 = require("../internal/resolve-placement");
|
|
@@ -172,7 +173,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
172
173
|
// Keep the semantic callback current without rebinding native lifecycle
|
|
173
174
|
// listeners during the same commit that calls showPopover()/hidePopover().
|
|
174
175
|
var onCloseRef = (0, _react.useRef)(onClose);
|
|
175
|
-
(0,
|
|
176
|
+
(0, _useLayoutEffect.useLayoutEffect)(function () {
|
|
176
177
|
onCloseRef.current = onClose;
|
|
177
178
|
}, [onClose]);
|
|
178
179
|
|
|
@@ -295,7 +296,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
295
296
|
// first dispatch, dropping the `focusRestorationTargetRef` snapshot
|
|
296
297
|
// and breaking nested-popover focus restoration on close. React runs
|
|
297
298
|
// layout effects in source order on the same commit.
|
|
298
|
-
(0,
|
|
299
|
+
(0, _useLayoutEffect.useLayoutEffect)(function () {
|
|
299
300
|
var element = ownRef.current;
|
|
300
301
|
if (!element) {
|
|
301
302
|
return;
|
|
@@ -344,7 +345,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
344
345
|
// Show/hide based on isOpen. `showPopover`/`hidePopover` are no-ops when
|
|
345
346
|
// already in the target state. Try/catch guards `InvalidStateError` on
|
|
346
347
|
// disconnected elements (StrictMode/concurrent/unmount edge cases).
|
|
347
|
-
(0,
|
|
348
|
+
(0, _useLayoutEffect.useLayoutEffect)(function () {
|
|
348
349
|
var element = ownRef.current;
|
|
349
350
|
if (!element) {
|
|
350
351
|
return;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _bindEventListener = require("bind-event-listener");
|
|
4
|
+
// Node supports findLast, but the package defaults to older array type declarations.
|
|
5
|
+
/// <reference lib="es2023.array" />
|
|
4
6
|
/* eslint-disable compat/compat */
|
|
5
7
|
/**
|
|
6
8
|
* Popover API & HTMLDialogElement polyfills for jsdom.
|
|
@@ -482,40 +484,133 @@ function handleDocumentPointerup(event) {
|
|
|
482
484
|
});
|
|
483
485
|
}
|
|
484
486
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
487
|
+
/**
|
|
488
|
+
* Represents one dialog or popover opening so queued Escape requests cannot close a later opening.
|
|
489
|
+
*/
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Tracks dialog and popover Escape targets in opening order.
|
|
493
|
+
*/
|
|
494
|
+
var escapeLayers = [];
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Removes an opening from Escape tracking so it cannot receive a later dismissal request.
|
|
498
|
+
*/
|
|
499
|
+
function unregisterEscapeLayer(_ref18) {
|
|
500
|
+
var element = _ref18.element;
|
|
501
|
+
var index = escapeLayers.findIndex(function (layer) {
|
|
502
|
+
return layer.element === element;
|
|
503
|
+
});
|
|
504
|
+
if (index !== -1) {
|
|
505
|
+
escapeLayers.splice(index, 1);
|
|
496
506
|
}
|
|
497
|
-
return null;
|
|
498
507
|
}
|
|
499
508
|
|
|
500
|
-
|
|
501
|
-
|
|
509
|
+
/**
|
|
510
|
+
* Records a new opening, replacing any stale registration for the same element.
|
|
511
|
+
*/
|
|
512
|
+
function registerEscapeLayer(_ref19) {
|
|
513
|
+
var layer = _ref19.layer;
|
|
514
|
+
unregisterEscapeLayer({
|
|
515
|
+
element: layer.element
|
|
516
|
+
});
|
|
517
|
+
escapeLayers.push(layer);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Checks whether a tracked element is still connected and open, including direct DOM changes.
|
|
522
|
+
*/
|
|
523
|
+
function isEscapeLayerOpen(_ref20) {
|
|
524
|
+
var layer = _ref20.layer;
|
|
525
|
+
return layer.element.isConnected && (layer.type === 'dialog' ? layer.element.open : isPopoverOpen({
|
|
526
|
+
element: layer.element
|
|
527
|
+
}));
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Removes registrations for closed or disconnected elements before choosing an Escape target.
|
|
532
|
+
*/
|
|
533
|
+
function pruneClosedEscapeLayers() {
|
|
534
|
+
escapeLayers.filter(function (layer) {
|
|
535
|
+
return !isEscapeLayerOpen({
|
|
536
|
+
layer: layer
|
|
537
|
+
});
|
|
538
|
+
}).forEach(function (layer) {
|
|
539
|
+
return unregisterEscapeLayer({
|
|
540
|
+
element: layer.element
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Checks whether a layer accepts Escape, using closedby and modality for dialogs.
|
|
547
|
+
* Spec: https://html.spec.whatwg.org/multipage/interactive-elements.html#computed-closed-by-state
|
|
548
|
+
*/
|
|
549
|
+
function acceptsEscape(_ref21) {
|
|
550
|
+
var _layer$element$getAtt;
|
|
551
|
+
var layer = _ref21.layer;
|
|
552
|
+
if (layer.type === 'popover') {
|
|
553
|
+
return true;
|
|
554
|
+
}
|
|
555
|
+
var closedBy = (_layer$element$getAtt = layer.element.getAttribute('closedby')) === null || _layer$element$getAtt === void 0 ? void 0 : _layer$element$getAtt.toLowerCase();
|
|
556
|
+
if (closedBy === 'none') {
|
|
557
|
+
return false;
|
|
558
|
+
}
|
|
559
|
+
if (closedBy === 'any' || closedBy === 'closerequest') {
|
|
560
|
+
return true;
|
|
561
|
+
}
|
|
562
|
+
// Missing or invalid closedby enables Escape for modal dialogs only.
|
|
563
|
+
return Boolean(layer.element._isModal);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Dismisses the latest eligible Escape target, allowing application handlers to prevent dialog cancellation.
|
|
568
|
+
* Spec: https://html.spec.whatwg.org/multipage/interactive-elements.html#set-up-the-dialog-close-watcher
|
|
569
|
+
*/
|
|
502
570
|
function handleDocumentKeydown(event) {
|
|
503
|
-
|
|
571
|
+
// A prevented key event must not invoke its default dismissal action.
|
|
572
|
+
if (event.key !== 'Escape' || event.defaultPrevented) {
|
|
504
573
|
return;
|
|
505
574
|
}
|
|
506
|
-
|
|
507
|
-
|
|
575
|
+
pruneClosedEscapeLayers();
|
|
576
|
+
|
|
577
|
+
// Capture this opening so handlers cannot redirect the same Escape to another layer.
|
|
578
|
+
var layer = escapeLayers.findLast(function (candidate) {
|
|
579
|
+
return acceptsEscape({
|
|
580
|
+
layer: candidate
|
|
581
|
+
});
|
|
508
582
|
});
|
|
509
|
-
if (
|
|
510
|
-
topHint.hidePopover();
|
|
583
|
+
if (!layer) {
|
|
511
584
|
return;
|
|
512
585
|
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
topAuto.hidePopover();
|
|
586
|
+
if (layer.type === 'popover') {
|
|
587
|
+
// Popover dismissal is synchronous.
|
|
588
|
+
layer.element.hidePopover();
|
|
589
|
+
return;
|
|
518
590
|
}
|
|
591
|
+
|
|
592
|
+
// Defer the dialog default action until application keydown listeners have run.
|
|
593
|
+
setTimeout(function () {
|
|
594
|
+
// Handlers may prevent Escape, change eligibility, or close and reopen the target.
|
|
595
|
+
if (event.defaultPrevented || !escapeLayers.includes(layer) || !isEscapeLayerOpen({
|
|
596
|
+
layer: layer
|
|
597
|
+
}) || !acceptsEscape({
|
|
598
|
+
layer: layer
|
|
599
|
+
})) {
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
var allowed = layer.element.dispatchEvent(new Event('cancel', {
|
|
603
|
+
cancelable: true,
|
|
604
|
+
bubbles: false
|
|
605
|
+
}));
|
|
606
|
+
// The cancel handler can close or reopen the dialog; only close the original opening.
|
|
607
|
+
if (allowed && escapeLayers.includes(layer) && isEscapeLayerOpen({
|
|
608
|
+
layer: layer
|
|
609
|
+
})) {
|
|
610
|
+
// close() dispatches beforetoggle and queues toggle and close notifications.
|
|
611
|
+
layer.element.close();
|
|
612
|
+
}
|
|
613
|
+
}, 0);
|
|
519
614
|
}
|
|
520
615
|
if (typeof HTMLElement !== 'undefined') {
|
|
521
616
|
var schedulePopoverToggle = createToggleScheduler();
|
|
@@ -597,6 +692,12 @@ if (typeof HTMLElement !== 'undefined') {
|
|
|
597
692
|
});
|
|
598
693
|
if (stack && !stack.includes(this)) {
|
|
599
694
|
stack.push(this);
|
|
695
|
+
registerEscapeLayer({
|
|
696
|
+
layer: {
|
|
697
|
+
type: 'popover',
|
|
698
|
+
element: this
|
|
699
|
+
}
|
|
700
|
+
});
|
|
600
701
|
}
|
|
601
702
|
clearOpacityOnOpenToggle({
|
|
602
703
|
element: this
|
|
@@ -632,6 +733,9 @@ if (typeof HTMLElement !== 'undefined') {
|
|
|
632
733
|
cancelable: false
|
|
633
734
|
});
|
|
634
735
|
this.removeAttribute('data-popover-open');
|
|
736
|
+
unregisterEscapeLayer({
|
|
737
|
+
element: this
|
|
738
|
+
});
|
|
635
739
|
var stack = stackForMode({
|
|
636
740
|
mode: getPopoverMode({
|
|
637
741
|
element: this
|
|
@@ -763,6 +867,12 @@ if (typeof HTMLDialogElement !== 'undefined') {
|
|
|
763
867
|
});
|
|
764
868
|
this.setAttribute('open', '');
|
|
765
869
|
this._isModal = true;
|
|
870
|
+
registerEscapeLayer({
|
|
871
|
+
layer: {
|
|
872
|
+
type: 'dialog',
|
|
873
|
+
element: this
|
|
874
|
+
}
|
|
875
|
+
});
|
|
766
876
|
scheduleDialogToggle({
|
|
767
877
|
dialog: this,
|
|
768
878
|
newState: 'open',
|
|
@@ -785,6 +895,13 @@ if (typeof HTMLDialogElement !== 'undefined') {
|
|
|
785
895
|
});
|
|
786
896
|
this.setAttribute('open', '');
|
|
787
897
|
this._isModal = false;
|
|
898
|
+
// Non-modal dialogs can opt into Escape through closedby.
|
|
899
|
+
registerEscapeLayer({
|
|
900
|
+
layer: {
|
|
901
|
+
type: 'dialog',
|
|
902
|
+
element: this
|
|
903
|
+
}
|
|
904
|
+
});
|
|
788
905
|
scheduleDialogToggle({
|
|
789
906
|
dialog: this,
|
|
790
907
|
newState: 'open',
|
|
@@ -808,6 +925,9 @@ if (typeof HTMLDialogElement !== 'undefined') {
|
|
|
808
925
|
cancelable: false
|
|
809
926
|
});
|
|
810
927
|
this.removeAttribute('open');
|
|
928
|
+
unregisterEscapeLayer({
|
|
929
|
+
element: this
|
|
930
|
+
});
|
|
811
931
|
this._isModal = false;
|
|
812
932
|
if (returnValue !== undefined) {
|
|
813
933
|
this.returnValue = returnValue;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/* dialog-content.tsx generated by @compiled/babel-plugin v3.0.2 */
|
|
2
2
|
import "./dialog-content.compiled.css";
|
|
3
3
|
import { ax, ix } from "@compiled/react/runtime";
|
|
4
|
-
import React, { forwardRef, useCallback, useId,
|
|
4
|
+
import React, { forwardRef, useCallback, useId, useRef } from 'react';
|
|
5
5
|
import { cx } from '@compiled/react';
|
|
6
6
|
import { bindAll } from 'bind-event-listener';
|
|
7
7
|
import mergeRefs from '@atlaskit/ds-lib/merge-refs';
|
|
8
8
|
import noop from '@atlaskit/ds-lib/noop';
|
|
9
|
+
import { useLayoutEffect } from '@atlaskit/ds-lib/use-layout-effect';
|
|
9
10
|
import { useNotifyOpenLayerObserver } from '@atlaskit/layering/use-notify-open-layer-observer';
|
|
10
11
|
import { useAnimatedVisibility } from '../internal/use-animated-visibility';
|
|
11
12
|
import { useFocusWrap } from '../internal/use-focus-wrap';
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
* See `notes/decisions/anchored-popover-at-point.md` for why this is a sibling
|
|
8
8
|
* hook instead of an anchor union inside `useAnchoredPopover`.
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
10
|
+
import { useRef } from 'react';
|
|
11
|
+
import { useLayoutEffect } from '@atlaskit/ds-lib/use-layout-effect';
|
|
11
12
|
import { useAnchoredPopover } from './use-anchored-popover';
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
* See `notes/architecture/positioning.md` and
|
|
11
11
|
* `notes/decisions/fit-available-space.md`.
|
|
12
12
|
*/
|
|
13
|
-
import {
|
|
13
|
+
import { useMemo } from 'react';
|
|
14
14
|
import { useId } from '@atlaskit/ds-lib/use-id';
|
|
15
|
+
import { useLayoutEffect } from '@atlaskit/ds-lib/use-layout-effect';
|
|
15
16
|
import { applyAnchorPositioning } from './anchor-positioning/apply-anchor-positioning';
|
|
16
17
|
import { getAnchoredPopoverSizeDeclarations } from './anchored-popover-size';
|
|
17
18
|
import { applyJavaScriptFallbackPositioning } from './javascript-fallback/apply-javascript-fallback-positioning';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { useCallback, useEffect,
|
|
1
|
+
import { useCallback, useEffect, useReducer, useRef } from 'react';
|
|
2
|
+
import { useLayoutEffect } from '@atlaskit/ds-lib/use-layout-effect';
|
|
2
3
|
import { isNativeElementOpen } from './is-native-element-open';
|
|
3
4
|
import { prefersReducedMotion } from './reduced-motion';
|
|
4
5
|
function runCancellableSettlement({
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/* popover.tsx generated by @compiled/babel-plugin v3.0.2 */
|
|
2
2
|
import "./popover.compiled.css";
|
|
3
3
|
import { ax, ix } from "@compiled/react/runtime";
|
|
4
|
-
import React, { forwardRef, useCallback, useId,
|
|
4
|
+
import React, { forwardRef, useCallback, useId, useMemo, useRef } from 'react';
|
|
5
5
|
import { cx } from '@compiled/react';
|
|
6
6
|
import { bind } from 'bind-event-listener';
|
|
7
7
|
import mergeRefs from '@atlaskit/ds-lib/merge-refs';
|
|
8
8
|
import once from '@atlaskit/ds-lib/once';
|
|
9
|
+
import { useLayoutEffect } from '@atlaskit/ds-lib/use-layout-effect';
|
|
9
10
|
import { useNotifyOpenLayerObserver } from '@atlaskit/layering/use-notify-open-layer-observer';
|
|
10
11
|
import { isNativeElementOpen } from '../internal/is-native-element-open';
|
|
11
12
|
import { resolvePlacement } from '../internal/resolve-placement';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// Node supports findLast, but the package defaults to older array type declarations.
|
|
2
|
+
/// <reference lib="es2023.array" />
|
|
1
3
|
/* eslint-disable compat/compat */
|
|
2
4
|
/**
|
|
3
5
|
* Popover API & HTMLDialogElement polyfills for jsdom.
|
|
@@ -495,41 +497,129 @@ function handleDocumentPointerup(event) {
|
|
|
495
497
|
});
|
|
496
498
|
}
|
|
497
499
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
500
|
+
/**
|
|
501
|
+
* Represents one dialog or popover opening so queued Escape requests cannot close a later opening.
|
|
502
|
+
*/
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Tracks dialog and popover Escape targets in opening order.
|
|
506
|
+
*/
|
|
507
|
+
const escapeLayers = [];
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Removes an opening from Escape tracking so it cannot receive a later dismissal request.
|
|
511
|
+
*/
|
|
512
|
+
function unregisterEscapeLayer({
|
|
513
|
+
element
|
|
503
514
|
}) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
return candidate;
|
|
508
|
-
}
|
|
509
|
-
stack.pop();
|
|
515
|
+
const index = escapeLayers.findIndex(layer => layer.element === element);
|
|
516
|
+
if (index !== -1) {
|
|
517
|
+
escapeLayers.splice(index, 1);
|
|
510
518
|
}
|
|
511
|
-
return null;
|
|
512
519
|
}
|
|
513
520
|
|
|
514
|
-
|
|
515
|
-
|
|
521
|
+
/**
|
|
522
|
+
* Records a new opening, replacing any stale registration for the same element.
|
|
523
|
+
*/
|
|
524
|
+
function registerEscapeLayer({
|
|
525
|
+
layer
|
|
526
|
+
}) {
|
|
527
|
+
unregisterEscapeLayer({
|
|
528
|
+
element: layer.element
|
|
529
|
+
});
|
|
530
|
+
escapeLayers.push(layer);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Checks whether a tracked element is still connected and open, including direct DOM changes.
|
|
535
|
+
*/
|
|
536
|
+
function isEscapeLayerOpen({
|
|
537
|
+
layer
|
|
538
|
+
}) {
|
|
539
|
+
return layer.element.isConnected && (layer.type === 'dialog' ? layer.element.open : isPopoverOpen({
|
|
540
|
+
element: layer.element
|
|
541
|
+
}));
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Removes registrations for closed or disconnected elements before choosing an Escape target.
|
|
546
|
+
*/
|
|
547
|
+
function pruneClosedEscapeLayers() {
|
|
548
|
+
escapeLayers.filter(layer => !isEscapeLayerOpen({
|
|
549
|
+
layer
|
|
550
|
+
})).forEach(layer => unregisterEscapeLayer({
|
|
551
|
+
element: layer.element
|
|
552
|
+
}));
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Checks whether a layer accepts Escape, using closedby and modality for dialogs.
|
|
557
|
+
* Spec: https://html.spec.whatwg.org/multipage/interactive-elements.html#computed-closed-by-state
|
|
558
|
+
*/
|
|
559
|
+
function acceptsEscape({
|
|
560
|
+
layer
|
|
561
|
+
}) {
|
|
562
|
+
var _layer$element$getAtt;
|
|
563
|
+
if (layer.type === 'popover') {
|
|
564
|
+
return true;
|
|
565
|
+
}
|
|
566
|
+
const closedBy = (_layer$element$getAtt = layer.element.getAttribute('closedby')) === null || _layer$element$getAtt === void 0 ? void 0 : _layer$element$getAtt.toLowerCase();
|
|
567
|
+
if (closedBy === 'none') {
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
if (closedBy === 'any' || closedBy === 'closerequest') {
|
|
571
|
+
return true;
|
|
572
|
+
}
|
|
573
|
+
// Missing or invalid closedby enables Escape for modal dialogs only.
|
|
574
|
+
return Boolean(layer.element._isModal);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Dismisses the latest eligible Escape target, allowing application handlers to prevent dialog cancellation.
|
|
579
|
+
* Spec: https://html.spec.whatwg.org/multipage/interactive-elements.html#set-up-the-dialog-close-watcher
|
|
580
|
+
*/
|
|
516
581
|
function handleDocumentKeydown(event) {
|
|
517
|
-
|
|
582
|
+
// A prevented key event must not invoke its default dismissal action.
|
|
583
|
+
if (event.key !== 'Escape' || event.defaultPrevented) {
|
|
518
584
|
return;
|
|
519
585
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
586
|
+
pruneClosedEscapeLayers();
|
|
587
|
+
|
|
588
|
+
// Capture this opening so handlers cannot redirect the same Escape to another layer.
|
|
589
|
+
const layer = escapeLayers.findLast(candidate => acceptsEscape({
|
|
590
|
+
layer: candidate
|
|
591
|
+
}));
|
|
592
|
+
if (!layer) {
|
|
525
593
|
return;
|
|
526
594
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
topAuto.hidePopover();
|
|
595
|
+
if (layer.type === 'popover') {
|
|
596
|
+
// Popover dismissal is synchronous.
|
|
597
|
+
layer.element.hidePopover();
|
|
598
|
+
return;
|
|
532
599
|
}
|
|
600
|
+
|
|
601
|
+
// Defer the dialog default action until application keydown listeners have run.
|
|
602
|
+
setTimeout(() => {
|
|
603
|
+
// Handlers may prevent Escape, change eligibility, or close and reopen the target.
|
|
604
|
+
if (event.defaultPrevented || !escapeLayers.includes(layer) || !isEscapeLayerOpen({
|
|
605
|
+
layer
|
|
606
|
+
}) || !acceptsEscape({
|
|
607
|
+
layer
|
|
608
|
+
})) {
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
const allowed = layer.element.dispatchEvent(new Event('cancel', {
|
|
612
|
+
cancelable: true,
|
|
613
|
+
bubbles: false
|
|
614
|
+
}));
|
|
615
|
+
// The cancel handler can close or reopen the dialog; only close the original opening.
|
|
616
|
+
if (allowed && escapeLayers.includes(layer) && isEscapeLayerOpen({
|
|
617
|
+
layer
|
|
618
|
+
})) {
|
|
619
|
+
// close() dispatches beforetoggle and queues toggle and close notifications.
|
|
620
|
+
layer.element.close();
|
|
621
|
+
}
|
|
622
|
+
}, 0);
|
|
533
623
|
}
|
|
534
624
|
if (typeof HTMLElement !== 'undefined') {
|
|
535
625
|
const schedulePopoverToggle = createToggleScheduler();
|
|
@@ -611,6 +701,12 @@ if (typeof HTMLElement !== 'undefined') {
|
|
|
611
701
|
});
|
|
612
702
|
if (stack && !stack.includes(this)) {
|
|
613
703
|
stack.push(this);
|
|
704
|
+
registerEscapeLayer({
|
|
705
|
+
layer: {
|
|
706
|
+
type: 'popover',
|
|
707
|
+
element: this
|
|
708
|
+
}
|
|
709
|
+
});
|
|
614
710
|
}
|
|
615
711
|
clearOpacityOnOpenToggle({
|
|
616
712
|
element: this
|
|
@@ -646,6 +742,9 @@ if (typeof HTMLElement !== 'undefined') {
|
|
|
646
742
|
cancelable: false
|
|
647
743
|
});
|
|
648
744
|
this.removeAttribute('data-popover-open');
|
|
745
|
+
unregisterEscapeLayer({
|
|
746
|
+
element: this
|
|
747
|
+
});
|
|
649
748
|
const stack = stackForMode({
|
|
650
749
|
mode: getPopoverMode({
|
|
651
750
|
element: this
|
|
@@ -773,6 +872,12 @@ if (typeof HTMLDialogElement !== 'undefined') {
|
|
|
773
872
|
});
|
|
774
873
|
this.setAttribute('open', '');
|
|
775
874
|
this._isModal = true;
|
|
875
|
+
registerEscapeLayer({
|
|
876
|
+
layer: {
|
|
877
|
+
type: 'dialog',
|
|
878
|
+
element: this
|
|
879
|
+
}
|
|
880
|
+
});
|
|
776
881
|
scheduleDialogToggle({
|
|
777
882
|
dialog: this,
|
|
778
883
|
newState: 'open',
|
|
@@ -795,6 +900,13 @@ if (typeof HTMLDialogElement !== 'undefined') {
|
|
|
795
900
|
});
|
|
796
901
|
this.setAttribute('open', '');
|
|
797
902
|
this._isModal = false;
|
|
903
|
+
// Non-modal dialogs can opt into Escape through closedby.
|
|
904
|
+
registerEscapeLayer({
|
|
905
|
+
layer: {
|
|
906
|
+
type: 'dialog',
|
|
907
|
+
element: this
|
|
908
|
+
}
|
|
909
|
+
});
|
|
798
910
|
scheduleDialogToggle({
|
|
799
911
|
dialog: this,
|
|
800
912
|
newState: 'open',
|
|
@@ -818,6 +930,9 @@ if (typeof HTMLDialogElement !== 'undefined') {
|
|
|
818
930
|
cancelable: false
|
|
819
931
|
});
|
|
820
932
|
this.removeAttribute('open');
|
|
933
|
+
unregisterEscapeLayer({
|
|
934
|
+
element: this
|
|
935
|
+
});
|
|
821
936
|
this._isModal = false;
|
|
822
937
|
if (returnValue !== undefined) {
|
|
823
938
|
this.returnValue = returnValue;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/* dialog-content.tsx generated by @compiled/babel-plugin v3.0.2 */
|
|
2
2
|
import "./dialog-content.compiled.css";
|
|
3
3
|
import { ax, ix } from "@compiled/react/runtime";
|
|
4
|
-
import React, { forwardRef, useCallback, useId,
|
|
4
|
+
import React, { forwardRef, useCallback, useId, useRef } from 'react';
|
|
5
5
|
import { cx } from '@compiled/react';
|
|
6
6
|
import { bindAll } from 'bind-event-listener';
|
|
7
7
|
import mergeRefs from '@atlaskit/ds-lib/merge-refs';
|
|
8
8
|
import noop from '@atlaskit/ds-lib/noop';
|
|
9
|
+
import { useLayoutEffect } from '@atlaskit/ds-lib/use-layout-effect';
|
|
9
10
|
import { useNotifyOpenLayerObserver } from '@atlaskit/layering/use-notify-open-layer-observer';
|
|
10
11
|
import { useAnimatedVisibility } from '../internal/use-animated-visibility';
|
|
11
12
|
import { useFocusWrap } from '../internal/use-focus-wrap';
|
|
@@ -12,7 +12,8 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
12
12
|
* See `notes/decisions/anchored-popover-at-point.md` for why this is a sibling
|
|
13
13
|
* hook instead of an anchor union inside `useAnchoredPopover`.
|
|
14
14
|
*/
|
|
15
|
-
import {
|
|
15
|
+
import { useRef } from 'react';
|
|
16
|
+
import { useLayoutEffect } from '@atlaskit/ds-lib/use-layout-effect';
|
|
16
17
|
import { useAnchoredPopover } from './use-anchored-popover';
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
* See `notes/architecture/positioning.md` and
|
|
11
11
|
* `notes/decisions/fit-available-space.md`.
|
|
12
12
|
*/
|
|
13
|
-
import {
|
|
13
|
+
import { useMemo } from 'react';
|
|
14
14
|
import { useId } from '@atlaskit/ds-lib/use-id';
|
|
15
|
+
import { useLayoutEffect } from '@atlaskit/ds-lib/use-layout-effect';
|
|
15
16
|
import { applyAnchorPositioning } from './anchor-positioning/apply-anchor-positioning';
|
|
16
17
|
import { getAnchoredPopoverSizeDeclarations } from './anchored-popover-size';
|
|
17
18
|
import { applyJavaScriptFallbackPositioning } from './javascript-fallback/apply-javascript-fallback-positioning';
|
|
@@ -2,7 +2,8 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
|
2
2
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
3
3
|
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; }
|
|
4
4
|
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; }
|
|
5
|
-
import { useCallback, useEffect,
|
|
5
|
+
import { useCallback, useEffect, useReducer, useRef } from 'react';
|
|
6
|
+
import { useLayoutEffect } from '@atlaskit/ds-lib/use-layout-effect';
|
|
6
7
|
import { isNativeElementOpen } from './is-native-element-open';
|
|
7
8
|
import { prefersReducedMotion } from './reduced-motion';
|
|
8
9
|
function runCancellableSettlement(_ref) {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/* popover.tsx generated by @compiled/babel-plugin v3.0.2 */
|
|
2
2
|
import "./popover.compiled.css";
|
|
3
3
|
import { ax, ix } from "@compiled/react/runtime";
|
|
4
|
-
import React, { forwardRef, useCallback, useId,
|
|
4
|
+
import React, { forwardRef, useCallback, useId, useMemo, useRef } from 'react';
|
|
5
5
|
import { cx } from '@compiled/react';
|
|
6
6
|
import { bind } from 'bind-event-listener';
|
|
7
7
|
import mergeRefs from '@atlaskit/ds-lib/merge-refs';
|
|
8
8
|
import once from '@atlaskit/ds-lib/once';
|
|
9
|
+
import { useLayoutEffect } from '@atlaskit/ds-lib/use-layout-effect';
|
|
9
10
|
import { useNotifyOpenLayerObserver } from '@atlaskit/layering/use-notify-open-layer-observer';
|
|
10
11
|
import { isNativeElementOpen } from '../internal/is-native-element-open';
|
|
11
12
|
import { resolvePlacement } from '../internal/resolve-placement';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// Node supports findLast, but the package defaults to older array type declarations.
|
|
2
|
+
/// <reference lib="es2023.array" />
|
|
1
3
|
/* eslint-disable compat/compat */
|
|
2
4
|
/**
|
|
3
5
|
* Popover API & HTMLDialogElement polyfills for jsdom.
|
|
@@ -480,40 +482,133 @@ function handleDocumentPointerup(event) {
|
|
|
480
482
|
});
|
|
481
483
|
}
|
|
482
484
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
485
|
+
/**
|
|
486
|
+
* Represents one dialog or popover opening so queued Escape requests cannot close a later opening.
|
|
487
|
+
*/
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Tracks dialog and popover Escape targets in opening order.
|
|
491
|
+
*/
|
|
492
|
+
var escapeLayers = [];
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Removes an opening from Escape tracking so it cannot receive a later dismissal request.
|
|
496
|
+
*/
|
|
497
|
+
function unregisterEscapeLayer(_ref18) {
|
|
498
|
+
var element = _ref18.element;
|
|
499
|
+
var index = escapeLayers.findIndex(function (layer) {
|
|
500
|
+
return layer.element === element;
|
|
501
|
+
});
|
|
502
|
+
if (index !== -1) {
|
|
503
|
+
escapeLayers.splice(index, 1);
|
|
494
504
|
}
|
|
495
|
-
return null;
|
|
496
505
|
}
|
|
497
506
|
|
|
498
|
-
|
|
499
|
-
|
|
507
|
+
/**
|
|
508
|
+
* Records a new opening, replacing any stale registration for the same element.
|
|
509
|
+
*/
|
|
510
|
+
function registerEscapeLayer(_ref19) {
|
|
511
|
+
var layer = _ref19.layer;
|
|
512
|
+
unregisterEscapeLayer({
|
|
513
|
+
element: layer.element
|
|
514
|
+
});
|
|
515
|
+
escapeLayers.push(layer);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Checks whether a tracked element is still connected and open, including direct DOM changes.
|
|
520
|
+
*/
|
|
521
|
+
function isEscapeLayerOpen(_ref20) {
|
|
522
|
+
var layer = _ref20.layer;
|
|
523
|
+
return layer.element.isConnected && (layer.type === 'dialog' ? layer.element.open : isPopoverOpen({
|
|
524
|
+
element: layer.element
|
|
525
|
+
}));
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Removes registrations for closed or disconnected elements before choosing an Escape target.
|
|
530
|
+
*/
|
|
531
|
+
function pruneClosedEscapeLayers() {
|
|
532
|
+
escapeLayers.filter(function (layer) {
|
|
533
|
+
return !isEscapeLayerOpen({
|
|
534
|
+
layer: layer
|
|
535
|
+
});
|
|
536
|
+
}).forEach(function (layer) {
|
|
537
|
+
return unregisterEscapeLayer({
|
|
538
|
+
element: layer.element
|
|
539
|
+
});
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Checks whether a layer accepts Escape, using closedby and modality for dialogs.
|
|
545
|
+
* Spec: https://html.spec.whatwg.org/multipage/interactive-elements.html#computed-closed-by-state
|
|
546
|
+
*/
|
|
547
|
+
function acceptsEscape(_ref21) {
|
|
548
|
+
var _layer$element$getAtt;
|
|
549
|
+
var layer = _ref21.layer;
|
|
550
|
+
if (layer.type === 'popover') {
|
|
551
|
+
return true;
|
|
552
|
+
}
|
|
553
|
+
var closedBy = (_layer$element$getAtt = layer.element.getAttribute('closedby')) === null || _layer$element$getAtt === void 0 ? void 0 : _layer$element$getAtt.toLowerCase();
|
|
554
|
+
if (closedBy === 'none') {
|
|
555
|
+
return false;
|
|
556
|
+
}
|
|
557
|
+
if (closedBy === 'any' || closedBy === 'closerequest') {
|
|
558
|
+
return true;
|
|
559
|
+
}
|
|
560
|
+
// Missing or invalid closedby enables Escape for modal dialogs only.
|
|
561
|
+
return Boolean(layer.element._isModal);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Dismisses the latest eligible Escape target, allowing application handlers to prevent dialog cancellation.
|
|
566
|
+
* Spec: https://html.spec.whatwg.org/multipage/interactive-elements.html#set-up-the-dialog-close-watcher
|
|
567
|
+
*/
|
|
500
568
|
function handleDocumentKeydown(event) {
|
|
501
|
-
|
|
569
|
+
// A prevented key event must not invoke its default dismissal action.
|
|
570
|
+
if (event.key !== 'Escape' || event.defaultPrevented) {
|
|
502
571
|
return;
|
|
503
572
|
}
|
|
504
|
-
|
|
505
|
-
|
|
573
|
+
pruneClosedEscapeLayers();
|
|
574
|
+
|
|
575
|
+
// Capture this opening so handlers cannot redirect the same Escape to another layer.
|
|
576
|
+
var layer = escapeLayers.findLast(function (candidate) {
|
|
577
|
+
return acceptsEscape({
|
|
578
|
+
layer: candidate
|
|
579
|
+
});
|
|
506
580
|
});
|
|
507
|
-
if (
|
|
508
|
-
topHint.hidePopover();
|
|
581
|
+
if (!layer) {
|
|
509
582
|
return;
|
|
510
583
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
topAuto.hidePopover();
|
|
584
|
+
if (layer.type === 'popover') {
|
|
585
|
+
// Popover dismissal is synchronous.
|
|
586
|
+
layer.element.hidePopover();
|
|
587
|
+
return;
|
|
516
588
|
}
|
|
589
|
+
|
|
590
|
+
// Defer the dialog default action until application keydown listeners have run.
|
|
591
|
+
setTimeout(function () {
|
|
592
|
+
// Handlers may prevent Escape, change eligibility, or close and reopen the target.
|
|
593
|
+
if (event.defaultPrevented || !escapeLayers.includes(layer) || !isEscapeLayerOpen({
|
|
594
|
+
layer: layer
|
|
595
|
+
}) || !acceptsEscape({
|
|
596
|
+
layer: layer
|
|
597
|
+
})) {
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
var allowed = layer.element.dispatchEvent(new Event('cancel', {
|
|
601
|
+
cancelable: true,
|
|
602
|
+
bubbles: false
|
|
603
|
+
}));
|
|
604
|
+
// The cancel handler can close or reopen the dialog; only close the original opening.
|
|
605
|
+
if (allowed && escapeLayers.includes(layer) && isEscapeLayerOpen({
|
|
606
|
+
layer: layer
|
|
607
|
+
})) {
|
|
608
|
+
// close() dispatches beforetoggle and queues toggle and close notifications.
|
|
609
|
+
layer.element.close();
|
|
610
|
+
}
|
|
611
|
+
}, 0);
|
|
517
612
|
}
|
|
518
613
|
if (typeof HTMLElement !== 'undefined') {
|
|
519
614
|
var schedulePopoverToggle = createToggleScheduler();
|
|
@@ -595,6 +690,12 @@ if (typeof HTMLElement !== 'undefined') {
|
|
|
595
690
|
});
|
|
596
691
|
if (stack && !stack.includes(this)) {
|
|
597
692
|
stack.push(this);
|
|
693
|
+
registerEscapeLayer({
|
|
694
|
+
layer: {
|
|
695
|
+
type: 'popover',
|
|
696
|
+
element: this
|
|
697
|
+
}
|
|
698
|
+
});
|
|
598
699
|
}
|
|
599
700
|
clearOpacityOnOpenToggle({
|
|
600
701
|
element: this
|
|
@@ -630,6 +731,9 @@ if (typeof HTMLElement !== 'undefined') {
|
|
|
630
731
|
cancelable: false
|
|
631
732
|
});
|
|
632
733
|
this.removeAttribute('data-popover-open');
|
|
734
|
+
unregisterEscapeLayer({
|
|
735
|
+
element: this
|
|
736
|
+
});
|
|
633
737
|
var stack = stackForMode({
|
|
634
738
|
mode: getPopoverMode({
|
|
635
739
|
element: this
|
|
@@ -761,6 +865,12 @@ if (typeof HTMLDialogElement !== 'undefined') {
|
|
|
761
865
|
});
|
|
762
866
|
this.setAttribute('open', '');
|
|
763
867
|
this._isModal = true;
|
|
868
|
+
registerEscapeLayer({
|
|
869
|
+
layer: {
|
|
870
|
+
type: 'dialog',
|
|
871
|
+
element: this
|
|
872
|
+
}
|
|
873
|
+
});
|
|
764
874
|
scheduleDialogToggle({
|
|
765
875
|
dialog: this,
|
|
766
876
|
newState: 'open',
|
|
@@ -783,6 +893,13 @@ if (typeof HTMLDialogElement !== 'undefined') {
|
|
|
783
893
|
});
|
|
784
894
|
this.setAttribute('open', '');
|
|
785
895
|
this._isModal = false;
|
|
896
|
+
// Non-modal dialogs can opt into Escape through closedby.
|
|
897
|
+
registerEscapeLayer({
|
|
898
|
+
layer: {
|
|
899
|
+
type: 'dialog',
|
|
900
|
+
element: this
|
|
901
|
+
}
|
|
902
|
+
});
|
|
786
903
|
scheduleDialogToggle({
|
|
787
904
|
dialog: this,
|
|
788
905
|
newState: 'open',
|
|
@@ -806,6 +923,9 @@ if (typeof HTMLDialogElement !== 'undefined') {
|
|
|
806
923
|
cancelable: false
|
|
807
924
|
});
|
|
808
925
|
this.removeAttribute('open');
|
|
926
|
+
unregisterEscapeLayer({
|
|
927
|
+
element: this
|
|
928
|
+
});
|
|
809
929
|
this._isModal = false;
|
|
810
930
|
if (returnValue !== undefined) {
|
|
811
931
|
this.returnValue = returnValue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/top-layer",
|
|
3
|
-
"version": "6.2.
|
|
3
|
+
"version": "6.2.5",
|
|
4
4
|
"description": "Low-level layering primitives based on popover and dialog",
|
|
5
5
|
"homepage": "https://atlassian.design/components/top-layer",
|
|
6
6
|
"repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
|