@atlaskit/popper 8.0.1 → 8.2.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 +31 -1
  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 +20 -9
  62. package/popper.docs.tsx +1 -0
package/CHANGELOG.md CHANGED
@@ -1,11 +1,41 @@
1
1
  # @atlaskit/popper
2
2
 
3
+ ## 8.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`cd097a2111788`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/cd097a2111788) -
8
+ Republish packages depending on `@atlaskit/react-compiler-gating` so their published dependency
9
+ reference is updated to the renamed `@atlaskit/react-compiler-gating` scope.
10
+
11
+ The earlier rename of `@atlassian/react-compiler-gating` to `@atlaskit/react-compiler-gating` only
12
+ bumped the renamed package itself, so dependent packages were never republished and their
13
+ published versions still referenced the old `@atlassian/react-compiler-gating` name, which is not
14
+ available in the public npm registry. This minor bump republishes all affected packages with the
15
+ corrected dependency.
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies
20
+
21
+ ## 8.1.0
22
+
23
+ ### Minor Changes
24
+
25
+ - [`db3328ec580e4`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/db3328ec580e4) -
26
+ Behind the `"platform-dst-top-layer"` feature flag, `@atlaskit/popper` now renders into the
27
+ browser top layer via `@atlaskit/top-layer`. Public API and exported types are unchanged.
28
+
29
+ ### Patch Changes
30
+
31
+ - Updated dependencies
32
+
3
33
  ## 8.0.1
4
34
 
5
35
  ### Patch Changes
6
36
 
7
37
  - [`ee28cf33718b0`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/ee28cf33718b0) -
8
- Add @atlassian/react-compiler-gating as a runtime dependency to enable React Compiler platform
38
+ Add @atlaskit/react-compiler-gating as a runtime dependency to enable React Compiler platform
9
39
  gating.
10
40
  - Updated dependencies
11
41
 
package/dist/cjs/index.js CHANGED
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  Object.defineProperty(exports, "Manager", {
7
7
  enumerable: true,
8
8
  get: function get() {
9
- return _reactPopper.Manager;
9
+ return _manager.Manager;
10
10
  }
11
11
  });
12
12
  Object.defineProperty(exports, "Popper", {
@@ -18,7 +18,7 @@ Object.defineProperty(exports, "Popper", {
18
18
  Object.defineProperty(exports, "Reference", {
19
19
  enumerable: true,
20
20
  get: function get() {
21
- return _reactPopper.Reference;
21
+ return _reference.Reference;
22
22
  }
23
23
  });
24
24
  Object.defineProperty(exports, "placements", {
@@ -28,4 +28,5 @@ Object.defineProperty(exports, "placements", {
28
28
  }
29
29
  });
30
30
  var _popper = require("./popper");
31
- var _reactPopper = require("react-popper");
31
+ var _manager = require("./manager");
32
+ var _reference = require("./reference");
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.AnchorContext = void 0;
7
+ var _react = require("react");
8
+ /**
9
+ * Module-private context used to bridge the anchor element from our
10
+ * `<Reference>` wrapper to `<Popper>`. Deliberately separate from
11
+ * `react-popper`'s own `ManagerReferenceNodeContext`: `react-popper`
12
+ * ships dual CJS and ESM builds, each with its own
13
+ * `React.createContext()` instance, and bundlers and Jest can resolve
14
+ * different builds. Bridging through a context we control guarantees a
15
+ * single shared instance across every consumer of `@atlaskit/popper`.
16
+ */
17
+ var AnchorContext = exports.AnchorContext = /*#__PURE__*/(0, _react.createContext)(null);
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.AnchorSetterContext = void 0;
7
+ var _react = require("react");
8
+ /**
9
+ * Module-private context that exposes the anchor setter to descendant
10
+ * `<Reference>` instances inside the same `<Manager>` subtree. The
11
+ * setter forwards the captured element into `AnchorContext` so
12
+ * descendant `<Popper>` instances can discover the anchor without
13
+ * reaching into `react-popper`'s internal context.
14
+ */
15
+ var AnchorSetterContext = exports.AnchorSetterContext = /*#__PURE__*/(0, _react.createContext)(function () {
16
+ return undefined;
17
+ });
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.readViewport = readViewport;
7
+ /**
8
+ * Returns the current viewport size in CSS pixels, preferring the visual
9
+ * viewport (which accounts for pinch-zoom on touch devices) over the
10
+ * layout viewport. Returns `{ width: 0, height: 0 }` in non-DOM
11
+ * environments so callers can use the result unconditionally.
12
+ */
13
+ function readViewport() {
14
+ if (typeof window === 'undefined') {
15
+ return {
16
+ width: 0,
17
+ height: 0
18
+ };
19
+ }
20
+ var visual = window.visualViewport;
21
+ if (visual) {
22
+ return {
23
+ width: visual.width,
24
+ height: visual.height
25
+ };
26
+ }
27
+ return {
28
+ width: window.innerWidth,
29
+ height: window.innerHeight
30
+ };
31
+ }
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.rectPointForPlacement = rectPointForPlacement;
7
+ /**
8
+ * Reduces an anchor rect to the single viewport point that, wrapped in a
9
+ * zero-size synthetic anchor, produces the same popover position
10
+ * `useAnchorPosition` would for the given placement. This works because
11
+ * `useAnchorPosition` only reads the edge / alignment corner of the rect,
12
+ * so a coincident zero-size point is geometrically equivalent.
13
+ *
14
+ * RTL is resolved here so the downstream synthetic anchor only sees physical
15
+ * coordinates. Defaults mirror `getPlacement` in
16
+ * `@atlaskit/top-layer/placement-map` (`axis: 'block'`, `edge: 'end'`,
17
+ * `align: 'center'`).
18
+ */
19
+ function rectPointForPlacement(_ref) {
20
+ var _placement$axis, _placement$edge, _placement$align;
21
+ var rect = _ref.rect,
22
+ placement = _ref.placement,
23
+ isRtl = _ref.isRtl;
24
+ var axis = (_placement$axis = placement.axis) !== null && _placement$axis !== void 0 ? _placement$axis : 'block';
25
+ var edge = (_placement$edge = placement.edge) !== null && _placement$edge !== void 0 ? _placement$edge : 'end';
26
+ var align = (_placement$align = placement.align) !== null && _placement$align !== void 0 ? _placement$align : 'center';
27
+ if (axis === 'block') {
28
+ // Popover sits above (`edge: 'start'`) or below (`edge: 'end'`)
29
+ // the anchor. Hug the matching horizontal edge; align along x.
30
+ var _y = edge === 'start' ? rect.top : rect.bottom;
31
+ var _x = horizontalForAlign({
32
+ rect: rect,
33
+ align: align,
34
+ isRtl: isRtl
35
+ });
36
+ return {
37
+ x: _x,
38
+ y: _y
39
+ };
40
+ }
41
+
42
+ // `axis: 'inline'`: popover sits inline-start or inline-end of the
43
+ // anchor. Hug the matching vertical edge; align along y.
44
+ var x = inlineEdgeX({
45
+ rect: rect,
46
+ edge: edge,
47
+ isRtl: isRtl
48
+ });
49
+ var y = verticalForAlign({
50
+ rect: rect,
51
+ align: align
52
+ });
53
+ return {
54
+ x: x,
55
+ y: y
56
+ };
57
+ }
58
+ function horizontalForAlign(_ref2) {
59
+ var rect = _ref2.rect,
60
+ align = _ref2.align,
61
+ isRtl = _ref2.isRtl;
62
+ if (align === 'center') {
63
+ return rect.left + rect.width / 2;
64
+ }
65
+ // `start` / `end` are logical. In LTR, `start` is the left edge.
66
+ // In RTL, `start` is the right edge.
67
+ var isStartLeft = !isRtl;
68
+ if (align === 'start') {
69
+ return isStartLeft ? rect.left : rect.right;
70
+ }
71
+ return isStartLeft ? rect.right : rect.left;
72
+ }
73
+ function verticalForAlign(_ref3) {
74
+ var rect = _ref3.rect,
75
+ align = _ref3.align;
76
+ if (align === 'center') {
77
+ return rect.top + rect.height / 2;
78
+ }
79
+ if (align === 'start') {
80
+ return rect.top;
81
+ }
82
+ return rect.bottom;
83
+ }
84
+ function inlineEdgeX(_ref4) {
85
+ var rect = _ref4.rect,
86
+ edge = _ref4.edge,
87
+ isRtl = _ref4.isRtl;
88
+ var isStartLeft = !isRtl;
89
+ if (edge === 'start') {
90
+ return isStartLeft ? rect.left : rect.right;
91
+ }
92
+ return isStartLeft ? rect.right : rect.left;
93
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.setStyle = setStyle;
7
+ /**
8
+ * Sets inline styles on an element and returns a cleanup function that
9
+ * restores the prior inline values (so we do not stomp consumer styles).
10
+ *
11
+ * Copied from `@atlaskit/top-layer`'s internal `setStyle` (not exported there
12
+ * yet); inline here until top-layer exposes it via a subpath export.
13
+ */
14
+ function setStyle(_ref) {
15
+ var element = _ref.element,
16
+ styles = _ref.styles;
17
+ // Snapshot the prior inline value (NOT the computed style - we only want
18
+ // to restore values that the consumer/our previous run inlined). An empty
19
+ // string means "no inline value", in which case cleanup uses removeProperty.
20
+ var priorValues = styles.map(function (_ref2) {
21
+ var property = _ref2.property;
22
+ return {
23
+ property: property,
24
+ value: element.style.getPropertyValue(property)
25
+ };
26
+ });
27
+ styles.forEach(function (_ref3) {
28
+ var property = _ref3.property,
29
+ value = _ref3.value;
30
+ element.style.setProperty(property, value);
31
+ });
32
+ return function cleanup() {
33
+ priorValues.forEach(function (_ref4) {
34
+ var property = _ref4.property,
35
+ value = _ref4.value;
36
+ if (value === '') {
37
+ element.style.removeProperty(property);
38
+ return;
39
+ }
40
+ element.style.setProperty(property, value);
41
+ });
42
+ };
43
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useAnchorState = useAnchorState;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _react = require("react");
10
+ /**
11
+ * Returns the local state used by `<Manager>` to publish the anchor
12
+ * captured by `<Reference>` to descendant `<Popper>` instances.
13
+ */
14
+ function useAnchorState() {
15
+ var _useState = (0, _react.useState)(null),
16
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
17
+ anchor = _useState2[0],
18
+ setAnchor = _useState2[1];
19
+ return {
20
+ anchor: anchor,
21
+ setAnchor: setAnchor
22
+ };
23
+ }
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useFitViewportMaxSize = useFitViewportMaxSize;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
+ var _react = require("react");
10
+ var _setStyle = require("./set-style");
11
+ /**
12
+ * Applies the `shouldFitViewport` size caps directly to the
13
+ * `position-area`-anchored popover host. Pure CSS — the browser owns every
14
+ * value, so there is no measurement, no scroll/resize listeners, and no
15
+ * `--ds-popper-anchor-*` custom properties.
16
+ *
17
+ * **Primary (placement) axis** is capped to `calc(100% - 5px - gap)`. Because
18
+ * the host carries `position-area`, its containing block *is* the position-area
19
+ * cell — the region between the anchor edge and the viewport edge — so `100%`
20
+ * resolves to that distance. The popover is pushed `gap` into the cell by its
21
+ * offset margin (`margin-*`, set by `useAnchorPosition`), so the gap is
22
+ * subtracted as well to keep the legacy `viewportPadding = 5` on the far edge.
23
+ * The cap is also more correct than measuring the requested placement: the cell
24
+ * follows whichever side `position-try-fallbacks` actually flips to, so it
25
+ * tracks the flip automatically.
26
+ *
27
+ * **Cross axis** is capped to `calc(100dvw|dvh - 10px)` (viewport, legacy
28
+ * `2 * viewportPadding`). `display: flex` (plus a `min-*-size: 0` reset on the
29
+ * child) lets an oversized child shrink and reflow to the cap. The host stays
30
+ * `overflow: visible` so it never clips the consumer surface's `box-shadow`;
31
+ * scrolling content that cannot reflow is the consumer surface's own
32
+ * responsibility (it owns `overflow`), matching legacy `react-popper`, which
33
+ * applied the cap to the consumer's own element.
34
+ *
35
+ * `min-inline-size` is reset to `0`. `useWidthFromAnchor({ mode: 'none' })`
36
+ * floors the host at `max-content` so a too-narrow span overflows and drives
37
+ * `position-try-fallbacks` rather than wrapping. That floor is the opposite of
38
+ * fitting: when it exceeds a cap, CSS min/max resolution lets the min win and
39
+ * the host overflows the viewport. In fit mode the caps must win, so the floor
40
+ * is neutralised here; `setStyle` restores the prior inline value on cleanup.
41
+ *
42
+ * Verified in Chromium: `max-block-size: calc(100% - …)` on a `position: fixed`
43
+ * + `position-area` element resolves `100%` to the cell, not the viewport.
44
+ */
45
+
46
+ var CROSS_INLINE_CAP = 'calc(100dvw - 10px)';
47
+ var CROSS_BLOCK_CAP = 'calc(100dvh - 10px)';
48
+
49
+ /**
50
+ * Legacy `viewportPadding` (`preventOverflow` padding) the popover kept from
51
+ * every viewport edge under `react-popper`. The caps above already *reserve*
52
+ * this space (`- 5px` on the primary far edge, `- 10px` = `2 * 5px` on the
53
+ * cross axis), but nothing makes the reservation land on the viewport side:
54
+ * the anchor-side gap is a real margin (`useAnchorPosition`'s `edgeMargin`),
55
+ * the viewport side has none, so a capped popover packs flush against the
56
+ * viewport edge it slid/flipped to. Re-applying the padding as a margin on the
57
+ * three non-anchor sides puts the reserved space back on the viewport side.
58
+ * `position-try` flips mirror margins and slides keep them per-side, so the
59
+ * gap tracks whichever edge the browser settles on.
60
+ */
61
+ var VIEWPORT_PADDING = '5px';
62
+
63
+ /**
64
+ * The popover's three non-anchor margin sides for a given placement axis — the
65
+ * primary *far* side plus both cross sides. The remaining (anchor-facing) side
66
+ * already carries the offset gap from `useAnchorPosition` and is left alone.
67
+ */
68
+ var NON_ANCHOR_MARGIN_SIDES = {
69
+ top: ['margin-block-start', 'margin-inline-start', 'margin-inline-end'],
70
+ bottom: ['margin-block-end', 'margin-inline-start', 'margin-inline-end'],
71
+ left: ['margin-inline-start', 'margin-block-start', 'margin-block-end'],
72
+ right: ['margin-inline-end', 'margin-block-start', 'margin-block-end']
73
+ };
74
+
75
+ /**
76
+ * @param target the `position-area`-anchored popover host
77
+ * @param placementAxis the primary axis derived from the popper placement
78
+ * @param gap the offset distance the popover is pushed from the
79
+ * anchor (CSS length), subtracted from the primary cap
80
+ * @param isEnabled mirrors the consumer's `shouldFitViewport` prop
81
+ * @param isOpen re-applies the caps after the host unmounts/remounts
82
+ * across open cycles (the host is torn down on exit)
83
+ */
84
+ function useFitViewportMaxSize(_ref) {
85
+ var target = _ref.target,
86
+ placementAxis = _ref.placementAxis,
87
+ gap = _ref.gap,
88
+ isEnabled = _ref.isEnabled,
89
+ isOpen = _ref.isOpen;
90
+ (0, _react.useLayoutEffect)(function () {
91
+ var element = target.current;
92
+ if (!element || !isEnabled) {
93
+ return;
94
+ }
95
+ var isBlockAxis = placementAxis === 'top' || placementAxis === 'bottom';
96
+ var primaryAxisCap = "calc(100% - 5px - ".concat(gap, ")");
97
+ var cleanupHost = (0, _setStyle.setStyle)({
98
+ element: element,
99
+ styles: [{
100
+ property: 'display',
101
+ value: 'flex'
102
+ },
103
+ // Neutralise `useWidthFromAnchor`'s `min-inline-size: max-content`
104
+ // floor so the caps below win and content reflows. `setStyle`
105
+ // restores the floor on cleanup.
106
+ {
107
+ property: 'min-inline-size',
108
+ value: '0'
109
+ }, isBlockAxis ? {
110
+ property: 'max-block-size',
111
+ value: primaryAxisCap
112
+ } : {
113
+ property: 'max-inline-size',
114
+ value: primaryAxisCap
115
+ }, isBlockAxis ? {
116
+ property: 'max-inline-size',
117
+ value: CROSS_INLINE_CAP
118
+ } : {
119
+ property: 'max-block-size',
120
+ value: CROSS_BLOCK_CAP
121
+ }].concat((0, _toConsumableArray2.default)(NON_ANCHOR_MARGIN_SIDES[placementAxis].map(function (property) {
122
+ return {
123
+ property: property,
124
+ value: VIEWPORT_PADDING
125
+ };
126
+ })))
127
+ });
128
+
129
+ // The host deliberately stays `overflow: visible`. An ancestor with
130
+ // `overflow: auto` clips a descendant's `box-shadow`, so capping and
131
+ // scrolling on the host would strip the elevation shadow from the
132
+ // consumer surface. Instead the host only constrains size; scrolling
133
+ // oversized content is the consumer surface's own responsibility,
134
+ // matching the contract `@atlaskit/top-layer`'s `PopoverSurface` follows
135
+ // (shadow and `overflow` on one element). For that surface (the host's
136
+ // flex child) to be clamped to the cap and scroll its own content, it
137
+ // must be allowed to shrink below its intrinsic size, so reset its
138
+ // min-size floor.
139
+ var child = element.firstElementChild;
140
+ var cleanupChild = child instanceof HTMLElement ? (0, _setStyle.setStyle)({
141
+ element: child,
142
+ styles: [{
143
+ property: 'min-block-size',
144
+ value: '0'
145
+ }, {
146
+ property: 'min-inline-size',
147
+ value: '0'
148
+ }]
149
+ }) : undefined;
150
+ return function () {
151
+ cleanupHost();
152
+ cleanupChild === null || cleanupChild === void 0 || cleanupChild();
153
+ };
154
+ }, [target, placementAxis, gap, isEnabled, isOpen]);
155
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useManagerAnchorSetter = useManagerAnchorSetter;
7
+ var _react = require("react");
8
+ var _anchorSetterContext = require("./anchor-setter-context");
9
+ /**
10
+ * Returns the setter that an ancestor `<Manager>` exposes to publish
11
+ * the anchor element from `<Reference>`. Returns a no-op when there is
12
+ * no surrounding `<Manager>`.
13
+ */
14
+ function useManagerAnchorSetter() {
15
+ return (0, _react.useContext)(_anchorSetterContext.AnchorSetterContext);
16
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useManagerAnchor = useManagerAnchor;
7
+ var _react = require("react");
8
+ var _anchorContext = require("./anchor-context");
9
+ /**
10
+ * Returns the current anchor element published by an ancestor
11
+ * `<Reference>` via the shared `<Manager>` provider. Returns `null`
12
+ * when there is no surrounding `<Manager>` / `<Reference>` pair.
13
+ */
14
+ function useManagerAnchor() {
15
+ return (0, _react.useContext)(_anchorContext.AnchorContext);
16
+ }
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useReferenceVisibility = useReferenceVisibility;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _react = require("react");
10
+ var _bindEventListener = require("bind-event-listener");
11
+ var _readViewport = require("./read-viewport");
12
+ var INITIAL = {
13
+ isReferenceHidden: false,
14
+ hasPopperEscaped: false
15
+ };
16
+ function isFullyOutsideViewport(rect, viewport) {
17
+ if (rect.width === 0 && rect.height === 0) {
18
+ return true;
19
+ }
20
+ if (rect.bottom <= 0) {
21
+ return true;
22
+ }
23
+ if (rect.right <= 0) {
24
+ return true;
25
+ }
26
+ if (rect.top >= viewport.height) {
27
+ return true;
28
+ }
29
+ if (rect.left >= viewport.width) {
30
+ return true;
31
+ }
32
+ return false;
33
+ }
34
+ function isClippingOverflow(value) {
35
+ return value === 'auto' || value === 'scroll' || value === 'hidden' || value === 'clip';
36
+ }
37
+ function isClippedByAncestors(element) {
38
+ var rect = element.getBoundingClientRect();
39
+ var parent = element.parentElement;
40
+ while (parent) {
41
+ // Read the longhand axis properties directly. The `overflow` shorthand
42
+ // is only populated when both axes share the same value, so reading it
43
+ // alone misses ancestors that set only `overflow-x` or `overflow-y`.
44
+ var style = window.getComputedStyle(parent);
45
+ var clipsHorizontally = isClippingOverflow(style.overflowX);
46
+ var clipsVertically = isClippingOverflow(style.overflowY);
47
+ if (clipsHorizontally || clipsVertically) {
48
+ var parentRect = parent.getBoundingClientRect();
49
+ var horizontallyOutside = rect.right <= parentRect.left || rect.left >= parentRect.right;
50
+ var verticallyOutside = rect.bottom <= parentRect.top || rect.top >= parentRect.bottom;
51
+ if (clipsHorizontally && horizontallyOutside) {
52
+ return true;
53
+ }
54
+ if (clipsVertically && verticallyOutside) {
55
+ return true;
56
+ }
57
+ }
58
+ parent = parent.parentElement;
59
+ }
60
+ return false;
61
+ }
62
+
63
+ /**
64
+ * Exists **only** to preserve API parity with the legacy popper.js
65
+ * implementation. The top-layer popper does not natively expose
66
+ * popper.js's `isReferenceHidden` / `hasPopperEscaped` render-prop
67
+ * modifiers, but existing consumers still branch on those values, so
68
+ * this hook reconstructs them from live DOM measurement.
69
+ *
70
+ * Do not reach for this hook in new code. If you find yourself wanting
71
+ * these signals for a new feature, prefer a first-class top-layer or
72
+ * anchor-positioning primitive instead.
73
+ *
74
+ * - `isReferenceHidden`: the anchor's bounding rect is fully outside the
75
+ * visual viewport OR is clipped to zero area by any scrollable
76
+ * ancestor.
77
+ * - `hasPopperEscaped`: the popover surface's rect is fully outside the
78
+ * visual viewport.
79
+ *
80
+ * Measurement runs in a `useLayoutEffect` so the first paint already
81
+ * reflects the correct values, preventing consumers from animating
82
+ * from `opacity: 1` to `opacity: 0` on mount.
83
+ */
84
+ function useReferenceVisibility(_ref) {
85
+ var anchor = _ref.anchor,
86
+ popoverRef = _ref.popoverRef;
87
+ var _useState = (0, _react.useState)(INITIAL),
88
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
89
+ visibility = _useState2[0],
90
+ setVisibility = _useState2[1];
91
+ var measure = (0, _react.useCallback)(function () {
92
+ if (!anchor) {
93
+ setVisibility(function (previous) {
94
+ return previous.isReferenceHidden === false && previous.hasPopperEscaped === false ? previous : INITIAL;
95
+ });
96
+ return;
97
+ }
98
+ var viewport = (0, _readViewport.readViewport)();
99
+ var anchorRect = anchor.getBoundingClientRect();
100
+ var isReferenceHidden = isFullyOutsideViewport(anchorRect, viewport) || isClippedByAncestors(anchor);
101
+ var popoverElement = popoverRef.current;
102
+ var hasPopperEscaped = popoverElement ? isFullyOutsideViewport(popoverElement.getBoundingClientRect(), viewport) : false;
103
+ setVisibility(function (previous) {
104
+ if (previous.isReferenceHidden === isReferenceHidden && previous.hasPopperEscaped === hasPopperEscaped) {
105
+ return previous;
106
+ }
107
+ return {
108
+ isReferenceHidden: isReferenceHidden,
109
+ hasPopperEscaped: hasPopperEscaped
110
+ };
111
+ });
112
+ }, [anchor, popoverRef]);
113
+ (0, _react.useLayoutEffect)(function () {
114
+ measure();
115
+ if (typeof window === 'undefined') {
116
+ return undefined;
117
+ }
118
+ var cleanups = [];
119
+
120
+ // Resize observer on the anchor so layout changes update visibility.
121
+ if (anchor && typeof ResizeObserver !== 'undefined') {
122
+ var observer = new ResizeObserver(function () {
123
+ return measure();
124
+ });
125
+ observer.observe(anchor);
126
+ cleanups.push(function () {
127
+ return observer.disconnect();
128
+ });
129
+ }
130
+
131
+ // Scroll + resize: any scroll event in the document can move the
132
+ // anchor in/out of any scrollable ancestor's viewport.
133
+ cleanups.push((0, _bindEventListener.bindAll)(window, [{
134
+ type: 'scroll',
135
+ listener: measure,
136
+ options: {
137
+ capture: true,
138
+ passive: true
139
+ }
140
+ }, {
141
+ type: 'resize',
142
+ listener: measure,
143
+ options: {
144
+ passive: true
145
+ }
146
+ }]));
147
+ var visual = window.visualViewport;
148
+ if (visual) {
149
+ cleanups.push((0, _bindEventListener.bind)(visual, {
150
+ type: 'resize',
151
+ listener: measure,
152
+ options: {
153
+ passive: true
154
+ }
155
+ }));
156
+ }
157
+ return function () {
158
+ cleanups.forEach(function (cleanup) {
159
+ return cleanup();
160
+ });
161
+ };
162
+ }, [anchor, measure]);
163
+ return visibility;
164
+ }