@atlaskit/popper 8.0.0 → 8.1.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 +21 -0
- package/dist/cjs/index.js +4 -3
- package/dist/cjs/internal/anchor-context.js +17 -0
- package/dist/cjs/internal/anchor-setter-context.js +17 -0
- package/dist/cjs/internal/read-viewport.js +31 -0
- package/dist/cjs/internal/rect-point-for-placement.js +93 -0
- package/dist/cjs/internal/set-style.js +43 -0
- package/dist/cjs/internal/use-anchor-state.js +23 -0
- package/dist/cjs/internal/use-fit-viewport-max-size.js +155 -0
- package/dist/cjs/internal/use-manager-anchor-setter.js +16 -0
- package/dist/cjs/internal/use-manager-anchor.js +16 -0
- package/dist/cjs/internal/use-reference-visibility.js +164 -0
- package/dist/cjs/manager.js +37 -0
- package/dist/cjs/popper-top-layer.js +286 -0
- package/dist/cjs/popper.js +48 -12
- package/dist/cjs/reference.js +44 -0
- package/dist/es2019/index.js +6 -1
- package/dist/es2019/internal/anchor-context.js +12 -0
- package/dist/es2019/internal/anchor-setter-context.js +9 -0
- package/dist/es2019/internal/read-viewport.js +25 -0
- package/dist/es2019/internal/rect-point-for-placement.js +91 -0
- package/dist/es2019/internal/set-style.js +39 -0
- package/dist/es2019/internal/use-anchor-state.js +12 -0
- package/dist/es2019/internal/use-fit-viewport-max-size.js +151 -0
- package/dist/es2019/internal/use-manager-anchor-setter.js +11 -0
- package/dist/es2019/internal/use-manager-anchor.js +11 -0
- package/dist/es2019/internal/use-reference-visibility.js +146 -0
- package/dist/es2019/manager.js +33 -0
- package/dist/es2019/popper-top-layer.js +267 -0
- package/dist/es2019/popper.js +37 -0
- package/dist/es2019/reference.js +35 -0
- package/dist/esm/index.js +6 -1
- package/dist/esm/internal/anchor-context.js +12 -0
- package/dist/esm/internal/anchor-setter-context.js +11 -0
- package/dist/esm/internal/read-viewport.js +25 -0
- package/dist/esm/internal/rect-point-for-placement.js +87 -0
- package/dist/esm/internal/set-style.js +37 -0
- package/dist/esm/internal/use-anchor-state.js +16 -0
- package/dist/esm/internal/use-fit-viewport-max-size.js +149 -0
- package/dist/esm/internal/use-manager-anchor-setter.js +11 -0
- package/dist/esm/internal/use-manager-anchor.js +11 -0
- package/dist/esm/internal/use-reference-visibility.js +157 -0
- package/dist/esm/manager.js +31 -0
- package/dist/esm/popper-top-layer.js +277 -0
- package/dist/esm/popper.js +48 -12
- package/dist/esm/reference.js +36 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/internal/anchor-context.d.ts +11 -0
- package/dist/types/internal/anchor-setter-context.d.ts +11 -0
- package/dist/types/internal/read-viewport.d.ts +12 -0
- package/dist/types/internal/rect-point-for-placement.d.ts +19 -0
- package/dist/types/internal/set-style.d.ts +14 -0
- package/dist/types/internal/use-anchor-state.d.ts +10 -0
- package/dist/types/internal/use-fit-viewport-max-size.d.ts +53 -0
- package/dist/types/internal/use-manager-anchor-setter.d.ts +7 -0
- package/dist/types/internal/use-manager-anchor.d.ts +6 -0
- package/dist/types/internal/use-reference-visibility.d.ts +32 -0
- package/dist/types/manager.d.ts +13 -0
- package/dist/types/popper-top-layer.d.ts +20 -0
- package/dist/types/reference.d.ts +25 -0
- package/package.json +18 -7
- package/popper.docs.tsx +1 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/* popper-top-layer.tsx generated by @compiled/babel-plugin v0.39.1 */
|
|
2
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
|
+
import { ax, ix } from "@compiled/react/runtime";
|
|
4
|
+
import React, { useMemo, useRef, useState } from 'react';
|
|
5
|
+
import { getDocument } from '@atlaskit/browser-apis';
|
|
6
|
+
import noop from '@atlaskit/ds-lib/noop';
|
|
7
|
+
import { fromLegacyPlacement } from '@atlaskit/top-layer/placement-map';
|
|
8
|
+
import { Popover } from '@atlaskit/top-layer/popover';
|
|
9
|
+
import { useAnchorPosition } from '@atlaskit/top-layer/use-anchor-position';
|
|
10
|
+
import { useAnchorPositionAtPoint } from '@atlaskit/top-layer/use-anchor-position-at-point';
|
|
11
|
+
import { usePopoverId } from '@atlaskit/top-layer/use-popover-id';
|
|
12
|
+
import { useWidthFromAnchor } from '@atlaskit/top-layer/use-width-from-anchor';
|
|
13
|
+
import { rectPointForPlacement } from './internal/rect-point-for-placement';
|
|
14
|
+
import { useFitViewportMaxSize } from './internal/use-fit-viewport-max-size';
|
|
15
|
+
import { useManagerAnchor } from './internal/use-manager-anchor';
|
|
16
|
+
import { useReferenceVisibility } from './internal/use-reference-visibility';
|
|
17
|
+
/**
|
|
18
|
+
* Inert render-prop values. The browser owns positioning under CSS Anchor
|
|
19
|
+
* Positioning, so `style` / `ref` / `arrowProps` / `update` / `forceUpdate`
|
|
20
|
+
* are no-ops that consumers can safely spread. Module scope keeps identities
|
|
21
|
+
* stable for effect dep arrays.
|
|
22
|
+
*/
|
|
23
|
+
var noopStyle = {};
|
|
24
|
+
var noopSetRef = noop;
|
|
25
|
+
var noopUpdate = function noopUpdate() {
|
|
26
|
+
return Promise.resolve(null);
|
|
27
|
+
};
|
|
28
|
+
var noopForceUpdate = function noopForceUpdate() {
|
|
29
|
+
return {};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* `react-popper` stamps `data-popper-arrow` on the arrow element at runtime
|
|
34
|
+
* but does not declare it on `arrowProps`. Widen the type so consumers that
|
|
35
|
+
* rely on the attribute (CSS selectors, snapshots, tests) keep working.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
var noopArrowProps = {
|
|
39
|
+
ref: noopSetRef,
|
|
40
|
+
style: noopStyle,
|
|
41
|
+
'data-popper-arrow': true
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Returns whether the current page is laid out right-to-left.
|
|
46
|
+
*/
|
|
47
|
+
function isPageRtl() {
|
|
48
|
+
var document = getDocument();
|
|
49
|
+
if (!document) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
return document.dir === 'rtl' || document.body.dir === 'rtl' || document.documentElement.dir === 'rtl';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* `@popperjs/core`'s `Placement` union is a strict subset of
|
|
57
|
+
* `TLegacyPlacement` (the placement-map adds `top-center` /
|
|
58
|
+
* `bottom-center` on top of popper's enum), so every value popper hands
|
|
59
|
+
* us is a valid legacy placement. The cast keeps the runtime path free
|
|
60
|
+
* of an extra module-level lookup that bundlers can occasionally fail
|
|
61
|
+
* to wire up (observed as `Cannot read properties of undefined (reading
|
|
62
|
+
* 'includes')` in component-test bundles).
|
|
63
|
+
*/
|
|
64
|
+
function toLegacyPlacement(placement) {
|
|
65
|
+
return placement;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Returns the primary axis (`top` / `bottom` / `left` / `right`) of a popper
|
|
70
|
+
* placement, used to pick which axis `useFitViewportMaxSize` caps to the
|
|
71
|
+
* anchor edge.
|
|
72
|
+
*/
|
|
73
|
+
function getPlacementAxis(placement) {
|
|
74
|
+
if (placement.startsWith('top')) {
|
|
75
|
+
return 'top';
|
|
76
|
+
}
|
|
77
|
+
if (placement.startsWith('bottom')) {
|
|
78
|
+
return 'bottom';
|
|
79
|
+
}
|
|
80
|
+
if (placement.startsWith('left')) {
|
|
81
|
+
return 'left';
|
|
82
|
+
}
|
|
83
|
+
if (placement.startsWith('right')) {
|
|
84
|
+
return 'right';
|
|
85
|
+
}
|
|
86
|
+
// `auto*` placements have no fixed axis. Default to `bottom` to match the
|
|
87
|
+
// `auto -> block-end` mapping in `fromLegacyPlacement`.
|
|
88
|
+
return 'bottom';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Normalises popper's `[along, away]` offset (which may include `null` or
|
|
93
|
+
* `undefined` entries) into the `[along, away]` number tuple
|
|
94
|
+
* `fromLegacyPlacement` expects.
|
|
95
|
+
*/
|
|
96
|
+
function popperToTopLayerOffset(offset) {
|
|
97
|
+
if (!offset) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
var _offset = _slicedToArray(offset, 2),
|
|
101
|
+
along = _offset[0],
|
|
102
|
+
away = _offset[1];
|
|
103
|
+
if (along == null && away == null) {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
return [along !== null && along !== void 0 ? along : 0, away !== null && away !== void 0 ? away : 0];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* FF-on implementation of `@atlaskit/popper`'s `<Popper>` primitive.
|
|
111
|
+
*
|
|
112
|
+
* Renders the consumer's render-prop output into a `<Popover>` from
|
|
113
|
+
* `@atlaskit/top-layer`, which lifts the element into the browser top
|
|
114
|
+
* layer and positions it via CSS Anchor Positioning. The render-prop
|
|
115
|
+
* contract (`PopperChildrenProps`) is preserved at the type level;
|
|
116
|
+
* `style` and `arrowProps.style` are inert at runtime because the
|
|
117
|
+
* browser owns positioning.
|
|
118
|
+
*
|
|
119
|
+
* Gated behind the `platform-dst-top-layer` feature flag from
|
|
120
|
+
* `popper.tsx`.
|
|
121
|
+
*/
|
|
122
|
+
export function PopperTopLayer(_ref) {
|
|
123
|
+
var _ref2;
|
|
124
|
+
var children = _ref.children,
|
|
125
|
+
offset = _ref.offset,
|
|
126
|
+
_ref$placement = _ref.placement,
|
|
127
|
+
placement = _ref$placement === void 0 ? 'bottom-start' : _ref$placement,
|
|
128
|
+
referenceElement = _ref.referenceElement,
|
|
129
|
+
_ref$shouldFitViewpor = _ref.shouldFitViewport,
|
|
130
|
+
shouldFitViewport = _ref$shouldFitViewpor === void 0 ? false : _ref$shouldFitViewpor;
|
|
131
|
+
// `modifiers` and `strategy` are accepted for source compatibility but have
|
|
132
|
+
// no runtime effect; CSS Anchor Positioning + top-layer rendering replaces
|
|
133
|
+
// them. See `top-layer/notes/migrations/popper-migration.md`.
|
|
134
|
+
|
|
135
|
+
// Anchor resolution: `referenceElement` prop, then `<Manager>` context.
|
|
136
|
+
var managerAnchor = useManagerAnchor();
|
|
137
|
+
var effectiveReference = (_ref2 = referenceElement !== null && referenceElement !== void 0 ? referenceElement : managerAnchor) !== null && _ref2 !== void 0 ? _ref2 : undefined;
|
|
138
|
+
|
|
139
|
+
// Real DOM nodes go to `useAnchorPosition`; popper `VirtualElement`s are
|
|
140
|
+
// bridged through `useAnchorPositionAtPoint`, which owns its own synthetic
|
|
141
|
+
// anchor.
|
|
142
|
+
var htmlAnchor = effectiveReference instanceof HTMLElement ? effectiveReference : null;
|
|
143
|
+
var virtualReference = effectiveReference != null && !(effectiveReference instanceof HTMLElement) ? effectiveReference : null;
|
|
144
|
+
var htmlAnchorRef = useRef(htmlAnchor);
|
|
145
|
+
htmlAnchorRef.current = htmlAnchor;
|
|
146
|
+
var popoverRef = useRef(null);
|
|
147
|
+
var popoverId = usePopoverId();
|
|
148
|
+
|
|
149
|
+
// Track the resolved DOM anchor in state so visibility / max-size hooks
|
|
150
|
+
// re-run when its identity changes. Virtual anchors do not feed these
|
|
151
|
+
// hooks because their probe is outside the consumer's DOM.
|
|
152
|
+
//
|
|
153
|
+
// Adjust state during render by comparing against the state itself: the
|
|
154
|
+
// conditional guard means `setResolvedAnchor` is skipped once they match,
|
|
155
|
+
// so it converges in one extra render. This is the React-documented pattern
|
|
156
|
+
// and is side-effect-free — no ref mutation during render.
|
|
157
|
+
var _useState = useState(htmlAnchor),
|
|
158
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
159
|
+
resolvedAnchor = _useState2[0],
|
|
160
|
+
setResolvedAnchor = _useState2[1];
|
|
161
|
+
if (resolvedAnchor !== htmlAnchor) {
|
|
162
|
+
setResolvedAnchor(htmlAnchor);
|
|
163
|
+
}
|
|
164
|
+
var topLayerPlacement = useMemo(function () {
|
|
165
|
+
return fromLegacyPlacement({
|
|
166
|
+
legacy: toLegacyPlacement(placement),
|
|
167
|
+
offset: popperToTopLayerOffset(offset)
|
|
168
|
+
});
|
|
169
|
+
}, [placement, offset]);
|
|
170
|
+
var isOpen = effectiveReference != null;
|
|
171
|
+
|
|
172
|
+
// HTML-element path. No-op when the reference is virtual or absent.
|
|
173
|
+
useAnchorPosition({
|
|
174
|
+
anchorRef: htmlAnchorRef,
|
|
175
|
+
popoverRef: popoverRef,
|
|
176
|
+
placement: topLayerPlacement,
|
|
177
|
+
isEnabled: htmlAnchor != null,
|
|
178
|
+
isOpen: isOpen
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// Virtual-element path. `useAnchorPositionAtPoint` owns a synthetic
|
|
182
|
+
// anchor in `document.body` and latches `getPoint` once per
|
|
183
|
+
// `isEnabled` activation. Reading the latest `virtualReference` and
|
|
184
|
+
// `topLayerPlacement` via refs ensures the latched closure always
|
|
185
|
+
// sees the current values rather than the ones captured at first
|
|
186
|
+
// activation, which would otherwise go stale if either prop changes
|
|
187
|
+
// while the popper stays open.
|
|
188
|
+
var virtualReferenceRef = useRef(virtualReference);
|
|
189
|
+
virtualReferenceRef.current = virtualReference;
|
|
190
|
+
var topLayerPlacementRef = useRef(topLayerPlacement);
|
|
191
|
+
topLayerPlacementRef.current = topLayerPlacement;
|
|
192
|
+
var isVirtualEnabled = virtualReference != null;
|
|
193
|
+
useAnchorPositionAtPoint({
|
|
194
|
+
popoverRef: popoverRef,
|
|
195
|
+
placement: topLayerPlacement,
|
|
196
|
+
isEnabled: isVirtualEnabled,
|
|
197
|
+
isOpen: isOpen,
|
|
198
|
+
getPoint: function getPoint() {
|
|
199
|
+
var current = virtualReferenceRef.current;
|
|
200
|
+
if (!current) {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
return rectPointForPlacement({
|
|
204
|
+
rect: current.getBoundingClientRect(),
|
|
205
|
+
placement: topLayerPlacementRef.current,
|
|
206
|
+
isRtl: isPageRtl()
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
var _useReferenceVisibili = useReferenceVisibility({
|
|
211
|
+
anchor: resolvedAnchor,
|
|
212
|
+
popoverRef: popoverRef
|
|
213
|
+
}),
|
|
214
|
+
isReferenceHidden = _useReferenceVisibili.isReferenceHidden,
|
|
215
|
+
hasPopperEscaped = _useReferenceVisibili.hasPopperEscaped;
|
|
216
|
+
|
|
217
|
+
// Restore legacy `react-popper`'s natural-width behaviour. Under CSS
|
|
218
|
+
// Anchor Positioning the `position-area` grid cell becomes the popover
|
|
219
|
+
// host's containing block, so an auto-width host shrinks to that cell.
|
|
220
|
+
// When the anchor sits near a viewport edge the cell is narrow, so the
|
|
221
|
+
// content wraps far more than it did under `react-popper` (which kept the
|
|
222
|
+
// content's natural width and shifted/flipped to stay on screen).
|
|
223
|
+
// `min-inline-size: max-content` (mode `'none'`) floors the host at its
|
|
224
|
+
// content's intrinsic width, so a too-narrow span overflows the viewport
|
|
225
|
+
// (driving `position-try-fallbacks`) instead of wrapping. This is safe
|
|
226
|
+
// alongside `shouldFitViewport`: the fit caps clamp the host on both axes,
|
|
227
|
+
// so the host never exceeds the viewport / anchor-edge cap.
|
|
228
|
+
useWidthFromAnchor({
|
|
229
|
+
mode: 'none',
|
|
230
|
+
popoverRef: popoverRef,
|
|
231
|
+
anchorRef: htmlAnchorRef,
|
|
232
|
+
isOpen: isOpen
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// `shouldFitViewport` caps are applied directly to the `position-area`
|
|
236
|
+
// host, whose containing block is the cell between the anchor edge and the
|
|
237
|
+
// viewport edge — so a pure-CSS `calc(100% - 5px - gap)` reproduces the
|
|
238
|
+
// legacy per-placement anchor-edge cap with no measurement. The gap mirrors
|
|
239
|
+
// `getPlacement`: an omitted offset resolves to `space.100`, otherwise the
|
|
240
|
+
// consumer's `away` value.
|
|
241
|
+
var resolvedOffset = popperToTopLayerOffset(offset);
|
|
242
|
+
var fitGap = resolvedOffset ? "".concat(resolvedOffset[1], "px") : "var(--ds-space-100, 8px)";
|
|
243
|
+
var placementAxis = getPlacementAxis(placement);
|
|
244
|
+
useFitViewportMaxSize({
|
|
245
|
+
target: popoverRef,
|
|
246
|
+
placementAxis: placementAxis,
|
|
247
|
+
gap: fitGap,
|
|
248
|
+
isEnabled: shouldFitViewport,
|
|
249
|
+
isOpen: isOpen
|
|
250
|
+
});
|
|
251
|
+
var renderChildren = children;
|
|
252
|
+
if (typeof renderChildren !== 'function') {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
var renderPropArg = {
|
|
256
|
+
ref: noopSetRef,
|
|
257
|
+
style: noopStyle,
|
|
258
|
+
placement: placement,
|
|
259
|
+
isReferenceHidden: isReferenceHidden,
|
|
260
|
+
hasPopperEscaped: hasPopperEscaped,
|
|
261
|
+
update: noopUpdate,
|
|
262
|
+
forceUpdate: noopForceUpdate,
|
|
263
|
+
arrowProps: noopArrowProps
|
|
264
|
+
};
|
|
265
|
+
var content = renderChildren(renderPropArg);
|
|
266
|
+
|
|
267
|
+
// The `shouldFitViewport` size caps live on the `<Popover>` host itself
|
|
268
|
+
// (applied by `useFitViewportMaxSize` above), so the consumer's content is
|
|
269
|
+
// rendered directly with no intermediate wrapper.
|
|
270
|
+
return /*#__PURE__*/React.createElement(Popover, {
|
|
271
|
+
ref: popoverRef,
|
|
272
|
+
id: popoverId,
|
|
273
|
+
isOpen: isOpen,
|
|
274
|
+
mode: "manual",
|
|
275
|
+
animate: false
|
|
276
|
+
}, content);
|
|
277
|
+
}
|
package/dist/esm/popper.js
CHANGED
|
@@ -2,7 +2,9 @@ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
|
2
2
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
3
|
import React, { useMemo } from 'react';
|
|
4
4
|
import { Popper as ReactPopper } from 'react-popper';
|
|
5
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
5
6
|
import { getMaxSizeModifiers } from './max-size';
|
|
7
|
+
import { PopperTopLayer } from './popper-top-layer';
|
|
6
8
|
export { placements } from '@popperjs/core';
|
|
7
9
|
// Export types from PopperJS / React Popper
|
|
8
10
|
|
|
@@ -21,19 +23,53 @@ function defaultChildrenFn() {
|
|
|
21
23
|
}
|
|
22
24
|
var defaultOffset = [0, 8];
|
|
23
25
|
export function Popper(_ref) {
|
|
24
|
-
var
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
_ref$placement = _ref.placement,
|
|
29
|
-
placement = _ref$placement === void 0 ? 'bottom-start' : _ref$placement,
|
|
30
|
-
_ref$referenceElement = _ref.referenceElement,
|
|
31
|
-
referenceElement = _ref$referenceElement === void 0 ? undefined : _ref$referenceElement,
|
|
26
|
+
var children = _ref.children,
|
|
27
|
+
offset = _ref.offset,
|
|
28
|
+
placement = _ref.placement,
|
|
29
|
+
referenceElement = _ref.referenceElement,
|
|
32
30
|
modifiers = _ref.modifiers,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
strategy = _ref.strategy,
|
|
32
|
+
shouldFitViewport = _ref.shouldFitViewport;
|
|
33
|
+
// The FF check sits at the very top of the public Popper so the
|
|
34
|
+
// rest of the function (which has its own hooks) does not violate
|
|
35
|
+
// the rules of hooks. Each branch is its own component with its
|
|
36
|
+
// own complete hook order. Props are forwarded explicitly to
|
|
37
|
+
// satisfy `no-unsafe-spread-props`.
|
|
38
|
+
if (fg('platform-dst-top-layer')) {
|
|
39
|
+
return /*#__PURE__*/React.createElement(PopperTopLayer, {
|
|
40
|
+
children: children,
|
|
41
|
+
offset: offset,
|
|
42
|
+
placement: placement,
|
|
43
|
+
referenceElement: referenceElement,
|
|
44
|
+
modifiers: modifiers,
|
|
45
|
+
strategy: strategy,
|
|
46
|
+
shouldFitViewport: shouldFitViewport
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return /*#__PURE__*/React.createElement(LegacyPopper, {
|
|
50
|
+
children: children,
|
|
51
|
+
offset: offset,
|
|
52
|
+
placement: placement,
|
|
53
|
+
referenceElement: referenceElement,
|
|
54
|
+
modifiers: modifiers,
|
|
55
|
+
strategy: strategy,
|
|
56
|
+
shouldFitViewport: shouldFitViewport
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function LegacyPopper(_ref2) {
|
|
60
|
+
var _ref2$children = _ref2.children,
|
|
61
|
+
children = _ref2$children === void 0 ? defaultChildrenFn : _ref2$children,
|
|
62
|
+
_ref2$offset = _ref2.offset,
|
|
63
|
+
offset = _ref2$offset === void 0 ? defaultOffset : _ref2$offset,
|
|
64
|
+
_ref2$placement = _ref2.placement,
|
|
65
|
+
placement = _ref2$placement === void 0 ? 'bottom-start' : _ref2$placement,
|
|
66
|
+
_ref2$referenceElemen = _ref2.referenceElement,
|
|
67
|
+
referenceElement = _ref2$referenceElemen === void 0 ? undefined : _ref2$referenceElemen,
|
|
68
|
+
modifiers = _ref2.modifiers,
|
|
69
|
+
_ref2$strategy = _ref2.strategy,
|
|
70
|
+
strategy = _ref2$strategy === void 0 ? 'fixed' : _ref2$strategy,
|
|
71
|
+
_ref2$shouldFitViewpo = _ref2.shouldFitViewport,
|
|
72
|
+
shouldFitViewport = _ref2$shouldFitViewpo === void 0 ? false : _ref2$shouldFitViewpo;
|
|
37
73
|
var _offset = _slicedToArray(offset, 2),
|
|
38
74
|
offsetX = _offset[0],
|
|
39
75
|
offsetY = _offset[1];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Reference as ReactPopperReference } from 'react-popper';
|
|
3
|
+
import mergeRefs from '@atlaskit/ds-lib/merge-refs';
|
|
4
|
+
import { useManagerAnchorSetter } from './internal/use-manager-anchor-setter';
|
|
5
|
+
|
|
6
|
+
// `react-popper`'s `Reference` exposes a loosely-typed callback ref so
|
|
7
|
+
// consumers can attach it to any host element. We mirror that shape
|
|
8
|
+
// instead of locking the children ref to `HTMLElement`, which would
|
|
9
|
+
// break legacy consumers that pass it to `<button>` / `<div>` directly.
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- mirroring react-popper's public ref shape
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Wraps `react-popper`'s `<Reference>` so the anchor element it captures
|
|
14
|
+
* is also published through `@atlaskit/popper`'s own bridge context.
|
|
15
|
+
* The bridge lets the FF-on top-layer adapter discover the anchor even
|
|
16
|
+
* when `react-popper`'s CJS and ESM builds resolve to different context
|
|
17
|
+
* instances (Jest vs production bundlers).
|
|
18
|
+
*
|
|
19
|
+
* The bridge + consumer refs are composed into a single stable callback and
|
|
20
|
+
* passed to `react-popper` as `innerRef`, so the (stable) ref `react-popper`
|
|
21
|
+
* hands to `children` never changes identity. Composing inline instead would
|
|
22
|
+
* produce a new ref callback every render, making React detach/reattach the
|
|
23
|
+
* anchor each commit — firing `publishAnchor(null)` then `publishAnchor(el)`
|
|
24
|
+
* and churning the `Manager`.
|
|
25
|
+
*/
|
|
26
|
+
export function Reference(_ref) {
|
|
27
|
+
var children = _ref.children,
|
|
28
|
+
innerRef = _ref.innerRef;
|
|
29
|
+
var publishAnchor = useManagerAnchorSetter();
|
|
30
|
+
var composedRef = useMemo(function () {
|
|
31
|
+
return mergeRefs([publishAnchor, innerRef]);
|
|
32
|
+
}, [publishAnchor, innerRef]);
|
|
33
|
+
return /*#__PURE__*/React.createElement(ReactPopperReference, {
|
|
34
|
+
innerRef: composedRef
|
|
35
|
+
}, children);
|
|
36
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { Popper, placements } from './popper';
|
|
2
2
|
export type { ManagerProps, ReferenceProps, PopperProps, PopperArrowProps, PopperChildrenProps, StrictModifier, Modifier, Placement, CustomPopperProps, } from './popper';
|
|
3
|
-
export { Manager
|
|
3
|
+
export { Manager } from './manager';
|
|
4
|
+
export { Reference } from './reference';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Module-private context used to bridge the anchor element from our
|
|
4
|
+
* `<Reference>` wrapper to `<Popper>`. Deliberately separate from
|
|
5
|
+
* `react-popper`'s own `ManagerReferenceNodeContext`: `react-popper`
|
|
6
|
+
* ships dual CJS and ESM builds, each with its own
|
|
7
|
+
* `React.createContext()` instance, and bundlers and Jest can resolve
|
|
8
|
+
* different builds. Bridging through a context we control guarantees a
|
|
9
|
+
* single shared instance across every consumer of `@atlaskit/popper`.
|
|
10
|
+
*/
|
|
11
|
+
export declare const AnchorContext: React.Context<HTMLElement | null>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
type TSetAnchor = (element: HTMLElement | null) => void;
|
|
3
|
+
/**
|
|
4
|
+
* Module-private context that exposes the anchor setter to descendant
|
|
5
|
+
* `<Reference>` instances inside the same `<Manager>` subtree. The
|
|
6
|
+
* setter forwards the captured element into `AnchorContext` so
|
|
7
|
+
* descendant `<Popper>` instances can discover the anchor without
|
|
8
|
+
* reaching into `react-popper`'s internal context.
|
|
9
|
+
*/
|
|
10
|
+
export declare const AnchorSetterContext: React.Context<TSetAnchor>;
|
|
11
|
+
export type { TSetAnchor };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type TViewport = {
|
|
2
|
+
width: number;
|
|
3
|
+
height: number;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Returns the current viewport size in CSS pixels, preferring the visual
|
|
7
|
+
* viewport (which accounts for pinch-zoom on touch devices) over the
|
|
8
|
+
* layout viewport. Returns `{ width: 0, height: 0 }` in non-DOM
|
|
9
|
+
* environments so callers can use the result unconditionally.
|
|
10
|
+
*/
|
|
11
|
+
export declare function readViewport(): TViewport;
|
|
12
|
+
export type { TViewport };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TPlacementOptions } from '@atlaskit/top-layer/placement-map';
|
|
2
|
+
import type { TAnchorPoint } from '@atlaskit/top-layer/use-anchor-position-at-point';
|
|
3
|
+
/**
|
|
4
|
+
* Reduces an anchor rect to the single viewport point that, wrapped in a
|
|
5
|
+
* zero-size synthetic anchor, produces the same popover position
|
|
6
|
+
* `useAnchorPosition` would for the given placement. This works because
|
|
7
|
+
* `useAnchorPosition` only reads the edge / alignment corner of the rect,
|
|
8
|
+
* so a coincident zero-size point is geometrically equivalent.
|
|
9
|
+
*
|
|
10
|
+
* RTL is resolved here so the downstream synthetic anchor only sees physical
|
|
11
|
+
* coordinates. Defaults mirror `getPlacement` in
|
|
12
|
+
* `@atlaskit/top-layer/placement-map` (`axis: 'block'`, `edge: 'end'`,
|
|
13
|
+
* `align: 'center'`).
|
|
14
|
+
*/
|
|
15
|
+
export declare function rectPointForPlacement({ rect, placement, isRtl, }: {
|
|
16
|
+
rect: DOMRect;
|
|
17
|
+
placement: TPlacementOptions;
|
|
18
|
+
isRtl: boolean;
|
|
19
|
+
}): TAnchorPoint;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sets inline styles on an element and returns a cleanup function that
|
|
3
|
+
* restores the prior inline values (so we do not stomp consumer styles).
|
|
4
|
+
*
|
|
5
|
+
* Copied from `@atlaskit/top-layer`'s internal `setStyle` (not exported there
|
|
6
|
+
* yet); inline here until top-layer exposes it via a subpath export.
|
|
7
|
+
*/
|
|
8
|
+
export declare function setStyle({ element, styles, }: {
|
|
9
|
+
element: HTMLElement;
|
|
10
|
+
styles: Array<{
|
|
11
|
+
property: string;
|
|
12
|
+
value: string;
|
|
13
|
+
}>;
|
|
14
|
+
}): () => void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type TAnchorState = {
|
|
2
|
+
anchor: HTMLElement | null;
|
|
3
|
+
setAnchor: (element: HTMLElement | null) => void;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Returns the local state used by `<Manager>` to publish the anchor
|
|
7
|
+
* captured by `<Reference>` to descendant `<Popper>` instances.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useAnchorState(): TAnchorState;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Applies the `shouldFitViewport` size caps directly to the
|
|
4
|
+
* `position-area`-anchored popover host. Pure CSS — the browser owns every
|
|
5
|
+
* value, so there is no measurement, no scroll/resize listeners, and no
|
|
6
|
+
* `--ds-popper-anchor-*` custom properties.
|
|
7
|
+
*
|
|
8
|
+
* **Primary (placement) axis** is capped to `calc(100% - 5px - gap)`. Because
|
|
9
|
+
* the host carries `position-area`, its containing block *is* the position-area
|
|
10
|
+
* cell — the region between the anchor edge and the viewport edge — so `100%`
|
|
11
|
+
* resolves to that distance. The popover is pushed `gap` into the cell by its
|
|
12
|
+
* offset margin (`margin-*`, set by `useAnchorPosition`), so the gap is
|
|
13
|
+
* subtracted as well to keep the legacy `viewportPadding = 5` on the far edge.
|
|
14
|
+
* The cap is also more correct than measuring the requested placement: the cell
|
|
15
|
+
* follows whichever side `position-try-fallbacks` actually flips to, so it
|
|
16
|
+
* tracks the flip automatically.
|
|
17
|
+
*
|
|
18
|
+
* **Cross axis** is capped to `calc(100dvw|dvh - 10px)` (viewport, legacy
|
|
19
|
+
* `2 * viewportPadding`). `display: flex` (plus a `min-*-size: 0` reset on the
|
|
20
|
+
* child) lets an oversized child shrink and reflow to the cap. The host stays
|
|
21
|
+
* `overflow: visible` so it never clips the consumer surface's `box-shadow`;
|
|
22
|
+
* scrolling content that cannot reflow is the consumer surface's own
|
|
23
|
+
* responsibility (it owns `overflow`), matching legacy `react-popper`, which
|
|
24
|
+
* applied the cap to the consumer's own element.
|
|
25
|
+
*
|
|
26
|
+
* `min-inline-size` is reset to `0`. `useWidthFromAnchor({ mode: 'none' })`
|
|
27
|
+
* floors the host at `max-content` so a too-narrow span overflows and drives
|
|
28
|
+
* `position-try-fallbacks` rather than wrapping. That floor is the opposite of
|
|
29
|
+
* fitting: when it exceeds a cap, CSS min/max resolution lets the min win and
|
|
30
|
+
* the host overflows the viewport. In fit mode the caps must win, so the floor
|
|
31
|
+
* is neutralised here; `setStyle` restores the prior inline value on cleanup.
|
|
32
|
+
*
|
|
33
|
+
* Verified in Chromium: `max-block-size: calc(100% - …)` on a `position: fixed`
|
|
34
|
+
* + `position-area` element resolves `100%` to the cell, not the viewport.
|
|
35
|
+
*/
|
|
36
|
+
type TPlacementAxis = 'top' | 'bottom' | 'left' | 'right';
|
|
37
|
+
/**
|
|
38
|
+
* @param target the `position-area`-anchored popover host
|
|
39
|
+
* @param placementAxis the primary axis derived from the popper placement
|
|
40
|
+
* @param gap the offset distance the popover is pushed from the
|
|
41
|
+
* anchor (CSS length), subtracted from the primary cap
|
|
42
|
+
* @param isEnabled mirrors the consumer's `shouldFitViewport` prop
|
|
43
|
+
* @param isOpen re-applies the caps after the host unmounts/remounts
|
|
44
|
+
* across open cycles (the host is torn down on exit)
|
|
45
|
+
*/
|
|
46
|
+
export declare function useFitViewportMaxSize({ target, placementAxis, gap, isEnabled, isOpen, }: {
|
|
47
|
+
target: RefObject<HTMLElement | null>;
|
|
48
|
+
placementAxis: TPlacementAxis;
|
|
49
|
+
gap: string;
|
|
50
|
+
isEnabled: boolean;
|
|
51
|
+
isOpen: boolean;
|
|
52
|
+
}): void;
|
|
53
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type TSetAnchor } from './anchor-setter-context';
|
|
2
|
+
/**
|
|
3
|
+
* Returns the setter that an ancestor `<Manager>` exposes to publish
|
|
4
|
+
* the anchor element from `<Reference>`. Returns a no-op when there is
|
|
5
|
+
* no surrounding `<Manager>`.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useManagerAnchorSetter(): TSetAnchor;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the current anchor element published by an ancestor
|
|
3
|
+
* `<Reference>` via the shared `<Manager>` provider. Returns `null`
|
|
4
|
+
* when there is no surrounding `<Manager>` / `<Reference>` pair.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useManagerAnchor(): HTMLElement | null;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
type TUseReferenceVisibilityArgs = {
|
|
3
|
+
anchor: HTMLElement | null;
|
|
4
|
+
popoverRef: RefObject<HTMLElement | null>;
|
|
5
|
+
};
|
|
6
|
+
type TVisibility = {
|
|
7
|
+
isReferenceHidden: boolean;
|
|
8
|
+
hasPopperEscaped: boolean;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Exists **only** to preserve API parity with the legacy popper.js
|
|
12
|
+
* implementation. The top-layer popper does not natively expose
|
|
13
|
+
* popper.js's `isReferenceHidden` / `hasPopperEscaped` render-prop
|
|
14
|
+
* modifiers, but existing consumers still branch on those values, so
|
|
15
|
+
* this hook reconstructs them from live DOM measurement.
|
|
16
|
+
*
|
|
17
|
+
* Do not reach for this hook in new code. If you find yourself wanting
|
|
18
|
+
* these signals for a new feature, prefer a first-class top-layer or
|
|
19
|
+
* anchor-positioning primitive instead.
|
|
20
|
+
*
|
|
21
|
+
* - `isReferenceHidden`: the anchor's bounding rect is fully outside the
|
|
22
|
+
* visual viewport OR is clipped to zero area by any scrollable
|
|
23
|
+
* ancestor.
|
|
24
|
+
* - `hasPopperEscaped`: the popover surface's rect is fully outside the
|
|
25
|
+
* visual viewport.
|
|
26
|
+
*
|
|
27
|
+
* Measurement runs in a `useLayoutEffect` so the first paint already
|
|
28
|
+
* reflects the correct values, preventing consumers from animating
|
|
29
|
+
* from `opacity: 1` to `opacity: 0` on mount.
|
|
30
|
+
*/
|
|
31
|
+
export declare function useReferenceVisibility({ anchor, popoverRef, }: TUseReferenceVisibilityArgs): TVisibility;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type ManagerProps } from 'react-popper';
|
|
3
|
+
type TManagerProps = ManagerProps;
|
|
4
|
+
/**
|
|
5
|
+
* Wraps `react-popper`'s `<Manager>` so the anchor that `<Reference>`
|
|
6
|
+
* captures is published through `@atlaskit/popper`'s own bridge context.
|
|
7
|
+
* Doing so insulates `<Popper>` consumers from `react-popper`'s dual
|
|
8
|
+
* CJS / ESM builds, which otherwise create two unrelated context
|
|
9
|
+
* instances that prevent the FF-on top-layer adapter from discovering
|
|
10
|
+
* the anchor.
|
|
11
|
+
*/
|
|
12
|
+
export declare function Manager({ children }: TManagerProps): React.JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jsxRuntime classic
|
|
3
|
+
* @jsx jsx
|
|
4
|
+
*/
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import type { CustomPopperProps } from './popper';
|
|
7
|
+
/**
|
|
8
|
+
* FF-on implementation of `@atlaskit/popper`'s `<Popper>` primitive.
|
|
9
|
+
*
|
|
10
|
+
* Renders the consumer's render-prop output into a `<Popover>` from
|
|
11
|
+
* `@atlaskit/top-layer`, which lifts the element into the browser top
|
|
12
|
+
* layer and positions it via CSS Anchor Positioning. The render-prop
|
|
13
|
+
* contract (`PopperChildrenProps`) is preserved at the type level;
|
|
14
|
+
* `style` and `arrowProps.style` are inert at runtime because the
|
|
15
|
+
* browser owns positioning.
|
|
16
|
+
*
|
|
17
|
+
* Gated behind the `platform-dst-top-layer` feature flag from
|
|
18
|
+
* `popper.tsx`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function PopperTopLayer<CustomModifiers>({ children, offset, placement, referenceElement, shouldFitViewport, }: CustomPopperProps<CustomModifiers>): React.JSX.Element | null;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React, { type ReactNode, type Ref } from 'react';
|
|
2
|
+
type TReferenceRef = Ref<any>;
|
|
3
|
+
type TChildrenArgs = {
|
|
4
|
+
ref: TReferenceRef;
|
|
5
|
+
};
|
|
6
|
+
type TReferenceProps = {
|
|
7
|
+
children: (args: TChildrenArgs) => ReactNode;
|
|
8
|
+
innerRef?: TReferenceRef;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Wraps `react-popper`'s `<Reference>` so the anchor element it captures
|
|
12
|
+
* is also published through `@atlaskit/popper`'s own bridge context.
|
|
13
|
+
* The bridge lets the FF-on top-layer adapter discover the anchor even
|
|
14
|
+
* when `react-popper`'s CJS and ESM builds resolve to different context
|
|
15
|
+
* instances (Jest vs production bundlers).
|
|
16
|
+
*
|
|
17
|
+
* The bridge + consumer refs are composed into a single stable callback and
|
|
18
|
+
* passed to `react-popper` as `innerRef`, so the (stable) ref `react-popper`
|
|
19
|
+
* hands to `children` never changes identity. Composing inline instead would
|
|
20
|
+
* produce a new ref callback every render, making React detach/reattach the
|
|
21
|
+
* anchor each commit — firing `publishAnchor(null)` then `publishAnchor(el)`
|
|
22
|
+
* and churning the `Manager`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function Reference({ children, innerRef }: TReferenceProps): React.JSX.Element;
|
|
25
|
+
export {};
|