braid-design-system 33.13.0-autosuggest-suggestions-data-prop-20251202035740 → 33.13.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 +15 -2
- package/dist/index.d.mts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/lib/components/TooltipRenderer/TooltipRenderer.cjs +66 -73
- package/dist/lib/components/TooltipRenderer/TooltipRenderer.css.cjs +7 -6
- package/dist/lib/components/TooltipRenderer/TooltipRenderer.css.mjs +7 -6
- package/dist/lib/components/TooltipRenderer/TooltipRenderer.mjs +67 -74
- package/dist/lib/components/private/Popover/Popover.cjs +90 -125
- package/dist/lib/components/private/Popover/Popover.css.cjs +0 -21
- package/dist/lib/components/private/Popover/Popover.css.mjs +2 -23
- package/dist/lib/components/private/Popover/Popover.mjs +92 -127
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# braid-design-system
|
|
2
2
|
|
|
3
|
-
## 33.13.0
|
|
3
|
+
## 33.13.0
|
|
4
4
|
|
|
5
5
|
### Minor Changes
|
|
6
6
|
|
|
7
|
-
- **Autosuggest:** Add support for data attributes on individual suggestions (
|
|
7
|
+
- **Autosuggest:** Add support for data attributes on individual suggestions ([#1938](https://github.com/seek-oss/braid-design-system/pull/1938))
|
|
8
8
|
|
|
9
9
|
The data attributes are applied to each rendered list item.
|
|
10
10
|
|
|
@@ -21,6 +21,19 @@
|
|
|
21
21
|
/>
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- **ButtonIcon, TooltipRenderer:** Close tooltips after clicking the trigger on desktop devices ([#1932](https://github.com/seek-oss/braid-design-system/pull/1932))
|
|
27
|
+
|
|
28
|
+
## 33.12.4
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- **Autosuggest, MenuRenderer, OverflowMenu, TooltipRenderer**: Ensure `TooltipRenderer` is correctly positioned on Android devices ([#1926](https://github.com/seek-oss/braid-design-system/pull/1926))
|
|
33
|
+
|
|
34
|
+
Additionally, adjust `TooltipRenderer` positioning at screen edges, removing extra edge spacing.
|
|
35
|
+
This ensures the tooltip arrow is more closely aligned with the trigger when the trigger is near the edge of the screen.
|
|
36
|
+
|
|
24
37
|
## 33.12.3
|
|
25
38
|
|
|
26
39
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -3422,6 +3422,13 @@ interface LoaderProps {
|
|
|
3422
3422
|
declare const Loader: ({ size, "aria-label": ariaLabel, delayVisibility, data, ...restProps }: LoaderProps) => react.JSX.Element;
|
|
3423
3423
|
|
|
3424
3424
|
type Placement = 'top' | 'bottom';
|
|
3425
|
+
interface PopoverPlacementData {
|
|
3426
|
+
placement: Placement;
|
|
3427
|
+
arrow?: {
|
|
3428
|
+
x?: number;
|
|
3429
|
+
y?: number;
|
|
3430
|
+
};
|
|
3431
|
+
}
|
|
3425
3432
|
interface PopoverProps {
|
|
3426
3433
|
id?: string;
|
|
3427
3434
|
role: NonNullable<AllHTMLAttributes<HTMLElement>['role'] | false>;
|
|
@@ -3434,8 +3441,10 @@ interface PopoverProps {
|
|
|
3434
3441
|
modal?: boolean;
|
|
3435
3442
|
open: boolean;
|
|
3436
3443
|
onClose?: () => void;
|
|
3444
|
+
onPlacementChange?: (data: PopoverPlacementData) => void;
|
|
3437
3445
|
triggerRef: RefObject<HTMLElement | null>;
|
|
3438
3446
|
enterFocusRef?: RefObject<HTMLElement | null>;
|
|
3447
|
+
arrowRef?: RefObject<HTMLElement | null>;
|
|
3439
3448
|
children: ReactNode;
|
|
3440
3449
|
}
|
|
3441
3450
|
|
package/dist/index.d.ts
CHANGED
|
@@ -3422,6 +3422,13 @@ interface LoaderProps {
|
|
|
3422
3422
|
declare const Loader: ({ size, "aria-label": ariaLabel, delayVisibility, data, ...restProps }: LoaderProps) => react.JSX.Element;
|
|
3423
3423
|
|
|
3424
3424
|
type Placement = 'top' | 'bottom';
|
|
3425
|
+
interface PopoverPlacementData {
|
|
3426
|
+
placement: Placement;
|
|
3427
|
+
arrow?: {
|
|
3428
|
+
x?: number;
|
|
3429
|
+
y?: number;
|
|
3430
|
+
};
|
|
3431
|
+
}
|
|
3425
3432
|
interface PopoverProps {
|
|
3426
3433
|
id?: string;
|
|
3427
3434
|
role: NonNullable<AllHTMLAttributes<HTMLElement>['role'] | false>;
|
|
@@ -3434,8 +3441,10 @@ interface PopoverProps {
|
|
|
3434
3441
|
modal?: boolean;
|
|
3435
3442
|
open: boolean;
|
|
3436
3443
|
onClose?: () => void;
|
|
3444
|
+
onPlacementChange?: (data: PopoverPlacementData) => void;
|
|
3437
3445
|
triggerRef: RefObject<HTMLElement | null>;
|
|
3438
3446
|
enterFocusRef?: RefObject<HTMLElement | null>;
|
|
3447
|
+
arrowRef?: RefObject<HTMLElement | null>;
|
|
3439
3448
|
children: ReactNode;
|
|
3440
3449
|
}
|
|
3441
3450
|
|
|
@@ -7,16 +7,15 @@ const lib_hooks_useFallbackId_cjs = require("../../hooks/useFallbackId.cjs");
|
|
|
7
7
|
const lib_hooks_useIsomorphicLayoutEffect_cjs = require("../../hooks/useIsomorphicLayoutEffect.cjs");
|
|
8
8
|
const lib_components_Box_Box_cjs = require("../Box/Box.cjs");
|
|
9
9
|
const lib_components_private_Popover_Popover_cjs = require("../private/Popover/Popover.cjs");
|
|
10
|
-
const lib_components_private_animationTimeout_cjs = require("../private/animationTimeout.cjs");
|
|
11
10
|
const lib_components_private_defaultTextProps_cjs = require("../private/defaultTextProps.cjs");
|
|
12
11
|
const lib_components_useSpace_useSpace_cjs = require("../useSpace/useSpace.cjs");
|
|
13
12
|
const lib_components_useThemeName_useThemeName_cjs = require("../useThemeName/useThemeName.cjs");
|
|
14
13
|
const lib_components_TooltipRenderer_TooltipRenderer_css_cjs = require("./TooltipRenderer.css.cjs");
|
|
15
14
|
const _interopDefaultCompat = (e) => e && typeof e === "object" && "default" in e ? e : { default: e };
|
|
16
15
|
const isMobile__default = /* @__PURE__ */ _interopDefaultCompat(isMobile);
|
|
17
|
-
const edgeOffset = "xxsmall";
|
|
18
16
|
const offsetSpace = "small";
|
|
19
17
|
const StaticTooltipContext = react.createContext(false);
|
|
18
|
+
const clamp = (min, value, max) => Math.max(min, Math.min(value, max));
|
|
20
19
|
const TooltipTextDefaultsProvider = ({
|
|
21
20
|
children
|
|
22
21
|
}) => {
|
|
@@ -31,35 +30,59 @@ const TooltipTextDefaultsProvider = ({
|
|
|
31
30
|
);
|
|
32
31
|
};
|
|
33
32
|
const TooltipContent = ({
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
placement,
|
|
34
|
+
arrowPosition,
|
|
35
|
+
arrowRef,
|
|
36
36
|
children
|
|
37
|
-
}) =>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
37
|
+
}) => {
|
|
38
|
+
const arrowX = arrowPosition?.x;
|
|
39
|
+
const arrowY = arrowPosition?.y;
|
|
40
|
+
const { space, grid } = lib_components_useSpace_useSpace_cjs.useSpace();
|
|
41
|
+
const edgeOffsetInPx = grid * space.xsmall;
|
|
42
|
+
const arrowWidthOffset = parseFloat(lib_components_TooltipRenderer_TooltipRenderer_css_cjs.constants.arrowSize) * 2;
|
|
43
|
+
const [tooltipWidth, setTooltipWidth] = react.useState(0);
|
|
44
|
+
const tooltipContainerRef = react.useRef(null);
|
|
45
|
+
lib_hooks_useIsomorphicLayoutEffect_cjs.useIsomorphicLayoutEffect(() => {
|
|
46
|
+
if (!tooltipContainerRef.current) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const { width } = tooltipContainerRef.current.getBoundingClientRect();
|
|
50
|
+
setTooltipWidth(width);
|
|
51
|
+
}, [children]);
|
|
52
|
+
const clampedArrowX = arrowX !== void 0 && tooltipWidth > 0 ? clamp(
|
|
53
|
+
edgeOffsetInPx,
|
|
54
|
+
arrowX,
|
|
55
|
+
tooltipWidth - edgeOffsetInPx - arrowWidthOffset
|
|
56
|
+
) : arrowX;
|
|
57
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
58
|
+
lib_components_Box_Box_cjs.Box,
|
|
59
|
+
{
|
|
60
|
+
ref: tooltipContainerRef,
|
|
61
|
+
textAlign: "left",
|
|
62
|
+
boxShadow: "large",
|
|
63
|
+
background: "neutral",
|
|
64
|
+
borderRadius: "large",
|
|
65
|
+
padding: "small",
|
|
66
|
+
className: [lib_components_TooltipRenderer_TooltipRenderer_css_cjs.maxWidth, lib_components_TooltipRenderer_TooltipRenderer_css_cjs.translateZ0],
|
|
67
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipTextDefaultsProvider, { children: [
|
|
68
|
+
/* @__PURE__ */ jsxRuntime.jsx(lib_components_Box_Box_cjs.Box, { className: lib_components_TooltipRenderer_TooltipRenderer_css_cjs.overflowWrap, zIndex: 1, position: "relative", children }),
|
|
69
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
70
|
+
lib_components_Box_Box_cjs.Box,
|
|
71
|
+
{
|
|
72
|
+
ref: arrowRef,
|
|
73
|
+
position: "fixed",
|
|
74
|
+
background: "neutral",
|
|
75
|
+
className: lib_components_TooltipRenderer_TooltipRenderer_css_cjs.arrow[placement ?? "top"],
|
|
76
|
+
style: dynamic.assignInlineVars({
|
|
77
|
+
[lib_components_TooltipRenderer_TooltipRenderer_css_cjs.arrowX]: clampedArrowX !== void 0 ? `${clampedArrowX}px` : void 0,
|
|
78
|
+
[lib_components_TooltipRenderer_TooltipRenderer_css_cjs.arrowY]: arrowY !== void 0 ? `${arrowY}px` : void 0
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
] })
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
};
|
|
63
86
|
const TooltipRenderer = ({
|
|
64
87
|
id,
|
|
65
88
|
tooltip,
|
|
@@ -67,16 +90,11 @@ const TooltipRenderer = ({
|
|
|
67
90
|
children
|
|
68
91
|
}) => {
|
|
69
92
|
const resolvedId = lib_hooks_useFallbackId_cjs.useFallbackId(id);
|
|
70
|
-
const tooltipRef = react.useRef(null);
|
|
71
93
|
const triggerRef = react.useRef(null);
|
|
94
|
+
const arrowRef = react.useRef(null);
|
|
72
95
|
const [open, setOpen] = react.useState(false);
|
|
73
|
-
const [
|
|
74
|
-
|
|
75
|
-
);
|
|
76
|
-
const [tooltipPosition, setTooltipPosition] = react.useState(
|
|
77
|
-
void 0
|
|
78
|
-
);
|
|
79
|
-
const { grid, space } = lib_components_useSpace_useSpace_cjs.useSpace();
|
|
96
|
+
const [resolvedPlacement, setResolvedPlacement] = react.useState(placement);
|
|
97
|
+
const [arrowPosition, setArrowPosition] = react.useState();
|
|
80
98
|
const isStatic = react.useContext(StaticTooltipContext);
|
|
81
99
|
const isMobileDevice = react.useRef(isMobile__default.default()).current;
|
|
82
100
|
const onScreen = react.useRef(null);
|
|
@@ -121,6 +139,7 @@ const TooltipRenderer = ({
|
|
|
121
139
|
triggerRef.current.addEventListener("focus", openTooltip);
|
|
122
140
|
triggerRef.current.addEventListener("mouseenter", openTooltip);
|
|
123
141
|
triggerRef.current.addEventListener("mouseleave", closeTooltip);
|
|
142
|
+
triggerRef.current.addEventListener("click", closeTooltip);
|
|
124
143
|
}
|
|
125
144
|
}
|
|
126
145
|
return () => {
|
|
@@ -132,42 +151,11 @@ const TooltipRenderer = ({
|
|
|
132
151
|
triggerRef.current.removeEventListener("focus", openTooltip);
|
|
133
152
|
triggerRef.current.removeEventListener("mouseenter", openTooltip);
|
|
134
153
|
triggerRef.current.removeEventListener("mouseleave", closeTooltip);
|
|
154
|
+
triggerRef.current.removeEventListener("click", closeTooltip);
|
|
135
155
|
}
|
|
136
156
|
}
|
|
137
157
|
};
|
|
138
158
|
}, [open, isMobileDevice]);
|
|
139
|
-
const handleTooltipPosition = () => {
|
|
140
|
-
const setPositions = () => {
|
|
141
|
-
if (tooltipRef.current) {
|
|
142
|
-
setTooltipPosition(tooltipRef.current.getBoundingClientRect());
|
|
143
|
-
}
|
|
144
|
-
if (triggerRef.current) {
|
|
145
|
-
setTriggerPosition(triggerRef.current.getBoundingClientRect());
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
setTimeout(() => {
|
|
149
|
-
const frameId = requestAnimationFrame(setPositions);
|
|
150
|
-
return () => cancelAnimationFrame(frameId);
|
|
151
|
-
}, lib_components_private_animationTimeout_cjs.animationTimeout / 2);
|
|
152
|
-
};
|
|
153
|
-
lib_hooks_useIsomorphicLayoutEffect_cjs.useIsomorphicLayoutEffect(() => {
|
|
154
|
-
if (!showTooltip) {
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
handleTooltipPosition();
|
|
158
|
-
window.addEventListener("resize", handleTooltipPosition);
|
|
159
|
-
return () => {
|
|
160
|
-
window.removeEventListener("resize", handleTooltipPosition);
|
|
161
|
-
};
|
|
162
|
-
}, [showTooltip]);
|
|
163
|
-
let inferredPlacement = placement;
|
|
164
|
-
let arrowLeftOffset = 0;
|
|
165
|
-
if (tooltipPosition && triggerPosition) {
|
|
166
|
-
inferredPlacement = tooltipPosition.top > triggerPosition.top ? "bottom" : "top";
|
|
167
|
-
const edgeOffsetInPx = space[edgeOffset] * grid;
|
|
168
|
-
const tooltipLeftToTriggerLeft = triggerPosition.left - tooltipPosition.left - edgeOffsetInPx;
|
|
169
|
-
arrowLeftOffset = tooltipLeftToTriggerLeft + triggerPosition.width / 2;
|
|
170
|
-
}
|
|
171
159
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
172
160
|
children({
|
|
173
161
|
triggerProps: {
|
|
@@ -183,7 +171,6 @@ const TooltipRenderer = ({
|
|
|
183
171
|
{
|
|
184
172
|
id: resolvedId,
|
|
185
173
|
role: "tooltip",
|
|
186
|
-
ref: tooltipRef,
|
|
187
174
|
offsetSpace,
|
|
188
175
|
align: "center",
|
|
189
176
|
placement,
|
|
@@ -192,12 +179,18 @@ const TooltipRenderer = ({
|
|
|
192
179
|
modal: false,
|
|
193
180
|
open: showTooltip,
|
|
194
181
|
onClose: !isStatic ? () => setOpen(false) : void 0,
|
|
182
|
+
onPlacementChange: ({ placement: newPlacement, arrow }) => {
|
|
183
|
+
setResolvedPlacement(newPlacement);
|
|
184
|
+
setArrowPosition(arrow);
|
|
185
|
+
},
|
|
195
186
|
triggerRef,
|
|
187
|
+
arrowRef,
|
|
196
188
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
197
189
|
TooltipContent,
|
|
198
190
|
{
|
|
199
|
-
|
|
200
|
-
|
|
191
|
+
placement: resolvedPlacement,
|
|
192
|
+
arrowPosition,
|
|
193
|
+
arrowRef,
|
|
201
194
|
children: tooltip
|
|
202
195
|
}
|
|
203
196
|
)
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
const fileScope = require("@vanilla-extract/css/fileScope");
|
|
3
3
|
const css = require("@vanilla-extract/css");
|
|
4
4
|
const cssUtils = require("@vanilla-extract/css-utils");
|
|
5
|
-
const lib_css_atoms_atomicProperties_cjs = require("../../css/atoms/atomicProperties.cjs");
|
|
6
5
|
const lib_themes_vars_css_cjs = require("../../themes/vars.css.cjs");
|
|
7
6
|
fileScope.setFileScope("src/lib/components/TooltipRenderer/TooltipRenderer.css.ts", "braid-design-system");
|
|
8
7
|
const constants = {
|
|
@@ -21,11 +20,11 @@ const translateZ0 = css.style({
|
|
|
21
20
|
}, "translateZ0");
|
|
22
21
|
const borderRadius = lib_themes_vars_css_cjs.vars.borderRadius.small;
|
|
23
22
|
const offset = cssUtils.calc(constants.arrowSize).divide(2).negate().toString();
|
|
24
|
-
const
|
|
25
|
-
const
|
|
23
|
+
const arrowX = css.createVar("arrowX");
|
|
24
|
+
const arrowY = css.createVar("arrowY");
|
|
26
25
|
const baseArrow = css.style({
|
|
27
|
-
left:
|
|
28
|
-
|
|
26
|
+
left: arrowX,
|
|
27
|
+
top: arrowY,
|
|
29
28
|
visibility: "hidden",
|
|
30
29
|
":before": {
|
|
31
30
|
visibility: "visible",
|
|
@@ -52,7 +51,9 @@ const arrow = css.styleVariants({
|
|
|
52
51
|
}, "arrow");
|
|
53
52
|
fileScope.endFileScope();
|
|
54
53
|
exports.arrow = arrow;
|
|
55
|
-
exports.
|
|
54
|
+
exports.arrowX = arrowX;
|
|
55
|
+
exports.arrowY = arrowY;
|
|
56
|
+
exports.constants = constants;
|
|
56
57
|
exports.maxWidth = maxWidth;
|
|
57
58
|
exports.overflowWrap = overflowWrap;
|
|
58
59
|
exports.translateZ0 = translateZ0;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { setFileScope, endFileScope } from "@vanilla-extract/css/fileScope";
|
|
2
2
|
import { style, styleVariants, createVar } from "@vanilla-extract/css";
|
|
3
3
|
import { calc } from "@vanilla-extract/css-utils";
|
|
4
|
-
import { space } from "../../css/atoms/atomicProperties.mjs";
|
|
5
4
|
import { vars } from "../../themes/vars.css.mjs";
|
|
6
5
|
setFileScope("src/lib/components/TooltipRenderer/TooltipRenderer.css.ts", "braid-design-system");
|
|
7
6
|
const constants = {
|
|
@@ -20,11 +19,11 @@ const translateZ0 = style({
|
|
|
20
19
|
}, "translateZ0");
|
|
21
20
|
const borderRadius = vars.borderRadius.small;
|
|
22
21
|
const offset = calc(constants.arrowSize).divide(2).negate().toString();
|
|
23
|
-
const
|
|
24
|
-
const
|
|
22
|
+
const arrowX = createVar("arrowX");
|
|
23
|
+
const arrowY = createVar("arrowY");
|
|
25
24
|
const baseArrow = style({
|
|
26
|
-
left:
|
|
27
|
-
|
|
25
|
+
left: arrowX,
|
|
26
|
+
top: arrowY,
|
|
28
27
|
visibility: "hidden",
|
|
29
28
|
":before": {
|
|
30
29
|
visibility: "visible",
|
|
@@ -52,7 +51,9 @@ const arrow = styleVariants({
|
|
|
52
51
|
endFileScope();
|
|
53
52
|
export {
|
|
54
53
|
arrow,
|
|
55
|
-
|
|
54
|
+
arrowX,
|
|
55
|
+
arrowY,
|
|
56
|
+
constants,
|
|
56
57
|
maxWidth,
|
|
57
58
|
overflowWrap,
|
|
58
59
|
translateZ0
|
|
@@ -6,14 +6,13 @@ import { useFallbackId } from "../../hooks/useFallbackId.mjs";
|
|
|
6
6
|
import { useIsomorphicLayoutEffect } from "../../hooks/useIsomorphicLayoutEffect.mjs";
|
|
7
7
|
import { Box } from "../Box/Box.mjs";
|
|
8
8
|
import { Popover } from "../private/Popover/Popover.mjs";
|
|
9
|
-
import { animationTimeout } from "../private/animationTimeout.mjs";
|
|
10
9
|
import { DefaultTextPropsProvider } from "../private/defaultTextProps.mjs";
|
|
11
10
|
import { useSpace } from "../useSpace/useSpace.mjs";
|
|
12
11
|
import { useThemeName } from "../useThemeName/useThemeName.mjs";
|
|
13
|
-
import { maxWidth, translateZ0, overflowWrap, arrow,
|
|
14
|
-
const edgeOffset = "xxsmall";
|
|
12
|
+
import { maxWidth, translateZ0, overflowWrap, arrow, arrowY, arrowX, constants } from "./TooltipRenderer.css.mjs";
|
|
15
13
|
const offsetSpace = "small";
|
|
16
14
|
const StaticTooltipContext = createContext(false);
|
|
15
|
+
const clamp = (min, value, max) => Math.max(min, Math.min(value, max));
|
|
17
16
|
const TooltipTextDefaultsProvider = ({
|
|
18
17
|
children
|
|
19
18
|
}) => {
|
|
@@ -28,35 +27,59 @@ const TooltipTextDefaultsProvider = ({
|
|
|
28
27
|
);
|
|
29
28
|
};
|
|
30
29
|
const TooltipContent = ({
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
placement,
|
|
31
|
+
arrowPosition,
|
|
32
|
+
arrowRef,
|
|
33
33
|
children
|
|
34
|
-
}) =>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
34
|
+
}) => {
|
|
35
|
+
const arrowX$1 = arrowPosition?.x;
|
|
36
|
+
const arrowY$1 = arrowPosition?.y;
|
|
37
|
+
const { space, grid } = useSpace();
|
|
38
|
+
const edgeOffsetInPx = grid * space.xsmall;
|
|
39
|
+
const arrowWidthOffset = parseFloat(constants.arrowSize) * 2;
|
|
40
|
+
const [tooltipWidth, setTooltipWidth] = useState(0);
|
|
41
|
+
const tooltipContainerRef = useRef(null);
|
|
42
|
+
useIsomorphicLayoutEffect(() => {
|
|
43
|
+
if (!tooltipContainerRef.current) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const { width } = tooltipContainerRef.current.getBoundingClientRect();
|
|
47
|
+
setTooltipWidth(width);
|
|
48
|
+
}, [children]);
|
|
49
|
+
const clampedArrowX = arrowX$1 !== void 0 && tooltipWidth > 0 ? clamp(
|
|
50
|
+
edgeOffsetInPx,
|
|
51
|
+
arrowX$1,
|
|
52
|
+
tooltipWidth - edgeOffsetInPx - arrowWidthOffset
|
|
53
|
+
) : arrowX$1;
|
|
54
|
+
return /* @__PURE__ */ jsx(
|
|
55
|
+
Box,
|
|
56
|
+
{
|
|
57
|
+
ref: tooltipContainerRef,
|
|
58
|
+
textAlign: "left",
|
|
59
|
+
boxShadow: "large",
|
|
60
|
+
background: "neutral",
|
|
61
|
+
borderRadius: "large",
|
|
62
|
+
padding: "small",
|
|
63
|
+
className: [maxWidth, translateZ0],
|
|
64
|
+
children: /* @__PURE__ */ jsxs(TooltipTextDefaultsProvider, { children: [
|
|
65
|
+
/* @__PURE__ */ jsx(Box, { className: overflowWrap, zIndex: 1, position: "relative", children }),
|
|
66
|
+
/* @__PURE__ */ jsx(
|
|
67
|
+
Box,
|
|
68
|
+
{
|
|
69
|
+
ref: arrowRef,
|
|
70
|
+
position: "fixed",
|
|
71
|
+
background: "neutral",
|
|
72
|
+
className: arrow[placement ?? "top"],
|
|
73
|
+
style: assignInlineVars({
|
|
74
|
+
[arrowX]: clampedArrowX !== void 0 ? `${clampedArrowX}px` : void 0,
|
|
75
|
+
[arrowY]: arrowY$1 !== void 0 ? `${arrowY$1}px` : void 0
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
] })
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
};
|
|
60
83
|
const TooltipRenderer = ({
|
|
61
84
|
id,
|
|
62
85
|
tooltip,
|
|
@@ -64,16 +87,11 @@ const TooltipRenderer = ({
|
|
|
64
87
|
children
|
|
65
88
|
}) => {
|
|
66
89
|
const resolvedId = useFallbackId(id);
|
|
67
|
-
const tooltipRef = useRef(null);
|
|
68
90
|
const triggerRef = useRef(null);
|
|
91
|
+
const arrowRef = useRef(null);
|
|
69
92
|
const [open, setOpen] = useState(false);
|
|
70
|
-
const [
|
|
71
|
-
|
|
72
|
-
);
|
|
73
|
-
const [tooltipPosition, setTooltipPosition] = useState(
|
|
74
|
-
void 0
|
|
75
|
-
);
|
|
76
|
-
const { grid, space } = useSpace();
|
|
93
|
+
const [resolvedPlacement, setResolvedPlacement] = useState(placement);
|
|
94
|
+
const [arrowPosition, setArrowPosition] = useState();
|
|
77
95
|
const isStatic = useContext(StaticTooltipContext);
|
|
78
96
|
const isMobileDevice = useRef(isMobile()).current;
|
|
79
97
|
const onScreen = useRef(null);
|
|
@@ -118,6 +136,7 @@ const TooltipRenderer = ({
|
|
|
118
136
|
triggerRef.current.addEventListener("focus", openTooltip);
|
|
119
137
|
triggerRef.current.addEventListener("mouseenter", openTooltip);
|
|
120
138
|
triggerRef.current.addEventListener("mouseleave", closeTooltip);
|
|
139
|
+
triggerRef.current.addEventListener("click", closeTooltip);
|
|
121
140
|
}
|
|
122
141
|
}
|
|
123
142
|
return () => {
|
|
@@ -129,42 +148,11 @@ const TooltipRenderer = ({
|
|
|
129
148
|
triggerRef.current.removeEventListener("focus", openTooltip);
|
|
130
149
|
triggerRef.current.removeEventListener("mouseenter", openTooltip);
|
|
131
150
|
triggerRef.current.removeEventListener("mouseleave", closeTooltip);
|
|
151
|
+
triggerRef.current.removeEventListener("click", closeTooltip);
|
|
132
152
|
}
|
|
133
153
|
}
|
|
134
154
|
};
|
|
135
155
|
}, [open, isMobileDevice]);
|
|
136
|
-
const handleTooltipPosition = () => {
|
|
137
|
-
const setPositions = () => {
|
|
138
|
-
if (tooltipRef.current) {
|
|
139
|
-
setTooltipPosition(tooltipRef.current.getBoundingClientRect());
|
|
140
|
-
}
|
|
141
|
-
if (triggerRef.current) {
|
|
142
|
-
setTriggerPosition(triggerRef.current.getBoundingClientRect());
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
setTimeout(() => {
|
|
146
|
-
const frameId = requestAnimationFrame(setPositions);
|
|
147
|
-
return () => cancelAnimationFrame(frameId);
|
|
148
|
-
}, animationTimeout / 2);
|
|
149
|
-
};
|
|
150
|
-
useIsomorphicLayoutEffect(() => {
|
|
151
|
-
if (!showTooltip) {
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
handleTooltipPosition();
|
|
155
|
-
window.addEventListener("resize", handleTooltipPosition);
|
|
156
|
-
return () => {
|
|
157
|
-
window.removeEventListener("resize", handleTooltipPosition);
|
|
158
|
-
};
|
|
159
|
-
}, [showTooltip]);
|
|
160
|
-
let inferredPlacement = placement;
|
|
161
|
-
let arrowLeftOffset = 0;
|
|
162
|
-
if (tooltipPosition && triggerPosition) {
|
|
163
|
-
inferredPlacement = tooltipPosition.top > triggerPosition.top ? "bottom" : "top";
|
|
164
|
-
const edgeOffsetInPx = space[edgeOffset] * grid;
|
|
165
|
-
const tooltipLeftToTriggerLeft = triggerPosition.left - tooltipPosition.left - edgeOffsetInPx;
|
|
166
|
-
arrowLeftOffset = tooltipLeftToTriggerLeft + triggerPosition.width / 2;
|
|
167
|
-
}
|
|
168
156
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
169
157
|
children({
|
|
170
158
|
triggerProps: {
|
|
@@ -180,7 +168,6 @@ const TooltipRenderer = ({
|
|
|
180
168
|
{
|
|
181
169
|
id: resolvedId,
|
|
182
170
|
role: "tooltip",
|
|
183
|
-
ref: tooltipRef,
|
|
184
171
|
offsetSpace,
|
|
185
172
|
align: "center",
|
|
186
173
|
placement,
|
|
@@ -189,12 +176,18 @@ const TooltipRenderer = ({
|
|
|
189
176
|
modal: false,
|
|
190
177
|
open: showTooltip,
|
|
191
178
|
onClose: !isStatic ? () => setOpen(false) : void 0,
|
|
179
|
+
onPlacementChange: ({ placement: newPlacement, arrow: arrow2 }) => {
|
|
180
|
+
setResolvedPlacement(newPlacement);
|
|
181
|
+
setArrowPosition(arrow2);
|
|
182
|
+
},
|
|
192
183
|
triggerRef,
|
|
184
|
+
arrowRef,
|
|
193
185
|
children: /* @__PURE__ */ jsx(
|
|
194
186
|
TooltipContent,
|
|
195
187
|
{
|
|
196
|
-
|
|
197
|
-
|
|
188
|
+
placement: resolvedPlacement,
|
|
189
|
+
arrowPosition,
|
|
190
|
+
arrowRef,
|
|
198
191
|
children: tooltip
|
|
199
192
|
}
|
|
200
193
|
)
|
|
@@ -1,37 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const jsxRuntime = require("react/jsx-runtime");
|
|
3
|
-
const
|
|
3
|
+
const reactDom = require("@floating-ui/react-dom");
|
|
4
4
|
const dedent = require("dedent");
|
|
5
5
|
const react = require("react");
|
|
6
|
-
const lib_hooks_useIsomorphicLayoutEffect_cjs = require("../../../hooks/useIsomorphicLayoutEffect.cjs");
|
|
7
6
|
const lib_components_Box_Box_cjs = require("../../Box/Box.cjs");
|
|
8
7
|
const lib_components_BraidPortal_BraidPortal_cjs = require("../../BraidPortal/BraidPortal.cjs");
|
|
8
|
+
const lib_components_useResponsiveValue_useResponsiveValue_cjs = require("../../useResponsiveValue/useResponsiveValue.cjs");
|
|
9
9
|
const lib_components_useSpace_useSpace_cjs = require("../../useSpace/useSpace.cjs");
|
|
10
10
|
const lib_components_private_animationTimeout_cjs = require("../animationTimeout.cjs");
|
|
11
11
|
const lib_components_private_Popover_Popover_css_cjs = require("./Popover.css.cjs");
|
|
12
|
+
const lib_css_atoms_sprinkles_css_cjs = require("../../../css/atoms/sprinkles.css.cjs");
|
|
12
13
|
const _interopDefaultCompat = (e) => e && typeof e === "object" && "default" in e ? e : { default: e };
|
|
13
14
|
const dedent__default = /* @__PURE__ */ _interopDefaultCompat(dedent);
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const positionMap = {
|
|
16
|
+
top: {
|
|
17
|
+
left: "top-start",
|
|
18
|
+
center: "top",
|
|
19
|
+
right: "top-end"
|
|
20
|
+
},
|
|
21
|
+
bottom: {
|
|
22
|
+
left: "bottom-start",
|
|
23
|
+
center: "bottom",
|
|
24
|
+
right: "bottom-end"
|
|
18
25
|
}
|
|
19
|
-
const rect = element.getBoundingClientRect();
|
|
20
|
-
const { top, bottom, left, right, width } = rect;
|
|
21
|
-
const { scrollX: scrollX2, scrollY, innerWidth } = window;
|
|
22
|
-
return {
|
|
23
|
-
// For `top`, we subtract this from the dynamic viewport height in `Popover.css.ts`
|
|
24
|
-
// which can't be accessed from Javascript.
|
|
25
|
-
top: top + scrollY,
|
|
26
|
-
bottom: bottom + scrollY,
|
|
27
|
-
left: left + scrollX2,
|
|
28
|
-
right: innerWidth - right - scrollX2,
|
|
29
|
-
width
|
|
30
|
-
};
|
|
31
26
|
};
|
|
32
|
-
function
|
|
33
|
-
return
|
|
27
|
+
function getFloatingUiPosition(placement, align) {
|
|
28
|
+
return positionMap[placement][align];
|
|
34
29
|
}
|
|
30
|
+
const zIndex = "notification";
|
|
31
|
+
const PopoverContext = react.createContext(null);
|
|
35
32
|
const PopoverContent = react.forwardRef(
|
|
36
33
|
({
|
|
37
34
|
id,
|
|
@@ -45,18 +42,59 @@ const PopoverContent = react.forwardRef(
|
|
|
45
42
|
modal = true,
|
|
46
43
|
open,
|
|
47
44
|
onClose,
|
|
45
|
+
onPlacementChange,
|
|
48
46
|
triggerRef,
|
|
49
47
|
enterFocusRef,
|
|
48
|
+
arrowRef,
|
|
50
49
|
children
|
|
51
50
|
}, forwardedRef) => {
|
|
52
|
-
const [triggerPosition, setTriggerPosition] = react.useState(void 0);
|
|
53
51
|
const ref = react.useRef(null);
|
|
54
52
|
react.useImperativeHandle(forwardedRef, () => ref.current);
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
const
|
|
53
|
+
const normalized = lib_css_atoms_sprinkles_css_cjs.normalizeResponsiveValue(offsetSpace);
|
|
54
|
+
const mobile = normalized.mobile ?? "none";
|
|
55
|
+
const tablet = normalized.tablet ?? mobile;
|
|
56
|
+
const desktop = normalized.desktop ?? tablet;
|
|
57
|
+
const wide = normalized.wide ?? desktop;
|
|
58
|
+
const resolvedOffsetSpace = lib_components_useResponsiveValue_useResponsiveValue_cjs.useResponsiveValue()({ mobile, tablet, desktop, wide }) ?? mobile;
|
|
59
|
+
const spaceScale = lib_components_useSpace_useSpace_cjs.useSpace();
|
|
60
|
+
let offsetSpacePx = 0;
|
|
61
|
+
if (resolvedOffsetSpace !== "none") {
|
|
62
|
+
offsetSpacePx = spaceScale.space[resolvedOffsetSpace] * spaceScale.grid;
|
|
63
|
+
}
|
|
64
|
+
const floatingUiRequestedPosition = getFloatingUiPosition(placement, align);
|
|
65
|
+
const middleware = [
|
|
66
|
+
reactDom.offset(offsetSpacePx),
|
|
67
|
+
!lockPlacement && reactDom.flip(),
|
|
68
|
+
width === "full" ? reactDom.size({
|
|
69
|
+
apply({ rects, elements }) {
|
|
70
|
+
Object.assign(elements.floating.style, {
|
|
71
|
+
width: `${rects.reference.width}px`
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}) : reactDom.shift({
|
|
75
|
+
crossAxis: align === "center"
|
|
76
|
+
}),
|
|
77
|
+
arrowRef && reactDom.arrow({ element: arrowRef })
|
|
78
|
+
].filter(Boolean);
|
|
79
|
+
const {
|
|
80
|
+
refs,
|
|
81
|
+
floatingStyles,
|
|
82
|
+
middlewareData,
|
|
83
|
+
placement: floatingUiEvaluatedPosition,
|
|
84
|
+
isPositioned
|
|
85
|
+
} = reactDom.useFloating({
|
|
86
|
+
placement: floatingUiRequestedPosition,
|
|
87
|
+
middleware,
|
|
88
|
+
whileElementsMounted: reactDom.autoUpdate
|
|
89
|
+
});
|
|
90
|
+
react.useEffect(() => {
|
|
91
|
+
refs.setReference(triggerRef.current);
|
|
92
|
+
}, [triggerRef, refs]);
|
|
93
|
+
react.useEffect(() => {
|
|
94
|
+
if (ref.current) {
|
|
95
|
+
refs.setFloating(ref.current);
|
|
96
|
+
}
|
|
97
|
+
}, [refs]);
|
|
60
98
|
react.useEffect(() => {
|
|
61
99
|
const handleKeydown = (event) => {
|
|
62
100
|
if (event.key === "Escape" || event.key === "Tab") {
|
|
@@ -81,9 +119,6 @@ const PopoverContent = react.forwardRef(
|
|
|
81
119
|
window.removeEventListener("keydown", handleKeydown);
|
|
82
120
|
};
|
|
83
121
|
}, [onClose, triggerRef]);
|
|
84
|
-
react.useEffect(() => {
|
|
85
|
-
setTriggerPosition(getPosition(triggerRef.current));
|
|
86
|
-
}, [triggerRef]);
|
|
87
122
|
react.useEffect(() => {
|
|
88
123
|
setTimeout(() => {
|
|
89
124
|
if (!enterFocusRef) {
|
|
@@ -101,95 +136,24 @@ const PopoverContent = react.forwardRef(
|
|
|
101
136
|
}
|
|
102
137
|
}
|
|
103
138
|
}, lib_components_private_animationTimeout_cjs.animationTimeout);
|
|
104
|
-
}, [open, enterFocusRef
|
|
139
|
+
}, [open, enterFocusRef]);
|
|
140
|
+
const resolvedPlacement = floatingUiEvaluatedPosition?.startsWith("top") ? "top" : "bottom";
|
|
105
141
|
react.useEffect(() => {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
resizeObserver.observe(document.body);
|
|
112
|
-
return () => {
|
|
113
|
-
window.removeEventListener("resize", handleResize);
|
|
114
|
-
resizeObserver.disconnect();
|
|
115
|
-
};
|
|
116
|
-
}, [triggerRef]);
|
|
117
|
-
const handlePlacement = () => {
|
|
118
|
-
const popoverBoundingRect = ref?.current?.getBoundingClientRect();
|
|
119
|
-
if (!popoverBoundingRect) {
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
const triggerBoundingRect = triggerRef.current?.getBoundingClientRect();
|
|
123
|
-
if (!triggerBoundingRect) {
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
const { height: popoverHeight } = popoverBoundingRect;
|
|
127
|
-
const heightRequired = popoverHeight + transitionThresholdInPx;
|
|
128
|
-
const fitsAbove = triggerBoundingRect.top >= heightRequired;
|
|
129
|
-
const fitsBelow = window.innerHeight - triggerBoundingRect.bottom >= heightRequired;
|
|
130
|
-
if (!fitsAbove && fitsBelow) {
|
|
131
|
-
setActualPlacement("bottom");
|
|
132
|
-
} else if (!fitsBelow && fitsAbove) {
|
|
133
|
-
setActualPlacement("top");
|
|
134
|
-
} else {
|
|
135
|
-
setActualPlacement(placement);
|
|
142
|
+
if (onPlacementChange) {
|
|
143
|
+
onPlacementChange({
|
|
144
|
+
placement: resolvedPlacement,
|
|
145
|
+
arrow: middlewareData.arrow
|
|
146
|
+
});
|
|
136
147
|
}
|
|
148
|
+
}, [resolvedPlacement, middlewareData.arrow, onPlacementChange]);
|
|
149
|
+
const combinedStyles = {
|
|
150
|
+
...floatingStyles,
|
|
151
|
+
...!isPositioned ? { opacity: 0, pointerEvents: "none" } : {}
|
|
137
152
|
};
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
const popoverBoundingRect = ref?.current?.getBoundingClientRect();
|
|
143
|
-
if (!popoverBoundingRect) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
const { width: popoverWidth } = popoverBoundingRect;
|
|
147
|
-
const triggerCenter = triggerPosition.width && triggerPosition.left + triggerPosition.width / 2;
|
|
148
|
-
const popoverLeft = align === "center" && triggerCenter ? triggerCenter - popoverWidth / 2 : triggerPosition.left;
|
|
149
|
-
const clampedPopoverLeft = clamp(
|
|
150
|
-
scrollX,
|
|
151
|
-
popoverLeft,
|
|
152
|
-
window.innerWidth + scrollX - popoverWidth
|
|
153
|
-
);
|
|
154
|
-
const triggerRightFromLeft = window.innerWidth - triggerPosition.right;
|
|
155
|
-
const clampedTriggerRightFromLeft = clamp(
|
|
156
|
-
scrollX + popoverWidth,
|
|
157
|
-
triggerRightFromLeft,
|
|
158
|
-
scrollX + window.innerWidth
|
|
159
|
-
);
|
|
160
|
-
if (alignmentAnchor === "right" && clampedTriggerRightFromLeft !== triggerPosition.right + horizontalOffset) {
|
|
161
|
-
setHorizontalOffset(
|
|
162
|
-
window.innerWidth - clampedTriggerRightFromLeft - triggerPosition.right
|
|
163
|
-
);
|
|
164
|
-
}
|
|
165
|
-
if (alignmentAnchor === "left" && clampedPopoverLeft !== triggerPosition.left + horizontalOffset) {
|
|
166
|
-
setHorizontalOffset(clampedPopoverLeft - triggerPosition.left);
|
|
167
|
-
}
|
|
168
|
-
return;
|
|
169
|
-
};
|
|
170
|
-
lib_hooks_useIsomorphicLayoutEffect_cjs.useIsomorphicLayoutEffect(() => {
|
|
171
|
-
if (!showPopover) {
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
if (width !== "full") {
|
|
175
|
-
handleHorizontalShift();
|
|
176
|
-
}
|
|
177
|
-
if (!lockPlacement) {
|
|
178
|
-
handlePlacement();
|
|
179
|
-
}
|
|
180
|
-
}, [showPopover]);
|
|
181
|
-
const triggerPositionVars = triggerPosition && {
|
|
182
|
-
// Vertical positioning
|
|
183
|
-
[lib_components_private_Popover_Popover_css_cjs.triggerVars[actualPlacement]]: `${triggerPosition[actualPlacement]}`,
|
|
184
|
-
// Horizontal positioning
|
|
185
|
-
[lib_components_private_Popover_Popover_css_cjs.triggerVars.left]: width === "full" || alignmentAnchor === "left" ? `${triggerPosition?.left}` : void 0,
|
|
186
|
-
[lib_components_private_Popover_Popover_css_cjs.triggerVars.right]: width === "full" || alignmentAnchor === "right" ? `${triggerPosition?.right}` : void 0,
|
|
187
|
-
// Horizontal scroll offset
|
|
188
|
-
[lib_components_private_Popover_Popover_css_cjs.horizontalOffset]: width !== "full" ? `${horizontalOffset}` : "0"
|
|
153
|
+
const popoverContextValue = {
|
|
154
|
+
arrow: middlewareData.arrow,
|
|
155
|
+
resolvedPlacement
|
|
189
156
|
};
|
|
190
|
-
if (!showPopover) {
|
|
191
|
-
return null;
|
|
192
|
-
}
|
|
193
157
|
return /* @__PURE__ */ jsxRuntime.jsxs(lib_components_BraidPortal_BraidPortal_cjs.BraidPortal, { children: [
|
|
194
158
|
modal && /* @__PURE__ */ jsxRuntime.jsx(
|
|
195
159
|
lib_components_Box_Box_cjs.Box,
|
|
@@ -217,17 +181,18 @@ const PopoverContent = react.forwardRef(
|
|
|
217
181
|
role: role || void 0,
|
|
218
182
|
tabIndex: -1,
|
|
219
183
|
zIndex,
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
184
|
+
style: combinedStyles,
|
|
185
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
186
|
+
lib_components_Box_Box_cjs.Box,
|
|
187
|
+
{
|
|
188
|
+
className: {
|
|
189
|
+
[lib_components_private_Popover_Popover_css_cjs.animation]: true,
|
|
190
|
+
[lib_components_private_Popover_Popover_css_cjs.invertPlacement]: resolvedPlacement === "bottom",
|
|
191
|
+
[lib_components_private_Popover_Popover_css_cjs.delayVisibility]: delayVisibility
|
|
192
|
+
},
|
|
193
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(PopoverContext.Provider, { value: popoverContextValue, children })
|
|
194
|
+
}
|
|
195
|
+
)
|
|
231
196
|
}
|
|
232
197
|
)
|
|
233
198
|
] });
|
|
@@ -9,23 +9,6 @@ const backdrop = css.style({
|
|
|
9
9
|
width: "100vw",
|
|
10
10
|
height: "100vh"
|
|
11
11
|
}, "backdrop");
|
|
12
|
-
const triggerVars = {
|
|
13
|
-
top: css.createVar("triggerVars_top"),
|
|
14
|
-
left: css.createVar("triggerVars_left"),
|
|
15
|
-
bottom: css.createVar("triggerVars_bottom"),
|
|
16
|
-
right: css.createVar("triggerVars_right")
|
|
17
|
-
};
|
|
18
|
-
const horizontalOffset = css.createVar("horizontalOffset");
|
|
19
|
-
const dynamicHeight = css.createVar("dynamicHeight");
|
|
20
|
-
const popoverPosition = css.style({
|
|
21
|
-
vars: {
|
|
22
|
-
[dynamicHeight]: "100svh"
|
|
23
|
-
},
|
|
24
|
-
top: cssUtils.calc(triggerVars.bottom).multiply("1px").toString(),
|
|
25
|
-
bottom: cssUtils.calc(css.fallbackVar(dynamicHeight, "100vh")).subtract(cssUtils.calc(triggerVars.top).multiply("1px")).toString(),
|
|
26
|
-
left: cssUtils.calc(triggerVars.left).add(horizontalOffset).multiply("1px").toString(),
|
|
27
|
-
right: cssUtils.calc(triggerVars.right).add(horizontalOffset).multiply("1px").toString()
|
|
28
|
-
}, "popoverPosition");
|
|
29
12
|
const placementModifier = css.createVar("placementModifier");
|
|
30
13
|
const invertPlacement = css.style({
|
|
31
14
|
vars: {
|
|
@@ -53,8 +36,4 @@ fileScope.endFileScope();
|
|
|
53
36
|
exports.animation = animation;
|
|
54
37
|
exports.backdrop = backdrop;
|
|
55
38
|
exports.delayVisibility = delayVisibility;
|
|
56
|
-
exports.horizontalOffset = horizontalOffset;
|
|
57
39
|
exports.invertPlacement = invertPlacement;
|
|
58
|
-
exports.popoverPosition = popoverPosition;
|
|
59
|
-
exports.transitionThreshold = transitionThreshold;
|
|
60
|
-
exports.triggerVars = triggerVars;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { setFileScope, endFileScope } from "@vanilla-extract/css/fileScope";
|
|
2
|
-
import {
|
|
2
|
+
import { style, keyframes, createVar, fallbackVar } from "@vanilla-extract/css";
|
|
3
3
|
import { calc } from "@vanilla-extract/css-utils";
|
|
4
4
|
import { animationTimeout } from "../animationTimeout.mjs";
|
|
5
5
|
import { vars } from "../../../themes/vars.css.mjs";
|
|
@@ -8,23 +8,6 @@ const backdrop = style({
|
|
|
8
8
|
width: "100vw",
|
|
9
9
|
height: "100vh"
|
|
10
10
|
}, "backdrop");
|
|
11
|
-
const triggerVars = {
|
|
12
|
-
top: createVar("triggerVars_top"),
|
|
13
|
-
left: createVar("triggerVars_left"),
|
|
14
|
-
bottom: createVar("triggerVars_bottom"),
|
|
15
|
-
right: createVar("triggerVars_right")
|
|
16
|
-
};
|
|
17
|
-
const horizontalOffset = createVar("horizontalOffset");
|
|
18
|
-
const dynamicHeight = createVar("dynamicHeight");
|
|
19
|
-
const popoverPosition = style({
|
|
20
|
-
vars: {
|
|
21
|
-
[dynamicHeight]: "100svh"
|
|
22
|
-
},
|
|
23
|
-
top: calc(triggerVars.bottom).multiply("1px").toString(),
|
|
24
|
-
bottom: calc(fallbackVar(dynamicHeight, "100vh")).subtract(calc(triggerVars.top).multiply("1px")).toString(),
|
|
25
|
-
left: calc(triggerVars.left).add(horizontalOffset).multiply("1px").toString(),
|
|
26
|
-
right: calc(triggerVars.right).add(horizontalOffset).multiply("1px").toString()
|
|
27
|
-
}, "popoverPosition");
|
|
28
11
|
const placementModifier = createVar("placementModifier");
|
|
29
12
|
const invertPlacement = style({
|
|
30
13
|
vars: {
|
|
@@ -53,9 +36,5 @@ export {
|
|
|
53
36
|
animation,
|
|
54
37
|
backdrop,
|
|
55
38
|
delayVisibility,
|
|
56
|
-
|
|
57
|
-
invertPlacement,
|
|
58
|
-
popoverPosition,
|
|
59
|
-
transitionThreshold,
|
|
60
|
-
triggerVars
|
|
39
|
+
invertPlacement
|
|
61
40
|
};
|
|
@@ -1,34 +1,31 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { offset, flip, size, shift, arrow, useFloating, autoUpdate } from "@floating-ui/react-dom";
|
|
3
3
|
import dedent from "dedent";
|
|
4
|
-
import { forwardRef,
|
|
5
|
-
import { useIsomorphicLayoutEffect } from "../../../hooks/useIsomorphicLayoutEffect.mjs";
|
|
4
|
+
import { forwardRef, useRef, useImperativeHandle, useEffect, createContext } from "react";
|
|
6
5
|
import { Box } from "../../Box/Box.mjs";
|
|
7
6
|
import { BraidPortal } from "../../BraidPortal/BraidPortal.mjs";
|
|
7
|
+
import { useResponsiveValue } from "../../useResponsiveValue/useResponsiveValue.mjs";
|
|
8
8
|
import { useSpace } from "../../useSpace/useSpace.mjs";
|
|
9
9
|
import { animationTimeout } from "../animationTimeout.mjs";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
import { backdrop, delayVisibility, invertPlacement, animation } from "./Popover.css.mjs";
|
|
11
|
+
import { normalizeResponsiveValue } from "../../../css/atoms/sprinkles.css.mjs";
|
|
12
|
+
const positionMap = {
|
|
13
|
+
top: {
|
|
14
|
+
left: "top-start",
|
|
15
|
+
center: "top",
|
|
16
|
+
right: "top-end"
|
|
17
|
+
},
|
|
18
|
+
bottom: {
|
|
19
|
+
left: "bottom-start",
|
|
20
|
+
center: "bottom",
|
|
21
|
+
right: "bottom-end"
|
|
15
22
|
}
|
|
16
|
-
const rect = element.getBoundingClientRect();
|
|
17
|
-
const { top, bottom, left, right, width } = rect;
|
|
18
|
-
const { scrollX: scrollX2, scrollY, innerWidth } = window;
|
|
19
|
-
return {
|
|
20
|
-
// For `top`, we subtract this from the dynamic viewport height in `Popover.css.ts`
|
|
21
|
-
// which can't be accessed from Javascript.
|
|
22
|
-
top: top + scrollY,
|
|
23
|
-
bottom: bottom + scrollY,
|
|
24
|
-
left: left + scrollX2,
|
|
25
|
-
right: innerWidth - right - scrollX2,
|
|
26
|
-
width
|
|
27
|
-
};
|
|
28
23
|
};
|
|
29
|
-
function
|
|
30
|
-
return
|
|
24
|
+
function getFloatingUiPosition(placement, align) {
|
|
25
|
+
return positionMap[placement][align];
|
|
31
26
|
}
|
|
27
|
+
const zIndex = "notification";
|
|
28
|
+
const PopoverContext = createContext(null);
|
|
32
29
|
const PopoverContent = forwardRef(
|
|
33
30
|
({
|
|
34
31
|
id,
|
|
@@ -42,18 +39,59 @@ const PopoverContent = forwardRef(
|
|
|
42
39
|
modal = true,
|
|
43
40
|
open,
|
|
44
41
|
onClose,
|
|
42
|
+
onPlacementChange,
|
|
45
43
|
triggerRef,
|
|
46
44
|
enterFocusRef,
|
|
45
|
+
arrowRef,
|
|
47
46
|
children
|
|
48
47
|
}, forwardedRef) => {
|
|
49
|
-
const [triggerPosition, setTriggerPosition] = useState(void 0);
|
|
50
48
|
const ref = useRef(null);
|
|
51
49
|
useImperativeHandle(forwardedRef, () => ref.current);
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
const
|
|
50
|
+
const normalized = normalizeResponsiveValue(offsetSpace);
|
|
51
|
+
const mobile = normalized.mobile ?? "none";
|
|
52
|
+
const tablet = normalized.tablet ?? mobile;
|
|
53
|
+
const desktop = normalized.desktop ?? tablet;
|
|
54
|
+
const wide = normalized.wide ?? desktop;
|
|
55
|
+
const resolvedOffsetSpace = useResponsiveValue()({ mobile, tablet, desktop, wide }) ?? mobile;
|
|
56
|
+
const spaceScale = useSpace();
|
|
57
|
+
let offsetSpacePx = 0;
|
|
58
|
+
if (resolvedOffsetSpace !== "none") {
|
|
59
|
+
offsetSpacePx = spaceScale.space[resolvedOffsetSpace] * spaceScale.grid;
|
|
60
|
+
}
|
|
61
|
+
const floatingUiRequestedPosition = getFloatingUiPosition(placement, align);
|
|
62
|
+
const middleware = [
|
|
63
|
+
offset(offsetSpacePx),
|
|
64
|
+
!lockPlacement && flip(),
|
|
65
|
+
width === "full" ? size({
|
|
66
|
+
apply({ rects, elements }) {
|
|
67
|
+
Object.assign(elements.floating.style, {
|
|
68
|
+
width: `${rects.reference.width}px`
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}) : shift({
|
|
72
|
+
crossAxis: align === "center"
|
|
73
|
+
}),
|
|
74
|
+
arrowRef && arrow({ element: arrowRef })
|
|
75
|
+
].filter(Boolean);
|
|
76
|
+
const {
|
|
77
|
+
refs,
|
|
78
|
+
floatingStyles,
|
|
79
|
+
middlewareData,
|
|
80
|
+
placement: floatingUiEvaluatedPosition,
|
|
81
|
+
isPositioned
|
|
82
|
+
} = useFloating({
|
|
83
|
+
placement: floatingUiRequestedPosition,
|
|
84
|
+
middleware,
|
|
85
|
+
whileElementsMounted: autoUpdate
|
|
86
|
+
});
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
refs.setReference(triggerRef.current);
|
|
89
|
+
}, [triggerRef, refs]);
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (ref.current) {
|
|
92
|
+
refs.setFloating(ref.current);
|
|
93
|
+
}
|
|
94
|
+
}, [refs]);
|
|
57
95
|
useEffect(() => {
|
|
58
96
|
const handleKeydown = (event) => {
|
|
59
97
|
if (event.key === "Escape" || event.key === "Tab") {
|
|
@@ -78,9 +116,6 @@ const PopoverContent = forwardRef(
|
|
|
78
116
|
window.removeEventListener("keydown", handleKeydown);
|
|
79
117
|
};
|
|
80
118
|
}, [onClose, triggerRef]);
|
|
81
|
-
useEffect(() => {
|
|
82
|
-
setTriggerPosition(getPosition(triggerRef.current));
|
|
83
|
-
}, [triggerRef]);
|
|
84
119
|
useEffect(() => {
|
|
85
120
|
setTimeout(() => {
|
|
86
121
|
if (!enterFocusRef) {
|
|
@@ -98,95 +133,24 @@ const PopoverContent = forwardRef(
|
|
|
98
133
|
}
|
|
99
134
|
}
|
|
100
135
|
}, animationTimeout);
|
|
101
|
-
}, [open, enterFocusRef
|
|
136
|
+
}, [open, enterFocusRef]);
|
|
137
|
+
const resolvedPlacement = floatingUiEvaluatedPosition?.startsWith("top") ? "top" : "bottom";
|
|
102
138
|
useEffect(() => {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
resizeObserver.observe(document.body);
|
|
109
|
-
return () => {
|
|
110
|
-
window.removeEventListener("resize", handleResize);
|
|
111
|
-
resizeObserver.disconnect();
|
|
112
|
-
};
|
|
113
|
-
}, [triggerRef]);
|
|
114
|
-
const handlePlacement = () => {
|
|
115
|
-
const popoverBoundingRect = ref?.current?.getBoundingClientRect();
|
|
116
|
-
if (!popoverBoundingRect) {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
const triggerBoundingRect = triggerRef.current?.getBoundingClientRect();
|
|
120
|
-
if (!triggerBoundingRect) {
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
const { height: popoverHeight } = popoverBoundingRect;
|
|
124
|
-
const heightRequired = popoverHeight + transitionThresholdInPx;
|
|
125
|
-
const fitsAbove = triggerBoundingRect.top >= heightRequired;
|
|
126
|
-
const fitsBelow = window.innerHeight - triggerBoundingRect.bottom >= heightRequired;
|
|
127
|
-
if (!fitsAbove && fitsBelow) {
|
|
128
|
-
setActualPlacement("bottom");
|
|
129
|
-
} else if (!fitsBelow && fitsAbove) {
|
|
130
|
-
setActualPlacement("top");
|
|
131
|
-
} else {
|
|
132
|
-
setActualPlacement(placement);
|
|
139
|
+
if (onPlacementChange) {
|
|
140
|
+
onPlacementChange({
|
|
141
|
+
placement: resolvedPlacement,
|
|
142
|
+
arrow: middlewareData.arrow
|
|
143
|
+
});
|
|
133
144
|
}
|
|
145
|
+
}, [resolvedPlacement, middlewareData.arrow, onPlacementChange]);
|
|
146
|
+
const combinedStyles = {
|
|
147
|
+
...floatingStyles,
|
|
148
|
+
...!isPositioned ? { opacity: 0, pointerEvents: "none" } : {}
|
|
134
149
|
};
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
const popoverBoundingRect = ref?.current?.getBoundingClientRect();
|
|
140
|
-
if (!popoverBoundingRect) {
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
const { width: popoverWidth } = popoverBoundingRect;
|
|
144
|
-
const triggerCenter = triggerPosition.width && triggerPosition.left + triggerPosition.width / 2;
|
|
145
|
-
const popoverLeft = align === "center" && triggerCenter ? triggerCenter - popoverWidth / 2 : triggerPosition.left;
|
|
146
|
-
const clampedPopoverLeft = clamp(
|
|
147
|
-
scrollX,
|
|
148
|
-
popoverLeft,
|
|
149
|
-
window.innerWidth + scrollX - popoverWidth
|
|
150
|
-
);
|
|
151
|
-
const triggerRightFromLeft = window.innerWidth - triggerPosition.right;
|
|
152
|
-
const clampedTriggerRightFromLeft = clamp(
|
|
153
|
-
scrollX + popoverWidth,
|
|
154
|
-
triggerRightFromLeft,
|
|
155
|
-
scrollX + window.innerWidth
|
|
156
|
-
);
|
|
157
|
-
if (alignmentAnchor === "right" && clampedTriggerRightFromLeft !== triggerPosition.right + horizontalOffset$1) {
|
|
158
|
-
setHorizontalOffset(
|
|
159
|
-
window.innerWidth - clampedTriggerRightFromLeft - triggerPosition.right
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
if (alignmentAnchor === "left" && clampedPopoverLeft !== triggerPosition.left + horizontalOffset$1) {
|
|
163
|
-
setHorizontalOffset(clampedPopoverLeft - triggerPosition.left);
|
|
164
|
-
}
|
|
165
|
-
return;
|
|
166
|
-
};
|
|
167
|
-
useIsomorphicLayoutEffect(() => {
|
|
168
|
-
if (!showPopover) {
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
if (width !== "full") {
|
|
172
|
-
handleHorizontalShift();
|
|
173
|
-
}
|
|
174
|
-
if (!lockPlacement) {
|
|
175
|
-
handlePlacement();
|
|
176
|
-
}
|
|
177
|
-
}, [showPopover]);
|
|
178
|
-
const triggerPositionVars = triggerPosition && {
|
|
179
|
-
// Vertical positioning
|
|
180
|
-
[triggerVars[actualPlacement]]: `${triggerPosition[actualPlacement]}`,
|
|
181
|
-
// Horizontal positioning
|
|
182
|
-
[triggerVars.left]: width === "full" || alignmentAnchor === "left" ? `${triggerPosition?.left}` : void 0,
|
|
183
|
-
[triggerVars.right]: width === "full" || alignmentAnchor === "right" ? `${triggerPosition?.right}` : void 0,
|
|
184
|
-
// Horizontal scroll offset
|
|
185
|
-
[horizontalOffset]: width !== "full" ? `${horizontalOffset$1}` : "0"
|
|
150
|
+
const popoverContextValue = {
|
|
151
|
+
arrow: middlewareData.arrow,
|
|
152
|
+
resolvedPlacement
|
|
186
153
|
};
|
|
187
|
-
if (!showPopover) {
|
|
188
|
-
return null;
|
|
189
|
-
}
|
|
190
154
|
return /* @__PURE__ */ jsxs(BraidPortal, { children: [
|
|
191
155
|
modal && /* @__PURE__ */ jsx(
|
|
192
156
|
Box,
|
|
@@ -214,17 +178,18 @@ const PopoverContent = forwardRef(
|
|
|
214
178
|
role: role || void 0,
|
|
215
179
|
tabIndex: -1,
|
|
216
180
|
zIndex,
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
181
|
+
style: combinedStyles,
|
|
182
|
+
children: /* @__PURE__ */ jsx(
|
|
183
|
+
Box,
|
|
184
|
+
{
|
|
185
|
+
className: {
|
|
186
|
+
[animation]: true,
|
|
187
|
+
[invertPlacement]: resolvedPlacement === "bottom",
|
|
188
|
+
[delayVisibility]: delayVisibility$1
|
|
189
|
+
},
|
|
190
|
+
children: /* @__PURE__ */ jsx(PopoverContext.Provider, { value: popoverContextValue, children })
|
|
191
|
+
}
|
|
192
|
+
)
|
|
228
193
|
}
|
|
229
194
|
)
|
|
230
195
|
] });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "braid-design-system",
|
|
3
|
-
"version": "33.13.0
|
|
3
|
+
"version": "33.13.0",
|
|
4
4
|
"description": "Themeable design system for the SEEK Group",
|
|
5
5
|
"homepage": "https://seek-oss.github.io/braid-design-system/",
|
|
6
6
|
"bugs": {
|
|
@@ -164,6 +164,7 @@
|
|
|
164
164
|
"@capsizecss/core": "^4.1.2",
|
|
165
165
|
"@capsizecss/metrics": "^3.0.0",
|
|
166
166
|
"@capsizecss/vanilla-extract": "^2.0.4",
|
|
167
|
+
"@floating-ui/react-dom": "^2.1.6",
|
|
167
168
|
"@vanilla-extract/css": "^1.9.2",
|
|
168
169
|
"@vanilla-extract/css-utils": "^0.1.3",
|
|
169
170
|
"@vanilla-extract/dynamic": "^2.1.2",
|