@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.
Files changed (141) hide show
  1. package/AGENTS.md +113 -0
  2. package/CHANGELOG.md +14 -0
  3. package/README.md +4 -4
  4. package/animations/package.json +1 -8
  5. package/dialog/package.json +1 -8
  6. package/dialog-scroll-lock/package.json +1 -8
  7. package/dist/cjs/animations/presets.js +96 -9
  8. package/dist/cjs/dialog/dialog-content.js +12 -30
  9. package/dist/cjs/entry-points/animations.js +12 -0
  10. package/dist/cjs/internal/set-style.js +5 -5
  11. package/dist/cjs/internal/slot.js +1 -1
  12. package/dist/cjs/internal/use-anchor-position-at-point.js +8 -8
  13. package/dist/cjs/internal/use-anchor-position.js +19 -40
  14. package/dist/cjs/internal/use-animated-visibility.js +31 -61
  15. package/dist/cjs/internal/use-initial-focus.js +9 -13
  16. package/dist/cjs/internal/use-width-from-anchor.js +6 -6
  17. package/dist/cjs/popover/popover.js +30 -58
  18. package/dist/cjs/popover-surface/popover-surface.js +4 -3
  19. package/dist/cjs/testing/polyfill.js +9 -9
  20. package/dist/cjs/use-simple-light-dismiss/index.js +3 -3
  21. package/dist/es2019/animations/presets.js +145 -2
  22. package/dist/es2019/dialog/dialog-content.js +12 -30
  23. package/dist/es2019/entry-points/animations.js +1 -1
  24. package/dist/es2019/internal/set-style.js +5 -5
  25. package/dist/es2019/internal/slot.js +1 -1
  26. package/dist/es2019/internal/use-anchor-position-at-point.js +8 -8
  27. package/dist/es2019/internal/use-anchor-position.js +19 -40
  28. package/dist/es2019/internal/use-animated-visibility.js +31 -61
  29. package/dist/es2019/internal/use-initial-focus.js +9 -13
  30. package/dist/es2019/internal/use-width-from-anchor.js +6 -6
  31. package/dist/es2019/popover/popover.js +30 -58
  32. package/dist/es2019/popover-surface/popover-surface.js +1 -1
  33. package/dist/es2019/testing/polyfill.js +7 -11
  34. package/dist/es2019/use-simple-light-dismiss/index.js +3 -3
  35. package/dist/esm/animations/presets.js +93 -9
  36. package/dist/esm/dialog/dialog-content.js +12 -30
  37. package/dist/esm/entry-points/animations.js +1 -1
  38. package/dist/esm/internal/set-style.js +5 -5
  39. package/dist/esm/internal/slot.js +1 -1
  40. package/dist/esm/internal/use-anchor-position-at-point.js +8 -8
  41. package/dist/esm/internal/use-anchor-position.js +19 -40
  42. package/dist/esm/internal/use-animated-visibility.js +31 -61
  43. package/dist/esm/internal/use-initial-focus.js +9 -13
  44. package/dist/esm/internal/use-width-from-anchor.js +6 -6
  45. package/dist/esm/popover/popover.js +30 -58
  46. package/dist/esm/popover-surface/popover-surface.js +1 -1
  47. package/dist/esm/testing/polyfill.js +9 -9
  48. package/dist/esm/use-simple-light-dismiss/index.js +3 -3
  49. package/dist/types/animations/presets.d.ts +16 -0
  50. package/dist/types/entry-points/animations.d.ts +1 -1
  51. package/dist/types/internal/set-style.d.ts +2 -2
  52. package/dist/types/internal/slot.d.ts +2 -2
  53. package/dist/types/internal/use-anchor-position-at-point.d.ts +2 -2
  54. package/dist/types/internal/use-anchor-position.d.ts +0 -4
  55. package/dist/types/internal/use-initial-focus.d.ts +1 -1
  56. package/dist/types/popover/types.d.ts +5 -7
  57. package/dist/types/popover-surface/popover-surface.d.ts +2 -2
  58. package/focus/package.json +1 -8
  59. package/get-aria-for-trigger/package.json +1 -8
  60. package/open-layer-observer/package.json +1 -8
  61. package/package.json +3 -3
  62. package/placement-map/package.json +1 -8
  63. package/popover/package.json +1 -8
  64. package/popover-surface/package.json +1 -8
  65. package/testing/polyfill/package.json +1 -8
  66. package/testing/to-be-visible/package.json +1 -8
  67. package/use-anchor-position/package.json +1 -8
  68. package/use-anchor-position-at-point/package.json +1 -8
  69. package/use-arrow-navigation/package.json +1 -8
  70. package/use-popover-id/package.json +1 -8
  71. package/use-simple-light-dismiss/package.json +1 -8
  72. package/use-width-from-anchor/package.json +1 -8
  73. package/dist/types-ts4.5/animations/presets.d.ts +0 -94
  74. package/dist/types-ts4.5/animations/types.d.ts +0 -38
  75. package/dist/types-ts4.5/dialog/create-close-event.d.ts +0 -23
  76. package/dist/types-ts4.5/dialog/dialog-content.d.ts +0 -24
  77. package/dist/types-ts4.5/dialog/index.d.ts +0 -3
  78. package/dist/types-ts4.5/dialog/types.d.ts +0 -126
  79. package/dist/types-ts4.5/dialog-scroll-lock/index.d.ts +0 -40
  80. package/dist/types-ts4.5/entry-points/animations.d.ts +0 -2
  81. package/dist/types-ts4.5/entry-points/dialog-scroll-lock.d.ts +0 -1
  82. package/dist/types-ts4.5/entry-points/dialog.d.ts +0 -2
  83. package/dist/types-ts4.5/entry-points/focus.d.ts +0 -4
  84. package/dist/types-ts4.5/entry-points/get-aria-for-trigger.d.ts +0 -1
  85. package/dist/types-ts4.5/entry-points/open-layer-observer.d.ts +0 -5
  86. package/dist/types-ts4.5/entry-points/placement-map.d.ts +0 -3
  87. package/dist/types-ts4.5/entry-points/popover-surface.d.ts +0 -2
  88. package/dist/types-ts4.5/entry-points/popover.d.ts +0 -2
  89. package/dist/types-ts4.5/entry-points/use-anchor-position-at-point.d.ts +0 -1
  90. package/dist/types-ts4.5/entry-points/use-anchor-position.d.ts +0 -1
  91. package/dist/types-ts4.5/entry-points/use-arrow-navigation.d.ts +0 -3
  92. package/dist/types-ts4.5/entry-points/use-popover-id.d.ts +0 -11
  93. package/dist/types-ts4.5/entry-points/use-simple-light-dismiss.d.ts +0 -2
  94. package/dist/types-ts4.5/entry-points/use-width-from-anchor.d.ts +0 -1
  95. package/dist/types-ts4.5/focus/get-first-focusable.d.ts +0 -8
  96. package/dist/types-ts4.5/focus/get-focusables.d.ts +0 -13
  97. package/dist/types-ts4.5/focus/get-last-focusable.d.ts +0 -8
  98. package/dist/types-ts4.5/focus/get-next-focusable.d.ts +0 -13
  99. package/dist/types-ts4.5/focus/is-in-same-layer.d.ts +0 -8
  100. package/dist/types-ts4.5/focus/is-nested-layer-focused.d.ts +0 -8
  101. package/dist/types-ts4.5/focus/selectors.d.ts +0 -4
  102. package/dist/types-ts4.5/focus/types.d.ts +0 -5
  103. package/dist/types-ts4.5/index.d.ts +0 -0
  104. package/dist/types-ts4.5/internal/anchor-positioning-fallback.d.ts +0 -26
  105. package/dist/types-ts4.5/internal/combine.d.ts +0 -14
  106. package/dist/types-ts4.5/internal/ensure-preset-styles.d.ts +0 -6
  107. package/dist/types-ts4.5/internal/get-aria-for-trigger.d.ts +0 -93
  108. package/dist/types-ts4.5/internal/placement-to-position-area.d.ts +0 -21
  109. package/dist/types-ts4.5/internal/placement-to-try-fallbacks.d.ts +0 -36
  110. package/dist/types-ts4.5/internal/reduced-motion.d.ts +0 -14
  111. package/dist/types-ts4.5/internal/resolve-css-length-to-pixels.d.ts +0 -20
  112. package/dist/types-ts4.5/internal/resolve-css-length.d.ts +0 -8
  113. package/dist/types-ts4.5/internal/resolve-placement.d.ts +0 -58
  114. package/dist/types-ts4.5/internal/role-to-aria-has-popup.d.ts +0 -13
  115. package/dist/types-ts4.5/internal/role-types.d.ts +0 -71
  116. package/dist/types-ts4.5/internal/set-style.d.ts +0 -11
  117. package/dist/types-ts4.5/internal/should-focus-into-popover.d.ts +0 -8
  118. package/dist/types-ts4.5/internal/slot.d.ts +0 -29
  119. package/dist/types-ts4.5/internal/use-anchor-position-at-point.d.ts +0 -67
  120. package/dist/types-ts4.5/internal/use-anchor-position.d.ts +0 -91
  121. package/dist/types-ts4.5/internal/use-animated-visibility.d.ts +0 -109
  122. package/dist/types-ts4.5/internal/use-animation-preset.d.ts +0 -11
  123. package/dist/types-ts4.5/internal/use-focus-wrap.d.ts +0 -25
  124. package/dist/types-ts4.5/internal/use-initial-focus.d.ts +0 -73
  125. package/dist/types-ts4.5/internal/use-preset-styles.d.ts +0 -15
  126. package/dist/types-ts4.5/internal/use-width-from-anchor.d.ts +0 -21
  127. package/dist/types-ts4.5/placement-map/index.d.ts +0 -51
  128. package/dist/types-ts4.5/placement-map/legacy-placements.d.ts +0 -27
  129. package/dist/types-ts4.5/placement-map/placement-mapping.d.ts +0 -13
  130. package/dist/types-ts4.5/popover/create-close-event.d.ts +0 -25
  131. package/dist/types-ts4.5/popover/index.d.ts +0 -3
  132. package/dist/types-ts4.5/popover/popover.d.ts +0 -17
  133. package/dist/types-ts4.5/popover/types.d.ts +0 -193
  134. package/dist/types-ts4.5/popover-surface/index.d.ts +0 -2
  135. package/dist/types-ts4.5/popover-surface/popover-surface.d.ts +0 -21
  136. package/dist/types-ts4.5/testing/polyfill.d.ts +0 -25
  137. package/dist/types-ts4.5/testing/to-be-visible.d.ts +0 -23
  138. package/dist/types-ts4.5/use-arrow-navigation/index.d.ts +0 -3
  139. package/dist/types-ts4.5/use-arrow-navigation/is-at-current-menu-level.d.ts +0 -48
  140. package/dist/types-ts4.5/use-arrow-navigation/use-arrow-navigation.d.ts +0 -102
  141. 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`. `useMemo` is
156
- * keyed on the primitive fields of the input so a fresh inline `placement`
157
- * object on every render does not produce a fresh resolved object. Both
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 the placement object inside the memo from the resolved primitive
176
- // deps so the factory does not close over the (potentially fresh) outer
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
- // Hoist crossAxisShift to a single computation; reused below to
251
- // populate the active `--ds-cross-axis-shift-margin-*` custom
252
- // property for the named arrow @position-try rules.
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
- // Surface the active cross-axis shift value as a custom property so
293
- // each named arrow @position-try rule can re-apply it after a flip.
294
- // The four properties cover (cross-axis, side); only one is non-zero
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 - reuse instead of recomputing.
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
- el: popover,
328
+ element: popover,
349
329
  styles: popoverStyles
350
330
  }));
351
331
  return _undoPositioning;
352
332
  }
353
333
 
354
- // JS fallback
355
- // The popover is already in the browser's top layer via popover="auto",
356
- // so it does not need position:fixed. We only reset the UA defaults
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
- el: popover,
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 isSettled = false;
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
- // Whether we should play CSS transitions. False when there is no preset
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
- // `phase` is the single source of truth for the visibility lifecycle.
124
- // We promote `closed → entering` (animated) or `closed → open`
125
- // (non-animated) synchronously during render so the host element mounts
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
- // `entering` (animation enabled):
164
- // Wait for the entry transition to settle, then move to `open` and fire
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
- // When animation is disabled, the lifecycle goes `closed → open`
196
- // directly with no `entering` phase. Fire `onEnterFinish` on the
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
- // `exiting` (animation enabled):
214
- // Wait for the exit transition to settle, then unmount the host element
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
- // `exiting` (animation disabled):
248
- // Wait for the browser's `toggle` (closed) event (for `<div popover>`)
249
- // or `close` event (for `<dialog>`) to fire before unmounting. This
250
- // guarantees:
251
- // - the consumer's toggle/close listener (close-reason capture,
252
- // nested focus restoration, `onClose` notification) runs against
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` (not `useEffect`) so the listener is bound in the
261
- // same commit as the consumer's show/hide layout effect that calls
262
- // `hidePopover()` / `dialog.close()`. The browser queues the resulting
263
- // `toggle`/`close` event as a task, which cannot run until the JS
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 NOT called here. It is decoupled from the unmount
271
- // handshake and fired by the dedicated non-animated exit-callback
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
- // When animation is disabled there is no `transitionend` to wait for,
302
- // so fire `onExitFinish` on the transition into `exiting`. The actual
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 the popup is owned by a focused
156
- // combobox-like textbox (in-popup or external e.g. react-select),
157
- // leave focus on the textbox. Navigation is proxied via the combobox.
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 — a keyboard usability
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
- // Skip the `phase === 'closed'` transitions (host is going away,
261
- // nothing to focus) and any transition whose previous phase was
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 el = elementRef.current;
271
- if (!el) {
266
+ var element = elementRef.current;
267
+ if (!element) {
272
268
  return;
273
269
  }
274
270
  (_getInitialFocusTarge = getInitialFocusTarget({
275
- container: el,
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
- el: node,
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
- el: node,
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
- el: node,
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
- el: node,
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
- el: node,
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
- el: node,
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 el = document.createElement('div');
34
- el.setAttribute('popover', 'hint');
35
- return el.popover === 'hint';
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
- // React 18 `useId()` returns IDs with colons (invalid in CSS selectors
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
- // Pre-computed phase predicate. `isVisible` mirrors "host element is
93
- // mounted and on screen" (any phase except `closed`); used as a dep
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
- // See: notes/architecture/focus-restoration.md
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 toggle/beforetoggle/keydown listeners via `useLayoutEffect` so
213
- // they are attached BEFORE the show/hide layout effect calls
214
- // `el.showPopover()`. `showPopover()` dispatches `beforetoggle`
215
- // synchronously; binding the listener in a regular `useEffect`
216
- // (which runs after layout effects) misses that first dispatch and
217
- // the `previouslyFocusedElementRef` snapshot never gets taken — which
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. `isVisible`
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 el = ownRef.current;
268
- if (!el || !(preset !== null && preset !== void 0 && preset.getProperties) || !placement) {
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
- el.style.setProperty(key, String(value));
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 el = ownRef.current;
287
- if (!el) {
265
+ var element = ownRef.current;
266
+ if (!element) {
288
267
  return;
289
268
  }
290
269
  if (isOpen) {
291
270
  programmaticCloseRef.current = false;
292
- // Reset the close-reason snapshot at the start of every open
293
- // cycle. The ref outlives the host element (lives on the
294
- // component, not the DOM), so a stale 'escape' from a prior
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
- el.showPopover();
276
+ element.showPopover();
301
277
  } catch (_unused) {}
302
278
  return function () {
303
279
  programmaticCloseRef.current = true;
304
280
  try {
305
- el.hidePopover();
281
+ element.hidePopover();
306
282
  } catch (_unused2) {}
307
283
  };
308
284
  }
309
285
  programmaticCloseRef.current = true;
310
286
  try {
311
- el.hidePopover();
287
+ element.hidePopover();
312
288
  } catch (_unused3) {}
313
289
  }, [isOpen]);
314
290
 
315
- // The host element is only rendered while the popover is open or its exit
316
- // animation is playing. Once the phase returns to `closed`, we unmount
317
- // the host entirely so it does not leave an empty `role="..."` /
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 _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
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 _react = _interopRequireDefault(require("react"));
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__*/_react.default.createElement("div", {
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
- for (var i = snapshot.length - 1; i >= 0; i -= 1) {
359
- var popover = snapshot[i];
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
- break;
365
- }
366
- popover.hidePopover();
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 el = popoverRef.current;
63
- if (!el) {
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 && el.contains(event.target)) {
68
+ if (event.target instanceof Node && element.contains(event.target)) {
69
69
  return;
70
70
  }
71
71
  onCloseRef.current({