@atlaskit/popper 8.0.1 → 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 +12 -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 +15 -4
- package/popper.docs.tsx +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @atlaskit/popper
|
|
2
2
|
|
|
3
|
+
## 8.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`db3328ec580e4`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/db3328ec580e4) -
|
|
8
|
+
Behind the `"platform-dst-top-layer"` feature flag, `@atlaskit/popper` now renders into the
|
|
9
|
+
browser top layer via `@atlaskit/top-layer`. Public API and exported types are unchanged.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
|
|
3
15
|
## 8.0.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
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
|
|
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
|
|
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
|
|
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
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.Manager = Manager;
|
|
8
|
+
var _react = _interopRequireDefault(require("react"));
|
|
9
|
+
var _reactPopper = require("react-popper");
|
|
10
|
+
var _anchorContext = require("./internal/anchor-context");
|
|
11
|
+
var _anchorSetterContext = require("./internal/anchor-setter-context");
|
|
12
|
+
var _useAnchorState2 = require("./internal/use-anchor-state");
|
|
13
|
+
// Derive the wrapper's props from `react-popper`'s own `ManagerProps` so the
|
|
14
|
+
// public surface provably accepts exactly what the underlying `<Manager>`
|
|
15
|
+
// accepts (today just `children`) and stays in sync if that contract changes.
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Wraps `react-popper`'s `<Manager>` so the anchor that `<Reference>`
|
|
19
|
+
* captures is published through `@atlaskit/popper`'s own bridge context.
|
|
20
|
+
* Doing so insulates `<Popper>` consumers from `react-popper`'s dual
|
|
21
|
+
* CJS / ESM builds, which otherwise create two unrelated context
|
|
22
|
+
* instances that prevent the FF-on top-layer adapter from discovering
|
|
23
|
+
* the anchor.
|
|
24
|
+
*/
|
|
25
|
+
function Manager(_ref) {
|
|
26
|
+
var children = _ref.children;
|
|
27
|
+
// `setAnchor` is the `useState` setter, which React guarantees is stable
|
|
28
|
+
// across renders, so it can be passed straight to the context provider.
|
|
29
|
+
var _useAnchorState = (0, _useAnchorState2.useAnchorState)(),
|
|
30
|
+
anchor = _useAnchorState.anchor,
|
|
31
|
+
setAnchor = _useAnchorState.setAnchor;
|
|
32
|
+
return /*#__PURE__*/_react.default.createElement(_reactPopper.Manager, null, /*#__PURE__*/_react.default.createElement(_anchorSetterContext.AnchorSetterContext.Provider, {
|
|
33
|
+
value: setAnchor
|
|
34
|
+
}, /*#__PURE__*/_react.default.createElement(_anchorContext.AnchorContext.Provider, {
|
|
35
|
+
value: anchor
|
|
36
|
+
}, children)));
|
|
37
|
+
}
|