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