@atlaskit/top-layer 4.4.5 → 5.0.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 +41 -0
- package/README.md +13 -4
- package/dist/cjs/dialog/dialog-content.js +2 -0
- package/dist/cjs/entry-points/use-popover-id.js +5 -10
- package/dist/cjs/internal/anchor-positioning/apply-anchor-positioning.js +86 -0
- package/dist/cjs/internal/anchor-positioning/cross-axis-shift-margins.js +34 -0
- package/dist/cjs/internal/anchor-positioning/edge-margin.js +21 -0
- package/dist/cjs/internal/anchor-positioning/fit-margins.js +77 -0
- package/dist/cjs/internal/anchor-positioning/get-existing-anchor-name.js +18 -0
- package/dist/cjs/internal/{placement-to-position-area.js → anchor-positioning/placement-to-position-area.js} +11 -11
- package/dist/cjs/internal/anchor-positioning/placement-to-try-fallbacks.js +95 -0
- package/dist/cjs/internal/anchored-popover-size.js +345 -0
- package/dist/cjs/internal/get-aria-for-trigger.js +7 -13
- package/dist/cjs/internal/{anchor-positioning-fallback.js → javascript-fallback/anchor-positioning-fallback.js} +12 -33
- package/dist/cjs/internal/javascript-fallback/apply-javascript-fallback-positioning.js +297 -0
- package/dist/cjs/internal/javascript-fallback/resolve-css-length-to-pixels.js +90 -0
- package/dist/cjs/internal/javascript-fallback/warn-fallback-failure.js +19 -0
- package/dist/cjs/internal/resolve-placement.js +14 -6
- package/dist/cjs/internal/supports-anchor-positioning.js +17 -0
- package/dist/cjs/internal/supports-anchor-size.js +17 -0
- package/dist/cjs/internal/supports-css-declaration.js +25 -0
- package/dist/cjs/internal/surface-reset.js +5 -0
- package/dist/cjs/internal/use-anchored-popover-at-point.js +124 -0
- package/dist/cjs/internal/use-anchored-popover.js +277 -0
- package/dist/cjs/popover/popover.compiled.css +4 -0
- package/dist/cjs/popover/popover.js +11 -4
- package/dist/cjs/testing/polyfill.js +6 -7
- package/dist/es2019/dialog/dialog-content.js +2 -0
- package/dist/es2019/entry-points/use-popover-id.js +6 -10
- package/dist/es2019/internal/anchor-positioning/apply-anchor-positioning.js +83 -0
- package/dist/es2019/internal/anchor-positioning/cross-axis-shift-margins.js +29 -0
- package/dist/es2019/internal/anchor-positioning/edge-margin.js +18 -0
- package/dist/es2019/internal/anchor-positioning/fit-margins.js +69 -0
- package/dist/es2019/internal/anchor-positioning/get-existing-anchor-name.js +12 -0
- package/dist/es2019/internal/{placement-to-position-area.js → anchor-positioning/placement-to-position-area.js} +9 -9
- package/dist/es2019/internal/anchor-positioning/placement-to-try-fallbacks.js +94 -0
- package/dist/es2019/internal/anchored-popover-size.js +343 -0
- package/dist/es2019/internal/get-aria-for-trigger.js +7 -13
- package/dist/es2019/internal/{anchor-positioning-fallback.js → javascript-fallback/anchor-positioning-fallback.js} +12 -33
- package/dist/es2019/internal/javascript-fallback/apply-javascript-fallback-positioning.js +291 -0
- package/dist/es2019/internal/javascript-fallback/resolve-css-length-to-pixels.js +87 -0
- package/dist/es2019/internal/javascript-fallback/warn-fallback-failure.js +14 -0
- package/dist/es2019/internal/resolve-placement.js +14 -6
- package/dist/es2019/internal/supports-anchor-positioning.js +12 -0
- package/dist/es2019/internal/supports-anchor-size.js +12 -0
- package/dist/es2019/internal/supports-css-declaration.js +20 -0
- package/dist/es2019/internal/surface-reset.js +1 -0
- package/dist/es2019/internal/use-anchored-popover-at-point.js +116 -0
- package/dist/es2019/internal/use-anchored-popover.js +265 -0
- package/dist/es2019/popover/popover.compiled.css +4 -0
- package/dist/es2019/popover/popover.js +11 -4
- package/dist/es2019/testing/polyfill.js +6 -7
- package/dist/esm/dialog/dialog-content.js +2 -0
- package/dist/esm/entry-points/use-popover-id.js +6 -10
- package/dist/esm/internal/anchor-positioning/apply-anchor-positioning.js +80 -0
- package/dist/esm/internal/anchor-positioning/cross-axis-shift-margins.js +28 -0
- package/dist/esm/internal/anchor-positioning/edge-margin.js +15 -0
- package/dist/esm/internal/anchor-positioning/fit-margins.js +71 -0
- package/dist/esm/internal/anchor-positioning/get-existing-anchor-name.js +12 -0
- package/dist/esm/internal/{placement-to-position-area.js → anchor-positioning/placement-to-position-area.js} +11 -12
- package/dist/esm/internal/anchor-positioning/placement-to-try-fallbacks.js +89 -0
- package/dist/esm/internal/anchored-popover-size.js +338 -0
- package/dist/esm/internal/get-aria-for-trigger.js +7 -13
- package/dist/esm/internal/{anchor-positioning-fallback.js → javascript-fallback/anchor-positioning-fallback.js} +12 -33
- package/dist/esm/internal/javascript-fallback/apply-javascript-fallback-positioning.js +290 -0
- package/dist/esm/internal/javascript-fallback/resolve-css-length-to-pixels.js +85 -0
- package/dist/esm/internal/javascript-fallback/warn-fallback-failure.js +13 -0
- package/dist/esm/internal/resolve-placement.js +14 -6
- package/dist/esm/internal/supports-anchor-positioning.js +12 -0
- package/dist/esm/internal/supports-anchor-size.js +12 -0
- package/dist/esm/internal/supports-css-declaration.js +19 -0
- package/dist/esm/internal/surface-reset.js +1 -0
- package/dist/esm/internal/use-anchored-popover-at-point.js +118 -0
- package/dist/esm/internal/use-anchored-popover.js +271 -0
- package/dist/esm/popover/popover.compiled.css +4 -0
- package/dist/esm/popover/popover.js +11 -4
- package/dist/esm/testing/polyfill.js +6 -7
- package/dist/types/entry-points/placement-map.d.ts +2 -2
- package/dist/types/entry-points/use-popover-id.d.ts +3 -7
- package/dist/types/internal/anchor-positioning/apply-anchor-positioning.d.ts +26 -0
- package/dist/types/internal/anchor-positioning/cross-axis-shift-margins.d.ts +19 -0
- package/dist/types/internal/anchor-positioning/edge-margin.d.ts +10 -0
- package/dist/types/internal/anchor-positioning/fit-margins.d.ts +30 -0
- package/dist/types/internal/anchor-positioning/get-existing-anchor-name.d.ts +8 -0
- package/dist/types/internal/{placement-to-position-area.d.ts → anchor-positioning/placement-to-position-area.d.ts} +10 -6
- package/dist/types/internal/anchor-positioning/placement-to-try-fallbacks.d.ts +30 -0
- package/dist/types/internal/anchored-popover-size.d.ts +126 -0
- package/dist/types/internal/get-aria-for-trigger.d.ts +13 -25
- package/dist/types/internal/javascript-fallback/anchor-positioning-fallback.d.ts +36 -0
- package/dist/types/internal/javascript-fallback/apply-javascript-fallback-positioning.d.ts +15 -0
- package/dist/types/internal/javascript-fallback/resolve-css-length-to-pixels.d.ts +20 -0
- package/dist/types/internal/javascript-fallback/warn-fallback-failure.d.ts +7 -0
- package/dist/types/internal/resolve-placement.d.ts +18 -2
- package/dist/types/internal/supports-anchor-positioning.d.ts +5 -0
- package/dist/types/internal/supports-anchor-size.d.ts +5 -0
- package/dist/types/internal/supports-css-declaration.d.ts +11 -0
- package/dist/types/internal/surface-reset.d.ts +25 -0
- package/dist/types/internal/use-anchored-popover-at-point.d.ts +48 -0
- package/dist/types/internal/use-anchored-popover.d.ts +143 -0
- package/dist/types/popover/index.d.ts +2 -1
- package/dist/types/popover/popover.d.ts +1 -1
- package/dist/types/popover/types.d.ts +15 -17
- package/dist/types/testing/polyfill.d.ts +3 -3
- package/package.json +2 -2
- package/use-anchored-popover/package.json +10 -0
- package/use-anchored-popover-at-point/package.json +10 -0
- package/dist/cjs/internal/placement-to-try-fallbacks.js +0 -108
- package/dist/cjs/internal/resolve-css-length-to-pixels.js +0 -104
- package/dist/cjs/internal/use-anchor-position-at-point.js +0 -129
- package/dist/cjs/internal/use-anchor-position.js +0 -501
- package/dist/cjs/internal/use-width-from-anchor.js +0 -124
- package/dist/es2019/internal/placement-to-try-fallbacks.js +0 -108
- package/dist/es2019/internal/resolve-css-length-to-pixels.js +0 -101
- package/dist/es2019/internal/use-anchor-position-at-point.js +0 -124
- package/dist/es2019/internal/use-anchor-position.js +0 -480
- package/dist/es2019/internal/use-width-from-anchor.js +0 -120
- package/dist/esm/internal/placement-to-try-fallbacks.js +0 -103
- package/dist/esm/internal/resolve-css-length-to-pixels.js +0 -98
- package/dist/esm/internal/use-anchor-position-at-point.js +0 -124
- package/dist/esm/internal/use-anchor-position.js +0 -494
- package/dist/esm/internal/use-width-from-anchor.js +0 -118
- package/dist/types/internal/anchor-positioning-fallback.d.ts +0 -51
- package/dist/types/internal/placement-to-try-fallbacks.d.ts +0 -13
- package/dist/types/internal/resolve-css-length-to-pixels.d.ts +0 -20
- package/dist/types/internal/use-anchor-position-at-point.d.ts +0 -67
- package/dist/types/internal/use-anchor-position.d.ts +0 -87
- package/dist/types/internal/use-width-from-anchor.d.ts +0 -19
- package/use-anchor-position/package.json +0 -10
- package/use-anchor-position-at-point/package.json +0 -10
- package/use-width-from-anchor/package.json +0 -10
|
@@ -1,501 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
-
Object.defineProperty(exports, "__esModule", {
|
|
5
|
-
value: true
|
|
6
|
-
});
|
|
7
|
-
exports.useAnchorPosition = useAnchorPosition;
|
|
8
|
-
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
|
-
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
10
|
-
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
11
|
-
var _react = require("react");
|
|
12
|
-
var _bindEventListener = require("bind-event-listener");
|
|
13
|
-
var _rafSchd = _interopRequireDefault(require("raf-schd"));
|
|
14
|
-
var _once = _interopRequireDefault(require("@atlaskit/ds-lib/once"));
|
|
15
|
-
var _anchorPositioningFallback = require("./anchor-positioning-fallback");
|
|
16
|
-
var _combine = require("./combine");
|
|
17
|
-
var _placementToPositionArea = require("./placement-to-position-area");
|
|
18
|
-
var _placementToTryFallbacks = require("./placement-to-try-fallbacks");
|
|
19
|
-
var _resolveCssLengthToPixels = require("./resolve-css-length-to-pixels");
|
|
20
|
-
var _resolvePlacement = require("./resolve-placement");
|
|
21
|
-
var _setStyle = require("./set-style");
|
|
22
|
-
/**
|
|
23
|
-
* Anchor positioning for top-layer popovers. See
|
|
24
|
-
* `notes/architecture/positioning.md` for the full model.
|
|
25
|
-
*
|
|
26
|
-
* Two runtime paths: CSS Anchor Positioning (modern browsers) and a JS
|
|
27
|
-
* fallback that measures the trigger and writes `top`/`left`.
|
|
28
|
-
*
|
|
29
|
-
* Both paths honour `offset.gap` and `offset.crossAxisShift`. The
|
|
30
|
-
* CSS path passes the values through as strings; the JS fallback resolves
|
|
31
|
-
* them to pixels via a hidden DOM probe (see `resolveCssLengthToPixels`)
|
|
32
|
-
* so tokens, `calc()`, `var()`, etc all work. The JS fallback hides the
|
|
33
|
-
* popover with `opacity: 0` until the first measurement completes, so it
|
|
34
|
-
* is never painted at the wrong location.
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
// `resolvePlacement` is intentionally NOT re-exported here - import it directly
|
|
38
|
-
// from `./resolve-placement` so search-and-jump lands at the source of truth.
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Module-scope no-op `ResizeObserver` used in non-DOM jest environments where
|
|
42
|
-
* `ResizeObserver` is `undefined`. Hoisted out of the effect to avoid
|
|
43
|
-
* allocating a new class declaration on every run.
|
|
44
|
-
*/
|
|
45
|
-
var NoopResizeObserver = /*#__PURE__*/function () {
|
|
46
|
-
function NoopResizeObserver() {
|
|
47
|
-
(0, _classCallCheck2.default)(this, NoopResizeObserver);
|
|
48
|
-
}
|
|
49
|
-
return (0, _createClass2.default)(NoopResizeObserver, [{
|
|
50
|
-
key: "observe",
|
|
51
|
-
value: function observe() {}
|
|
52
|
-
}, {
|
|
53
|
-
key: "unobserve",
|
|
54
|
-
value: function unobserve() {}
|
|
55
|
-
}, {
|
|
56
|
-
key: "disconnect",
|
|
57
|
-
value: function disconnect() {}
|
|
58
|
-
}]);
|
|
59
|
-
}();
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Returns true when the popover is currently open. Wrapped because the
|
|
63
|
-
* `:popover-open` pseudo-class is not implemented in some test environments
|
|
64
|
-
* (e.g. jsdom), where `matches` throws on unknown selectors.
|
|
65
|
-
*/
|
|
66
|
-
function isPopoverOpen(popover) {
|
|
67
|
-
try {
|
|
68
|
-
return popover.matches(':popover-open');
|
|
69
|
-
} catch (_unused) {
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Detects whether the browser supports CSS Anchor Positioning.
|
|
76
|
-
* Uses `once()` for lazy evaluation: safe for SSR and avoids hydration mismatches.
|
|
77
|
-
*/
|
|
78
|
-
var supportsAnchorPositioning = (0, _once.default)(function () {
|
|
79
|
-
if (typeof window === 'undefined' || typeof CSS === 'undefined' || typeof CSS.supports !== 'function') {
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
return CSS.supports('anchor-name', '--a');
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Every logical margin property this module can write: one per axis, per side.
|
|
87
|
-
*
|
|
88
|
-
* Deriving the union from `TPlacementAxis` and `TPlacementEdge` rather than
|
|
89
|
-
* writing the four names out keeps it in step with the placement model, and
|
|
90
|
-
* makes `CROSS_AXIS_SHIFT_CUSTOM_PROPERTY` below exhaustive by construction.
|
|
91
|
-
*/
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* The custom property mirroring each cross-axis shift margin.
|
|
95
|
-
*
|
|
96
|
-
* These are written for the planned named arrow `@position-try` rules. Nothing
|
|
97
|
-
* reads them yet, and the shift no longer depends on them: the antisymmetric
|
|
98
|
-
* margins written by `crossAxisShiftMargins` survive a cross-axis slide on
|
|
99
|
-
* their own.
|
|
100
|
-
*
|
|
101
|
-
* Keyed on `TLogicalMarginProperty` and not on `string`, so a margin property
|
|
102
|
-
* that has no custom property (or a custom property whose margin no longer
|
|
103
|
-
* exists) is a compile error rather than an `undefined` lookup that reaches
|
|
104
|
-
* `setStyle` as `{ property: undefined, value }`.
|
|
105
|
-
*/
|
|
106
|
-
var CROSS_AXIS_SHIFT_CUSTOM_PROPERTY = {
|
|
107
|
-
'margin-inline-start': '--ds-cross-axis-shift-margin-start',
|
|
108
|
-
'margin-inline-end': '--ds-cross-axis-shift-margin-end',
|
|
109
|
-
'margin-block-start': '--ds-cross-axis-shift-margin-block-start',
|
|
110
|
-
'margin-block-end': '--ds-cross-axis-shift-margin-block-end'
|
|
111
|
-
};
|
|
112
|
-
var ZEROED_CROSS_AXIS_SHIFT_CUSTOM_PROPERTIES = Object.values(CROSS_AXIS_SHIFT_CUSTOM_PROPERTY).map(function (property) {
|
|
113
|
-
return {
|
|
114
|
-
property: property,
|
|
115
|
-
value: '0px'
|
|
116
|
-
};
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Returns the CSS margin declaration that creates a gap between the
|
|
121
|
-
* popover and its trigger on the side facing the anchor.
|
|
122
|
-
*
|
|
123
|
-
* For example, a `block-end` placement (popover below) gets
|
|
124
|
-
* `margin-block-start: 8px` to push it away from the trigger's bottom edge.
|
|
125
|
-
*/
|
|
126
|
-
function edgeMargin(_ref) {
|
|
127
|
-
var placement = _ref.placement,
|
|
128
|
-
offset = _ref.offset;
|
|
129
|
-
var axis = placement.axis,
|
|
130
|
-
edge = placement.edge;
|
|
131
|
-
// The gap sits on the side FACING the anchor, which is always the side
|
|
132
|
-
// opposite the placement edge.
|
|
133
|
-
var anchorFacingEdge = edge === 'end' ? 'start' : 'end';
|
|
134
|
-
return {
|
|
135
|
-
property: "margin-".concat(axis, "-").concat(anchorFacingEdge),
|
|
136
|
-
value: offset
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* **The cross-axis shift margins.**
|
|
142
|
-
*
|
|
143
|
-
* The shift is written antisymmetrically on BOTH cross-axis sides
|
|
144
|
-
* (`start: +value`, `end: -value`) rather than as a single margin on the side
|
|
145
|
-
* picked from `align`. Two separate behaviours require it:
|
|
146
|
-
*
|
|
147
|
-
* 1. **`align: 'center'` is centered with `anchor-center`, which centers the
|
|
148
|
-
* popover's MARGIN box on the anchor.** A single-sided margin widens the
|
|
149
|
-
* margin box, so it displaces the border box by only half its value. An
|
|
150
|
-
* antisymmetric pair leaves the margin box width unchanged (`+value` and
|
|
151
|
-
* `-value` sum to zero) while moving its center by the full value.
|
|
152
|
-
* 2. **`position-try-fallbacks` can slide the popover onto the opposite
|
|
153
|
-
* cross-axis side.** A `<position-area>` fallback keeps the base style's
|
|
154
|
-
* margins, and margin on the un-anchored side has no effect, so a
|
|
155
|
-
* single-sided margin is silently dropped once the browser slides across the
|
|
156
|
-
* cross axis. With both sides written, whichever side ends up anchored moves
|
|
157
|
-
* the popover the same physical direction.
|
|
158
|
-
*
|
|
159
|
-
* Leaving the margin box width unchanged also means the shift does not move
|
|
160
|
-
* the point at which `position-try-fallbacks` decides the popover overflows.
|
|
161
|
-
*
|
|
162
|
-
* A `<try-tactic>` fallback (`flip-block`, `flip-inline`) behaves differently to
|
|
163
|
-
* a `<position-area>` one: it SWAPS the start and end margins rather than
|
|
164
|
-
* keeping them, which is what preserves the gap through a flip. So a flip across
|
|
165
|
-
* the cross axis mirrors the shift along with the rest of the placement, rather
|
|
166
|
-
* than preserving its physical direction. Only the diagonal fallback does that,
|
|
167
|
-
* and only for `align: 'start' | 'end'`. See `placementToTryFallbacks`.
|
|
168
|
-
*
|
|
169
|
-
* A positive value always moves the popover toward the cross-axis END, so
|
|
170
|
-
* `direction: 'forwards'` means the same thing for every `align` value. See
|
|
171
|
-
* `notes/decisions/placement-offset.md`.
|
|
172
|
-
*/
|
|
173
|
-
function crossAxisShiftMargins(_ref2) {
|
|
174
|
-
var placement = _ref2.placement,
|
|
175
|
-
crossAxisShiftCssValue = _ref2.crossAxisShiftCssValue,
|
|
176
|
-
direction = _ref2.direction;
|
|
177
|
-
var crossAxis = placement.axis === 'block' ? 'inline' : 'block';
|
|
178
|
-
// Wrap any string in calc() with the sign factor. CSS handles the math,
|
|
179
|
-
// so opaque values such as design tokens negate correctly.
|
|
180
|
-
var negated = "calc(-1 * ".concat(crossAxisShiftCssValue, ")");
|
|
181
|
-
var isForwards = direction === 'forwards';
|
|
182
|
-
return [{
|
|
183
|
-
property: "margin-".concat(crossAxis, "-start"),
|
|
184
|
-
value: isForwards ? crossAxisShiftCssValue : negated
|
|
185
|
-
}, {
|
|
186
|
-
property: "margin-".concat(crossAxis, "-end"),
|
|
187
|
-
value: isForwards ? negated : crossAxisShiftCssValue
|
|
188
|
-
}];
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Returns a referentially-stable, fully-resolved `TPlacement`. The memo is
|
|
193
|
-
* keyed on the resolved primitive fields so a fresh inline `placement` object
|
|
194
|
-
* (or undefined fields vs explicit defaults) does not produce a fresh result.
|
|
195
|
-
*/
|
|
196
|
-
function useStablePlacement(placement) {
|
|
197
|
-
var resolved = (0, _resolvePlacement.resolvePlacement)({
|
|
198
|
-
placement: placement
|
|
199
|
-
});
|
|
200
|
-
var axis = resolved.axis;
|
|
201
|
-
var edge = resolved.edge;
|
|
202
|
-
var align = resolved.align;
|
|
203
|
-
var gap = resolved.offset.gap;
|
|
204
|
-
var shiftValue = resolved.offset.crossAxisShift.value;
|
|
205
|
-
var shiftDirection = resolved.offset.crossAxisShift.direction;
|
|
206
|
-
// Rebuild inside the memo from primitive deps so the factory does not
|
|
207
|
-
// close over the outer `resolved` reference and exhaustive-deps can verify.
|
|
208
|
-
return (0, _react.useMemo)(function () {
|
|
209
|
-
return {
|
|
210
|
-
axis: axis,
|
|
211
|
-
edge: edge,
|
|
212
|
-
align: align,
|
|
213
|
-
offset: {
|
|
214
|
-
gap: gap,
|
|
215
|
-
crossAxisShift: {
|
|
216
|
-
value: shiftValue,
|
|
217
|
-
direction: shiftDirection
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
}, [axis, edge, align, gap, shiftValue, shiftDirection]);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Hook that positions an element relative to an anchor element using
|
|
226
|
-
* CSS Anchor Positioning (with a JS fallback for older browsers).
|
|
227
|
-
*
|
|
228
|
-
* This hook is the positioning primitive. It has no knowledge of popovers,
|
|
229
|
-
* visibility, or animation. Compose it with `Popover` for anchor-positioned
|
|
230
|
-
* top-layer content.
|
|
231
|
-
*
|
|
232
|
-
* When CSS Anchor Positioning is supported, it sets CSS properties
|
|
233
|
-
* (`anchor-name`, `position-anchor`, `position-area`, `position-try-fallbacks`)
|
|
234
|
-
* directly on the elements via `el.style.setProperty()`.
|
|
235
|
-
*
|
|
236
|
-
* When not supported, it falls back to JavaScript-based positioning using
|
|
237
|
-
* `position: fixed` with measured coordinates, re-running on scroll (capture)
|
|
238
|
-
* and resize events.
|
|
239
|
-
*/
|
|
240
|
-
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
241
|
-
function useAnchorPosition(_ref3) {
|
|
242
|
-
var anchorRef = _ref3.anchorRef,
|
|
243
|
-
popoverRef = _ref3.popoverRef,
|
|
244
|
-
_ref3$placement = _ref3.placement,
|
|
245
|
-
placement = _ref3$placement === void 0 ? {} : _ref3$placement,
|
|
246
|
-
_ref3$forceFallbackPo = _ref3.forceFallbackPositioning,
|
|
247
|
-
forceFallbackPositioning = _ref3$forceFallbackPo === void 0 ? false : _ref3$forceFallbackPo,
|
|
248
|
-
_ref3$isEnabled = _ref3.isEnabled,
|
|
249
|
-
isEnabled = _ref3$isEnabled === void 0 ? true : _ref3$isEnabled,
|
|
250
|
-
isOpen = _ref3.isOpen;
|
|
251
|
-
var id = (0, _react.useId)();
|
|
252
|
-
var stablePlacement = useStablePlacement(placement);
|
|
253
|
-
(0, _react.useLayoutEffect)(function () {
|
|
254
|
-
if (!isEnabled) {
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
var trigger = anchorRef.current;
|
|
258
|
-
var popover = popoverRef.current;
|
|
259
|
-
if (!trigger || !popover) {
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
var gapCssValue = stablePlacement.offset.gap;
|
|
263
|
-
var crossAxisShiftCssValue = stablePlacement.offset.crossAxisShift.value;
|
|
264
|
-
var shouldForceFallback = Boolean(forceFallbackPositioning);
|
|
265
|
-
if (supportsAnchorPositioning() && !shouldForceFallback) {
|
|
266
|
-
// Reuse an existing `anchor-name` if the element already has one.
|
|
267
|
-
// Another popover might already be anchored to the old name.
|
|
268
|
-
var anchorName = trigger.style.getPropertyValue('anchor-name') || "--anchor-".concat(id.replace(/:/g, ''));
|
|
269
|
-
var gap = edgeMargin({
|
|
270
|
-
placement: stablePlacement,
|
|
271
|
-
offset: gapCssValue
|
|
272
|
-
});
|
|
273
|
-
// Computed once; also mirrored into the
|
|
274
|
-
// `--ds-cross-axis-shift-margin-*` custom properties below.
|
|
275
|
-
var crossAxisShift = crossAxisShiftMargins({
|
|
276
|
-
placement: stablePlacement,
|
|
277
|
-
crossAxisShiftCssValue: crossAxisShiftCssValue,
|
|
278
|
-
direction: stablePlacement.offset.crossAxisShift.direction
|
|
279
|
-
});
|
|
280
|
-
var popoverStyles = [{
|
|
281
|
-
property: 'position-anchor',
|
|
282
|
-
value: anchorName
|
|
283
|
-
}, {
|
|
284
|
-
property: 'position-area',
|
|
285
|
-
value: (0, _placementToPositionArea.placementToPositionArea)({
|
|
286
|
-
placement: stablePlacement
|
|
287
|
-
})
|
|
288
|
-
}, {
|
|
289
|
-
property: 'position-try-fallbacks',
|
|
290
|
-
value: (0, _placementToTryFallbacks.placementToTryFallbacks)({
|
|
291
|
-
placement: stablePlacement
|
|
292
|
-
})
|
|
293
|
-
},
|
|
294
|
-
// Reset browser default popover positioning that conflicts
|
|
295
|
-
// with anchor positioning (UA: `inset: 0; margin: auto;`)
|
|
296
|
-
{
|
|
297
|
-
property: 'margin',
|
|
298
|
-
value: '0'
|
|
299
|
-
}, {
|
|
300
|
-
property: 'inset',
|
|
301
|
-
value: 'auto'
|
|
302
|
-
}, gap].concat((0, _toConsumableArray2.default)(crossAxisShift), (0, _toConsumableArray2.default)(ZEROED_CROSS_AXIS_SHIFT_CUSTOM_PROPERTIES), (0, _toConsumableArray2.default)(crossAxisShift.map(function (_ref4) {
|
|
303
|
-
var property = _ref4.property,
|
|
304
|
-
value = _ref4.value;
|
|
305
|
-
return {
|
|
306
|
-
property: CROSS_AXIS_SHIFT_CUSTOM_PROPERTY[property],
|
|
307
|
-
value: value
|
|
308
|
-
};
|
|
309
|
-
})));
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* **We are never cleaning up anchor names**
|
|
313
|
-
*
|
|
314
|
-
* _Rationale_
|
|
315
|
-
*
|
|
316
|
-
* - Multiple popovers can share the same anchor element.
|
|
317
|
-
* - Sometimes the `useAnchorPosition` hook and `Popover`
|
|
318
|
-
* are not in the same component.
|
|
319
|
-
* - There can be times when, even with reference counting, we
|
|
320
|
-
* could remove the anchor-name while it is still being used
|
|
321
|
-
* by something else - especially with async react updates
|
|
322
|
-
* which can cause tearing
|
|
323
|
-
*
|
|
324
|
-
* _More_
|
|
325
|
-
*
|
|
326
|
-
* See `notes/decisions/anchor-name-lifetime.md`
|
|
327
|
-
*/
|
|
328
|
-
trigger.style.setProperty('anchor-name', anchorName);
|
|
329
|
-
return (0, _setStyle.setStyle)({
|
|
330
|
-
element: popover,
|
|
331
|
-
styles: popoverStyles
|
|
332
|
-
});
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// JS fallback. The popover is already in the top layer via
|
|
336
|
-
// popover="auto", so we only reset UA defaults and set top/left
|
|
337
|
-
// based on measurements.
|
|
338
|
-
var cleanupBaseStyles = (0, _setStyle.setStyle)({
|
|
339
|
-
element: popover,
|
|
340
|
-
styles: [{
|
|
341
|
-
property: 'margin',
|
|
342
|
-
value: '0'
|
|
343
|
-
}, {
|
|
344
|
-
property: 'inset',
|
|
345
|
-
value: 'auto'
|
|
346
|
-
}]
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
// The popover can be consumer-owned (`@atlaskit/popper`'s `createPopper`),
|
|
350
|
-
// so restore prior inline values rather than removing ours.
|
|
351
|
-
var undoPosition;
|
|
352
|
-
var undoHide;
|
|
353
|
-
|
|
354
|
-
// `opacity: 0` not `visibility: hidden`: Firefox skips visibility-hidden
|
|
355
|
-
// elements during `<dialog>` initial-focus traversal.
|
|
356
|
-
function hideUntilPositioned() {
|
|
357
|
-
// Keep the first snapshot, else we capture our own `opacity: 0`.
|
|
358
|
-
// (`!popover` is for TS: narrowing does not reach nested functions.)
|
|
359
|
-
if (!popover || undoHide) {
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
undoHide = (0, _setStyle.setStyle)({
|
|
363
|
-
element: popover,
|
|
364
|
-
styles: [{
|
|
365
|
-
property: 'opacity',
|
|
366
|
-
value: '0'
|
|
367
|
-
}]
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
function reveal() {
|
|
371
|
-
var _undoHide;
|
|
372
|
-
(_undoHide = undoHide) === null || _undoHide === void 0 || _undoHide();
|
|
373
|
-
undoHide = undefined;
|
|
374
|
-
}
|
|
375
|
-
function restorePosition() {
|
|
376
|
-
var _undoPosition;
|
|
377
|
-
(_undoPosition = undoPosition) === null || _undoPosition === void 0 || _undoPosition();
|
|
378
|
-
undoPosition = undefined;
|
|
379
|
-
}
|
|
380
|
-
function update() {
|
|
381
|
-
if (!trigger || !popover) {
|
|
382
|
-
return;
|
|
383
|
-
}
|
|
384
|
-
var triggerRect = trigger.getBoundingClientRect();
|
|
385
|
-
var viewport = {
|
|
386
|
-
width: window.innerWidth,
|
|
387
|
-
height: window.innerHeight
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
// Resolve consumer-supplied CSS length strings (tokens, calc, var,
|
|
391
|
-
// px, rem, etc) to pixels. The probe is mounted INSIDE the popover
|
|
392
|
-
// itself so the resolved length matches the scope a token would
|
|
393
|
-
// resolve against from inside the popover content. (The popover
|
|
394
|
-
// lives in the top layer, not the trigger's DOM tree, so probing
|
|
395
|
-
// at `popover.parentElement` would resolve in a different scope
|
|
396
|
-
// than the consumer's token authoring expects.)
|
|
397
|
-
var gapPx = (0, _resolveCssLengthToPixels.resolveCssLengthToPixels)({
|
|
398
|
-
value: gapCssValue,
|
|
399
|
-
container: popover
|
|
400
|
-
});
|
|
401
|
-
var crossAxisShiftPx = (0, _resolveCssLengthToPixels.resolveCssLengthToPixels)({
|
|
402
|
-
value: crossAxisShiftCssValue,
|
|
403
|
-
container: popover
|
|
404
|
-
});
|
|
405
|
-
var _computeFallbackPosit = (0, _anchorPositioningFallback.computeFallbackPosition)({
|
|
406
|
-
triggerRect: triggerRect,
|
|
407
|
-
popoverEl: popover,
|
|
408
|
-
placement: stablePlacement,
|
|
409
|
-
viewport: viewport,
|
|
410
|
-
gap: gapPx,
|
|
411
|
-
crossAxisShift: {
|
|
412
|
-
value: crossAxisShiftPx,
|
|
413
|
-
direction: stablePlacement.offset.crossAxisShift.direction
|
|
414
|
-
}
|
|
415
|
-
}),
|
|
416
|
-
top = _computeFallbackPosit.top,
|
|
417
|
-
left = _computeFallbackPosit.left;
|
|
418
|
-
|
|
419
|
-
// Restore first so the snapshot stays the consumer's value.
|
|
420
|
-
restorePosition();
|
|
421
|
-
undoPosition = (0, _setStyle.setStyle)({
|
|
422
|
-
element: popover,
|
|
423
|
-
styles: [{
|
|
424
|
-
property: 'top',
|
|
425
|
-
value: "".concat(top, "px")
|
|
426
|
-
}, {
|
|
427
|
-
property: 'left',
|
|
428
|
-
value: "".concat(left, "px")
|
|
429
|
-
}]
|
|
430
|
-
});
|
|
431
|
-
reveal();
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
// Throttle scroll/resize updates to one per animation frame
|
|
435
|
-
var scheduledUpdate = (0, _rafSchd.default)(update);
|
|
436
|
-
|
|
437
|
-
// Wait for the FIRST valid layout before measuring: the popover
|
|
438
|
-
// is `display: none` until `showPopover()`, and some browsers
|
|
439
|
-
// fire `toggle` before layout, so RAF-after-toggle is unreliable.
|
|
440
|
-
// ResizeObserver fires once the browser has real dimensions.
|
|
441
|
-
// Self-disconnects after one valid measurement; ongoing
|
|
442
|
-
// scroll/resize is handled by the window listeners below.
|
|
443
|
-
// `ResizeObserver` is missing in some non-DOM jest environments
|
|
444
|
-
// (e.g. post-office's `node` environment). Fall back to a no-op
|
|
445
|
-
// observer there. The scroll/resize listeners below still keep
|
|
446
|
-
// the popover positioned in the rare case the consumer also
|
|
447
|
-
// polyfilled `showPopover` but not `ResizeObserver`. Real
|
|
448
|
-
// browsers always have it. The `NoopResizeObserver` class is
|
|
449
|
-
// hoisted to module scope (see top of file) so we do not allocate
|
|
450
|
-
// a new constructor on every effect run.
|
|
451
|
-
var ResizeObserverImpl = typeof ResizeObserver !== 'undefined' ? ResizeObserver : NoopResizeObserver;
|
|
452
|
-
var resizeObserver = new ResizeObserverImpl(function () {
|
|
453
|
-
if (popover.offsetWidth > 0 && popover.offsetHeight > 0) {
|
|
454
|
-
update();
|
|
455
|
-
resizeObserver.disconnect();
|
|
456
|
-
}
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
// If the popover is already open by the time this effect runs (for
|
|
460
|
-
// example, the parent `useAnchorPosition` effect runs after the child
|
|
461
|
-
// `Popover` effect that called `showPopover()`), the initial `toggle`
|
|
462
|
-
// event has already fired and our listener below would miss it. Start
|
|
463
|
-
// observing immediately so the first measurement still happens.
|
|
464
|
-
if (isPopoverOpen(popover)) {
|
|
465
|
-
hideUntilPositioned();
|
|
466
|
-
resizeObserver.observe(popover);
|
|
467
|
-
}
|
|
468
|
-
var undoPositioning = (0, _combine.combine)(cleanupBaseStyles,
|
|
469
|
-
// Each open needs a fresh measurement, so hide and re-observe.
|
|
470
|
-
(0, _bindEventListener.bind)(popover, {
|
|
471
|
-
type: 'toggle',
|
|
472
|
-
listener: function listener(event) {
|
|
473
|
-
var toggleEvent = event;
|
|
474
|
-
if (toggleEvent.newState === 'open') {
|
|
475
|
-
hideUntilPositioned();
|
|
476
|
-
resizeObserver.observe(popover);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
}), function () {
|
|
480
|
-
return resizeObserver.disconnect();
|
|
481
|
-
}, (0, _bindEventListener.bind)(window, {
|
|
482
|
-
type: 'scroll',
|
|
483
|
-
listener: scheduledUpdate,
|
|
484
|
-
options: {
|
|
485
|
-
capture: true,
|
|
486
|
-
passive: true
|
|
487
|
-
}
|
|
488
|
-
}), (0, _bindEventListener.bind)(window, {
|
|
489
|
-
type: 'resize',
|
|
490
|
-
listener: scheduledUpdate,
|
|
491
|
-
options: {
|
|
492
|
-
passive: true
|
|
493
|
-
}
|
|
494
|
-
}), function () {
|
|
495
|
-
scheduledUpdate.cancel();
|
|
496
|
-
restorePosition();
|
|
497
|
-
reveal();
|
|
498
|
-
});
|
|
499
|
-
return undoPositioning;
|
|
500
|
-
}, [anchorRef, popoverRef, stablePlacement, forceFallbackPositioning, isEnabled, id, isOpen]);
|
|
501
|
-
}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
-
Object.defineProperty(exports, "__esModule", {
|
|
5
|
-
value: true
|
|
6
|
-
});
|
|
7
|
-
exports.useWidthFromAnchor = useWidthFromAnchor;
|
|
8
|
-
var _react = require("react");
|
|
9
|
-
var _once = _interopRequireDefault(require("@atlaskit/ds-lib/once"));
|
|
10
|
-
var _setStyle = require("./set-style");
|
|
11
|
-
/**
|
|
12
|
-
* Probes anchor SIZING, separately from `anchor-name` (see
|
|
13
|
-
* `supportsAnchorPositioning`): some browsers have positioning but not sizing.
|
|
14
|
-
* `once()` for SSR safety.
|
|
15
|
-
*/
|
|
16
|
-
var supportsAnchorSize = (0, _once.default)(function () {
|
|
17
|
-
if (typeof window === 'undefined' || typeof CSS === 'undefined' || typeof CSS.supports !== 'function') {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
return CSS.supports('min-inline-size', 'anchor-size(self-inline)');
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* The JS fallback's stand-in for `anchor-size(self-inline)`. `offsetWidth` / `offsetHeight` are
|
|
25
|
-
* physical, so the axis is picked from the popover's `writing-mode`. Anything not horizontal is
|
|
26
|
-
* treated as vertical, and an unknown or empty value falls back to `offsetWidth`.
|
|
27
|
-
*/
|
|
28
|
-
function getFallbackAnchorInlineSize(_ref) {
|
|
29
|
-
var anchor = _ref.anchor,
|
|
30
|
-
popover = _ref.popover;
|
|
31
|
-
// `String()` because not every test environment implements `writing-mode`.
|
|
32
|
-
var writingMode = String(getComputedStyle(popover).writingMode);
|
|
33
|
-
var isVertical = writingMode.startsWith('vertical') || writingMode.startsWith('sideways');
|
|
34
|
-
return isVertical ? anchor.offsetHeight : anchor.offsetWidth;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Sets the width of a popover element relative to its anchor element.
|
|
39
|
-
*
|
|
40
|
-
* - `'match-anchor'` → `inline-size: anchor-size(self-inline)`, exact
|
|
41
|
-
* - `'min-anchor'` → `min-inline-size: anchor-size(self-inline)`, floor only
|
|
42
|
-
* - `'none'` → `min-inline-size: max-content`, content floor (default)
|
|
43
|
-
*
|
|
44
|
-
* `self-inline` is the inline axis of the element USING the function (the popover), never the
|
|
45
|
-
* anchor, so it matches the axis `inline-size` constrains. See
|
|
46
|
-
* `notes/decisions/width-from-anchor-floors.md`.
|
|
47
|
-
*/
|
|
48
|
-
function useWidthFromAnchor(_ref2) {
|
|
49
|
-
var mode = _ref2.mode,
|
|
50
|
-
popoverRef = _ref2.popoverRef,
|
|
51
|
-
anchorRef = _ref2.anchorRef,
|
|
52
|
-
isOpen = _ref2.isOpen;
|
|
53
|
-
(0, _react.useLayoutEffect)(function () {
|
|
54
|
-
var node = popoverRef.current;
|
|
55
|
-
if (!node) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
if (mode === 'match-anchor') {
|
|
59
|
-
// No floor here: it would let the popover grow past the anchor.
|
|
60
|
-
if (supportsAnchorSize()) {
|
|
61
|
-
return (0, _setStyle.setStyle)({
|
|
62
|
-
element: node,
|
|
63
|
-
styles: [{
|
|
64
|
-
property: 'inline-size',
|
|
65
|
-
value: 'anchor-size(self-inline)'
|
|
66
|
-
}]
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
var anchor = anchorRef.current;
|
|
70
|
-
if (anchor) {
|
|
71
|
-
return (0, _setStyle.setStyle)({
|
|
72
|
-
element: node,
|
|
73
|
-
styles: [{
|
|
74
|
-
property: 'inline-size',
|
|
75
|
-
value: "".concat(getFallbackAnchorInlineSize({
|
|
76
|
-
anchor: anchor,
|
|
77
|
-
popover: node
|
|
78
|
-
}), "px")
|
|
79
|
-
}]
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
if (mode === 'min-anchor') {
|
|
85
|
-
// One floor only. The content floor from mode 'none' deliberately does not also apply
|
|
86
|
-
// here, and cannot: it would need this same property. See the decision note.
|
|
87
|
-
if (supportsAnchorSize()) {
|
|
88
|
-
return (0, _setStyle.setStyle)({
|
|
89
|
-
element: node,
|
|
90
|
-
styles: [{
|
|
91
|
-
property: 'min-inline-size',
|
|
92
|
-
value: 'anchor-size(self-inline)'
|
|
93
|
-
}]
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
var _anchor = anchorRef.current;
|
|
97
|
-
if (_anchor) {
|
|
98
|
-
return (0, _setStyle.setStyle)({
|
|
99
|
-
element: node,
|
|
100
|
-
styles: [{
|
|
101
|
-
property: 'min-inline-size',
|
|
102
|
-
value: "".concat(getFallbackAnchorInlineSize({
|
|
103
|
-
anchor: _anchor,
|
|
104
|
-
popover: node
|
|
105
|
-
}), "px")
|
|
106
|
-
}]
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Nothing to measure, so no floor.
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Makes a too-narrow span overflow and drive `position-try-fallbacks` instead of wrapping.
|
|
115
|
-
// `@atlaskit/popper` resets this exact property to `0` for its fit-to-viewport mode.
|
|
116
|
-
return (0, _setStyle.setStyle)({
|
|
117
|
-
element: node,
|
|
118
|
-
styles: [{
|
|
119
|
-
property: 'min-inline-size',
|
|
120
|
-
value: 'max-content'
|
|
121
|
-
}]
|
|
122
|
-
});
|
|
123
|
-
}, [mode, popoverRef, anchorRef, isOpen]);
|
|
124
|
-
}
|