@atlaskit/top-layer 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +112 -0
- package/README.md +4 -2
- package/dist/cjs/arrow/index.js +2 -2
- package/dist/cjs/dialog/dialog-content.js +6 -1
- package/dist/cjs/entry-points/use-width-from-anchor.js +12 -0
- package/dist/cjs/focus/focus.js +4 -4
- package/dist/cjs/internal/combine.js +2 -2
- package/dist/cjs/internal/use-anchor-position.js +25 -7
- 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/internal/use-width-from-anchor.js +107 -0
- package/dist/cjs/popover/popover.js +12 -10
- package/dist/cjs/popup/popup-content.js +10 -37
- 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 +6 -1
- package/dist/es2019/entry-points/use-width-from-anchor.js +1 -0
- package/dist/es2019/focus/focus.js +1 -1
- package/dist/es2019/internal/combine.js +1 -1
- package/dist/es2019/internal/use-anchor-position.js +13 -7
- 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/internal/use-width-from-anchor.js +103 -0
- package/dist/es2019/popover/popover.js +12 -10
- package/dist/es2019/popup/popup-content.js +9 -36
- 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 +6 -1
- package/dist/esm/entry-points/use-width-from-anchor.js +1 -0
- package/dist/esm/focus/focus.js +4 -4
- package/dist/esm/internal/combine.js +2 -2
- package/dist/esm/internal/use-anchor-position.js +25 -7
- 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/internal/use-width-from-anchor.js +102 -0
- package/dist/esm/popover/popover.js +12 -10
- package/dist/esm/popup/popup-content.js +10 -37
- package/dist/esm/popup/popup-trigger.js +2 -2
- package/dist/esm/use-simple-light-dismiss/index.js +1 -1
- package/dist/types/entry-points/use-width-from-anchor.d.ts +1 -0
- package/dist/types/internal/use-anchor-position.d.ts +1 -1
- package/dist/types/internal/use-focus-wrap.d.ts +1 -1
- package/dist/types/internal/use-width-from-anchor.d.ts +20 -0
- package/dist/types/popover/popover.d.ts +3 -1
- package/dist/types/popover/types.d.ts +13 -0
- package/dist/types/popup/popup-content.d.ts +1 -1
- package/dist/types/popup/popup-trigger.d.ts +1 -1
- package/dist/types/popup/types.d.ts +8 -8
- package/dist/types/use-simple-light-dismiss/index.d.ts +3 -3
- package/dist/types-ts4.5/entry-points/use-width-from-anchor.d.ts +1 -0
- package/dist/types-ts4.5/internal/use-anchor-position.d.ts +1 -1
- package/dist/types-ts4.5/internal/use-focus-wrap.d.ts +1 -1
- package/dist/types-ts4.5/internal/use-width-from-anchor.d.ts +20 -0
- package/dist/types-ts4.5/popover/popover.d.ts +3 -1
- package/dist/types-ts4.5/popover/types.d.ts +13 -0
- 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/popup/types.d.ts +8 -8
- package/dist/types-ts4.5/use-simple-light-dismiss/index.d.ts +3 -3
- package/package.json +2 -2
- package/use-width-from-anchor/package.json +17 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { useLayoutEffect } from 'react';
|
|
2
|
+
import { setStyle } from './set-style';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Sets the width of a popover element relative to its anchor element.
|
|
6
|
+
*
|
|
7
|
+
* - `'match-anchor'` → `width: anchor-size(width)` — popover matches anchor width exactly.
|
|
8
|
+
* - `'min-anchor'` → `min-width: anchor-size(width)` — popover is at least as wide as anchor,
|
|
9
|
+
* but can grow wider.
|
|
10
|
+
* - `'none'` → no explicit width is set (default behaviour)
|
|
11
|
+
*
|
|
12
|
+
* Uses CSS `anchor-size(width)` when the browser supports it, falling back to a
|
|
13
|
+
* one-off measurement of `anchor.offsetWidth`.
|
|
14
|
+
*
|
|
15
|
+
* Designed to be composed alongside `useAnchorPosition` for top-layer popovers.
|
|
16
|
+
*/
|
|
17
|
+
export function useWidthFromAnchor(_ref) {
|
|
18
|
+
var mode = _ref.mode,
|
|
19
|
+
popoverRef = _ref.popoverRef,
|
|
20
|
+
anchorRef = _ref.anchorRef;
|
|
21
|
+
useLayoutEffect(function () {
|
|
22
|
+
var node = popoverRef.current;
|
|
23
|
+
if (!node) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Feature-detect `anchor-size()` specifically (not just `anchor-name`)
|
|
28
|
+
// so the JS fallback fires correctly in browsers that support anchor
|
|
29
|
+
// positioning but not anchor sizing.
|
|
30
|
+
var supportsAnchorSize = typeof CSS !== 'undefined' && typeof CSS.supports === 'function' && CSS.supports('width', 'anchor-size(width)');
|
|
31
|
+
if (mode === 'match-anchor') {
|
|
32
|
+
// Set an exact width matching the anchor.
|
|
33
|
+
// `min-inline-size` is intentionally NOT set here — it would override the
|
|
34
|
+
// explicit width constraint, allowing the popover to grow past the anchor's width.
|
|
35
|
+
if (supportsAnchorSize) {
|
|
36
|
+
return setStyle({
|
|
37
|
+
el: node,
|
|
38
|
+
styles: [{
|
|
39
|
+
property: 'width',
|
|
40
|
+
value: 'anchor-size(width)'
|
|
41
|
+
}]
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// JS fallback: one-off read of the anchor's width.
|
|
46
|
+
var anchor = anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current;
|
|
47
|
+
if (anchor) {
|
|
48
|
+
return setStyle({
|
|
49
|
+
el: node,
|
|
50
|
+
styles: [{
|
|
51
|
+
property: 'width',
|
|
52
|
+
value: "".concat(anchor.offsetWidth, "px")
|
|
53
|
+
}]
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// For 'min-anchor' and 'none', apply `min-inline-size: max-content` to ensure
|
|
60
|
+
// correct position-try-fallbacks behaviour (popover margin box overflows the
|
|
61
|
+
// viewport when its span region is too narrow, rather than wrapping content).
|
|
62
|
+
var minInlineSizeStyle = {
|
|
63
|
+
property: 'min-inline-size',
|
|
64
|
+
value: 'max-content'
|
|
65
|
+
};
|
|
66
|
+
if (mode === 'min-anchor') {
|
|
67
|
+
// Set a minimum width matching the anchor. The popover can grow wider
|
|
68
|
+
// if its content requires it.
|
|
69
|
+
if (supportsAnchorSize) {
|
|
70
|
+
return setStyle({
|
|
71
|
+
el: node,
|
|
72
|
+
styles: [minInlineSizeStyle, {
|
|
73
|
+
property: 'min-width',
|
|
74
|
+
value: 'anchor-size(width)'
|
|
75
|
+
}]
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
var _anchor = anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current;
|
|
79
|
+
if (_anchor) {
|
|
80
|
+
return setStyle({
|
|
81
|
+
el: node,
|
|
82
|
+
styles: [minInlineSizeStyle, {
|
|
83
|
+
property: 'min-width',
|
|
84
|
+
value: "".concat(_anchor.offsetWidth, "px")
|
|
85
|
+
}]
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// No anchor available in JS fallback — still apply min-inline-size.
|
|
90
|
+
return setStyle({
|
|
91
|
+
el: node,
|
|
92
|
+
styles: [minInlineSizeStyle]
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 'none' mode: no explicit width, but still apply `min-inline-size: max-content`.
|
|
97
|
+
return setStyle({
|
|
98
|
+
el: node,
|
|
99
|
+
styles: [minInlineSizeStyle]
|
|
100
|
+
});
|
|
101
|
+
}, [mode, popoverRef, anchorRef]);
|
|
102
|
+
}
|
|
@@ -35,7 +35,9 @@ var styles = {
|
|
|
35
35
|
* Unopinionated top-layer primitive.
|
|
36
36
|
*
|
|
37
37
|
* Manages only visibility (isOpen) and animation (animate). Has no knowledge
|
|
38
|
-
* of positioning — compose with `useAnchorPosition` for anchor positioning
|
|
38
|
+
* of positioning — compose with `useAnchorPosition` for anchor positioning
|
|
39
|
+
* and optionally `useWidthFromAnchor` for setting the width of a popover element
|
|
40
|
+
* relative to its anchor trigger.
|
|
39
41
|
*
|
|
40
42
|
* Visibility is driven by the `isOpen` prop:
|
|
41
43
|
* - `isOpen={true}` → `showPopover()`, entry animation via `@starting-style`
|
|
@@ -117,21 +119,21 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
|
|
|
117
119
|
// the browser processes light dismiss), read in the toggle handler.
|
|
118
120
|
var closeReasonRef = useRef('light-dismiss');
|
|
119
121
|
var handleToggle = useCallback(function (event) {
|
|
120
|
-
var
|
|
122
|
+
var element = ownRef.current;
|
|
121
123
|
if (event.newState === 'open') {
|
|
122
|
-
if (
|
|
124
|
+
if (element) {
|
|
123
125
|
onOpenChange === null || onOpenChange === void 0 || onOpenChange({
|
|
124
126
|
isOpen: true,
|
|
125
|
-
element:
|
|
127
|
+
element: element
|
|
126
128
|
});
|
|
127
129
|
}
|
|
128
130
|
return;
|
|
129
131
|
}
|
|
130
132
|
if (event.newState === 'closed') {
|
|
131
|
-
if (
|
|
133
|
+
if (element) {
|
|
132
134
|
onOpenChange === null || onOpenChange === void 0 || onOpenChange({
|
|
133
135
|
isOpen: false,
|
|
134
|
-
element:
|
|
136
|
+
element: element
|
|
135
137
|
});
|
|
136
138
|
}
|
|
137
139
|
|
|
@@ -149,13 +151,13 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
|
|
|
149
151
|
}
|
|
150
152
|
}, [onClose, onOpenChange]);
|
|
151
153
|
useEffect(function () {
|
|
152
|
-
var
|
|
153
|
-
if (!
|
|
154
|
+
var element = ownRef.current;
|
|
155
|
+
if (!element) {
|
|
154
156
|
return;
|
|
155
157
|
}
|
|
156
158
|
|
|
157
159
|
// Capture-phase: tag Escape before the browser processes light dismiss.
|
|
158
|
-
var unbindEscape = bind(
|
|
160
|
+
var unbindEscape = bind(element, {
|
|
159
161
|
type: 'keydown',
|
|
160
162
|
listener: function listener(event) {
|
|
161
163
|
if (event.key === 'Escape') {
|
|
@@ -166,7 +168,7 @@ export var Popover = /*#__PURE__*/forwardRef(function Popover(_ref, ref) {
|
|
|
166
168
|
capture: true
|
|
167
169
|
}
|
|
168
170
|
});
|
|
169
|
-
var unbindToggle = bind(
|
|
171
|
+
var unbindToggle = bind(element, {
|
|
170
172
|
type: 'toggle',
|
|
171
173
|
listener: handleToggle
|
|
172
174
|
});
|
|
@@ -6,12 +6,13 @@ import mergeRefs from '@atlaskit/ds-lib/merge-refs';
|
|
|
6
6
|
import { roleToAriaHasPopup } from '../internal/role-types';
|
|
7
7
|
import { useAnchorPosition } from '../internal/use-anchor-position';
|
|
8
8
|
import { usePresetStyles } from '../internal/use-preset-styles';
|
|
9
|
+
import { useWidthFromAnchor } from '../internal/use-width-from-anchor';
|
|
9
10
|
import { Popover } from '../popover/popover';
|
|
10
11
|
import { useMaybePopupContext } from './popup-context';
|
|
11
12
|
/**
|
|
12
13
|
* Thin context wrapper that composes `Popover` + `useAnchorPosition`.
|
|
13
14
|
*
|
|
14
|
-
* Used inside the `<Popup>` compound
|
|
15
|
+
* Used inside the `<Popup>` compound - reads triggerRef, placement, isOpen,
|
|
15
16
|
* and onClose from context. For standalone usage (tooltip, spotlight, flag),
|
|
16
17
|
* use `Popover` + `useAnchorPosition` directly.
|
|
17
18
|
*/
|
|
@@ -24,8 +25,8 @@ export var PopupContent = /*#__PURE__*/forwardRef(function PopupContent(_ref, re
|
|
|
24
25
|
animate = _ref.animate,
|
|
25
26
|
arrow = _ref.arrow,
|
|
26
27
|
mode = _ref.mode,
|
|
27
|
-
_ref$
|
|
28
|
-
|
|
28
|
+
_ref$widthFromAnchor = _ref.widthFromAnchor,
|
|
29
|
+
widthFromAnchor = _ref$widthFromAnchor === void 0 ? 'none' : _ref$widthFromAnchor,
|
|
29
30
|
xcss = _ref.xcss,
|
|
30
31
|
isOpenProp = _ref.isOpen,
|
|
31
32
|
triggerRefProp = _ref.triggerRef,
|
|
@@ -88,7 +89,7 @@ export var PopupContent = /*#__PURE__*/forwardRef(function PopupContent(_ref, re
|
|
|
88
89
|
// ── Nested popover focus restoration fallback ──
|
|
89
90
|
// The browser only captures `previouslyFocusedElement` for the
|
|
90
91
|
// outermost popover="auto" in the stack. Inner (nested) popovers
|
|
91
|
-
// have shouldRestoreFocus=false, so the browser
|
|
92
|
+
// have shouldRestoreFocus=false, so the browser will not restore
|
|
92
93
|
// focus when they close.
|
|
93
94
|
//
|
|
94
95
|
// We detect this case by checking if focus is still inside the
|
|
@@ -131,39 +132,11 @@ export var PopupContent = /*#__PURE__*/forwardRef(function PopupContent(_ref, re
|
|
|
131
132
|
forceFallbackPositioning: forceFallbackPositioning,
|
|
132
133
|
arrow: arrowPreset !== null && arrowPreset !== void 0 ? arrowPreset : undefined
|
|
133
134
|
});
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
useLayoutEffect(function () {
|
|
140
|
-
if (width === 'content') {
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
var node = popoverRef.current;
|
|
144
|
-
if (!node) {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
var cssProperty = width === 'trigger' ? 'width' : 'min-width';
|
|
148
|
-
var anchorValue = 'anchor-size(width)';
|
|
149
|
-
|
|
150
|
-
// Feature-detect `anchor-size()` specifically (not just `anchor-name`)
|
|
151
|
-
// so the JS fallback fires correctly in browsers that support anchor
|
|
152
|
-
// positioning but not anchor sizing.
|
|
153
|
-
var supportsAnchorSize = typeof CSS !== 'undefined' && typeof CSS.supports === 'function' && CSS.supports('width', 'anchor-size(width)');
|
|
154
|
-
if (supportsAnchorSize) {
|
|
155
|
-
node.style.setProperty(cssProperty, anchorValue);
|
|
156
|
-
} else {
|
|
157
|
-
// JS fallback: one-off read of the trigger's width.
|
|
158
|
-
var trigger = triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.current;
|
|
159
|
-
if (trigger) {
|
|
160
|
-
node.style.setProperty(cssProperty, "".concat(trigger.offsetWidth, "px"));
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
return function () {
|
|
164
|
-
node.style.removeProperty(cssProperty);
|
|
165
|
-
};
|
|
166
|
-
}, [width, popoverRef, triggerRef]);
|
|
135
|
+
useWidthFromAnchor({
|
|
136
|
+
mode: widthFromAnchor,
|
|
137
|
+
popoverRef: popoverRef,
|
|
138
|
+
anchorRef: triggerRef
|
|
139
|
+
});
|
|
167
140
|
|
|
168
141
|
// Merge: the popoverRef (shared with trigger + positioning) and the forwarded ref.
|
|
169
142
|
var combinedRef = mergeRefs([popoverRef, ref]);
|
|
@@ -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
|
+
// does not 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 does not re-bind on every render.
|
|
24
24
|
var onCloseRef = useRef(onClose);
|
|
25
25
|
onCloseRef.current = onClose;
|
|
26
26
|
useEffect(function () {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useWidthFromAnchor } from '../internal/use-width-from-anchor';
|
|
@@ -132,7 +132,7 @@ export declare function useAnchorPosition({ anchorRef, popoverRef, placement, fo
|
|
|
132
132
|
* the preset's named `@position-try` rules (which update both
|
|
133
133
|
* `position-area` and `margin` on flip) and sets `--ds-arrow-size`.
|
|
134
134
|
*
|
|
135
|
-
* 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 -
|
|
136
136
|
* arrows are CSS-only.
|
|
137
137
|
*/
|
|
138
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
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
import type { TWidthFromAnchorMode } from '../popover/types';
|
|
3
|
+
/**
|
|
4
|
+
* Sets the width of a popover element relative to its anchor element.
|
|
5
|
+
*
|
|
6
|
+
* - `'match-anchor'` → `width: anchor-size(width)` — popover matches anchor width exactly.
|
|
7
|
+
* - `'min-anchor'` → `min-width: anchor-size(width)` — popover is at least as wide as anchor,
|
|
8
|
+
* but can grow wider.
|
|
9
|
+
* - `'none'` → no explicit width is set (default behaviour)
|
|
10
|
+
*
|
|
11
|
+
* Uses CSS `anchor-size(width)` when the browser supports it, falling back to a
|
|
12
|
+
* one-off measurement of `anchor.offsetWidth`.
|
|
13
|
+
*
|
|
14
|
+
* Designed to be composed alongside `useAnchorPosition` for top-layer popovers.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useWidthFromAnchor({ mode, popoverRef, anchorRef, }: {
|
|
17
|
+
mode: TWidthFromAnchorMode;
|
|
18
|
+
popoverRef: RefObject<HTMLElement | null>;
|
|
19
|
+
anchorRef: RefObject<HTMLElement | null> | undefined;
|
|
20
|
+
}): void;
|
|
@@ -8,7 +8,9 @@ import { type TPopoverForwardedProps } from './types';
|
|
|
8
8
|
* Unopinionated top-layer primitive.
|
|
9
9
|
*
|
|
10
10
|
* Manages only visibility (isOpen) and animation (animate). Has no knowledge
|
|
11
|
-
* of positioning — compose with `useAnchorPosition` for anchor positioning
|
|
11
|
+
* of positioning — compose with `useAnchorPosition` for anchor positioning
|
|
12
|
+
* and optionally `useWidthFromAnchor` for setting the width of a popover element
|
|
13
|
+
* relative to its anchor trigger.
|
|
12
14
|
*
|
|
13
15
|
* Visibility is driven by the `isOpen` prop:
|
|
14
16
|
* - `isOpen={true}` → `showPopover()`, entry animation via `@starting-style`
|
|
@@ -157,4 +157,17 @@ export type TPopoverProps = TPopoverBaseProps & TAriaRoleOptional & ({
|
|
|
157
157
|
mode: 'manual';
|
|
158
158
|
onClose?: never;
|
|
159
159
|
});
|
|
160
|
+
/**
|
|
161
|
+
* The width mode of the popover relative to its anchor element.
|
|
162
|
+
*
|
|
163
|
+
* - `'none'` (default): popover sizes to its content, ignoring the anchor width.
|
|
164
|
+
* - `'match-anchor'`: popover matches the anchor element's width exactly
|
|
165
|
+
* via CSS `anchor-size(width)`. Falls back to a one-off measurement
|
|
166
|
+
* of `anchorRef.current.offsetWidth` when CSS Anchor Positioning
|
|
167
|
+
* is not supported.
|
|
168
|
+
* - `'min-anchor'`: popover is at least as wide as the anchor, but
|
|
169
|
+
* can grow wider if content requires it. Uses `min-width: anchor-size(width)`.
|
|
170
|
+
* Falls back to a one-off measurement of the anchor's width.
|
|
171
|
+
*/
|
|
172
|
+
export type TWidthFromAnchorMode = 'none' | 'match-anchor' | 'min-anchor';
|
|
160
173
|
export {};
|
|
@@ -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;
|
|
@@ -4,7 +4,7 @@ import { type TAnimationPreset } from '../animations/types';
|
|
|
4
4
|
import { type TArrowPreset } from '../arrow/types';
|
|
5
5
|
import { type TPlacementOptions } from '../internal/resolve-placement';
|
|
6
6
|
import { type TRoleRequiringAccessibleName, type TRoleWithImplicitName } from '../internal/role-types';
|
|
7
|
-
import { type TPopoverCloseReason } from '../popover/types';
|
|
7
|
+
import { type TPopoverCloseReason, type TWidthFromAnchorMode } from '../popover/types';
|
|
8
8
|
/**
|
|
9
9
|
* Describes where to position a popover relative to its trigger. All fields
|
|
10
10
|
* are optional. The default `{}` means "below the trigger, centered, with a
|
|
@@ -115,18 +115,18 @@ type TPopupContentBaseProps = {
|
|
|
115
115
|
*/
|
|
116
116
|
ref?: Ref<HTMLDivElement>;
|
|
117
117
|
/**
|
|
118
|
-
* Controls the width of the popover.
|
|
118
|
+
* Controls the width of the popover relative to its anchor element.
|
|
119
119
|
*
|
|
120
|
-
* - `'
|
|
121
|
-
* - `'
|
|
120
|
+
* - `'none'` (default): popover sizes to its content, ignoring the anchor width.
|
|
121
|
+
* - `'match-anchor'`: popover matches the anchor element's width exactly
|
|
122
122
|
* via CSS `anchor-size(width)`. Falls back to a one-off measurement
|
|
123
|
-
* of `
|
|
123
|
+
* of `anchorRef.current.offsetWidth` when CSS Anchor Positioning
|
|
124
124
|
* is not supported.
|
|
125
|
-
* - `'min-
|
|
125
|
+
* - `'min-anchor'`: popover is at least as wide as the anchor, but
|
|
126
126
|
* can grow wider if content requires it. Uses `min-width: anchor-size(width)`.
|
|
127
|
-
* Falls back to a one-off measurement of the
|
|
127
|
+
* Falls back to a one-off measurement of the anchor's width.
|
|
128
128
|
*/
|
|
129
|
-
|
|
129
|
+
widthFromAnchor?: TWidthFromAnchorMode;
|
|
130
130
|
/**
|
|
131
131
|
* Applies additional CSS styles to the popover root element using
|
|
132
132
|
* design-system-safe xcss.
|
|
@@ -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: {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useWidthFromAnchor } from '../internal/use-width-from-anchor';
|
|
@@ -132,7 +132,7 @@ export declare function useAnchorPosition({ anchorRef, popoverRef, placement, fo
|
|
|
132
132
|
* the preset's named `@position-try` rules (which update both
|
|
133
133
|
* `position-area` and `margin` on flip) and sets `--ds-arrow-size`.
|
|
134
134
|
*
|
|
135
|
-
* 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 -
|
|
136
136
|
* arrows are CSS-only.
|
|
137
137
|
*/
|
|
138
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
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
import type { TWidthFromAnchorMode } from '../popover/types';
|
|
3
|
+
/**
|
|
4
|
+
* Sets the width of a popover element relative to its anchor element.
|
|
5
|
+
*
|
|
6
|
+
* - `'match-anchor'` → `width: anchor-size(width)` — popover matches anchor width exactly.
|
|
7
|
+
* - `'min-anchor'` → `min-width: anchor-size(width)` — popover is at least as wide as anchor,
|
|
8
|
+
* but can grow wider.
|
|
9
|
+
* - `'none'` → no explicit width is set (default behaviour)
|
|
10
|
+
*
|
|
11
|
+
* Uses CSS `anchor-size(width)` when the browser supports it, falling back to a
|
|
12
|
+
* one-off measurement of `anchor.offsetWidth`.
|
|
13
|
+
*
|
|
14
|
+
* Designed to be composed alongside `useAnchorPosition` for top-layer popovers.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useWidthFromAnchor({ mode, popoverRef, anchorRef, }: {
|
|
17
|
+
mode: TWidthFromAnchorMode;
|
|
18
|
+
popoverRef: RefObject<HTMLElement | null>;
|
|
19
|
+
anchorRef: RefObject<HTMLElement | null> | undefined;
|
|
20
|
+
}): void;
|
|
@@ -8,7 +8,9 @@ import { type TPopoverForwardedProps } from './types';
|
|
|
8
8
|
* Unopinionated top-layer primitive.
|
|
9
9
|
*
|
|
10
10
|
* Manages only visibility (isOpen) and animation (animate). Has no knowledge
|
|
11
|
-
* of positioning — compose with `useAnchorPosition` for anchor positioning
|
|
11
|
+
* of positioning — compose with `useAnchorPosition` for anchor positioning
|
|
12
|
+
* and optionally `useWidthFromAnchor` for setting the width of a popover element
|
|
13
|
+
* relative to its anchor trigger.
|
|
12
14
|
*
|
|
13
15
|
* Visibility is driven by the `isOpen` prop:
|
|
14
16
|
* - `isOpen={true}` → `showPopover()`, entry animation via `@starting-style`
|
|
@@ -157,4 +157,17 @@ export type TPopoverProps = TPopoverBaseProps & TAriaRoleOptional & ({
|
|
|
157
157
|
mode: 'manual';
|
|
158
158
|
onClose?: never;
|
|
159
159
|
});
|
|
160
|
+
/**
|
|
161
|
+
* The width mode of the popover relative to its anchor element.
|
|
162
|
+
*
|
|
163
|
+
* - `'none'` (default): popover sizes to its content, ignoring the anchor width.
|
|
164
|
+
* - `'match-anchor'`: popover matches the anchor element's width exactly
|
|
165
|
+
* via CSS `anchor-size(width)`. Falls back to a one-off measurement
|
|
166
|
+
* of `anchorRef.current.offsetWidth` when CSS Anchor Positioning
|
|
167
|
+
* is not supported.
|
|
168
|
+
* - `'min-anchor'`: popover is at least as wide as the anchor, but
|
|
169
|
+
* can grow wider if content requires it. Uses `min-width: anchor-size(width)`.
|
|
170
|
+
* Falls back to a one-off measurement of the anchor's width.
|
|
171
|
+
*/
|
|
172
|
+
export type TWidthFromAnchorMode = 'none' | 'match-anchor' | 'min-anchor';
|
|
160
173
|
export {};
|
|
@@ -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;
|
|
@@ -4,7 +4,7 @@ import { type TAnimationPreset } from '../animations/types';
|
|
|
4
4
|
import { type TArrowPreset } from '../arrow/types';
|
|
5
5
|
import { type TPlacementOptions } from '../internal/resolve-placement';
|
|
6
6
|
import { type TRoleRequiringAccessibleName, type TRoleWithImplicitName } from '../internal/role-types';
|
|
7
|
-
import { type TPopoverCloseReason } from '../popover/types';
|
|
7
|
+
import { type TPopoverCloseReason, type TWidthFromAnchorMode } from '../popover/types';
|
|
8
8
|
/**
|
|
9
9
|
* Describes where to position a popover relative to its trigger. All fields
|
|
10
10
|
* are optional. The default `{}` means "below the trigger, centered, with a
|
|
@@ -115,18 +115,18 @@ type TPopupContentBaseProps = {
|
|
|
115
115
|
*/
|
|
116
116
|
ref?: Ref<HTMLDivElement>;
|
|
117
117
|
/**
|
|
118
|
-
* Controls the width of the popover.
|
|
118
|
+
* Controls the width of the popover relative to its anchor element.
|
|
119
119
|
*
|
|
120
|
-
* - `'
|
|
121
|
-
* - `'
|
|
120
|
+
* - `'none'` (default): popover sizes to its content, ignoring the anchor width.
|
|
121
|
+
* - `'match-anchor'`: popover matches the anchor element's width exactly
|
|
122
122
|
* via CSS `anchor-size(width)`. Falls back to a one-off measurement
|
|
123
|
-
* of `
|
|
123
|
+
* of `anchorRef.current.offsetWidth` when CSS Anchor Positioning
|
|
124
124
|
* is not supported.
|
|
125
|
-
* - `'min-
|
|
125
|
+
* - `'min-anchor'`: popover is at least as wide as the anchor, but
|
|
126
126
|
* can grow wider if content requires it. Uses `min-width: anchor-size(width)`.
|
|
127
|
-
* Falls back to a one-off measurement of the
|
|
127
|
+
* Falls back to a one-off measurement of the anchor's width.
|
|
128
128
|
*/
|
|
129
|
-
|
|
129
|
+
widthFromAnchor?: TWidthFromAnchorMode;
|
|
130
130
|
/**
|
|
131
131
|
* Applies additional CSS styles to the popover root element using
|
|
132
132
|
* design-system-safe xcss.
|
|
@@ -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.
|
|
3
|
+
"version": "0.7.0",
|
|
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",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@atlaskit/textfield": "^8.3.0",
|
|
60
60
|
"@atlassian/react-compiler-gating": "workspace:^",
|
|
61
61
|
"@atlassian/ssr-tests": "workspace:^",
|
|
62
|
-
"@atlassian/testing-library": "^0.
|
|
62
|
+
"@atlassian/testing-library": "^0.6.0",
|
|
63
63
|
"@testing-library/jest-dom": "^6.4.5",
|
|
64
64
|
"@testing-library/react": "^16.3.0",
|
|
65
65
|
"@types/raf-schd": "^4.0.1",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaskit/top-layer/use-width-from-anchor",
|
|
3
|
+
"main": "../dist/cjs/entry-points/use-width-from-anchor.js",
|
|
4
|
+
"module": "../dist/esm/entry-points/use-width-from-anchor.js",
|
|
5
|
+
"module:es2019": "../dist/es2019/entry-points/use-width-from-anchor.js",
|
|
6
|
+
"sideEffects": [
|
|
7
|
+
"*.compiled.css"
|
|
8
|
+
],
|
|
9
|
+
"types": "../dist/types/entry-points/use-width-from-anchor.d.ts",
|
|
10
|
+
"typesVersions": {
|
|
11
|
+
">=4.5 <5.9": {
|
|
12
|
+
"*": [
|
|
13
|
+
"../dist/types-ts4.5/entry-points/use-width-from-anchor.d.ts"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|