@atlaskit/top-layer 0.6.1 → 0.6.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 +12 -0
- package/README.md +2 -4
- package/dist/cjs/arrow/index.js +2 -2
- package/dist/cjs/dialog/dialog-content.js +1 -6
- package/dist/cjs/focus/focus.js +4 -4
- package/dist/cjs/internal/combine.js +2 -2
- package/dist/cjs/internal/use-anchor-position.js +24 -27
- package/dist/cjs/internal/use-animated-visibility.js +3 -3
- package/dist/cjs/internal/use-focus-wrap.js +7 -7
- package/dist/cjs/internal/use-initial-focus.js +1 -1
- package/dist/cjs/popover/popover.js +9 -9
- package/dist/cjs/popup/popup-content.js +2 -2
- package/dist/cjs/popup/popup-trigger.js +2 -2
- package/dist/cjs/use-simple-light-dismiss/index.js +1 -1
- package/dist/es2019/arrow/index.js +2 -2
- package/dist/es2019/dialog/dialog-content.js +1 -6
- package/dist/es2019/focus/focus.js +1 -1
- package/dist/es2019/internal/combine.js +1 -1
- package/dist/es2019/internal/use-anchor-position.js +24 -15
- package/dist/es2019/internal/use-animated-visibility.js +3 -3
- package/dist/es2019/internal/use-focus-wrap.js +7 -7
- package/dist/es2019/internal/use-initial-focus.js +1 -1
- package/dist/es2019/popover/popover.js +9 -9
- package/dist/es2019/popup/popup-content.js +2 -2
- package/dist/es2019/popup/popup-trigger.js +2 -2
- package/dist/es2019/use-simple-light-dismiss/index.js +1 -1
- package/dist/esm/arrow/index.js +2 -2
- package/dist/esm/dialog/dialog-content.js +1 -6
- package/dist/esm/focus/focus.js +4 -4
- package/dist/esm/internal/combine.js +2 -2
- package/dist/esm/internal/use-anchor-position.js +24 -27
- package/dist/esm/internal/use-animated-visibility.js +3 -3
- package/dist/esm/internal/use-focus-wrap.js +7 -7
- package/dist/esm/internal/use-initial-focus.js +1 -1
- package/dist/esm/popover/popover.js +9 -9
- package/dist/esm/popup/popup-content.js +2 -2
- package/dist/esm/popup/popup-trigger.js +2 -2
- package/dist/esm/use-simple-light-dismiss/index.js +1 -1
- package/dist/types/internal/ensure-preset-styles.d.ts +1 -1
- package/dist/types/internal/use-anchor-position.d.ts +15 -1
- package/dist/types/internal/use-focus-wrap.d.ts +1 -1
- package/dist/types/popup/popup-content.d.ts +1 -1
- package/dist/types/popup/popup-trigger.d.ts +1 -1
- package/dist/types/use-simple-light-dismiss/index.d.ts +3 -3
- package/dist/types-ts4.5/internal/ensure-preset-styles.d.ts +1 -1
- package/dist/types-ts4.5/internal/use-anchor-position.d.ts +15 -1
- package/dist/types-ts4.5/internal/use-focus-wrap.d.ts +1 -1
- package/dist/types-ts4.5/popup/popup-content.d.ts +1 -1
- package/dist/types-ts4.5/popup/popup-trigger.d.ts +1 -1
- package/dist/types-ts4.5/use-simple-light-dismiss/index.d.ts +3 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @atlaskit/top-layer
|
|
2
2
|
|
|
3
|
+
## 0.6.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`9d77f6602f870`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/9d77f6602f870) -
|
|
8
|
+
Fix two CSS anchor positioning bugs for aligned placements (align-start/align-end):
|
|
9
|
+
1. Popups at viewport corners now correctly fall back to the diagonally opposite corner when their
|
|
10
|
+
preferred placement has no space, rather than remaining partially off-screen.
|
|
11
|
+
|
|
12
|
+
2. Popups near a single viewport edge now correctly trigger position fallbacks when their content
|
|
13
|
+
is wider than the available space, rather than wrapping content into a narrow column.
|
|
14
|
+
|
|
3
15
|
## 0.6.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -129,7 +129,7 @@ Browsers without `@starting-style` support will show/hide elements instantly —
|
|
|
129
129
|
|
|
130
130
|
Browser tests in `__tests__/playwright/` verify the following WCAG 2.2 success criteria. See
|
|
131
131
|
[`notes/goals/accessibility-criteria.md`](notes/goals/accessibility-criteria.md) and
|
|
132
|
-
[`notes/
|
|
132
|
+
[`notes/audits/accessibility-audit-report.md`](notes/audits/accessibility-audit-report.md) for
|
|
133
133
|
details.
|
|
134
134
|
|
|
135
135
|
| A11y criterion | Browser test |
|
|
@@ -150,6 +150,4 @@ details.
|
|
|
150
150
|
## Documentation
|
|
151
151
|
|
|
152
152
|
See [`notes/`](notes/) for project documentation, architecture decisions, migration records, and
|
|
153
|
-
audit reports. The [`notes/README.md`](notes/README.md) provides a full index
|
|
154
|
-
migration status** and links to
|
|
155
|
-
[`notes/decisions/migration-roadmap.md`](notes/decisions/migration-roadmap.md).
|
|
153
|
+
audit reports. The [`notes/README.md`](notes/README.md) provides a full index.
|
package/dist/cjs/arrow/index.js
CHANGED
|
@@ -21,7 +21,7 @@ var _useAnchorPosition = require("../internal/use-anchor-position");
|
|
|
21
21
|
*
|
|
22
22
|
* Constraints:
|
|
23
23
|
* - `box-shadow` must be `none` (interferes with `clip-path: inset() margin-box`)
|
|
24
|
-
* - `::before` and `::after` are consumed
|
|
24
|
+
* - `::before` and `::after` are consumed — consumers cannot use them
|
|
25
25
|
* - Arrow pseudo-elements use `background: inherit` from the popover element
|
|
26
26
|
*
|
|
27
27
|
* @see https://goulet.dev/posts/tooltip-with-popover-and-anchor-positioning/
|
|
@@ -46,7 +46,7 @@ function positionAreaToRuleName(_ref) {
|
|
|
46
46
|
* that change both `position-area` and `margin` when flipping.
|
|
47
47
|
*
|
|
48
48
|
* This is required for the arrow technique because built-in keywords
|
|
49
|
-
* (`flip-block`, `flip-inline`) only flip `position-area`
|
|
49
|
+
* (`flip-block`, `flip-inline`) only flip `position-area` — they do
|
|
50
50
|
* not update the margin direction needed to reveal the correct arrow.
|
|
51
51
|
*/
|
|
52
52
|
function getTryFallbacks(_ref2) {
|
|
@@ -128,12 +128,7 @@ var Dialog = exports.Dialog = /*#__PURE__*/(0, _react.forwardRef)(function Dialo
|
|
|
128
128
|
var escapedId = CSS.escape(dialogId);
|
|
129
129
|
return /*#__PURE__*/_react.default.createElement("dialog", (0, _extends2.default)({
|
|
130
130
|
ref: combinedRef,
|
|
131
|
-
id: dialogId
|
|
132
|
-
// Modern browsers infer modal semantics from `.showModal()` but
|
|
133
|
-
// some assistive tech still keys off `aria-modal="true"`. Setting
|
|
134
|
-
// it explicitly is recommended by WAI-ARIA APG dialog pattern.
|
|
135
|
-
,
|
|
136
|
-
"aria-modal": "true",
|
|
131
|
+
id: dialogId,
|
|
137
132
|
"aria-label": label,
|
|
138
133
|
"aria-labelledby": label ? undefined : labelledBy,
|
|
139
134
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
|
package/dist/cjs/focus/focus.js
CHANGED
|
@@ -46,10 +46,10 @@ var selectors = function () {
|
|
|
46
46
|
function getFocusables(_ref) {
|
|
47
47
|
var container = _ref.container,
|
|
48
48
|
filter = _ref.filter;
|
|
49
|
-
return Array.from(container.querySelectorAll(selectors.focusable)).filter(function (
|
|
50
|
-
return
|
|
51
|
-
}).filter(function (
|
|
52
|
-
return !filter || filter(
|
|
49
|
+
return Array.from(container.querySelectorAll(selectors.focusable)).filter(function (el) {
|
|
50
|
+
return el instanceof HTMLElement;
|
|
51
|
+
}).filter(function (el) {
|
|
52
|
+
return !filter || filter(el, container);
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -22,8 +22,8 @@ function combine() {
|
|
|
22
22
|
cleanupFns[_key] = arguments[_key];
|
|
23
23
|
}
|
|
24
24
|
return function cleanup() {
|
|
25
|
-
cleanupFns.forEach(function (
|
|
26
|
-
return
|
|
25
|
+
cleanupFns.forEach(function (fn) {
|
|
26
|
+
return fn === null || fn === void 0 ? void 0 : fn();
|
|
27
27
|
});
|
|
28
28
|
};
|
|
29
29
|
}
|
|
@@ -13,8 +13,6 @@ Object.defineProperty(exports, "getPlacement", {
|
|
|
13
13
|
exports.placementToPositionArea = placementToPositionArea;
|
|
14
14
|
exports.placementToTryFallbacks = placementToTryFallbacks;
|
|
15
15
|
exports.useAnchorPosition = useAnchorPosition;
|
|
16
|
-
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
17
|
-
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
18
16
|
var _react = require("react");
|
|
19
17
|
var _bindEventListener = require("bind-event-listener");
|
|
20
18
|
var _rafSchd = _interopRequireDefault(require("raf-schd"));
|
|
@@ -93,6 +91,20 @@ function placementToPositionArea(_ref) {
|
|
|
93
91
|
* For aligned placements (start/end), includes the same-edge centered
|
|
94
92
|
* position as fallbacks so the browser can try centering when the aligned
|
|
95
93
|
* position would overflow, before flipping to the opposite edge.
|
|
94
|
+
*
|
|
95
|
+
* **Why `flip-inline flip-block` (or `flip-block flip-inline`) is included:**
|
|
96
|
+
*
|
|
97
|
+
* When a popup is in a viewport corner (e.g. inline-end align-end at the
|
|
98
|
+
* top-right), flipping only the primary axis (`flip-inline`) moves the popup
|
|
99
|
+
* to the left but keeps the same cross-axis span direction (e.g. upward),
|
|
100
|
+
* which is still off-screen. The combined keyword `flip-inline flip-block`
|
|
101
|
+
* mirrors the popup diagonally — it flips BOTH the position-area AND both
|
|
102
|
+
* inline and block margins simultaneously, placing the popup at the
|
|
103
|
+
* diagonally opposite corner where there is always space.
|
|
104
|
+
*
|
|
105
|
+
* Named `position-area` entries (e.g. `inline-start span-block-end`) in
|
|
106
|
+
* `position-try-fallbacks` do NOT update margins, so only the `flip-*`
|
|
107
|
+
* tactic keywords correctly flip the gap margin along with the position.
|
|
96
108
|
*/
|
|
97
109
|
function placementToTryFallbacks(_ref2) {
|
|
98
110
|
var placement = _ref2.placement;
|
|
@@ -108,9 +120,10 @@ function placementToTryFallbacks(_ref2) {
|
|
|
108
120
|
var _sameEdge = "".concat(axis, "-").concat(edge);
|
|
109
121
|
var _oppositeEdge = "".concat(axis, "-").concat(flippedEdge);
|
|
110
122
|
var _flipKeyword = axis === 'block' ? 'flip-block' : 'flip-inline';
|
|
123
|
+
var flipCrossKeyword = axis === 'block' ? 'flip-inline' : 'flip-block';
|
|
124
|
+
// Try same-edge shifts first; two flip entries cover single-edge then corner overflow.
|
|
111
125
|
// Legacy Popper fallbacks for e.g. bottom-start: [bottom, bottom-end, top-start, top, top-end, auto].
|
|
112
|
-
|
|
113
|
-
return ["".concat(_sameEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'end' : 'start'), _sameEdge, "".concat(_sameEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'start' : 'end'), _flipKeyword, "".concat(_oppositeEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'end' : 'start'), _oppositeEdge, "".concat(_oppositeEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'start' : 'end')].join(', ');
|
|
126
|
+
return ["".concat(_sameEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'end' : 'start'), _sameEdge, "".concat(_sameEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'start' : 'end'), _flipKeyword, "".concat(_flipKeyword, " ").concat(flipCrossKeyword), "".concat(_oppositeEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'end' : 'start'), _oppositeEdge, "".concat(_oppositeEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'start' : 'end')].join(', ');
|
|
114
127
|
}
|
|
115
128
|
var sameEdge = "".concat(axis, "-").concat(edge);
|
|
116
129
|
var oppositeEdge = "".concat(axis, "-").concat(flippedEdge);
|
|
@@ -315,6 +328,12 @@ function useAnchorPosition(_ref5) {
|
|
|
315
328
|
property: 'inset',
|
|
316
329
|
value: 'auto'
|
|
317
330
|
},
|
|
331
|
+
// Ensures the popup's margin box overflows the viewport when its span region is too
|
|
332
|
+
// narrow, triggering position-try-fallbacks correctly rather than wrapping content.
|
|
333
|
+
{
|
|
334
|
+
property: 'min-inline-size',
|
|
335
|
+
value: 'max-content'
|
|
336
|
+
},
|
|
318
337
|
// Main-axis gap between the popover and its trigger
|
|
319
338
|
{
|
|
320
339
|
property: gap.property,
|
|
@@ -475,29 +494,7 @@ function useAnchorPosition(_ref5) {
|
|
|
475
494
|
// ResizeObserver fires once the browser has real dimensions.
|
|
476
495
|
// Self-disconnects after one valid measurement; ongoing
|
|
477
496
|
// scroll/resize is handled by the window listeners below.
|
|
478
|
-
|
|
479
|
-
// (e.g. post-office's `node` environment). Fall back to a no-op
|
|
480
|
-
// observer there — the scroll/resize listeners below still keep
|
|
481
|
-
// the popover positioned in the rare case the consumer also
|
|
482
|
-
// polyfilled `showPopover` but not `ResizeObserver`. Real
|
|
483
|
-
// browsers always have it.
|
|
484
|
-
var NoopResizeObserver = /*#__PURE__*/function () {
|
|
485
|
-
function NoopResizeObserver() {
|
|
486
|
-
(0, _classCallCheck2.default)(this, NoopResizeObserver);
|
|
487
|
-
}
|
|
488
|
-
return (0, _createClass2.default)(NoopResizeObserver, [{
|
|
489
|
-
key: "observe",
|
|
490
|
-
value: function observe() {}
|
|
491
|
-
}, {
|
|
492
|
-
key: "unobserve",
|
|
493
|
-
value: function unobserve() {}
|
|
494
|
-
}, {
|
|
495
|
-
key: "disconnect",
|
|
496
|
-
value: function disconnect() {}
|
|
497
|
-
}]);
|
|
498
|
-
}();
|
|
499
|
-
var ResizeObserverImpl = typeof ResizeObserver !== 'undefined' ? ResizeObserver : NoopResizeObserver;
|
|
500
|
-
var resizeObserver = new ResizeObserverImpl(function () {
|
|
497
|
+
var resizeObserver = new ResizeObserver(function () {
|
|
501
498
|
if (popover.offsetWidth > 0 && popover.offsetHeight > 0) {
|
|
502
499
|
update();
|
|
503
500
|
resizeObserver.disconnect();
|
|
@@ -114,8 +114,8 @@ function useAnimatedVisibility(_ref) {
|
|
|
114
114
|
if (isOpen || !showChildren || !willAnimate) {
|
|
115
115
|
return;
|
|
116
116
|
}
|
|
117
|
-
var
|
|
118
|
-
if (!
|
|
117
|
+
var el = elementRef.current;
|
|
118
|
+
if (!el) {
|
|
119
119
|
return;
|
|
120
120
|
}
|
|
121
121
|
function finish() {
|
|
@@ -129,7 +129,7 @@ function useAnimatedVisibility(_ref) {
|
|
|
129
129
|
var fallbackId = setTimeout(finish, ((_preset$exitDurationM = preset === null || preset === void 0 ? void 0 : preset.exitDurationMs) !== null && _preset$exitDurationM !== void 0 ? _preset$exitDurationM : 0) + 50);
|
|
130
130
|
|
|
131
131
|
// Primary: listen for the CSS transition to complete
|
|
132
|
-
var unbind = (0, _bindEventListener.bind)(
|
|
132
|
+
var unbind = (0, _bindEventListener.bind)(el, {
|
|
133
133
|
type: 'transitionend',
|
|
134
134
|
listener: finish,
|
|
135
135
|
options: {
|
|
@@ -39,7 +39,7 @@ function roleRequiresFocusWrap(role) {
|
|
|
39
39
|
* elements within the container using wrapping navigation.
|
|
40
40
|
*
|
|
41
41
|
* Light dismiss (Escape, click outside) continues to work natively
|
|
42
|
-
* via `popover="auto"`
|
|
42
|
+
* via `popover="auto"` — this hook only intercepts Tab.
|
|
43
43
|
*
|
|
44
44
|
* Always call this hook unconditionally. The listener is only
|
|
45
45
|
* attached when the role requires focus wrapping, and is cleaned
|
|
@@ -49,11 +49,11 @@ function useFocusWrap(_ref) {
|
|
|
49
49
|
var elementRef = _ref.elementRef,
|
|
50
50
|
role = _ref.role;
|
|
51
51
|
(0, _react.useEffect)(function () {
|
|
52
|
-
var
|
|
53
|
-
if (!
|
|
52
|
+
var el = elementRef.current;
|
|
53
|
+
if (!el || !roleRequiresFocusWrap(role)) {
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
|
-
var unbind = (0, _bindEventListener.bind)(
|
|
56
|
+
var unbind = (0, _bindEventListener.bind)(el, {
|
|
57
57
|
type: 'keydown',
|
|
58
58
|
listener: function listener(event) {
|
|
59
59
|
if (event.key !== 'Tab') {
|
|
@@ -65,7 +65,7 @@ function useFocusWrap(_ref) {
|
|
|
65
65
|
// Try to move to the next/previous focusable element relative
|
|
66
66
|
// to the currently focused element within the container.
|
|
67
67
|
var next = (0, _focus.getNextFocusable)({
|
|
68
|
-
container:
|
|
68
|
+
container: el,
|
|
69
69
|
direction: direction
|
|
70
70
|
});
|
|
71
71
|
if (next) {
|
|
@@ -77,9 +77,9 @@ function useFocusWrap(_ref) {
|
|
|
77
77
|
// focused element isn't in the focusable list). Fall back to
|
|
78
78
|
// the first or last focusable element depending on direction.
|
|
79
79
|
var fallback = direction === 'forwards' ? (0, _focus.getFirstFocusable)({
|
|
80
|
-
container:
|
|
80
|
+
container: el
|
|
81
81
|
}) : (0, _focus.getLastFocusable)({
|
|
82
|
-
container:
|
|
82
|
+
container: el
|
|
83
83
|
});
|
|
84
84
|
if (fallback) {
|
|
85
85
|
fallback.focus();
|
|
@@ -18,7 +18,7 @@ var _focus = require("../focus/focus");
|
|
|
18
18
|
* - no role / other roles: no focus movement
|
|
19
19
|
*
|
|
20
20
|
* Note: React 18's `autoFocus` JSX prop does NOT set the HTML `autofocus`
|
|
21
|
-
* attribute
|
|
21
|
+
* attribute — it only calls `.focus()` imperatively during commit, which
|
|
22
22
|
* has no effect on hidden popover content. Consumers must set the native
|
|
23
23
|
* attribute via a ref callback (e.g. `node.setAttribute('autofocus', '')`).
|
|
24
24
|
* React 19+ reflects the JSX prop as the HTML attribute automatically.
|
|
@@ -126,21 +126,21 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
126
126
|
// the browser processes light dismiss), read in the toggle handler.
|
|
127
127
|
var closeReasonRef = (0, _react.useRef)('light-dismiss');
|
|
128
128
|
var handleToggle = (0, _react.useCallback)(function (event) {
|
|
129
|
-
var
|
|
129
|
+
var el = ownRef.current;
|
|
130
130
|
if (event.newState === 'open') {
|
|
131
|
-
if (
|
|
131
|
+
if (el) {
|
|
132
132
|
onOpenChange === null || onOpenChange === void 0 || onOpenChange({
|
|
133
133
|
isOpen: true,
|
|
134
|
-
element:
|
|
134
|
+
element: el
|
|
135
135
|
});
|
|
136
136
|
}
|
|
137
137
|
return;
|
|
138
138
|
}
|
|
139
139
|
if (event.newState === 'closed') {
|
|
140
|
-
if (
|
|
140
|
+
if (el) {
|
|
141
141
|
onOpenChange === null || onOpenChange === void 0 || onOpenChange({
|
|
142
142
|
isOpen: false,
|
|
143
|
-
element:
|
|
143
|
+
element: el
|
|
144
144
|
});
|
|
145
145
|
}
|
|
146
146
|
|
|
@@ -158,13 +158,13 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
158
158
|
}
|
|
159
159
|
}, [onClose, onOpenChange]);
|
|
160
160
|
(0, _react.useEffect)(function () {
|
|
161
|
-
var
|
|
162
|
-
if (!
|
|
161
|
+
var el = ownRef.current;
|
|
162
|
+
if (!el) {
|
|
163
163
|
return;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
// Capture-phase: tag Escape before the browser processes light dismiss.
|
|
167
|
-
var unbindEscape = (0, _bindEventListener.bind)(
|
|
167
|
+
var unbindEscape = (0, _bindEventListener.bind)(el, {
|
|
168
168
|
type: 'keydown',
|
|
169
169
|
listener: function listener(event) {
|
|
170
170
|
if (event.key === 'Escape') {
|
|
@@ -175,7 +175,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
|
|
|
175
175
|
capture: true
|
|
176
176
|
}
|
|
177
177
|
});
|
|
178
|
-
var unbindToggle = (0, _bindEventListener.bind)(
|
|
178
|
+
var unbindToggle = (0, _bindEventListener.bind)(el, {
|
|
179
179
|
type: 'toggle',
|
|
180
180
|
listener: handleToggle
|
|
181
181
|
});
|
|
@@ -20,7 +20,7 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
20
20
|
/**
|
|
21
21
|
* Thin context wrapper that composes `Popover` + `useAnchorPosition`.
|
|
22
22
|
*
|
|
23
|
-
* Used inside the `<Popup>` compound
|
|
23
|
+
* Used inside the `<Popup>` compound — reads triggerRef, placement, isOpen,
|
|
24
24
|
* and onClose from context. For standalone usage (tooltip, spotlight, flag),
|
|
25
25
|
* use `Popover` + `useAnchorPosition` directly.
|
|
26
26
|
*/
|
|
@@ -97,7 +97,7 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
|
|
|
97
97
|
// ── Nested popover focus restoration fallback ──
|
|
98
98
|
// The browser only captures `previouslyFocusedElement` for the
|
|
99
99
|
// outermost popover="auto" in the stack. Inner (nested) popovers
|
|
100
|
-
// have shouldRestoreFocus=false, so the browser
|
|
100
|
+
// have shouldRestoreFocus=false, so the browser won't restore
|
|
101
101
|
// focus when they close.
|
|
102
102
|
//
|
|
103
103
|
// We detect this case by checking if focus is still inside the
|
|
@@ -26,7 +26,7 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
26
26
|
* from opening.
|
|
27
27
|
*
|
|
28
28
|
* If you need Compiled `css` on the trigger, use `Popup.TriggerFunction`
|
|
29
|
-
* instead
|
|
29
|
+
* instead — it hands you raw props via a render-prop and avoids
|
|
30
30
|
* `cloneElement` entirely.
|
|
31
31
|
*/
|
|
32
32
|
function PopupTrigger(_ref) {
|
|
@@ -40,7 +40,7 @@ function PopupTrigger(_ref) {
|
|
|
40
40
|
var childOnClick = /*#__PURE__*/(0, _react.isValidElement)(children) ? children.props.onClick : undefined;
|
|
41
41
|
|
|
42
42
|
// Use a ref to track the latest isOpen value so the click handler
|
|
43
|
-
//
|
|
43
|
+
// doesn't need isOpen in its dependency array (which would recreate
|
|
44
44
|
// the handler on every open/close, breaking cloneElement identity).
|
|
45
45
|
var isOpenRef = _react.default.useRef(isOpen);
|
|
46
46
|
isOpenRef.current = isOpen;
|
|
@@ -26,7 +26,7 @@ function useSimpleLightDismiss(_ref) {
|
|
|
26
26
|
var popoverRef = _ref.popoverRef,
|
|
27
27
|
isOpen = _ref.isOpen,
|
|
28
28
|
onClose = _ref.onClose;
|
|
29
|
-
// Keep a stable ref to onClose so the effect
|
|
29
|
+
// Keep a stable ref to onClose so the effect doesn't re-bind on every render.
|
|
30
30
|
var onCloseRef = (0, _react.useRef)(onClose);
|
|
31
31
|
onCloseRef.current = onClose;
|
|
32
32
|
(0, _react.useEffect)(function () {
|
|
@@ -14,7 +14,7 @@ import { getPlacement, placementToPositionArea } from '../internal/use-anchor-po
|
|
|
14
14
|
*
|
|
15
15
|
* Constraints:
|
|
16
16
|
* - `box-shadow` must be `none` (interferes with `clip-path: inset() margin-box`)
|
|
17
|
-
* - `::before` and `::after` are consumed
|
|
17
|
+
* - `::before` and `::after` are consumed — consumers cannot use them
|
|
18
18
|
* - Arrow pseudo-elements use `background: inherit` from the popover element
|
|
19
19
|
*
|
|
20
20
|
* @see https://goulet.dev/posts/tooltip-with-popover-and-anchor-positioning/
|
|
@@ -184,7 +184,7 @@ function positionAreaToRuleName({
|
|
|
184
184
|
* that change both `position-area` and `margin` when flipping.
|
|
185
185
|
*
|
|
186
186
|
* This is required for the arrow technique because built-in keywords
|
|
187
|
-
* (`flip-block`, `flip-inline`) only flip `position-area`
|
|
187
|
+
* (`flip-block`, `flip-inline`) only flip `position-area` — they do
|
|
188
188
|
* not update the margin direction needed to reveal the correct arrow.
|
|
189
189
|
*/
|
|
190
190
|
function getTryFallbacks({
|
|
@@ -120,12 +120,7 @@ export const Dialog = /*#__PURE__*/forwardRef(function Dialog({
|
|
|
120
120
|
const escapedId = CSS.escape(dialogId);
|
|
121
121
|
return /*#__PURE__*/React.createElement("dialog", _extends({
|
|
122
122
|
ref: combinedRef,
|
|
123
|
-
id: dialogId
|
|
124
|
-
// Modern browsers infer modal semantics from `.showModal()` but
|
|
125
|
-
// some assistive tech still keys off `aria-modal="true"`. Setting
|
|
126
|
-
// it explicitly is recommended by WAI-ARIA APG dialog pattern.
|
|
127
|
-
,
|
|
128
|
-
"aria-modal": "true",
|
|
123
|
+
id: dialogId,
|
|
129
124
|
"aria-label": label,
|
|
130
125
|
"aria-labelledby": label ? undefined : labelledBy,
|
|
131
126
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
|
|
@@ -39,7 +39,7 @@ function getFocusables({
|
|
|
39
39
|
container,
|
|
40
40
|
filter
|
|
41
41
|
}) {
|
|
42
|
-
return Array.from(container.querySelectorAll(selectors.focusable)).filter(
|
|
42
|
+
return Array.from(container.querySelectorAll(selectors.focusable)).filter(el => el instanceof HTMLElement).filter(el => !filter || filter(el, container));
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
@@ -13,6 +13,6 @@
|
|
|
13
13
|
*/
|
|
14
14
|
export function combine(...cleanupFns) {
|
|
15
15
|
return function cleanup() {
|
|
16
|
-
cleanupFns.forEach(
|
|
16
|
+
cleanupFns.forEach(fn => fn === null || fn === void 0 ? void 0 : fn());
|
|
17
17
|
};
|
|
18
18
|
}
|
|
@@ -79,6 +79,20 @@ export function placementToPositionArea({
|
|
|
79
79
|
* For aligned placements (start/end), includes the same-edge centered
|
|
80
80
|
* position as fallbacks so the browser can try centering when the aligned
|
|
81
81
|
* position would overflow, before flipping to the opposite edge.
|
|
82
|
+
*
|
|
83
|
+
* **Why `flip-inline flip-block` (or `flip-block flip-inline`) is included:**
|
|
84
|
+
*
|
|
85
|
+
* When a popup is in a viewport corner (e.g. inline-end align-end at the
|
|
86
|
+
* top-right), flipping only the primary axis (`flip-inline`) moves the popup
|
|
87
|
+
* to the left but keeps the same cross-axis span direction (e.g. upward),
|
|
88
|
+
* which is still off-screen. The combined keyword `flip-inline flip-block`
|
|
89
|
+
* mirrors the popup diagonally — it flips BOTH the position-area AND both
|
|
90
|
+
* inline and block margins simultaneously, placing the popup at the
|
|
91
|
+
* diagonally opposite corner where there is always space.
|
|
92
|
+
*
|
|
93
|
+
* Named `position-area` entries (e.g. `inline-start span-block-end`) in
|
|
94
|
+
* `position-try-fallbacks` do NOT update margins, so only the `flip-*`
|
|
95
|
+
* tactic keywords correctly flip the gap margin along with the position.
|
|
82
96
|
*/
|
|
83
97
|
export function placementToTryFallbacks({
|
|
84
98
|
placement
|
|
@@ -96,9 +110,10 @@ export function placementToTryFallbacks({
|
|
|
96
110
|
const sameEdge = `${axis}-${edge}`;
|
|
97
111
|
const oppositeEdge = `${axis}-${flippedEdge}`;
|
|
98
112
|
const flipKeyword = axis === 'block' ? 'flip-block' : 'flip-inline';
|
|
113
|
+
const flipCrossKeyword = axis === 'block' ? 'flip-inline' : 'flip-block';
|
|
114
|
+
// Try same-edge shifts first; two flip entries cover single-edge then corner overflow.
|
|
99
115
|
// Legacy Popper fallbacks for e.g. bottom-start: [bottom, bottom-end, top-start, top, top-end, auto].
|
|
100
|
-
|
|
101
|
-
return [`${sameEdge} span-${crossAxis}-${align === 'start' ? 'end' : 'start'}`, sameEdge, `${sameEdge} span-${crossAxis}-${align === 'start' ? 'start' : 'end'}`, flipKeyword, `${oppositeEdge} span-${crossAxis}-${align === 'start' ? 'end' : 'start'}`, oppositeEdge, `${oppositeEdge} span-${crossAxis}-${align === 'start' ? 'start' : 'end'}`].join(', ');
|
|
116
|
+
return [`${sameEdge} span-${crossAxis}-${align === 'start' ? 'end' : 'start'}`, sameEdge, `${sameEdge} span-${crossAxis}-${align === 'start' ? 'start' : 'end'}`, flipKeyword, `${flipKeyword} ${flipCrossKeyword}`, `${oppositeEdge} span-${crossAxis}-${align === 'start' ? 'end' : 'start'}`, oppositeEdge, `${oppositeEdge} span-${crossAxis}-${align === 'start' ? 'start' : 'end'}`].join(', ');
|
|
102
117
|
}
|
|
103
118
|
const sameEdge = `${axis}-${edge}`;
|
|
104
119
|
const oppositeEdge = `${axis}-${flippedEdge}`;
|
|
@@ -308,6 +323,12 @@ export function useAnchorPosition({
|
|
|
308
323
|
property: 'inset',
|
|
309
324
|
value: 'auto'
|
|
310
325
|
},
|
|
326
|
+
// Ensures the popup's margin box overflows the viewport when its span region is too
|
|
327
|
+
// narrow, triggering position-try-fallbacks correctly rather than wrapping content.
|
|
328
|
+
{
|
|
329
|
+
property: 'min-inline-size',
|
|
330
|
+
value: 'max-content'
|
|
331
|
+
},
|
|
311
332
|
// Main-axis gap between the popover and its trigger
|
|
312
333
|
{
|
|
313
334
|
property: gap.property,
|
|
@@ -467,19 +488,7 @@ export function useAnchorPosition({
|
|
|
467
488
|
// ResizeObserver fires once the browser has real dimensions.
|
|
468
489
|
// Self-disconnects after one valid measurement; ongoing
|
|
469
490
|
// scroll/resize is handled by the window listeners below.
|
|
470
|
-
|
|
471
|
-
// (e.g. post-office's `node` environment). Fall back to a no-op
|
|
472
|
-
// observer there — the scroll/resize listeners below still keep
|
|
473
|
-
// the popover positioned in the rare case the consumer also
|
|
474
|
-
// polyfilled `showPopover` but not `ResizeObserver`. Real
|
|
475
|
-
// browsers always have it.
|
|
476
|
-
const NoopResizeObserver = class {
|
|
477
|
-
observe() {}
|
|
478
|
-
unobserve() {}
|
|
479
|
-
disconnect() {}
|
|
480
|
-
};
|
|
481
|
-
const ResizeObserverImpl = typeof ResizeObserver !== 'undefined' ? ResizeObserver : NoopResizeObserver;
|
|
482
|
-
const resizeObserver = new ResizeObserverImpl(() => {
|
|
491
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
483
492
|
if (popover.offsetWidth > 0 && popover.offsetHeight > 0) {
|
|
484
493
|
update();
|
|
485
494
|
resizeObserver.disconnect();
|
|
@@ -104,8 +104,8 @@ export function useAnimatedVisibility({
|
|
|
104
104
|
if (isOpen || !showChildren || !willAnimate) {
|
|
105
105
|
return;
|
|
106
106
|
}
|
|
107
|
-
const
|
|
108
|
-
if (!
|
|
107
|
+
const el = elementRef.current;
|
|
108
|
+
if (!el) {
|
|
109
109
|
return;
|
|
110
110
|
}
|
|
111
111
|
function finish() {
|
|
@@ -119,7 +119,7 @@ export function useAnimatedVisibility({
|
|
|
119
119
|
const fallbackId = setTimeout(finish, ((_preset$exitDurationM = preset === null || preset === void 0 ? void 0 : preset.exitDurationMs) !== null && _preset$exitDurationM !== void 0 ? _preset$exitDurationM : 0) + 50);
|
|
120
120
|
|
|
121
121
|
// Primary: listen for the CSS transition to complete
|
|
122
|
-
const unbind = bind(
|
|
122
|
+
const unbind = bind(el, {
|
|
123
123
|
type: 'transitionend',
|
|
124
124
|
listener: finish,
|
|
125
125
|
options: {
|
|
@@ -34,7 +34,7 @@ function roleRequiresFocusWrap(role) {
|
|
|
34
34
|
* elements within the container using wrapping navigation.
|
|
35
35
|
*
|
|
36
36
|
* Light dismiss (Escape, click outside) continues to work natively
|
|
37
|
-
* via `popover="auto"`
|
|
37
|
+
* via `popover="auto"` — this hook only intercepts Tab.
|
|
38
38
|
*
|
|
39
39
|
* Always call this hook unconditionally. The listener is only
|
|
40
40
|
* attached when the role requires focus wrapping, and is cleaned
|
|
@@ -45,11 +45,11 @@ export function useFocusWrap({
|
|
|
45
45
|
role
|
|
46
46
|
}) {
|
|
47
47
|
useEffect(() => {
|
|
48
|
-
const
|
|
49
|
-
if (!
|
|
48
|
+
const el = elementRef.current;
|
|
49
|
+
if (!el || !roleRequiresFocusWrap(role)) {
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
|
-
const unbind = bind(
|
|
52
|
+
const unbind = bind(el, {
|
|
53
53
|
type: 'keydown',
|
|
54
54
|
listener: event => {
|
|
55
55
|
if (event.key !== 'Tab') {
|
|
@@ -61,7 +61,7 @@ export function useFocusWrap({
|
|
|
61
61
|
// Try to move to the next/previous focusable element relative
|
|
62
62
|
// to the currently focused element within the container.
|
|
63
63
|
const next = getNextFocusable({
|
|
64
|
-
container:
|
|
64
|
+
container: el,
|
|
65
65
|
direction
|
|
66
66
|
});
|
|
67
67
|
if (next) {
|
|
@@ -73,9 +73,9 @@ export function useFocusWrap({
|
|
|
73
73
|
// focused element isn't in the focusable list). Fall back to
|
|
74
74
|
// the first or last focusable element depending on direction.
|
|
75
75
|
const fallback = direction === 'forwards' ? getFirstFocusable({
|
|
76
|
-
container:
|
|
76
|
+
container: el
|
|
77
77
|
}) : getLastFocusable({
|
|
78
|
-
container:
|
|
78
|
+
container: el
|
|
79
79
|
});
|
|
80
80
|
if (fallback) {
|
|
81
81
|
fallback.focus();
|
|
@@ -13,7 +13,7 @@ import { getFirstFocusable } from '../focus/focus';
|
|
|
13
13
|
* - no role / other roles: no focus movement
|
|
14
14
|
*
|
|
15
15
|
* Note: React 18's `autoFocus` JSX prop does NOT set the HTML `autofocus`
|
|
16
|
-
* attribute
|
|
16
|
+
* attribute — it only calls `.focus()` imperatively during commit, which
|
|
17
17
|
* has no effect on hidden popover content. Consumers must set the native
|
|
18
18
|
* attribute via a ref callback (e.g. `node.setAttribute('autofocus', '')`).
|
|
19
19
|
* React 19+ reflects the JSX prop as the HTML attribute automatically.
|
|
@@ -116,21 +116,21 @@ export const Popover = /*#__PURE__*/forwardRef(function Popover({
|
|
|
116
116
|
// the browser processes light dismiss), read in the toggle handler.
|
|
117
117
|
const closeReasonRef = useRef('light-dismiss');
|
|
118
118
|
const handleToggle = useCallback(event => {
|
|
119
|
-
const
|
|
119
|
+
const el = ownRef.current;
|
|
120
120
|
if (event.newState === 'open') {
|
|
121
|
-
if (
|
|
121
|
+
if (el) {
|
|
122
122
|
onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange({
|
|
123
123
|
isOpen: true,
|
|
124
|
-
element:
|
|
124
|
+
element: el
|
|
125
125
|
});
|
|
126
126
|
}
|
|
127
127
|
return;
|
|
128
128
|
}
|
|
129
129
|
if (event.newState === 'closed') {
|
|
130
|
-
if (
|
|
130
|
+
if (el) {
|
|
131
131
|
onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange({
|
|
132
132
|
isOpen: false,
|
|
133
|
-
element:
|
|
133
|
+
element: el
|
|
134
134
|
});
|
|
135
135
|
}
|
|
136
136
|
|
|
@@ -148,13 +148,13 @@ export const Popover = /*#__PURE__*/forwardRef(function Popover({
|
|
|
148
148
|
}
|
|
149
149
|
}, [onClose, onOpenChange]);
|
|
150
150
|
useEffect(() => {
|
|
151
|
-
const
|
|
152
|
-
if (!
|
|
151
|
+
const el = ownRef.current;
|
|
152
|
+
if (!el) {
|
|
153
153
|
return;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
// Capture-phase: tag Escape before the browser processes light dismiss.
|
|
157
|
-
const unbindEscape = bind(
|
|
157
|
+
const unbindEscape = bind(el, {
|
|
158
158
|
type: 'keydown',
|
|
159
159
|
listener: event => {
|
|
160
160
|
if (event.key === 'Escape') {
|
|
@@ -165,7 +165,7 @@ export const Popover = /*#__PURE__*/forwardRef(function Popover({
|
|
|
165
165
|
capture: true
|
|
166
166
|
}
|
|
167
167
|
});
|
|
168
|
-
const unbindToggle = bind(
|
|
168
|
+
const unbindToggle = bind(el, {
|
|
169
169
|
type: 'toggle',
|
|
170
170
|
listener: handleToggle
|
|
171
171
|
});
|
|
@@ -11,7 +11,7 @@ import { useMaybePopupContext } from './popup-context';
|
|
|
11
11
|
/**
|
|
12
12
|
* Thin context wrapper that composes `Popover` + `useAnchorPosition`.
|
|
13
13
|
*
|
|
14
|
-
* Used inside the `<Popup>` compound
|
|
14
|
+
* Used inside the `<Popup>` compound — reads triggerRef, placement, isOpen,
|
|
15
15
|
* and onClose from context. For standalone usage (tooltip, spotlight, flag),
|
|
16
16
|
* use `Popover` + `useAnchorPosition` directly.
|
|
17
17
|
*/
|
|
@@ -88,7 +88,7 @@ export const PopupContent = /*#__PURE__*/forwardRef(function PopupContent({
|
|
|
88
88
|
// ── Nested popover focus restoration fallback ──
|
|
89
89
|
// The browser only captures `previouslyFocusedElement` for the
|
|
90
90
|
// outermost popover="auto" in the stack. Inner (nested) popovers
|
|
91
|
-
// have shouldRestoreFocus=false, so the browser
|
|
91
|
+
// have shouldRestoreFocus=false, so the browser won't restore
|
|
92
92
|
// focus when they close.
|
|
93
93
|
//
|
|
94
94
|
// We detect this case by checking if focus is still inside the
|
|
@@ -18,7 +18,7 @@ import { usePopupContext } from './popup-context';
|
|
|
18
18
|
* from opening.
|
|
19
19
|
*
|
|
20
20
|
* If you need Compiled `css` on the trigger, use `Popup.TriggerFunction`
|
|
21
|
-
* instead
|
|
21
|
+
* instead — it hands you raw props via a render-prop and avoids
|
|
22
22
|
* `cloneElement` entirely.
|
|
23
23
|
*/
|
|
24
24
|
export function PopupTrigger({
|
|
@@ -34,7 +34,7 @@ export function PopupTrigger({
|
|
|
34
34
|
const childOnClick = /*#__PURE__*/isValidElement(children) ? children.props.onClick : undefined;
|
|
35
35
|
|
|
36
36
|
// Use a ref to track the latest isOpen value so the click handler
|
|
37
|
-
//
|
|
37
|
+
// doesn't need isOpen in its dependency array (which would recreate
|
|
38
38
|
// the handler on every open/close, breaking cloneElement identity).
|
|
39
39
|
const isOpenRef = React.useRef(isOpen);
|
|
40
40
|
isOpenRef.current = isOpen;
|
|
@@ -21,7 +21,7 @@ export function useSimpleLightDismiss({
|
|
|
21
21
|
isOpen,
|
|
22
22
|
onClose
|
|
23
23
|
}) {
|
|
24
|
-
// Keep a stable ref to onClose so the effect
|
|
24
|
+
// Keep a stable ref to onClose so the effect doesn't re-bind on every render.
|
|
25
25
|
const onCloseRef = useRef(onClose);
|
|
26
26
|
onCloseRef.current = onClose;
|
|
27
27
|
useEffect(() => {
|
package/dist/esm/arrow/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { getPlacement, placementToPositionArea } from '../internal/use-anchor-po
|
|
|
14
14
|
*
|
|
15
15
|
* Constraints:
|
|
16
16
|
* - `box-shadow` must be `none` (interferes with `clip-path: inset() margin-box`)
|
|
17
|
-
* - `::before` and `::after` are consumed
|
|
17
|
+
* - `::before` and `::after` are consumed — consumers cannot use them
|
|
18
18
|
* - Arrow pseudo-elements use `background: inherit` from the popover element
|
|
19
19
|
*
|
|
20
20
|
* @see https://goulet.dev/posts/tooltip-with-popover-and-anchor-positioning/
|
|
@@ -39,7 +39,7 @@ function positionAreaToRuleName(_ref) {
|
|
|
39
39
|
* that change both `position-area` and `margin` when flipping.
|
|
40
40
|
*
|
|
41
41
|
* This is required for the arrow technique because built-in keywords
|
|
42
|
-
* (`flip-block`, `flip-inline`) only flip `position-area`
|
|
42
|
+
* (`flip-block`, `flip-inline`) only flip `position-area` — they do
|
|
43
43
|
* not update the margin direction needed to reveal the correct arrow.
|
|
44
44
|
*/
|
|
45
45
|
function getTryFallbacks(_ref2) {
|
|
@@ -119,12 +119,7 @@ export var Dialog = /*#__PURE__*/forwardRef(function Dialog(_ref, ref) {
|
|
|
119
119
|
var escapedId = CSS.escape(dialogId);
|
|
120
120
|
return /*#__PURE__*/React.createElement("dialog", _extends({
|
|
121
121
|
ref: combinedRef,
|
|
122
|
-
id: dialogId
|
|
123
|
-
// Modern browsers infer modal semantics from `.showModal()` but
|
|
124
|
-
// some assistive tech still keys off `aria-modal="true"`. Setting
|
|
125
|
-
// it explicitly is recommended by WAI-ARIA APG dialog pattern.
|
|
126
|
-
,
|
|
127
|
-
"aria-modal": "true",
|
|
122
|
+
id: dialogId,
|
|
128
123
|
"aria-label": label,
|
|
129
124
|
"aria-labelledby": label ? undefined : labelledBy,
|
|
130
125
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
|
package/dist/esm/focus/focus.js
CHANGED
|
@@ -38,10 +38,10 @@ var selectors = function () {
|
|
|
38
38
|
function getFocusables(_ref) {
|
|
39
39
|
var container = _ref.container,
|
|
40
40
|
filter = _ref.filter;
|
|
41
|
-
return Array.from(container.querySelectorAll(selectors.focusable)).filter(function (
|
|
42
|
-
return
|
|
43
|
-
}).filter(function (
|
|
44
|
-
return !filter || filter(
|
|
41
|
+
return Array.from(container.querySelectorAll(selectors.focusable)).filter(function (el) {
|
|
42
|
+
return el instanceof HTMLElement;
|
|
43
|
+
}).filter(function (el) {
|
|
44
|
+
return !filter || filter(el, container);
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -16,8 +16,8 @@ export function combine() {
|
|
|
16
16
|
cleanupFns[_key] = arguments[_key];
|
|
17
17
|
}
|
|
18
18
|
return function cleanup() {
|
|
19
|
-
cleanupFns.forEach(function (
|
|
20
|
-
return
|
|
19
|
+
cleanupFns.forEach(function (fn) {
|
|
20
|
+
return fn === null || fn === void 0 ? void 0 : fn();
|
|
21
21
|
});
|
|
22
22
|
};
|
|
23
23
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
2
|
-
import _createClass from "@babel/runtime/helpers/createClass";
|
|
3
1
|
/**
|
|
4
2
|
* Anchor positioning for top-layer popovers. See
|
|
5
3
|
* `notes/architecture/positioning.md` for the full model.
|
|
@@ -79,6 +77,20 @@ export function placementToPositionArea(_ref) {
|
|
|
79
77
|
* For aligned placements (start/end), includes the same-edge centered
|
|
80
78
|
* position as fallbacks so the browser can try centering when the aligned
|
|
81
79
|
* position would overflow, before flipping to the opposite edge.
|
|
80
|
+
*
|
|
81
|
+
* **Why `flip-inline flip-block` (or `flip-block flip-inline`) is included:**
|
|
82
|
+
*
|
|
83
|
+
* When a popup is in a viewport corner (e.g. inline-end align-end at the
|
|
84
|
+
* top-right), flipping only the primary axis (`flip-inline`) moves the popup
|
|
85
|
+
* to the left but keeps the same cross-axis span direction (e.g. upward),
|
|
86
|
+
* which is still off-screen. The combined keyword `flip-inline flip-block`
|
|
87
|
+
* mirrors the popup diagonally — it flips BOTH the position-area AND both
|
|
88
|
+
* inline and block margins simultaneously, placing the popup at the
|
|
89
|
+
* diagonally opposite corner where there is always space.
|
|
90
|
+
*
|
|
91
|
+
* Named `position-area` entries (e.g. `inline-start span-block-end`) in
|
|
92
|
+
* `position-try-fallbacks` do NOT update margins, so only the `flip-*`
|
|
93
|
+
* tactic keywords correctly flip the gap margin along with the position.
|
|
82
94
|
*/
|
|
83
95
|
export function placementToTryFallbacks(_ref2) {
|
|
84
96
|
var placement = _ref2.placement;
|
|
@@ -94,9 +106,10 @@ export function placementToTryFallbacks(_ref2) {
|
|
|
94
106
|
var _sameEdge = "".concat(axis, "-").concat(edge);
|
|
95
107
|
var _oppositeEdge = "".concat(axis, "-").concat(flippedEdge);
|
|
96
108
|
var _flipKeyword = axis === 'block' ? 'flip-block' : 'flip-inline';
|
|
109
|
+
var flipCrossKeyword = axis === 'block' ? 'flip-inline' : 'flip-block';
|
|
110
|
+
// Try same-edge shifts first; two flip entries cover single-edge then corner overflow.
|
|
97
111
|
// Legacy Popper fallbacks for e.g. bottom-start: [bottom, bottom-end, top-start, top, top-end, auto].
|
|
98
|
-
|
|
99
|
-
return ["".concat(_sameEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'end' : 'start'), _sameEdge, "".concat(_sameEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'start' : 'end'), _flipKeyword, "".concat(_oppositeEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'end' : 'start'), _oppositeEdge, "".concat(_oppositeEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'start' : 'end')].join(', ');
|
|
112
|
+
return ["".concat(_sameEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'end' : 'start'), _sameEdge, "".concat(_sameEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'start' : 'end'), _flipKeyword, "".concat(_flipKeyword, " ").concat(flipCrossKeyword), "".concat(_oppositeEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'end' : 'start'), _oppositeEdge, "".concat(_oppositeEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'start' : 'end')].join(', ');
|
|
100
113
|
}
|
|
101
114
|
var sameEdge = "".concat(axis, "-").concat(edge);
|
|
102
115
|
var oppositeEdge = "".concat(axis, "-").concat(flippedEdge);
|
|
@@ -301,6 +314,12 @@ export function useAnchorPosition(_ref5) {
|
|
|
301
314
|
property: 'inset',
|
|
302
315
|
value: 'auto'
|
|
303
316
|
},
|
|
317
|
+
// Ensures the popup's margin box overflows the viewport when its span region is too
|
|
318
|
+
// narrow, triggering position-try-fallbacks correctly rather than wrapping content.
|
|
319
|
+
{
|
|
320
|
+
property: 'min-inline-size',
|
|
321
|
+
value: 'max-content'
|
|
322
|
+
},
|
|
304
323
|
// Main-axis gap between the popover and its trigger
|
|
305
324
|
{
|
|
306
325
|
property: gap.property,
|
|
@@ -461,29 +480,7 @@ export function useAnchorPosition(_ref5) {
|
|
|
461
480
|
// ResizeObserver fires once the browser has real dimensions.
|
|
462
481
|
// Self-disconnects after one valid measurement; ongoing
|
|
463
482
|
// scroll/resize is handled by the window listeners below.
|
|
464
|
-
|
|
465
|
-
// (e.g. post-office's `node` environment). Fall back to a no-op
|
|
466
|
-
// observer there — the scroll/resize listeners below still keep
|
|
467
|
-
// the popover positioned in the rare case the consumer also
|
|
468
|
-
// polyfilled `showPopover` but not `ResizeObserver`. Real
|
|
469
|
-
// browsers always have it.
|
|
470
|
-
var NoopResizeObserver = /*#__PURE__*/function () {
|
|
471
|
-
function NoopResizeObserver() {
|
|
472
|
-
_classCallCheck(this, NoopResizeObserver);
|
|
473
|
-
}
|
|
474
|
-
return _createClass(NoopResizeObserver, [{
|
|
475
|
-
key: "observe",
|
|
476
|
-
value: function observe() {}
|
|
477
|
-
}, {
|
|
478
|
-
key: "unobserve",
|
|
479
|
-
value: function unobserve() {}
|
|
480
|
-
}, {
|
|
481
|
-
key: "disconnect",
|
|
482
|
-
value: function disconnect() {}
|
|
483
|
-
}]);
|
|
484
|
-
}();
|
|
485
|
-
var ResizeObserverImpl = typeof ResizeObserver !== 'undefined' ? ResizeObserver : NoopResizeObserver;
|
|
486
|
-
var resizeObserver = new ResizeObserverImpl(function () {
|
|
483
|
+
var resizeObserver = new ResizeObserver(function () {
|
|
487
484
|
if (popover.offsetWidth > 0 && popover.offsetHeight > 0) {
|
|
488
485
|
update();
|
|
489
486
|
resizeObserver.disconnect();
|
|
@@ -107,8 +107,8 @@ export function useAnimatedVisibility(_ref) {
|
|
|
107
107
|
if (isOpen || !showChildren || !willAnimate) {
|
|
108
108
|
return;
|
|
109
109
|
}
|
|
110
|
-
var
|
|
111
|
-
if (!
|
|
110
|
+
var el = elementRef.current;
|
|
111
|
+
if (!el) {
|
|
112
112
|
return;
|
|
113
113
|
}
|
|
114
114
|
function finish() {
|
|
@@ -122,7 +122,7 @@ export function useAnimatedVisibility(_ref) {
|
|
|
122
122
|
var fallbackId = setTimeout(finish, ((_preset$exitDurationM = preset === null || preset === void 0 ? void 0 : preset.exitDurationMs) !== null && _preset$exitDurationM !== void 0 ? _preset$exitDurationM : 0) + 50);
|
|
123
123
|
|
|
124
124
|
// Primary: listen for the CSS transition to complete
|
|
125
|
-
var unbind = bind(
|
|
125
|
+
var unbind = bind(el, {
|
|
126
126
|
type: 'transitionend',
|
|
127
127
|
listener: finish,
|
|
128
128
|
options: {
|
|
@@ -34,7 +34,7 @@ function roleRequiresFocusWrap(role) {
|
|
|
34
34
|
* elements within the container using wrapping navigation.
|
|
35
35
|
*
|
|
36
36
|
* Light dismiss (Escape, click outside) continues to work natively
|
|
37
|
-
* via `popover="auto"`
|
|
37
|
+
* via `popover="auto"` — this hook only intercepts Tab.
|
|
38
38
|
*
|
|
39
39
|
* Always call this hook unconditionally. The listener is only
|
|
40
40
|
* attached when the role requires focus wrapping, and is cleaned
|
|
@@ -44,11 +44,11 @@ export function useFocusWrap(_ref) {
|
|
|
44
44
|
var elementRef = _ref.elementRef,
|
|
45
45
|
role = _ref.role;
|
|
46
46
|
useEffect(function () {
|
|
47
|
-
var
|
|
48
|
-
if (!
|
|
47
|
+
var el = elementRef.current;
|
|
48
|
+
if (!el || !roleRequiresFocusWrap(role)) {
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
|
-
var unbind = bind(
|
|
51
|
+
var unbind = bind(el, {
|
|
52
52
|
type: 'keydown',
|
|
53
53
|
listener: function listener(event) {
|
|
54
54
|
if (event.key !== 'Tab') {
|
|
@@ -60,7 +60,7 @@ export function useFocusWrap(_ref) {
|
|
|
60
60
|
// Try to move to the next/previous focusable element relative
|
|
61
61
|
// to the currently focused element within the container.
|
|
62
62
|
var next = getNextFocusable({
|
|
63
|
-
container:
|
|
63
|
+
container: el,
|
|
64
64
|
direction: direction
|
|
65
65
|
});
|
|
66
66
|
if (next) {
|
|
@@ -72,9 +72,9 @@ export function useFocusWrap(_ref) {
|
|
|
72
72
|
// focused element isn't in the focusable list). Fall back to
|
|
73
73
|
// the first or last focusable element depending on direction.
|
|
74
74
|
var fallback = direction === 'forwards' ? getFirstFocusable({
|
|
75
|
-
container:
|
|
75
|
+
container: el
|
|
76
76
|
}) : getLastFocusable({
|
|
77
|
-
container:
|
|
77
|
+
container: el
|
|
78
78
|
});
|
|
79
79
|
if (fallback) {
|
|
80
80
|
fallback.focus();
|
|
@@ -13,7 +13,7 @@ import { getFirstFocusable } from '../focus/focus';
|
|
|
13
13
|
* - no role / other roles: no focus movement
|
|
14
14
|
*
|
|
15
15
|
* Note: React 18's `autoFocus` JSX prop does NOT set the HTML `autofocus`
|
|
16
|
-
* attribute
|
|
16
|
+
* attribute — it only calls `.focus()` imperatively during commit, which
|
|
17
17
|
* has no effect on hidden popover content. Consumers must set the native
|
|
18
18
|
* attribute via a ref callback (e.g. `node.setAttribute('autofocus', '')`).
|
|
19
19
|
* React 19+ reflects the JSX prop as the HTML attribute automatically.
|
|
@@ -117,21 +117,21 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
|
|
|
117
117
|
// the browser processes light dismiss), read in the toggle handler.
|
|
118
118
|
var closeReasonRef = useRef('light-dismiss');
|
|
119
119
|
var handleToggle = useCallback(function (event) {
|
|
120
|
-
var
|
|
120
|
+
var el = ownRef.current;
|
|
121
121
|
if (event.newState === 'open') {
|
|
122
|
-
if (
|
|
122
|
+
if (el) {
|
|
123
123
|
onOpenChange === null || onOpenChange === void 0 || onOpenChange({
|
|
124
124
|
isOpen: true,
|
|
125
|
-
element:
|
|
125
|
+
element: el
|
|
126
126
|
});
|
|
127
127
|
}
|
|
128
128
|
return;
|
|
129
129
|
}
|
|
130
130
|
if (event.newState === 'closed') {
|
|
131
|
-
if (
|
|
131
|
+
if (el) {
|
|
132
132
|
onOpenChange === null || onOpenChange === void 0 || onOpenChange({
|
|
133
133
|
isOpen: false,
|
|
134
|
-
element:
|
|
134
|
+
element: el
|
|
135
135
|
});
|
|
136
136
|
}
|
|
137
137
|
|
|
@@ -149,13 +149,13 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
|
|
|
149
149
|
}
|
|
150
150
|
}, [onClose, onOpenChange]);
|
|
151
151
|
useEffect(function () {
|
|
152
|
-
var
|
|
153
|
-
if (!
|
|
152
|
+
var el = ownRef.current;
|
|
153
|
+
if (!el) {
|
|
154
154
|
return;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
// Capture-phase: tag Escape before the browser processes light dismiss.
|
|
158
|
-
var unbindEscape = bind(
|
|
158
|
+
var unbindEscape = bind(el, {
|
|
159
159
|
type: 'keydown',
|
|
160
160
|
listener: function listener(event) {
|
|
161
161
|
if (event.key === 'Escape') {
|
|
@@ -166,7 +166,7 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
|
|
|
166
166
|
capture: true
|
|
167
167
|
}
|
|
168
168
|
});
|
|
169
|
-
var unbindToggle = bind(
|
|
169
|
+
var unbindToggle = bind(el, {
|
|
170
170
|
type: 'toggle',
|
|
171
171
|
listener: handleToggle
|
|
172
172
|
});
|
|
@@ -11,7 +11,7 @@ import { useMaybePopupContext } from './popup-context';
|
|
|
11
11
|
/**
|
|
12
12
|
* Thin context wrapper that composes `Popover` + `useAnchorPosition`.
|
|
13
13
|
*
|
|
14
|
-
* Used inside the `<Popup>` compound
|
|
14
|
+
* Used inside the `<Popup>` compound — reads triggerRef, placement, isOpen,
|
|
15
15
|
* and onClose from context. For standalone usage (tooltip, spotlight, flag),
|
|
16
16
|
* use `Popover` + `useAnchorPosition` directly.
|
|
17
17
|
*/
|
|
@@ -88,7 +88,7 @@ export var PopupContent = /*#__PURE__*/forwardRef(function PopupContent(_ref, re
|
|
|
88
88
|
// ── Nested popover focus restoration fallback ──
|
|
89
89
|
// The browser only captures `previouslyFocusedElement` for the
|
|
90
90
|
// outermost popover="auto" in the stack. Inner (nested) popovers
|
|
91
|
-
// have shouldRestoreFocus=false, so the browser
|
|
91
|
+
// have shouldRestoreFocus=false, so the browser won't restore
|
|
92
92
|
// focus when they close.
|
|
93
93
|
//
|
|
94
94
|
// We detect this case by checking if focus is still inside the
|
|
@@ -18,7 +18,7 @@ import { usePopupContext } from './popup-context';
|
|
|
18
18
|
* from opening.
|
|
19
19
|
*
|
|
20
20
|
* If you need Compiled `css` on the trigger, use `Popup.TriggerFunction`
|
|
21
|
-
* instead
|
|
21
|
+
* instead — it hands you raw props via a render-prop and avoids
|
|
22
22
|
* `cloneElement` entirely.
|
|
23
23
|
*/
|
|
24
24
|
export function PopupTrigger(_ref) {
|
|
@@ -32,7 +32,7 @@ export function PopupTrigger(_ref) {
|
|
|
32
32
|
var childOnClick = /*#__PURE__*/isValidElement(children) ? children.props.onClick : undefined;
|
|
33
33
|
|
|
34
34
|
// Use a ref to track the latest isOpen value so the click handler
|
|
35
|
-
//
|
|
35
|
+
// doesn't need isOpen in its dependency array (which would recreate
|
|
36
36
|
// the handler on every open/close, breaking cloneElement identity).
|
|
37
37
|
var isOpenRef = React.useRef(isOpen);
|
|
38
38
|
isOpenRef.current = isOpen;
|
|
@@ -20,7 +20,7 @@ export function useSimpleLightDismiss(_ref) {
|
|
|
20
20
|
var popoverRef = _ref.popoverRef,
|
|
21
21
|
isOpen = _ref.isOpen,
|
|
22
22
|
onClose = _ref.onClose;
|
|
23
|
-
// Keep a stable ref to onClose so the effect
|
|
23
|
+
// Keep a stable ref to onClose so the effect doesn't re-bind on every render.
|
|
24
24
|
var onCloseRef = useRef(onClose);
|
|
25
25
|
onCloseRef.current = onClose;
|
|
26
26
|
useEffect(function () {
|
|
@@ -53,6 +53,20 @@ export declare function placementToPositionArea({ placement }: {
|
|
|
53
53
|
* For aligned placements (start/end), includes the same-edge centered
|
|
54
54
|
* position as fallbacks so the browser can try centering when the aligned
|
|
55
55
|
* position would overflow, before flipping to the opposite edge.
|
|
56
|
+
*
|
|
57
|
+
* **Why `flip-inline flip-block` (or `flip-block flip-inline`) is included:**
|
|
58
|
+
*
|
|
59
|
+
* When a popup is in a viewport corner (e.g. inline-end align-end at the
|
|
60
|
+
* top-right), flipping only the primary axis (`flip-inline`) moves the popup
|
|
61
|
+
* to the left but keeps the same cross-axis span direction (e.g. upward),
|
|
62
|
+
* which is still off-screen. The combined keyword `flip-inline flip-block`
|
|
63
|
+
* mirrors the popup diagonally — it flips BOTH the position-area AND both
|
|
64
|
+
* inline and block margins simultaneously, placing the popup at the
|
|
65
|
+
* diagonally opposite corner where there is always space.
|
|
66
|
+
*
|
|
67
|
+
* Named `position-area` entries (e.g. `inline-start span-block-end`) in
|
|
68
|
+
* `position-try-fallbacks` do NOT update margins, so only the `flip-*`
|
|
69
|
+
* tactic keywords correctly flip the gap margin along with the position.
|
|
56
70
|
*/
|
|
57
71
|
export declare function placementToTryFallbacks({ placement }: {
|
|
58
72
|
placement: TPlacementOptions;
|
|
@@ -118,7 +132,7 @@ export declare function useAnchorPosition({ anchorRef, popoverRef, placement, fo
|
|
|
118
132
|
* the preset's named `@position-try` rules (which update both
|
|
119
133
|
* `position-area` and `margin` on flip) and sets `--ds-arrow-size`.
|
|
120
134
|
*
|
|
121
|
-
* Pass `null` to disable. Has no effect in the JS fallback path
|
|
135
|
+
* Pass `null` to disable. Has no effect in the JS fallback path —
|
|
122
136
|
* arrows are CSS-only.
|
|
123
137
|
*/
|
|
124
138
|
arrow?: TArrowPreset | null;
|
|
@@ -8,7 +8,7 @@ import { type RefObject } from 'react';
|
|
|
8
8
|
* elements within the container using wrapping navigation.
|
|
9
9
|
*
|
|
10
10
|
* Light dismiss (Escape, click outside) continues to work natively
|
|
11
|
-
* via `popover="auto"`
|
|
11
|
+
* via `popover="auto"` — this hook only intercepts Tab.
|
|
12
12
|
*
|
|
13
13
|
* Always call this hook unconditionally. The listener is only
|
|
14
14
|
* attached when the role requires focus wrapping, and is cleaned
|
|
@@ -7,7 +7,7 @@ import { type TPopupContentProps } from './types';
|
|
|
7
7
|
/**
|
|
8
8
|
* Thin context wrapper that composes `Popover` + `useAnchorPosition`.
|
|
9
9
|
*
|
|
10
|
-
* Used inside the `<Popup>` compound
|
|
10
|
+
* Used inside the `<Popup>` compound — reads triggerRef, placement, isOpen,
|
|
11
11
|
* and onClose from context. For standalone usage (tooltip, spotlight, flag),
|
|
12
12
|
* use `Popover` + `useAnchorPosition` directly.
|
|
13
13
|
*/
|
|
@@ -17,7 +17,7 @@ import { type TPopupTriggerProps } from './types';
|
|
|
17
17
|
* from opening.
|
|
18
18
|
*
|
|
19
19
|
* If you need Compiled `css` on the trigger, use `Popup.TriggerFunction`
|
|
20
|
-
* instead
|
|
20
|
+
* instead — it hands you raw props via a render-prop and avoids
|
|
21
21
|
* `cloneElement` entirely.
|
|
22
22
|
*/
|
|
23
23
|
export declare function PopupTrigger({ children }: TPopupTriggerProps): ReactNode;
|
|
@@ -13,12 +13,12 @@ type TUseSimpleLightDismissOptions = {
|
|
|
13
13
|
/**
|
|
14
14
|
* Called when a light-dismiss event occurs.
|
|
15
15
|
*
|
|
16
|
-
* - `reason: 'escape'`
|
|
17
|
-
* - `reason: 'light-dismiss'`
|
|
16
|
+
* - `reason: 'escape'` — the user pressed the Escape key.
|
|
17
|
+
* - `reason: 'light-dismiss'` — the user clicked outside the popover.
|
|
18
18
|
*
|
|
19
19
|
* **Note:** This hook provides simple, standalone light dismiss that does not
|
|
20
20
|
* participate in the browser's `popover="auto"` dismiss stack. Every active
|
|
21
|
-
* instance will fire independently
|
|
21
|
+
* instance will fire independently — if multiple popovers use this hook,
|
|
22
22
|
* they will all receive dismiss events.
|
|
23
23
|
*/
|
|
24
24
|
onClose: (args: {
|
|
@@ -53,6 +53,20 @@ export declare function placementToPositionArea({ placement }: {
|
|
|
53
53
|
* For aligned placements (start/end), includes the same-edge centered
|
|
54
54
|
* position as fallbacks so the browser can try centering when the aligned
|
|
55
55
|
* position would overflow, before flipping to the opposite edge.
|
|
56
|
+
*
|
|
57
|
+
* **Why `flip-inline flip-block` (or `flip-block flip-inline`) is included:**
|
|
58
|
+
*
|
|
59
|
+
* When a popup is in a viewport corner (e.g. inline-end align-end at the
|
|
60
|
+
* top-right), flipping only the primary axis (`flip-inline`) moves the popup
|
|
61
|
+
* to the left but keeps the same cross-axis span direction (e.g. upward),
|
|
62
|
+
* which is still off-screen. The combined keyword `flip-inline flip-block`
|
|
63
|
+
* mirrors the popup diagonally — it flips BOTH the position-area AND both
|
|
64
|
+
* inline and block margins simultaneously, placing the popup at the
|
|
65
|
+
* diagonally opposite corner where there is always space.
|
|
66
|
+
*
|
|
67
|
+
* Named `position-area` entries (e.g. `inline-start span-block-end`) in
|
|
68
|
+
* `position-try-fallbacks` do NOT update margins, so only the `flip-*`
|
|
69
|
+
* tactic keywords correctly flip the gap margin along with the position.
|
|
56
70
|
*/
|
|
57
71
|
export declare function placementToTryFallbacks({ placement }: {
|
|
58
72
|
placement: TPlacementOptions;
|
|
@@ -118,7 +132,7 @@ export declare function useAnchorPosition({ anchorRef, popoverRef, placement, fo
|
|
|
118
132
|
* the preset's named `@position-try` rules (which update both
|
|
119
133
|
* `position-area` and `margin` on flip) and sets `--ds-arrow-size`.
|
|
120
134
|
*
|
|
121
|
-
* Pass `null` to disable. Has no effect in the JS fallback path
|
|
135
|
+
* Pass `null` to disable. Has no effect in the JS fallback path —
|
|
122
136
|
* arrows are CSS-only.
|
|
123
137
|
*/
|
|
124
138
|
arrow?: TArrowPreset | null;
|
|
@@ -8,7 +8,7 @@ import { type RefObject } from 'react';
|
|
|
8
8
|
* elements within the container using wrapping navigation.
|
|
9
9
|
*
|
|
10
10
|
* Light dismiss (Escape, click outside) continues to work natively
|
|
11
|
-
* via `popover="auto"`
|
|
11
|
+
* via `popover="auto"` — this hook only intercepts Tab.
|
|
12
12
|
*
|
|
13
13
|
* Always call this hook unconditionally. The listener is only
|
|
14
14
|
* attached when the role requires focus wrapping, and is cleaned
|
|
@@ -7,7 +7,7 @@ import { type TPopupContentProps } from './types';
|
|
|
7
7
|
/**
|
|
8
8
|
* Thin context wrapper that composes `Popover` + `useAnchorPosition`.
|
|
9
9
|
*
|
|
10
|
-
* Used inside the `<Popup>` compound
|
|
10
|
+
* Used inside the `<Popup>` compound — reads triggerRef, placement, isOpen,
|
|
11
11
|
* and onClose from context. For standalone usage (tooltip, spotlight, flag),
|
|
12
12
|
* use `Popover` + `useAnchorPosition` directly.
|
|
13
13
|
*/
|
|
@@ -17,7 +17,7 @@ import { type TPopupTriggerProps } from './types';
|
|
|
17
17
|
* from opening.
|
|
18
18
|
*
|
|
19
19
|
* If you need Compiled `css` on the trigger, use `Popup.TriggerFunction`
|
|
20
|
-
* instead
|
|
20
|
+
* instead — it hands you raw props via a render-prop and avoids
|
|
21
21
|
* `cloneElement` entirely.
|
|
22
22
|
*/
|
|
23
23
|
export declare function PopupTrigger({ children }: TPopupTriggerProps): ReactNode;
|
|
@@ -13,12 +13,12 @@ type TUseSimpleLightDismissOptions = {
|
|
|
13
13
|
/**
|
|
14
14
|
* Called when a light-dismiss event occurs.
|
|
15
15
|
*
|
|
16
|
-
* - `reason: 'escape'`
|
|
17
|
-
* - `reason: 'light-dismiss'`
|
|
16
|
+
* - `reason: 'escape'` — the user pressed the Escape key.
|
|
17
|
+
* - `reason: 'light-dismiss'` — the user clicked outside the popover.
|
|
18
18
|
*
|
|
19
19
|
* **Note:** This hook provides simple, standalone light dismiss that does not
|
|
20
20
|
* participate in the browser's `popover="auto"` dismiss stack. Every active
|
|
21
|
-
* instance will fire independently
|
|
21
|
+
* instance will fire independently — if multiple popovers use this hook,
|
|
22
22
|
* they will all receive dismiss events.
|
|
23
23
|
*/
|
|
24
24
|
onClose: (args: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/top-layer",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Low-level layering primitives based on popover and dialog",
|
|
5
5
|
"homepage": "https://atlassian.design/components/top-layer",
|
|
6
6
|
"repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
|