@atlaskit/popup 4.23.1 → 4.23.3
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 +17 -0
- package/dist/cjs/compositional/popup-content-top-layer.js +3 -4
- package/dist/cjs/popup-top-layer.js +59 -54
- package/dist/es2019/compositional/popup-content-top-layer.js +3 -4
- package/dist/es2019/popup-top-layer.js +61 -57
- package/dist/esm/compositional/popup-content-top-layer.js +3 -4
- package/dist/esm/popup-top-layer.js +59 -54
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @atlaskit/popup
|
|
2
2
|
|
|
3
|
+
## 4.23.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`e5b4070f51a93`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/e5b4070f51a93) -
|
|
8
|
+
Remove Top Layer compatibility aliases and expose close-event helpers from the `dialog` and
|
|
9
|
+
`popover` entry points.
|
|
10
|
+
- Updated dependencies
|
|
11
|
+
|
|
12
|
+
## 4.23.2
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- [`021a645c6f39a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/021a645c6f39a) -
|
|
17
|
+
Update internal top-layer adopter code paths behind `platform-dst-top-layer`.
|
|
18
|
+
- Updated dependencies
|
|
19
|
+
|
|
3
20
|
## 4.23.1
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -15,10 +15,9 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
|
|
|
15
15
|
var _runtime = require("@compiled/react/runtime");
|
|
16
16
|
var _noop = _interopRequireDefault(require("@atlaskit/ds-lib/noop"));
|
|
17
17
|
var _animations = require("@atlaskit/top-layer/animations");
|
|
18
|
-
var _createCloseEvent = require("@atlaskit/top-layer/create-close-event");
|
|
19
18
|
var _placementMap = require("@atlaskit/top-layer/placement-map");
|
|
20
19
|
var _popover = require("@atlaskit/top-layer/popover");
|
|
21
|
-
var
|
|
20
|
+
var _popoverSurface = require("@atlaskit/top-layer/popover-surface");
|
|
22
21
|
var _useAnchorPosition = require("@atlaskit/top-layer/use-anchor-position");
|
|
23
22
|
var _useWidthFromAnchor = require("@atlaskit/top-layer/use-width-from-anchor");
|
|
24
23
|
var _topLayerBridge = require("../internal/top-layer-bridge");
|
|
@@ -87,7 +86,7 @@ function PopupContentTopLayer(_ref) {
|
|
|
87
86
|
if (!onClose) {
|
|
88
87
|
return;
|
|
89
88
|
}
|
|
90
|
-
onClose((0,
|
|
89
|
+
onClose((0, _popover.createPopoverCloseEvent)({
|
|
91
90
|
reason: reason
|
|
92
91
|
}));
|
|
93
92
|
}, [onClose]);
|
|
@@ -139,7 +138,7 @@ function PopupContentTopLayer(_ref) {
|
|
|
139
138
|
"data-testid": testId,
|
|
140
139
|
tabIndex: autoFocus ? -1 : undefined,
|
|
141
140
|
xcss: xcss
|
|
142
|
-
}, children(contentProps)) : /*#__PURE__*/React.createElement(
|
|
141
|
+
}, children(contentProps)) : /*#__PURE__*/React.createElement(_popoverSurface.PopoverSurface, null, /*#__PURE__*/React.createElement("div", {
|
|
143
142
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
|
|
144
143
|
className: (0, _runtime.ax)([shouldFitViewport && "_1reo1wug _18m91wug", (0, _runtime.ax)([xcss])])
|
|
145
144
|
}, children(contentProps))));
|
|
@@ -15,9 +15,13 @@ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")
|
|
|
15
15
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
16
16
|
var _noop = _interopRequireDefault(require("@atlaskit/ds-lib/noop"));
|
|
17
17
|
var _animations = require("@atlaskit/top-layer/animations");
|
|
18
|
-
var
|
|
18
|
+
var _getAriaForTrigger = require("@atlaskit/top-layer/get-aria-for-trigger");
|
|
19
19
|
var _placementMap = require("@atlaskit/top-layer/placement-map");
|
|
20
|
-
var
|
|
20
|
+
var _popover = require("@atlaskit/top-layer/popover");
|
|
21
|
+
var _popoverSurface = require("@atlaskit/top-layer/popover-surface");
|
|
22
|
+
var _useAnchorPosition = require("@atlaskit/top-layer/use-anchor-position");
|
|
23
|
+
var _usePopoverId = require("@atlaskit/top-layer/use-popover-id");
|
|
24
|
+
var _useWidthFromAnchor = require("@atlaskit/top-layer/use-width-from-anchor");
|
|
21
25
|
var _topLayerBridge = require("./internal/top-layer-bridge");
|
|
22
26
|
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
27
|
var contentOverflowStyles = {
|
|
@@ -39,6 +43,7 @@ var EMPTY_STYLE = {};
|
|
|
39
43
|
* Gated behind the `platform-dst-top-layer` feature flag.
|
|
40
44
|
*/
|
|
41
45
|
var PopupTopLayer = exports.PopupTopLayer = /*#__PURE__*/(0, _react.memo)(function PopupTopLayer(_ref) {
|
|
46
|
+
var _roleProps$role;
|
|
42
47
|
var xcss = _ref.xcss,
|
|
43
48
|
isOpen = _ref.isOpen,
|
|
44
49
|
providedId = _ref.id,
|
|
@@ -73,12 +78,14 @@ var PopupTopLayer = exports.PopupTopLayer = /*#__PURE__*/(0, _react.memo)(functi
|
|
|
73
78
|
shouldFitViewport = _ref.shouldFitViewport,
|
|
74
79
|
_appearance = _ref.appearance;
|
|
75
80
|
var triggerRef = (0, _react.useRef)(null);
|
|
81
|
+
var popoverRef = (0, _react.useRef)(null);
|
|
76
82
|
var popupContainerRef = (0, _react.useRef)(null);
|
|
77
83
|
var _useState = (0, _react.useState)(null),
|
|
78
84
|
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
79
85
|
setInitialFocusRef = _useState2[1];
|
|
86
|
+
var popoverId = (0, _usePopoverId.usePopoverId)();
|
|
80
87
|
|
|
81
|
-
//
|
|
88
|
+
// Placement conversion.
|
|
82
89
|
// Legacy `offset` is the popper `[along, away]` tuple; `fromLegacyPlacement`
|
|
83
90
|
// folds it into the new `placement.offset` shape so it travels with placement.
|
|
84
91
|
var topLayerPlacement = (0, _react.useMemo)(function () {
|
|
@@ -87,28 +94,38 @@ var PopupTopLayer = exports.PopupTopLayer = /*#__PURE__*/(0, _react.memo)(functi
|
|
|
87
94
|
offset: offsetProp
|
|
88
95
|
});
|
|
89
96
|
}, [placement, offsetProp]);
|
|
97
|
+
(0, _useAnchorPosition.useAnchorPosition)({
|
|
98
|
+
anchorRef: triggerRef,
|
|
99
|
+
popoverRef: popoverRef,
|
|
100
|
+
placement: topLayerPlacement
|
|
101
|
+
});
|
|
102
|
+
(0, _useWidthFromAnchor.useWidthFromAnchor)({
|
|
103
|
+
mode: shouldFitContainer ? 'match-anchor' : 'none',
|
|
104
|
+
popoverRef: popoverRef,
|
|
105
|
+
anchorRef: triggerRef
|
|
106
|
+
});
|
|
90
107
|
|
|
91
|
-
//
|
|
108
|
+
// onClose bridge.
|
|
92
109
|
// Translates top-layer's { reason: TPopoverCloseReason } into legacy
|
|
93
110
|
// onClose(event, currentLevel?) by synthesizing DOM events.
|
|
94
111
|
//
|
|
95
112
|
// Focus restoration is handled natively by the Popover API:
|
|
96
|
-
// - Escape
|
|
97
|
-
// - Click-outside
|
|
113
|
+
// - Escape: browser restores focus to the trigger automatically
|
|
114
|
+
// - Click-outside: browser does NOT restore (correct behavior)
|
|
98
115
|
// No manual triggerRef.current?.focus() is needed.
|
|
99
116
|
var handleOnClose = (0, _react.useCallback)(function (_ref2) {
|
|
100
117
|
var reason = _ref2.reason;
|
|
101
118
|
if (!onClose) {
|
|
102
119
|
return;
|
|
103
120
|
}
|
|
104
|
-
onClose((0,
|
|
121
|
+
onClose((0, _popover.createPopoverCloseEvent)({
|
|
105
122
|
reason: reason
|
|
106
123
|
}));
|
|
107
124
|
}, [onClose]);
|
|
108
125
|
|
|
109
|
-
//
|
|
126
|
+
// Content render-prop bridge.
|
|
110
127
|
// Legacy content() receives { isOpen, update, setInitialFocusRef, onClose }.
|
|
111
|
-
// update is a no-op
|
|
128
|
+
// update is a no-op because CSS Anchor Positioning self-updates.
|
|
112
129
|
var contentProps = (0, _react.useMemo)(function () {
|
|
113
130
|
return {
|
|
114
131
|
isOpen: isOpen,
|
|
@@ -118,62 +135,50 @@ var PopupTopLayer = exports.PopupTopLayer = /*#__PURE__*/(0, _react.memo)(functi
|
|
|
118
135
|
};
|
|
119
136
|
}, [isOpen, onClose]);
|
|
120
137
|
|
|
121
|
-
//
|
|
122
|
-
// Build the role/label props for
|
|
138
|
+
// Role mapping.
|
|
139
|
+
// Build the role/label props for Popover.
|
|
123
140
|
// Roles requiring accessible names must have label or labelledBy.
|
|
124
141
|
var roleProps = (0, _topLayerBridge.useRoleProps)({
|
|
125
142
|
role: role,
|
|
126
143
|
label: label,
|
|
127
144
|
titleId: titleId
|
|
128
145
|
});
|
|
146
|
+
var ariaAttributes = (0, _getAriaForTrigger.getAriaForTrigger)({
|
|
147
|
+
role: (_roleProps$role = roleProps.role) !== null && _roleProps$role !== void 0 ? _roleProps$role : 'dialog',
|
|
148
|
+
isOpen: isOpen,
|
|
149
|
+
popoverId: popoverId
|
|
150
|
+
});
|
|
129
151
|
|
|
130
152
|
// Narrow to ForwardRefExoticComponent so JSX accepts the ref prop.
|
|
131
153
|
// All popupComponent implementations use forwardRef per the PopupComponentProps contract.
|
|
132
154
|
var Container = PopupContainer;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
// - Consumers relying on aria-expanded to show/hide trigger UI don't lose the
|
|
156
|
-
// trigger (popup anchor) before the animation finishes.
|
|
157
|
-
'aria-expanded': ariaAttributes['aria-expanded'],
|
|
158
|
-
// FUDGE(top-layer-api): cast to the narrow public TriggerProps['aria-haspopup'] union.
|
|
159
|
-
// `@atlaskit/top-layer` derives `aria-haspopup` from the content's role and types it
|
|
160
|
-
// as the wider WAI-ARIA union (boolean | 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid').
|
|
161
|
-
// We keep the public popup TriggerProps narrow (boolean | 'dialog') because the
|
|
162
|
-
// top-layer API surface is not yet settled. Widening adopter types now would commit
|
|
163
|
-
// us to a public surface we may revisit. The runtime value is unchanged; only the
|
|
164
|
-
// TypeScript-visible type is narrowed at this boundary.
|
|
165
|
-
// REMOVE WHEN: the top-layer public API is committed (see
|
|
166
|
-
// packages/design-system/top-layer/notes/decisions/migration-roadmap.md "Open API
|
|
167
|
-
// decisions deferred to a follow-up PR") and a follow-up `minor` PR widens
|
|
168
|
-
// `TriggerProps['aria-haspopup']` to match.
|
|
169
|
-
'aria-haspopup': ariaAttributes['aria-haspopup']
|
|
170
|
-
};
|
|
171
|
-
return trigger(triggerProps);
|
|
172
|
-
}), /*#__PURE__*/React.createElement(_popup.Popup.Content, (0, _extends2.default)({}, roleProps, {
|
|
155
|
+
|
|
156
|
+
// Map to legacy TriggerProps.
|
|
157
|
+
var triggerProps = {
|
|
158
|
+
ref: function ref(node) {
|
|
159
|
+
triggerRef.current = node;
|
|
160
|
+
},
|
|
161
|
+
'aria-controls': providedId !== null && providedId !== void 0 ? providedId : popoverId,
|
|
162
|
+
// `aria-expanded` reflects current open state.
|
|
163
|
+
'aria-expanded': ariaAttributes['aria-expanded'],
|
|
164
|
+
// FUDGE(top-layer-api): cast to the narrow public TriggerProps['aria-haspopup'] union.
|
|
165
|
+
// `getAriaForTrigger` derives `aria-haspopup` from the content's role and types it
|
|
166
|
+
// as the wider WAI-ARIA union (boolean | 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid').
|
|
167
|
+
// We keep the public popup TriggerProps narrow (boolean | 'dialog') because the
|
|
168
|
+
// top-layer API surface is not yet settled. Widening adopter types now would commit
|
|
169
|
+
// us to a public surface we may revisit. The runtime value is unchanged; only the
|
|
170
|
+
// TypeScript-visible type is narrowed at this boundary.
|
|
171
|
+
'aria-haspopup': ariaAttributes['aria-haspopup']
|
|
172
|
+
};
|
|
173
|
+
return /*#__PURE__*/React.createElement(_react.Fragment, null, trigger(triggerProps), /*#__PURE__*/React.createElement(_popover.Popover, (0, _extends2.default)({
|
|
174
|
+
ref: popoverRef,
|
|
175
|
+
id: providedId !== null && providedId !== void 0 ? providedId : popoverId
|
|
176
|
+
}, roleProps, {
|
|
173
177
|
isOpen: isOpen,
|
|
178
|
+
onClose: handleOnClose,
|
|
174
179
|
animate: animation,
|
|
175
|
-
|
|
176
|
-
|
|
180
|
+
placement: topLayerPlacement,
|
|
181
|
+
testId: testId && "".concat(testId, "--content")
|
|
177
182
|
}), Container ? /*#__PURE__*/React.createElement(Container, {
|
|
178
183
|
ref: popupContainerRef,
|
|
179
184
|
style: EMPTY_STYLE,
|
|
@@ -182,7 +187,7 @@ var PopupTopLayer = exports.PopupTopLayer = /*#__PURE__*/(0, _react.memo)(functi
|
|
|
182
187
|
"data-testid": testId,
|
|
183
188
|
tabIndex: autoFocus ? -1 : undefined,
|
|
184
189
|
xcss: xcss
|
|
185
|
-
}, content(contentProps)) : /*#__PURE__*/React.createElement(
|
|
190
|
+
}, content(contentProps)) : /*#__PURE__*/React.createElement(_popoverSurface.PopoverSurface, null, /*#__PURE__*/React.createElement("div", {
|
|
186
191
|
className: (0, _runtime.ax)([contentOverflowStyles[shouldFitViewport ? 'fitViewport' : 'default']])
|
|
187
192
|
}, content(contentProps)))));
|
|
188
193
|
});
|
|
@@ -6,10 +6,9 @@ import { useCallback, useContext, useMemo, useRef, useState } from 'react';
|
|
|
6
6
|
import { ax, ix } from '@compiled/react/runtime';
|
|
7
7
|
import noop from '@atlaskit/ds-lib/noop';
|
|
8
8
|
import { slideAndFade } from '@atlaskit/top-layer/animations';
|
|
9
|
-
import { createPopoverCloseEvent } from '@atlaskit/top-layer/create-close-event';
|
|
10
9
|
import { fromLegacyPlacement } from '@atlaskit/top-layer/placement-map';
|
|
11
|
-
import { Popover } from '@atlaskit/top-layer/popover';
|
|
12
|
-
import {
|
|
10
|
+
import { createPopoverCloseEvent, Popover } from '@atlaskit/top-layer/popover';
|
|
11
|
+
import { PopoverSurface } from '@atlaskit/top-layer/popover-surface';
|
|
13
12
|
import { useAnchorPosition } from '@atlaskit/top-layer/use-anchor-position';
|
|
14
13
|
import { useWidthFromAnchor } from '@atlaskit/top-layer/use-width-from-anchor';
|
|
15
14
|
import { useRoleProps } from '../internal/top-layer-bridge';
|
|
@@ -144,7 +143,7 @@ export function PopupContentTopLayer({
|
|
|
144
143
|
"data-testid": testId,
|
|
145
144
|
tabIndex: autoFocus ? -1 : undefined,
|
|
146
145
|
xcss: xcss
|
|
147
|
-
}, children(contentProps)) : /*#__PURE__*/React.createElement(
|
|
146
|
+
}, children(contentProps)) : /*#__PURE__*/React.createElement(PopoverSurface, null, /*#__PURE__*/React.createElement("div", {
|
|
148
147
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
|
|
149
148
|
className: ax([shouldFitViewport && "_1reo1wug _18m91wug", ax([xcss])])
|
|
150
149
|
}, children(contentProps))));
|
|
@@ -3,12 +3,16 @@ import _extends from "@babel/runtime/helpers/extends";
|
|
|
3
3
|
import "./popup-top-layer.compiled.css";
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { ax, ix } from "@compiled/react/runtime";
|
|
6
|
-
import { memo, useCallback, useMemo, useRef, useState } from 'react';
|
|
6
|
+
import { Fragment, memo, useCallback, useMemo, useRef, useState } from 'react';
|
|
7
7
|
import noop from '@atlaskit/ds-lib/noop';
|
|
8
8
|
import { slideAndFade } from '@atlaskit/top-layer/animations';
|
|
9
|
-
import {
|
|
9
|
+
import { getAriaForTrigger } from '@atlaskit/top-layer/get-aria-for-trigger';
|
|
10
10
|
import { fromLegacyPlacement } from '@atlaskit/top-layer/placement-map';
|
|
11
|
-
import {
|
|
11
|
+
import { createPopoverCloseEvent, Popover } from '@atlaskit/top-layer/popover';
|
|
12
|
+
import { PopoverSurface } from '@atlaskit/top-layer/popover-surface';
|
|
13
|
+
import { useAnchorPosition } from '@atlaskit/top-layer/use-anchor-position';
|
|
14
|
+
import { usePopoverId } from '@atlaskit/top-layer/use-popover-id';
|
|
15
|
+
import { useWidthFromAnchor } from '@atlaskit/top-layer/use-width-from-anchor';
|
|
12
16
|
import { useRoleProps } from './internal/top-layer-bridge';
|
|
13
17
|
const contentOverflowStyles = {
|
|
14
18
|
fitViewport: "_1reo1wug _18m91wug",
|
|
@@ -49,9 +53,9 @@ export const PopupTopLayer = /*#__PURE__*/memo(function PopupTopLayer({
|
|
|
49
53
|
role,
|
|
50
54
|
label,
|
|
51
55
|
titleId,
|
|
52
|
-
//
|
|
56
|
+
// No-op props.
|
|
53
57
|
// These props are accepted for API compatibility but have no effect
|
|
54
|
-
// in the top-layer path. Each is documented with why it
|
|
58
|
+
// in the top-layer path. Each is documented with why it is unnecessary.
|
|
55
59
|
|
|
56
60
|
// top-layer: stacking managed by browser top layer. zIndex is a no-op.
|
|
57
61
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -84,25 +88,38 @@ export const PopupTopLayer = /*#__PURE__*/memo(function PopupTopLayer({
|
|
|
84
88
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
85
89
|
appearance: _appearance
|
|
86
90
|
}) {
|
|
91
|
+
var _roleProps$role;
|
|
87
92
|
const triggerRef = useRef(null);
|
|
93
|
+
const popoverRef = useRef(null);
|
|
88
94
|
const popupContainerRef = useRef(null);
|
|
89
95
|
const [, setInitialFocusRef] = useState(null);
|
|
96
|
+
const popoverId = usePopoverId();
|
|
90
97
|
|
|
91
|
-
//
|
|
98
|
+
// Placement conversion.
|
|
92
99
|
// Legacy `offset` is the popper `[along, away]` tuple; `fromLegacyPlacement`
|
|
93
100
|
// folds it into the new `placement.offset` shape so it travels with placement.
|
|
94
101
|
const topLayerPlacement = useMemo(() => fromLegacyPlacement({
|
|
95
102
|
legacy: placement,
|
|
96
103
|
offset: offsetProp
|
|
97
104
|
}), [placement, offsetProp]);
|
|
105
|
+
useAnchorPosition({
|
|
106
|
+
anchorRef: triggerRef,
|
|
107
|
+
popoverRef,
|
|
108
|
+
placement: topLayerPlacement
|
|
109
|
+
});
|
|
110
|
+
useWidthFromAnchor({
|
|
111
|
+
mode: shouldFitContainer ? 'match-anchor' : 'none',
|
|
112
|
+
popoverRef,
|
|
113
|
+
anchorRef: triggerRef
|
|
114
|
+
});
|
|
98
115
|
|
|
99
|
-
//
|
|
116
|
+
// onClose bridge.
|
|
100
117
|
// Translates top-layer's { reason: TPopoverCloseReason } into legacy
|
|
101
118
|
// onClose(event, currentLevel?) by synthesizing DOM events.
|
|
102
119
|
//
|
|
103
120
|
// Focus restoration is handled natively by the Popover API:
|
|
104
|
-
// - Escape
|
|
105
|
-
// - Click-outside
|
|
121
|
+
// - Escape: browser restores focus to the trigger automatically
|
|
122
|
+
// - Click-outside: browser does NOT restore (correct behavior)
|
|
106
123
|
// No manual triggerRef.current?.focus() is needed.
|
|
107
124
|
const handleOnClose = useCallback(({
|
|
108
125
|
reason
|
|
@@ -115,9 +132,9 @@ export const PopupTopLayer = /*#__PURE__*/memo(function PopupTopLayer({
|
|
|
115
132
|
}));
|
|
116
133
|
}, [onClose]);
|
|
117
134
|
|
|
118
|
-
//
|
|
135
|
+
// Content render-prop bridge.
|
|
119
136
|
// Legacy content() receives { isOpen, update, setInitialFocusRef, onClose }.
|
|
120
|
-
// update is a no-op
|
|
137
|
+
// update is a no-op because CSS Anchor Positioning self-updates.
|
|
121
138
|
const contentProps = useMemo(() => ({
|
|
122
139
|
isOpen: isOpen,
|
|
123
140
|
update: noop,
|
|
@@ -125,63 +142,50 @@ export const PopupTopLayer = /*#__PURE__*/memo(function PopupTopLayer({
|
|
|
125
142
|
setInitialFocusRef
|
|
126
143
|
}), [isOpen, onClose]);
|
|
127
144
|
|
|
128
|
-
//
|
|
129
|
-
// Build the role/label props for
|
|
145
|
+
// Role mapping.
|
|
146
|
+
// Build the role/label props for Popover.
|
|
130
147
|
// Roles requiring accessible names must have label or labelledBy.
|
|
131
148
|
const roleProps = useRoleProps({
|
|
132
149
|
role,
|
|
133
150
|
label,
|
|
134
151
|
titleId
|
|
135
152
|
});
|
|
153
|
+
const ariaAttributes = getAriaForTrigger({
|
|
154
|
+
role: (_roleProps$role = roleProps.role) !== null && _roleProps$role !== void 0 ? _roleProps$role : 'dialog',
|
|
155
|
+
isOpen,
|
|
156
|
+
popoverId
|
|
157
|
+
});
|
|
136
158
|
|
|
137
159
|
// Narrow to ForwardRefExoticComponent so JSX accepts the ref prop.
|
|
138
160
|
// All popupComponent implementations use forwardRef per the PopupComponentProps contract.
|
|
139
161
|
const Container = PopupContainer;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
//
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
// - Screen readers don't announce the popup as closed while it is still visible.
|
|
163
|
-
// - Consumers relying on aria-expanded to show/hide trigger UI don't lose the
|
|
164
|
-
// trigger (popup anchor) before the animation finishes.
|
|
165
|
-
'aria-expanded': ariaAttributes['aria-expanded'],
|
|
166
|
-
// FUDGE(top-layer-api): cast to the narrow public TriggerProps['aria-haspopup'] union.
|
|
167
|
-
// `@atlaskit/top-layer` derives `aria-haspopup` from the content's role and types it
|
|
168
|
-
// as the wider WAI-ARIA union (boolean | 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid').
|
|
169
|
-
// We keep the public popup TriggerProps narrow (boolean | 'dialog') because the
|
|
170
|
-
// top-layer API surface is not yet settled. Widening adopter types now would commit
|
|
171
|
-
// us to a public surface we may revisit. The runtime value is unchanged; only the
|
|
172
|
-
// TypeScript-visible type is narrowed at this boundary.
|
|
173
|
-
// REMOVE WHEN: the top-layer public API is committed (see
|
|
174
|
-
// packages/design-system/top-layer/notes/decisions/migration-roadmap.md "Open API
|
|
175
|
-
// decisions deferred to a follow-up PR") and a follow-up `minor` PR widens
|
|
176
|
-
// `TriggerProps['aria-haspopup']` to match.
|
|
177
|
-
'aria-haspopup': ariaAttributes['aria-haspopup']
|
|
178
|
-
};
|
|
179
|
-
return trigger(triggerProps);
|
|
180
|
-
}), /*#__PURE__*/React.createElement(Popup.Content, _extends({}, roleProps, {
|
|
162
|
+
|
|
163
|
+
// Map to legacy TriggerProps.
|
|
164
|
+
const triggerProps = {
|
|
165
|
+
ref: node => {
|
|
166
|
+
triggerRef.current = node;
|
|
167
|
+
},
|
|
168
|
+
'aria-controls': providedId !== null && providedId !== void 0 ? providedId : popoverId,
|
|
169
|
+
// `aria-expanded` reflects current open state.
|
|
170
|
+
'aria-expanded': ariaAttributes['aria-expanded'],
|
|
171
|
+
// FUDGE(top-layer-api): cast to the narrow public TriggerProps['aria-haspopup'] union.
|
|
172
|
+
// `getAriaForTrigger` derives `aria-haspopup` from the content's role and types it
|
|
173
|
+
// as the wider WAI-ARIA union (boolean | 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid').
|
|
174
|
+
// We keep the public popup TriggerProps narrow (boolean | 'dialog') because the
|
|
175
|
+
// top-layer API surface is not yet settled. Widening adopter types now would commit
|
|
176
|
+
// us to a public surface we may revisit. The runtime value is unchanged; only the
|
|
177
|
+
// TypeScript-visible type is narrowed at this boundary.
|
|
178
|
+
'aria-haspopup': ariaAttributes['aria-haspopup']
|
|
179
|
+
};
|
|
180
|
+
return /*#__PURE__*/React.createElement(Fragment, null, trigger(triggerProps), /*#__PURE__*/React.createElement(Popover, _extends({
|
|
181
|
+
ref: popoverRef,
|
|
182
|
+
id: providedId !== null && providedId !== void 0 ? providedId : popoverId
|
|
183
|
+
}, roleProps, {
|
|
181
184
|
isOpen: isOpen,
|
|
185
|
+
onClose: handleOnClose,
|
|
182
186
|
animate: animation,
|
|
183
|
-
|
|
184
|
-
|
|
187
|
+
placement: topLayerPlacement,
|
|
188
|
+
testId: testId && `${testId}--content`
|
|
185
189
|
}), Container ? /*#__PURE__*/React.createElement(Container, {
|
|
186
190
|
ref: popupContainerRef,
|
|
187
191
|
style: EMPTY_STYLE,
|
|
@@ -190,7 +194,7 @@ export const PopupTopLayer = /*#__PURE__*/memo(function PopupTopLayer({
|
|
|
190
194
|
"data-testid": testId,
|
|
191
195
|
tabIndex: autoFocus ? -1 : undefined,
|
|
192
196
|
xcss: xcss
|
|
193
|
-
}, content(contentProps)) : /*#__PURE__*/React.createElement(
|
|
197
|
+
}, content(contentProps)) : /*#__PURE__*/React.createElement(PopoverSurface, null, /*#__PURE__*/React.createElement("div", {
|
|
194
198
|
className: ax([contentOverflowStyles[shouldFitViewport ? 'fitViewport' : 'default']])
|
|
195
199
|
}, content(contentProps)))));
|
|
196
200
|
});
|
|
@@ -7,10 +7,9 @@ import { useCallback, useContext, useMemo, useRef, useState } from 'react';
|
|
|
7
7
|
import { ax, ix } from '@compiled/react/runtime';
|
|
8
8
|
import noop from '@atlaskit/ds-lib/noop';
|
|
9
9
|
import { slideAndFade } from '@atlaskit/top-layer/animations';
|
|
10
|
-
import { createPopoverCloseEvent } from '@atlaskit/top-layer/create-close-event';
|
|
11
10
|
import { fromLegacyPlacement } from '@atlaskit/top-layer/placement-map';
|
|
12
|
-
import { Popover } from '@atlaskit/top-layer/popover';
|
|
13
|
-
import {
|
|
11
|
+
import { createPopoverCloseEvent, Popover } from '@atlaskit/top-layer/popover';
|
|
12
|
+
import { PopoverSurface } from '@atlaskit/top-layer/popover-surface';
|
|
14
13
|
import { useAnchorPosition } from '@atlaskit/top-layer/use-anchor-position';
|
|
15
14
|
import { useWidthFromAnchor } from '@atlaskit/top-layer/use-width-from-anchor';
|
|
16
15
|
import { useRoleProps } from '../internal/top-layer-bridge';
|
|
@@ -130,7 +129,7 @@ export function PopupContentTopLayer(_ref) {
|
|
|
130
129
|
"data-testid": testId,
|
|
131
130
|
tabIndex: autoFocus ? -1 : undefined,
|
|
132
131
|
xcss: xcss
|
|
133
|
-
}, children(contentProps)) : /*#__PURE__*/React.createElement(
|
|
132
|
+
}, children(contentProps)) : /*#__PURE__*/React.createElement(PopoverSurface, null, /*#__PURE__*/React.createElement("div", {
|
|
134
133
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
|
|
135
134
|
className: ax([shouldFitViewport && "_1reo1wug _18m91wug", ax([xcss])])
|
|
136
135
|
}, children(contentProps))));
|
|
@@ -4,12 +4,16 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
|
4
4
|
import "./popup-top-layer.compiled.css";
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import { ax, ix } from "@compiled/react/runtime";
|
|
7
|
-
import { memo, useCallback, useMemo, useRef, useState } from 'react';
|
|
7
|
+
import { Fragment, memo, useCallback, useMemo, useRef, useState } from 'react';
|
|
8
8
|
import noop from '@atlaskit/ds-lib/noop';
|
|
9
9
|
import { slideAndFade } from '@atlaskit/top-layer/animations';
|
|
10
|
-
import {
|
|
10
|
+
import { getAriaForTrigger } from '@atlaskit/top-layer/get-aria-for-trigger';
|
|
11
11
|
import { fromLegacyPlacement } from '@atlaskit/top-layer/placement-map';
|
|
12
|
-
import {
|
|
12
|
+
import { createPopoverCloseEvent, Popover } from '@atlaskit/top-layer/popover';
|
|
13
|
+
import { PopoverSurface } from '@atlaskit/top-layer/popover-surface';
|
|
14
|
+
import { useAnchorPosition } from '@atlaskit/top-layer/use-anchor-position';
|
|
15
|
+
import { usePopoverId } from '@atlaskit/top-layer/use-popover-id';
|
|
16
|
+
import { useWidthFromAnchor } from '@atlaskit/top-layer/use-width-from-anchor';
|
|
13
17
|
import { useRoleProps } from './internal/top-layer-bridge';
|
|
14
18
|
var contentOverflowStyles = {
|
|
15
19
|
fitViewport: "_1reo1wug _18m91wug",
|
|
@@ -30,6 +34,7 @@ var EMPTY_STYLE = {};
|
|
|
30
34
|
* Gated behind the `platform-dst-top-layer` feature flag.
|
|
31
35
|
*/
|
|
32
36
|
export var PopupTopLayer = /*#__PURE__*/memo(function PopupTopLayer(_ref) {
|
|
37
|
+
var _roleProps$role;
|
|
33
38
|
var xcss = _ref.xcss,
|
|
34
39
|
isOpen = _ref.isOpen,
|
|
35
40
|
providedId = _ref.id,
|
|
@@ -64,12 +69,14 @@ export var PopupTopLayer = /*#__PURE__*/memo(function PopupTopLayer(_ref) {
|
|
|
64
69
|
shouldFitViewport = _ref.shouldFitViewport,
|
|
65
70
|
_appearance = _ref.appearance;
|
|
66
71
|
var triggerRef = useRef(null);
|
|
72
|
+
var popoverRef = useRef(null);
|
|
67
73
|
var popupContainerRef = useRef(null);
|
|
68
74
|
var _useState = useState(null),
|
|
69
75
|
_useState2 = _slicedToArray(_useState, 2),
|
|
70
76
|
setInitialFocusRef = _useState2[1];
|
|
77
|
+
var popoverId = usePopoverId();
|
|
71
78
|
|
|
72
|
-
//
|
|
79
|
+
// Placement conversion.
|
|
73
80
|
// Legacy `offset` is the popper `[along, away]` tuple; `fromLegacyPlacement`
|
|
74
81
|
// folds it into the new `placement.offset` shape so it travels with placement.
|
|
75
82
|
var topLayerPlacement = useMemo(function () {
|
|
@@ -78,14 +85,24 @@ export var PopupTopLayer = /*#__PURE__*/memo(function PopupTopLayer(_ref) {
|
|
|
78
85
|
offset: offsetProp
|
|
79
86
|
});
|
|
80
87
|
}, [placement, offsetProp]);
|
|
88
|
+
useAnchorPosition({
|
|
89
|
+
anchorRef: triggerRef,
|
|
90
|
+
popoverRef: popoverRef,
|
|
91
|
+
placement: topLayerPlacement
|
|
92
|
+
});
|
|
93
|
+
useWidthFromAnchor({
|
|
94
|
+
mode: shouldFitContainer ? 'match-anchor' : 'none',
|
|
95
|
+
popoverRef: popoverRef,
|
|
96
|
+
anchorRef: triggerRef
|
|
97
|
+
});
|
|
81
98
|
|
|
82
|
-
//
|
|
99
|
+
// onClose bridge.
|
|
83
100
|
// Translates top-layer's { reason: TPopoverCloseReason } into legacy
|
|
84
101
|
// onClose(event, currentLevel?) by synthesizing DOM events.
|
|
85
102
|
//
|
|
86
103
|
// Focus restoration is handled natively by the Popover API:
|
|
87
|
-
// - Escape
|
|
88
|
-
// - Click-outside
|
|
104
|
+
// - Escape: browser restores focus to the trigger automatically
|
|
105
|
+
// - Click-outside: browser does NOT restore (correct behavior)
|
|
89
106
|
// No manual triggerRef.current?.focus() is needed.
|
|
90
107
|
var handleOnClose = useCallback(function (_ref2) {
|
|
91
108
|
var reason = _ref2.reason;
|
|
@@ -97,9 +114,9 @@ export var PopupTopLayer = /*#__PURE__*/memo(function PopupTopLayer(_ref) {
|
|
|
97
114
|
}));
|
|
98
115
|
}, [onClose]);
|
|
99
116
|
|
|
100
|
-
//
|
|
117
|
+
// Content render-prop bridge.
|
|
101
118
|
// Legacy content() receives { isOpen, update, setInitialFocusRef, onClose }.
|
|
102
|
-
// update is a no-op
|
|
119
|
+
// update is a no-op because CSS Anchor Positioning self-updates.
|
|
103
120
|
var contentProps = useMemo(function () {
|
|
104
121
|
return {
|
|
105
122
|
isOpen: isOpen,
|
|
@@ -109,62 +126,50 @@ export var PopupTopLayer = /*#__PURE__*/memo(function PopupTopLayer(_ref) {
|
|
|
109
126
|
};
|
|
110
127
|
}, [isOpen, onClose]);
|
|
111
128
|
|
|
112
|
-
//
|
|
113
|
-
// Build the role/label props for
|
|
129
|
+
// Role mapping.
|
|
130
|
+
// Build the role/label props for Popover.
|
|
114
131
|
// Roles requiring accessible names must have label or labelledBy.
|
|
115
132
|
var roleProps = useRoleProps({
|
|
116
133
|
role: role,
|
|
117
134
|
label: label,
|
|
118
135
|
titleId: titleId
|
|
119
136
|
});
|
|
137
|
+
var ariaAttributes = getAriaForTrigger({
|
|
138
|
+
role: (_roleProps$role = roleProps.role) !== null && _roleProps$role !== void 0 ? _roleProps$role : 'dialog',
|
|
139
|
+
isOpen: isOpen,
|
|
140
|
+
popoverId: popoverId
|
|
141
|
+
});
|
|
120
142
|
|
|
121
143
|
// Narrow to ForwardRefExoticComponent so JSX accepts the ref prop.
|
|
122
144
|
// All popupComponent implementations use forwardRef per the PopupComponentProps contract.
|
|
123
145
|
var Container = PopupContainer;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
// - Consumers relying on aria-expanded to show/hide trigger UI don't lose the
|
|
147
|
-
// trigger (popup anchor) before the animation finishes.
|
|
148
|
-
'aria-expanded': ariaAttributes['aria-expanded'],
|
|
149
|
-
// FUDGE(top-layer-api): cast to the narrow public TriggerProps['aria-haspopup'] union.
|
|
150
|
-
// `@atlaskit/top-layer` derives `aria-haspopup` from the content's role and types it
|
|
151
|
-
// as the wider WAI-ARIA union (boolean | 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid').
|
|
152
|
-
// We keep the public popup TriggerProps narrow (boolean | 'dialog') because the
|
|
153
|
-
// top-layer API surface is not yet settled. Widening adopter types now would commit
|
|
154
|
-
// us to a public surface we may revisit. The runtime value is unchanged; only the
|
|
155
|
-
// TypeScript-visible type is narrowed at this boundary.
|
|
156
|
-
// REMOVE WHEN: the top-layer public API is committed (see
|
|
157
|
-
// packages/design-system/top-layer/notes/decisions/migration-roadmap.md "Open API
|
|
158
|
-
// decisions deferred to a follow-up PR") and a follow-up `minor` PR widens
|
|
159
|
-
// `TriggerProps['aria-haspopup']` to match.
|
|
160
|
-
'aria-haspopup': ariaAttributes['aria-haspopup']
|
|
161
|
-
};
|
|
162
|
-
return trigger(triggerProps);
|
|
163
|
-
}), /*#__PURE__*/React.createElement(Popup.Content, _extends({}, roleProps, {
|
|
146
|
+
|
|
147
|
+
// Map to legacy TriggerProps.
|
|
148
|
+
var triggerProps = {
|
|
149
|
+
ref: function ref(node) {
|
|
150
|
+
triggerRef.current = node;
|
|
151
|
+
},
|
|
152
|
+
'aria-controls': providedId !== null && providedId !== void 0 ? providedId : popoverId,
|
|
153
|
+
// `aria-expanded` reflects current open state.
|
|
154
|
+
'aria-expanded': ariaAttributes['aria-expanded'],
|
|
155
|
+
// FUDGE(top-layer-api): cast to the narrow public TriggerProps['aria-haspopup'] union.
|
|
156
|
+
// `getAriaForTrigger` 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
|
+
'aria-haspopup': ariaAttributes['aria-haspopup']
|
|
163
|
+
};
|
|
164
|
+
return /*#__PURE__*/React.createElement(Fragment, null, trigger(triggerProps), /*#__PURE__*/React.createElement(Popover, _extends({
|
|
165
|
+
ref: popoverRef,
|
|
166
|
+
id: providedId !== null && providedId !== void 0 ? providedId : popoverId
|
|
167
|
+
}, roleProps, {
|
|
164
168
|
isOpen: isOpen,
|
|
169
|
+
onClose: handleOnClose,
|
|
165
170
|
animate: animation,
|
|
166
|
-
|
|
167
|
-
|
|
171
|
+
placement: topLayerPlacement,
|
|
172
|
+
testId: testId && "".concat(testId, "--content")
|
|
168
173
|
}), Container ? /*#__PURE__*/React.createElement(Container, {
|
|
169
174
|
ref: popupContainerRef,
|
|
170
175
|
style: EMPTY_STYLE,
|
|
@@ -173,7 +178,7 @@ export var PopupTopLayer = /*#__PURE__*/memo(function PopupTopLayer(_ref) {
|
|
|
173
178
|
"data-testid": testId,
|
|
174
179
|
tabIndex: autoFocus ? -1 : undefined,
|
|
175
180
|
xcss: xcss
|
|
176
|
-
}, content(contentProps)) : /*#__PURE__*/React.createElement(
|
|
181
|
+
}, content(contentProps)) : /*#__PURE__*/React.createElement(PopoverSurface, null, /*#__PURE__*/React.createElement("div", {
|
|
177
182
|
className: ax([contentOverflowStyles[shouldFitViewport ? 'fitViewport' : 'default']])
|
|
178
183
|
}, content(contentProps)))));
|
|
179
184
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/popup",
|
|
3
|
-
"version": "4.23.
|
|
3
|
+
"version": "4.23.3",
|
|
4
4
|
"description": "A popup displays brief content in an overlay.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -41,14 +41,14 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@atlaskit/css": "^0.19.0",
|
|
43
43
|
"@atlaskit/ds-lib": "^7.0.0",
|
|
44
|
-
"@atlaskit/layering": "^3.
|
|
44
|
+
"@atlaskit/layering": "^3.8.0",
|
|
45
45
|
"@atlaskit/motion": "^6.2.0",
|
|
46
46
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
47
47
|
"@atlaskit/popper": "^7.2.0",
|
|
48
48
|
"@atlaskit/portal": "^5.5.0",
|
|
49
49
|
"@atlaskit/primitives": "^19.0.0",
|
|
50
|
-
"@atlaskit/tokens": "^13.
|
|
51
|
-
"@atlaskit/top-layer": "^0.
|
|
50
|
+
"@atlaskit/tokens": "^13.3.0",
|
|
51
|
+
"@atlaskit/top-layer": "^0.15.0",
|
|
52
52
|
"@babel/runtime": "^7.0.0",
|
|
53
53
|
"@compiled/react": "^0.20.0",
|
|
54
54
|
"bind-event-listener": "^3.0.0",
|