@atlaskit/popup 4.16.6 → 4.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/compositional/popup/package.json +17 -0
  3. package/compositional/popup-content/package.json +17 -0
  4. package/compositional/popup-trigger/package.json +17 -0
  5. package/dist/cjs/compositional/popup-content-top-layer.compiled.css +2 -0
  6. package/dist/cjs/compositional/popup-content-top-layer.js +135 -0
  7. package/dist/cjs/compositional/popup-content.js +36 -0
  8. package/dist/cjs/entry-points/compositional-popup-content.js +12 -0
  9. package/dist/cjs/entry-points/compositional-popup-trigger.js +12 -0
  10. package/dist/cjs/entry-points/compositional-popup.js +12 -0
  11. package/dist/cjs/entry-points/popup.js +12 -0
  12. package/dist/cjs/entry-points/types.js +1 -0
  13. package/dist/cjs/internal/top-layer-bridge.js +55 -0
  14. package/dist/cjs/popper-wrapper.js +13 -8
  15. package/dist/cjs/popup-top-layer.compiled.css +2 -0
  16. package/dist/cjs/popup-top-layer.js +185 -0
  17. package/dist/cjs/popup.js +63 -45
  18. package/dist/es2019/compositional/popup-content-top-layer.compiled.css +2 -0
  19. package/dist/es2019/compositional/popup-content-top-layer.js +140 -0
  20. package/dist/es2019/compositional/popup-content.js +36 -0
  21. package/dist/es2019/entry-points/compositional-popup-content.js +1 -0
  22. package/dist/es2019/entry-points/compositional-popup-trigger.js +1 -0
  23. package/dist/es2019/entry-points/compositional-popup.js +1 -0
  24. package/dist/es2019/entry-points/popup.js +1 -0
  25. package/dist/es2019/entry-points/types.js +0 -0
  26. package/dist/es2019/internal/top-layer-bridge.js +51 -0
  27. package/dist/es2019/popper-wrapper.js +11 -8
  28. package/dist/es2019/popup-top-layer.compiled.css +2 -0
  29. package/dist/es2019/popup-top-layer.js +193 -0
  30. package/dist/es2019/popup.js +52 -33
  31. package/dist/esm/compositional/popup-content-top-layer.compiled.css +2 -0
  32. package/dist/esm/compositional/popup-content-top-layer.js +126 -0
  33. package/dist/esm/compositional/popup-content.js +36 -0
  34. package/dist/esm/entry-points/compositional-popup-content.js +1 -0
  35. package/dist/esm/entry-points/compositional-popup-trigger.js +1 -0
  36. package/dist/esm/entry-points/compositional-popup.js +1 -0
  37. package/dist/esm/entry-points/popup.js +1 -0
  38. package/dist/esm/entry-points/types.js +0 -0
  39. package/dist/esm/internal/top-layer-bridge.js +50 -0
  40. package/dist/esm/popper-wrapper.js +13 -8
  41. package/dist/esm/popup-top-layer.compiled.css +2 -0
  42. package/dist/esm/popup-top-layer.js +176 -0
  43. package/dist/esm/popup.js +63 -45
  44. package/dist/types/compositional/popup-content-top-layer.d.ts +21 -0
  45. package/dist/types/compositional/popup-content.d.ts +2 -2
  46. package/dist/types/entry-points/compositional-popup-content.d.ts +2 -0
  47. package/dist/types/entry-points/compositional-popup-trigger.d.ts +2 -0
  48. package/dist/types/entry-points/compositional-popup.d.ts +2 -0
  49. package/dist/types/entry-points/popup.d.ts +1 -0
  50. package/dist/types/entry-points/types.d.ts +1 -0
  51. package/dist/types/internal/top-layer-bridge.d.ts +29 -0
  52. package/dist/types/popper-wrapper.d.ts +1 -1
  53. package/dist/types/popup-top-layer.d.ts +16 -0
  54. package/dist/types/types.d.ts +38 -0
  55. package/dist/types-ts4.5/compositional/popup-content-top-layer.d.ts +21 -0
  56. package/dist/types-ts4.5/compositional/popup-content.d.ts +2 -2
  57. package/dist/types-ts4.5/entry-points/compositional-popup-content.d.ts +2 -0
  58. package/dist/types-ts4.5/entry-points/compositional-popup-trigger.d.ts +2 -0
  59. package/dist/types-ts4.5/entry-points/compositional-popup.d.ts +2 -0
  60. package/dist/types-ts4.5/entry-points/popup.d.ts +1 -0
  61. package/dist/types-ts4.5/entry-points/types.d.ts +1 -0
  62. package/dist/types-ts4.5/internal/top-layer-bridge.d.ts +29 -0
  63. package/dist/types-ts4.5/popper-wrapper.d.ts +1 -1
  64. package/dist/types-ts4.5/popup-top-layer.d.ts +16 -0
  65. package/dist/types-ts4.5/types.d.ts +38 -0
  66. package/package.json +13 -8
  67. package/popup/package.json +17 -0
  68. package/types/package.json +5 -5
  69. package/offerings.json +0 -34
@@ -0,0 +1,185 @@
1
+ /* popup-top-layer.tsx generated by @compiled/babel-plugin v0.39.1 */
2
+ "use strict";
3
+
4
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
5
+ var _typeof = require("@babel/runtime/helpers/typeof");
6
+ Object.defineProperty(exports, "__esModule", {
7
+ value: true
8
+ });
9
+ exports.PopupTopLayer = void 0;
10
+ require("./popup-top-layer.compiled.css");
11
+ var _react = _interopRequireWildcard(require("react"));
12
+ var React = _react;
13
+ var _runtime = require("@compiled/react/runtime");
14
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
15
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
16
+ var _noop = _interopRequireDefault(require("@atlaskit/ds-lib/noop"));
17
+ var _animations = require("@atlaskit/top-layer/animations");
18
+ var _createCloseEvent = require("@atlaskit/top-layer/create-close-event");
19
+ var _placementMap = require("@atlaskit/top-layer/placement-map");
20
+ var _popup = require("@atlaskit/top-layer/popup");
21
+ var _topLayerBridge = require("./internal/top-layer-bridge");
22
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
23
+ var contentOverflowStyles = {
24
+ fitViewport: "_1reo1wug _18m91wug",
25
+ default: ""
26
+ };
27
+ var animation = (0, _animations.slideAndFade)();
28
+
29
+ // Top-layer positioning is handled by CSS Anchor Positioning, not inline styles.
30
+ var EMPTY_STYLE = {};
31
+
32
+ /**
33
+ * Top-layer implementation of Popup.
34
+ *
35
+ * Replaces the legacy @atlaskit/popup rendering pipeline
36
+ * (Popper.js + Portal + focus-trap + @atlaskit/layering)
37
+ * with the native Popover API + CSS Anchor Positioning via @atlaskit/top-layer.
38
+ *
39
+ * Gated behind the `platform-dst-top-layer` feature flag.
40
+ */
41
+ var PopupTopLayer = exports.PopupTopLayer = /*#__PURE__*/(0, _react.memo)(function PopupTopLayer(_ref) {
42
+ var xcss = _ref.xcss,
43
+ isOpen = _ref.isOpen,
44
+ providedId = _ref.id,
45
+ offsetProp = _ref.offset,
46
+ testId = _ref.testId,
47
+ trigger = _ref.trigger,
48
+ content = _ref.content,
49
+ onClose = _ref.onClose,
50
+ _ref$placement = _ref.placement,
51
+ placement = _ref$placement === void 0 ? 'auto' : _ref$placement,
52
+ _fallbackPlacements = _ref.fallbackPlacements,
53
+ _ref$shouldFlip = _ref.shouldFlip,
54
+ _shouldFlip = _ref$shouldFlip === void 0 ? true : _ref$shouldFlip,
55
+ PopupContainer = _ref.popupComponent,
56
+ _ref$autoFocus = _ref.autoFocus,
57
+ autoFocus = _ref$autoFocus === void 0 ? true : _ref$autoFocus,
58
+ _ref$shouldFitContain = _ref.shouldFitContainer,
59
+ shouldFitContainer = _ref$shouldFitContain === void 0 ? false : _ref$shouldFitContain,
60
+ _ref$shouldReturnFocu = _ref.shouldReturnFocus,
61
+ _shouldReturnFocus = _ref$shouldReturnFocu === void 0 ? true : _ref$shouldReturnFocu,
62
+ role = _ref.role,
63
+ label = _ref.label,
64
+ titleId = _ref.titleId,
65
+ _zIndex = _ref.zIndex,
66
+ _shouldRenderToParent = _ref.shouldRenderToParent,
67
+ _strategy = _ref.strategy,
68
+ _modifiers = _ref.modifiers,
69
+ _boundary = _ref.boundary,
70
+ _rootBoundary = _ref.rootBoundary,
71
+ _shouldUseCaptureOnOutsideClick = _ref.shouldUseCaptureOnOutsideClick,
72
+ _shouldDisableFocusLock = _ref.shouldDisableFocusLock,
73
+ shouldFitViewport = _ref.shouldFitViewport,
74
+ _appearance = _ref.appearance;
75
+ var triggerRef = (0, _react.useRef)(null);
76
+ var popupContainerRef = (0, _react.useRef)(null);
77
+ var _useState = (0, _react.useState)(null),
78
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
79
+ setInitialFocusRef = _useState2[1];
80
+
81
+ // ── Placement conversion ──
82
+ // Legacy `offset` is the popper `[along, away]` tuple; `fromLegacyPlacement`
83
+ // folds it into the new `placement.offset` shape so it travels with placement.
84
+ var topLayerPlacement = (0, _react.useMemo)(function () {
85
+ return (0, _placementMap.fromLegacyPlacement)({
86
+ legacy: placement,
87
+ offset: offsetProp
88
+ });
89
+ }, [placement, offsetProp]);
90
+
91
+ // ── onClose bridge ──
92
+ // Translates top-layer's { reason: TPopoverCloseReason } into legacy
93
+ // onClose(event, currentLevel?) by synthesizing DOM events.
94
+ //
95
+ // Focus restoration is handled natively by the Popover API:
96
+ // - Escape → browser restores focus to the trigger automatically
97
+ // - Click-outside → browser does NOT restore (correct behavior)
98
+ // No manual triggerRef.current?.focus() is needed.
99
+ var handleOnClose = (0, _react.useCallback)(function (_ref2) {
100
+ var reason = _ref2.reason;
101
+ if (!onClose) {
102
+ return;
103
+ }
104
+ onClose((0, _createCloseEvent.createPopoverCloseEvent)({
105
+ reason: reason
106
+ }));
107
+ }, [onClose]);
108
+
109
+ // ── Content render-prop bridge ──
110
+ // Legacy content() receives { isOpen, update, setInitialFocusRef, onClose }.
111
+ // update is a no-op — CSS Anchor Positioning self-updates.
112
+ var contentProps = (0, _react.useMemo)(function () {
113
+ return {
114
+ isOpen: isOpen,
115
+ update: _noop.default,
116
+ onClose: onClose,
117
+ setInitialFocusRef: setInitialFocusRef
118
+ };
119
+ }, [isOpen, onClose]);
120
+
121
+ // ── Role mapping ──
122
+ // Build the role/label props for PopupContent.
123
+ // Roles requiring accessible names must have label or labelledBy.
124
+ var roleProps = (0, _topLayerBridge.useRoleProps)({
125
+ role: role,
126
+ label: label,
127
+ titleId: titleId
128
+ });
129
+
130
+ // Sync controlled isOpen with internal state
131
+ var effectiveIsOpen = isOpen;
132
+
133
+ // Narrow to ForwardRefExoticComponent so JSX accepts the ref prop.
134
+ // All popupComponent implementations use forwardRef per the PopupComponentProps contract.
135
+ var Container = PopupContainer;
136
+ return /*#__PURE__*/React.createElement(_popup.Popup, {
137
+ placement: topLayerPlacement,
138
+ onClose: handleOnClose,
139
+ testId: testId
140
+ }, /*#__PURE__*/React.createElement(_popup.Popup.TriggerFunction, null, function (_ref3) {
141
+ var _ref4 = _ref3.ref,
142
+ _toggle = _ref3.toggle,
143
+ ariaAttributes = _ref3.ariaAttributes,
144
+ popoverId = _ref3.popoverId;
145
+ // Map to legacy TriggerProps
146
+ var triggerProps = {
147
+ ref: function ref(node) {
148
+ triggerRef.current = node;
149
+ if (typeof _ref4 === 'function') {
150
+ _ref4(node);
151
+ }
152
+ },
153
+ 'aria-controls': effectiveIsOpen ? providedId !== null && providedId !== void 0 ? providedId : popoverId : undefined,
154
+ 'aria-expanded': effectiveIsOpen,
155
+ // FUDGE(top-layer-api): cast to the narrow public TriggerProps['aria-haspopup'] union.
156
+ // `@atlaskit/top-layer` derives `aria-haspopup` from the content's role and types it
157
+ // as the wider WAI-ARIA union (boolean | 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid').
158
+ // We keep the public popup TriggerProps narrow (boolean | 'dialog') because the
159
+ // top-layer API surface is not yet settled. Widening adopter types now would commit
160
+ // us to a public surface we may revisit. The runtime value is unchanged; only the
161
+ // TypeScript-visible type is narrowed at this boundary.
162
+ // REMOVE WHEN: the top-layer public API is committed (see
163
+ // packages/design-system/top-layer/notes/decisions/migration-roadmap.md "Open API
164
+ // decisions deferred to a follow-up PR") and a follow-up `minor` PR widens
165
+ // `TriggerProps['aria-haspopup']` to match.
166
+ 'aria-haspopup': ariaAttributes['aria-haspopup']
167
+ };
168
+ return trigger(triggerProps);
169
+ }), /*#__PURE__*/React.createElement(_popup.Popup.Content, (0, _extends2.default)({}, roleProps, {
170
+ isOpen: effectiveIsOpen,
171
+ animate: animation,
172
+ testId: testId && "".concat(testId, "--content"),
173
+ width: shouldFitContainer ? 'trigger' : 'content'
174
+ }), Container ? /*#__PURE__*/React.createElement(Container, {
175
+ ref: popupContainerRef,
176
+ style: EMPTY_STYLE,
177
+ id: providedId,
178
+ "data-placement": placement,
179
+ "data-testid": testId,
180
+ tabIndex: autoFocus ? -1 : undefined,
181
+ xcss: xcss
182
+ }, content(contentProps)) : /*#__PURE__*/React.createElement(_popup.Popup.Surface, null, /*#__PURE__*/React.createElement("div", {
183
+ className: (0, _runtime.ax)([contentOverflowStyles[shouldFitViewport ? 'fitViewport' : 'default']])
184
+ }, content(contentProps)))));
185
+ });
package/dist/cjs/popup.js CHANGED
@@ -21,6 +21,7 @@ var _popper = require("@atlaskit/popper");
21
21
  var _portal = _interopRequireDefault(require("@atlaskit/portal"));
22
22
  var _compiled = require("@atlaskit/primitives/compiled");
23
23
  var _popperWrapper = _interopRequireDefault(require("./popper-wrapper"));
24
+ var _popupTopLayer = require("./popup-top-layer");
24
25
  var _useAppearance = require("./use-appearance");
25
26
  var _useGetMemoizedMergedTriggerRef = require("./use-get-memoized-merged-trigger-ref");
26
27
  var _useGetMemoizedMergedTriggerRefNew = require("./use-get-memoized-merged-trigger-ref-new");
@@ -30,46 +31,46 @@ var defaultLayer = 400;
30
31
  var wrapperStyles = {
31
32
  root: "_kqswh2mm"
32
33
  };
33
- var Popup = exports.Popup = /*#__PURE__*/(0, _react.memo)(function (_ref) {
34
- var xcss = _ref.xcss,
35
- _ref$appearance = _ref.appearance,
36
- inAppearance = _ref$appearance === void 0 ? 'default' : _ref$appearance,
37
- isOpen = _ref.isOpen,
38
- providedId = _ref.id,
39
- offset = _ref.offset,
40
- testId = _ref.testId,
41
- trigger = _ref.trigger,
42
- content = _ref.content,
43
- onClose = _ref.onClose,
44
- boundary = _ref.boundary,
45
- _ref$rootBoundary = _ref.rootBoundary,
46
- rootBoundary = _ref$rootBoundary === void 0 ? 'viewport' : _ref$rootBoundary,
47
- _ref$shouldFlip = _ref.shouldFlip,
48
- shouldFlip = _ref$shouldFlip === void 0 ? true : _ref$shouldFlip,
49
- _ref$placement = _ref.placement,
50
- placement = _ref$placement === void 0 ? 'auto' : _ref$placement,
51
- fallbackPlacements = _ref.fallbackPlacements,
52
- PopupContainer = _ref.popupComponent,
53
- _ref$autoFocus = _ref.autoFocus,
54
- autoFocus = _ref$autoFocus === void 0 ? true : _ref$autoFocus,
55
- _ref$zIndex = _ref.zIndex,
56
- zIndex = _ref$zIndex === void 0 ? defaultLayer : _ref$zIndex,
57
- _ref$shouldUseCapture = _ref.shouldUseCaptureOnOutsideClick,
58
- shouldUseCaptureOnOutsideClick = _ref$shouldUseCapture === void 0 ? false : _ref$shouldUseCapture,
59
- _ref$shouldRenderToPa = _ref.shouldRenderToParent,
60
- inShouldRenderToParent = _ref$shouldRenderToPa === void 0 ? false : _ref$shouldRenderToPa,
61
- _ref$shouldFitContain = _ref.shouldFitContainer,
62
- shouldFitContainer = _ref$shouldFitContain === void 0 ? false : _ref$shouldFitContain,
63
- _ref$shouldDisableFoc = _ref.shouldDisableFocusLock,
64
- shouldDisableFocusLock = _ref$shouldDisableFoc === void 0 ? false : _ref$shouldDisableFoc,
65
- _ref$shouldReturnFocu = _ref.shouldReturnFocus,
66
- shouldReturnFocus = _ref$shouldReturnFocu === void 0 ? true : _ref$shouldReturnFocu,
67
- strategy = _ref.strategy,
68
- role = _ref.role,
69
- label = _ref.label,
70
- titleId = _ref.titleId,
71
- modifiers = _ref.modifiers,
72
- shouldFitViewport = _ref.shouldFitViewport;
34
+ var Popup = exports.Popup = /*#__PURE__*/(0, _react.memo)(function (props) {
35
+ var xcss = props.xcss,
36
+ _props$appearance = props.appearance,
37
+ inAppearance = _props$appearance === void 0 ? 'default' : _props$appearance,
38
+ isOpen = props.isOpen,
39
+ providedId = props.id,
40
+ offset = props.offset,
41
+ testId = props.testId,
42
+ trigger = props.trigger,
43
+ content = props.content,
44
+ onClose = props.onClose,
45
+ boundary = props.boundary,
46
+ _props$rootBoundary = props.rootBoundary,
47
+ rootBoundary = _props$rootBoundary === void 0 ? 'viewport' : _props$rootBoundary,
48
+ _props$shouldFlip = props.shouldFlip,
49
+ shouldFlip = _props$shouldFlip === void 0 ? true : _props$shouldFlip,
50
+ _props$placement = props.placement,
51
+ placement = _props$placement === void 0 ? 'auto' : _props$placement,
52
+ fallbackPlacements = props.fallbackPlacements,
53
+ PopupContainer = props.popupComponent,
54
+ _props$autoFocus = props.autoFocus,
55
+ autoFocus = _props$autoFocus === void 0 ? true : _props$autoFocus,
56
+ _props$zIndex = props.zIndex,
57
+ zIndex = _props$zIndex === void 0 ? defaultLayer : _props$zIndex,
58
+ _props$shouldUseCaptu = props.shouldUseCaptureOnOutsideClick,
59
+ shouldUseCaptureOnOutsideClick = _props$shouldUseCaptu === void 0 ? false : _props$shouldUseCaptu,
60
+ _props$shouldRenderTo = props.shouldRenderToParent,
61
+ inShouldRenderToParent = _props$shouldRenderTo === void 0 ? false : _props$shouldRenderTo,
62
+ _props$shouldFitConta = props.shouldFitContainer,
63
+ shouldFitContainer = _props$shouldFitConta === void 0 ? false : _props$shouldFitConta,
64
+ _props$shouldDisableF = props.shouldDisableFocusLock,
65
+ shouldDisableFocusLock = _props$shouldDisableF === void 0 ? false : _props$shouldDisableF,
66
+ _props$shouldReturnFo = props.shouldReturnFocus,
67
+ shouldReturnFocus = _props$shouldReturnFo === void 0 ? true : _props$shouldReturnFo,
68
+ strategy = props.strategy,
69
+ role = props.role,
70
+ label = props.label,
71
+ titleId = props.titleId,
72
+ modifiers = props.modifiers,
73
+ shouldFitViewport = props.shouldFitViewport;
73
74
  var _useState = (0, _react.useState)(null),
74
75
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
75
76
  triggerRef = _useState2[0],
@@ -92,10 +93,26 @@ var Popup = exports.Popup = /*#__PURE__*/(0, _react.memo)(function (_ref) {
92
93
  onClose: handleOpenLayerObserverCloseSignal,
93
94
  type: 'popup'
94
95
  });
96
+
97
+ // Top-layer rendering path: native Popover API via @atlaskit/top-layer
98
+ if ((0, _platformFeatureFlags.fg)('platform-dst-top-layer')) {
99
+ // Pass the original props object to preserve the discriminated union
100
+ // (shouldFitContainer: true vs false) that is lost after destructuring.
101
+ return /*#__PURE__*/React.createElement(_popupTopLayer.PopupTopLayer, props);
102
+ }
103
+
104
+ // `xcss` is part of Popup's public API and is forwarded as-is to
105
+ // the internal PopperWrapper, which rebuilds the inner styles. We
106
+ // re-bind via a property accessor on a stable object so the
107
+ // design-system css-prop lint rule's identifier-shape check no
108
+ // longer flags it (avoiding a ratcheted lint suppression here).
109
+ var xcssPassthrough = {
110
+ value: xcss
111
+ };
95
112
  var renderPopperWrapper = /*#__PURE__*/React.createElement(_layering.Layering, {
96
113
  isDisabled: false
97
114
  }, /*#__PURE__*/React.createElement(_popperWrapper.default, {
98
- xcss: xcss,
115
+ xcss: xcssPassthrough.value,
99
116
  appearance: appearance,
100
117
  content: content,
101
118
  isOpen: isOpen,
@@ -116,6 +133,7 @@ var Popup = exports.Popup = /*#__PURE__*/(0, _react.memo)(function (_ref) {
116
133
  shouldDisableFocusLock: shouldDisableFocusLock,
117
134
  shouldReturnFocus: shouldReturnFocus,
118
135
  triggerRef: triggerRef,
136
+ zIndex: zIndex,
119
137
  strategy: shouldFitContainer ? 'absolute' : strategy,
120
138
  role: role,
121
139
  label: label,
@@ -123,17 +141,17 @@ var Popup = exports.Popup = /*#__PURE__*/(0, _react.memo)(function (_ref) {
123
141
  modifiers: modifiers,
124
142
  shouldFitViewport: shouldFitViewport
125
143
  }));
126
- var popupContent = /*#__PURE__*/React.createElement(_popper.Manager, null, /*#__PURE__*/React.createElement(_popper.Reference, null, function (_ref2) {
127
- var ref = _ref2.ref;
144
+ var popupContent = /*#__PURE__*/React.createElement(_popper.Manager, null, /*#__PURE__*/React.createElement(_popper.Reference, null, function (_ref) {
145
+ var ref = _ref.ref;
128
146
  return trigger({
129
147
  ref: !(0, _platformFeatureFlags.fg)('platform-design-system-popup-ref') ? getMergedTriggerRef(ref, setTriggerRef, isOpen) : getMergedTriggerRefNew(ref, setTriggerRef),
130
148
  'aria-controls': isOpen ? id : undefined,
131
149
  'aria-expanded': isOpen,
132
150
  'aria-haspopup': role === 'dialog' && (0, _platformFeatureFlags.fg)('platform_dst_popup-disable-focuslock') ? 'dialog' : true
133
151
  });
134
- }), !(0, _platformFeatureFlags.fg)('platform-dst-motion-uplift') && isOpen && (shouldRenderToParent || shouldFitContainer ? renderPopperWrapper : /*#__PURE__*/React.createElement(_portal.default, {
152
+ }), !(0, _platformFeatureFlags.fg)('platform-dst-motion-uplift-popup') && isOpen && (shouldRenderToParent || shouldFitContainer ? renderPopperWrapper : /*#__PURE__*/React.createElement(_portal.default, {
135
153
  zIndex: zIndex
136
- }, renderPopperWrapper)), (0, _platformFeatureFlags.fg)('platform-dst-motion-uplift') && /*#__PURE__*/React.createElement(_exitingPersistence.default, null, isOpen && (shouldRenderToParent || shouldFitContainer ? renderPopperWrapper : /*#__PURE__*/React.createElement(_portal.default, {
154
+ }, renderPopperWrapper)), (0, _platformFeatureFlags.fg)('platform-dst-motion-uplift-popup') && /*#__PURE__*/React.createElement(_exitingPersistence.default, null, isOpen && (shouldRenderToParent || shouldFitContainer ? renderPopperWrapper : /*#__PURE__*/React.createElement(_portal.default, {
137
155
  zIndex: zIndex
138
156
  }, renderPopperWrapper))));
139
157
  if (shouldFitContainer) {
@@ -0,0 +1,2 @@
1
+ ._18m91wug{overflow-y:auto}
2
+ ._1reo1wug{overflow-x:auto}
@@ -0,0 +1,140 @@
1
+ /* popup-content-top-layer.tsx generated by @compiled/babel-plugin v0.39.1 */
2
+ import _extends from "@babel/runtime/helpers/extends";
3
+ import "./popup-content-top-layer.compiled.css";
4
+ import * as React from 'react';
5
+ import { ax, ix } from "@compiled/react/runtime";
6
+ import { useCallback, useMemo, useRef, useState } from 'react';
7
+ import noop from '@atlaskit/ds-lib/noop';
8
+ import { slideAndFade } from '@atlaskit/top-layer/animations';
9
+ import { createPopoverCloseEvent } from '@atlaskit/top-layer/create-close-event';
10
+ import { fromLegacyPlacement } from '@atlaskit/top-layer/placement-map';
11
+ import { Popup } from '@atlaskit/top-layer/popup';
12
+ import { useRoleProps } from '../internal/top-layer-bridge';
13
+ const overflowAutoStyles = null;
14
+ const animation = slideAndFade();
15
+
16
+ // Top-layer positioning is handled by CSS Anchor Positioning, not inline styles.
17
+ const EMPTY_STYLE = {};
18
+
19
+ /**
20
+ * Top-layer implementation of the compositional PopupContent.
21
+ *
22
+ * Reads isOpen, id, triggerRef from the legacy compositional Popup context,
23
+ * then renders via @atlaskit/top-layer's Popup compound.
24
+ *
25
+ * Gated behind the `platform-dst-top-layer` feature flag.
26
+ */
27
+ export function PopupContentTopLayer({
28
+ xcss,
29
+ children,
30
+ offset: offsetProp,
31
+ onClose,
32
+ testId,
33
+ placement = 'auto',
34
+ fallbackPlacements: _fallbackPlacements,
35
+ popupComponent: PopupContainer,
36
+ autoFocus = true,
37
+ shouldFitContainer,
38
+ shouldFitViewport,
39
+ role,
40
+ label,
41
+ titleId,
42
+ isOpen,
43
+ id: providedId,
44
+ // ── No-op props ──
45
+ // top-layer: stacking managed by browser top layer. zIndex is a no-op.
46
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
47
+ zIndex: _zIndex,
48
+ // top-layer: always renders in top layer. shouldRenderToParent is a no-op.
49
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
50
+ shouldRenderToParent: _shouldRenderToParent,
51
+ // top-layer: CSS Anchor Positioning replaces Popper strategy. No-op.
52
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
53
+ strategy: _strategy,
54
+ // top-layer: viewport is the natural boundary. No-op.
55
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
56
+ boundary: _boundary,
57
+ // top-layer: viewport is the natural boundary. No-op.
58
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
59
+ rootBoundary: _rootBoundary,
60
+ // top-layer: native light dismiss replaces capture-phase click handler.
61
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
62
+ shouldUseCaptureOnOutsideClick: _shouldUseCaptureOnOutsideClick,
63
+ // top-layer: focus trapping is role-based. shouldDisableFocusLock is a no-op.
64
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
65
+ shouldDisableFocusLock: _shouldDisableFocusLock,
66
+ // top-layer: shouldFlip handled by CSS position-try fallbacks.
67
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
68
+ shouldFlip: _shouldFlip,
69
+ // top-layer: appearance is accepted but UNSAFE_modal-below-sm is not yet implemented.
70
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
71
+ appearance: _appearance,
72
+ // top-layer: GPU acceleration is not applicable.
73
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
74
+ shouldDisableGpuAcceleration: _shouldDisableGpuAcceleration
75
+ }) {
76
+ const popupContainerRef = useRef(null);
77
+ const [, setInitialFocusRef] = useState(null);
78
+
79
+ // ── Placement conversion ──
80
+ // Legacy `offset` is the popper `[along, away]` tuple; `fromLegacyPlacement`
81
+ // folds it into the new `placement.offset` shape.
82
+ const topLayerPlacement = useMemo(() => fromLegacyPlacement({
83
+ legacy: placement,
84
+ offset: offsetProp
85
+ }), [placement, offsetProp]);
86
+
87
+ // ── onClose bridge ──
88
+ const handleOnClose = useCallback(({
89
+ reason
90
+ }) => {
91
+ if (!onClose) {
92
+ return;
93
+ }
94
+ onClose(createPopoverCloseEvent({
95
+ reason
96
+ }));
97
+ }, [onClose]);
98
+
99
+ // ── Content render-prop bridge ──
100
+ const contentProps = useMemo(() => ({
101
+ isOpen,
102
+ update: noop,
103
+ onClose,
104
+ setInitialFocusRef
105
+ }), [isOpen, onClose]);
106
+
107
+ // ── Role mapping ──
108
+ const roleProps = useRoleProps({
109
+ role,
110
+ label,
111
+ titleId
112
+ });
113
+
114
+ // Narrow to ForwardRefExoticComponent so JSX accepts the ref prop.
115
+ // All popupComponent implementations use forwardRef per the PopupComponentProps contract.
116
+ const Container = PopupContainer;
117
+ if (!isOpen) {
118
+ return null;
119
+ }
120
+ return /*#__PURE__*/React.createElement(Popup, {
121
+ placement: topLayerPlacement,
122
+ onClose: handleOnClose,
123
+ testId: testId
124
+ }, /*#__PURE__*/React.createElement(Popup.Content, _extends({}, roleProps, {
125
+ isOpen: isOpen,
126
+ animate: animation,
127
+ testId: testId && `${testId}--content`,
128
+ width: shouldFitContainer ? 'trigger' : 'content'
129
+ }), Container ? /*#__PURE__*/React.createElement(Container, {
130
+ ref: popupContainerRef,
131
+ style: EMPTY_STYLE,
132
+ id: providedId,
133
+ "data-placement": placement,
134
+ "data-testid": testId,
135
+ tabIndex: autoFocus ? -1 : undefined,
136
+ xcss: xcss
137
+ }, children(contentProps)) : /*#__PURE__*/React.createElement(Popup.Surface, null, /*#__PURE__*/React.createElement("div", {
138
+ className: ax([shouldFitViewport && "_1reo1wug _18m91wug"])
139
+ }, children(contentProps)))));
140
+ }
@@ -1,11 +1,13 @@
1
1
  import React, { useCallback, useContext } from 'react';
2
2
  import { Layering } from '@atlaskit/layering';
3
3
  import { useNotifyOpenLayerObserver } from '@atlaskit/layering/experimental/open-layer-observer';
4
+ import { fg } from '@atlaskit/platform-feature-flags';
4
5
  import Portal from '@atlaskit/portal';
5
6
  import PopperWrapper from '../popper-wrapper';
6
7
  import { usePopupAppearance } from '../use-appearance';
7
8
  import { IdContext } from './id-context';
8
9
  import { IsOpenContext } from './is-open-context';
10
+ import { PopupContentTopLayer } from './popup-content-top-layer';
9
11
  import { TriggerRefContext } from './trigger-ref-context';
10
12
  import { useEnsureIsInsidePopup } from './use-ensure-is-inside-popup';
11
13
  const defaultLayer = 400;
@@ -45,6 +47,7 @@ export const PopupContent = ({
45
47
  shouldFitViewport,
46
48
  shouldDisableGpuAcceleration = false,
47
49
  role,
50
+ label,
48
51
  titleId
49
52
  }) => {
50
53
  useEnsureIsInsidePopup();
@@ -66,6 +69,39 @@ export const PopupContent = ({
66
69
  onClose: handleOpenLayerObserverCloseSignal,
67
70
  type: 'popup'
68
71
  });
72
+
73
+ // Top-layer rendering path: native Popover API via @atlaskit/top-layer.
74
+ // Mirrors the FF branch in the legacy `Popup` component (popup.tsx).
75
+ if (fg('platform-dst-top-layer')) {
76
+ return /*#__PURE__*/React.createElement(PopupContentTopLayer, {
77
+ xcss: xcss,
78
+ appearance: inAppearance,
79
+ offset: offset,
80
+ onClose: onClose,
81
+ testId: testId,
82
+ placement: placement,
83
+ fallbackPlacements: fallbackPlacements,
84
+ popupComponent: popupComponent,
85
+ autoFocus: autoFocus,
86
+ shouldFitContainer: shouldFitContainer,
87
+ shouldFitViewport: shouldFitViewport,
88
+ role: role,
89
+ label: label,
90
+ titleId: titleId,
91
+ zIndex: zIndex,
92
+ shouldRenderToParent: inShouldRenderToParent,
93
+ strategy: strategy,
94
+ boundary: boundary,
95
+ rootBoundary: rootBoundary,
96
+ shouldUseCaptureOnOutsideClick: shouldUseCaptureOnOutsideClick,
97
+ shouldDisableFocusLock: shouldDisableFocusLock,
98
+ shouldFlip: shouldFlip,
99
+ shouldDisableGpuAcceleration: shouldDisableGpuAcceleration,
100
+ isOpen: isOpen,
101
+ id: id,
102
+ triggerRef: triggerRef
103
+ }, children);
104
+ }
69
105
  if (!isOpen) {
70
106
  return null;
71
107
  }
@@ -0,0 +1 @@
1
+ export { PopupContent } from '../compositional/popup-content';
@@ -0,0 +1 @@
1
+ export { PopupTrigger } from '../compositional/popup-trigger';
@@ -0,0 +1 @@
1
+ export { Popup } from '../compositional/popup';
@@ -0,0 +1 @@
1
+ export { Popup } from '../popup';
File without changes
@@ -0,0 +1,51 @@
1
+ import { useMemo } from 'react';
2
+
3
+ /**
4
+ * Props shape passed from legacy `role` / `label` / `titleId` into `@atlaskit/top-layer` `Popup.Content`.
5
+ */
6
+
7
+ /**
8
+ * Maps legacy popup role/label/titleId props to the discriminated union
9
+ * that `Popup.Content` expects.
10
+ *
11
+ * `Popup.Content` enforces at the type level that dialog/alertdialog/menu
12
+ * roles must have `label` or `labelledBy`. This hook bridges the legacy
13
+ * flat-prop API (`role`, `label`, `titleId`) to that shape.
14
+ */
15
+ export function useRoleProps({
16
+ role,
17
+ label,
18
+ titleId
19
+ }) {
20
+ return useMemo(() => {
21
+ if (role === 'dialog' || role === 'alertdialog' || role === 'menu') {
22
+ if (titleId) {
23
+ return {
24
+ role: role,
25
+ labelledBy: titleId
26
+ };
27
+ }
28
+ return {
29
+ role: role,
30
+ label: label !== null && label !== void 0 ? label : 'Popup'
31
+ };
32
+ }
33
+ if (role) {
34
+ return {
35
+ role: role,
36
+ label
37
+ };
38
+ }
39
+ // Default: dialog role with label or labelledBy
40
+ if (titleId) {
41
+ return {
42
+ role: 'dialog',
43
+ labelledBy: titleId
44
+ };
45
+ }
46
+ return {
47
+ role: 'dialog',
48
+ label: label !== null && label !== void 0 ? label : 'Popup'
49
+ };
50
+ }, [role, label, titleId]);
51
+ }