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