@atlaskit/top-layer 4.2.2 → 4.2.4

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.
@@ -1,3 +1,4 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
1
2
  import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
3
  import _createClass from "@babel/runtime/helpers/createClass";
3
4
  /**
@@ -74,6 +75,40 @@ var supportsAnchorPositioning = once(function () {
74
75
  return CSS.supports('anchor-name', '--a');
75
76
  });
76
77
 
78
+ /**
79
+ * Every logical margin property this module can write: one per axis, per side.
80
+ *
81
+ * Deriving the union from `TPlacementAxis` and `TPlacementEdge` rather than
82
+ * writing the four names out keeps it in step with the placement model, and
83
+ * makes `CROSS_AXIS_SHIFT_CUSTOM_PROPERTY` below exhaustive by construction.
84
+ */
85
+
86
+ /**
87
+ * The custom property mirroring each cross-axis shift margin.
88
+ *
89
+ * These are written for the planned named arrow `@position-try` rules. Nothing
90
+ * reads them yet, and the shift no longer depends on them: the antisymmetric
91
+ * margins written by `crossAxisShiftMargins` survive a cross-axis slide on
92
+ * their own.
93
+ *
94
+ * Keyed on `TLogicalMarginProperty` and not on `string`, so a margin property
95
+ * that has no custom property (or a custom property whose margin no longer
96
+ * exists) is a compile error rather than an `undefined` lookup that reaches
97
+ * `setStyle` as `{ property: undefined, value }`.
98
+ */
99
+ var CROSS_AXIS_SHIFT_CUSTOM_PROPERTY = {
100
+ 'margin-inline-start': '--ds-cross-axis-shift-margin-start',
101
+ 'margin-inline-end': '--ds-cross-axis-shift-margin-end',
102
+ 'margin-block-start': '--ds-cross-axis-shift-margin-block-start',
103
+ 'margin-block-end': '--ds-cross-axis-shift-margin-block-end'
104
+ };
105
+ var ZEROED_CROSS_AXIS_SHIFT_CUSTOM_PROPERTIES = Object.values(CROSS_AXIS_SHIFT_CUSTOM_PROPERTY).map(function (property) {
106
+ return {
107
+ property: property,
108
+ value: '0px'
109
+ };
110
+ });
111
+
77
112
  /**
78
113
  * Returns the CSS margin declaration that creates a gap between the
79
114
  * popover and its trigger on the side facing the anchor.
@@ -86,62 +121,64 @@ function edgeMargin(_ref) {
86
121
  offset = _ref.offset;
87
122
  var axis = placement.axis,
88
123
  edge = placement.edge;
89
- var value = offset;
90
- if (axis === 'block' && edge === 'end') {
91
- return {
92
- property: 'margin-block-start',
93
- value: value
94
- };
95
- }
96
- if (axis === 'block' && edge === 'start') {
97
- return {
98
- property: 'margin-block-end',
99
- value: value
100
- };
101
- }
102
- if (axis === 'inline' && edge === 'end') {
103
- return {
104
- property: 'margin-inline-start',
105
- value: value
106
- };
107
- }
108
- if (axis === 'inline' && edge === 'start') {
109
- return {
110
- property: 'margin-inline-end',
111
- value: value
112
- };
113
- }
124
+ // The gap sits on the side FACING the anchor, which is always the side
125
+ // opposite the placement edge.
126
+ var anchorFacingEdge = edge === 'end' ? 'start' : 'end';
114
127
  return {
115
- property: 'margin-block-start',
116
- value: value
128
+ property: "margin-".concat(axis, "-").concat(anchorFacingEdge),
129
+ value: offset
117
130
  };
118
131
  }
119
132
 
120
133
  /**
121
- * Cross-axis shift margin. Margin side matches the popover's anchored
122
- * cross-axis edge: `align: 'start'` uses the START margin, `align: 'end'`
123
- * uses the END margin with the sign inverted (so `forwards` is always
124
- * positive), `align: 'center'` uses START. Margin on the un-anchored side
125
- * has no effect under CSS Anchor Positioning.
134
+ * **The cross-axis shift margins.**
135
+ *
136
+ * The shift is written antisymmetrically on BOTH cross-axis sides
137
+ * (`start: +value`, `end: -value`) rather than as a single margin on the side
138
+ * picked from `align`. Two separate behaviours require it:
139
+ *
140
+ * 1. **`align: 'center'` is centered with `anchor-center`, which centers the
141
+ * popover's MARGIN box on the anchor.** A single-sided margin widens the
142
+ * margin box, so it displaces the border box by only half its value. An
143
+ * antisymmetric pair leaves the margin box width unchanged (`+value` and
144
+ * `-value` sum to zero) while moving its center by the full value.
145
+ * 2. **`position-try-fallbacks` can slide the popover onto the opposite
146
+ * cross-axis side.** A `<position-area>` fallback keeps the base style's
147
+ * margins, and margin on the un-anchored side has no effect, so a
148
+ * single-sided margin is silently dropped once the browser slides across the
149
+ * cross axis. With both sides written, whichever side ends up anchored moves
150
+ * the popover the same physical direction.
151
+ *
152
+ * Leaving the margin box width unchanged also means the shift does not move
153
+ * the point at which `position-try-fallbacks` decides the popover overflows.
154
+ *
155
+ * A `<try-tactic>` fallback (`flip-block`, `flip-inline`) behaves differently to
156
+ * a `<position-area>` one: it SWAPS the start and end margins rather than
157
+ * keeping them, which is what preserves the gap through a flip. So a flip across
158
+ * the cross axis mirrors the shift along with the rest of the placement, rather
159
+ * than preserving its physical direction. Only the diagonal fallback does that,
160
+ * and only for `align: 'start' | 'end'`. See `placementToTryFallbacks`.
161
+ *
162
+ * A positive value always moves the popover toward the cross-axis END, so
163
+ * `direction: 'forwards'` means the same thing for every `align` value. See
164
+ * `notes/decisions/placement-offset.md`.
126
165
  */
127
- function crossAxisShiftMargin(_ref2) {
166
+ function crossAxisShiftMargins(_ref2) {
128
167
  var placement = _ref2.placement,
129
168
  crossAxisShiftCssValue = _ref2.crossAxisShiftCssValue,
130
169
  direction = _ref2.direction;
131
- var axis = placement.axis,
132
- align = placement.align;
133
- var directionSign = direction === 'forwards' ? 1 : -1;
134
- var crossAxis = axis === 'block' ? 'inline' : 'block';
135
- var useEndSide = align === 'end';
136
- var side = useEndSide ? 'end' : 'start';
137
- var sideSign = useEndSide ? -1 : 1;
138
- var finalSign = directionSign * sideSign;
139
- // Wrap any string in calc() with the sign factor. CSS handles the math.
140
- var value = finalSign === 1 ? crossAxisShiftCssValue : "calc(-1 * ".concat(crossAxisShiftCssValue, ")");
141
- return {
142
- property: "margin-".concat(crossAxis, "-").concat(side),
143
- value: value
144
- };
170
+ var crossAxis = placement.axis === 'block' ? 'inline' : 'block';
171
+ // Wrap any string in calc() with the sign factor. CSS handles the math,
172
+ // so opaque values such as design tokens negate correctly.
173
+ var negated = "calc(-1 * ".concat(crossAxisShiftCssValue, ")");
174
+ var isForwards = direction === 'forwards';
175
+ return [{
176
+ property: "margin-".concat(crossAxis, "-start"),
177
+ value: isForwards ? crossAxisShiftCssValue : negated
178
+ }, {
179
+ property: "margin-".concat(crossAxis, "-end"),
180
+ value: isForwards ? negated : crossAxisShiftCssValue
181
+ }];
145
182
  }
146
183
 
147
184
  /**
@@ -226,10 +263,9 @@ export function useAnchorPosition(_ref3) {
226
263
  placement: stablePlacement,
227
264
  offset: gapCssValue
228
265
  });
229
- // Computed once; reused below to populate the active
230
- // `--ds-cross-axis-shift-margin-*` custom property for the
231
- // named arrow @position-try rules.
232
- var crossAxisShift = crossAxisShiftMargin({
266
+ // Computed once; also mirrored into the
267
+ // `--ds-cross-axis-shift-margin-*` custom properties below.
268
+ var crossAxisShift = crossAxisShiftMargins({
233
269
  placement: stablePlacement,
234
270
  crossAxisShiftCssValue: crossAxisShiftCssValue,
235
271
  direction: stablePlacement.offset.crossAxisShift.direction
@@ -256,48 +292,14 @@ export function useAnchorPosition(_ref3) {
256
292
  }, {
257
293
  property: 'inset',
258
294
  value: 'auto'
259
- }, {
260
- property: gap.property,
261
- value: gap.value
262
- }, {
263
- property: crossAxisShift.property,
264
- value: crossAxisShift.value
265
- }];
266
-
267
- // Expose the active cross-axis shift via custom properties so each
268
- // named arrow @position-try rule can re-apply it after a flip.
269
- // One of the four (cross-axis, side) properties is non-zero at a time.
270
- popoverStyles.push({
271
- property: '--ds-cross-axis-shift-margin-start',
272
- value: '0px'
273
- });
274
- popoverStyles.push({
275
- property: '--ds-cross-axis-shift-margin-end',
276
- value: '0px'
277
- });
278
- popoverStyles.push({
279
- property: '--ds-cross-axis-shift-margin-block-start',
280
- value: '0px'
281
- });
282
- popoverStyles.push({
283
- property: '--ds-cross-axis-shift-margin-block-end',
284
- value: '0px'
285
- });
286
- // `crossAxisShift` IS the active margin; reuse instead of recomputing.
287
- var crossAxisShiftActive = crossAxisShift;
288
- var customPropertyByMarginProperty = {
289
- 'margin-inline-start': '--ds-cross-axis-shift-margin-start',
290
- 'margin-inline-end': '--ds-cross-axis-shift-margin-end',
291
- 'margin-block-start': '--ds-cross-axis-shift-margin-block-start',
292
- 'margin-block-end': '--ds-cross-axis-shift-margin-block-end'
293
- };
294
- var crossAxisShiftCustomProperty = customPropertyByMarginProperty[crossAxisShiftActive.property];
295
- if (crossAxisShiftCustomProperty) {
296
- popoverStyles.push({
297
- property: crossAxisShiftCustomProperty,
298
- value: crossAxisShiftActive.value
299
- });
300
- }
295
+ }, gap].concat(_toConsumableArray(crossAxisShift), _toConsumableArray(ZEROED_CROSS_AXIS_SHIFT_CUSTOM_PROPERTIES), _toConsumableArray(crossAxisShift.map(function (_ref4) {
296
+ var property = _ref4.property,
297
+ value = _ref4.value;
298
+ return {
299
+ property: CROSS_AXIS_SHIFT_CUSTOM_PROPERTY[property],
300
+ value: value
301
+ };
302
+ })));
301
303
 
302
304
  /**
303
305
  * **We are never cleaning up anchor names**
@@ -1,78 +1,89 @@
1
1
  import { useLayoutEffect } from 'react';
2
+ import once from '@atlaskit/ds-lib/once';
2
3
  import { setStyle } from './set-style';
3
4
 
5
+ /**
6
+ * Probes anchor SIZING, separately from `anchor-name` (see
7
+ * `supportsAnchorPositioning`): some browsers have positioning but not sizing.
8
+ * `once()` for SSR safety.
9
+ */
10
+ var supportsAnchorSize = once(function () {
11
+ if (typeof window === 'undefined' || typeof CSS === 'undefined' || typeof CSS.supports !== 'function') {
12
+ return false;
13
+ }
14
+ return CSS.supports('min-inline-size', 'anchor-size(self-inline)');
15
+ });
16
+
17
+ /**
18
+ * The JS fallback's stand-in for `anchor-size(self-inline)`. `offsetWidth` / `offsetHeight` are
19
+ * physical, so the axis is picked from the popover's `writing-mode`. Anything not horizontal is
20
+ * treated as vertical, and an unknown or empty value falls back to `offsetWidth`.
21
+ */
22
+ function getFallbackAnchorInlineSize(_ref) {
23
+ var anchor = _ref.anchor,
24
+ popover = _ref.popover;
25
+ // `String()` because not every test environment implements `writing-mode`.
26
+ var writingMode = String(getComputedStyle(popover).writingMode);
27
+ var isVertical = writingMode.startsWith('vertical') || writingMode.startsWith('sideways');
28
+ return isVertical ? anchor.offsetHeight : anchor.offsetWidth;
29
+ }
30
+
4
31
  /**
5
32
  * Sets the width of a popover element relative to its anchor element.
6
33
  *
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`.
34
+ * - `'match-anchor'` → `inline-size: anchor-size(self-inline)`, exact
35
+ * - `'min-anchor'` → `min-inline-size: anchor-size(self-inline)`, floor only
36
+ * - `'none'` → `min-inline-size: max-content`, content floor (default)
14
37
  *
15
- * Designed to be composed alongside `useAnchorPosition` for top-layer popovers.
38
+ * `self-inline` is the inline axis of the element USING the function (the popover), never the
39
+ * anchor, so it matches the axis `inline-size` constrains. See
40
+ * `notes/decisions/width-from-anchor-floors.md`.
16
41
  */
17
- export function useWidthFromAnchor(_ref) {
18
- var mode = _ref.mode,
19
- popoverRef = _ref.popoverRef,
20
- anchorRef = _ref.anchorRef,
21
- isOpen = _ref.isOpen;
42
+ export function useWidthFromAnchor(_ref2) {
43
+ var mode = _ref2.mode,
44
+ popoverRef = _ref2.popoverRef,
45
+ anchorRef = _ref2.anchorRef,
46
+ isOpen = _ref2.isOpen;
22
47
  useLayoutEffect(function () {
23
48
  var node = popoverRef.current;
24
49
  if (!node) {
25
50
  return;
26
51
  }
27
-
28
- // Feature-detect `anchor-size()` specifically (not just `anchor-name`)
29
- // so the JS fallback fires correctly in browsers that support anchor
30
- // positioning but not anchor sizing.
31
- var supportsAnchorSize = typeof CSS !== 'undefined' && typeof CSS.supports === 'function' && CSS.supports('width', 'anchor-size(width)');
32
52
  if (mode === 'match-anchor') {
33
- // Set an exact width matching the anchor.
34
- // `min-inline-size` is intentionally NOT set here - it would override the
35
- // explicit width constraint, allowing the popover to grow past the anchor's width.
36
- if (supportsAnchorSize) {
53
+ // No floor here: it would let the popover grow past the anchor.
54
+ if (supportsAnchorSize()) {
37
55
  return setStyle({
38
56
  element: node,
39
57
  styles: [{
40
- property: 'width',
41
- value: 'anchor-size(width)'
58
+ property: 'inline-size',
59
+ value: 'anchor-size(self-inline)'
42
60
  }]
43
61
  });
44
62
  }
45
-
46
- // JS fallback: one-off read of the anchor's width.
47
63
  var anchor = anchorRef.current;
48
64
  if (anchor) {
49
65
  return setStyle({
50
66
  element: node,
51
67
  styles: [{
52
- property: 'width',
53
- value: "".concat(anchor.offsetWidth, "px")
68
+ property: 'inline-size',
69
+ value: "".concat(getFallbackAnchorInlineSize({
70
+ anchor: anchor,
71
+ popover: node
72
+ }), "px")
54
73
  }]
55
74
  });
56
75
  }
57
76
  return;
58
77
  }
59
-
60
- // For 'min-anchor' and 'none', apply `min-inline-size: max-content` to ensure
61
- // correct position-try-fallbacks behaviour (popover margin box overflows the
62
- // viewport when its span region is too narrow, rather than wrapping content).
63
- var minInlineSizeStyle = {
64
- property: 'min-inline-size',
65
- value: 'max-content'
66
- };
67
78
  if (mode === 'min-anchor') {
68
- // Set a minimum width matching the anchor. The popover can grow wider
69
- // if its content requires it.
70
- if (supportsAnchorSize) {
79
+ // One floor only. The content floor from mode 'none' deliberately does not also apply
80
+ // here, and cannot: it would need this same property. See the decision note.
81
+ if (supportsAnchorSize()) {
71
82
  return setStyle({
72
83
  element: node,
73
- styles: [minInlineSizeStyle, {
74
- property: 'min-width',
75
- value: 'anchor-size(width)'
84
+ styles: [{
85
+ property: 'min-inline-size',
86
+ value: 'anchor-size(self-inline)'
76
87
  }]
77
88
  });
78
89
  }
@@ -80,24 +91,28 @@ export function useWidthFromAnchor(_ref) {
80
91
  if (_anchor) {
81
92
  return setStyle({
82
93
  element: node,
83
- styles: [minInlineSizeStyle, {
84
- property: 'min-width',
85
- value: "".concat(_anchor.offsetWidth, "px")
94
+ styles: [{
95
+ property: 'min-inline-size',
96
+ value: "".concat(getFallbackAnchorInlineSize({
97
+ anchor: _anchor,
98
+ popover: node
99
+ }), "px")
86
100
  }]
87
101
  });
88
102
  }
89
103
 
90
- // No anchor available in JS fallback - still apply min-inline-size.
91
- return setStyle({
92
- element: node,
93
- styles: [minInlineSizeStyle]
94
- });
104
+ // Nothing to measure, so no floor.
105
+ return;
95
106
  }
96
107
 
97
- // 'none' mode: no explicit width, but still apply `min-inline-size: max-content`.
108
+ // Makes a too-narrow span overflow and drive `position-try-fallbacks` instead of wrapping.
109
+ // `@atlaskit/popper` resets this exact property to `0` for its fit-to-viewport mode.
98
110
  return setStyle({
99
111
  element: node,
100
- styles: [minInlineSizeStyle]
112
+ styles: [{
113
+ property: 'min-inline-size',
114
+ value: 'max-content'
115
+ }]
101
116
  });
102
117
  }, [mode, popoverRef, anchorRef, isOpen]);
103
118
  }
@@ -1,4 +1,34 @@
1
- import { type TPlacement } from './resolve-placement';
1
+ import { type TCrossAxisShiftDirection, type TPlacement } from './resolve-placement';
2
+ /**
3
+ * JS fallback positioning math. Used only when the browser does not
4
+ * support CSS Anchor Positioning (less than 6% of users).
5
+ *
6
+ * Consumer-supplied `offset.gap` and `offset.crossAxisShift` are
7
+ * honored: the caller (`useAnchorPosition`) resolves CSS length strings
8
+ * (tokens, calc, var, etc) to pixels via a DOM probe before passing them
9
+ * in. The caller also keeps the popover hidden (`opacity: 0`) until the
10
+ * first measurement completes, so the popover never paints at the wrong
11
+ * position.
12
+ */
13
+ /**
14
+ * A viewport-relative position, in pixels. Physical rather than logical
15
+ * because it is written straight to `top` / `left`.
16
+ */
17
+ type TPosition = {
18
+ top: number;
19
+ left: number;
20
+ };
21
+ /**
22
+ * The cross-axis shift with its length already resolved to pixels.
23
+ *
24
+ * Mirrors `TCrossAxisShiftOffset`, whose `value` is an unresolved CSS length
25
+ * string. Only this module needs the pixel form, because only this module does
26
+ * the arithmetic itself.
27
+ */
28
+ type TResolvedCrossAxisShift = {
29
+ value: number;
30
+ direction: TCrossAxisShiftDirection;
31
+ };
2
32
  /**
3
33
  * Computes popover position from trigger rect and viewport, flipping to
4
34
  * the side with more space when needed. Re-runs on scroll/resize.
@@ -16,11 +46,6 @@ export declare function computeFallbackPosition({ triggerRect, popoverEl, placem
16
46
  height: number;
17
47
  };
18
48
  gap: number;
19
- crossAxisShift: {
20
- value: number;
21
- direction: 'forwards' | 'backwards';
22
- };
23
- }): {
24
- top: number;
25
- left: number;
26
- };
49
+ crossAxisShift: TResolvedCrossAxisShift;
50
+ }): TPosition;
51
+ export {};
@@ -65,8 +65,9 @@ type TAriaForTrigger = {
65
65
  * `menu → "menu"`, `tooltip → undefined`). React omits the attribute when
66
66
  * the value is `undefined`.
67
67
  * - `aria-expanded` - reflects the current open state.
68
- * - `aria-controls` - references the popover element by its id while the
69
- * popover is open, and is omitted while the popover is closed and unmounted.
68
+ * - `aria-controls` - references the popover element by its id, even
69
+ * while the popover is closed. The relationship is stable; `aria-expanded`
70
+ * carries the current visibility state.
70
71
  *
71
72
  * **This function is for click/keyboard-activated popovers only.** For
72
73
  * hover-driven tooltips, the trigger should use `aria-describedby` instead.
@@ -1,14 +1,20 @@
1
+ /**
2
+ * Which way along the cross axis a shift moves the popover. `'forwards'` is
3
+ * always toward the cross-axis END and `'backwards'` toward the START, for
4
+ * every `align` value. See `notes/decisions/placement-offset.md`.
5
+ */
6
+ export type TCrossAxisShiftDirection = 'forwards' | 'backwards';
1
7
  /**
2
8
  * Cross-axis shift. `value` is a CSS length string (consumer numbers are
3
- * normalized to `${n}px`). `direction` is `'forwards'` (toward end) or
4
- * `'backwards'` (toward start).
9
+ * normalized to `${n}px`).
5
10
  */
6
11
  export type TCrossAxisShiftOffset = {
7
12
  value: string;
8
- direction: 'forwards' | 'backwards';
13
+ direction: TCrossAxisShiftDirection;
9
14
  };
10
15
  export type TPlacementAxis = 'block' | 'inline';
11
16
  export type TPlacementEdge = 'start' | 'end';
17
+ export type TPlacementAlign = 'start' | 'center' | 'end';
12
18
  /**
13
19
  * Fully-resolved placement (internal). Use `resolvePlacement` for partial input.
14
20
  * `offset.gap` and `offset.crossAxisShift.value` are always CSS
@@ -17,13 +23,10 @@ export type TPlacementEdge = 'start' | 'end';
17
23
  export type TPlacement = {
18
24
  axis: TPlacementAxis;
19
25
  edge: TPlacementEdge;
20
- align: 'start' | 'center' | 'end';
26
+ align: TPlacementAlign;
21
27
  offset: {
22
28
  gap: string;
23
- crossAxisShift: {
24
- value: string;
25
- direction: 'forwards' | 'backwards';
26
- };
29
+ crossAxisShift: TCrossAxisShiftOffset;
27
30
  };
28
31
  };
29
32
  /**
@@ -36,14 +39,14 @@ export type TPlacement = {
36
39
  * - `crossAxisShift` - nudge along the trigger edge (perpendicular to the placement axis)
37
40
  */
38
41
  export type TPlacementOptions = {
39
- axis?: 'block' | 'inline';
40
- edge?: 'start' | 'end';
41
- align?: 'start' | 'center' | 'end';
42
+ axis?: TPlacementAxis;
43
+ edge?: TPlacementEdge;
44
+ align?: TPlacementAlign;
42
45
  offset?: {
43
46
  gap?: number | string;
44
47
  crossAxisShift?: {
45
48
  value?: number | string;
46
- direction?: 'forwards' | 'backwards';
49
+ direction?: TCrossAxisShiftDirection;
47
50
  };
48
51
  };
49
52
  };
@@ -1,11 +1,20 @@
1
+ /**
2
+ * A single inline style declaration.
3
+ *
4
+ * `TProperty` narrows the property name for callers that write a known, closed
5
+ * set of properties. Narrowing it lets a record keyed on those same names be
6
+ * checked for exhaustiveness at compile time, rather than silently resolving to
7
+ * `undefined` for a name that was never mapped.
8
+ */
9
+ export type TStyleDeclaration<TProperty extends string = string> = {
10
+ property: TProperty;
11
+ value: string;
12
+ };
1
13
  /**
2
14
  * Sets inline styles on an element and returns a cleanup function that
3
15
  * restores the prior inline values (so we do not stomp consumer styles).
4
16
  */
5
17
  export declare function setStyle({ element, styles, }: {
6
18
  element: HTMLElement;
7
- styles: Array<{
8
- property: string;
9
- value: string;
10
- }>;
19
+ styles: TStyleDeclaration[];
11
20
  }): () => void;
@@ -3,15 +3,13 @@ import type { TWidthFromAnchorMode } from '../popover/types';
3
3
  /**
4
4
  * Sets the width of a popover element relative to its anchor element.
5
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)
6
+ * - `'match-anchor'` → `inline-size: anchor-size(self-inline)`, exact
7
+ * - `'min-anchor'` → `min-inline-size: anchor-size(self-inline)`, floor only
8
+ * - `'none'` → `min-inline-size: max-content`, content floor (default)
10
9
  *
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.
10
+ * `self-inline` is the inline axis of the element USING the function (the popover), never the
11
+ * anchor, so it matches the axis `inline-size` constrains. See
12
+ * `notes/decisions/width-from-anchor-floors.md`.
15
13
  */
16
14
  export declare function useWidthFromAnchor({ mode, popoverRef, anchorRef, isOpen, }: {
17
15
  mode: TWidthFromAnchorMode;
@@ -166,11 +166,12 @@ export type TPopoverProps = TPopoverBaseProps & TAriaRoleRequired & ({
166
166
  *
167
167
  * - `'none'` (default): popover sizes to its content, ignoring the anchor width.
168
168
  * - `'match-anchor'`: popover matches the anchor element's width exactly
169
- * via CSS `anchor-size(width)`. Falls back to a one-off measurement
170
- * of `anchorRef.current.offsetWidth` when CSS Anchor Positioning
171
- * is not supported.
169
+ * via CSS `inline-size: anchor-size(self-inline)`. Falls back to a
170
+ * one-off measurement of `anchorRef.current.offsetWidth` when CSS
171
+ * Anchor Positioning is not supported.
172
172
  * - `'min-anchor'`: popover is at least as wide as the anchor, but
173
- * can grow wider if content requires it. Uses `min-width: anchor-size(width)`.
174
- * Falls back to a one-off measurement of the anchor's width.
173
+ * can grow wider if content requires it. Uses
174
+ * `min-inline-size: anchor-size(self-inline)`. Falls back to a one-off
175
+ * measurement of the anchor's width.
175
176
  */
176
177
  export type TWidthFromAnchorMode = 'none' | 'match-anchor' | 'min-anchor';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/top-layer",
3
- "version": "4.2.2",
3
+ "version": "4.2.4",
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",