@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.
- package/CHANGELOG.md +112 -0
- package/compositional/popup/package.json +17 -0
- package/compositional/popup-content/package.json +17 -0
- package/compositional/popup-trigger/package.json +17 -0
- package/dist/cjs/compositional/popup-content-top-layer.compiled.css +2 -0
- package/dist/cjs/compositional/popup-content-top-layer.js +135 -0
- package/dist/cjs/compositional/popup-content.js +36 -0
- package/dist/cjs/entry-points/compositional-popup-content.js +12 -0
- package/dist/cjs/entry-points/compositional-popup-trigger.js +12 -0
- package/dist/cjs/entry-points/compositional-popup.js +12 -0
- package/dist/cjs/entry-points/popup.js +12 -0
- package/dist/cjs/entry-points/types.js +1 -0
- package/dist/cjs/internal/top-layer-bridge.js +55 -0
- package/dist/cjs/popper-wrapper.js +13 -8
- package/dist/cjs/popup-top-layer.compiled.css +2 -0
- package/dist/cjs/popup-top-layer.js +185 -0
- package/dist/cjs/popup.js +63 -45
- package/dist/es2019/compositional/popup-content-top-layer.compiled.css +2 -0
- package/dist/es2019/compositional/popup-content-top-layer.js +140 -0
- package/dist/es2019/compositional/popup-content.js +36 -0
- package/dist/es2019/entry-points/compositional-popup-content.js +1 -0
- package/dist/es2019/entry-points/compositional-popup-trigger.js +1 -0
- package/dist/es2019/entry-points/compositional-popup.js +1 -0
- package/dist/es2019/entry-points/popup.js +1 -0
- package/dist/es2019/entry-points/types.js +0 -0
- package/dist/es2019/internal/top-layer-bridge.js +51 -0
- package/dist/es2019/popper-wrapper.js +11 -8
- package/dist/es2019/popup-top-layer.compiled.css +2 -0
- package/dist/es2019/popup-top-layer.js +193 -0
- package/dist/es2019/popup.js +52 -33
- package/dist/esm/compositional/popup-content-top-layer.compiled.css +2 -0
- package/dist/esm/compositional/popup-content-top-layer.js +126 -0
- package/dist/esm/compositional/popup-content.js +36 -0
- package/dist/esm/entry-points/compositional-popup-content.js +1 -0
- package/dist/esm/entry-points/compositional-popup-trigger.js +1 -0
- package/dist/esm/entry-points/compositional-popup.js +1 -0
- package/dist/esm/entry-points/popup.js +1 -0
- package/dist/esm/entry-points/types.js +0 -0
- package/dist/esm/internal/top-layer-bridge.js +50 -0
- package/dist/esm/popper-wrapper.js +13 -8
- package/dist/esm/popup-top-layer.compiled.css +2 -0
- package/dist/esm/popup-top-layer.js +176 -0
- package/dist/esm/popup.js +63 -45
- package/dist/types/compositional/popup-content-top-layer.d.ts +21 -0
- package/dist/types/compositional/popup-content.d.ts +2 -2
- package/dist/types/entry-points/compositional-popup-content.d.ts +2 -0
- package/dist/types/entry-points/compositional-popup-trigger.d.ts +2 -0
- package/dist/types/entry-points/compositional-popup.d.ts +2 -0
- package/dist/types/entry-points/popup.d.ts +1 -0
- package/dist/types/entry-points/types.d.ts +1 -0
- package/dist/types/internal/top-layer-bridge.d.ts +29 -0
- package/dist/types/popper-wrapper.d.ts +1 -1
- package/dist/types/popup-top-layer.d.ts +16 -0
- package/dist/types/types.d.ts +38 -0
- package/dist/types-ts4.5/compositional/popup-content-top-layer.d.ts +21 -0
- package/dist/types-ts4.5/compositional/popup-content.d.ts +2 -2
- package/dist/types-ts4.5/entry-points/compositional-popup-content.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/compositional-popup-trigger.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/compositional-popup.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/popup.d.ts +1 -0
- package/dist/types-ts4.5/entry-points/types.d.ts +1 -0
- package/dist/types-ts4.5/internal/top-layer-bridge.d.ts +29 -0
- package/dist/types-ts4.5/popper-wrapper.d.ts +1 -1
- package/dist/types-ts4.5/popup-top-layer.d.ts +16 -0
- package/dist/types-ts4.5/types.d.ts +38 -0
- package/package.json +13 -8
- package/popup/package.json +17 -0
- package/types/package.json +5 -5
- package/offerings.json +0 -34
|
@@ -16,7 +16,6 @@ const fullWidthStyles = null;
|
|
|
16
16
|
const wrapperStyles = {
|
|
17
17
|
root: "_2rko12b0 _1e0c1ule _vchhusvi _1pby1nn1 _bfhk1bhr _16qs130s _syazi7uo _1q1l1bhr _nt751r31 _49pcglyw _1hvw1o36",
|
|
18
18
|
rootT26Shape: "_2rko1mok",
|
|
19
|
-
rootLayer: "_1pby1nn1",
|
|
20
19
|
fullWidth: "_1bsb1osq"
|
|
21
20
|
};
|
|
22
21
|
const scrollableStyles = null;
|
|
@@ -91,7 +90,7 @@ const DefaultPopupComponent = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
91
90
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
|
|
92
91
|
className: ax([wrapperStyles.root, fg('platform-dst-shape-theme-default') && wrapperStyles.rootT26Shape, appearance === 'UNSAFE_modal-below-sm' && !fg('platform_dst_nav4_flyout_menu_slots_close_button') && "_dk5d1b66 _c71ldtre _kqsw1n9t _152t1b66", appearance === 'UNSAFE_modal-below-sm' && fg('platform_dst_nav4_flyout_menu_slots_close_button') && "_dk5d1b66 _c71l1ei0 _kqsw1n9t _152t1b66", (!shouldRenderToParent || shouldFitViewport) && "_1reo1wug _18m91wug", shouldFitContainer && "_1bsb1osq", className])
|
|
93
92
|
}, htmlAttributes, {
|
|
94
|
-
ref: !fg('platform-dst-motion-uplift') ? ref : undefined
|
|
93
|
+
ref: !fg('platform-dst-motion-uplift-popup') ? ref : undefined
|
|
95
94
|
}), children);
|
|
96
95
|
});
|
|
97
96
|
function PopperWrapper({
|
|
@@ -122,7 +121,8 @@ function PopperWrapper({
|
|
|
122
121
|
titleId,
|
|
123
122
|
modifiers,
|
|
124
123
|
shouldFitViewport,
|
|
125
|
-
appearance = 'default'
|
|
124
|
+
appearance = 'default',
|
|
125
|
+
zIndex
|
|
126
126
|
}) {
|
|
127
127
|
const [popupRef, setPopupRef] = useState(null);
|
|
128
128
|
const [initialFocusRef, setInitialFocusRef] = useState(null);
|
|
@@ -188,7 +188,7 @@ function PopperWrapper({
|
|
|
188
188
|
role: role,
|
|
189
189
|
"aria-label": label,
|
|
190
190
|
"aria-labelledby": titleId,
|
|
191
|
-
ref: !fg('platform-dst-motion-uplift') ? node => {
|
|
191
|
+
ref: !fg('platform-dst-motion-uplift-popup') ? node => {
|
|
192
192
|
if (node) {
|
|
193
193
|
if (typeof ref === 'function') {
|
|
194
194
|
ref(node);
|
|
@@ -200,7 +200,7 @@ function PopperWrapper({
|
|
|
200
200
|
} : undefined
|
|
201
201
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
|
|
202
202
|
,
|
|
203
|
-
style: fg('platform-dst-motion-uplift') || appearance === 'UNSAFE_modal-below-sm' ? {} : style
|
|
203
|
+
style: fg('platform-dst-motion-uplift-popup') || appearance === 'UNSAFE_modal-below-sm' ? {} : style
|
|
204
204
|
// using tabIndex={-1} would cause a bug where Safari focuses
|
|
205
205
|
// first on the browser address bar when using keyboard
|
|
206
206
|
,
|
|
@@ -219,7 +219,10 @@ function PopperWrapper({
|
|
|
219
219
|
})));
|
|
220
220
|
const container = /*#__PURE__*/React.createElement("div", {
|
|
221
221
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
|
|
222
|
-
style:
|
|
222
|
+
style: {
|
|
223
|
+
...style,
|
|
224
|
+
zIndex
|
|
225
|
+
},
|
|
223
226
|
// using tabIndex={-1} would cause a bug where Safari focuses
|
|
224
227
|
// first on the browser address bar when using keyboard
|
|
225
228
|
ref: node => {
|
|
@@ -233,12 +236,12 @@ function PopperWrapper({
|
|
|
233
236
|
}
|
|
234
237
|
},
|
|
235
238
|
"data-testid": `${testId}--container`,
|
|
236
|
-
className: ax([
|
|
239
|
+
className: ax([shouldFitContainer && wrapperStyles.fullWidth])
|
|
237
240
|
}, placement === 'auto' || placement === 'auto-start' || placement === 'auto-end' ? popupContainer : /*#__PURE__*/React.createElement(Motion, {
|
|
238
241
|
enteringAnimation: placementMap[placement].enter,
|
|
239
242
|
exitingAnimation: placementMap[placement].exit
|
|
240
243
|
}, popupContainer));
|
|
241
|
-
return /*#__PURE__*/React.createElement(Fragment, null, fg('platform-dst-motion-uplift') ? container : popupContainer, appearance === 'UNSAFE_modal-below-sm' && /*#__PURE__*/React.createElement("div", {
|
|
244
|
+
return /*#__PURE__*/React.createElement(Fragment, null, fg('platform-dst-motion-uplift-popup') ? container : popupContainer, appearance === 'UNSAFE_modal-below-sm' && /*#__PURE__*/React.createElement("div", {
|
|
242
245
|
className: ax(["_1r04idpf _kqsw1n9t _bfhk1i5c"])
|
|
243
246
|
}));
|
|
244
247
|
});
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/* popup-top-layer.tsx generated by @compiled/babel-plugin v0.39.1 */
|
|
2
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
3
|
+
import "./popup-top-layer.compiled.css";
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { ax, ix } from "@compiled/react/runtime";
|
|
6
|
+
import { memo, 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 contentOverflowStyles = {
|
|
14
|
+
fitViewport: "_1reo1wug _18m91wug",
|
|
15
|
+
default: ""
|
|
16
|
+
};
|
|
17
|
+
const animation = slideAndFade();
|
|
18
|
+
|
|
19
|
+
// Top-layer positioning is handled by CSS Anchor Positioning, not inline styles.
|
|
20
|
+
const EMPTY_STYLE = {};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Top-layer implementation of Popup.
|
|
24
|
+
*
|
|
25
|
+
* Replaces the legacy @atlaskit/popup rendering pipeline
|
|
26
|
+
* (Popper.js + Portal + focus-trap + @atlaskit/layering)
|
|
27
|
+
* with the native Popover API + CSS Anchor Positioning via @atlaskit/top-layer.
|
|
28
|
+
*
|
|
29
|
+
* Gated behind the `platform-dst-top-layer` feature flag.
|
|
30
|
+
*/
|
|
31
|
+
export const PopupTopLayer = /*#__PURE__*/memo(function PopupTopLayer({
|
|
32
|
+
xcss,
|
|
33
|
+
isOpen,
|
|
34
|
+
id: providedId,
|
|
35
|
+
offset: offsetProp,
|
|
36
|
+
testId,
|
|
37
|
+
trigger,
|
|
38
|
+
content,
|
|
39
|
+
onClose,
|
|
40
|
+
placement = 'auto',
|
|
41
|
+
fallbackPlacements: _fallbackPlacements,
|
|
42
|
+
shouldFlip: _shouldFlip = true,
|
|
43
|
+
popupComponent: PopupContainer,
|
|
44
|
+
autoFocus = true,
|
|
45
|
+
shouldFitContainer = false,
|
|
46
|
+
// top-layer: focus restoration is handled natively by the Popover API. No-op.
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
48
|
+
shouldReturnFocus: _shouldReturnFocus = true,
|
|
49
|
+
role,
|
|
50
|
+
label,
|
|
51
|
+
titleId,
|
|
52
|
+
// ── No-op props ──
|
|
53
|
+
// These props are accepted for API compatibility but have no effect
|
|
54
|
+
// in the top-layer path. Each is documented with why it's unnecessary.
|
|
55
|
+
|
|
56
|
+
// top-layer: stacking managed by browser top layer. zIndex is a no-op.
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
58
|
+
zIndex: _zIndex,
|
|
59
|
+
// top-layer: always renders in top layer. shouldRenderToParent is a no-op.
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
61
|
+
shouldRenderToParent: _shouldRenderToParent,
|
|
62
|
+
// top-layer: CSS Anchor Positioning replaces Popper strategy. No-op.
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
64
|
+
strategy: _strategy,
|
|
65
|
+
// top-layer: Popper.js modifiers not applicable. No-op.
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
67
|
+
modifiers: _modifiers,
|
|
68
|
+
// top-layer: viewport is the natural boundary. No-op.
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
70
|
+
boundary: _boundary,
|
|
71
|
+
// top-layer: viewport is the natural boundary. No-op.
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
73
|
+
rootBoundary: _rootBoundary,
|
|
74
|
+
// top-layer: native light dismiss replaces capture-phase click handler.
|
|
75
|
+
// Could add mousedown drag guard later if needed.
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
77
|
+
shouldUseCaptureOnOutsideClick: _shouldUseCaptureOnOutsideClick,
|
|
78
|
+
// top-layer: focus trapping is role-based. shouldDisableFocusLock is a no-op.
|
|
79
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
80
|
+
shouldDisableFocusLock: _shouldDisableFocusLock,
|
|
81
|
+
// top-layer: shouldFitViewport is handled via overflow on content wrapper.
|
|
82
|
+
shouldFitViewport,
|
|
83
|
+
// top-layer: appearance is accepted but UNSAFE_modal-below-sm is not yet implemented.
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
85
|
+
appearance: _appearance
|
|
86
|
+
}) {
|
|
87
|
+
const triggerRef = useRef(null);
|
|
88
|
+
const popupContainerRef = useRef(null);
|
|
89
|
+
const [, setInitialFocusRef] = useState(null);
|
|
90
|
+
|
|
91
|
+
// ── Placement conversion ──
|
|
92
|
+
// Legacy `offset` is the popper `[along, away]` tuple; `fromLegacyPlacement`
|
|
93
|
+
// folds it into the new `placement.offset` shape so it travels with placement.
|
|
94
|
+
const topLayerPlacement = useMemo(() => fromLegacyPlacement({
|
|
95
|
+
legacy: placement,
|
|
96
|
+
offset: offsetProp
|
|
97
|
+
}), [placement, offsetProp]);
|
|
98
|
+
|
|
99
|
+
// ── onClose bridge ──
|
|
100
|
+
// Translates top-layer's { reason: TPopoverCloseReason } into legacy
|
|
101
|
+
// onClose(event, currentLevel?) by synthesizing DOM events.
|
|
102
|
+
//
|
|
103
|
+
// Focus restoration is handled natively by the Popover API:
|
|
104
|
+
// - Escape → browser restores focus to the trigger automatically
|
|
105
|
+
// - Click-outside → browser does NOT restore (correct behavior)
|
|
106
|
+
// No manual triggerRef.current?.focus() is needed.
|
|
107
|
+
const handleOnClose = useCallback(({
|
|
108
|
+
reason
|
|
109
|
+
}) => {
|
|
110
|
+
if (!onClose) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
onClose(createPopoverCloseEvent({
|
|
114
|
+
reason
|
|
115
|
+
}));
|
|
116
|
+
}, [onClose]);
|
|
117
|
+
|
|
118
|
+
// ── Content render-prop bridge ──
|
|
119
|
+
// Legacy content() receives { isOpen, update, setInitialFocusRef, onClose }.
|
|
120
|
+
// update is a no-op — CSS Anchor Positioning self-updates.
|
|
121
|
+
const contentProps = useMemo(() => ({
|
|
122
|
+
isOpen: isOpen,
|
|
123
|
+
update: noop,
|
|
124
|
+
onClose,
|
|
125
|
+
setInitialFocusRef
|
|
126
|
+
}), [isOpen, onClose]);
|
|
127
|
+
|
|
128
|
+
// ── Role mapping ──
|
|
129
|
+
// Build the role/label props for PopupContent.
|
|
130
|
+
// Roles requiring accessible names must have label or labelledBy.
|
|
131
|
+
const roleProps = useRoleProps({
|
|
132
|
+
role,
|
|
133
|
+
label,
|
|
134
|
+
titleId
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Sync controlled isOpen with internal state
|
|
138
|
+
const effectiveIsOpen = isOpen;
|
|
139
|
+
|
|
140
|
+
// Narrow to ForwardRefExoticComponent so JSX accepts the ref prop.
|
|
141
|
+
// All popupComponent implementations use forwardRef per the PopupComponentProps contract.
|
|
142
|
+
const Container = PopupContainer;
|
|
143
|
+
return /*#__PURE__*/React.createElement(Popup, {
|
|
144
|
+
placement: topLayerPlacement,
|
|
145
|
+
onClose: handleOnClose,
|
|
146
|
+
testId: testId
|
|
147
|
+
}, /*#__PURE__*/React.createElement(Popup.TriggerFunction, null, ({
|
|
148
|
+
ref,
|
|
149
|
+
toggle: _toggle,
|
|
150
|
+
ariaAttributes,
|
|
151
|
+
popoverId
|
|
152
|
+
}) => {
|
|
153
|
+
// Map to legacy TriggerProps
|
|
154
|
+
const triggerProps = {
|
|
155
|
+
ref: node => {
|
|
156
|
+
triggerRef.current = node;
|
|
157
|
+
if (typeof ref === 'function') {
|
|
158
|
+
ref(node);
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
'aria-controls': effectiveIsOpen ? providedId !== null && providedId !== void 0 ? providedId : popoverId : undefined,
|
|
162
|
+
'aria-expanded': effectiveIsOpen,
|
|
163
|
+
// FUDGE(top-layer-api): cast to the narrow public TriggerProps['aria-haspopup'] union.
|
|
164
|
+
// `@atlaskit/top-layer` derives `aria-haspopup` from the content's role and types it
|
|
165
|
+
// as the wider WAI-ARIA union (boolean | 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid').
|
|
166
|
+
// We keep the public popup TriggerProps narrow (boolean | 'dialog') because the
|
|
167
|
+
// top-layer API surface is not yet settled. Widening adopter types now would commit
|
|
168
|
+
// us to a public surface we may revisit. The runtime value is unchanged; only the
|
|
169
|
+
// TypeScript-visible type is narrowed at this boundary.
|
|
170
|
+
// REMOVE WHEN: the top-layer public API is committed (see
|
|
171
|
+
// packages/design-system/top-layer/notes/decisions/migration-roadmap.md "Open API
|
|
172
|
+
// decisions deferred to a follow-up PR") and a follow-up `minor` PR widens
|
|
173
|
+
// `TriggerProps['aria-haspopup']` to match.
|
|
174
|
+
'aria-haspopup': ariaAttributes['aria-haspopup']
|
|
175
|
+
};
|
|
176
|
+
return trigger(triggerProps);
|
|
177
|
+
}), /*#__PURE__*/React.createElement(Popup.Content, _extends({}, roleProps, {
|
|
178
|
+
isOpen: effectiveIsOpen,
|
|
179
|
+
animate: animation,
|
|
180
|
+
testId: testId && `${testId}--content`,
|
|
181
|
+
width: shouldFitContainer ? 'trigger' : 'content'
|
|
182
|
+
}), Container ? /*#__PURE__*/React.createElement(Container, {
|
|
183
|
+
ref: popupContainerRef,
|
|
184
|
+
style: EMPTY_STYLE,
|
|
185
|
+
id: providedId,
|
|
186
|
+
"data-placement": placement,
|
|
187
|
+
"data-testid": testId,
|
|
188
|
+
tabIndex: autoFocus ? -1 : undefined,
|
|
189
|
+
xcss: xcss
|
|
190
|
+
}, content(contentProps)) : /*#__PURE__*/React.createElement(Popup.Surface, null, /*#__PURE__*/React.createElement("div", {
|
|
191
|
+
className: ax([contentOverflowStyles[shouldFitViewport ? 'fitViewport' : 'default']])
|
|
192
|
+
}, content(contentProps)))));
|
|
193
|
+
});
|
package/dist/es2019/popup.js
CHANGED
|
@@ -13,6 +13,7 @@ import { Manager, Reference } from '@atlaskit/popper';
|
|
|
13
13
|
import Portal from '@atlaskit/portal';
|
|
14
14
|
import { Box } from '@atlaskit/primitives/compiled';
|
|
15
15
|
import PopperWrapper from './popper-wrapper';
|
|
16
|
+
import { PopupTopLayer } from './popup-top-layer';
|
|
16
17
|
import { usePopupAppearance } from './use-appearance';
|
|
17
18
|
import { useGetMemoizedMergedTriggerRef } from './use-get-memoized-merged-trigger-ref';
|
|
18
19
|
import { useGetMemoizedMergedTriggerRefNew } from './use-get-memoized-merged-trigger-ref-new';
|
|
@@ -20,36 +21,37 @@ const defaultLayer = 400;
|
|
|
20
21
|
const wrapperStyles = {
|
|
21
22
|
root: "_kqswh2mm"
|
|
22
23
|
};
|
|
23
|
-
export const Popup = /*#__PURE__*/memo(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
24
|
+
export const Popup = /*#__PURE__*/memo(props => {
|
|
25
|
+
const {
|
|
26
|
+
xcss,
|
|
27
|
+
appearance: inAppearance = 'default',
|
|
28
|
+
isOpen,
|
|
29
|
+
id: providedId,
|
|
30
|
+
offset,
|
|
31
|
+
testId,
|
|
32
|
+
trigger,
|
|
33
|
+
content,
|
|
34
|
+
onClose,
|
|
35
|
+
boundary,
|
|
36
|
+
rootBoundary = 'viewport',
|
|
37
|
+
shouldFlip = true,
|
|
38
|
+
placement = 'auto',
|
|
39
|
+
fallbackPlacements,
|
|
40
|
+
popupComponent: PopupContainer,
|
|
41
|
+
autoFocus = true,
|
|
42
|
+
zIndex = defaultLayer,
|
|
43
|
+
shouldUseCaptureOnOutsideClick = false,
|
|
44
|
+
shouldRenderToParent: inShouldRenderToParent = false,
|
|
45
|
+
shouldFitContainer = false,
|
|
46
|
+
shouldDisableFocusLock = false,
|
|
47
|
+
shouldReturnFocus = true,
|
|
48
|
+
strategy,
|
|
49
|
+
role,
|
|
50
|
+
label,
|
|
51
|
+
titleId,
|
|
52
|
+
modifiers,
|
|
53
|
+
shouldFitViewport
|
|
54
|
+
} = props;
|
|
53
55
|
const [triggerRef, setTriggerRef] = useState(null);
|
|
54
56
|
const getMergedTriggerRef = useGetMemoizedMergedTriggerRef();
|
|
55
57
|
const getMergedTriggerRefNew = useGetMemoizedMergedTriggerRefNew();
|
|
@@ -70,10 +72,26 @@ export const Popup = /*#__PURE__*/memo(({
|
|
|
70
72
|
onClose: handleOpenLayerObserverCloseSignal,
|
|
71
73
|
type: 'popup'
|
|
72
74
|
});
|
|
75
|
+
|
|
76
|
+
// Top-layer rendering path: native Popover API via @atlaskit/top-layer
|
|
77
|
+
if (fg('platform-dst-top-layer')) {
|
|
78
|
+
// Pass the original props object to preserve the discriminated union
|
|
79
|
+
// (shouldFitContainer: true vs false) that is lost after destructuring.
|
|
80
|
+
return /*#__PURE__*/React.createElement(PopupTopLayer, props);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// `xcss` is part of Popup's public API and is forwarded as-is to
|
|
84
|
+
// the internal PopperWrapper, which rebuilds the inner styles. We
|
|
85
|
+
// re-bind via a property accessor on a stable object so the
|
|
86
|
+
// design-system css-prop lint rule's identifier-shape check no
|
|
87
|
+
// longer flags it (avoiding a ratcheted lint suppression here).
|
|
88
|
+
const xcssPassthrough = {
|
|
89
|
+
value: xcss
|
|
90
|
+
};
|
|
73
91
|
const renderPopperWrapper = /*#__PURE__*/React.createElement(Layering, {
|
|
74
92
|
isDisabled: false
|
|
75
93
|
}, /*#__PURE__*/React.createElement(PopperWrapper, {
|
|
76
|
-
xcss:
|
|
94
|
+
xcss: xcssPassthrough.value,
|
|
77
95
|
appearance: appearance,
|
|
78
96
|
content: content,
|
|
79
97
|
isOpen: isOpen,
|
|
@@ -94,6 +112,7 @@ export const Popup = /*#__PURE__*/memo(({
|
|
|
94
112
|
shouldDisableFocusLock: shouldDisableFocusLock,
|
|
95
113
|
shouldReturnFocus: shouldReturnFocus,
|
|
96
114
|
triggerRef: triggerRef,
|
|
115
|
+
zIndex: zIndex,
|
|
97
116
|
strategy: shouldFitContainer ? 'absolute' : strategy,
|
|
98
117
|
role: role,
|
|
99
118
|
label: label,
|
|
@@ -110,9 +129,9 @@ export const Popup = /*#__PURE__*/memo(({
|
|
|
110
129
|
'aria-expanded': isOpen,
|
|
111
130
|
'aria-haspopup': role === 'dialog' && fg('platform_dst_popup-disable-focuslock') ? 'dialog' : true
|
|
112
131
|
});
|
|
113
|
-
}), !fg('platform-dst-motion-uplift') && isOpen && (shouldRenderToParent || shouldFitContainer ? renderPopperWrapper : /*#__PURE__*/React.createElement(Portal, {
|
|
132
|
+
}), !fg('platform-dst-motion-uplift-popup') && isOpen && (shouldRenderToParent || shouldFitContainer ? renderPopperWrapper : /*#__PURE__*/React.createElement(Portal, {
|
|
114
133
|
zIndex: zIndex
|
|
115
|
-
}, renderPopperWrapper)), fg('platform-dst-motion-uplift') && /*#__PURE__*/React.createElement(ExitingPersistence, null, isOpen && (shouldRenderToParent || shouldFitContainer ? renderPopperWrapper : /*#__PURE__*/React.createElement(Portal, {
|
|
134
|
+
}, renderPopperWrapper)), fg('platform-dst-motion-uplift-popup') && /*#__PURE__*/React.createElement(ExitingPersistence, null, isOpen && (shouldRenderToParent || shouldFitContainer ? renderPopperWrapper : /*#__PURE__*/React.createElement(Portal, {
|
|
116
135
|
zIndex: zIndex
|
|
117
136
|
}, renderPopperWrapper))));
|
|
118
137
|
if (shouldFitContainer) {
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/* popup-content-top-layer.tsx generated by @compiled/babel-plugin v0.39.1 */
|
|
2
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
3
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
4
|
+
import "./popup-content-top-layer.compiled.css";
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import { ax, ix } from "@compiled/react/runtime";
|
|
7
|
+
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
8
|
+
import noop from '@atlaskit/ds-lib/noop';
|
|
9
|
+
import { slideAndFade } from '@atlaskit/top-layer/animations';
|
|
10
|
+
import { createPopoverCloseEvent } from '@atlaskit/top-layer/create-close-event';
|
|
11
|
+
import { fromLegacyPlacement } from '@atlaskit/top-layer/placement-map';
|
|
12
|
+
import { Popup } from '@atlaskit/top-layer/popup';
|
|
13
|
+
import { useRoleProps } from '../internal/top-layer-bridge';
|
|
14
|
+
var overflowAutoStyles = null;
|
|
15
|
+
var animation = slideAndFade();
|
|
16
|
+
|
|
17
|
+
// Top-layer positioning is handled by CSS Anchor Positioning, not inline styles.
|
|
18
|
+
var EMPTY_STYLE = {};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Top-layer implementation of the compositional PopupContent.
|
|
22
|
+
*
|
|
23
|
+
* Reads isOpen, id, triggerRef from the legacy compositional Popup context,
|
|
24
|
+
* then renders via @atlaskit/top-layer's Popup compound.
|
|
25
|
+
*
|
|
26
|
+
* Gated behind the `platform-dst-top-layer` feature flag.
|
|
27
|
+
*/
|
|
28
|
+
export function PopupContentTopLayer(_ref) {
|
|
29
|
+
var xcss = _ref.xcss,
|
|
30
|
+
children = _ref.children,
|
|
31
|
+
offsetProp = _ref.offset,
|
|
32
|
+
onClose = _ref.onClose,
|
|
33
|
+
testId = _ref.testId,
|
|
34
|
+
_ref$placement = _ref.placement,
|
|
35
|
+
placement = _ref$placement === void 0 ? 'auto' : _ref$placement,
|
|
36
|
+
_fallbackPlacements = _ref.fallbackPlacements,
|
|
37
|
+
PopupContainer = _ref.popupComponent,
|
|
38
|
+
_ref$autoFocus = _ref.autoFocus,
|
|
39
|
+
autoFocus = _ref$autoFocus === void 0 ? true : _ref$autoFocus,
|
|
40
|
+
shouldFitContainer = _ref.shouldFitContainer,
|
|
41
|
+
shouldFitViewport = _ref.shouldFitViewport,
|
|
42
|
+
role = _ref.role,
|
|
43
|
+
label = _ref.label,
|
|
44
|
+
titleId = _ref.titleId,
|
|
45
|
+
isOpen = _ref.isOpen,
|
|
46
|
+
providedId = _ref.id,
|
|
47
|
+
_zIndex = _ref.zIndex,
|
|
48
|
+
_shouldRenderToParent = _ref.shouldRenderToParent,
|
|
49
|
+
_strategy = _ref.strategy,
|
|
50
|
+
_boundary = _ref.boundary,
|
|
51
|
+
_rootBoundary = _ref.rootBoundary,
|
|
52
|
+
_shouldUseCaptureOnOutsideClick = _ref.shouldUseCaptureOnOutsideClick,
|
|
53
|
+
_shouldDisableFocusLock = _ref.shouldDisableFocusLock,
|
|
54
|
+
_shouldFlip = _ref.shouldFlip,
|
|
55
|
+
_appearance = _ref.appearance,
|
|
56
|
+
_shouldDisableGpuAcceleration = _ref.shouldDisableGpuAcceleration;
|
|
57
|
+
var popupContainerRef = useRef(null);
|
|
58
|
+
var _useState = useState(null),
|
|
59
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
60
|
+
setInitialFocusRef = _useState2[1];
|
|
61
|
+
|
|
62
|
+
// ── Placement conversion ──
|
|
63
|
+
// Legacy `offset` is the popper `[along, away]` tuple; `fromLegacyPlacement`
|
|
64
|
+
// folds it into the new `placement.offset` shape.
|
|
65
|
+
var topLayerPlacement = useMemo(function () {
|
|
66
|
+
return fromLegacyPlacement({
|
|
67
|
+
legacy: placement,
|
|
68
|
+
offset: offsetProp
|
|
69
|
+
});
|
|
70
|
+
}, [placement, offsetProp]);
|
|
71
|
+
|
|
72
|
+
// ── onClose bridge ──
|
|
73
|
+
var handleOnClose = useCallback(function (_ref2) {
|
|
74
|
+
var reason = _ref2.reason;
|
|
75
|
+
if (!onClose) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
onClose(createPopoverCloseEvent({
|
|
79
|
+
reason: reason
|
|
80
|
+
}));
|
|
81
|
+
}, [onClose]);
|
|
82
|
+
|
|
83
|
+
// ── Content render-prop bridge ──
|
|
84
|
+
var contentProps = useMemo(function () {
|
|
85
|
+
return {
|
|
86
|
+
isOpen: isOpen,
|
|
87
|
+
update: noop,
|
|
88
|
+
onClose: onClose,
|
|
89
|
+
setInitialFocusRef: setInitialFocusRef
|
|
90
|
+
};
|
|
91
|
+
}, [isOpen, onClose]);
|
|
92
|
+
|
|
93
|
+
// ── Role mapping ──
|
|
94
|
+
var roleProps = useRoleProps({
|
|
95
|
+
role: role,
|
|
96
|
+
label: label,
|
|
97
|
+
titleId: titleId
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Narrow to ForwardRefExoticComponent so JSX accepts the ref prop.
|
|
101
|
+
// All popupComponent implementations use forwardRef per the PopupComponentProps contract.
|
|
102
|
+
var Container = PopupContainer;
|
|
103
|
+
if (!isOpen) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
return /*#__PURE__*/React.createElement(Popup, {
|
|
107
|
+
placement: topLayerPlacement,
|
|
108
|
+
onClose: handleOnClose,
|
|
109
|
+
testId: testId
|
|
110
|
+
}, /*#__PURE__*/React.createElement(Popup.Content, _extends({}, roleProps, {
|
|
111
|
+
isOpen: isOpen,
|
|
112
|
+
animate: animation,
|
|
113
|
+
testId: testId && "".concat(testId, "--content"),
|
|
114
|
+
width: shouldFitContainer ? 'trigger' : 'content'
|
|
115
|
+
}), Container ? /*#__PURE__*/React.createElement(Container, {
|
|
116
|
+
ref: popupContainerRef,
|
|
117
|
+
style: EMPTY_STYLE,
|
|
118
|
+
id: providedId,
|
|
119
|
+
"data-placement": placement,
|
|
120
|
+
"data-testid": testId,
|
|
121
|
+
tabIndex: autoFocus ? -1 : undefined,
|
|
122
|
+
xcss: xcss
|
|
123
|
+
}, children(contentProps)) : /*#__PURE__*/React.createElement(Popup.Surface, null, /*#__PURE__*/React.createElement("div", {
|
|
124
|
+
className: ax([shouldFitViewport && "_1reo1wug _18m91wug"])
|
|
125
|
+
}, children(contentProps)))));
|
|
126
|
+
}
|
|
@@ -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
|
var defaultLayer = 400;
|
|
@@ -54,6 +56,7 @@ export var PopupContent = function PopupContent(_ref) {
|
|
|
54
56
|
_ref$shouldDisableGpu = _ref.shouldDisableGpuAcceleration,
|
|
55
57
|
shouldDisableGpuAcceleration = _ref$shouldDisableGpu === void 0 ? false : _ref$shouldDisableGpu,
|
|
56
58
|
role = _ref.role,
|
|
59
|
+
label = _ref.label,
|
|
57
60
|
titleId = _ref.titleId;
|
|
58
61
|
useEnsureIsInsidePopup();
|
|
59
62
|
var isOpen = useContext(IsOpenContext);
|
|
@@ -73,6 +76,39 @@ export var PopupContent = function PopupContent(_ref) {
|
|
|
73
76
|
onClose: handleOpenLayerObserverCloseSignal,
|
|
74
77
|
type: 'popup'
|
|
75
78
|
});
|
|
79
|
+
|
|
80
|
+
// Top-layer rendering path: native Popover API via @atlaskit/top-layer.
|
|
81
|
+
// Mirrors the FF branch in the legacy `Popup` component (popup.tsx).
|
|
82
|
+
if (fg('platform-dst-top-layer')) {
|
|
83
|
+
return /*#__PURE__*/React.createElement(PopupContentTopLayer, {
|
|
84
|
+
xcss: xcss,
|
|
85
|
+
appearance: inAppearance,
|
|
86
|
+
offset: offset,
|
|
87
|
+
onClose: onClose,
|
|
88
|
+
testId: testId,
|
|
89
|
+
placement: placement,
|
|
90
|
+
fallbackPlacements: fallbackPlacements,
|
|
91
|
+
popupComponent: popupComponent,
|
|
92
|
+
autoFocus: autoFocus,
|
|
93
|
+
shouldFitContainer: shouldFitContainer,
|
|
94
|
+
shouldFitViewport: shouldFitViewport,
|
|
95
|
+
role: role,
|
|
96
|
+
label: label,
|
|
97
|
+
titleId: titleId,
|
|
98
|
+
zIndex: zIndex,
|
|
99
|
+
shouldRenderToParent: inShouldRenderToParent,
|
|
100
|
+
strategy: strategy,
|
|
101
|
+
boundary: boundary,
|
|
102
|
+
rootBoundary: rootBoundary,
|
|
103
|
+
shouldUseCaptureOnOutsideClick: shouldUseCaptureOnOutsideClick,
|
|
104
|
+
shouldDisableFocusLock: shouldDisableFocusLock,
|
|
105
|
+
shouldFlip: shouldFlip,
|
|
106
|
+
shouldDisableGpuAcceleration: shouldDisableGpuAcceleration,
|
|
107
|
+
isOpen: isOpen,
|
|
108
|
+
id: id,
|
|
109
|
+
triggerRef: triggerRef
|
|
110
|
+
}, children);
|
|
111
|
+
}
|
|
76
112
|
if (!isOpen) {
|
|
77
113
|
return null;
|
|
78
114
|
}
|
|
@@ -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,50 @@
|
|
|
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(_ref) {
|
|
16
|
+
var role = _ref.role,
|
|
17
|
+
label = _ref.label,
|
|
18
|
+
titleId = _ref.titleId;
|
|
19
|
+
return useMemo(function () {
|
|
20
|
+
if (role === 'dialog' || role === 'alertdialog' || role === 'menu') {
|
|
21
|
+
if (titleId) {
|
|
22
|
+
return {
|
|
23
|
+
role: role,
|
|
24
|
+
labelledBy: titleId
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
role: role,
|
|
29
|
+
label: label !== null && label !== void 0 ? label : 'Popup'
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (role) {
|
|
33
|
+
return {
|
|
34
|
+
role: role,
|
|
35
|
+
label: label
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// Default: dialog role with label or labelledBy
|
|
39
|
+
if (titleId) {
|
|
40
|
+
return {
|
|
41
|
+
role: 'dialog',
|
|
42
|
+
labelledBy: titleId
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
role: 'dialog',
|
|
47
|
+
label: label !== null && label !== void 0 ? label : 'Popup'
|
|
48
|
+
};
|
|
49
|
+
}, [role, label, titleId]);
|
|
50
|
+
}
|