@atlaskit/top-layer 0.8.0 → 0.10.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 +41 -0
- package/README.md +5 -1
- package/dialog/create-close-event/package.json +17 -0
- package/dist/cjs/animations/presets.js +11 -4
- package/dist/cjs/arrow/index.js +131 -0
- package/dist/cjs/arrow/types.js +5 -0
- package/dist/cjs/dialog/dialog-content.js +23 -6
- package/dist/cjs/entry-points/dialog/create-close-event.js +12 -0
- package/dist/cjs/entry-points/placement-map.js +6 -5
- package/dist/cjs/entry-points/popover/create-close-event.js +12 -0
- package/dist/cjs/focus/focus.js +73 -19
- package/dist/cjs/index.js +3 -4
- package/dist/cjs/internal/resolve-css-length-to-pixels.js +61 -10
- package/dist/cjs/internal/role-types.js +40 -9
- package/dist/cjs/internal/set-style.js +23 -25
- package/dist/cjs/internal/use-anchor-position.js +109 -68
- package/dist/cjs/internal/use-focus-wrap.js +13 -2
- package/dist/cjs/internal/use-initial-focus.js +31 -10
- package/dist/cjs/placement-map/index.js +9 -110
- package/dist/cjs/placement-map/legacy-placements.js +113 -0
- package/dist/cjs/popover/popover.js +44 -11
- package/dist/cjs/popup/popup-content.js +19 -13
- package/dist/cjs/popup/popup-context.js +2 -0
- package/dist/cjs/popup/popup-surface.js +6 -0
- package/dist/cjs/popup/popup-trigger-function.js +1 -1
- package/dist/cjs/popup/popup-trigger.js +17 -37
- package/dist/cjs/popup/popup.js +21 -10
- package/dist/cjs/use-arrow-navigation/use-arrow-navigation.js +27 -10
- package/dist/es2019/animations/presets.js +10 -3
- package/dist/es2019/arrow/index.js +269 -0
- package/dist/es2019/arrow/types.js +1 -0
- package/dist/es2019/dialog/dialog-content.js +23 -6
- package/dist/es2019/entry-points/create-close-event.js +7 -0
- package/dist/es2019/entry-points/dialog/create-close-event.js +1 -0
- package/dist/es2019/entry-points/placement-map.js +2 -1
- package/dist/es2019/entry-points/popover/create-close-event.js +1 -0
- package/dist/es2019/focus/focus.js +58 -7
- package/dist/es2019/index.js +3 -4
- package/dist/es2019/internal/resolve-css-length-to-pixels.js +60 -7
- package/dist/es2019/internal/role-types.js +40 -9
- package/dist/es2019/internal/set-style.js +19 -22
- package/dist/es2019/internal/use-anchor-position.js +97 -54
- package/dist/es2019/internal/use-focus-wrap.js +14 -3
- package/dist/es2019/internal/use-initial-focus.js +32 -11
- package/dist/es2019/placement-map/index.js +8 -108
- package/dist/es2019/placement-map/legacy-placements.js +107 -0
- package/dist/es2019/popover/popover.js +44 -10
- package/dist/es2019/popup/popup-content.js +20 -14
- package/dist/es2019/popup/popup-context.js +2 -0
- package/dist/es2019/popup/popup-surface.js +6 -0
- package/dist/es2019/popup/popup-trigger-function.js +1 -1
- package/dist/es2019/popup/popup-trigger.js +17 -37
- package/dist/es2019/popup/popup.js +20 -9
- package/dist/es2019/use-arrow-navigation/use-arrow-navigation.js +27 -10
- package/dist/esm/animations/presets.js +10 -3
- package/dist/esm/arrow/index.js +124 -0
- package/dist/esm/arrow/types.js +1 -0
- package/dist/esm/dialog/dialog-content.js +23 -6
- package/dist/esm/entry-points/create-close-event.js +7 -0
- package/dist/esm/entry-points/dialog/create-close-event.js +1 -0
- package/dist/esm/entry-points/placement-map.js +2 -1
- package/dist/esm/entry-points/popover/create-close-event.js +1 -0
- package/dist/esm/focus/focus.js +72 -19
- package/dist/esm/index.js +3 -4
- package/dist/esm/internal/resolve-css-length-to-pixels.js +61 -10
- package/dist/esm/internal/role-types.js +39 -9
- package/dist/esm/internal/set-style.js +23 -25
- package/dist/esm/internal/use-anchor-position.js +110 -64
- package/dist/esm/internal/use-focus-wrap.js +14 -3
- package/dist/esm/internal/use-initial-focus.js +32 -11
- package/dist/esm/placement-map/index.js +8 -108
- package/dist/esm/placement-map/legacy-placements.js +107 -0
- package/dist/esm/popover/popover.js +44 -11
- package/dist/esm/popup/popup-content.js +20 -14
- package/dist/esm/popup/popup-context.js +2 -0
- package/dist/esm/popup/popup-surface.js +6 -0
- package/dist/esm/popup/popup-trigger-function.js +1 -1
- package/dist/esm/popup/popup-trigger.js +17 -37
- package/dist/esm/popup/popup.js +21 -10
- package/dist/esm/use-arrow-navigation/use-arrow-navigation.js +27 -10
- package/dist/types/arrow/index.d.ts +24 -0
- package/dist/types/arrow/types.d.ts +29 -0
- package/dist/types/dialog/dialog-content.d.ts +5 -1
- package/dist/types/dialog/types.d.ts +50 -24
- package/dist/types/entry-points/create-close-event.d.ts +7 -0
- package/dist/types/entry-points/dialog/create-close-event.d.ts +2 -0
- package/dist/types/entry-points/placement-map.d.ts +2 -1
- package/dist/types/entry-points/popover/create-close-event.d.ts +2 -0
- package/dist/types/focus/focus.d.ts +8 -0
- package/dist/types/internal/resolve-css-length-to-pixels.d.ts +4 -6
- package/dist/types/internal/role-types.d.ts +25 -4
- package/dist/types/internal/set-style.d.ts +2 -19
- package/dist/types/internal/use-anchor-position.d.ts +2 -3
- package/dist/types/internal/use-initial-focus.d.ts +5 -4
- package/dist/types/placement-map/index.d.ts +8 -21
- package/dist/types/placement-map/legacy-placements.d.ts +21 -0
- package/dist/types/popover/popover.d.ts +1 -1
- package/dist/types/popover/types.d.ts +20 -19
- package/dist/types/popup/popup-surface.d.ts +6 -0
- package/dist/types/popup/popup-trigger-function.d.ts +10 -6
- package/dist/types/popup/popup-trigger.d.ts +8 -17
- package/dist/types/popup/popup.d.ts +2 -2
- package/dist/types/popup/types.d.ts +68 -22
- package/dist/types/use-arrow-navigation/use-arrow-navigation.d.ts +19 -5
- package/dist/types-ts4.5/arrow/index.d.ts +24 -0
- package/dist/types-ts4.5/arrow/types.d.ts +29 -0
- package/dist/types-ts4.5/dialog/dialog-content.d.ts +5 -1
- package/dist/types-ts4.5/dialog/types.d.ts +50 -24
- package/dist/types-ts4.5/entry-points/create-close-event.d.ts +7 -0
- package/dist/types-ts4.5/entry-points/dialog/create-close-event.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/placement-map.d.ts +2 -1
- package/dist/types-ts4.5/entry-points/popover/create-close-event.d.ts +2 -0
- package/dist/types-ts4.5/focus/focus.d.ts +8 -0
- package/dist/types-ts4.5/internal/resolve-css-length-to-pixels.d.ts +4 -6
- package/dist/types-ts4.5/internal/role-types.d.ts +25 -4
- package/dist/types-ts4.5/internal/set-style.d.ts +2 -19
- package/dist/types-ts4.5/internal/use-anchor-position.d.ts +2 -3
- package/dist/types-ts4.5/internal/use-initial-focus.d.ts +5 -4
- package/dist/types-ts4.5/placement-map/index.d.ts +8 -21
- package/dist/types-ts4.5/placement-map/legacy-placements.d.ts +39 -0
- package/dist/types-ts4.5/popover/popover.d.ts +1 -1
- package/dist/types-ts4.5/popover/types.d.ts +20 -19
- package/dist/types-ts4.5/popup/popup-surface.d.ts +6 -0
- package/dist/types-ts4.5/popup/popup-trigger-function.d.ts +10 -6
- package/dist/types-ts4.5/popup/popup-trigger.d.ts +8 -17
- package/dist/types-ts4.5/popup/popup.d.ts +2 -2
- package/dist/types-ts4.5/popup/types.d.ts +68 -22
- package/dist/types-ts4.5/use-arrow-navigation/use-arrow-navigation.d.ts +19 -5
- package/package.json +3 -1
- package/popover/create-close-event/package.json +17 -0
|
@@ -24,8 +24,8 @@ var _focus = require("../focus/focus");
|
|
|
24
24
|
* React 19+ reflects the JSX prop as the HTML attribute automatically.
|
|
25
25
|
*/
|
|
26
26
|
function getInitialFocusTarget(_ref) {
|
|
27
|
-
var container = _ref.container
|
|
28
|
-
|
|
27
|
+
var container = _ref.container,
|
|
28
|
+
role = _ref.role;
|
|
29
29
|
if (role === 'dialog' || role === 'alertdialog') {
|
|
30
30
|
// Prefer element with the native HTML autofocus attribute.
|
|
31
31
|
var autofocusEl = container.querySelector('[autofocus]');
|
|
@@ -66,14 +66,15 @@ function getInitialFocusTarget(_ref) {
|
|
|
66
66
|
/**
|
|
67
67
|
* Moves focus into a popover element when it opens, based on its ARIA role.
|
|
68
68
|
*
|
|
69
|
-
*
|
|
69
|
+
* Follows the WAI-ARIA APG initial-focus patterns for each role:
|
|
70
70
|
* - `dialog` / `alertdialog` → focus first focusable (or `[autofocus]`)
|
|
71
71
|
* - `menu` → focus first menu item
|
|
72
72
|
* - `listbox` → focus selected or first option
|
|
73
|
-
* - `tooltip` / no role → no focus movement
|
|
73
|
+
* - `tooltip` / no role → no focus movement (focus must remain on trigger;
|
|
74
|
+
* moving focus into the tooltip would dismiss it)
|
|
74
75
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
76
|
+
* Role is taken from the typed `role` prop - this is the consumer's contract
|
|
77
|
+
* and is not subject to drift from a directly-mutated DOM attribute.
|
|
77
78
|
*
|
|
78
79
|
* Always call this hook unconditionally. Focus is only moved when `isOpen`
|
|
79
80
|
* transitions to `true` and the role requires it.
|
|
@@ -82,6 +83,12 @@ function useInitialFocus(_ref2) {
|
|
|
82
83
|
var elementRef = _ref2.elementRef,
|
|
83
84
|
isOpen = _ref2.isOpen,
|
|
84
85
|
role = _ref2.role;
|
|
86
|
+
// Track the most recently scheduled RAF so a rapid `isOpen → false → true`
|
|
87
|
+
// transition can cancel the previous frame before its closure runs against
|
|
88
|
+
// a stale popover element. Without this, the RAF queued during the first
|
|
89
|
+
// open could fire after the second open had begun and focus the wrong
|
|
90
|
+
// instance.
|
|
91
|
+
var pendingRafRef = (0, _react.useRef)(null);
|
|
85
92
|
(0, _react.useEffect)(function () {
|
|
86
93
|
if (!isOpen) {
|
|
87
94
|
return;
|
|
@@ -91,6 +98,11 @@ function useInitialFocus(_ref2) {
|
|
|
91
98
|
return;
|
|
92
99
|
}
|
|
93
100
|
|
|
101
|
+
// Cancel any RAF queued by the previous open cycle.
|
|
102
|
+
if (pendingRafRef.current !== null) {
|
|
103
|
+
cancelAnimationFrame(pendingRafRef.current);
|
|
104
|
+
}
|
|
105
|
+
|
|
94
106
|
// Use requestAnimationFrame to ensure the popover is fully rendered
|
|
95
107
|
// and visible in the top layer before attempting to move focus.
|
|
96
108
|
// showPopover() is called in useLayoutEffect (which runs before this
|
|
@@ -98,15 +110,24 @@ function useInitialFocus(_ref2) {
|
|
|
98
110
|
// element is guaranteed to be in the top layer.
|
|
99
111
|
var rafId = requestAnimationFrame(function () {
|
|
100
112
|
var _getInitialFocusTarge;
|
|
113
|
+
pendingRafRef.current = null;
|
|
114
|
+
// Verify the element we captured is still the live popover. In
|
|
115
|
+
// rapid-toggle scenarios the ref may already point to a different
|
|
116
|
+
// instance - skip rather than focus the wrong popover.
|
|
117
|
+
if (elementRef.current !== el) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
101
120
|
(_getInitialFocusTarge = getInitialFocusTarget({
|
|
102
|
-
container: el
|
|
121
|
+
container: el,
|
|
122
|
+
role: role
|
|
103
123
|
})) === null || _getInitialFocusTarge === void 0 || _getInitialFocusTarge.focus();
|
|
104
124
|
});
|
|
125
|
+
pendingRafRef.current = rafId;
|
|
105
126
|
return function () {
|
|
106
127
|
cancelAnimationFrame(rafId);
|
|
128
|
+
if (pendingRafRef.current === rafId) {
|
|
129
|
+
pendingRafRef.current = null;
|
|
130
|
+
}
|
|
107
131
|
};
|
|
108
|
-
// We intentionally depend on `role` even though `getInitialFocusTarget`
|
|
109
|
-
// reads from the DOM attribute. This ensures the effect re-runs if
|
|
110
|
-
// the role prop changes while the popover is open.
|
|
111
132
|
}, [elementRef, isOpen, role]);
|
|
112
133
|
}
|
|
@@ -5,16 +5,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
7
|
exports.fromLegacyPlacement = fromLegacyPlacement;
|
|
8
|
-
exports.placementMapping = void 0;
|
|
9
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
10
9
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
10
|
+
var _legacyPlacements = require("./legacy-placements");
|
|
11
11
|
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; }
|
|
12
12
|
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; }
|
|
13
|
-
/**
|
|
14
|
-
* Legacy Popper.js placement values (used by `@atlaskit/popper`, `@atlaskit/popup`,
|
|
15
|
-
* `@atlaskit/tooltip`, etc.).
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
13
|
/**
|
|
19
14
|
* Maps legacy Popper.js placement values to the new object-based
|
|
20
15
|
* `Placement` values used by `@atlaskit/top-layer/popover`.
|
|
@@ -25,9 +20,11 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
25
20
|
* | ------------------- | --------------------------------------------------- |
|
|
26
21
|
* | `top` | `{ axis: 'block', edge: 'start', align: 'center' }` |
|
|
27
22
|
* | `top-start` | `{ axis: 'block', edge: 'start', align: 'start' }` |
|
|
23
|
+
* | `top-center` | `{ axis: 'block', edge: 'start', align: 'center' }` |
|
|
28
24
|
* | `top-end` | `{ axis: 'block', edge: 'start', align: 'end' }` |
|
|
29
25
|
* | `bottom` | `{ axis: 'block', edge: 'end', align: 'center' }` |
|
|
30
26
|
* | `bottom-start` | `{ axis: 'block', edge: 'end', align: 'start' }` |
|
|
27
|
+
* | `bottom-center` | `{ axis: 'block', edge: 'end', align: 'center' }` |
|
|
31
28
|
* | `bottom-end` | `{ axis: 'block', edge: 'end', align: 'end' }` |
|
|
32
29
|
* | `right` | `{ axis: 'inline', edge: 'end', align: 'center' }` |
|
|
33
30
|
* | `right-start` | `{ axis: 'inline', edge: 'end', align: 'start' }` |
|
|
@@ -39,7 +36,10 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
39
36
|
* | `auto-start` | `{ axis: 'block', edge: 'end', align: 'start' }` |
|
|
40
37
|
* | `auto-end` | `{ axis: 'block', edge: 'end', align: 'end' }` |
|
|
41
38
|
*
|
|
42
|
-
*
|
|
39
|
+
* `auto*` is mapped to `block-end` (a reduction in expressiveness vs Popper's
|
|
40
|
+
* runtime auto-flip). CSS `position-try-fallbacks` provides flipping at the
|
|
41
|
+
* edge - but the initial placement is fixed. If migrating away from Popper's
|
|
42
|
+
* dynamic auto, prefer an explicit placement.
|
|
43
43
|
*
|
|
44
44
|
* @example
|
|
45
45
|
* ```ts
|
|
@@ -51,107 +51,10 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
51
51
|
* // newPlacement === { axis: 'block', edge: 'end', align: 'start' }
|
|
52
52
|
* ```
|
|
53
53
|
*/
|
|
54
|
-
var placementMapping = exports.placementMapping = {
|
|
55
|
-
top: {
|
|
56
|
-
axis: 'block',
|
|
57
|
-
edge: 'start',
|
|
58
|
-
align: 'center'
|
|
59
|
-
},
|
|
60
|
-
'top-start': {
|
|
61
|
-
axis: 'block',
|
|
62
|
-
edge: 'start',
|
|
63
|
-
align: 'start'
|
|
64
|
-
},
|
|
65
|
-
'top-center': {
|
|
66
|
-
axis: 'block',
|
|
67
|
-
edge: 'start',
|
|
68
|
-
align: 'center'
|
|
69
|
-
},
|
|
70
|
-
'top-end': {
|
|
71
|
-
axis: 'block',
|
|
72
|
-
edge: 'start',
|
|
73
|
-
align: 'end'
|
|
74
|
-
},
|
|
75
|
-
bottom: {
|
|
76
|
-
axis: 'block',
|
|
77
|
-
edge: 'end',
|
|
78
|
-
align: 'center'
|
|
79
|
-
},
|
|
80
|
-
'bottom-start': {
|
|
81
|
-
axis: 'block',
|
|
82
|
-
edge: 'end',
|
|
83
|
-
align: 'start'
|
|
84
|
-
},
|
|
85
|
-
'bottom-center': {
|
|
86
|
-
axis: 'block',
|
|
87
|
-
edge: 'end',
|
|
88
|
-
align: 'center'
|
|
89
|
-
},
|
|
90
|
-
'bottom-end': {
|
|
91
|
-
axis: 'block',
|
|
92
|
-
edge: 'end',
|
|
93
|
-
align: 'end'
|
|
94
|
-
},
|
|
95
|
-
right: {
|
|
96
|
-
axis: 'inline',
|
|
97
|
-
edge: 'end',
|
|
98
|
-
align: 'center'
|
|
99
|
-
},
|
|
100
|
-
'right-start': {
|
|
101
|
-
axis: 'inline',
|
|
102
|
-
edge: 'end',
|
|
103
|
-
align: 'start'
|
|
104
|
-
},
|
|
105
|
-
'right-end': {
|
|
106
|
-
axis: 'inline',
|
|
107
|
-
edge: 'end',
|
|
108
|
-
align: 'end'
|
|
109
|
-
},
|
|
110
|
-
left: {
|
|
111
|
-
axis: 'inline',
|
|
112
|
-
edge: 'start',
|
|
113
|
-
align: 'center'
|
|
114
|
-
},
|
|
115
|
-
'left-start': {
|
|
116
|
-
axis: 'inline',
|
|
117
|
-
edge: 'start',
|
|
118
|
-
align: 'start'
|
|
119
|
-
},
|
|
120
|
-
'left-end': {
|
|
121
|
-
axis: 'inline',
|
|
122
|
-
edge: 'start',
|
|
123
|
-
align: 'end'
|
|
124
|
-
},
|
|
125
|
-
auto: {
|
|
126
|
-
axis: 'block',
|
|
127
|
-
edge: 'end',
|
|
128
|
-
align: 'center'
|
|
129
|
-
},
|
|
130
|
-
'auto-start': {
|
|
131
|
-
axis: 'block',
|
|
132
|
-
edge: 'end',
|
|
133
|
-
align: 'start'
|
|
134
|
-
},
|
|
135
|
-
'auto-end': {
|
|
136
|
-
axis: 'block',
|
|
137
|
-
edge: 'end',
|
|
138
|
-
align: 'end'
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Convert a legacy Popper.js placement to the new `position-area`-based Placement.
|
|
144
|
-
* Optional `offset` is the legacy Popper `[along, away]` tuple (also known as
|
|
145
|
-
* `[skidding, distance]`); negative `along` becomes `direction: 'backwards'`.
|
|
146
|
-
*
|
|
147
|
-
* The tuple keeps the historical popper names so call sites that already pass
|
|
148
|
-
* `[along, away]` migrate without thinking; the new internal field names
|
|
149
|
-
* (`gap` / `crossAxisShift`) are produced inside this adapter.
|
|
150
|
-
*/
|
|
151
54
|
function fromLegacyPlacement(_ref) {
|
|
152
55
|
var legacy = _ref.legacy,
|
|
153
56
|
offset = _ref.offset;
|
|
154
|
-
var basePlacement = placementMapping[legacy];
|
|
57
|
+
var basePlacement = _legacyPlacements.placementMapping[legacy];
|
|
155
58
|
if (!offset) {
|
|
156
59
|
return basePlacement;
|
|
157
60
|
}
|
|
@@ -168,8 +71,4 @@ function fromLegacyPlacement(_ref) {
|
|
|
168
71
|
}
|
|
169
72
|
}
|
|
170
73
|
});
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* The full mapping record, exposed for consumers that need to iterate or introspect.
|
|
175
|
-
*/
|
|
74
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.placementMapping = exports.LEGACY_PLACEMENTS = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Legacy Popper.js placement values (used by `@atlaskit/popper`,
|
|
9
|
+
* `@atlaskit/popup`, `@atlaskit/tooltip`, etc.). Re-exported from
|
|
10
|
+
* `@atlaskit/top-layer/placement-map` for migration consumers that need
|
|
11
|
+
* to enumerate every placement (e.g. for a settings dropdown). New code
|
|
12
|
+
* should use the object-based `TPlacementOptions` directly.
|
|
13
|
+
*/
|
|
14
|
+
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
15
|
+
var LEGACY_PLACEMENTS = exports.LEGACY_PLACEMENTS = ['auto', 'auto-start', 'auto-end', 'top', 'top-start', 'top-center', 'top-end', 'bottom', 'bottom-start', 'bottom-center', 'bottom-end', 'right', 'right-start', 'right-end', 'left', 'left-start', 'left-end'];
|
|
16
|
+
/**
|
|
17
|
+
* The full mapping record. Internal - use `fromLegacyPlacement` from the
|
|
18
|
+
* public entry-point so the offset-tuple translation is applied consistently.
|
|
19
|
+
*
|
|
20
|
+
* Note: `auto`, `auto-start`, `auto-end` map to `block-end` placements. This
|
|
21
|
+
* is a reduction in expressiveness vs Popper.js (which picked the best
|
|
22
|
+
* placement at runtime). CSS `position-try-fallbacks` flips at the edge but
|
|
23
|
+
* the initial placement is fixed. Migration consumers who relied on Popper's
|
|
24
|
+
* dynamic auto-flip should pick an explicit placement instead.
|
|
25
|
+
*/
|
|
26
|
+
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
27
|
+
var placementMapping = exports.placementMapping = {
|
|
28
|
+
top: {
|
|
29
|
+
axis: 'block',
|
|
30
|
+
edge: 'start',
|
|
31
|
+
align: 'center'
|
|
32
|
+
},
|
|
33
|
+
'top-start': {
|
|
34
|
+
axis: 'block',
|
|
35
|
+
edge: 'start',
|
|
36
|
+
align: 'start'
|
|
37
|
+
},
|
|
38
|
+
'top-center': {
|
|
39
|
+
axis: 'block',
|
|
40
|
+
edge: 'start',
|
|
41
|
+
align: 'center'
|
|
42
|
+
},
|
|
43
|
+
'top-end': {
|
|
44
|
+
axis: 'block',
|
|
45
|
+
edge: 'start',
|
|
46
|
+
align: 'end'
|
|
47
|
+
},
|
|
48
|
+
bottom: {
|
|
49
|
+
axis: 'block',
|
|
50
|
+
edge: 'end',
|
|
51
|
+
align: 'center'
|
|
52
|
+
},
|
|
53
|
+
'bottom-start': {
|
|
54
|
+
axis: 'block',
|
|
55
|
+
edge: 'end',
|
|
56
|
+
align: 'start'
|
|
57
|
+
},
|
|
58
|
+
'bottom-center': {
|
|
59
|
+
axis: 'block',
|
|
60
|
+
edge: 'end',
|
|
61
|
+
align: 'center'
|
|
62
|
+
},
|
|
63
|
+
'bottom-end': {
|
|
64
|
+
axis: 'block',
|
|
65
|
+
edge: 'end',
|
|
66
|
+
align: 'end'
|
|
67
|
+
},
|
|
68
|
+
right: {
|
|
69
|
+
axis: 'inline',
|
|
70
|
+
edge: 'end',
|
|
71
|
+
align: 'center'
|
|
72
|
+
},
|
|
73
|
+
'right-start': {
|
|
74
|
+
axis: 'inline',
|
|
75
|
+
edge: 'end',
|
|
76
|
+
align: 'start'
|
|
77
|
+
},
|
|
78
|
+
'right-end': {
|
|
79
|
+
axis: 'inline',
|
|
80
|
+
edge: 'end',
|
|
81
|
+
align: 'end'
|
|
82
|
+
},
|
|
83
|
+
left: {
|
|
84
|
+
axis: 'inline',
|
|
85
|
+
edge: 'start',
|
|
86
|
+
align: 'center'
|
|
87
|
+
},
|
|
88
|
+
'left-start': {
|
|
89
|
+
axis: 'inline',
|
|
90
|
+
edge: 'start',
|
|
91
|
+
align: 'start'
|
|
92
|
+
},
|
|
93
|
+
'left-end': {
|
|
94
|
+
axis: 'inline',
|
|
95
|
+
edge: 'start',
|
|
96
|
+
align: 'end'
|
|
97
|
+
},
|
|
98
|
+
auto: {
|
|
99
|
+
axis: 'block',
|
|
100
|
+
edge: 'end',
|
|
101
|
+
align: 'center'
|
|
102
|
+
},
|
|
103
|
+
'auto-start': {
|
|
104
|
+
axis: 'block',
|
|
105
|
+
edge: 'end',
|
|
106
|
+
align: 'start'
|
|
107
|
+
},
|
|
108
|
+
'auto-end': {
|
|
109
|
+
axis: 'block',
|
|
110
|
+
edge: 'end',
|
|
111
|
+
align: 'end'
|
|
112
|
+
}
|
|
113
|
+
};
|
|
@@ -15,8 +15,8 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
|
|
|
15
15
|
var _react = _interopRequireWildcard(require("react"));
|
|
16
16
|
var _bindEventListener = require("bind-event-listener");
|
|
17
17
|
var _mergeRefs = _interopRequireDefault(require("@atlaskit/ds-lib/merge-refs"));
|
|
18
|
-
var _noop = _interopRequireDefault(require("@atlaskit/ds-lib/noop"));
|
|
19
18
|
var _once = _interopRequireDefault(require("@atlaskit/ds-lib/once"));
|
|
19
|
+
var _openLayerObserver = require("@atlaskit/layering/experimental/open-layer-observer");
|
|
20
20
|
var _useAnimatedVisibility = require("../internal/use-animated-visibility");
|
|
21
21
|
var _useFocusWrap = require("../internal/use-focus-wrap");
|
|
22
22
|
var _useInitialFocus = require("../internal/use-initial-focus");
|
|
@@ -40,6 +40,18 @@ var supportsPopoverHint = (0, _once.default)(function () {
|
|
|
40
40
|
var styles = {
|
|
41
41
|
root: "_19itglyw _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _19pkidpf _2hwxidpf _otyridpf _18u0idpf _1r041wug _1reoewfl _18m9ewfl _bfhk1j28"
|
|
42
42
|
};
|
|
43
|
+
/**
|
|
44
|
+
* ARIA roles on the Popover primitive that register with the open layer observer
|
|
45
|
+
* as LayerType 'popup'. These are interactive overlays that should be tracked
|
|
46
|
+
* and dismissed when closeLayers() is called (e.g. when the side nav resizes).
|
|
47
|
+
*
|
|
48
|
+
* Note on open layer observer types not included here:
|
|
49
|
+
* - 'modal' only ever comes from the Dialog primitive, not Popover.
|
|
50
|
+
* - Other layer types (e.g. 'tooltip') do not yet exist in LayerType because
|
|
51
|
+
* there is no current use case for distinguishing them in the observer.
|
|
52
|
+
*/
|
|
53
|
+
var POPUP_ROLES = new Set(['menu', 'listbox', 'dialog', 'alertdialog', 'tree', 'grid']);
|
|
54
|
+
|
|
43
55
|
/**
|
|
44
56
|
* Unopinionated top-layer primitive.
|
|
45
57
|
*
|
|
@@ -54,15 +66,14 @@ var styles = {
|
|
|
54
66
|
*
|
|
55
67
|
* For `mode="auto"`, the browser can dismiss the popover via light dismiss
|
|
56
68
|
* (Escape, click outside). When that happens, `onClose` is called and the
|
|
57
|
-
* consumer must set `isOpen` to `false`. The DOM owns the dismiss
|
|
69
|
+
* consumer must set `isOpen` to `false`. The DOM owns the dismiss; React
|
|
58
70
|
* must follow.
|
|
59
71
|
*/
|
|
60
72
|
var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Popover(_ref, ref) {
|
|
61
73
|
var children = _ref.children,
|
|
62
74
|
_ref$mode = _ref.mode,
|
|
63
75
|
modeProp = _ref$mode === void 0 ? 'auto' : _ref$mode,
|
|
64
|
-
|
|
65
|
-
onClose = _ref$onClose === void 0 ? _noop.default : _ref$onClose,
|
|
76
|
+
onClose = _ref.onClose,
|
|
66
77
|
onOpenChange = _ref.onOpenChange,
|
|
67
78
|
onExitFinish = _ref.onExitFinish,
|
|
68
79
|
animate = _ref.animate,
|
|
@@ -77,7 +88,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
77
88
|
var autoId = (0, _react.useId)();
|
|
78
89
|
var ownRef = (0, _react.useRef)(null);
|
|
79
90
|
var combinedRef = (0, _mergeRefs.default)([ownRef, ref].filter(Boolean));
|
|
80
|
-
// Regex is intentional
|
|
91
|
+
// Regex is intentional: `replaceAll` is not available in our supported
|
|
81
92
|
// browser matrix. In React 18, `useId()` returns IDs containing colons
|
|
82
93
|
// (e.g. `:r1:`) which are invalid in CSS selectors and `popover` target
|
|
83
94
|
// attributes. React 19.2.0 replaced colons with underscores, making this
|
|
@@ -95,7 +106,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
95
106
|
// ── Focus management ──
|
|
96
107
|
// Initial focus: on open, moves focus into the popover (role-dependent).
|
|
97
108
|
// Focus wrap: Tab/Shift+Tab cycle within the popover for dialog roles.
|
|
98
|
-
// Focus restoration: handled natively by the Popover API
|
|
109
|
+
// Focus restoration: handled natively by the Popover API. The browser
|
|
99
110
|
// tracks `previouslyFocusedElement` on show and restores it on hide.
|
|
100
111
|
// No custom restoration hook is needed. See: notes/architecture/focus-restoration.md
|
|
101
112
|
(0, _useFocusWrap.useFocusWrap)({
|
|
@@ -108,6 +119,24 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
108
119
|
role: role
|
|
109
120
|
});
|
|
110
121
|
|
|
122
|
+
// ── Open layer observer registration ──
|
|
123
|
+
// Notifies the open layer observer so app-coordination features
|
|
124
|
+
// (closeLayers(), open-count subscriptions) work with top-layer popovers.
|
|
125
|
+
//
|
|
126
|
+
// Only set type: 'popup' for roles that are interactive overlay popups.
|
|
127
|
+
// Passive/informational roles (tooltip, note, status, alert, log) and
|
|
128
|
+
// no-role cases do not map to LayerType 'popup', so type is left undefined.
|
|
129
|
+
var handleObserverClose = (0, _react.useCallback)(function () {
|
|
130
|
+
onClose === null || onClose === void 0 || onClose({
|
|
131
|
+
reason: 'programmatic'
|
|
132
|
+
});
|
|
133
|
+
}, [onClose]);
|
|
134
|
+
(0, _openLayerObserver.useNotifyOpenLayerObserver)({
|
|
135
|
+
type: role && POPUP_ROLES.has(role) ? 'popup' : undefined,
|
|
136
|
+
isOpen: isOpen,
|
|
137
|
+
onClose: handleObserverClose
|
|
138
|
+
});
|
|
139
|
+
|
|
111
140
|
// Hint mode fallback: "hint" downgrades to "auto" if unsupported.
|
|
112
141
|
//
|
|
113
142
|
// Decision (2026-03-17 audit): We keep "auto" as the fallback (not "manual")
|
|
@@ -120,8 +149,8 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
120
149
|
var mode = modeProp === 'hint' && !supportsPopoverHint() ? 'auto' : modeProp;
|
|
121
150
|
|
|
122
151
|
// Distinguishes programmatic hidePopover() from browser-initiated dismiss.
|
|
123
|
-
// When we call hidePopover() ourselves the beforetoggle event fires synchronously
|
|
124
|
-
// this ref prevents the toggle handler from calling onClose redundantly.
|
|
152
|
+
// When we call hidePopover() ourselves the beforetoggle event fires synchronously,
|
|
153
|
+
// so this ref prevents the toggle handler from calling onClose redundantly.
|
|
125
154
|
var programmaticCloseRef = (0, _react.useRef)(false);
|
|
126
155
|
|
|
127
156
|
// Escape key tracking: set in a capture-phase keydown listener (fires before
|
|
@@ -154,7 +183,11 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
154
183
|
// Browser dismiss (Escape or click-outside). Notify consumer.
|
|
155
184
|
var reason = closeReasonRef.current;
|
|
156
185
|
closeReasonRef.current = 'light-dismiss'; // reset for next dismiss
|
|
157
|
-
onClose
|
|
186
|
+
// `onClose` is required for `auto`/`hint` and forbidden for
|
|
187
|
+
// `manual`, but `TPopoverForwardedProps` is a flat type used
|
|
188
|
+
// internally by `PopupContent` - the optional check guards
|
|
189
|
+
// the manual-mode forwarded path where the field is undefined.
|
|
190
|
+
onClose === null || onClose === void 0 || onClose({
|
|
158
191
|
reason: reason
|
|
159
192
|
});
|
|
160
193
|
}
|
|
@@ -189,7 +222,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
189
222
|
|
|
190
223
|
// Placement-dependent animation CSS vars (e.g. slide direction).
|
|
191
224
|
// Separate from show/hide so that preset reference changes
|
|
192
|
-
// (e.g. inline `animate={slideAndFade()}`)
|
|
225
|
+
// (e.g. inline `animate={slideAndFade()}`) do not re-trigger visibility.
|
|
193
226
|
(0, _react.useLayoutEffect)(function () {
|
|
194
227
|
var el = ownRef.current;
|
|
195
228
|
if (!el || !(preset !== null && preset !== void 0 && preset.getProperties) || !placement) {
|
|
@@ -211,7 +244,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
211
244
|
// in the target state (e.g. browser dismissed via light-dismiss before our
|
|
212
245
|
// effect ran).
|
|
213
246
|
// Defensive try/catch: these APIs throw InvalidStateError if the element
|
|
214
|
-
// is disconnected or missing the popover attribute. While we
|
|
247
|
+
// is disconnected or missing the popover attribute. While we do not expect
|
|
215
248
|
// that to happen in normal usage, it can occur in edge cases (e.g. React
|
|
216
249
|
// concurrent mode, StrictMode double-effects, or unmount races).
|
|
217
250
|
(0, _react.useLayoutEffect)(function () {
|
|
@@ -40,7 +40,8 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
|
|
|
40
40
|
placementProp = _ref.placement,
|
|
41
41
|
onCloseProp = _ref.onClose,
|
|
42
42
|
testIdProp = _ref.testId,
|
|
43
|
-
forceFallbackPositioningProp = _ref.forceFallbackPositioning
|
|
43
|
+
forceFallbackPositioningProp = _ref.forceFallbackPositioning,
|
|
44
|
+
idProp = _ref.id;
|
|
44
45
|
// When inside <Popup>, context provides defaults. Props always win.
|
|
45
46
|
var ctx = (0, _popupContext.useMaybePopupContext)();
|
|
46
47
|
var triggerRef = triggerRefProp !== null && triggerRefProp !== void 0 ? triggerRefProp : ctx === null || ctx === void 0 ? void 0 : ctx.triggerRef;
|
|
@@ -83,7 +84,7 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
|
|
|
83
84
|
// does not restore focus when they close.
|
|
84
85
|
//
|
|
85
86
|
// To handle this, we listen for the close transition via `onOpenChange` and
|
|
86
|
-
// restore focus to the trigger if the browser
|
|
87
|
+
// restore focus to the trigger if the browser did not. This runs after the
|
|
87
88
|
// browser's native restoration (which happens synchronously during hidePopover),
|
|
88
89
|
// so it only takes effect when the browser skipped restoration (nested case).
|
|
89
90
|
//
|
|
@@ -100,7 +101,7 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
|
|
|
100
101
|
// focus when they close.
|
|
101
102
|
//
|
|
102
103
|
// We detect this case by checking if focus is still inside the
|
|
103
|
-
// closing popover element. If it is, the browser
|
|
104
|
+
// closing popover element. If it is, the browser did not restore,
|
|
104
105
|
// and we need to move focus to the trigger ourselves.
|
|
105
106
|
//
|
|
106
107
|
// This does NOT fire for:
|
|
@@ -109,13 +110,15 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
|
|
|
109
110
|
if (!args.isOpen) {
|
|
110
111
|
var trigger = triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.current;
|
|
111
112
|
var focusStillInPopover = trigger && args.element.contains(document.activeElement);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
113
|
+
// Single source of truth for "this role moves focus on open
|
|
114
|
+
// and therefore needs to be restored on close" - see
|
|
115
|
+
// `shouldFocusIntoPopover` in `internal/role-types.tsx`.
|
|
116
|
+
if (focusStillInPopover && (0, _roleTypes.shouldFocusIntoPopover)({
|
|
117
|
+
role: role
|
|
118
|
+
})) {
|
|
119
|
+
trigger.focus({
|
|
120
|
+
preventScroll: true
|
|
121
|
+
});
|
|
119
122
|
}
|
|
120
123
|
}
|
|
121
124
|
}, [setIsOpen, consumerOnOpenChange, triggerRef, role]);
|
|
@@ -145,8 +148,8 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
|
|
|
145
148
|
var combinedRef = (0, _mergeRefs.default)([popoverRef, ref]);
|
|
146
149
|
|
|
147
150
|
// TPopupContentProps already validates the discriminated union (role + label,
|
|
148
|
-
// mode + onClose) at its API boundary. Popover accepts
|
|
149
|
-
// internally so individual prop forwarding
|
|
151
|
+
// mode + onClose) at its API boundary. Popover accepts TPopoverForwardedProps
|
|
152
|
+
// internally so individual prop forwarding does not need to re-prove the union.
|
|
150
153
|
var popoverProps = {
|
|
151
154
|
isOpen: isOpen,
|
|
152
155
|
animate: animate,
|
|
@@ -159,7 +162,10 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
|
|
|
159
162
|
onOpenChange: handleOpenChange,
|
|
160
163
|
testId: testId,
|
|
161
164
|
children: children,
|
|
162
|
-
|
|
165
|
+
// Standalone consumers can pass an explicit `id` - used by their own
|
|
166
|
+
// trigger to wire `aria-controls`. Inside the `<Popup>` compound, the
|
|
167
|
+
// id flows from context (`ctx.popoverId`).
|
|
168
|
+
id: idProp !== null && idProp !== void 0 ? idProp : ctx === null || ctx === void 0 ? void 0 : ctx.popoverId,
|
|
163
169
|
xcss: xcss
|
|
164
170
|
};
|
|
165
171
|
return /*#__PURE__*/_react.default.createElement(_popover.Popover, (0, _extends2.default)({
|
|
@@ -23,6 +23,7 @@ var PopupProvider = exports.PopupProvider = PopupContext.Provider;
|
|
|
23
23
|
*
|
|
24
24
|
* Throws if called outside of a `<Popup>` compound component.
|
|
25
25
|
*/
|
|
26
|
+
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
26
27
|
function usePopupContext() {
|
|
27
28
|
var ctx = (0, _react.useContext)(PopupContext);
|
|
28
29
|
if (ctx === null) {
|
|
@@ -37,6 +38,7 @@ function usePopupContext() {
|
|
|
37
38
|
* Used by `PopupContent` to support standalone usage (e.g. tooltip)
|
|
38
39
|
* where values are passed as props instead of coming from a compound component.
|
|
39
40
|
*/
|
|
41
|
+
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
40
42
|
function useMaybePopupContext() {
|
|
41
43
|
return (0, _react.useContext)(PopupContext);
|
|
42
44
|
}
|
|
@@ -21,6 +21,12 @@ var styles = {
|
|
|
21
21
|
* should use `Popup.Content` without wrapping in `PopupSurface`.
|
|
22
22
|
*
|
|
23
23
|
* Exposed as `Popup.Surface` on the compound component.
|
|
24
|
+
*
|
|
25
|
+
* **Presentational primitive - `children`-only by design.** This component
|
|
26
|
+
* intentionally exposes no `style`, `className`, `xcss`, `id`, or `ref`
|
|
27
|
+
* props. If you need any of those, render your own wrapper element inside
|
|
28
|
+
* `Popup.Content` instead - `PopupSurface` is the no-config "give me the
|
|
29
|
+
* default ADS overlay look" surface, nothing more.
|
|
24
30
|
*/
|
|
25
31
|
function PopupSurface(_ref) {
|
|
26
32
|
var children = _ref.children;
|
|
@@ -13,7 +13,7 @@ var _popupContext = require("./popup-context");
|
|
|
13
13
|
/**
|
|
14
14
|
* Render-prop alternative to `Popup.Trigger`.
|
|
15
15
|
*
|
|
16
|
-
* Use when you need full control over the trigger element
|
|
16
|
+
* Use when you need full control over the trigger element. For example,
|
|
17
17
|
* to compose your own trigger with custom event handlers, wrap a third-party
|
|
18
18
|
* component, or build a trigger from multiple elements.
|
|
19
19
|
*
|