@atlaskit/top-layer 0.16.0 → 0.18.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/AGENTS.md +113 -0
- package/CHANGELOG.md +14 -0
- package/README.md +4 -4
- package/animations/package.json +1 -8
- package/dialog/package.json +1 -8
- package/dialog-scroll-lock/package.json +1 -8
- package/dist/cjs/animations/presets.js +96 -9
- package/dist/cjs/dialog/dialog-content.js +12 -30
- package/dist/cjs/entry-points/animations.js +12 -0
- package/dist/cjs/internal/set-style.js +5 -5
- package/dist/cjs/internal/slot.js +1 -1
- package/dist/cjs/internal/use-anchor-position-at-point.js +8 -8
- package/dist/cjs/internal/use-anchor-position.js +19 -40
- package/dist/cjs/internal/use-animated-visibility.js +31 -61
- package/dist/cjs/internal/use-initial-focus.js +9 -13
- package/dist/cjs/internal/use-width-from-anchor.js +6 -6
- package/dist/cjs/popover/popover.js +30 -58
- package/dist/cjs/popover-surface/popover-surface.js +4 -3
- package/dist/cjs/testing/polyfill.js +9 -9
- package/dist/cjs/use-simple-light-dismiss/index.js +3 -3
- package/dist/es2019/animations/presets.js +145 -2
- package/dist/es2019/dialog/dialog-content.js +12 -30
- package/dist/es2019/entry-points/animations.js +1 -1
- package/dist/es2019/internal/set-style.js +5 -5
- package/dist/es2019/internal/slot.js +1 -1
- package/dist/es2019/internal/use-anchor-position-at-point.js +8 -8
- package/dist/es2019/internal/use-anchor-position.js +19 -40
- package/dist/es2019/internal/use-animated-visibility.js +31 -61
- package/dist/es2019/internal/use-initial-focus.js +9 -13
- package/dist/es2019/internal/use-width-from-anchor.js +6 -6
- package/dist/es2019/popover/popover.js +30 -58
- package/dist/es2019/popover-surface/popover-surface.js +1 -1
- package/dist/es2019/testing/polyfill.js +7 -11
- package/dist/es2019/use-simple-light-dismiss/index.js +3 -3
- package/dist/esm/animations/presets.js +93 -9
- package/dist/esm/dialog/dialog-content.js +12 -30
- package/dist/esm/entry-points/animations.js +1 -1
- package/dist/esm/internal/set-style.js +5 -5
- package/dist/esm/internal/slot.js +1 -1
- package/dist/esm/internal/use-anchor-position-at-point.js +8 -8
- package/dist/esm/internal/use-anchor-position.js +19 -40
- package/dist/esm/internal/use-animated-visibility.js +31 -61
- package/dist/esm/internal/use-initial-focus.js +9 -13
- package/dist/esm/internal/use-width-from-anchor.js +6 -6
- package/dist/esm/popover/popover.js +30 -58
- package/dist/esm/popover-surface/popover-surface.js +1 -1
- package/dist/esm/testing/polyfill.js +9 -9
- package/dist/esm/use-simple-light-dismiss/index.js +3 -3
- package/dist/types/animations/presets.d.ts +16 -0
- package/dist/types/entry-points/animations.d.ts +1 -1
- package/dist/types/internal/set-style.d.ts +2 -2
- package/dist/types/internal/slot.d.ts +2 -2
- package/dist/types/internal/use-anchor-position-at-point.d.ts +2 -2
- package/dist/types/internal/use-anchor-position.d.ts +0 -4
- package/dist/types/internal/use-initial-focus.d.ts +1 -1
- package/dist/types/popover/types.d.ts +5 -7
- package/dist/types/popover-surface/popover-surface.d.ts +2 -2
- package/focus/package.json +1 -8
- package/get-aria-for-trigger/package.json +1 -8
- package/open-layer-observer/package.json +1 -8
- package/package.json +3 -3
- package/placement-map/package.json +1 -8
- package/popover/package.json +1 -8
- package/popover-surface/package.json +1 -8
- package/testing/polyfill/package.json +1 -8
- package/testing/to-be-visible/package.json +1 -8
- package/use-anchor-position/package.json +1 -8
- package/use-anchor-position-at-point/package.json +1 -8
- package/use-arrow-navigation/package.json +1 -8
- package/use-popover-id/package.json +1 -8
- package/use-simple-light-dismiss/package.json +1 -8
- package/use-width-from-anchor/package.json +1 -8
- package/dist/types-ts4.5/animations/presets.d.ts +0 -94
- package/dist/types-ts4.5/animations/types.d.ts +0 -38
- package/dist/types-ts4.5/dialog/create-close-event.d.ts +0 -23
- package/dist/types-ts4.5/dialog/dialog-content.d.ts +0 -24
- package/dist/types-ts4.5/dialog/index.d.ts +0 -3
- package/dist/types-ts4.5/dialog/types.d.ts +0 -126
- package/dist/types-ts4.5/dialog-scroll-lock/index.d.ts +0 -40
- package/dist/types-ts4.5/entry-points/animations.d.ts +0 -2
- package/dist/types-ts4.5/entry-points/dialog-scroll-lock.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/dialog.d.ts +0 -2
- package/dist/types-ts4.5/entry-points/focus.d.ts +0 -4
- package/dist/types-ts4.5/entry-points/get-aria-for-trigger.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/open-layer-observer.d.ts +0 -5
- package/dist/types-ts4.5/entry-points/placement-map.d.ts +0 -3
- package/dist/types-ts4.5/entry-points/popover-surface.d.ts +0 -2
- package/dist/types-ts4.5/entry-points/popover.d.ts +0 -2
- package/dist/types-ts4.5/entry-points/use-anchor-position-at-point.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/use-anchor-position.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/use-arrow-navigation.d.ts +0 -3
- package/dist/types-ts4.5/entry-points/use-popover-id.d.ts +0 -11
- package/dist/types-ts4.5/entry-points/use-simple-light-dismiss.d.ts +0 -2
- package/dist/types-ts4.5/entry-points/use-width-from-anchor.d.ts +0 -1
- package/dist/types-ts4.5/focus/get-first-focusable.d.ts +0 -8
- package/dist/types-ts4.5/focus/get-focusables.d.ts +0 -13
- package/dist/types-ts4.5/focus/get-last-focusable.d.ts +0 -8
- package/dist/types-ts4.5/focus/get-next-focusable.d.ts +0 -13
- package/dist/types-ts4.5/focus/is-in-same-layer.d.ts +0 -8
- package/dist/types-ts4.5/focus/is-nested-layer-focused.d.ts +0 -8
- package/dist/types-ts4.5/focus/selectors.d.ts +0 -4
- package/dist/types-ts4.5/focus/types.d.ts +0 -5
- package/dist/types-ts4.5/index.d.ts +0 -0
- package/dist/types-ts4.5/internal/anchor-positioning-fallback.d.ts +0 -26
- package/dist/types-ts4.5/internal/combine.d.ts +0 -14
- package/dist/types-ts4.5/internal/ensure-preset-styles.d.ts +0 -6
- package/dist/types-ts4.5/internal/get-aria-for-trigger.d.ts +0 -93
- package/dist/types-ts4.5/internal/placement-to-position-area.d.ts +0 -21
- package/dist/types-ts4.5/internal/placement-to-try-fallbacks.d.ts +0 -36
- package/dist/types-ts4.5/internal/reduced-motion.d.ts +0 -14
- package/dist/types-ts4.5/internal/resolve-css-length-to-pixels.d.ts +0 -20
- package/dist/types-ts4.5/internal/resolve-css-length.d.ts +0 -8
- package/dist/types-ts4.5/internal/resolve-placement.d.ts +0 -58
- package/dist/types-ts4.5/internal/role-to-aria-has-popup.d.ts +0 -13
- package/dist/types-ts4.5/internal/role-types.d.ts +0 -71
- package/dist/types-ts4.5/internal/set-style.d.ts +0 -11
- package/dist/types-ts4.5/internal/should-focus-into-popover.d.ts +0 -8
- package/dist/types-ts4.5/internal/slot.d.ts +0 -29
- package/dist/types-ts4.5/internal/use-anchor-position-at-point.d.ts +0 -67
- package/dist/types-ts4.5/internal/use-anchor-position.d.ts +0 -91
- package/dist/types-ts4.5/internal/use-animated-visibility.d.ts +0 -109
- package/dist/types-ts4.5/internal/use-animation-preset.d.ts +0 -11
- package/dist/types-ts4.5/internal/use-focus-wrap.d.ts +0 -25
- package/dist/types-ts4.5/internal/use-initial-focus.d.ts +0 -73
- package/dist/types-ts4.5/internal/use-preset-styles.d.ts +0 -15
- package/dist/types-ts4.5/internal/use-width-from-anchor.d.ts +0 -21
- package/dist/types-ts4.5/placement-map/index.d.ts +0 -51
- package/dist/types-ts4.5/placement-map/legacy-placements.d.ts +0 -27
- package/dist/types-ts4.5/placement-map/placement-mapping.d.ts +0 -13
- package/dist/types-ts4.5/popover/create-close-event.d.ts +0 -25
- package/dist/types-ts4.5/popover/index.d.ts +0 -3
- package/dist/types-ts4.5/popover/popover.d.ts +0 -17
- package/dist/types-ts4.5/popover/types.d.ts +0 -193
- package/dist/types-ts4.5/popover-surface/index.d.ts +0 -2
- package/dist/types-ts4.5/popover-surface/popover-surface.d.ts +0 -21
- package/dist/types-ts4.5/testing/polyfill.d.ts +0 -25
- package/dist/types-ts4.5/testing/to-be-visible.d.ts +0 -23
- package/dist/types-ts4.5/use-arrow-navigation/index.d.ts +0 -3
- package/dist/types-ts4.5/use-arrow-navigation/is-at-current-menu-level.d.ts +0 -48
- package/dist/types-ts4.5/use-arrow-navigation/use-arrow-navigation.d.ts +0 -102
- package/dist/types-ts4.5/use-simple-light-dismiss/index.d.ts +0 -45
|
@@ -152,17 +152,11 @@ function crossAxisShiftMargin(_ref2) {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
/**
|
|
155
|
-
* Returns a referentially-stable, fully-resolved `TPlacement`.
|
|
156
|
-
* keyed on the primitive fields
|
|
157
|
-
*
|
|
158
|
-
* `getPlacement` and the equality check are skipped when the inputs are
|
|
159
|
-
* unchanged.
|
|
155
|
+
* Returns a referentially-stable, fully-resolved `TPlacement`. The memo is
|
|
156
|
+
* keyed on the resolved primitive fields so a fresh inline `placement` object
|
|
157
|
+
* (or undefined fields vs explicit defaults) does not produce a fresh result.
|
|
160
158
|
*/
|
|
161
159
|
function useStablePlacement(placement) {
|
|
162
|
-
// Resolve to the fully-defaulted primitives BEFORE the memo so the deps
|
|
163
|
-
// array sees the same key for `{}`, `undefined` fields, and explicit
|
|
164
|
-
// defaults. Otherwise `axis: undefined` and `axis: 'block'` would be
|
|
165
|
-
// treated as different inputs and re-run the downstream effect.
|
|
166
160
|
var resolved = (0, _resolvePlacement.getPlacement)({
|
|
167
161
|
placement: placement
|
|
168
162
|
});
|
|
@@ -172,10 +166,8 @@ function useStablePlacement(placement) {
|
|
|
172
166
|
var gap = resolved.offset.gap;
|
|
173
167
|
var shiftValue = resolved.offset.crossAxisShift.value;
|
|
174
168
|
var shiftDirection = resolved.offset.crossAxisShift.direction;
|
|
175
|
-
// Rebuild
|
|
176
|
-
//
|
|
177
|
-
// `resolved` reference, and `react-hooks/exhaustive-deps` can verify the
|
|
178
|
-
// deps array.
|
|
169
|
+
// Rebuild inside the memo from primitive deps so the factory does not
|
|
170
|
+
// close over the outer `resolved` reference and exhaustive-deps can verify.
|
|
179
171
|
return (0, _react.useMemo)(function () {
|
|
180
172
|
return {
|
|
181
173
|
axis: axis,
|
|
@@ -207,10 +199,6 @@ function useStablePlacement(placement) {
|
|
|
207
199
|
* When not supported, it falls back to JavaScript-based positioning using
|
|
208
200
|
* `position: fixed` with measured coordinates, re-running on scroll (capture)
|
|
209
201
|
* and resize events.
|
|
210
|
-
*
|
|
211
|
-
* `placement` may be a fresh inline object on every render: a structural
|
|
212
|
-
* comparison is used internally so re-runs are skipped when the resolved
|
|
213
|
-
* placement shape is unchanged.
|
|
214
202
|
*/
|
|
215
203
|
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
216
204
|
function useAnchorPosition(_ref3) {
|
|
@@ -224,8 +212,6 @@ function useAnchorPosition(_ref3) {
|
|
|
224
212
|
isEnabled = _ref3$isEnabled === void 0 ? true : _ref3$isEnabled,
|
|
225
213
|
isOpen = _ref3.isOpen;
|
|
226
214
|
var id = (0, _react.useId)();
|
|
227
|
-
// Stabilize `placement` object so the same object literal
|
|
228
|
-
// value returns an object with the same reference
|
|
229
215
|
var stablePlacement = useStablePlacement(placement);
|
|
230
216
|
(0, _react.useLayoutEffect)(function () {
|
|
231
217
|
if (!isEnabled) {
|
|
@@ -247,9 +233,9 @@ function useAnchorPosition(_ref3) {
|
|
|
247
233
|
placement: stablePlacement,
|
|
248
234
|
offset: gapCssValue
|
|
249
235
|
});
|
|
250
|
-
//
|
|
251
|
-
//
|
|
252
|
-
//
|
|
236
|
+
// Computed once; reused below to populate the active
|
|
237
|
+
// `--ds-cross-axis-shift-margin-*` custom property for the
|
|
238
|
+
// named arrow @position-try rules.
|
|
253
239
|
var crossAxisShift = crossAxisShiftMargin({
|
|
254
240
|
placement: stablePlacement,
|
|
255
241
|
crossAxisShiftCssValue: crossAxisShiftCssValue,
|
|
@@ -277,22 +263,17 @@ function useAnchorPosition(_ref3) {
|
|
|
277
263
|
}, {
|
|
278
264
|
property: 'inset',
|
|
279
265
|
value: 'auto'
|
|
280
|
-
},
|
|
281
|
-
// Main-axis gap between the popover and its trigger
|
|
282
|
-
{
|
|
266
|
+
}, {
|
|
283
267
|
property: gap.property,
|
|
284
268
|
value: gap.value
|
|
285
|
-
},
|
|
286
|
-
// Cross-axis shift
|
|
287
|
-
{
|
|
269
|
+
}, {
|
|
288
270
|
property: crossAxisShift.property,
|
|
289
271
|
value: crossAxisShift.value
|
|
290
272
|
}];
|
|
291
273
|
|
|
292
|
-
//
|
|
293
|
-
//
|
|
294
|
-
//
|
|
295
|
-
// at a time.
|
|
274
|
+
// Expose the active cross-axis shift via custom properties so each
|
|
275
|
+
// named arrow @position-try rule can re-apply it after a flip.
|
|
276
|
+
// One of the four (cross-axis, side) properties is non-zero at a time.
|
|
296
277
|
popoverStyles.push({
|
|
297
278
|
property: '--ds-cross-axis-shift-margin-start',
|
|
298
279
|
value: '0px'
|
|
@@ -309,9 +290,8 @@ function useAnchorPosition(_ref3) {
|
|
|
309
290
|
property: '--ds-cross-axis-shift-margin-block-end',
|
|
310
291
|
value: '0px'
|
|
311
292
|
});
|
|
312
|
-
// `crossAxisShift` IS the active margin
|
|
293
|
+
// `crossAxisShift` IS the active margin; reuse instead of recomputing.
|
|
313
294
|
var crossAxisShiftActive = crossAxisShift;
|
|
314
|
-
// Map margin property to its corresponding custom property name.
|
|
315
295
|
var customPropertyByMarginProperty = {
|
|
316
296
|
'margin-inline-start': '--ds-cross-axis-shift-margin-start',
|
|
317
297
|
'margin-inline-end': '--ds-cross-axis-shift-margin-end',
|
|
@@ -345,18 +325,17 @@ function useAnchorPosition(_ref3) {
|
|
|
345
325
|
*/
|
|
346
326
|
trigger.style.setProperty('anchor-name', anchorName);
|
|
347
327
|
var _undoPositioning = (0, _combine.combine)((0, _setStyle.setStyle)({
|
|
348
|
-
|
|
328
|
+
element: popover,
|
|
349
329
|
styles: popoverStyles
|
|
350
330
|
}));
|
|
351
331
|
return _undoPositioning;
|
|
352
332
|
}
|
|
353
333
|
|
|
354
|
-
// JS fallback
|
|
355
|
-
//
|
|
356
|
-
//
|
|
357
|
-
// (inset: 0; margin: auto) and set top/left based on measurements.
|
|
334
|
+
// JS fallback. The popover is already in the top layer via
|
|
335
|
+
// popover="auto", so we only reset UA defaults and set top/left
|
|
336
|
+
// based on measurements.
|
|
358
337
|
var cleanupBaseStyles = (0, _setStyle.setStyle)({
|
|
359
|
-
|
|
338
|
+
element: popover,
|
|
360
339
|
styles: [{
|
|
361
340
|
property: 'margin',
|
|
362
341
|
value: '0'
|
|
@@ -19,14 +19,16 @@ function runOnTransitionEndOrTimeout(_ref) {
|
|
|
19
19
|
var element = _ref.element,
|
|
20
20
|
safetyNetMs = _ref.safetyNetMs,
|
|
21
21
|
onSettled = _ref.onSettled;
|
|
22
|
-
var
|
|
22
|
+
var state = {
|
|
23
|
+
isSettled: false
|
|
24
|
+
};
|
|
23
25
|
function teardown() {
|
|
24
|
-
isSettled = true;
|
|
26
|
+
state.isSettled = true;
|
|
25
27
|
clearTimeout(safetyNetId);
|
|
26
28
|
unbind();
|
|
27
29
|
}
|
|
28
30
|
function settle() {
|
|
29
|
-
if (isSettled) {
|
|
31
|
+
if (state.isSettled) {
|
|
30
32
|
return;
|
|
31
33
|
}
|
|
32
34
|
teardown();
|
|
@@ -110,22 +112,16 @@ function useAnimatedVisibility(_ref2) {
|
|
|
110
112
|
elementRef = _ref2.elementRef,
|
|
111
113
|
onEnterFinish = _ref2.onEnterFinish,
|
|
112
114
|
onExitFinish = _ref2.onExitFinish;
|
|
113
|
-
// Resolve the animation preset and inject its CSS (idempotent).
|
|
114
|
-
// Returns `null` when `animate` is falsy.
|
|
115
115
|
var preset = (0, _usePresetStyles.usePresetStyles)({
|
|
116
116
|
preset: animate
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
-
//
|
|
120
|
-
// or the user has enabled the "prefers reduced motion" OS setting.
|
|
119
|
+
// False when there is no preset or `prefers-reduced-motion` is set.
|
|
121
120
|
var willAnimate = Boolean(animate) && !(0, _reducedMotion.prefersReducedMotion)();
|
|
122
121
|
|
|
123
|
-
// `
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
// in the same commit as the open intent (React supports a single
|
|
127
|
-
// setState during render as a synchronous re-render before paint).
|
|
128
|
-
// All other transitions are driven by phase-specific effects below.
|
|
122
|
+
// Promote `closed → entering`/`closed → open` synchronously during
|
|
123
|
+
// render so the host element mounts in the same commit as the open
|
|
124
|
+
// intent. All other transitions are driven by phase-specific effects.
|
|
129
125
|
var _useState = (0, _react.useState)(function () {
|
|
130
126
|
if (!isOpen) {
|
|
131
127
|
return 'closed';
|
|
@@ -160,10 +156,8 @@ function useAnimatedVisibility(_ref2) {
|
|
|
160
156
|
var onExitFinishRef = (0, _react.useRef)(onExitFinish);
|
|
161
157
|
onExitFinishRef.current = onExitFinish;
|
|
162
158
|
|
|
163
|
-
// `
|
|
164
|
-
//
|
|
165
|
-
// `onEnterFinish`. A fallback timeout (enterDurationMs + 50ms buffer)
|
|
166
|
-
// guarantees the settle path runs even if `transitionend` is swallowed
|
|
159
|
+
// Animated entry: wait for `transitionend` (or a safety-net timeout) and
|
|
160
|
+
// move to `open`. The fallback guarantees settle on swallowed events
|
|
167
161
|
// (zero-duration, browser quirk, mid-transition unmount).
|
|
168
162
|
(0, _react.useEffect)(function () {
|
|
169
163
|
var _preset$enterDuration;
|
|
@@ -191,12 +185,9 @@ function useAnimatedVisibility(_ref2) {
|
|
|
191
185
|
});
|
|
192
186
|
}, [phase, preset === null || preset === void 0 ? void 0 : preset.enterDurationMs, elementRef]);
|
|
193
187
|
|
|
194
|
-
// Non-animated entry callback
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
// transition into `open` from the non-animated path. We detect this
|
|
198
|
-
// via a previous-phase ref to avoid firing on the animated path's
|
|
199
|
-
// `entering → open` transition (which has its own callback above).
|
|
188
|
+
// Non-animated entry callback. The lifecycle goes `closed → open`
|
|
189
|
+
// directly with no `entering` phase; fire `onEnterFinish` on that jump.
|
|
190
|
+
// A previous-phase ref avoids double-firing on the animated path.
|
|
200
191
|
var prevPhaseForEntryRef = (0, _react.useRef)('closed');
|
|
201
192
|
(0, _react.useEffect)(function () {
|
|
202
193
|
var prevPhase = prevPhaseForEntryRef.current;
|
|
@@ -210,12 +201,8 @@ function useAnimatedVisibility(_ref2) {
|
|
|
210
201
|
}
|
|
211
202
|
}, [phase]);
|
|
212
203
|
|
|
213
|
-
// `
|
|
214
|
-
//
|
|
215
|
-
// (set phase back to `closed`) and fire `onExitFinish`. The fallback
|
|
216
|
-
// timeout (exitDurationMs + 50ms buffer) guarantees we always unmount
|
|
217
|
-
// even if `transitionend` is never emitted (element removed from the
|
|
218
|
-
// top layer, zero-duration transition, interrupted animation).
|
|
204
|
+
// Animated exit: wait for `transitionend` (or a safety-net timeout),
|
|
205
|
+
// fire `onExitFinish`, then move to `closed` to unmount the host.
|
|
219
206
|
(0, _react.useEffect)(function () {
|
|
220
207
|
var _preset$exitDurationM;
|
|
221
208
|
if (phase !== 'exiting' || !willAnimate) {
|
|
@@ -244,33 +231,20 @@ function useAnimatedVisibility(_ref2) {
|
|
|
244
231
|
});
|
|
245
232
|
}, [phase, willAnimate, preset === null || preset === void 0 ? void 0 : preset.exitDurationMs, elementRef]);
|
|
246
233
|
|
|
247
|
-
// `
|
|
248
|
-
//
|
|
249
|
-
//
|
|
250
|
-
//
|
|
251
|
-
//
|
|
252
|
-
//
|
|
253
|
-
// the still-attached element,
|
|
254
|
-
// - the browser's native focus restoration triggered by
|
|
255
|
-
// `hidePopover()` / `<dialog>.close()` has fired,
|
|
256
|
-
// before React unmounts the node. A naive `setTimeout(0)` race
|
|
257
|
-
// occasionally beats the `toggle` task in Chromium, causing focus
|
|
258
|
-
// restoration to drop (the toggle event arrives at a detached element).
|
|
234
|
+
// Non-animated exit: wait for the browser's `toggle` (closed) or
|
|
235
|
+
// `close` event before unmounting, so the consumer's listener (close
|
|
236
|
+
// reason, nested focus restoration, `onClose`) and the browser's
|
|
237
|
+
// native focus restoration both run against the still-attached
|
|
238
|
+
// element. A naive `setTimeout(0)` occasionally beats the `toggle`
|
|
239
|
+
// task in Chromium and drops focus restoration.
|
|
259
240
|
//
|
|
260
|
-
// `useLayoutEffect`
|
|
261
|
-
//
|
|
262
|
-
//
|
|
263
|
-
//
|
|
264
|
-
// frame (including all effect flushes) completes, so the listener is
|
|
265
|
-
// always attached before the event fires. Promotion to layout timing
|
|
266
|
-
// removes any theoretical gap and future-proofs the ordering against
|
|
267
|
-
// effect reordering. Safe under SSR: `phase` starts at `'closed'`, so
|
|
268
|
-
// the body short-circuits and no DOM access happens on the server.
|
|
241
|
+
// `useLayoutEffect` so the listener binds in the same commit as the
|
|
242
|
+
// show/hide layout effect that calls `hidePopover()` / `dialog.close()`.
|
|
243
|
+
// The toggle/close event is queued as a task and cannot run until the
|
|
244
|
+
// frame completes. SSR-safe: `phase` starts at `'closed'`.
|
|
269
245
|
//
|
|
270
|
-
// `onExitFinish` is
|
|
271
|
-
//
|
|
272
|
-
// effect below, so consumers observe a synchronous "exit finished"
|
|
273
|
-
// signal that matches `isOpen` flipping to `false`.
|
|
246
|
+
// `onExitFinish` is fired separately (see effect below) so consumers
|
|
247
|
+
// observe it the moment `isOpen` flips to `false`.
|
|
274
248
|
(0, _react.useLayoutEffect)(function () {
|
|
275
249
|
if (phase !== 'exiting' || willAnimate) {
|
|
276
250
|
return;
|
|
@@ -297,13 +271,9 @@ function useAnimatedVisibility(_ref2) {
|
|
|
297
271
|
}]);
|
|
298
272
|
}, [phase, willAnimate, elementRef]);
|
|
299
273
|
|
|
300
|
-
// Non-animated exit callback
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
// host-element unmount is gated on the browser `toggle`/`close` event
|
|
304
|
-
// by the effect above; `onExitFinish` is observably decoupled from
|
|
305
|
-
// that handshake so consumers see the callback fire at the same time
|
|
306
|
-
// `isOpen` flipped to `false`.
|
|
274
|
+
// Non-animated exit callback. No `transitionend` to wait for, so fire
|
|
275
|
+
// `onExitFinish` on the transition into `exiting` (the unmount itself
|
|
276
|
+
// is gated by the toggle/close handshake above).
|
|
307
277
|
var prevPhaseForExitRef = (0, _react.useRef)('closed');
|
|
308
278
|
(0, _react.useEffect)(function () {
|
|
309
279
|
var prevPhase = prevPhaseForExitRef.current;
|
|
@@ -134,8 +134,6 @@ function getInitialFocusTarget(_ref2) {
|
|
|
134
134
|
});
|
|
135
135
|
}
|
|
136
136
|
if (role === 'menu') {
|
|
137
|
-
// ARIA Combobox Pattern: if the popup is owned by a focused combobox,
|
|
138
|
-
// leave focus on the textbox. Navigation is proxied via the combobox.
|
|
139
137
|
if (isComboboxControllingPopup({
|
|
140
138
|
container: container
|
|
141
139
|
})) {
|
|
@@ -152,9 +150,9 @@ function getInitialFocusTarget(_ref2) {
|
|
|
152
150
|
});
|
|
153
151
|
}
|
|
154
152
|
if (role === 'listbox') {
|
|
155
|
-
// ARIA Combobox Pattern: if
|
|
156
|
-
//
|
|
157
|
-
//
|
|
153
|
+
// ARIA Combobox Pattern: if a combobox-like textbox owns the popup
|
|
154
|
+
// (in-popup or external e.g. react-select), leave focus on the
|
|
155
|
+
// textbox - navigation is proxied through it.
|
|
158
156
|
if (isComboboxControllingPopup({
|
|
159
157
|
container: container
|
|
160
158
|
})) {
|
|
@@ -216,7 +214,7 @@ function getInitialFocusTarget(_ref2) {
|
|
|
216
214
|
* `<dialog>.close()`. If the consumer reopens before the exit transition
|
|
217
215
|
* has settled, the phase machine jumps `exiting → entering` without
|
|
218
216
|
* passing through `closed`, so without this branch the popup would be
|
|
219
|
-
* visible again with focus stranded on the trigger
|
|
217
|
+
* visible again with focus stranded on the trigger - a keyboard usability
|
|
220
218
|
* gap for menu/dialog/listbox roles.
|
|
221
219
|
*
|
|
222
220
|
* Note: there is a rare programmatic path where a consumer flips `isOpen`
|
|
@@ -257,22 +255,20 @@ function useInitialFocus(_ref3) {
|
|
|
257
255
|
var prevPhase = prevPhaseRef.current;
|
|
258
256
|
prevPhaseRef.current = phase;
|
|
259
257
|
|
|
260
|
-
//
|
|
261
|
-
//
|
|
262
|
-
// neither `'closed'` (fresh open) nor `'exiting'` (mid-exit
|
|
263
|
-
// reopen, focus already on the trigger).
|
|
258
|
+
// Only focus on transitions into a visible phase from `'closed'`
|
|
259
|
+
// (fresh open) or `'exiting'` (mid-exit reopen).
|
|
264
260
|
if (phase === 'closed') {
|
|
265
261
|
return;
|
|
266
262
|
}
|
|
267
263
|
if (prevPhase !== 'closed' && prevPhase !== 'exiting') {
|
|
268
264
|
return;
|
|
269
265
|
}
|
|
270
|
-
var
|
|
271
|
-
if (!
|
|
266
|
+
var element = elementRef.current;
|
|
267
|
+
if (!element) {
|
|
272
268
|
return;
|
|
273
269
|
}
|
|
274
270
|
(_getInitialFocusTarge = getInitialFocusTarget({
|
|
275
|
-
container:
|
|
271
|
+
container: element,
|
|
276
272
|
role: role
|
|
277
273
|
})) === null || _getInitialFocusTarge === void 0 || _getInitialFocusTarge.focus();
|
|
278
274
|
}, [elementRef, phase, role]);
|
|
@@ -40,7 +40,7 @@ function useWidthFromAnchor(_ref) {
|
|
|
40
40
|
// explicit width constraint, allowing the popover to grow past the anchor's width.
|
|
41
41
|
if (supportsAnchorSize) {
|
|
42
42
|
return (0, _setStyle.setStyle)({
|
|
43
|
-
|
|
43
|
+
element: node,
|
|
44
44
|
styles: [{
|
|
45
45
|
property: 'width',
|
|
46
46
|
value: 'anchor-size(width)'
|
|
@@ -52,7 +52,7 @@ function useWidthFromAnchor(_ref) {
|
|
|
52
52
|
var anchor = anchorRef.current;
|
|
53
53
|
if (anchor) {
|
|
54
54
|
return (0, _setStyle.setStyle)({
|
|
55
|
-
|
|
55
|
+
element: node,
|
|
56
56
|
styles: [{
|
|
57
57
|
property: 'width',
|
|
58
58
|
value: "".concat(anchor.offsetWidth, "px")
|
|
@@ -74,7 +74,7 @@ function useWidthFromAnchor(_ref) {
|
|
|
74
74
|
// if its content requires it.
|
|
75
75
|
if (supportsAnchorSize) {
|
|
76
76
|
return (0, _setStyle.setStyle)({
|
|
77
|
-
|
|
77
|
+
element: node,
|
|
78
78
|
styles: [minInlineSizeStyle, {
|
|
79
79
|
property: 'min-width',
|
|
80
80
|
value: 'anchor-size(width)'
|
|
@@ -84,7 +84,7 @@ function useWidthFromAnchor(_ref) {
|
|
|
84
84
|
var _anchor = anchorRef.current;
|
|
85
85
|
if (_anchor) {
|
|
86
86
|
return (0, _setStyle.setStyle)({
|
|
87
|
-
|
|
87
|
+
element: node,
|
|
88
88
|
styles: [minInlineSizeStyle, {
|
|
89
89
|
property: 'min-width',
|
|
90
90
|
value: "".concat(_anchor.offsetWidth, "px")
|
|
@@ -94,14 +94,14 @@ function useWidthFromAnchor(_ref) {
|
|
|
94
94
|
|
|
95
95
|
// No anchor available in JS fallback - still apply min-inline-size.
|
|
96
96
|
return (0, _setStyle.setStyle)({
|
|
97
|
-
|
|
97
|
+
element: node,
|
|
98
98
|
styles: [minInlineSizeStyle]
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
// 'none' mode: no explicit width, but still apply `min-inline-size: max-content`.
|
|
103
103
|
return (0, _setStyle.setStyle)({
|
|
104
|
-
|
|
104
|
+
element: node,
|
|
105
105
|
styles: [minInlineSizeStyle]
|
|
106
106
|
});
|
|
107
107
|
}, [mode, popoverRef, anchorRef, isOpen]);
|
|
@@ -30,9 +30,9 @@ var supportsPopoverHint = (0, _once.default)(function () {
|
|
|
30
30
|
return false;
|
|
31
31
|
}
|
|
32
32
|
// eslint-disable-next-line @atlaskit/platform/no-direct-document-usage -- feature detection
|
|
33
|
-
var
|
|
34
|
-
|
|
35
|
-
return
|
|
33
|
+
var element = document.createElement('div');
|
|
34
|
+
element.setAttribute('popover', 'hint');
|
|
35
|
+
return element.popover === 'hint';
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- popover UA reset requires values not in cssMap's type union
|
|
@@ -75,9 +75,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
75
75
|
var autoId = (0, _react.useId)();
|
|
76
76
|
var ownRef = (0, _react.useRef)(null);
|
|
77
77
|
var combinedRef = (0, _mergeRefs.default)([ownRef, ref].filter(Boolean));
|
|
78
|
-
//
|
|
79
|
-
// and popover target attributes). Strip them; remove once React 18 is
|
|
80
|
-
// dropped (React 19.2 uses underscores).
|
|
78
|
+
// `useId()` colons are invalid in CSS selectors and popover target attributes.
|
|
81
79
|
var popoverId = idProp !== null && idProp !== void 0 ? idProp : "popover-".concat(autoId.replace(/:/g, ''));
|
|
82
80
|
var _useAnimatedVisibilit = (0, _useAnimatedVisibility.useAnimatedVisibility)({
|
|
83
81
|
isOpen: isOpen,
|
|
@@ -89,21 +87,15 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
89
87
|
phase = _useAnimatedVisibilit.phase,
|
|
90
88
|
preset = _useAnimatedVisibilit.preset;
|
|
91
89
|
|
|
92
|
-
//
|
|
93
|
-
//
|
|
94
|
-
// signal for listener-re-bind effects so they re-attach to the fresh
|
|
95
|
-
// host element after a close → reopen unmount/remount cycle.
|
|
90
|
+
// True while the host element is mounted (any phase except `closed`).
|
|
91
|
+
// Used as a dep so listener-rebind effects re-attach after a remount.
|
|
96
92
|
var isVisible = phase !== 'closed';
|
|
97
93
|
|
|
98
94
|
// Focus management: initial focus on entry (role-dependent), Tab cycling
|
|
99
95
|
// for dialog roles. Restoration is native for outermost popovers; nested
|
|
100
|
-
// focus-capturing roles are handled below via `beforetoggle` snapshot.
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
// Both hooks take `phase` directly: `useFocusWrap` keeps its listener
|
|
104
|
-
// attached while `phase !== 'closed'` (so focus stays trapped through
|
|
105
|
-
// the animated-exit window — WCAG 2.4.3 regression guard);
|
|
106
|
-
// `useInitialFocus` moves focus on the transition into `'open'`.
|
|
96
|
+
// focus-capturing roles are handled below via the `beforetoggle` snapshot.
|
|
97
|
+
// Passing `phase` keeps `useFocusWrap` attached through the animated-exit
|
|
98
|
+
// window (WCAG 2.4.3 guard). See notes/architecture/focus-restoration.md.
|
|
107
99
|
(0, _useFocusWrap.useFocusWrap)({
|
|
108
100
|
elementRef: ownRef,
|
|
109
101
|
role: role,
|
|
@@ -200,7 +192,6 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
200
192
|
|
|
201
193
|
// Browser dismiss (Escape/click-outside).
|
|
202
194
|
var reason = closeReasonRef.current;
|
|
203
|
-
// reset for next dismiss
|
|
204
195
|
closeReasonRef.current = 'light-dismiss';
|
|
205
196
|
// Optional: `manual` mode has no `onClose` in the forwarded type.
|
|
206
197
|
onClose === null || onClose === void 0 || onClose({
|
|
@@ -209,21 +200,12 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
209
200
|
}
|
|
210
201
|
}, [onClose, onOpenChange, role]);
|
|
211
202
|
|
|
212
|
-
// Bind
|
|
213
|
-
//
|
|
214
|
-
// `
|
|
215
|
-
//
|
|
216
|
-
//
|
|
217
|
-
//
|
|
218
|
-
// breaks nested-popover focus restoration on close.
|
|
219
|
-
//
|
|
220
|
-
// `isVisible` is in deps so the listeners re-bind to the new host
|
|
221
|
-
// element after a host unmount/remount cycle. The cleanup detaches
|
|
222
|
-
// the old listeners.
|
|
223
|
-
//
|
|
224
|
-
// This layout effect MUST appear in the file before the show/hide
|
|
225
|
-
// layout effect — React runs layout effects in source order on the
|
|
226
|
-
// same commit, and we need listeners attached first.
|
|
203
|
+
// Bind via `useLayoutEffect`, and BEFORE the show/hide layout effect
|
|
204
|
+
// below, so listeners are attached when `showPopover()` synchronously
|
|
205
|
+
// dispatches `beforetoggle`. A regular `useEffect` would miss that
|
|
206
|
+
// first dispatch, dropping the `previouslyFocusedElementRef` snapshot
|
|
207
|
+
// and breaking nested-popover focus restoration on close. React runs
|
|
208
|
+
// layout effects in source order on the same commit.
|
|
227
209
|
(0, _react.useLayoutEffect)(function () {
|
|
228
210
|
var element = ownRef.current;
|
|
229
211
|
if (!element) {
|
|
@@ -259,13 +241,10 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
259
241
|
}, [handleToggle, handleBeforeToggle, isVisible]);
|
|
260
242
|
|
|
261
243
|
// Placement-dependent animation CSS vars. Kept separate from show/hide
|
|
262
|
-
// so preset reference changes do not re-trigger visibility.
|
|
263
|
-
// is in deps so the CSS vars are re-applied to the new host element after
|
|
264
|
-
// a remount cycle (otherwise the freshly mounted element would have no
|
|
265
|
-
// transform / placement vars set).
|
|
244
|
+
// so preset reference changes do not re-trigger visibility.
|
|
266
245
|
(0, _react.useLayoutEffect)(function () {
|
|
267
|
-
var
|
|
268
|
-
if (!
|
|
246
|
+
var element = ownRef.current;
|
|
247
|
+
if (!element || !(preset !== null && preset !== void 0 && preset.getProperties) || !placement) {
|
|
269
248
|
return;
|
|
270
249
|
}
|
|
271
250
|
var props = preset.getProperties({
|
|
@@ -275,7 +254,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
275
254
|
var _ref3 = (0, _slicedToArray2.default)(_ref2, 2),
|
|
276
255
|
key = _ref3[0],
|
|
277
256
|
value = _ref3[1];
|
|
278
|
-
|
|
257
|
+
element.style.setProperty(key, String(value));
|
|
279
258
|
});
|
|
280
259
|
}, [preset, placement, isVisible]);
|
|
281
260
|
|
|
@@ -283,42 +262,35 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
283
262
|
// already in the target state. Try/catch guards `InvalidStateError` on
|
|
284
263
|
// disconnected elements (StrictMode/concurrent/unmount edge cases).
|
|
285
264
|
(0, _react.useLayoutEffect)(function () {
|
|
286
|
-
var
|
|
287
|
-
if (!
|
|
265
|
+
var element = ownRef.current;
|
|
266
|
+
if (!element) {
|
|
288
267
|
return;
|
|
289
268
|
}
|
|
290
269
|
if (isOpen) {
|
|
291
270
|
programmaticCloseRef.current = false;
|
|
292
|
-
//
|
|
293
|
-
//
|
|
294
|
-
//
|
|
295
|
-
// cycle would otherwise leak into the next close — especially
|
|
296
|
-
// in the no-animation path where the host unmounts before
|
|
297
|
-
// `handleToggle` has a chance to reset the ref itself.
|
|
271
|
+
// Clear stale 'escape' from a prior cycle: the ref outlives
|
|
272
|
+
// the host element, and the no-animation path unmounts before
|
|
273
|
+
// `handleToggle` can reset it.
|
|
298
274
|
closeReasonRef.current = 'light-dismiss';
|
|
299
275
|
try {
|
|
300
|
-
|
|
276
|
+
element.showPopover();
|
|
301
277
|
} catch (_unused) {}
|
|
302
278
|
return function () {
|
|
303
279
|
programmaticCloseRef.current = true;
|
|
304
280
|
try {
|
|
305
|
-
|
|
281
|
+
element.hidePopover();
|
|
306
282
|
} catch (_unused2) {}
|
|
307
283
|
};
|
|
308
284
|
}
|
|
309
285
|
programmaticCloseRef.current = true;
|
|
310
286
|
try {
|
|
311
|
-
|
|
287
|
+
element.hidePopover();
|
|
312
288
|
} catch (_unused3) {}
|
|
313
289
|
}, [isOpen]);
|
|
314
290
|
|
|
315
|
-
//
|
|
316
|
-
//
|
|
317
|
-
//
|
|
318
|
-
// `popover` element in the accessibility tree. The element re-mounts on
|
|
319
|
-
// the next `isOpen=true` commit; refs and event listeners re-bind via
|
|
320
|
-
// the existing layout effect and `useEffect`. The popover `id` is stable
|
|
321
|
-
// across opens (derived from `useId()` or the consumer-supplied `idProp`).
|
|
291
|
+
// Unmount the host once exit completes so it does not leave an empty
|
|
292
|
+
// `role`/`popover` element in the accessibility tree. The element
|
|
293
|
+
// remounts on the next open; the `popoverId` is stable across opens.
|
|
322
294
|
if (!isVisible) {
|
|
323
295
|
return null;
|
|
324
296
|
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
/* popover-surface.tsx generated by @compiled/babel-plugin v0.39.1 */
|
|
2
2
|
"use strict";
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
8
|
exports.PopoverSurface = PopoverSurface;
|
|
9
9
|
require("./popover-surface.compiled.css");
|
|
10
|
+
var React = _interopRequireWildcard(require("react"));
|
|
10
11
|
var _runtime = require("@compiled/react/runtime");
|
|
11
|
-
var
|
|
12
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
12
13
|
var styles = {
|
|
13
14
|
root: "_2rkofajl _1reo1wug _18m91wug _bfhk1bhr _16qs130s"
|
|
14
15
|
};
|
|
@@ -27,7 +28,7 @@ var styles = {
|
|
|
27
28
|
*/
|
|
28
29
|
function PopoverSurface(_ref) {
|
|
29
30
|
var children = _ref.children;
|
|
30
|
-
return /*#__PURE__*/
|
|
31
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
31
32
|
className: (0, _runtime.ax)([styles.root])
|
|
32
33
|
}, children);
|
|
33
34
|
}
|
|
@@ -354,17 +354,17 @@ function isInChainTo(_ref12) {
|
|
|
354
354
|
function hidePopoversInStackNotInChainTo(_ref13) {
|
|
355
355
|
var stack = _ref13.stack,
|
|
356
356
|
target = _ref13.target;
|
|
357
|
-
var snapshot = stack.slice();
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
if (isInChainTo({
|
|
357
|
+
var snapshot = stack.slice().reverse();
|
|
358
|
+
var stopIndex = snapshot.findIndex(function (popover) {
|
|
359
|
+
return isInChainTo({
|
|
361
360
|
candidate: popover,
|
|
362
361
|
target: target
|
|
363
|
-
})
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
var toHide = stopIndex === -1 ? snapshot : snapshot.slice(0, stopIndex);
|
|
365
|
+
toHide.forEach(function (popover) {
|
|
366
|
+
return popover.hidePopover();
|
|
367
|
+
});
|
|
368
368
|
}
|
|
369
369
|
|
|
370
370
|
// Two-phase light-dismiss: pointerdown stores the nearest open popover for
|
|
@@ -59,13 +59,13 @@ function useSimpleLightDismiss(_ref) {
|
|
|
59
59
|
var unbindClickOutside = (0, _bindEventListener.bind)(document, {
|
|
60
60
|
type: 'click',
|
|
61
61
|
listener: function listener(event) {
|
|
62
|
-
var
|
|
63
|
-
if (!
|
|
62
|
+
var element = popoverRef.current;
|
|
63
|
+
if (!element) {
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
// If the click target is inside the popover, do not dismiss.
|
|
68
|
-
if (event.target instanceof Node &&
|
|
68
|
+
if (event.target instanceof Node && element.contains(event.target)) {
|
|
69
69
|
return;
|
|
70
70
|
}
|
|
71
71
|
onCloseRef.current({
|