@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.
Files changed (62) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/cjs/index.js +4 -3
  3. package/dist/cjs/internal/anchor-context.js +17 -0
  4. package/dist/cjs/internal/anchor-setter-context.js +17 -0
  5. package/dist/cjs/internal/read-viewport.js +31 -0
  6. package/dist/cjs/internal/rect-point-for-placement.js +93 -0
  7. package/dist/cjs/internal/set-style.js +43 -0
  8. package/dist/cjs/internal/use-anchor-state.js +23 -0
  9. package/dist/cjs/internal/use-fit-viewport-max-size.js +155 -0
  10. package/dist/cjs/internal/use-manager-anchor-setter.js +16 -0
  11. package/dist/cjs/internal/use-manager-anchor.js +16 -0
  12. package/dist/cjs/internal/use-reference-visibility.js +164 -0
  13. package/dist/cjs/manager.js +37 -0
  14. package/dist/cjs/popper-top-layer.js +286 -0
  15. package/dist/cjs/popper.js +48 -12
  16. package/dist/cjs/reference.js +44 -0
  17. package/dist/es2019/index.js +6 -1
  18. package/dist/es2019/internal/anchor-context.js +12 -0
  19. package/dist/es2019/internal/anchor-setter-context.js +9 -0
  20. package/dist/es2019/internal/read-viewport.js +25 -0
  21. package/dist/es2019/internal/rect-point-for-placement.js +91 -0
  22. package/dist/es2019/internal/set-style.js +39 -0
  23. package/dist/es2019/internal/use-anchor-state.js +12 -0
  24. package/dist/es2019/internal/use-fit-viewport-max-size.js +151 -0
  25. package/dist/es2019/internal/use-manager-anchor-setter.js +11 -0
  26. package/dist/es2019/internal/use-manager-anchor.js +11 -0
  27. package/dist/es2019/internal/use-reference-visibility.js +146 -0
  28. package/dist/es2019/manager.js +33 -0
  29. package/dist/es2019/popper-top-layer.js +267 -0
  30. package/dist/es2019/popper.js +37 -0
  31. package/dist/es2019/reference.js +35 -0
  32. package/dist/esm/index.js +6 -1
  33. package/dist/esm/internal/anchor-context.js +12 -0
  34. package/dist/esm/internal/anchor-setter-context.js +11 -0
  35. package/dist/esm/internal/read-viewport.js +25 -0
  36. package/dist/esm/internal/rect-point-for-placement.js +87 -0
  37. package/dist/esm/internal/set-style.js +37 -0
  38. package/dist/esm/internal/use-anchor-state.js +16 -0
  39. package/dist/esm/internal/use-fit-viewport-max-size.js +149 -0
  40. package/dist/esm/internal/use-manager-anchor-setter.js +11 -0
  41. package/dist/esm/internal/use-manager-anchor.js +11 -0
  42. package/dist/esm/internal/use-reference-visibility.js +157 -0
  43. package/dist/esm/manager.js +31 -0
  44. package/dist/esm/popper-top-layer.js +277 -0
  45. package/dist/esm/popper.js +48 -12
  46. package/dist/esm/reference.js +36 -0
  47. package/dist/types/index.d.ts +2 -1
  48. package/dist/types/internal/anchor-context.d.ts +11 -0
  49. package/dist/types/internal/anchor-setter-context.d.ts +11 -0
  50. package/dist/types/internal/read-viewport.d.ts +12 -0
  51. package/dist/types/internal/rect-point-for-placement.d.ts +19 -0
  52. package/dist/types/internal/set-style.d.ts +14 -0
  53. package/dist/types/internal/use-anchor-state.d.ts +10 -0
  54. package/dist/types/internal/use-fit-viewport-max-size.d.ts +53 -0
  55. package/dist/types/internal/use-manager-anchor-setter.d.ts +7 -0
  56. package/dist/types/internal/use-manager-anchor.d.ts +6 -0
  57. package/dist/types/internal/use-reference-visibility.d.ts +32 -0
  58. package/dist/types/manager.d.ts +13 -0
  59. package/dist/types/popper-top-layer.d.ts +20 -0
  60. package/dist/types/reference.d.ts +25 -0
  61. package/package.json +18 -7
  62. 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
+ }
@@ -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 _ref$children = _ref.children,
25
- children = _ref$children === void 0 ? defaultChildrenFn : _ref$children,
26
- _ref$offset = _ref.offset,
27
- offset = _ref$offset === void 0 ? defaultOffset : _ref$offset,
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
- _ref$strategy = _ref.strategy,
34
- strategy = _ref$strategy === void 0 ? 'fixed' : _ref$strategy,
35
- _ref$shouldFitViewpor = _ref.shouldFitViewport,
36
- shouldFitViewport = _ref$shouldFitViewpor === void 0 ? false : _ref$shouldFitViewpor;
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
+ }
@@ -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, Reference } from 'react-popper';
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 {};