@atlaskit/top-layer 1.6.0 → 1.7.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 (41) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +13 -0
  3. package/compass.yml +10 -1
  4. package/dist/cjs/dialog/dialog-content.compiled.css +0 -10
  5. package/dist/cjs/dialog/dialog-content.js +20 -28
  6. package/dist/cjs/entry-points/animations.js +1 -49
  7. package/dist/cjs/internal/use-animated-visibility.js +14 -17
  8. package/dist/cjs/internal/use-safari-escape-fix.js +62 -0
  9. package/dist/cjs/popover/animations.js +1 -147
  10. package/dist/cjs/popover/popover.compiled.css +1 -10
  11. package/dist/cjs/popover/popover.js +9 -12
  12. package/dist/cjs/testing/polyfill.js +3 -0
  13. package/dist/es2019/dialog/dialog-content.compiled.css +0 -10
  14. package/dist/es2019/dialog/dialog-content.js +20 -28
  15. package/dist/es2019/entry-points/animations.js +0 -2
  16. package/dist/es2019/internal/use-animated-visibility.js +14 -18
  17. package/dist/es2019/internal/use-safari-escape-fix.js +58 -0
  18. package/dist/es2019/popover/animations.js +1 -145
  19. package/dist/es2019/popover/popover.compiled.css +1 -10
  20. package/dist/es2019/popover/popover.js +8 -12
  21. package/dist/es2019/testing/polyfill.js +3 -0
  22. package/dist/esm/dialog/dialog-content.compiled.css +0 -10
  23. package/dist/esm/dialog/dialog-content.js +20 -28
  24. package/dist/esm/entry-points/animations.js +0 -2
  25. package/dist/esm/internal/use-animated-visibility.js +14 -18
  26. package/dist/esm/internal/use-safari-escape-fix.js +57 -0
  27. package/dist/esm/popover/animations.js +1 -144
  28. package/dist/esm/popover/popover.compiled.css +1 -10
  29. package/dist/esm/popover/popover.js +9 -12
  30. package/dist/esm/testing/polyfill.js +3 -0
  31. package/dist/types/dialog/types.d.ts +5 -5
  32. package/dist/types/entry-points/animations.d.ts +0 -2
  33. package/dist/types/internal/use-animated-visibility.d.ts +15 -33
  34. package/dist/types/internal/use-safari-escape-fix.d.ts +12 -0
  35. package/dist/types/popover/animations.d.ts +7 -52
  36. package/dist/types/popover/types.d.ts +6 -3
  37. package/package.json +6 -5
  38. package/dist/cjs/dialog/animations.js +0 -90
  39. package/dist/es2019/dialog/animations.js +0 -80
  40. package/dist/esm/dialog/animations.js +0 -82
  41. package/dist/types/dialog/animations.d.ts +0 -57
@@ -20,23 +20,15 @@
20
20
  ._1o51q7pw{animation-fill-mode:forwards}
21
21
  ._1oeci9qs{transition-duration:var(--ds-duration-medium,.2s)}
22
22
  ._1oil1d08[open]{transition-timing-function:var(--ds-easing-inout-bold,cubic-bezier(.4,0,0,1))}
23
- ._1pgl1lbj{animation-timing-function:var(--ds-easing-in-practical,cubic-bezier(.6,0,.8,.6))}
24
23
  ._1q51ze3t{padding-block-start:var(--ds-space-0,0)}
25
- ._1rjx1d08[open]{animation-timing-function:var(--ds-easing-inout-bold,cubic-bezier(.4,0,0,1))}
26
24
  ._1rsueoah[open]::-ms-backdrop{animation-fill-mode:backwards}
27
25
  ._1rsueoah[open]::backdrop{animation-fill-mode:backwards}
28
26
  ._1s9z1a5r{transition-behavior:allow-discrete}
29
- ._1szp1mzy[open]{animation-duration:var(--ds-duration-long,.25s)}
30
27
  ._2hwx1wug{margin-right:auto}
31
- ._5sagi9qs{animation-duration:var(--ds-duration-medium,.2s)}
32
28
  ._85i5ze3t{padding-block-end:var(--ds-space-0,0)}
33
- ._8ar61bym[open]{animation-name:var(--ds-keyframe-fade-in,FadeIn0to100)}
34
- ._8ar6yjsl[open]{animation-name:k1c1nn4,var(--ds-keyframe-fade-in,FadeIn0to100)}
35
29
  ._bfhk1j28{background-color:transparent}
36
30
  ._bozgze3t{padding-inline-start:var(--ds-space-0,0)}
37
31
  ._c71lglyw{max-height:none}
38
- ._j7hq1a5s{animation-name:var(--ds-keyframe-fade-out,FadeOut100to0)}
39
- ._j7hqcmlg{animation-name:ku52lnv,var(--ds-keyframe-fade-out,FadeOut100to0)}
40
32
  ._k8m011k7{transition-property:overlay,display}
41
33
  ._njwk11k7::-ms-backdrop{-ms-transition-property:overlay,display;transition-property:overlay,display}
42
34
  ._njwk11k7::backdrop{transition-property:overlay,display}
@@ -45,6 +37,4 @@
45
37
  ._y4tize3t{padding-inline-end:var(--ds-space-0,0)}
46
38
  ._yhpqi9qs::-ms-backdrop{transition-duration:var(--ds-duration-medium,.2s)}
47
39
  ._yhpqi9qs::backdrop{transition-duration:var(--ds-duration-medium,.2s)}
48
- @keyframes k1c1nn4{0%{transform:translateY(calc(var(--ds-dialog-ty, 9pt)))}to{transform:none}}
49
- @keyframes ku52lnv{0%{transform:none}to{transform:translateY(calc(var(--ds-dialog-ty, 9pt)*-1))}}
50
40
  @media (prefers-reduced-motion:reduce){._bl8aglyw{animation-name:none}._156y147i{transition-duration:var(--ds-duration-instant,0ms)}._10aiglyw[open]{animation-name:none}._aeld147i[open]{transition-duration:var(--ds-duration-instant,0ms)}._l57nglyw::-ms-backdrop{animation-name:none}._l57nglyw::backdrop{animation-name:none}._1sbq147i::-ms-backdrop{transition-duration:var(--ds-duration-instant,0ms)}._1sbq147i::backdrop{transition-duration:var(--ds-duration-instant,0ms)}._19awglyw[open]::-ms-backdrop{animation-name:none}._19awglyw[open]::backdrop{animation-name:none}._1i6z147i[open]::-ms-backdrop{transition-duration:var(--ds-duration-instant,0ms)}._1i6z147i[open]::backdrop{transition-duration:var(--ds-duration-instant,0ms)}}
@@ -6,22 +6,16 @@ import { bind } from 'bind-event-listener';
6
6
  import mergeRefs from '@atlaskit/ds-lib/merge-refs';
7
7
  import noop from '@atlaskit/ds-lib/noop';
8
8
  import { useNotifyOpenLayerObserver } from '@atlaskit/layering/experimental/open-layer-observer';
9
- import { setStyle } from '../internal/set-style';
10
9
  import { useAnimatedVisibility } from '../internal/use-animated-visibility';
11
10
  import { useFocusWrap } from '../internal/use-focus-wrap';
12
- var slideInKeyframes = null;
13
- var slideOutKeyframes = null;
14
-
11
+ import { useSafariEscapeFix } from '../internal/use-safari-escape-fix';
15
12
  // These animation styles use the non-strict Compiled cssMap because they rely
16
13
  // on `@starting-style`, `[open]`, and `allow-discrete`. Keep them in this
17
14
  // component so the Compiled transform can statically extract every referenced
18
15
  // style.
19
16
  var dialogAnimationStyles = {
20
17
  root: "_k8m011k7 _1oeci9qs _1s9z1a5r _1fsl1mzy _1oil1d08",
21
- motion: "_y44vgeqi _1o51q7pw _1iu47kvq _1i0neoah",
22
- 'slide-up-and-fade': "_j7hqcmlg _5sagi9qs _1pgl1lbj _8ar6yjsl _1szp1mzy _1rjx1d08",
23
- fade: "_j7hq1a5s _5sagi9qs _1pgl1lbj _8ar61bym _1szp1mzy _1rjx1d08",
24
- custom: ""
18
+ motion: "_y44vgeqi _1o51q7pw _1iu47kvq _1i0neoah"
25
19
  };
26
20
  var styles = {
27
21
  dialog: "_19itglyw _19pk1wug _2hwx1wug _otyr1wug _18u01wug _1q51ze3t _y4tize3t _85i5ze3t _bozgze3t _p12fglyw _c71lglyw _bfhk1j28 _bl8aglyw _156y147i _10aiglyw _aeld147i"
@@ -55,7 +49,8 @@ export var Dialog = /*#__PURE__*/forwardRef(function Dialog(_ref, ref) {
55
49
  onClose = _ref.onClose,
56
50
  onEnterFinish = _ref.onEnterFinish,
57
51
  onExitFinish = _ref.onExitFinish,
58
- animate = _ref.animate,
52
+ _ref$animate = _ref.animate,
53
+ animate = _ref$animate === void 0 ? false : _ref$animate,
59
54
  consumerXcss = _ref.xcss,
60
55
  style = _ref.style,
61
56
  testId = _ref.testId,
@@ -69,6 +64,7 @@ export var Dialog = /*#__PURE__*/forwardRef(function Dialog(_ref, ref) {
69
64
  var combinedRef = mergeRefs([ownRef, ref]);
70
65
  var _useAnimatedVisibilit = useAnimatedVisibility({
71
66
  isOpen: isOpen,
67
+ animationKind: 'dialog',
72
68
  animate: animate,
73
69
  elementRef: ownRef,
74
70
  onEnterFinish: onEnterFinish,
@@ -120,23 +116,13 @@ export var Dialog = /*#__PURE__*/forwardRef(function Dialog(_ref, ref) {
120
116
  }
121
117
  }, [isOpen]);
122
118
 
123
- // Apply preset-provided animation custom properties (e.g. the
124
- // `--ds-dialog-ty` slide distance for `dialogSlideUpAndFade`). The
125
- // cleanup restores the previous inline values so a preset change does
126
- // not leave stale custom properties on the element. Dialog presets do
127
- // not vary by placement, so an empty placement is passed.
128
- useLayoutEffect(function () {
129
- var dialog = ownRef.current;
130
- if (!dialog || !(preset !== null && preset !== void 0 && preset.getStyles)) {
131
- return;
132
- }
133
- return setStyle({
134
- element: dialog,
135
- styles: preset.getStyles({
136
- placement: {}
137
- })
138
- });
139
- }, [preset, isVisible]);
119
+ // Safari bug: escape closes open dialog and popovers, rather than just innermost popover
120
+ // See notes/decisions/safari-escape-nested-popover-in-dialog.md
121
+ var _useSafariEscapeFix = useSafariEscapeFix({
122
+ dialogRef: ownRef,
123
+ isVisible: isVisible
124
+ }),
125
+ shouldIgnoreEscape = _useSafariEscapeFix.shouldIgnoreEscape;
140
126
 
141
127
  // Handle native Escape (cancel event)
142
128
  var handleCancel = useCallback(function (event) {
@@ -149,10 +135,16 @@ export var Dialog = /*#__PURE__*/forwardRef(function Dialog(_ref, ref) {
149
135
  return;
150
136
  }
151
137
  event.preventDefault();
138
+ // Spurious Safari `cancel`: the keydown snapshot saw an open child
139
+ // popover, so this Escape belongs to that popover (light-dismissed
140
+ // natively). Keep the dialog open instead of forwarding to `onClose`.
141
+ if (shouldIgnoreEscape()) {
142
+ return;
143
+ }
152
144
  onClose({
153
145
  reason: 'escape'
154
146
  });
155
- }, [onClose]);
147
+ }, [onClose, shouldIgnoreEscape]);
156
148
 
157
149
  // Handle backdrop click
158
150
  // Attached via bind-event-listener rather than a React prop so we avoid
@@ -198,6 +190,6 @@ export var Dialog = /*#__PURE__*/forwardRef(function Dialog(_ref, ref) {
198
190
  style: style,
199
191
  onCancel: handleCancel,
200
192
  "data-testid": testId,
201
- className: ax([styles.dialog, shouldHideBackdrop ? backdropStyles.hidden : backdropStyles.root, preset && backdropStyles.motion, preset && dialogAnimationStyles.root, preset && dialogAnimationStyles[preset.name], consumerXcss])
193
+ className: ax([styles.dialog, shouldHideBackdrop ? backdropStyles.hidden : backdropStyles.root, preset && backdropStyles.motion, preset && dialogAnimationStyles.root, preset && dialogAnimationStyles.motion, consumerXcss])
202
194
  }, children);
203
195
  });
@@ -1,2 +0,0 @@
1
- export { dialogMotion, dialogSlideUpAndFade, dialogFade } from '../dialog/animations';
2
- export { popupMotion, slideAndFade, fade, scaleAndFade } from '../popover/animations';
@@ -2,18 +2,6 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
2
  import { useEffect, useLayoutEffect, useRef, useState } from 'react';
3
3
  import { bind, bindAll } from 'bind-event-listener';
4
4
  import { prefersReducedMotion } from './reduced-motion';
5
-
6
- /**
7
- * A self-contained animation preset for top-layer elements.
8
- *
9
- * Contains a stable preset name used by the host component to select its
10
- * component-local Compiled style entry, plus optional per-placement inline
11
- * styles.
12
- *
13
- * The actual Compiled styles are kept static and component-local so the
14
- * Compiled transform can extract them at build time.
15
- */
16
-
17
5
  /**
18
6
  * Using the recommended motion timings for safety net.
19
7
  *
@@ -72,6 +60,13 @@ function runOnTransitionEndOrTimeout(_ref) {
72
60
  return teardown;
73
61
  }
74
62
 
63
+ /**
64
+ * Animation config for entry/exit transitions.
65
+ *
66
+ * Currently no configuration is supported via this prop,
67
+ * and this is just a placeholder.
68
+ */
69
+
75
70
  /**
76
71
  * Visibility lifecycle phase shared between `useAnimatedVisibility`,
77
72
  * `useFocusWrap`, `useInitialFocus`, and the `Popover` / `Dialog`
@@ -135,6 +130,7 @@ function runOnTransitionEndOrTimeout(_ref) {
135
130
  */
136
131
  export function useAnimatedVisibility(_ref2) {
137
132
  var isOpen = _ref2.isOpen,
133
+ animationKind = _ref2.animationKind,
138
134
  animate = _ref2.animate,
139
135
  elementRef = _ref2.elementRef,
140
136
  onEnterFinish = _ref2.onEnterFinish,
@@ -188,7 +184,7 @@ export function useAnimatedVisibility(_ref2) {
188
184
  // move to `open`. The fallback guarantees settle on swallowed events
189
185
  // (zero-duration, browser quirk, mid-transition unmount).
190
186
  useEffect(function () {
191
- if (phase !== 'entering' || !(preset !== null && preset !== void 0 && preset.kind)) {
187
+ if (phase !== 'entering') {
192
188
  return;
193
189
  }
194
190
  var element = elementRef.current;
@@ -197,7 +193,7 @@ export function useAnimatedVisibility(_ref2) {
197
193
  }
198
194
  return runOnTransitionEndOrTimeout({
199
195
  element: element,
200
- safetyNetMs: safetyNetMsMap[preset.kind].enter + 50,
196
+ safetyNetMs: safetyNetMsMap[animationKind].enter + 50,
201
197
  onSettled: function onSettled() {
202
198
  var _onEnterFinishRef$cur;
203
199
  // Fire the consumer callback before transitioning phase so any
@@ -210,7 +206,7 @@ export function useAnimatedVisibility(_ref2) {
210
206
  });
211
207
  }
212
208
  });
213
- }, [phase, preset === null || preset === void 0 ? void 0 : preset.kind, elementRef]);
209
+ }, [phase, animationKind, elementRef]);
214
210
 
215
211
  // Non-animated entry callback. The lifecycle goes `closed → open`
216
212
  // directly with no `entering` phase; fire `onEnterFinish` on that jump.
@@ -231,7 +227,7 @@ export function useAnimatedVisibility(_ref2) {
231
227
  // Animated exit: wait for `transitionend` (or a safety-net timeout),
232
228
  // fire `onExitFinish`, then move to `closed` to unmount the host.
233
229
  useEffect(function () {
234
- if (phase !== 'exiting' || !willAnimate || !(preset !== null && preset !== void 0 && preset.kind)) {
230
+ if (phase !== 'exiting' || !willAnimate) {
235
231
  return;
236
232
  }
237
233
  var element = elementRef.current;
@@ -240,7 +236,7 @@ export function useAnimatedVisibility(_ref2) {
240
236
  }
241
237
  return runOnTransitionEndOrTimeout({
242
238
  element: element,
243
- safetyNetMs: safetyNetMsMap[preset.kind].exit + 50,
239
+ safetyNetMs: safetyNetMsMap[animationKind].exit + 50,
244
240
  onSettled: function onSettled() {
245
241
  var _onExitFinishRef$curr;
246
242
  // Fire the consumer callback before transitioning phase to
@@ -255,7 +251,7 @@ export function useAnimatedVisibility(_ref2) {
255
251
  });
256
252
  }
257
253
  });
258
- }, [phase, willAnimate, preset === null || preset === void 0 ? void 0 : preset.kind, elementRef]);
254
+ }, [phase, willAnimate, animationKind, elementRef]);
259
255
 
260
256
  // Non-animated exit: wait for the browser's `toggle` (closed) or
261
257
  // `close` event before unmounting, so the consumer's listener (close
@@ -0,0 +1,57 @@
1
+ import { useEffect, useMemo, useRef } from 'react';
2
+ import { bind } from 'bind-event-listener';
3
+ import { isSafari } from '@atlaskit/ds-lib/is-safari';
4
+
5
+ /**
6
+ * Safari-only guard: WebKit fires dialog `cancel` on Escape even when a child
7
+ * `auto`/`hint` popover consumed it, closing the dialog too.
8
+ * See notes/decisions/safari-escape-nested-popover-in-dialog.md
9
+ */
10
+ export function useSafariEscapeFix(_ref) {
11
+ var dialogRef = _ref.dialogRef,
12
+ isVisible = _ref.isVisible;
13
+ var childPopoverOpenAtEscapeRef = useRef(false);
14
+ useEffect(function () {
15
+ if (!isSafari()) {
16
+ return;
17
+ }
18
+ var dialog = dialogRef.current;
19
+ if (!dialog) {
20
+ return;
21
+ }
22
+
23
+ // Bind to `document`, not the dialog: on Safari focus can be on `<body>`
24
+ // (buttons are not focused on click), where a dialog-scoped listener would
25
+ // never fire. The query below stays scoped to this dialog's subtree.
26
+ return bind(document, {
27
+ type: 'keydown',
28
+ listener: function listener(event) {
29
+ if (event.key !== 'Escape') {
30
+ return;
31
+ }
32
+ try {
33
+ childPopoverOpenAtEscapeRef.current = Boolean(dialog.querySelector('[popover="auto"]:popover-open, [popover="hint"]:popover-open'));
34
+ } catch (_unused) {
35
+ // `:popover-open` is unsupported in some environments (e.g. jsdom);
36
+ // treat as "no child popover" so a plain Escape still closes the dialog.
37
+ childPopoverOpenAtEscapeRef.current = false;
38
+ }
39
+ },
40
+ options: {
41
+ capture: true
42
+ }
43
+ });
44
+ }, [dialogRef, isVisible]);
45
+ var api = useMemo(function () {
46
+ return {
47
+ shouldIgnoreEscape: function shouldIgnoreEscape() {
48
+ if (childPopoverOpenAtEscapeRef.current) {
49
+ childPopoverOpenAtEscapeRef.current = false;
50
+ return true;
51
+ }
52
+ return false;
53
+ }
54
+ };
55
+ }, []);
56
+ return api;
57
+ }
@@ -1,5 +1,5 @@
1
1
  import { getPlacement } from '../internal/resolve-placement';
2
- function getPopupMotionStyles(_ref) {
2
+ export function getPopupMotionStyles(_ref) {
3
3
  var placement = _ref.placement;
4
4
  var _getPlacement = getPlacement({
5
5
  placement: placement
@@ -41,147 +41,4 @@ function getPopupMotionStyles(_ref) {
41
41
  property: '--ds-popover-motion-exit',
42
42
  value: "var(--ds-popup-exit-bottom, 100ms cubic-bezier(0.6, 0, 0.8, 0.6) SlideOutBottom8px, 100ms cubic-bezier(0.6, 0, 0.8, 0.6) FadeOut100to0)"
43
43
  }];
44
- }
45
-
46
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
47
- export function popupMotion() {
48
- return {
49
- kind: 'popover',
50
- name: 'motion',
51
- getStyles: getPopupMotionStyles
52
- };
53
- }
54
- function getSlideAndFadeStyles(_ref2) {
55
- var placement = _ref2.placement,
56
- distance = _ref2.distance;
57
- var pos = "".concat(distance, "px");
58
- var neg = "-".concat(distance, "px");
59
- var _getPlacement2 = getPlacement({
60
- placement: placement
61
- }),
62
- axis = _getPlacement2.axis,
63
- edge = _getPlacement2.edge;
64
- if (axis === 'block' && edge === 'start') {
65
- return [{
66
- property: '--ds-popover-tx',
67
- value: '0'
68
- }, {
69
- property: '--ds-popover-ty',
70
- value: pos
71
- }];
72
- }
73
- if (axis === 'block' && edge === 'end') {
74
- return [{
75
- property: '--ds-popover-tx',
76
- value: '0'
77
- }, {
78
- property: '--ds-popover-ty',
79
- value: neg
80
- }];
81
- }
82
- if (axis === 'inline' && edge === 'start') {
83
- return [{
84
- property: '--ds-popover-tx',
85
- value: pos
86
- }, {
87
- property: '--ds-popover-ty',
88
- value: '0'
89
- }];
90
- }
91
- if (axis === 'inline' && edge === 'end') {
92
- return [{
93
- property: '--ds-popover-tx',
94
- value: neg
95
- }, {
96
- property: '--ds-popover-ty',
97
- value: '0'
98
- }];
99
- }
100
- return [{
101
- property: '--ds-popover-tx',
102
- value: '0'
103
- }, {
104
- property: '--ds-popover-ty',
105
- value: neg
106
- }];
107
- }
108
-
109
- /**
110
- * Directional slide + opacity animation.
111
- *
112
- * The popover slides in from the direction opposite its placement edge
113
- * (e.g. a `block-end` popover slides down from above).
114
- *
115
- * @param options.distance - Slide distance in pixels. Defaults to `4`.
116
- *
117
- * @example
118
- * ```tsx
119
- * import { slideAndFade } from '@atlaskit/top-layer/animations';
120
- *
121
- * // Default 4px slide (tooltip)
122
- * <Popover animate={slideAndFade()} />
123
- *
124
- * // Custom 8px slide (popup / dropdown)
125
- * <Popover animate={slideAndFade({ distance: 8 })} />
126
- * ```
127
- */
128
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
129
- export function slideAndFade(options) {
130
- var _options$distance;
131
- var distance = (_options$distance = options === null || options === void 0 ? void 0 : options.distance) !== null && _options$distance !== void 0 ? _options$distance : 4;
132
- return {
133
- kind: 'popover',
134
- name: 'slide-and-fade',
135
- getStyles: function getStyles(_ref3) {
136
- var placement = _ref3.placement;
137
- return getSlideAndFadeStyles({
138
- placement: placement,
139
- distance: distance
140
- });
141
- }
142
- };
143
- }
144
-
145
- // fade
146
-
147
- /**
148
- * Simple opacity transition, no transform.
149
- *
150
- * Suitable for popup dialogs or content that does not need directional motion.
151
- *
152
- * @example
153
- * ```tsx
154
- * import { fade } from '@atlaskit/top-layer/animations';
155
- *
156
- * <Popover animate={fade()} />
157
- * ```
158
- */
159
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
160
- export function fade() {
161
- return {
162
- kind: 'popover',
163
- name: 'fade'
164
- };
165
- }
166
-
167
- // scaleAndFade
168
-
169
- /**
170
- * Scale from 0.95 + opacity transition.
171
- *
172
- * Suitable for menus, dropdowns, and select options.
173
- *
174
- * @example
175
- * ```tsx
176
- * import { scaleAndFade } from '@atlaskit/top-layer/animations';
177
- *
178
- * <Popover animate={scaleAndFade()} />
179
- * ```
180
- */
181
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
182
- export function scaleAndFade() {
183
- return {
184
- kind: 'popover',
185
- name: 'scale-and-fade'
186
- };
187
44
  }
@@ -7,7 +7,6 @@
7
7
  ._18u0idpf{margin-left:0}
8
8
  ._19bvidpf{padding-left:0}
9
9
  ._19pkidpf{margin-top:0}
10
- ._1a5xt94y{--dir:1px}
11
10
  ._1o51q7pw{animation-fill-mode:forwards}
12
11
  ._1oecdn4k{transition-duration:var(--ds-duration-xshort,.1s)}
13
12
  ._1pgl1lbj{animation-timing-function:var(--ds-easing-in-practical,cubic-bezier(.6,0,.8,.6))}
@@ -15,22 +14,14 @@
15
14
  ._1reoewfl{overflow-x:visible}
16
15
  ._1s9z1a5r{transition-behavior:allow-discrete}
17
16
  ._2hwxidpf{margin-right:0}
17
+ ._4t3i1wug{height:auto}
18
18
  ._5sagdn4k{animation-duration:var(--ds-duration-xshort,.1s)}
19
- ._71re1bym:popover-open{animation-name:var(--ds-keyframe-fade-in,FadeIn0to100)}
20
- ._71re1v6b:popover-open{animation-name:var(--ds-keyframe-fade-in,FadeIn0to100),var(--ds-keyframe-scale-in-small,ScaleIn95to100)}
21
- ._71rervlo:popover-open{animation-name:k1ut9kob,var(--ds-keyframe-fade-in,FadeIn0to100)}
22
19
  ._bfhk1j28{background-color:transparent}
23
20
  ._ca0qidpf{padding-top:0}
24
- ._j7hq1a5s{animation-name:var(--ds-keyframe-fade-out,FadeOut100to0)}
25
- ._j7hq1l2h{animation-name:k1e4c1ew,var(--ds-keyframe-fade-out,FadeOut100to0)}
26
- ._j7hqneez{animation-name:var(--ds-keyframe-fade-out,FadeOut100to0),var(--ds-keyframe-scale-out-small,ScaleOut100to95)}
27
21
  ._k8m011k7{transition-property:overlay,display}
28
22
  ._n3tdidpf{padding-bottom:0}
29
23
  ._n70peoah:popover-open{animation-fill-mode:backwards}
30
24
  ._o8i7indk:popover-open{animation-timing-function:var(--ds-easing-out-practical,cubic-bezier(.4,1,.6,1))}
31
25
  ._otyridpf{margin-bottom:0}
32
26
  ._u5f3idpf{padding-right:0}
33
- [dir=rtl] ._34bx1n1a{--dir:-1px}
34
- @keyframes k1e4c1ew{0%{transform:none}to{transform:translate(calc(var(--dir)*var(--ds-popover-tx, 0)),var(--ds-popover-ty,0))}}
35
- @keyframes k1ut9kob{0%{transform:translate(calc(var(--dir)*var(--ds-popover-tx, 0)),var(--ds-popover-ty,0))}to{transform:none}}
36
27
  @media (prefers-reduced-motion:reduce){._bl8aglyw{animation-name:none}._156yru3m{transition-duration:0s}._8rmvglyw:popover-open{animation-name:none}._2qm2ru3m:popover-open{transition-duration:0s}}
@@ -11,6 +11,7 @@ import { setStyle } from '../internal/set-style';
11
11
  import { useAnimatedVisibility } from '../internal/use-animated-visibility';
12
12
  import { useFocusWrap } from '../internal/use-focus-wrap';
13
13
  import { useInitialFocus } from '../internal/use-initial-focus';
14
+ import { getPopupMotionStyles } from './animations';
14
15
  /**
15
16
  * Detects `popover="hint"` support via DOM reflection. SSR-safe, cached.
16
17
  */
@@ -23,22 +24,16 @@ var supportsPopoverHint = once(function () {
23
24
  element.setAttribute('popover', 'hint');
24
25
  return element.popover === 'hint';
25
26
  });
26
- var slideInKeyframes = null;
27
- var slideOutKeyframes = null;
28
27
 
29
28
  // These animation styles use the non-strict Compiled cssMap because they rely
30
29
  // on `@starting-style`, `:popover-open`, `[dir='rtl']`, and `allow-discrete`.
31
30
  // Keep them in this component so the Compiled transform can statically extract
32
31
  // every referenced style.
33
32
  var popoverAnimationStyles = {
34
- root: "_k8m011k7 _1oecdn4k _1s9z1a5r _1a5xt94y _12t71ign _34bx1n1a _bl8aglyw _156yru3m _8rmvglyw _2qm2ru3m",
35
- motion: "_y44vof1f _1o51q7pw _15ns179n _n70peoah",
36
- 'slide-and-fade': "_j7hq1l2h _5sagdn4k _1pgl1lbj _71rervlo _1psg1ign _o8i7indk",
37
- fade: "_j7hq1a5s _5sagdn4k _1pgl1lbj _71re1bym _1psg1ign _o8i7indk",
38
- 'scale-and-fade': "_j7hqneez _5sagdn4k _1pgl1lbj _71re1v6b _1psg1ign _o8i7indk"
33
+ root: "_y44vof1f _k8m011k7 _1oecdn4k _1s9z1a5r _1o51q7pw _5sagdn4k _1pgl1lbj _15ns179n _12t71ign _n70peoah _1psg1ign _o8i7indk _bl8aglyw _156yru3m _8rmvglyw _2qm2ru3m"
39
34
  };
40
35
  var styles = {
41
- root: "_19itglyw _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _19pkidpf _2hwxidpf _otyridpf _18u0idpf _1r041wug _1reoewfl _18m9ewfl _bfhk1j28"
36
+ root: "_19itglyw _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _19pkidpf _2hwxidpf _otyridpf _18u0idpf _1r041wug _1reoewfl _18m9ewfl _bfhk1j28 _4t3i1wug"
42
37
  };
43
38
  /**
44
39
  * Roles registered with the open layer observer as `popup`, so `closeLayers()`
@@ -86,7 +81,8 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
86
81
  onOpenChange = _ref.onOpenChange,
87
82
  onEnterFinish = _ref.onEnterFinish,
88
83
  onExitFinish = _ref.onExitFinish,
89
- animate = _ref.animate,
84
+ _ref$animate = _ref.animate,
85
+ animate = _ref$animate === void 0 ? false : _ref$animate,
90
86
  placement = _ref.placement,
91
87
  testId = _ref.testId,
92
88
  isOpen = _ref.isOpen,
@@ -102,6 +98,7 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
102
98
  var popoverId = idProp !== null && idProp !== void 0 ? idProp : "popover-".concat(autoId.replace(/:/g, ''));
103
99
  var _useAnimatedVisibilit = useAnimatedVisibility({
104
100
  isOpen: isOpen,
101
+ animationKind: 'popover',
105
102
  animate: animate,
106
103
  elementRef: ownRef,
107
104
  onEnterFinish: onEnterFinish,
@@ -269,12 +266,12 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
269
266
  // stale custom properties on the element.
270
267
  useLayoutEffect(function () {
271
268
  var element = ownRef.current;
272
- if (!element || !(preset !== null && preset !== void 0 && preset.getStyles) || !placement) {
269
+ if (!element || !placement) {
273
270
  return;
274
271
  }
275
272
  return setStyle({
276
273
  element: element,
277
- styles: preset.getStyles({
274
+ styles: getPopupMotionStyles({
278
275
  placement: placement
279
276
  })
280
277
  });
@@ -327,6 +324,6 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
327
324
  "aria-label": label,
328
325
  "aria-labelledby": labelledBy,
329
326
  "data-testid": testId,
330
- className: ax([styles.root, preset && popoverAnimationStyles.root, preset && popoverAnimationStyles[preset.name], consumerXcss])
327
+ className: ax([styles.root, preset && popoverAnimationStyles.root, consumerXcss])
331
328
  }, children);
332
329
  });
@@ -524,6 +524,9 @@ if (typeof HTMLElement !== 'undefined') {
524
524
  // delegate every other selector to the original implementation.
525
525
  // Spec: https://html.spec.whatwg.org/multipage/semantics-other.html#selector-popover-open
526
526
  var originalMatches = Element.prototype.matches;
527
+ // The DOM lib types `Element.prototype.matches` as a set of type-predicate
528
+ // overloads. This polyfill intentionally replaces it with a plain boolean
529
+ // implementation, so we cast to the original member type.
527
530
  Element.prototype.matches = function patchedMatches(selector) {
528
531
  if (selector === ':popover-open') {
529
532
  return this.hasAttribute('data-popover-open');
@@ -1,6 +1,6 @@
1
1
  import { type CSSProperties, type ReactNode } from 'react';
2
2
  import { type CompiledStyles } from '@compiled/react';
3
- import type { TDialogAnimationPreset } from './animations';
3
+ import type { TAnimationConfig } from '../internal/use-animated-visibility';
4
4
  /**
5
5
  * Close reasons produced by the Dialog primitive.
6
6
  *
@@ -48,12 +48,12 @@ type TDialogBaseProps = {
48
48
  reason: TDialogCloseReason;
49
49
  }) => void;
50
50
  /**
51
- * Animation preset for entry/exit transitions.
51
+ * Animation config for entry/exit transitions.
52
52
  *
53
- * Pass a `TAnimationPreset` (e.g. `dialogSlideUpAndFade()`) to enable
54
- * CSS-based entry and exit animation. Pass `false` (or omit) to disable.
53
+ * Pass `true` to use the default dialog animation. Pass a config object to
54
+ * customize supported animation settings. Pass `false` or omit to disable.
55
55
  */
56
- animate?: TDialogAnimationPreset | false;
56
+ animate?: boolean | TAnimationConfig;
57
57
  /**
58
58
  * Additional Compiled styles applied to the `<dialog>` element.
59
59
  *
@@ -1,2 +0,0 @@
1
- export { dialogMotion, dialogSlideUpAndFade, dialogFade, type TDialogAnimationPreset, } from '../dialog/animations';
2
- export { popupMotion, slideAndFade, fade, scaleAndFade, type TPopoverAnimationPreset, } from '../popover/animations';
@@ -1,44 +1,26 @@
1
1
  import { type RefObject } from 'react';
2
- import type { TPlacementOptions } from './resolve-placement';
3
- type TAnimationPresetKind = 'dialog' | 'popover';
2
+ type TAnimationKind = 'dialog' | 'popover';
4
3
  /**
5
- * A self-contained animation preset for top-layer elements.
4
+ * Animation config for entry/exit transitions.
6
5
  *
7
- * Contains a stable preset name used by the host component to select its
8
- * component-local Compiled style entry, plus optional per-placement inline
9
- * styles.
10
- *
11
- * The actual Compiled styles are kept static and component-local so the
12
- * Compiled transform can extract them at build time.
6
+ * Currently no configuration is supported via this prop,
7
+ * and this is just a placeholder.
13
8
  */
14
- export type TAnimationPreset<Kind extends TAnimationPresetKind, Name = string> = {
15
- kind: Kind;
16
- /**
17
- * Stable preset name used to select a component-local Compiled style entry.
18
- */
19
- name: Name;
20
- /**
21
- * Per-placement inline styles (e.g. directional offset custom properties for
22
- * `slideAndFade`). Only used by presets that vary by placement or by a
23
- * configurable distance.
24
- */
25
- getStyles?: (args: {
26
- placement: TPlacementOptions;
27
- }) => Array<{
28
- property: string;
29
- value: string;
30
- }>;
31
- };
32
- type TUseAnimatedVisibilityArgs<Kind extends TAnimationPresetKind, Name> = {
9
+ export type TAnimationConfig = never;
10
+ type TUseAnimatedVisibilityArgs = {
33
11
  /**
34
12
  * Whether the element is logically open.
35
13
  */
36
14
  isOpen: boolean;
37
15
  /**
38
- * Animation preset for entry/exit transitions.
16
+ * Animation kind used to select default safety-net timings.
17
+ */
18
+ animationKind: TAnimationKind;
19
+ /**
20
+ * Animation config for entry/exit transitions.
39
21
  * Pass `false` or `undefined` to disable animation.
40
22
  */
41
- animate: TAnimationPreset<Kind, Name> | false | undefined;
23
+ animate: boolean | TAnimationConfig;
42
24
  /**
43
25
  * Ref to the DOM element that plays the entry/exit transitions.
44
26
  * Used to listen for `transitionend`.
@@ -56,7 +38,7 @@ type TUseAnimatedVisibilityArgs<Kind extends TAnimationPresetKind, Name> = {
56
38
  */
57
39
  onExitFinish?: () => void;
58
40
  };
59
- type TUseAnimatedVisibilityResult<Kind extends TAnimationPresetKind, Name> = {
41
+ type TUseAnimatedVisibilityResult = {
60
42
  /**
61
43
  * Current visibility phase. See `TPhase` for the full lifecycle.
62
44
  *
@@ -71,7 +53,7 @@ type TUseAnimatedVisibilityResult<Kind extends TAnimationPresetKind, Name> = {
71
53
  * Resolved animation preset (styles applied via the host element's `css`
72
54
  * prop), or `null` if animation is disabled.
73
55
  */
74
- preset: TAnimationPreset<Kind, Name> | null;
56
+ preset: boolean | TAnimationConfig | null;
75
57
  };
76
58
  /**
77
59
  * Visibility lifecycle phase shared between `useAnimatedVisibility`,
@@ -134,5 +116,5 @@ export type TPhase = 'closed' | 'entering' | 'open' | 'exiting';
134
116
  * Every effect dispatches on the single `phase` value instead of a
135
117
  * cross-product of booleans.
136
118
  */
137
- export declare function useAnimatedVisibility<Kind extends TAnimationPresetKind, Name>({ isOpen, animate, elementRef, onEnterFinish, onExitFinish, }: TUseAnimatedVisibilityArgs<Kind, Name>): TUseAnimatedVisibilityResult<Kind, Name>;
119
+ export declare function useAnimatedVisibility({ isOpen, animationKind, animate, elementRef, onEnterFinish, onExitFinish, }: TUseAnimatedVisibilityArgs): TUseAnimatedVisibilityResult;
138
120
  export {};