@atlaskit/top-layer 1.5.0 → 1.6.1

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 (40) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/compass.yml +10 -1
  3. package/dist/cjs/dialog/dialog-content.compiled.css +7 -25
  4. package/dist/cjs/dialog/dialog-content.js +16 -51
  5. package/dist/cjs/entry-points/animations.js +1 -48
  6. package/dist/cjs/internal/use-animated-visibility.js +35 -6
  7. package/dist/cjs/popover/animations.js +50 -0
  8. package/dist/cjs/popover/popover.compiled.css +7 -14
  9. package/dist/cjs/popover/popover.js +19 -31
  10. package/dist/cjs/testing/polyfill.js +3 -0
  11. package/dist/es2019/dialog/dialog-content.compiled.css +7 -25
  12. package/dist/es2019/dialog/dialog-content.js +15 -48
  13. package/dist/es2019/entry-points/animations.js +0 -1
  14. package/dist/es2019/internal/use-animated-visibility.js +35 -6
  15. package/dist/es2019/popover/animations.js +46 -0
  16. package/dist/es2019/popover/popover.compiled.css +7 -14
  17. package/dist/es2019/popover/popover.js +18 -28
  18. package/dist/es2019/testing/polyfill.js +3 -0
  19. package/dist/esm/dialog/dialog-content.compiled.css +7 -25
  20. package/dist/esm/dialog/dialog-content.js +16 -51
  21. package/dist/esm/entry-points/animations.js +0 -1
  22. package/dist/esm/internal/use-animated-visibility.js +35 -6
  23. package/dist/esm/popover/animations.js +44 -0
  24. package/dist/esm/popover/popover.compiled.css +7 -14
  25. package/dist/esm/popover/popover.js +19 -31
  26. package/dist/esm/testing/polyfill.js +3 -0
  27. package/dist/types/dialog/types.d.ts +5 -5
  28. package/dist/types/entry-points/animations.d.ts +0 -2
  29. package/dist/types/internal/use-animated-visibility.d.ts +16 -5
  30. package/dist/types/popover/animations.d.ts +7 -0
  31. package/dist/types/popover/types.d.ts +7 -4
  32. package/package.json +30 -12
  33. package/dist/cjs/animations/presets.js +0 -298
  34. package/dist/cjs/animations/types.js +0 -5
  35. package/dist/es2019/animations/presets.js +0 -285
  36. package/dist/es2019/animations/types.js +0 -1
  37. package/dist/esm/animations/presets.js +0 -285
  38. package/dist/esm/animations/types.js +0 -1
  39. package/dist/types/animations/presets.d.ts +0 -128
  40. package/dist/types/animations/types.d.ts +0 -34
@@ -1,7 +1,4 @@
1
1
  /* dialog-content.tsx generated by @compiled/babel-plugin v0.39.1 */
2
- import _extends from "@babel/runtime/helpers/extends";
3
- import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
- import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
5
2
  import "./dialog-content.compiled.css";
6
3
  import { ax, ix } from "@compiled/react/runtime";
7
4
  import React, { forwardRef, useCallback, useEffect, useId, useLayoutEffect, useRef } from 'react';
@@ -16,12 +13,16 @@ import { useFocusWrap } from '../internal/use-focus-wrap';
16
13
  // component so the Compiled transform can statically extract every referenced
17
14
  // style.
18
15
  var dialogAnimationStyles = {
19
- motion: "_y44vgeqi _1o51q7pw _k8m011k7 _1oecfnf5 _1s9z1a5r _1iu47kvq _1i0neoah _1m5e1op4 _1jhdq7pw _1ltk1i5c _njwk11k7 _yhpqfnf5 _1fyf1a5r _vhgsxbuz _1rsueoah _bl8aglyw _156yru3m _10aiglyw _aeldru3m _l57nglyw _1sbqru3m _19awglyw _1i6zru3m",
20
- slideUpAndFade: "_tzy4idpf _t9ec9o47 _k8m0rv36 _1oecluct _6fl41a34 _1s9z1a5r _1gbckb7n _1kdeglyw _1fsl1ttt _rornidpf _1hqtc4j2 _1ltk1j28 _njwkivc9 _yhpqluct _13ku1a34 _1fyf1a5r _d7fr1i5c _4v7i1ttt _1dar1j28 _156yru3m _aeldru3m _1sbqru3m _1i6zru3m",
21
- fade: "_tzy4idpf _k8m01slm _1oecluct _6fl41a34 _1s9z1a5r _1gbckb7n _1fsl1ttt _rornidpf _1ltk1j28 _njwkivc9 _yhpqluct _13ku1a34 _1fyf1a5r _d7fr1i5c _4v7i1ttt _1dar1j28 _156yru3m _aeldru3m _1sbqru3m _1i6zru3m"
16
+ root: "_k8m011k7 _1oeci9qs _1s9z1a5r _1fsl1mzy _1oil1d08",
17
+ motion: "_y44vgeqi _1o51q7pw _1iu47kvq _1i0neoah"
22
18
  };
23
19
  var styles = {
24
- dialog: "_19itglyw _19pk1wug _2hwx1wug _otyr1wug _18u01wug _1q51ze3t _y4tize3t _85i5ze3t _bozgze3t _p12fglyw _c71lglyw _bfhk1j28 _1ltk1i5c"
20
+ dialog: "_19itglyw _19pk1wug _2hwx1wug _otyr1wug _18u01wug _1q51ze3t _y4tize3t _85i5ze3t _bozgze3t _p12fglyw _c71lglyw _bfhk1j28 _bl8aglyw _156y147i _10aiglyw _aeld147i"
21
+ };
22
+ var backdropStyles = {
23
+ root: "_1ltk1i5c",
24
+ hidden: "_1ltk1j28",
25
+ motion: "_1m5e1op4 _1jhdq7pw _njwk11k7 _yhpqi9qs _1fyf1a5r _vhgsxbuz _1rsueoah _l57nglyw _1sbq147i _19awglyw _1i6z147i"
25
26
  };
26
27
 
27
28
  /**
@@ -47,8 +48,9 @@ export var Dialog = /*#__PURE__*/forwardRef(function Dialog(_ref, ref) {
47
48
  onClose = _ref.onClose,
48
49
  onEnterFinish = _ref.onEnterFinish,
49
50
  onExitFinish = _ref.onExitFinish,
50
- animate = _ref.animate,
51
- xcssFromProps = _ref.xcss,
51
+ _ref$animate = _ref.animate,
52
+ animate = _ref$animate === void 0 ? false : _ref$animate,
53
+ consumerXcss = _ref.xcss,
52
54
  style = _ref.style,
53
55
  testId = _ref.testId,
54
56
  providedId = _ref.id,
@@ -61,6 +63,7 @@ export var Dialog = /*#__PURE__*/forwardRef(function Dialog(_ref, ref) {
61
63
  var combinedRef = mergeRefs([ownRef, ref]);
62
64
  var _useAnimatedVisibilit = useAnimatedVisibility({
63
65
  isOpen: isOpen,
66
+ animationKind: 'dialog',
64
67
  animate: animate,
65
68
  elementRef: ownRef,
66
69
  onEnterFinish: onEnterFinish,
@@ -112,32 +115,6 @@ export var Dialog = /*#__PURE__*/forwardRef(function Dialog(_ref, ref) {
112
115
  }
113
116
  }, [isOpen]);
114
117
 
115
- // Apply preset-provided animation custom properties (e.g. the
116
- // `--ds-dialog-ty` slide distance for `dialogSlideUpAndFade`). The
117
- // cleanup removes them so a preset change does not leave stale
118
- // custom properties on the element. Dialog presets do not vary by
119
- // placement, so an empty placement is passed.
120
- useLayoutEffect(function () {
121
- var dialog = ownRef.current;
122
- if (!dialog || !(preset !== null && preset !== void 0 && preset.getProperties)) {
123
- return;
124
- }
125
- var props = preset.getProperties({
126
- placement: {}
127
- });
128
- Object.entries(props).forEach(function (_ref2) {
129
- var _ref3 = _slicedToArray(_ref2, 2),
130
- key = _ref3[0],
131
- value = _ref3[1];
132
- dialog.style.setProperty(key, String(value));
133
- });
134
- return function () {
135
- Object.keys(props).forEach(function (key) {
136
- dialog.style.removeProperty(key);
137
- });
138
- };
139
- }, [preset, isVisible]);
140
-
141
118
  // Handle native Escape (cancel event)
142
119
  var handleCancel = useCallback(function (event) {
143
120
  // Only handle a cancel targeting THIS dialog. Native `cancel` does not
@@ -177,12 +154,6 @@ export var Dialog = /*#__PURE__*/forwardRef(function Dialog(_ref, ref) {
177
154
  });
178
155
  }, [onClose, isVisible]);
179
156
 
180
- // Atomic CSS (Compiled) deduplicates ::backdrop { background-color }
181
- // into a single class, making it impossible to toggle between two values
182
- // via cssMap entries. An ID-scoped <style> has higher specificity than
183
- // any atomic class, so the override always wins.
184
- var escapedId = CSS.escape(dialogId);
185
-
186
157
  // Unmount the `<dialog>` once exit completes so it does not leave an
187
158
  // empty `role="dialog"` element in the accessibility tree. On the next
188
159
  // open the element remounts and the `[isOpen]` and `[onClose, isVisible]`
@@ -190,7 +161,7 @@ export var Dialog = /*#__PURE__*/forwardRef(function Dialog(_ref, ref) {
190
161
  if (!isVisible) {
191
162
  return null;
192
163
  }
193
- return /*#__PURE__*/React.createElement("dialog", _extends({
164
+ return /*#__PURE__*/React.createElement("dialog", {
194
165
  ref: combinedRef,
195
166
  id: dialogId
196
167
  // `aria-modal` is intentionally NOT set: native `<dialog>.showModal()`
@@ -201,15 +172,9 @@ export var Dialog = /*#__PURE__*/forwardRef(function Dialog(_ref, ref) {
201
172
  ,
202
173
  "aria-label": label,
203
174
  "aria-labelledby": label ? undefined : labelledBy,
204
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
205
175
  style: style,
206
176
  onCancel: handleCancel,
207
- "data-testid": testId
208
- }, preset ? _defineProperty({}, "data-ds-dialog-".concat(preset.name), '') : undefined, {
209
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- xcss prop passes Compiled atomic class names from consumer-owned cssMap entries
210
- className: ax([styles.dialog, (preset === null || preset === void 0 ? void 0 : preset.name) === 'motion' && dialogAnimationStyles.motion, (preset === null || preset === void 0 ? void 0 : preset.name) === 'slide-up-and-fade' && dialogAnimationStyles.slideUpAndFade, (preset === null || preset === void 0 ? void 0 : preset.name) === 'fade' && dialogAnimationStyles.fade, xcssFromProps])
211
- }), shouldHideBackdrop &&
212
- /*#__PURE__*/
213
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-global-styles
214
- React.createElement("style", null, "#".concat(escapedId, "::backdrop{background-color:transparent}")), children);
177
+ "data-testid": testId,
178
+ className: ax([styles.dialog, shouldHideBackdrop ? backdropStyles.hidden : backdropStyles.root, preset && backdropStyles.motion, preset && dialogAnimationStyles.root, preset && dialogAnimationStyles.motion, consumerXcss])
179
+ }, children);
215
180
  });
@@ -1 +0,0 @@
1
- export { dialogMotion, popupMotion, slideAndFade, fade, scaleAndFade, dialogSlideUpAndFade, dialogFade } from '../animations/presets';
@@ -2,6 +2,29 @@ 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
+ * Using the recommended motion timings for safety net.
7
+ *
8
+ * Not setting these timings on the preset config because they're defined in the CSS,
9
+ * so configuring it in the preset doesn't achieve anything except introduce a potential
10
+ * source of drift.
11
+ *
12
+ * TODO: figure out a way to not need to redeclare these in the future,
13
+ * and keep CSS and JS timings in sync always.
14
+ */
15
+ var safetyNetMsMap = {
16
+ dialog: {
17
+ enter: 250,
18
+ // Corresponds to `motion.duration.long`
19
+ exit: 200 // Corresponds to `motion.duration.medium`
20
+ },
21
+ popover: {
22
+ enter: 150,
23
+ // Corresponds to `motion.duration.short`
24
+ exit: 100 // Corresponds to `motion.duration.xshort`
25
+ }
26
+ };
27
+
5
28
  /**
6
29
  * Fires `onSettled` once when `transitionend` fires on `element`, or after
7
30
  * `safetyNetMs` if the event is swallowed (mid-transition unmount, CSS
@@ -37,6 +60,13 @@ function runOnTransitionEndOrTimeout(_ref) {
37
60
  return teardown;
38
61
  }
39
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
+
40
70
  /**
41
71
  * Visibility lifecycle phase shared between `useAnimatedVisibility`,
42
72
  * `useFocusWrap`, `useInitialFocus`, and the `Popover` / `Dialog`
@@ -100,6 +130,7 @@ function runOnTransitionEndOrTimeout(_ref) {
100
130
  */
101
131
  export function useAnimatedVisibility(_ref2) {
102
132
  var isOpen = _ref2.isOpen,
133
+ animationKind = _ref2.animationKind,
103
134
  animate = _ref2.animate,
104
135
  elementRef = _ref2.elementRef,
105
136
  onEnterFinish = _ref2.onEnterFinish,
@@ -153,7 +184,6 @@ export function useAnimatedVisibility(_ref2) {
153
184
  // move to `open`. The fallback guarantees settle on swallowed events
154
185
  // (zero-duration, browser quirk, mid-transition unmount).
155
186
  useEffect(function () {
156
- var _preset$enterDuration;
157
187
  if (phase !== 'entering') {
158
188
  return;
159
189
  }
@@ -163,7 +193,7 @@ export function useAnimatedVisibility(_ref2) {
163
193
  }
164
194
  return runOnTransitionEndOrTimeout({
165
195
  element: element,
166
- safetyNetMs: ((_preset$enterDuration = preset === null || preset === void 0 ? void 0 : preset.enterDurationMs) !== null && _preset$enterDuration !== void 0 ? _preset$enterDuration : 0) + 50,
196
+ safetyNetMs: safetyNetMsMap[animationKind].enter + 50,
167
197
  onSettled: function onSettled() {
168
198
  var _onEnterFinishRef$cur;
169
199
  // Fire the consumer callback before transitioning phase so any
@@ -176,7 +206,7 @@ export function useAnimatedVisibility(_ref2) {
176
206
  });
177
207
  }
178
208
  });
179
- }, [phase, preset === null || preset === void 0 ? void 0 : preset.enterDurationMs, elementRef]);
209
+ }, [phase, animationKind, elementRef]);
180
210
 
181
211
  // Non-animated entry callback. The lifecycle goes `closed → open`
182
212
  // directly with no `entering` phase; fire `onEnterFinish` on that jump.
@@ -197,7 +227,6 @@ export function useAnimatedVisibility(_ref2) {
197
227
  // Animated exit: wait for `transitionend` (or a safety-net timeout),
198
228
  // fire `onExitFinish`, then move to `closed` to unmount the host.
199
229
  useEffect(function () {
200
- var _preset$exitDurationM;
201
230
  if (phase !== 'exiting' || !willAnimate) {
202
231
  return;
203
232
  }
@@ -207,7 +236,7 @@ export function useAnimatedVisibility(_ref2) {
207
236
  }
208
237
  return runOnTransitionEndOrTimeout({
209
238
  element: element,
210
- safetyNetMs: ((_preset$exitDurationM = preset === null || preset === void 0 ? void 0 : preset.exitDurationMs) !== null && _preset$exitDurationM !== void 0 ? _preset$exitDurationM : 0) + 50,
239
+ safetyNetMs: safetyNetMsMap[animationKind].exit + 50,
211
240
  onSettled: function onSettled() {
212
241
  var _onExitFinishRef$curr;
213
242
  // Fire the consumer callback before transitioning phase to
@@ -222,7 +251,7 @@ export function useAnimatedVisibility(_ref2) {
222
251
  });
223
252
  }
224
253
  });
225
- }, [phase, willAnimate, preset === null || preset === void 0 ? void 0 : preset.exitDurationMs, elementRef]);
254
+ }, [phase, willAnimate, animationKind, elementRef]);
226
255
 
227
256
  // Non-animated exit: wait for the browser's `toggle` (closed) or
228
257
  // `close` event before unmounting, so the consumer's listener (close
@@ -0,0 +1,44 @@
1
+ import { getPlacement } from '../internal/resolve-placement';
2
+ export function getPopupMotionStyles(_ref) {
3
+ var placement = _ref.placement;
4
+ var _getPlacement = getPlacement({
5
+ placement: placement
6
+ }),
7
+ axis = _getPlacement.axis,
8
+ edge = _getPlacement.edge;
9
+ if (axis === 'block' && edge === 'start') {
10
+ return [{
11
+ property: '--ds-popover-motion-enter',
12
+ value: "var(--ds-popup-enter-top, 150ms cubic-bezier(0.4, 1, 0.6, 1) SlideInTop8px, 150ms cubic-bezier(0.4, 1, 0.6, 1) FadeIn0to100)"
13
+ }, {
14
+ property: '--ds-popover-motion-exit',
15
+ value: "var(--ds-popup-exit-top, 100ms cubic-bezier(0.6, 0, 0.8, 0.6) SlideOutTop8px, 100ms cubic-bezier(0.6, 0, 0.8, 0.6) FadeOut100to0)"
16
+ }];
17
+ }
18
+ if (axis === 'inline' && edge === 'start') {
19
+ return [{
20
+ property: '--ds-popover-motion-enter',
21
+ value: "var(--ds-popup-enter-left, 150ms cubic-bezier(0.4, 1, 0.6, 1) SlideInLeft8px, 150ms cubic-bezier(0.4, 1, 0.6, 1) FadeIn0to100)"
22
+ }, {
23
+ property: '--ds-popover-motion-exit',
24
+ value: "var(--ds-popup-exit-left, 100ms cubic-bezier(0.6, 0, 0.8, 0.6) SlideOutLeft8px, 100ms cubic-bezier(0.6, 0, 0.8, 0.6) FadeOut100to0)"
25
+ }];
26
+ }
27
+ if (axis === 'inline' && edge === 'end') {
28
+ return [{
29
+ property: '--ds-popover-motion-enter',
30
+ value: "var(--ds-popup-enter-right, 150ms cubic-bezier(0.4, 1, 0.6, 1) SlideInRight8px, 150ms cubic-bezier(0.4, 1, 0.6, 1) FadeIn0to100)"
31
+ }, {
32
+ property: '--ds-popover-motion-exit',
33
+ value: "var(--ds-popup-exit-right, 100ms cubic-bezier(0.6, 0, 0.8, 0.6) SlideOutRight8px, 100ms cubic-bezier(0.6, 0, 0.8, 0.6) FadeOut100to0)"
34
+ }];
35
+ }
36
+ // Default: block/end (popover below trigger)
37
+ return [{
38
+ property: '--ds-popover-motion-enter',
39
+ value: "var(--ds-popup-enter-bottom, 150ms cubic-bezier(0.4, 1, 0.6, 1) SlideInBottom8px, 150ms cubic-bezier(0.4, 1, 0.6, 1) FadeIn0to100)"
40
+ }, {
41
+ property: '--ds-popover-motion-exit',
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
+ }];
44
+ }
@@ -2,32 +2,25 @@
2
2
  ._15ns179n:popover-open{animation:var(--ds-popover-motion-enter)}
3
3
  ._19itglyw{border:none}
4
4
  ._1r041wug{inset:auto}
5
- ._y44vof1f{animation:var(--ds-popover-motion-exit)}._12t71ttt:popover-open{transition-duration:.35s}
6
- ._162xglyw:popover-open{transform:none}
5
+ ._y44vof1f{animation:var(--ds-popover-motion-exit)}._12t71ign:popover-open{transition-duration:var(--ds-duration-short,.15s)}
7
6
  ._18m9ewfl{overflow-y:visible}
8
7
  ._18u0idpf{margin-left:0}
9
8
  ._19bvidpf{padding-left:0}
10
9
  ._19pkidpf{margin-top:0}
11
- ._1f6ykb7n:popover-open{opacity:1}
12
10
  ._1o51q7pw{animation-fill-mode:forwards}
13
- ._1oec6ebc{transition-duration:.15s}
14
- ._1oecluct{transition-duration:175ms}
11
+ ._1oecdn4k{transition-duration:var(--ds-duration-xshort,.1s)}
12
+ ._1pgl1lbj{animation-timing-function:var(--ds-easing-in-practical,cubic-bezier(.6,0,.8,.6))}
13
+ ._1psg1ign:popover-open{animation-duration:var(--ds-duration-short,.15s)}
15
14
  ._1reoewfl{overflow-x:visible}
16
15
  ._1s9z1a5r{transition-behavior:allow-discrete}
17
16
  ._2hwxidpf{margin-right:0}
18
- ._6fl41a34{transition-timing-function:cubic-bezier(.15,1,.3,1)}
17
+ ._5sagdn4k{animation-duration:var(--ds-duration-xshort,.1s)}
19
18
  ._bfhk1j28{background-color:transparent}
20
19
  ._ca0qidpf{padding-top:0}
21
20
  ._k8m011k7{transition-property:overlay,display}
22
- ._k8m01slm{transition-property:opacity,overlay,display}
23
- ._k8m0rv36{transition-property:opacity,transform,overlay,display}
24
21
  ._n3tdidpf{padding-bottom:0}
25
22
  ._n70peoah:popover-open{animation-fill-mode:backwards}
23
+ ._o8i7indk:popover-open{animation-timing-function:var(--ds-easing-out-practical,cubic-bezier(.4,1,.6,1))}
26
24
  ._otyridpf{margin-bottom:0}
27
- ._t9ecgt2x{transform:scale(.95)}
28
- ._t9ecxauz{transform:translate(var(--ds-popover-tx,0),var(--ds-popover-ty,0))}
29
- ._tzy4idpf{opacity:0}
30
25
  ._u5f3idpf{padding-right:0}
31
- [dir=rtl] ._1tz31oq6{transform:translate(calc(var(--ds-popover-tx, 0)*-1),var(--ds-popover-ty,0))}
32
- @media (prefers-reduced-motion:reduce){._156yru3m{transition-duration:0s}._2qm2ru3m:popover-open{transition-duration:0s}._bl8aglyw{animation-name:none}._8rmvglyw:popover-open{animation-name:none}}
33
- @starting-style{._1wuhidpf:popover-open{opacity:0}._1423gt2x:popover-open{transform:scale(.95)}._1423xauz:popover-open{transform:translate(var(--ds-popover-tx,0),var(--ds-popover-ty,0))}[dir=rtl] ._1dml1oq6:popover-open{transform:translate(calc(var(--ds-popover-tx, 0)*-1),var(--ds-popover-ty,0))}}
26
+ @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}}
@@ -1,7 +1,4 @@
1
1
  /* popover.tsx generated by @compiled/babel-plugin v0.39.1 */
2
- import _extends from "@babel/runtime/helpers/extends";
3
- import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
- import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
5
2
  import "./popover.compiled.css";
6
3
  import { ax, ix } from "@compiled/react/runtime";
7
4
  import React, { forwardRef, useCallback, useId, useLayoutEffect, useRef } from 'react';
@@ -10,9 +7,11 @@ import mergeRefs from '@atlaskit/ds-lib/merge-refs';
10
7
  import once from '@atlaskit/ds-lib/once';
11
8
  import { useNotifyOpenLayerObserver } from '@atlaskit/layering/experimental/open-layer-observer';
12
9
  import { shouldFocusIntoPopover } from '../internal/role-types';
10
+ import { setStyle } from '../internal/set-style';
13
11
  import { useAnimatedVisibility } from '../internal/use-animated-visibility';
14
12
  import { useFocusWrap } from '../internal/use-focus-wrap';
15
13
  import { useInitialFocus } from '../internal/use-initial-focus';
14
+ import { getPopupMotionStyles } from './animations';
16
15
  /**
17
16
  * Detects `popover="hint"` support via DOM reflection. SSR-safe, cached.
18
17
  */
@@ -31,10 +30,7 @@ var supportsPopoverHint = once(function () {
31
30
  // Keep them in this component so the Compiled transform can statically extract
32
31
  // every referenced style.
33
32
  var popoverAnimationStyles = {
34
- popupMotion: "_y44vof1f _1o51q7pw _k8m011k7 _1oec6ebc _1s9z1a5r _15ns179n _n70peoah _bl8aglyw _156yru3m _8rmvglyw _2qm2ru3m",
35
- slideAndFade: "_tzy4idpf _t9ecxauz _k8m0rv36 _1oecluct _6fl41a34 _1s9z1a5r _1tz31oq6 _1f6ykb7n _162xglyw _12t71ttt _1wuhidpf _1423xauz _156yru3m _2qm2ru3m _1dml1oq6",
36
- fade: "_tzy4idpf _k8m01slm _1oecluct _6fl41a34 _1s9z1a5r _1f6ykb7n _12t71ttt _1wuhidpf _156yru3m _2qm2ru3m",
37
- scaleAndFade: "_tzy4idpf _t9ecgt2x _k8m0rv36 _1oecluct _6fl41a34 _1s9z1a5r _1f6ykb7n _162xglyw _12t71ttt _1wuhidpf _1423gt2x _156yru3m _2qm2ru3m"
33
+ root: "_y44vof1f _k8m011k7 _1oecdn4k _1s9z1a5r _1o51q7pw _5sagdn4k _1pgl1lbj _15ns179n _12t71ign _n70peoah _1psg1ign _o8i7indk _bl8aglyw _156yru3m _8rmvglyw _2qm2ru3m"
38
34
  };
39
35
  var styles = {
40
36
  root: "_19itglyw _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _19pkidpf _2hwxidpf _otyridpf _18u0idpf _1r041wug _1reoewfl _18m9ewfl _bfhk1j28"
@@ -85,11 +81,12 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
85
81
  onOpenChange = _ref.onOpenChange,
86
82
  onEnterFinish = _ref.onEnterFinish,
87
83
  onExitFinish = _ref.onExitFinish,
88
- animate = _ref.animate,
84
+ _ref$animate = _ref.animate,
85
+ animate = _ref$animate === void 0 ? false : _ref$animate,
89
86
  placement = _ref.placement,
90
87
  testId = _ref.testId,
91
88
  isOpen = _ref.isOpen,
92
- xcssFromProps = _ref.xcss,
89
+ consumerXcss = _ref.xcss,
93
90
  role = _ref.role,
94
91
  label = _ref.label,
95
92
  labelledBy = _ref.labelledBy,
@@ -101,6 +98,7 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
101
98
  var popoverId = idProp !== null && idProp !== void 0 ? idProp : "popover-".concat(autoId.replace(/:/g, ''));
102
99
  var _useAnimatedVisibilit = useAnimatedVisibility({
103
100
  isOpen: isOpen,
101
+ animationKind: 'popover',
104
102
  animate: animate,
105
103
  elementRef: ownRef,
106
104
  onEnterFinish: onEnterFinish,
@@ -264,27 +262,19 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
264
262
 
265
263
  // Placement-dependent animation CSS vars. Kept separate from show/hide
266
264
  // so preset reference changes do not re-trigger visibility. The cleanup
267
- // removes the properties so a preset change does not leave stale custom
268
- // properties on the element.
265
+ // restores the previous inline values so a preset change does not leave
266
+ // stale custom properties on the element.
269
267
  useLayoutEffect(function () {
270
268
  var element = ownRef.current;
271
- if (!element || !(preset !== null && preset !== void 0 && preset.getProperties) || !placement) {
269
+ if (!element || !placement) {
272
270
  return;
273
271
  }
274
- var props = preset.getProperties({
275
- placement: placement
272
+ return setStyle({
273
+ element: element,
274
+ styles: getPopupMotionStyles({
275
+ placement: placement
276
+ })
276
277
  });
277
- Object.entries(props).forEach(function (_ref2) {
278
- var _ref3 = _slicedToArray(_ref2, 2),
279
- key = _ref3[0],
280
- value = _ref3[1];
281
- element.style.setProperty(key, String(value));
282
- });
283
- return function () {
284
- Object.keys(props).forEach(function (key) {
285
- element.style.removeProperty(key);
286
- });
287
- };
288
278
  }, [preset, placement, isVisible]);
289
279
 
290
280
  // Show/hide based on isOpen. `showPopover`/`hidePopover` are no-ops when
@@ -323,7 +313,7 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
323
313
  if (!isVisible) {
324
314
  return null;
325
315
  }
326
- return /*#__PURE__*/React.createElement("div", _extends({
316
+ return /*#__PURE__*/React.createElement("div", {
327
317
  ref: combinedRef,
328
318
  id: popoverId
329
319
  // @ts-expect-error -- popover attribute not yet in React types
@@ -333,9 +323,7 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
333
323
  role: role,
334
324
  "aria-label": label,
335
325
  "aria-labelledby": labelledBy,
336
- "data-testid": testId
337
- }, preset ? _defineProperty({}, "data-ds-popover-".concat(preset.name), '') : undefined, {
338
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- xcss prop passes compiled atomic class names
339
- className: ax([styles.root, (preset === null || preset === void 0 ? void 0 : preset.name) === 'popup-motion' && popoverAnimationStyles.popupMotion, (preset === null || preset === void 0 ? void 0 : preset.name) === 'slide-and-fade' && popoverAnimationStyles.slideAndFade, (preset === null || preset === void 0 ? void 0 : preset.name) === 'fade' && popoverAnimationStyles.fade, (preset === null || preset === void 0 ? void 0 : preset.name) === 'scale-and-fade' && popoverAnimationStyles.scaleAndFade, xcssFromProps])
340
- }), children);
326
+ "data-testid": testId,
327
+ className: ax([styles.root, preset && popoverAnimationStyles.root, consumerXcss])
328
+ }, children);
341
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 TAnimationPreset } from '../animations/types';
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?: TAnimationPreset | 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, popupMotion, slideAndFade, fade, scaleAndFade, dialogSlideUpAndFade, dialogFade, } from '../animations/presets';
2
- export type { TAnimationPreset } from '../animations/types';
@@ -1,15 +1,26 @@
1
1
  import { type RefObject } from 'react';
2
- import { type TAnimationPreset } from '../animations/types';
2
+ type TAnimationKind = 'dialog' | 'popover';
3
+ /**
4
+ * Animation config for entry/exit transitions.
5
+ *
6
+ * Currently no configuration is supported via this prop,
7
+ * and this is just a placeholder.
8
+ */
9
+ export type TAnimationConfig = never;
3
10
  type TUseAnimatedVisibilityArgs = {
4
11
  /**
5
12
  * Whether the element is logically open.
6
13
  */
7
14
  isOpen: boolean;
8
15
  /**
9
- * 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.
10
21
  * Pass `false` or `undefined` to disable animation.
11
22
  */
12
- animate: TAnimationPreset | false | undefined;
23
+ animate: boolean | TAnimationConfig;
13
24
  /**
14
25
  * Ref to the DOM element that plays the entry/exit transitions.
15
26
  * Used to listen for `transitionend`.
@@ -42,7 +53,7 @@ type TUseAnimatedVisibilityResult = {
42
53
  * Resolved animation preset (styles applied via the host element's `css`
43
54
  * prop), or `null` if animation is disabled.
44
55
  */
45
- preset: TAnimationPreset | null;
56
+ preset: boolean | TAnimationConfig | null;
46
57
  };
47
58
  /**
48
59
  * Visibility lifecycle phase shared between `useAnimatedVisibility`,
@@ -105,5 +116,5 @@ export type TPhase = 'closed' | 'entering' | 'open' | 'exiting';
105
116
  * Every effect dispatches on the single `phase` value instead of a
106
117
  * cross-product of booleans.
107
118
  */
108
- export declare function useAnimatedVisibility({ isOpen, animate, elementRef, onEnterFinish, onExitFinish, }: TUseAnimatedVisibilityArgs): TUseAnimatedVisibilityResult;
119
+ export declare function useAnimatedVisibility({ isOpen, animationKind, animate, elementRef, onEnterFinish, onExitFinish, }: TUseAnimatedVisibilityArgs): TUseAnimatedVisibilityResult;
109
120
  export {};
@@ -0,0 +1,7 @@
1
+ import { type TPlacementOptions } from '../internal/resolve-placement';
2
+ export declare function getPopupMotionStyles({ placement, }: {
3
+ placement: TPlacementOptions;
4
+ }): Array<{
5
+ property: string;
6
+ value: string;
7
+ }>;
@@ -1,8 +1,8 @@
1
1
  import { type ReactNode } from 'react';
2
2
  import { type StrictXCSSProp } from '@atlaskit/css';
3
- import { type TAnimationPreset } from '../animations/types';
4
3
  import { type TPlacementOptions } from '../internal/resolve-placement';
5
4
  import { type TAriaRoleRequired, type TRoleRequiringAccessibleName, type TRoleWithImplicitName } from '../internal/role-types';
5
+ import type { TAnimationConfig } from '../internal/use-animated-visibility';
6
6
  /**
7
7
  * The reason a popover was closed.
8
8
  *
@@ -36,14 +36,17 @@ type TPopoverBaseProps = {
36
36
  * Additional CSS styles applied to the popover root element.
37
37
  * Use to set `backgroundColor` to match the popup surface colour.
38
38
  */
39
- xcss?: StrictXCSSProp<'backgroundColor', never>;
39
+ xcss?: StrictXCSSProp<'animationName', '&:popover-open', {
40
+ requiredPseudos: '&:popover-open';
41
+ requiredProperties: never;
42
+ }>;
40
43
  /**
41
44
  * Animation preset for entry/exit transitions.
42
45
  *
43
46
  * Animations use `@starting-style` and `allow-discrete` for progressive
44
47
  * enhancement: browsers without support show/hide instantly.
45
48
  */
46
- animate?: false | TAnimationPreset;
49
+ animate?: boolean | TAnimationConfig;
47
50
  /**
48
51
  * Test ID applied to the popover element.
49
52
  */
@@ -109,7 +112,7 @@ type TPopoverBaseProps = {
109
112
  /**
110
113
  * Placement hint for directional animations (e.g. `slideAndFade`).
111
114
  *
112
- * When `animate` is provided, the preset's `getProperties(placement)` is
115
+ * When `animate` is provided, the preset's `getStyles(placement)` is
113
116
  * called to set CSS custom properties (like `--ds-popover-tx`, `--ds-popover-ty`)
114
117
  * that control the slide direction. Has no effect without `animate`.
115
118
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/top-layer",
3
- "version": "1.5.0",
3
+ "version": "1.6.1",
4
4
  "description": "Low-level layering primitives based on popover and dialog",
5
5
  "homepage": "https://atlassian.design/components/top-layer",
6
6
  "repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
@@ -10,7 +10,9 @@
10
10
  "module": "dist/esm/index.js",
11
11
  "module:es2019": "dist/es2019/index.js",
12
12
  "types": "dist/types/index.d.ts",
13
- "sideEffects": ["*.compiled.css"],
13
+ "sideEffects": [
14
+ "*.compiled.css"
15
+ ],
14
16
  "atlaskit:src": "src/index.tsx",
15
17
  "atlassian": {
16
18
  "react-compiler": {
@@ -26,7 +28,9 @@
26
28
  "category": "Libraries"
27
29
  },
28
30
  "integrationTests": {
29
- "additionalBrowsers": ["desktop-firefox"]
31
+ "additionalBrowsers": [
32
+ "desktop-firefox"
33
+ ]
30
34
  }
31
35
  },
32
36
  "dependencies": {
@@ -35,7 +39,7 @@
35
39
  "@atlaskit/ds-lib": "^8.0.0",
36
40
  "@atlaskit/layering": "^4.1.0",
37
41
  "@atlaskit/react-compiler-gating": "^0.2.0",
38
- "@atlaskit/tokens": "^15.5.0",
42
+ "@atlaskit/tokens": "^15.7.0",
39
43
  "@babel/runtime": "^7.0.0",
40
44
  "@compiled/react": "^0.20.0",
41
45
  "bind-event-listener": "^3.0.0",
@@ -51,11 +55,11 @@
51
55
  "@atlaskit/button": "^24.3.0",
52
56
  "@atlaskit/heading": "^6.2.0",
53
57
  "@atlaskit/lozenge": "^14.1.0",
54
- "@atlaskit/primitives": "^20.5.0",
58
+ "@atlaskit/primitives": "^20.6.0",
55
59
  "@atlaskit/ssr": "workspace:^",
56
60
  "@atlaskit/textfield": "^9.1.0",
57
61
  "@atlassian/ssr-tests": "workspace:^",
58
- "@atlassian/testing-library": "^0.10.0",
62
+ "@atlassian/testing-library": "^0.11.0",
59
63
  "@testing-library/jest-dom": "^6.4.5",
60
64
  "@testing-library/react": "^16.3.0",
61
65
  "@types/raf-schd": "^4.0.1",
@@ -65,15 +69,29 @@
65
69
  },
66
70
  "techstack": {
67
71
  "@atlassian/frontend": {
68
- "import-structure": ["atlassian-conventions"],
69
- "circular-dependencies": ["file-and-folder-level"]
72
+ "import-structure": [
73
+ "atlassian-conventions"
74
+ ],
75
+ "circular-dependencies": [
76
+ "file-and-folder-level"
77
+ ]
70
78
  },
71
79
  "@repo/internal": {
72
80
  "dom-events": "use-bind-event-listener",
73
- "ui-components": ["lite-mode"],
74
- "design-tokens": ["color", "spacing"],
75
- "deprecation": ["no-deprecated-imports"],
76
- "styling": ["static", "compiled"]
81
+ "ui-components": [
82
+ "lite-mode"
83
+ ],
84
+ "design-tokens": [
85
+ "color",
86
+ "spacing"
87
+ ],
88
+ "deprecation": [
89
+ "no-deprecated-imports"
90
+ ],
91
+ "styling": [
92
+ "static",
93
+ "compiled"
94
+ ]
77
95
  }
78
96
  },
79
97
  "publishConfig": {