tempest-react-sdk 0.65.0 → 0.67.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/dist/auth/create-tempest-auth.cjs +1 -1
- package/dist/auth/create-tempest-auth.cjs.map +1 -1
- package/dist/auth/create-tempest-auth.js +31 -36
- package/dist/auth/create-tempest-auth.js.map +1 -1
- package/dist/components/BottomSheet/BottomSheet.cjs +1 -1
- package/dist/components/BottomSheet/BottomSheet.cjs.map +1 -1
- package/dist/components/BottomSheet/BottomSheet.js +31 -40
- package/dist/components/BottomSheet/BottomSheet.js.map +1 -1
- package/dist/components/Combobox/Combobox.cjs +1 -1
- package/dist/components/Combobox/Combobox.cjs.map +1 -1
- package/dist/components/Combobox/Combobox.js +94 -73
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Combobox/Combobox.module.cjs +1 -1
- package/dist/components/Combobox/Combobox.module.cjs.map +1 -1
- package/dist/components/Combobox/Combobox.module.js +4 -3
- package/dist/components/Combobox/Combobox.module.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.cjs +1 -1
- package/dist/components/ContextMenu/ContextMenu.cjs.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.js +80 -83
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
- package/dist/components/Drawer/Drawer.cjs +1 -1
- package/dist/components/Drawer/Drawer.cjs.map +1 -1
- package/dist/components/Drawer/Drawer.js +43 -46
- package/dist/components/Drawer/Drawer.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.cjs +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.cjs.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.js +129 -105
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.module.cjs +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.module.cjs.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.module.js +12 -11
- package/dist/components/DropdownMenu/DropdownMenu.module.js.map +1 -1
- package/dist/components/HoverCard/HoverCard.cjs +1 -1
- package/dist/components/HoverCard/HoverCard.cjs.map +1 -1
- package/dist/components/HoverCard/HoverCard.js +54 -29
- package/dist/components/HoverCard/HoverCard.js.map +1 -1
- package/dist/components/HoverCard/HoverCard.module.cjs +1 -1
- package/dist/components/HoverCard/HoverCard.module.cjs.map +1 -1
- package/dist/components/HoverCard/HoverCard.module.js +4 -3
- package/dist/components/HoverCard/HoverCard.module.js.map +1 -1
- package/dist/components/Lightbox/Lightbox.cjs +1 -1
- package/dist/components/Lightbox/Lightbox.cjs.map +1 -1
- package/dist/components/Lightbox/Lightbox.js +86 -89
- package/dist/components/Lightbox/Lightbox.js.map +1 -1
- package/dist/components/Menubar/Menubar.cjs +1 -1
- package/dist/components/Menubar/Menubar.cjs.map +1 -1
- package/dist/components/Menubar/Menubar.js +86 -65
- package/dist/components/Menubar/Menubar.js.map +1 -1
- package/dist/components/Menubar/Menubar.module.cjs +1 -1
- package/dist/components/Menubar/Menubar.module.cjs.map +1 -1
- package/dist/components/Menubar/Menubar.module.js +4 -3
- package/dist/components/Menubar/Menubar.module.js.map +1 -1
- package/dist/components/Modal/Modal.cjs +1 -1
- package/dist/components/Modal/Modal.cjs.map +1 -1
- package/dist/components/Modal/Modal.js +44 -51
- package/dist/components/Modal/Modal.js.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.cjs +1 -1
- package/dist/components/MultiSelect/MultiSelect.cjs.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.js +113 -96
- package/dist/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.module.cjs +1 -1
- package/dist/components/MultiSelect/MultiSelect.module.cjs.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.module.js +4 -3
- package/dist/components/MultiSelect/MultiSelect.module.js.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenu.cjs +1 -1
- package/dist/components/NavigationMenu/NavigationMenu.cjs.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenu.js +83 -61
- package/dist/components/NavigationMenu/NavigationMenu.js.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenu.module.cjs +1 -1
- package/dist/components/NavigationMenu/NavigationMenu.module.cjs.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenu.module.js +4 -3
- package/dist/components/NavigationMenu/NavigationMenu.module.js.map +1 -1
- package/dist/components/Popover/Popover.cjs +1 -1
- package/dist/components/Popover/Popover.cjs.map +1 -1
- package/dist/components/Popover/Popover.js +57 -36
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Popover/Popover.module.cjs +1 -1
- package/dist/components/Popover/Popover.module.cjs.map +1 -1
- package/dist/components/Popover/Popover.module.js +7 -6
- package/dist/components/Popover/Popover.module.js.map +1 -1
- package/dist/components/Portal/anchor-position.cjs +2 -0
- package/dist/components/Portal/anchor-position.cjs.map +1 -0
- package/dist/components/Portal/anchor-position.js +99 -0
- package/dist/components/Portal/anchor-position.js.map +1 -0
- package/dist/components/Portal/escape-layer.cjs +2 -0
- package/dist/components/Portal/escape-layer.cjs.map +1 -0
- package/dist/components/Portal/escape-layer.js +30 -0
- package/dist/components/Portal/escape-layer.js.map +1 -0
- package/dist/components/Portal/tab-bridge.cjs +2 -0
- package/dist/components/Portal/tab-bridge.cjs.map +1 -0
- package/dist/components/Portal/tab-bridge.js +39 -0
- package/dist/components/Portal/tab-bridge.js.map +1 -0
- package/dist/components/Tooltip/Tooltip.cjs +1 -1
- package/dist/components/Tooltip/Tooltip.cjs.map +1 -1
- package/dist/components/Tooltip/Tooltip.js +43 -29
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.module.cjs +1 -1
- package/dist/components/Tooltip/Tooltip.module.cjs.map +1 -1
- package/dist/components/Tooltip/Tooltip.module.js +4 -3
- package/dist/components/Tooltip/Tooltip.module.js.map +1 -1
- package/dist/hooks/use-focus-trap.cjs +1 -1
- package/dist/hooks/use-focus-trap.cjs.map +1 -1
- package/dist/hooks/use-focus-trap.js +2 -2
- package/dist/hooks/use-focus-trap.js.map +1 -1
- package/dist/hooks/use-sortable.cjs +1 -1
- package/dist/hooks/use-sortable.cjs.map +1 -1
- package/dist/hooks/use-sortable.js +3 -3
- package/dist/hooks/use-sortable.js.map +1 -1
- package/dist/http/api-client.cjs +1 -1
- package/dist/http/api-client.cjs.map +1 -1
- package/dist/http/api-client.js +87 -85
- package/dist/http/api-client.js.map +1 -1
- package/dist/http/credential-scope.cjs +2 -0
- package/dist/http/credential-scope.cjs.map +1 -0
- package/dist/http/credential-scope.js +23 -0
- package/dist/http/credential-scope.js.map +1 -0
- package/dist/http/describe-api-error.cjs +1 -1
- package/dist/http/describe-api-error.cjs.map +1 -1
- package/dist/http/describe-api-error.js +4 -2
- package/dist/http/describe-api-error.js.map +1 -1
- package/dist/http/resumable-upload.cjs +1 -1
- package/dist/http/resumable-upload.cjs.map +1 -1
- package/dist/http/resumable-upload.js +121 -120
- package/dist/http/resumable-upload.js.map +1 -1
- package/dist/http/upload-with-progress.cjs +1 -1
- package/dist/http/upload-with-progress.cjs.map +1 -1
- package/dist/http/upload-with-progress.js +35 -34
- package/dist/http/upload-with-progress.js.map +1 -1
- package/dist/styles/actions.css +3 -0
- package/dist/styles/advanced.css +1 -0
- package/dist/styles/component/Combobox.css +1 -0
- package/dist/styles/component/DropdownMenu.css +1 -0
- package/dist/styles/component/HoverCard.css +1 -0
- package/dist/styles/component/Menubar.css +1 -0
- package/dist/styles/component/MultiSelect.css +1 -0
- package/dist/styles/component/NavigationMenu.css +1 -0
- package/dist/styles/component/Popover.css +1 -0
- package/dist/styles/component/Tooltip.css +1 -0
- package/dist/styles/forms.css +2 -0
- package/dist/styles/navigation.css +2 -0
- package/dist/styles.css +1 -1
- package/dist/tempest-react-sdk.cjs +1 -1
- package/dist/tempest-react-sdk.d.ts +364 -29
- package/dist/tempest-react-sdk.js +335 -333
- package/dist/utils/absent.cjs +2 -0
- package/dist/utils/absent.cjs.map +1 -0
- package/dist/utils/absent.js +12 -0
- package/dist/utils/absent.js.map +1 -0
- package/dist/utils/format.cjs +1 -1
- package/dist/utils/format.cjs.map +1 -1
- package/dist/utils/format.js +42 -37
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/numbers.cjs +1 -1
- package/dist/utils/numbers.cjs.map +1 -1
- package/dist/utils/numbers.js +14 -12
- package/dist/utils/numbers.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,82 +1,104 @@
|
|
|
1
1
|
import { cn as e } from "../../utils/cn.js";
|
|
2
|
-
import t from "
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { useEscapeLayer as t } from "../Portal/escape-layer.js";
|
|
3
|
+
import { Portal as n } from "../Portal/Portal.js";
|
|
4
|
+
import { useAnchorPosition as r } from "../Portal/anchor-position.js";
|
|
5
|
+
import { usePortalTabOrder as i } from "../Portal/tab-bridge.js";
|
|
6
|
+
import a from "./NavigationMenu.module.js";
|
|
7
|
+
import { useCallback as o, useEffect as s, useId as c, useRef as l, useState as u } from "react";
|
|
8
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
5
9
|
//#region src/components/NavigationMenu/NavigationMenu.tsx
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
var p = 4;
|
|
11
|
+
function m({ items: m, portal: h = !0, className: g, ..._ }) {
|
|
12
|
+
let [v, y] = u(-1), [b, x] = u(-1), S = c(), C = l(null), w = o(() => {
|
|
13
|
+
y(-1), x(-1);
|
|
14
|
+
}, []), T = v === -1 ? b : v, [E, D] = u(null), [O, k] = u(null), A = h && T !== -1, j = r({
|
|
15
|
+
anchor: E,
|
|
16
|
+
floating: O,
|
|
17
|
+
side: "bottom",
|
|
18
|
+
align: "start",
|
|
19
|
+
offset: p,
|
|
20
|
+
enabled: A
|
|
21
|
+
});
|
|
22
|
+
i({
|
|
23
|
+
enabled: A,
|
|
24
|
+
anchor: E,
|
|
25
|
+
panel: O
|
|
26
|
+
}), t(T !== -1, w), s(() => {
|
|
27
|
+
if (T === -1) return;
|
|
12
28
|
let e = (e) => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
_.current && !_.current.contains(e.target) && v();
|
|
29
|
+
let t = e.target;
|
|
30
|
+
C.current?.contains(t) || O?.contains(t) || w();
|
|
16
31
|
};
|
|
17
|
-
return window.addEventListener("
|
|
18
|
-
window.removeEventListener("
|
|
32
|
+
return window.addEventListener("mousedown", e), () => {
|
|
33
|
+
window.removeEventListener("mousedown", e);
|
|
19
34
|
};
|
|
20
|
-
}, [
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
35
|
+
}, [
|
|
36
|
+
T,
|
|
37
|
+
w,
|
|
38
|
+
O
|
|
39
|
+
]);
|
|
40
|
+
let M = (e, t) => {
|
|
41
|
+
let n = () => {
|
|
42
|
+
e.onSelect?.(), w();
|
|
24
43
|
};
|
|
25
|
-
return e.href ? /* @__PURE__ */
|
|
44
|
+
return e.href ? /* @__PURE__ */ d("a", {
|
|
26
45
|
href: e.href,
|
|
27
|
-
role:
|
|
28
|
-
className:
|
|
29
|
-
onClick:
|
|
46
|
+
role: t === "menuitem" ? "menuitem" : void 0,
|
|
47
|
+
className: a.link,
|
|
48
|
+
onClick: n,
|
|
30
49
|
children: e.label
|
|
31
|
-
}) : /* @__PURE__ */
|
|
50
|
+
}) : /* @__PURE__ */ d("button", {
|
|
32
51
|
type: "button",
|
|
33
|
-
role:
|
|
34
|
-
className:
|
|
35
|
-
onClick:
|
|
52
|
+
role: t === "menuitem" ? "menuitem" : void 0,
|
|
53
|
+
className: a.link,
|
|
54
|
+
onClick: n,
|
|
36
55
|
children: e.label
|
|
37
56
|
});
|
|
38
57
|
};
|
|
39
|
-
return /* @__PURE__ */
|
|
40
|
-
ref:
|
|
41
|
-
className: e(
|
|
42
|
-
...
|
|
43
|
-
children: /* @__PURE__ */
|
|
44
|
-
className:
|
|
45
|
-
children:
|
|
46
|
-
if (!(
|
|
47
|
-
className:
|
|
48
|
-
children:
|
|
49
|
-
},
|
|
50
|
-
let
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
return /* @__PURE__ */ d("nav", {
|
|
59
|
+
ref: C,
|
|
60
|
+
className: e(a.root, g),
|
|
61
|
+
..._,
|
|
62
|
+
children: /* @__PURE__ */ d("ul", {
|
|
63
|
+
className: a.list,
|
|
64
|
+
children: m.map((t, r) => {
|
|
65
|
+
if (!(t.children && t.children.length > 0)) return /* @__PURE__ */ d("li", {
|
|
66
|
+
className: a.item,
|
|
67
|
+
children: M(t, "none")
|
|
68
|
+
}, r);
|
|
69
|
+
let i = T === r, o = `${S}-panel-${r}`, s = /* @__PURE__ */ d("ul", {
|
|
70
|
+
ref: k,
|
|
71
|
+
id: o,
|
|
72
|
+
role: "menu",
|
|
73
|
+
className: e(a.panel, h && a.portalled),
|
|
74
|
+
style: j,
|
|
75
|
+
children: t.children.map((e, t) => /* @__PURE__ */ d("li", {
|
|
76
|
+
role: "none",
|
|
77
|
+
className: a.subItem,
|
|
78
|
+
children: M(e, "menuitem")
|
|
79
|
+
}, t))
|
|
80
|
+
});
|
|
81
|
+
return /* @__PURE__ */ f("li", {
|
|
82
|
+
ref: i ? D : void 0,
|
|
83
|
+
className: a.item,
|
|
84
|
+
onMouseEnter: () => x(r),
|
|
85
|
+
onMouseLeave: () => x((e) => e === r ? -1 : e),
|
|
86
|
+
children: [/* @__PURE__ */ d("button", {
|
|
56
87
|
type: "button",
|
|
57
|
-
className:
|
|
88
|
+
className: a.trigger,
|
|
58
89
|
"aria-haspopup": "menu",
|
|
59
|
-
"aria-expanded":
|
|
60
|
-
"aria-controls":
|
|
61
|
-
onClick: () =>
|
|
62
|
-
onFocus: () =>
|
|
63
|
-
children:
|
|
64
|
-
}),
|
|
65
|
-
|
|
66
|
-
role: "menu",
|
|
67
|
-
className: t.panel,
|
|
68
|
-
children: e.children.map((e, n) => /* @__PURE__ */ s("li", {
|
|
69
|
-
role: "none",
|
|
70
|
-
className: t.subItem,
|
|
71
|
-
children: b(e, "menuitem")
|
|
72
|
-
}, n))
|
|
73
|
-
})]
|
|
74
|
-
}, n);
|
|
90
|
+
"aria-expanded": i,
|
|
91
|
+
"aria-controls": o,
|
|
92
|
+
onClick: () => y((e) => e === r ? -1 : r),
|
|
93
|
+
onFocus: () => x(r),
|
|
94
|
+
children: t.label
|
|
95
|
+
}), i && (h ? /* @__PURE__ */ d(n, { children: s }) : s)]
|
|
96
|
+
}, r);
|
|
75
97
|
})
|
|
76
98
|
})
|
|
77
99
|
});
|
|
78
100
|
}
|
|
79
101
|
//#endregion
|
|
80
|
-
export {
|
|
102
|
+
export { m as NavigationMenu };
|
|
81
103
|
|
|
82
104
|
//# sourceMappingURL=NavigationMenu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavigationMenu.js","names":[],"sources":["../../../src/components/NavigationMenu/NavigationMenu.tsx"],"sourcesContent":["/**\n * @tempest-limits function-lines — the body resolves the active item from the\n * current path, owns the open submenu and the hover-intent delay, all of which\n * decide the same highlighted row.\n */\nimport { useCallback, useEffect, useId, useRef, useState } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./NavigationMenu.module.css\";\n\nexport interface NavigationMenuItem {\n /** Visible label for the entry. */\n label: ReactNode;\n /** When set, the entry renders as an anchor. */\n href?: string;\n /** Invoked when the entry is activated (click / Enter). */\n onSelect?: () => void;\n /** Nested entries — presence turns the item into a submenu trigger. */\n children?: NavigationMenuItem[];\n}\n\nexport interface NavigationMenuProps extends HTMLAttributes<HTMLElement> {\n /** Top-level navigation entries. */\n items: NavigationMenuItem[];\n}\n\n/**\n * Horizontal navigation menu with hover/click/focus dropdown submenus.\n *\n * - Top-level items render in a `<nav><ul>`.\n * - Items with `children` open a submenu panel (`role=\"menu\"`) on hover, focus,\n * or click. Only one panel is open at a time.\n * - Closes on outside click, Escape, or selecting a leaf entry.\n *\n * @example\n * <NavigationMenu\n * items={[\n * { label: \"Home\", href: \"/\" },\n * {\n * label: \"Products\",\n * children: [\n * { label: \"Analytics\", href: \"/analytics\" },\n * { label: \"Billing\", onSelect: () => openBilling() },\n * ],\n * },\n * ]}\n * />\n */\nexport function NavigationMenu({ items, className, ...props }: NavigationMenuProps) {\n const [clickedIndex, setClickedIndex] = useState<number>(-1);\n const [hovered, setHovered] = useState<number>(-1);\n const baseId = useId();\n const rootRef = useRef<HTMLElement>(null);\n\n const close = useCallback((): void => {\n setClickedIndex(-1);\n setHovered(-1);\n }, []);\n\n const openIndex = clickedIndex !== -1 ? clickedIndex : hovered;\n\n useEffect(() => {\n if (openIndex === -1) return;\n const onKey = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\") close();\n };\n const onDown = (event: MouseEvent): void => {\n if (rootRef.current && !rootRef.current.contains(event.target as Node)) close();\n };\n window.addEventListener(\"keydown\", onKey);\n window.addEventListener(\"mousedown\", onDown);\n return () => {\n window.removeEventListener(\"keydown\", onKey);\n window.removeEventListener(\"mousedown\", onDown);\n };\n }, [openIndex, close]);\n\n const renderLeaf = (item: NavigationMenuItem, role: \"none\" | \"menuitem\"): ReactNode => {\n const handleClick = (): void => {\n item.onSelect?.();\n close();\n };\n if (item.href) {\n return (\n <a\n href={item.href}\n role={role === \"menuitem\" ? \"menuitem\" : undefined}\n className={styles.link}\n onClick={handleClick}\n >\n {item.label}\n </a>\n );\n }\n return (\n <button\n type=\"button\"\n role={role === \"menuitem\" ? \"menuitem\" : undefined}\n className={styles.link}\n onClick={handleClick}\n >\n {item.label}\n </button>\n );\n };\n\n return (\n <nav ref={rootRef} className={cn(styles.root, className)} {...props}>\n <ul className={styles.list}>\n {items.map((item, index) => {\n const hasChildren = !!item.children && item.children.length > 0;\n if (!hasChildren) {\n return (\n <li key={index} className={styles.item}>\n {renderLeaf(item, \"none\")}\n </li>\n );\n }\n const open = openIndex === index;\n const panelId = `${baseId}-panel-${index}`;\n return (\n <li\n key={index}\n className={styles.item}\n onMouseEnter={() => setHovered(index)}\n onMouseLeave={() => setHovered((prev) => (prev === index ? -1 : prev))}\n >\n <button\n type=\"button\"\n className={styles.trigger}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-controls={panelId}\n onClick={() =>\n setClickedIndex((prev) => (prev === index ? -1 : index))\n }\n onFocus={() => setHovered(index)}\n >\n {item.label}\n </button>\n {open && (\n <ul id={panelId} role=\"menu\" className={styles.panel}>\n {item.children!.map((child, childIndex) => (\n <li key={childIndex} role=\"none\" className={styles.subItem}>\n {renderLeaf(child, \"menuitem\")}\n </li>\n ))}\n </ul>\n )}\n </li>\n );\n })}\n </ul>\n </nav>\n );\n}\n"],"mappings":";;;;;AAgDA,SAAgB,EAAe,EAAE,UAAO,cAAW,GAAG,KAA8B;CAChF,IAAM,CAAC,GAAc,KAAmB,EAAiB,EAAE,GACrD,CAAC,GAAS,KAAc,EAAiB,EAAE,GAC3C,IAAS,EAAM,GACf,IAAU,EAAoB,IAAI,GAElC,IAAQ,QAAwB;EAElC,AADA,EAAgB,EAAE,GAClB,EAAW,EAAE;CACjB,GAAG,CAAC,CAAC,GAEC,IAAY,MAAiB,KAAoB,IAAf;CAExC,QAAgB;EACZ,IAAI,MAAc,IAAI;EACtB,IAAM,KAAS,MAA+B;GAC1C,AAAI,EAAM,QAAQ,YAAU,EAAM;EACtC,GACM,KAAU,MAA4B;GACxC,AAAI,EAAQ,WAAW,CAAC,EAAQ,QAAQ,SAAS,EAAM,MAAc,KAAG,EAAM;EAClF;EAGA,OAFA,OAAO,iBAAiB,WAAW,CAAK,GACxC,OAAO,iBAAiB,aAAa,CAAM,SAC9B;GAET,AADA,OAAO,oBAAoB,WAAW,CAAK,GAC3C,OAAO,oBAAoB,aAAa,CAAM;EAClD;CACJ,GAAG,CAAC,GAAW,CAAK,CAAC;CAErB,IAAM,KAAc,GAA0B,MAAyC;EACnF,IAAM,UAA0B;GAE5B,AADA,EAAK,WAAW,GAChB,EAAM;EACV;EAaA,OAZI,EAAK,OAED,kBAAC,KAAD;GACI,MAAM,EAAK;GACX,MAAM,MAAS,aAAa,aAAa,KAAA;GACzC,WAAW,EAAO;GAClB,SAAS;GAER,UAAA,EAAK;EACP,CAAA,IAIP,kBAAC,UAAD;GACI,MAAK;GACL,MAAM,MAAS,aAAa,aAAa,KAAA;GACzC,WAAW,EAAO;GAClB,SAAS;GAER,UAAA,EAAK;EACF,CAAA;CAEhB;CAEA,OACI,kBAAC,OAAD;EAAK,KAAK;EAAS,WAAW,EAAG,EAAO,MAAM,CAAS;EAAG,GAAI;EAC1D,UAAA,kBAAC,MAAD;GAAI,WAAW,EAAO;GACjB,UAAA,EAAM,KAAK,GAAM,MAAU;IAExB,IAAI,EADkB,EAAK,YAAY,EAAK,SAAS,SAAS,IAE1D,OACI,kBAAC,MAAD;KAAgB,WAAW,EAAO;KAC7B,UAAA,EAAW,GAAM,MAAM;IACxB,GAFK,CAEL;IAGZ,IAAM,IAAO,MAAc,GACrB,IAAU,GAAG,EAAO,SAAS;IACnC,OACI,kBAAC,MAAD;KAEI,WAAW,EAAO;KAClB,oBAAoB,EAAW,CAAK;KACpC,oBAAoB,GAAY,MAAU,MAAS,IAAQ,KAAK,CAAK;KAJzE,UAAA,CAMI,kBAAC,UAAD;MACI,MAAK;MACL,WAAW,EAAO;MAClB,iBAAc;MACd,iBAAe;MACf,iBAAe;MACf,eACI,GAAiB,MAAU,MAAS,IAAQ,KAAK,CAAM;MAE3D,eAAe,EAAW,CAAK;MAE9B,UAAA,EAAK;KACF,CAAA,GACP,KACG,kBAAC,MAAD;MAAI,IAAI;MAAS,MAAK;MAAO,WAAW,EAAO;MAC1C,UAAA,EAAK,SAAU,KAAK,GAAO,MACxB,kBAAC,MAAD;OAAqB,MAAK;OAAO,WAAW,EAAO;OAC9C,UAAA,EAAW,GAAO,UAAU;MAC7B,GAFK,CAEL,CACP;KACD,CAAA,CAER;IA3BK,GAAA,CA2BL;GAEZ,CAAC;EACD,CAAA;CACH,CAAA;AAEb"}
|
|
1
|
+
{"version":3,"file":"NavigationMenu.js","names":[],"sources":["../../../src/components/NavigationMenu/NavigationMenu.tsx"],"sourcesContent":["/**\n * @tempest-limits function-lines — the body resolves the active item from the\n * current path, owns the open submenu and the hover-intent delay, all of which\n * decide the same highlighted row.\n */\nimport { useCallback, useEffect, useId, useRef, useState } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { Portal } from \"@/components/Portal\";\nimport { useAnchorPosition } from \"@/components/Portal/anchor-position\";\nimport { useEscapeLayer } from \"@/components/Portal/escape-layer\";\nimport { usePortalTabOrder } from \"@/components/Portal/tab-bridge\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./NavigationMenu.module.css\";\n\nexport interface NavigationMenuItem {\n /** Visible label for the entry. */\n label: ReactNode;\n /** When set, the entry renders as an anchor. */\n href?: string;\n /** Invoked when the entry is activated (click / Enter). */\n onSelect?: () => void;\n /** Nested entries — presence turns the item into a submenu trigger. */\n children?: NavigationMenuItem[];\n}\n\nexport interface NavigationMenuProps extends HTMLAttributes<HTMLElement> {\n /** Top-level navigation entries. */\n items: NavigationMenuItem[];\n /**\n * Render the open panel in a portal, positioned under its trigger. Default\n * `true`.\n *\n * In flow, an ancestor with `overflow` other than `visible` clips the panel,\n * and the SDK's own `Navbar` is one: its `nav` slot scrolls horizontally, and\n * `overflow-x: auto` forces `overflow-y` to `auto` too — a submenu showed\n * 0% of its panel there (measured in Chrome at 1440 px). In a portal the\n * panel escapes the clip, flips at the viewport edge, stays in the tab order\n * right after its trigger, and follows it on scroll and resize.\n */\n portal?: boolean;\n}\n\n/** Gap between trigger and panel, in px — the in-flow CSS uses the same 4 px. */\nconst PANEL_OFFSET = 4;\n\n/**\n * Horizontal navigation menu with hover/click/focus dropdown submenus.\n *\n * - Top-level items render in a `<nav><ul>`.\n * - Items with `children` open a submenu panel (`role=\"menu\"`) on hover, focus,\n * or click. Only one panel is open at a time.\n * - Closes on outside click, Escape, or selecting a leaf entry.\n *\n * @example\n * <NavigationMenu\n * items={[\n * { label: \"Home\", href: \"/\" },\n * {\n * label: \"Products\",\n * children: [\n * { label: \"Analytics\", href: \"/analytics\" },\n * { label: \"Billing\", onSelect: () => openBilling() },\n * ],\n * },\n * ]}\n * />\n */\nexport function NavigationMenu({ items, portal = true, className, ...props }: NavigationMenuProps) {\n const [clickedIndex, setClickedIndex] = useState<number>(-1);\n const [hovered, setHovered] = useState<number>(-1);\n const baseId = useId();\n const rootRef = useRef<HTMLElement>(null);\n\n const close = useCallback((): void => {\n setClickedIndex(-1);\n setHovered(-1);\n }, []);\n\n const openIndex = clickedIndex !== -1 ? clickedIndex : hovered;\n\n const [anchorNode, setAnchorNode] = useState<HTMLLIElement | null>(null);\n const [panelNode, setPanelNode] = useState<HTMLUListElement | null>(null);\n const floating = portal && openIndex !== -1;\n const floatingStyle = useAnchorPosition({\n anchor: anchorNode,\n floating: panelNode,\n side: \"bottom\",\n align: \"start\",\n offset: PANEL_OFFSET,\n enabled: floating,\n });\n usePortalTabOrder({ enabled: floating, anchor: anchorNode, panel: panelNode });\n\n useEscapeLayer(openIndex !== -1, close);\n\n /**\n * Close on a press outside both the menu and the open panel.\n *\n * The panel is checked on its own because in a portal it is not inside the\n * menu's root: a press on one of its entries would otherwise count as\n * outside, close the panel on `mousedown`, and swallow the entry's click.\n */\n useEffect(() => {\n if (openIndex === -1) return;\n const onDown = (event: MouseEvent): void => {\n const target = event.target as Node;\n if (rootRef.current?.contains(target) || panelNode?.contains(target)) return;\n close();\n };\n window.addEventListener(\"mousedown\", onDown);\n return () => {\n window.removeEventListener(\"mousedown\", onDown);\n };\n }, [openIndex, close, panelNode]);\n\n const renderLeaf = (item: NavigationMenuItem, role: \"none\" | \"menuitem\"): ReactNode => {\n const handleClick = (): void => {\n item.onSelect?.();\n close();\n };\n if (item.href) {\n return (\n <a\n href={item.href}\n role={role === \"menuitem\" ? \"menuitem\" : undefined}\n className={styles.link}\n onClick={handleClick}\n >\n {item.label}\n </a>\n );\n }\n return (\n <button\n type=\"button\"\n role={role === \"menuitem\" ? \"menuitem\" : undefined}\n className={styles.link}\n onClick={handleClick}\n >\n {item.label}\n </button>\n );\n };\n\n return (\n <nav ref={rootRef} className={cn(styles.root, className)} {...props}>\n <ul className={styles.list}>\n {items.map((item, index) => {\n const hasChildren = !!item.children && item.children.length > 0;\n if (!hasChildren) {\n return (\n <li key={index} className={styles.item}>\n {renderLeaf(item, \"none\")}\n </li>\n );\n }\n const open = openIndex === index;\n const panelId = `${baseId}-panel-${index}`;\n const panel = (\n <ul\n ref={setPanelNode}\n id={panelId}\n role=\"menu\"\n className={cn(styles.panel, portal && styles.portalled)}\n style={floatingStyle}\n >\n {item.children!.map((child, childIndex) => (\n <li key={childIndex} role=\"none\" className={styles.subItem}>\n {renderLeaf(child, \"menuitem\")}\n </li>\n ))}\n </ul>\n );\n return (\n <li\n key={index}\n ref={open ? setAnchorNode : undefined}\n className={styles.item}\n onMouseEnter={() => setHovered(index)}\n onMouseLeave={() => setHovered((prev) => (prev === index ? -1 : prev))}\n >\n <button\n type=\"button\"\n className={styles.trigger}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-controls={panelId}\n onClick={() =>\n setClickedIndex((prev) => (prev === index ? -1 : index))\n }\n onFocus={() => setHovered(index)}\n >\n {item.label}\n </button>\n {open && (portal ? <Portal>{panel}</Portal> : panel)}\n </li>\n );\n })}\n </ul>\n </nav>\n );\n}\n"],"mappings":";;;;;;;;;AA2CA,IAAM,IAAe;AAwBrB,SAAgB,EAAe,EAAE,UAAO,YAAS,IAAM,cAAW,GAAG,KAA8B;CAC/F,IAAM,CAAC,GAAc,KAAmB,EAAiB,EAAE,GACrD,CAAC,GAAS,KAAc,EAAiB,EAAE,GAC3C,IAAS,EAAM,GACf,IAAU,EAAoB,IAAI,GAElC,IAAQ,QAAwB;EAElC,AADA,EAAgB,EAAE,GAClB,EAAW,EAAE;CACjB,GAAG,CAAC,CAAC,GAEC,IAAY,MAAiB,KAAoB,IAAf,GAElC,CAAC,GAAY,KAAiB,EAA+B,IAAI,GACjE,CAAC,GAAW,KAAgB,EAAkC,IAAI,GAClE,IAAW,KAAU,MAAc,IACnC,IAAgB,EAAkB;EACpC,QAAQ;EACR,UAAU;EACV,MAAM;EACN,OAAO;EACP,QAAQ;EACR,SAAS;CACb,CAAC;CAYD,AAXA,EAAkB;EAAE,SAAS;EAAU,QAAQ;EAAY,OAAO;CAAU,CAAC,GAE7E,EAAe,MAAc,IAAI,CAAK,GAStC,QAAgB;EACZ,IAAI,MAAc,IAAI;EACtB,IAAM,KAAU,MAA4B;GACxC,IAAM,IAAS,EAAM;GACjB,EAAQ,SAAS,SAAS,CAAM,KAAK,GAAW,SAAS,CAAM,KACnE,EAAM;EACV;EAEA,OADA,OAAO,iBAAiB,aAAa,CAAM,SAC9B;GACT,OAAO,oBAAoB,aAAa,CAAM;EAClD;CACJ,GAAG;EAAC;EAAW;EAAO;CAAS,CAAC;CAEhC,IAAM,KAAc,GAA0B,MAAyC;EACnF,IAAM,UAA0B;GAE5B,AADA,EAAK,WAAW,GAChB,EAAM;EACV;EAaA,OAZI,EAAK,OAED,kBAAC,KAAD;GACI,MAAM,EAAK;GACX,MAAM,MAAS,aAAa,aAAa,KAAA;GACzC,WAAW,EAAO;GAClB,SAAS;GAER,UAAA,EAAK;EACP,CAAA,IAIP,kBAAC,UAAD;GACI,MAAK;GACL,MAAM,MAAS,aAAa,aAAa,KAAA;GACzC,WAAW,EAAO;GAClB,SAAS;GAER,UAAA,EAAK;EACF,CAAA;CAEhB;CAEA,OACI,kBAAC,OAAD;EAAK,KAAK;EAAS,WAAW,EAAG,EAAO,MAAM,CAAS;EAAG,GAAI;EAC1D,UAAA,kBAAC,MAAD;GAAI,WAAW,EAAO;GACjB,UAAA,EAAM,KAAK,GAAM,MAAU;IAExB,IAAI,EADkB,EAAK,YAAY,EAAK,SAAS,SAAS,IAE1D,OACI,kBAAC,MAAD;KAAgB,WAAW,EAAO;KAC7B,UAAA,EAAW,GAAM,MAAM;IACxB,GAFK,CAEL;IAGZ,IAAM,IAAO,MAAc,GACrB,IAAU,GAAG,EAAO,SAAS,KAC7B,IACF,kBAAC,MAAD;KACI,KAAK;KACL,IAAI;KACJ,MAAK;KACL,WAAW,EAAG,EAAO,OAAO,KAAU,EAAO,SAAS;KACtD,OAAO;KAEN,UAAA,EAAK,SAAU,KAAK,GAAO,MACxB,kBAAC,MAAD;MAAqB,MAAK;MAAO,WAAW,EAAO;MAC9C,UAAA,EAAW,GAAO,UAAU;KAC7B,GAFK,CAEL,CACP;IACD,CAAA;IAER,OACI,kBAAC,MAAD;KAEI,KAAK,IAAO,IAAgB,KAAA;KAC5B,WAAW,EAAO;KAClB,oBAAoB,EAAW,CAAK;KACpC,oBAAoB,GAAY,MAAU,MAAS,IAAQ,KAAK,CAAK;KALzE,UAAA,CAOI,kBAAC,UAAD;MACI,MAAK;MACL,WAAW,EAAO;MAClB,iBAAc;MACd,iBAAe;MACf,iBAAe;MACf,eACI,GAAiB,MAAU,MAAS,IAAQ,KAAK,CAAM;MAE3D,eAAe,EAAW,CAAK;MAE9B,UAAA,EAAK;KACF,CAAA,GACP,MAAS,IAAS,kBAAC,GAAD,EAAA,UAAS,EAAc,CAAA,IAAI,EAC9C;IApBK,GAAA,CAoBL;GAEZ,CAAC;EACD,CAAA;CACH,CAAA;AAEb"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
require("../../styles/component/NavigationMenu.css");
|
|
2
|
-
var e=`tempest_root_Nosqs`,t=`tempest_list_v9FNC`,n=`tempest_item_9RzZ7`,r=`tempest_link_67ULr`,i=`tempest_trigger_2gBDu`,a=`tempest_panel_N2ujp`,o=`tempest_tempest-nav-menu-in_8tNCR`,s=`tempest_subItem_LjtO7`,c={root:e,list:t,item:n,link:r,trigger:i,panel:a,tempestNavMenuIn:o,subItem:s};exports.default=
|
|
2
|
+
var e=`tempest_root_Nosqs`,t=`tempest_list_v9FNC`,n=`tempest_item_9RzZ7`,r=`tempest_link_67ULr`,i=`tempest_trigger_2gBDu`,a=`tempest_panel_N2ujp`,o=`tempest_tempest-nav-menu-in_8tNCR`,s=`tempest_subItem_LjtO7`,c=`tempest_portalled_2V2JB`,l={root:e,list:t,item:n,link:r,trigger:i,panel:a,tempestNavMenuIn:o,subItem:s,portalled:c};exports.default=l,exports.item=n,exports.link=r,exports.list=t,exports.panel=a,exports.portalled=c,exports.root=e,exports.subItem=s,exports.tempestNavMenuIn=o,exports.trigger=i;
|
|
3
3
|
//# sourceMappingURL=NavigationMenu.module.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavigationMenu.module.cjs","names":[],"sources":["../../../src/components/NavigationMenu/NavigationMenu.module.css"],"sourcesContent":[".root {\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n}\n\n.list {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-1);\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.item {\n position: relative;\n}\n\n.link,\n.trigger {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-1);\n padding: var(--tempest-space-2) var(--tempest-space-3);\n background: none;\n border: none;\n border-radius: var(--tempest-radius-sm);\n color: var(--tempest-text);\n font-family: inherit;\n font-size: inherit;\n line-height: var(--tempest-leading-snug);\n text-align: left;\n text-decoration: none;\n cursor: pointer;\n transition: var(--tempest-transition-color);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .link:hover,\n .trigger:hover {\n background-color: var(--tempest-surface);\n }\n}\n\n.link:focus-visible,\n.trigger:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.panel {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n z-index: var(--tempest-z-dropdown);\n min-width: 180px;\n max-width: 320px;\n background-color: var(--tempest-bg);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n box-shadow: var(--tempest-shadow-lg);\n padding: var(--tempest-space-1);\n list-style: none;\n margin: 0;\n animation: tempest-nav-menu-in var(--tempest-duration-fast) var(--tempest-ease-out);\n}\n\n.subItem {\n display: block;\n}\n\n.subItem .link {\n width: 100%;\n}\n\n@keyframes tempest-nav-menu-in {\n from {\n opacity: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .panel {\n animation: none;\n }\n}\n"],"mappings":";"}
|
|
1
|
+
{"version":3,"file":"NavigationMenu.module.cjs","names":[],"sources":["../../../src/components/NavigationMenu/NavigationMenu.module.css"],"sourcesContent":[".root {\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n}\n\n.list {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-1);\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.item {\n position: relative;\n}\n\n.link,\n.trigger {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-1);\n padding: var(--tempest-space-2) var(--tempest-space-3);\n background: none;\n border: none;\n border-radius: var(--tempest-radius-sm);\n color: var(--tempest-text);\n font-family: inherit;\n font-size: inherit;\n line-height: var(--tempest-leading-snug);\n text-align: left;\n text-decoration: none;\n cursor: pointer;\n transition: var(--tempest-transition-color);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .link:hover,\n .trigger:hover {\n background-color: var(--tempest-surface);\n }\n}\n\n.link:focus-visible,\n.trigger:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.panel {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n z-index: var(--tempest-z-dropdown);\n min-width: 180px;\n max-width: 320px;\n background-color: var(--tempest-bg);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n box-shadow: var(--tempest-shadow-lg);\n padding: var(--tempest-space-1);\n list-style: none;\n margin: 0;\n animation: tempest-nav-menu-in var(--tempest-duration-fast) var(--tempest-ease-out);\n}\n\n.subItem {\n display: block;\n}\n\n.subItem .link {\n width: 100%;\n}\n\n@keyframes tempest-nav-menu-in {\n from {\n opacity: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .panel {\n animation: none;\n }\n}\n\n.portalled {\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n z-index: var(--tempest-z-popover);\n}\n"],"mappings":";"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../../styles/component/NavigationMenu.css";
|
|
2
2
|
//#region src/components/NavigationMenu/NavigationMenu.module.css
|
|
3
|
-
var e = "tempest_root_Nosqs", t = "tempest_list_v9FNC", n = "tempest_item_9RzZ7", r = "tempest_link_67ULr", i = "tempest_trigger_2gBDu", a = "tempest_panel_N2ujp", o = "tempest_tempest-nav-menu-in_8tNCR", s = "tempest_subItem_LjtO7", c = {
|
|
3
|
+
var e = "tempest_root_Nosqs", t = "tempest_list_v9FNC", n = "tempest_item_9RzZ7", r = "tempest_link_67ULr", i = "tempest_trigger_2gBDu", a = "tempest_panel_N2ujp", o = "tempest_tempest-nav-menu-in_8tNCR", s = "tempest_subItem_LjtO7", c = "tempest_portalled_2V2JB", l = {
|
|
4
4
|
root: e,
|
|
5
5
|
list: t,
|
|
6
6
|
item: n,
|
|
@@ -8,9 +8,10 @@ var e = "tempest_root_Nosqs", t = "tempest_list_v9FNC", n = "tempest_item_9RzZ7"
|
|
|
8
8
|
trigger: i,
|
|
9
9
|
panel: a,
|
|
10
10
|
tempestNavMenuIn: o,
|
|
11
|
-
subItem: s
|
|
11
|
+
subItem: s,
|
|
12
|
+
portalled: c
|
|
12
13
|
};
|
|
13
14
|
//#endregion
|
|
14
|
-
export {
|
|
15
|
+
export { l as default, n as item, r as link, t as list, a as panel, c as portalled, e as root, s as subItem, o as tempestNavMenuIn, i as trigger };
|
|
15
16
|
|
|
16
17
|
//# sourceMappingURL=NavigationMenu.module.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavigationMenu.module.js","names":[],"sources":["../../../src/components/NavigationMenu/NavigationMenu.module.css"],"sourcesContent":[".root {\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n}\n\n.list {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-1);\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.item {\n position: relative;\n}\n\n.link,\n.trigger {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-1);\n padding: var(--tempest-space-2) var(--tempest-space-3);\n background: none;\n border: none;\n border-radius: var(--tempest-radius-sm);\n color: var(--tempest-text);\n font-family: inherit;\n font-size: inherit;\n line-height: var(--tempest-leading-snug);\n text-align: left;\n text-decoration: none;\n cursor: pointer;\n transition: var(--tempest-transition-color);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .link:hover,\n .trigger:hover {\n background-color: var(--tempest-surface);\n }\n}\n\n.link:focus-visible,\n.trigger:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.panel {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n z-index: var(--tempest-z-dropdown);\n min-width: 180px;\n max-width: 320px;\n background-color: var(--tempest-bg);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n box-shadow: var(--tempest-shadow-lg);\n padding: var(--tempest-space-1);\n list-style: none;\n margin: 0;\n animation: tempest-nav-menu-in var(--tempest-duration-fast) var(--tempest-ease-out);\n}\n\n.subItem {\n display: block;\n}\n\n.subItem .link {\n width: 100%;\n}\n\n@keyframes tempest-nav-menu-in {\n from {\n opacity: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .panel {\n animation: none;\n }\n}\n"],"mappings":";"}
|
|
1
|
+
{"version":3,"file":"NavigationMenu.module.js","names":[],"sources":["../../../src/components/NavigationMenu/NavigationMenu.module.css"],"sourcesContent":[".root {\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n}\n\n.list {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-1);\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.item {\n position: relative;\n}\n\n.link,\n.trigger {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-1);\n padding: var(--tempest-space-2) var(--tempest-space-3);\n background: none;\n border: none;\n border-radius: var(--tempest-radius-sm);\n color: var(--tempest-text);\n font-family: inherit;\n font-size: inherit;\n line-height: var(--tempest-leading-snug);\n text-align: left;\n text-decoration: none;\n cursor: pointer;\n transition: var(--tempest-transition-color);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .link:hover,\n .trigger:hover {\n background-color: var(--tempest-surface);\n }\n}\n\n.link:focus-visible,\n.trigger:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.panel {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n z-index: var(--tempest-z-dropdown);\n min-width: 180px;\n max-width: 320px;\n background-color: var(--tempest-bg);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n box-shadow: var(--tempest-shadow-lg);\n padding: var(--tempest-space-1);\n list-style: none;\n margin: 0;\n animation: tempest-nav-menu-in var(--tempest-duration-fast) var(--tempest-ease-out);\n}\n\n.subItem {\n display: block;\n}\n\n.subItem .link {\n width: 100%;\n}\n\n@keyframes tempest-nav-menu-in {\n from {\n opacity: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .panel {\n animation: none;\n }\n}\n\n.portalled {\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n z-index: var(--tempest-z-popover);\n}\n"],"mappings":";"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../../utils/cn.cjs"),t=require("./Popover.module.cjs");let
|
|
1
|
+
const e=require("../../utils/cn.cjs"),t=require("../Portal/escape-layer.cjs"),n=require("../Portal/Portal.cjs"),r=require("../Portal/anchor-position.cjs"),i=require("../Portal/tab-bridge.cjs"),a=require("./Popover.module.cjs");let o=require("react"),s=require("react/jsx-runtime");var c=8;function l({trigger:l,children:u,placement:d=`bottom`,portal:f=!0,open:p,onOpenChange:m,defaultOpen:h=!1,closeOnEsc:g=!0,closeOnOutsideClick:_=!0,className:v}){let y=p!==void 0,[b,x]=(0,o.useState)(h),S=y?p:b,C=(0,o.useId)(),[w,T]=(0,o.useState)(null),[E,D]=(0,o.useState)(null),O=r.useAnchorPosition({anchor:w,floating:E,side:d,align:`center`,offset:c,enabled:f&&S});i.usePortalTabOrder({enabled:f&&S,anchor:w,panel:E});let k=(0,o.useCallback)(e=>{y||x(e),m?.(e)},[y,m]);t.useEscapeLayer(S&&g,()=>k(!1)),(0,o.useEffect)(()=>{if(!S)return;let e=e=>{if(!_)return;let t=e.target;w?.contains(t)||E?.contains(t)||k(!1)};return window.addEventListener(`mousedown`,e),()=>{window.removeEventListener(`mousedown`,e)}},[S,_,k,w,E]);let A=e=>{l.props.onClick?.(e),k(!S)},j={...l,props:{...l.props,onClick:A,"aria-expanded":S,"aria-controls":C}},M=(0,s.jsx)(`div`,{ref:D,id:C,role:`dialog`,className:e.cn(a.default.popover,f?a.default.portalled:a.default[d],v),style:O,children:u});return(0,s.jsxs)(`span`,{ref:T,className:a.default.root,children:[j,S&&(f?(0,s.jsx)(n.Portal,{children:M}):M)]})}exports.Popover=l;
|
|
2
2
|
//# sourceMappingURL=Popover.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.cjs","names":[],"sources":["../../../src/components/Popover/Popover.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — trigger and children are the two halves, placement\n * is where it lands, and open/onOpenChange/defaultOpen is the standard controlled-\n * or-not pair. closeOnEsc and closeOnOutsideClick are separate because a popover\n * holding a form wants one and not the other.\n */\nimport { useCallback, useEffect, useId,
|
|
1
|
+
{"version":3,"file":"Popover.cjs","names":[],"sources":["../../../src/components/Popover/Popover.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — trigger and children are the two halves, placement\n * is where it lands, portal is whether it escapes the tree, and open/onOpenChange/defaultOpen is the standard controlled-\n * or-not pair. closeOnEsc and closeOnOutsideClick are separate because a popover\n * holding a form wants one and not the other.\n */\nimport { useCallback, useEffect, useId, useState } from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport { Portal } from \"@/components/Portal\";\nimport { useAnchorPosition } from \"@/components/Portal/anchor-position\";\nimport { useEscapeLayer } from \"@/components/Portal/escape-layer\";\nimport { usePortalTabOrder } from \"@/components/Portal/tab-bridge\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Popover.module.css\";\n\nexport type PopoverPlacement = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nexport interface PopoverProps {\n /** Trigger element. Receives `onClick`/`aria-expanded`/`aria-controls`. */\n trigger: ReactElement<{\n onClick?: (e: React.MouseEvent) => void;\n \"aria-expanded\"?: boolean;\n \"aria-controls\"?: string;\n }>;\n children: ReactNode;\n placement?: PopoverPlacement;\n /**\n * Render the panel in a portal, positioned against the trigger. Default `true`.\n *\n * In flow, any ancestor with `overflow` other than `visible` clips the panel —\n * inside a `DataTable` cell only 3% of it was visible (measured in Chrome at\n * 1440 px). In a portal it escapes the clip, flips to the opposite side when\n * the requested one has no room, and follows the trigger on scroll and resize.\n * `false` keeps the in-flow panel.\n */\n portal?: boolean;\n /** Controlled open state. */\n open?: boolean;\n /** Called when the user toggles or dismisses. */\n onOpenChange?: (open: boolean) => void;\n /** Default open state for uncontrolled usage. */\n defaultOpen?: boolean;\n /** Close on Escape. Default true. */\n closeOnEsc?: boolean;\n /** Close on outside click. Default true. */\n closeOnOutsideClick?: boolean;\n className?: string;\n}\n\n/** Gap between trigger and panel, in px — the in-flow CSS uses the same 8 px. */\nconst POPOVER_OFFSET = 8;\n\n/**\n * Lightweight popover. Renders a panel anchored to a trigger, dismissed on\n * outside click / Escape.\n *\n * Portalled by default, with viewport-aware placement: the panel flips to the\n * opposite side when the requested one overflows, and is clamped inside the\n * viewport otherwise.\n */\nexport function Popover({\n trigger,\n children,\n placement = \"bottom\",\n portal = true,\n open,\n onOpenChange,\n defaultOpen = false,\n closeOnEsc = true,\n closeOnOutsideClick = true,\n className,\n}: PopoverProps) {\n const isControlled = open !== undefined;\n const [internalOpen, setInternalOpen] = useState<boolean>(defaultOpen);\n const isOpen = isControlled ? open : internalOpen;\n const id = useId();\n const [rootNode, setRootNode] = useState<HTMLSpanElement | null>(null);\n const [panelNode, setPanelNode] = useState<HTMLDivElement | null>(null);\n const floatingStyle = useAnchorPosition({\n anchor: rootNode,\n floating: panelNode,\n side: placement,\n align: \"center\",\n offset: POPOVER_OFFSET,\n enabled: portal && isOpen,\n });\n usePortalTabOrder({ enabled: portal && isOpen, anchor: rootNode, panel: panelNode });\n\n const setOpen = useCallback(\n (next: boolean): void => {\n if (!isControlled) setInternalOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n useEscapeLayer(isOpen && closeOnEsc, () => setOpen(false));\n\n /**\n * Dismiss on a press outside both trigger and panel.\n *\n * The panel is checked on its own because in a portal it is not inside the\n * trigger's wrapper, and a press inside it — on a form field, say — would\n * otherwise count as outside.\n */\n useEffect(() => {\n if (!isOpen) return;\n const onDown = (event: MouseEvent): void => {\n if (!closeOnOutsideClick) return;\n const target = event.target as Node;\n if (rootNode?.contains(target) || panelNode?.contains(target)) return;\n setOpen(false);\n };\n window.addEventListener(\"mousedown\", onDown);\n return () => {\n window.removeEventListener(\"mousedown\", onDown);\n };\n }, [isOpen, closeOnOutsideClick, setOpen, rootNode, panelNode]);\n\n const handleTriggerClick = (event: React.MouseEvent): void => {\n trigger.props.onClick?.(event);\n setOpen(!isOpen);\n };\n\n const triggerClone = {\n ...trigger,\n props: {\n ...trigger.props,\n onClick: handleTriggerClick,\n \"aria-expanded\": isOpen,\n \"aria-controls\": id,\n },\n } as ReactElement;\n\n const panel = (\n <div\n ref={setPanelNode}\n id={id}\n role=\"dialog\"\n className={cn(styles.popover, portal ? styles.portalled : styles[placement], className)}\n style={floatingStyle}\n >\n {children}\n </div>\n );\n\n return (\n <span ref={setRootNode} className={styles.root}>\n {triggerClone}\n {isOpen && (portal ? <Portal>{panel}</Portal> : panel)}\n </span>\n );\n}\n"],"mappings":"yRAkDA,IAAM,EAAiB,EAUvB,SAAgB,EAAQ,CACpB,UACA,WACA,YAAY,SACZ,SAAS,GACT,OACA,eACA,cAAc,GACd,aAAa,GACb,sBAAsB,GACtB,aACa,CACb,IAAM,EAAe,IAAS,IAAA,GACxB,CAAC,EAAc,IAAA,EAAmB,EAAA,SAAA,CAAkB,CAAW,EAC/D,EAAS,EAAe,EAAO,EAC/B,GAAA,EAAK,EAAA,MAAA,CAAM,EACX,CAAC,EAAU,IAAA,EAAe,EAAA,SAAA,CAAiC,IAAI,EAC/D,CAAC,EAAW,IAAA,EAAgB,EAAA,SAAA,CAAgC,IAAI,EAChE,EAAgB,EAAA,kBAAkB,CACpC,OAAQ,EACR,SAAU,EACV,KAAM,EACN,MAAO,SACP,OAAQ,EACR,QAAS,GAAU,CACvB,CAAC,EACD,EAAA,kBAAkB,CAAE,QAAS,GAAU,EAAQ,OAAQ,EAAU,MAAO,CAAU,CAAC,EAEnF,IAAM,GAAA,EAAU,EAAA,YAAA,CACX,GAAwB,CAChB,GAAc,EAAgB,CAAI,EACvC,IAAe,CAAI,CACvB,EACA,CAAC,EAAc,CAAY,CAC/B,EAEA,EAAA,eAAe,GAAU,MAAkB,EAAQ,EAAK,CAAC,GASzD,EAAA,EAAA,UAAA,KAAgB,CACZ,GAAI,CAAC,EAAQ,OACb,IAAM,EAAU,GAA4B,CACxC,GAAI,CAAC,EAAqB,OAC1B,IAAM,EAAS,EAAM,OACjB,GAAU,SAAS,CAAM,GAAK,GAAW,SAAS,CAAM,GAC5D,EAAQ,EAAK,CACjB,EAEA,OADA,OAAO,iBAAiB,YAAa,CAAM,MAC9B,CACT,OAAO,oBAAoB,YAAa,CAAM,CAClD,CACJ,EAAG,CAAC,EAAQ,EAAqB,EAAS,EAAU,CAAS,CAAC,EAE9D,IAAM,EAAsB,GAAkC,CAC1D,EAAQ,MAAM,UAAU,CAAK,EAC7B,EAAQ,CAAC,CAAM,CACnB,EAEM,EAAe,CACjB,GAAG,EACH,MAAO,CACH,GAAG,EAAQ,MACX,QAAS,EACT,gBAAiB,EACjB,gBAAiB,CACrB,CACJ,EAEM,GACF,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,IAAK,EACD,KACJ,KAAK,SACL,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,EAAS,EAAA,QAAO,UAAY,EAAA,QAAO,GAAY,CAAS,EACtF,MAAO,EAEN,UACA,CAAA,EAGT,OACI,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,IAAK,EAAa,UAAW,EAAA,QAAO,KAA1C,SAAA,CACK,EACA,IAAW,GAAS,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CAAA,SAAS,CAAc,CAAA,EAAI,EAC9C,GAEd"}
|
|
@@ -1,51 +1,72 @@
|
|
|
1
1
|
import { cn as e } from "../../utils/cn.js";
|
|
2
|
-
import t from "
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { useEscapeLayer as t } from "../Portal/escape-layer.js";
|
|
3
|
+
import { Portal as n } from "../Portal/Portal.js";
|
|
4
|
+
import { useAnchorPosition as r } from "../Portal/anchor-position.js";
|
|
5
|
+
import { usePortalTabOrder as i } from "../Portal/tab-bridge.js";
|
|
6
|
+
import a from "./Popover.module.js";
|
|
7
|
+
import { useCallback as o, useEffect as s, useId as c, useState as l } from "react";
|
|
8
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
5
9
|
//#region src/components/Popover/Popover.tsx
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
var f = 8;
|
|
11
|
+
function p({ trigger: p, children: m, placement: h = "bottom", portal: g = !0, open: _, onOpenChange: v, defaultOpen: y = !1, closeOnEsc: b = !0, closeOnOutsideClick: x = !0, className: S }) {
|
|
12
|
+
let C = _ !== void 0, [w, T] = l(y), E = C ? _ : w, D = c(), [O, k] = l(null), [A, j] = l(null), M = r({
|
|
13
|
+
anchor: O,
|
|
14
|
+
floating: A,
|
|
15
|
+
side: h,
|
|
16
|
+
align: "center",
|
|
17
|
+
offset: f,
|
|
18
|
+
enabled: g && E
|
|
19
|
+
});
|
|
20
|
+
i({
|
|
21
|
+
enabled: g && E,
|
|
22
|
+
anchor: O,
|
|
23
|
+
panel: A
|
|
24
|
+
});
|
|
25
|
+
let N = o((e) => {
|
|
26
|
+
C || T(e), v?.(e);
|
|
27
|
+
}, [C, v]);
|
|
28
|
+
t(E && b, () => N(!1)), s(() => {
|
|
29
|
+
if (!E) return;
|
|
12
30
|
let e = (e) => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
31
|
+
if (!x) return;
|
|
32
|
+
let t = e.target;
|
|
33
|
+
O?.contains(t) || A?.contains(t) || N(!1);
|
|
16
34
|
};
|
|
17
|
-
return window.addEventListener("
|
|
18
|
-
window.removeEventListener("
|
|
35
|
+
return window.addEventListener("mousedown", e), () => {
|
|
36
|
+
window.removeEventListener("mousedown", e);
|
|
19
37
|
};
|
|
20
38
|
}, [
|
|
39
|
+
E,
|
|
21
40
|
x,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
41
|
+
N,
|
|
42
|
+
O,
|
|
43
|
+
A
|
|
25
44
|
]);
|
|
26
|
-
let
|
|
27
|
-
|
|
28
|
-
},
|
|
29
|
-
...
|
|
45
|
+
let P = (e) => {
|
|
46
|
+
p.props.onClick?.(e), N(!E);
|
|
47
|
+
}, F = {
|
|
48
|
+
...p,
|
|
30
49
|
props: {
|
|
31
|
-
...
|
|
32
|
-
onClick:
|
|
33
|
-
"aria-expanded":
|
|
34
|
-
"aria-controls":
|
|
50
|
+
...p.props,
|
|
51
|
+
onClick: P,
|
|
52
|
+
"aria-expanded": E,
|
|
53
|
+
"aria-controls": D
|
|
35
54
|
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
55
|
+
}, I = /* @__PURE__ */ u("div", {
|
|
56
|
+
ref: j,
|
|
57
|
+
id: D,
|
|
58
|
+
role: "dialog",
|
|
59
|
+
className: e(a.popover, g ? a.portalled : a[h], S),
|
|
60
|
+
style: M,
|
|
61
|
+
children: m
|
|
62
|
+
});
|
|
63
|
+
return /* @__PURE__ */ d("span", {
|
|
64
|
+
ref: k,
|
|
65
|
+
className: a.root,
|
|
66
|
+
children: [F, E && (g ? /* @__PURE__ */ u(n, { children: I }) : I)]
|
|
46
67
|
});
|
|
47
68
|
}
|
|
48
69
|
//#endregion
|
|
49
|
-
export {
|
|
70
|
+
export { p as Popover };
|
|
50
71
|
|
|
51
72
|
//# sourceMappingURL=Popover.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.js","names":[],"sources":["../../../src/components/Popover/Popover.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — trigger and children are the two halves, placement\n * is where it lands, and open/onOpenChange/defaultOpen is the standard controlled-\n * or-not pair. closeOnEsc and closeOnOutsideClick are separate because a popover\n * holding a form wants one and not the other.\n */\nimport { useCallback, useEffect, useId,
|
|
1
|
+
{"version":3,"file":"Popover.js","names":[],"sources":["../../../src/components/Popover/Popover.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — trigger and children are the two halves, placement\n * is where it lands, portal is whether it escapes the tree, and open/onOpenChange/defaultOpen is the standard controlled-\n * or-not pair. closeOnEsc and closeOnOutsideClick are separate because a popover\n * holding a form wants one and not the other.\n */\nimport { useCallback, useEffect, useId, useState } from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport { Portal } from \"@/components/Portal\";\nimport { useAnchorPosition } from \"@/components/Portal/anchor-position\";\nimport { useEscapeLayer } from \"@/components/Portal/escape-layer\";\nimport { usePortalTabOrder } from \"@/components/Portal/tab-bridge\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Popover.module.css\";\n\nexport type PopoverPlacement = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nexport interface PopoverProps {\n /** Trigger element. Receives `onClick`/`aria-expanded`/`aria-controls`. */\n trigger: ReactElement<{\n onClick?: (e: React.MouseEvent) => void;\n \"aria-expanded\"?: boolean;\n \"aria-controls\"?: string;\n }>;\n children: ReactNode;\n placement?: PopoverPlacement;\n /**\n * Render the panel in a portal, positioned against the trigger. Default `true`.\n *\n * In flow, any ancestor with `overflow` other than `visible` clips the panel —\n * inside a `DataTable` cell only 3% of it was visible (measured in Chrome at\n * 1440 px). In a portal it escapes the clip, flips to the opposite side when\n * the requested one has no room, and follows the trigger on scroll and resize.\n * `false` keeps the in-flow panel.\n */\n portal?: boolean;\n /** Controlled open state. */\n open?: boolean;\n /** Called when the user toggles or dismisses. */\n onOpenChange?: (open: boolean) => void;\n /** Default open state for uncontrolled usage. */\n defaultOpen?: boolean;\n /** Close on Escape. Default true. */\n closeOnEsc?: boolean;\n /** Close on outside click. Default true. */\n closeOnOutsideClick?: boolean;\n className?: string;\n}\n\n/** Gap between trigger and panel, in px — the in-flow CSS uses the same 8 px. */\nconst POPOVER_OFFSET = 8;\n\n/**\n * Lightweight popover. Renders a panel anchored to a trigger, dismissed on\n * outside click / Escape.\n *\n * Portalled by default, with viewport-aware placement: the panel flips to the\n * opposite side when the requested one overflows, and is clamped inside the\n * viewport otherwise.\n */\nexport function Popover({\n trigger,\n children,\n placement = \"bottom\",\n portal = true,\n open,\n onOpenChange,\n defaultOpen = false,\n closeOnEsc = true,\n closeOnOutsideClick = true,\n className,\n}: PopoverProps) {\n const isControlled = open !== undefined;\n const [internalOpen, setInternalOpen] = useState<boolean>(defaultOpen);\n const isOpen = isControlled ? open : internalOpen;\n const id = useId();\n const [rootNode, setRootNode] = useState<HTMLSpanElement | null>(null);\n const [panelNode, setPanelNode] = useState<HTMLDivElement | null>(null);\n const floatingStyle = useAnchorPosition({\n anchor: rootNode,\n floating: panelNode,\n side: placement,\n align: \"center\",\n offset: POPOVER_OFFSET,\n enabled: portal && isOpen,\n });\n usePortalTabOrder({ enabled: portal && isOpen, anchor: rootNode, panel: panelNode });\n\n const setOpen = useCallback(\n (next: boolean): void => {\n if (!isControlled) setInternalOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n useEscapeLayer(isOpen && closeOnEsc, () => setOpen(false));\n\n /**\n * Dismiss on a press outside both trigger and panel.\n *\n * The panel is checked on its own because in a portal it is not inside the\n * trigger's wrapper, and a press inside it — on a form field, say — would\n * otherwise count as outside.\n */\n useEffect(() => {\n if (!isOpen) return;\n const onDown = (event: MouseEvent): void => {\n if (!closeOnOutsideClick) return;\n const target = event.target as Node;\n if (rootNode?.contains(target) || panelNode?.contains(target)) return;\n setOpen(false);\n };\n window.addEventListener(\"mousedown\", onDown);\n return () => {\n window.removeEventListener(\"mousedown\", onDown);\n };\n }, [isOpen, closeOnOutsideClick, setOpen, rootNode, panelNode]);\n\n const handleTriggerClick = (event: React.MouseEvent): void => {\n trigger.props.onClick?.(event);\n setOpen(!isOpen);\n };\n\n const triggerClone = {\n ...trigger,\n props: {\n ...trigger.props,\n onClick: handleTriggerClick,\n \"aria-expanded\": isOpen,\n \"aria-controls\": id,\n },\n } as ReactElement;\n\n const panel = (\n <div\n ref={setPanelNode}\n id={id}\n role=\"dialog\"\n className={cn(styles.popover, portal ? styles.portalled : styles[placement], className)}\n style={floatingStyle}\n >\n {children}\n </div>\n );\n\n return (\n <span ref={setRootNode} className={styles.root}>\n {triggerClone}\n {isOpen && (portal ? <Portal>{panel}</Portal> : panel)}\n </span>\n );\n}\n"],"mappings":";;;;;;;;;AAkDA,IAAM,IAAiB;AAUvB,SAAgB,EAAQ,EACpB,YACA,aACA,eAAY,UACZ,YAAS,IACT,SACA,iBACA,iBAAc,IACd,gBAAa,IACb,yBAAsB,IACtB,gBACa;CACb,IAAM,IAAe,MAAS,KAAA,GACxB,CAAC,GAAc,KAAmB,EAAkB,CAAW,GAC/D,IAAS,IAAe,IAAO,GAC/B,IAAK,EAAM,GACX,CAAC,GAAU,KAAe,EAAiC,IAAI,GAC/D,CAAC,GAAW,KAAgB,EAAgC,IAAI,GAChE,IAAgB,EAAkB;EACpC,QAAQ;EACR,UAAU;EACV,MAAM;EACN,OAAO;EACP,QAAQ;EACR,SAAS,KAAU;CACvB,CAAC;CACD,EAAkB;EAAE,SAAS,KAAU;EAAQ,QAAQ;EAAU,OAAO;CAAU,CAAC;CAEnF,IAAM,IAAU,GACX,MAAwB;EAErB,AADK,KAAc,EAAgB,CAAI,GACvC,IAAe,CAAI;CACvB,GACA,CAAC,GAAc,CAAY,CAC/B;CAWA,AATA,EAAe,KAAU,SAAkB,EAAQ,EAAK,CAAC,GASzD,QAAgB;EACZ,IAAI,CAAC,GAAQ;EACb,IAAM,KAAU,MAA4B;GACxC,IAAI,CAAC,GAAqB;GAC1B,IAAM,IAAS,EAAM;GACjB,GAAU,SAAS,CAAM,KAAK,GAAW,SAAS,CAAM,KAC5D,EAAQ,EAAK;EACjB;EAEA,OADA,OAAO,iBAAiB,aAAa,CAAM,SAC9B;GACT,OAAO,oBAAoB,aAAa,CAAM;EAClD;CACJ,GAAG;EAAC;EAAQ;EAAqB;EAAS;EAAU;CAAS,CAAC;CAE9D,IAAM,KAAsB,MAAkC;EAE1D,AADA,EAAQ,MAAM,UAAU,CAAK,GAC7B,EAAQ,CAAC,CAAM;CACnB,GAEM,IAAe;EACjB,GAAG;EACH,OAAO;GACH,GAAG,EAAQ;GACX,SAAS;GACT,iBAAiB;GACjB,iBAAiB;EACrB;CACJ,GAEM,IACF,kBAAC,OAAD;EACI,KAAK;EACD;EACJ,MAAK;EACL,WAAW,EAAG,EAAO,SAAS,IAAS,EAAO,YAAY,EAAO,IAAY,CAAS;EACtF,OAAO;EAEN;CACA,CAAA;CAGT,OACI,kBAAC,QAAD;EAAM,KAAK;EAAa,WAAW,EAAO;EAA1C,UAAA,CACK,GACA,MAAW,IAAS,kBAAC,GAAD,EAAA,UAAS,EAAc,CAAA,IAAI,EAC9C;;AAEd"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
require("../../styles/component/Popover.css");
|
|
2
|
-
var e=`tempest_root_vEMon`,t=`tempest_popover_E9K9X`,n=`tempest_tempest-popover-in_W8miP`,r=`
|
|
2
|
+
var e=`tempest_root_vEMon`,t=`tempest_popover_E9K9X`,n=`tempest_tempest-popover-in_W8miP`,r=`tempest_portalled_pZ553`,i=`tempest_top_TYlrh`,a=`tempest_bottom_wGs70`,o=`tempest_left_h7fCr`,s=`tempest_right_--bJW`,c={root:e,popover:t,tempestPopoverIn:n,portalled:r,top:i,bottom:a,left:o,right:s};exports.bottom=a,exports.default=c,exports.left=o,exports.popover=t,exports.portalled=r,exports.right=s,exports.root=e,exports.tempestPopoverIn=n,exports.top=i;
|
|
3
3
|
//# sourceMappingURL=Popover.module.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.module.cjs","names":[],"sources":["../../../src/components/Popover/Popover.module.css"],"sourcesContent":[".root {\n position: relative;\n display: inline-flex;\n}\n\n.popover {\n position: absolute;\n z-index: var(--tempest-z-popover);\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n box-shadow: var(--tempest-shadow-lg);\n padding: var(--tempest-space-3) var(--tempest-space-4);\n min-width: 200px;\n max-width: 320px;\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n line-height: var(--tempest-leading-snug);\n animation: tempest-popover-in var(--tempest-duration-fast) var(--tempest-ease-out);\n}\n\n.popover:focus {\n outline: none;\n}\n\n/* Placements (center-aligned across the trigger). */\n.top {\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n}\n.bottom {\n top: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n}\n.left {\n right: calc(100% + 8px);\n top: 50%;\n transform: translateY(-50%);\n}\n.right {\n left: calc(100% + 8px);\n top: 50%;\n transform: translateY(-50%);\n}\n\n@keyframes tempest-popover-in {\n from {\n opacity: 0;\n transform: translate(var(--tempest-popover-tx, -50%), 4px);\n }\n to {\n opacity: 1;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .popover {\n animation: none;\n }\n}\n"],"mappings":";"}
|
|
1
|
+
{"version":3,"file":"Popover.module.cjs","names":[],"sources":["../../../src/components/Popover/Popover.module.css"],"sourcesContent":[".root {\n position: relative;\n display: inline-flex;\n}\n\n.popover {\n position: absolute;\n z-index: var(--tempest-z-popover);\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n box-shadow: var(--tempest-shadow-lg);\n padding: var(--tempest-space-3) var(--tempest-space-4);\n min-width: 200px;\n max-width: 320px;\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n line-height: var(--tempest-leading-snug);\n animation: tempest-popover-in var(--tempest-duration-fast) var(--tempest-ease-out);\n}\n\n.popover:focus {\n outline: none;\n}\n\n.portalled {\n --tempest-popover-tx: 0;\n}\n\n/* Placements (center-aligned across the trigger). */\n.top {\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n}\n.bottom {\n top: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n}\n.left {\n right: calc(100% + 8px);\n top: 50%;\n transform: translateY(-50%);\n}\n.right {\n left: calc(100% + 8px);\n top: 50%;\n transform: translateY(-50%);\n}\n\n@keyframes tempest-popover-in {\n from {\n opacity: 0;\n transform: translate(var(--tempest-popover-tx, -50%), 4px);\n }\n to {\n opacity: 1;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .popover {\n animation: none;\n }\n}\n"],"mappings":";"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import "../../styles/component/Popover.css";
|
|
2
2
|
//#region src/components/Popover/Popover.module.css
|
|
3
|
-
var e = "tempest_root_vEMon", t = "tempest_popover_E9K9X", n = "tempest_tempest-popover-in_W8miP", r = "
|
|
3
|
+
var e = "tempest_root_vEMon", t = "tempest_popover_E9K9X", n = "tempest_tempest-popover-in_W8miP", r = "tempest_portalled_pZ553", i = "tempest_top_TYlrh", a = "tempest_bottom_wGs70", o = "tempest_left_h7fCr", s = "tempest_right_--bJW", c = {
|
|
4
4
|
root: e,
|
|
5
5
|
popover: t,
|
|
6
6
|
tempestPopoverIn: n,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
portalled: r,
|
|
8
|
+
top: i,
|
|
9
|
+
bottom: a,
|
|
10
|
+
left: o,
|
|
11
|
+
right: s
|
|
11
12
|
};
|
|
12
13
|
//#endregion
|
|
13
|
-
export {
|
|
14
|
+
export { a as bottom, c as default, o as left, t as popover, r as portalled, s as right, e as root, n as tempestPopoverIn, i as top };
|
|
14
15
|
|
|
15
16
|
//# sourceMappingURL=Popover.module.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.module.js","names":[],"sources":["../../../src/components/Popover/Popover.module.css"],"sourcesContent":[".root {\n position: relative;\n display: inline-flex;\n}\n\n.popover {\n position: absolute;\n z-index: var(--tempest-z-popover);\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n box-shadow: var(--tempest-shadow-lg);\n padding: var(--tempest-space-3) var(--tempest-space-4);\n min-width: 200px;\n max-width: 320px;\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n line-height: var(--tempest-leading-snug);\n animation: tempest-popover-in var(--tempest-duration-fast) var(--tempest-ease-out);\n}\n\n.popover:focus {\n outline: none;\n}\n\n/* Placements (center-aligned across the trigger). */\n.top {\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n}\n.bottom {\n top: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n}\n.left {\n right: calc(100% + 8px);\n top: 50%;\n transform: translateY(-50%);\n}\n.right {\n left: calc(100% + 8px);\n top: 50%;\n transform: translateY(-50%);\n}\n\n@keyframes tempest-popover-in {\n from {\n opacity: 0;\n transform: translate(var(--tempest-popover-tx, -50%), 4px);\n }\n to {\n opacity: 1;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .popover {\n animation: none;\n }\n}\n"],"mappings":";"}
|
|
1
|
+
{"version":3,"file":"Popover.module.js","names":[],"sources":["../../../src/components/Popover/Popover.module.css"],"sourcesContent":[".root {\n position: relative;\n display: inline-flex;\n}\n\n.popover {\n position: absolute;\n z-index: var(--tempest-z-popover);\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n box-shadow: var(--tempest-shadow-lg);\n padding: var(--tempest-space-3) var(--tempest-space-4);\n min-width: 200px;\n max-width: 320px;\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n line-height: var(--tempest-leading-snug);\n animation: tempest-popover-in var(--tempest-duration-fast) var(--tempest-ease-out);\n}\n\n.popover:focus {\n outline: none;\n}\n\n.portalled {\n --tempest-popover-tx: 0;\n}\n\n/* Placements (center-aligned across the trigger). */\n.top {\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n}\n.bottom {\n top: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n}\n.left {\n right: calc(100% + 8px);\n top: 50%;\n transform: translateY(-50%);\n}\n.right {\n left: calc(100% + 8px);\n top: 50%;\n transform: translateY(-50%);\n}\n\n@keyframes tempest-popover-in {\n from {\n opacity: 0;\n transform: translate(var(--tempest-popover-tx, -50%), 4px);\n }\n to {\n opacity: 1;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .popover {\n animation: none;\n }\n}\n"],"mappings":";"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
let e=require("react");var t={top:`bottom`,bottom:`top`,left:`right`,right:`left`};function n(e,t,n){return Math.max(t,Math.min(e,Math.max(t,n)))}function r(e,t){let{anchor:n,width:r,height:i,offset:a}=e;switch(t){case`top`:return n.top-a-i;case`bottom`:return n.top+n.height+a;case`left`:return n.left-a-r;default:return n.left+n.width+a}}function i(e,t){let{width:n,height:i,viewportWidth:a,viewportHeight:o,margin:s}=e,c=r(e,t),l=t===`top`||t===`bottom`?i:n,u=t===`top`||t===`bottom`?o:a;return c>=s&&c+l<=u-s}function a(e,t,n,r){return r===`start`?e:r===`end`?e+t-n:e+(t-n)/2}function o(e){let{anchor:o,width:s,height:c,viewportWidth:l,viewportHeight:u,align:d,margin:f}=e,p=e.side,m=t[p],h=!i(e,p)&&i(e,m)?m:p,g=h===`top`||h===`bottom`,_=r(e,h),v=g?_:a(o.top,o.height,c,d),y=g?a(o.left,o.width,s,d):_;return{top:n(v,f,u-c-f),left:n(y,f,l-s-f),side:h}}function s({anchor:t,floating:n,side:r,align:i,offset:a,enabled:s,matchWidth:c=!1}){let[l,u]=(0,e.useState)(null);if((0,e.useLayoutEffect)(()=>{if(!s||!t||!n){u(null);return}let e=()=>{let e=t.getBoundingClientRect(),s=c?e.width:void 0;s!==void 0&&n.style.setProperty(`width`,`${s}px`);let l={...o({anchor:{top:e.top,left:e.left,width:e.width,height:e.height},width:n.offsetWidth,height:n.offsetHeight,viewportWidth:window.innerWidth,viewportHeight:window.innerHeight,side:r,align:i,offset:a,margin:8}),width:s};u(e=>e&&e.top===l.top&&e.left===l.left&&e.side===l.side&&e.width===l.width?e:l)};e();let l=0,d=()=>{l===0&&(l=requestAnimationFrame(()=>{l=0,e()}))};window.addEventListener(`scroll`,d,{capture:!0,passive:!0}),window.addEventListener(`resize`,d);let f=typeof ResizeObserver>`u`?null:new ResizeObserver(d);return f?.observe(n),f?.observe(t),()=>{f?.disconnect(),l!==0&&cancelAnimationFrame(l),window.removeEventListener(`scroll`,d,{capture:!0}),window.removeEventListener(`resize`,d)}},[s,t,n,r,i,a,c]),s)return{position:`fixed`,top:l?.top??0,left:l?.left??0,width:l?.width}}exports.computeAnchorPosition=o,exports.useAnchorPosition=s;
|
|
2
|
+
//# sourceMappingURL=anchor-position.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anchor-position.cjs","names":[],"sources":["../../../src/components/Portal/anchor-position.ts"],"sourcesContent":["import { useLayoutEffect, useState } from \"react\";\nimport type { CSSProperties } from \"react\";\n\n/** Side of the anchor a floating layer is placed on. */\nexport type AnchorSide = \"top\" | \"bottom\" | \"left\" | \"right\";\n\n/** Alignment of the floating layer along the anchor's edge. */\nexport type AnchorAlign = \"start\" | \"center\" | \"end\";\n\n/** The viewport-relative box a placement is computed from. */\nexport interface AnchorRect {\n top: number;\n left: number;\n width: number;\n height: number;\n}\n\n/** Everything {@link computeAnchorPosition} needs, all in CSS pixels. */\nexport interface AnchorGeometry {\n anchor: AnchorRect;\n width: number;\n height: number;\n viewportWidth: number;\n viewportHeight: number;\n side: AnchorSide;\n align: AnchorAlign;\n offset: number;\n margin: number;\n}\n\n/** A resolved placement: viewport coordinates plus the side actually used. */\nexport interface AnchorPlacement {\n top: number;\n left: number;\n side: AnchorSide;\n}\n\n/** What {@link useAnchorPosition} keeps between measurements. */\ninterface MeasuredPlacement extends AnchorPlacement {\n /** The anchor's width, when the layer matches it. */\n width: number | undefined;\n}\n\nconst OPPOSITE: Record<AnchorSide, AnchorSide> = {\n top: \"bottom\",\n bottom: \"top\",\n left: \"right\",\n right: \"left\",\n};\n\n/** Distance kept between a floating layer and the viewport edge, in px. */\nexport const ANCHOR_VIEWPORT_MARGIN = 8;\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(value, Math.max(min, max)));\n}\n\nfunction mainAxis(geometry: AnchorGeometry, side: AnchorSide): number {\n const { anchor, width, height, offset } = geometry;\n switch (side) {\n case \"top\":\n return anchor.top - offset - height;\n case \"bottom\":\n return anchor.top + anchor.height + offset;\n case \"left\":\n return anchor.left - offset - width;\n case \"right\":\n default:\n return anchor.left + anchor.width + offset;\n }\n}\n\nfunction fits(geometry: AnchorGeometry, side: AnchorSide): boolean {\n const { width, height, viewportWidth, viewportHeight, margin } = geometry;\n const start = mainAxis(geometry, side);\n const size = side === \"top\" || side === \"bottom\" ? height : width;\n const limit = side === \"top\" || side === \"bottom\" ? viewportHeight : viewportWidth;\n return start >= margin && start + size <= limit - margin;\n}\n\nfunction crossAxis(start: number, length: number, size: number, align: AnchorAlign): number {\n if (align === \"start\") return start;\n if (align === \"end\") return start + length - size;\n return start + (length - size) / 2;\n}\n\n/**\n * Place a floating layer next to its anchor, inside the viewport.\n *\n * The requested side wins when the layer fits there. When it does not and the\n * opposite side does, the layer flips — the case that matters is the action menu\n * of the last row of a table near the bottom of the screen, which would otherwise\n * open below the fold. When neither side fits, the requested one is kept and the\n * layer is clamped, because a partially visible menu the user can scroll to beats\n * one that jumps sides depending on a pixel.\n *\n * Both axes are then clamped to the viewport minus `margin`.\n *\n * @param geometry - The anchor box, the floating layer's size, the viewport, and\n * the requested placement.\n * @returns The viewport coordinates for a `position: fixed` layer, and the side\n * that was used after flipping.\n */\nexport function computeAnchorPosition(geometry: AnchorGeometry): AnchorPlacement {\n const { anchor, width, height, viewportWidth, viewportHeight, align, margin } = geometry;\n const requested = geometry.side;\n const flipped = OPPOSITE[requested];\n const side = !fits(geometry, requested) && fits(geometry, flipped) ? flipped : requested;\n const vertical = side === \"top\" || side === \"bottom\";\n const main = mainAxis(geometry, side);\n const top = vertical ? main : crossAxis(anchor.top, anchor.height, height, align);\n const left = vertical ? crossAxis(anchor.left, anchor.width, width, align) : main;\n return {\n top: clamp(top, margin, viewportHeight - height - margin),\n left: clamp(left, margin, viewportWidth - width - margin),\n side,\n };\n}\n\n/** Options of {@link useAnchorPosition}. */\nexport interface AnchorPositionOptions {\n /** Element the layer is anchored to. */\n anchor: HTMLElement | null;\n /** The floating layer itself, once mounted. */\n floating: HTMLElement | null;\n side: AnchorSide;\n align: AnchorAlign;\n /** Gap between anchor and layer, in px. */\n offset: number;\n /** When false the hook does nothing and returns `undefined`. */\n enabled: boolean;\n /**\n * Give the layer the anchor's width — a listbox under its input. Default\n * `false`.\n */\n matchWidth?: boolean;\n}\n\n/**\n * Keep a portalled layer glued to its anchor.\n *\n * Takes the floating element as a value rather than a ref, because `Portal`\n * renders `null` on its first pass and mounts in an effect: a layout effect keyed\n * off `open` would run while the layer does not exist and measure nothing. With\n * the node held in state (a callback ref), the effect runs on the render that has\n * it, and `useLayoutEffect` settles the position before the first paint.\n *\n * The size comes from `offsetWidth`/`offsetHeight`, not from\n * `getBoundingClientRect`, which reports the transformed box — the layers enter\n * with a `translate`/`scale` animation, and the transformed rect would place them\n * a few pixels off. The anchor's rect is the right one to read: it is where the\n * trigger is painted.\n *\n * Scroll (captured, so a scrolling table wrapper counts) and resize reposition the\n * layer on the next animation frame, so a menu open inside a table that scrolls\n * follows its row instead of floating where the row used to be. So does a change\n * in the size of either box, through a `ResizeObserver`: a combobox list flipped\n * above its input shrinks as the user types, and a multi-select field grows a\n * line as chips are added — without the observer the list would keep its old\n * top and float away from the field, or cover it.\n *\n * With `matchWidth` the anchor's width is written to the layer **before** its\n * height is read, so the height is measured at the width it will be painted at —\n * a list whose options wrap at the narrower width is taller.\n *\n * The unmeasured first pass is **not** hidden with `visibility: hidden`: an\n * element under it cannot take focus, and the menu's focus effect runs before\n * the measured re-render, so the first entry silently kept no focus (measured in\n * Chrome; jsdom does not enforce it). Nothing is painted at the unmeasured\n * position anyway — the layout effect re-renders before the browser paints.\n *\n * @param options - Anchor, floating node, placement, and whether it is active.\n * @returns A `position: fixed` style for the layer, or `undefined` when disabled.\n */\nexport function useAnchorPosition({\n anchor,\n floating,\n side,\n align,\n offset,\n enabled,\n matchWidth = false,\n}: AnchorPositionOptions): CSSProperties | undefined {\n const [placement, setPlacement] = useState<MeasuredPlacement | null>(null);\n\n useLayoutEffect(() => {\n if (!enabled || !anchor || !floating) {\n setPlacement(null);\n return;\n }\n const update = (): void => {\n const rect = anchor.getBoundingClientRect();\n const width = matchWidth ? rect.width : undefined;\n if (width !== undefined) floating.style.setProperty(\"width\", `${width}px`);\n const position = computeAnchorPosition({\n anchor: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },\n width: floating.offsetWidth,\n height: floating.offsetHeight,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n side,\n align,\n offset,\n margin: ANCHOR_VIEWPORT_MARGIN,\n });\n const next: MeasuredPlacement = { ...position, width };\n setPlacement((current) =>\n current &&\n current.top === next.top &&\n current.left === next.left &&\n current.side === next.side &&\n current.width === next.width\n ? current\n : next,\n );\n };\n update();\n let frame = 0;\n const schedule = (): void => {\n if (frame !== 0) return;\n frame = requestAnimationFrame(() => {\n frame = 0;\n update();\n });\n };\n window.addEventListener(\"scroll\", schedule, { capture: true, passive: true });\n window.addEventListener(\"resize\", schedule);\n const observer =\n typeof ResizeObserver === \"undefined\" ? null : new ResizeObserver(schedule);\n observer?.observe(floating);\n observer?.observe(anchor);\n return () => {\n observer?.disconnect();\n if (frame !== 0) cancelAnimationFrame(frame);\n window.removeEventListener(\"scroll\", schedule, { capture: true });\n window.removeEventListener(\"resize\", schedule);\n };\n }, [enabled, anchor, floating, side, align, offset, matchWidth]);\n\n if (!enabled) return undefined;\n return {\n position: \"fixed\",\n top: placement?.top ?? 0,\n left: placement?.left ?? 0,\n width: placement?.width,\n };\n}\n"],"mappings":"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"}
|