@agent-factory-platform/ui-kit 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +18 -0
  2. package/dist/charts/adapter.js +111 -0
  3. package/dist/charts/basic.js +115 -0
  4. package/dist/charts/chart-tooltip.js +21 -0
  5. package/dist/charts/event-markers-primitive.d.ts +10 -1
  6. package/dist/charts/event-markers-primitive.js +116 -0
  7. package/dist/charts/index.d.ts +1 -0
  8. package/dist/charts/ohlc-annotations.d.ts +56 -0
  9. package/dist/charts/ohlc-annotations.js +84 -0
  10. package/dist/charts/ohlc.d.ts +5 -1
  11. package/dist/charts/ohlc.js +240 -0
  12. package/dist/charts/series.js +584 -0
  13. package/dist/charts/theme.js +35 -0
  14. package/dist/charts/time-combo.js +17 -0
  15. package/dist/component-api.js +3 -5
  16. package/dist/component-api.json.js +9 -0
  17. package/dist/component-manifest.json.js +9 -0
  18. package/dist/components/alert.js +35 -0
  19. package/dist/components/avatar.js +101 -0
  20. package/dist/components/badge.js +111 -0
  21. package/dist/components/button-group.js +22 -0
  22. package/dist/components/button.js +64 -0
  23. package/dist/components/calendar-period-navigator.js +34 -0
  24. package/dist/components/card.js +35 -0
  25. package/dist/components/chart-frame.js +53 -0
  26. package/dist/components/color-picker.js +155 -0
  27. package/dist/components/combobox.js +129 -0
  28. package/dist/components/command-dialog.js +89 -0
  29. package/dist/components/confirm-dialog.js +57 -0
  30. package/dist/components/data-table.js +135 -0
  31. package/dist/components/date-time.js +203 -0
  32. package/dist/components/disclosure.js +29 -0
  33. package/dist/components/drawer.js +150 -0
  34. package/dist/components/dropdown-select.js +191 -0
  35. package/dist/components/field.js +21 -0
  36. package/dist/components/floating-window.js +159 -0
  37. package/dist/components/heading.js +21 -0
  38. package/dist/components/hover-tip.js +90 -0
  39. package/dist/components/icon-tip.js +12 -0
  40. package/dist/components/input-group.js +16 -0
  41. package/dist/components/input-otp.js +56 -0
  42. package/dist/components/input.js +44 -0
  43. package/dist/components/item.js +47 -0
  44. package/dist/components/kbd.js +18 -0
  45. package/dist/components/line-chart.js +79 -0
  46. package/dist/components/listbox.js +33 -0
  47. package/dist/components/live-value.js +26 -0
  48. package/dist/components/modal.js +140 -0
  49. package/dist/components/multi-select.js +54 -0
  50. package/dist/components/native-select.js +17 -0
  51. package/dist/components/navigation.js +42 -0
  52. package/dist/components/page.js +24 -0
  53. package/dist/components/popover-menu.js +164 -0
  54. package/dist/components/progress.js +23 -0
  55. package/dist/components/resizable-pane.js +73 -0
  56. package/dist/components/scroll-load-more.js +61 -0
  57. package/dist/components/seg-slider.js +42 -0
  58. package/dist/components/segmented-control.js +46 -0
  59. package/dist/components/selection-controls.js +119 -0
  60. package/dist/components/sidebar.js +23 -0
  61. package/dist/components/skeleton.js +9 -0
  62. package/dist/components/slider.js +162 -0
  63. package/dist/components/sliding-tabs.js +118 -0
  64. package/dist/components/spinner.js +9 -0
  65. package/dist/components/spotlight-tour.js +122 -0
  66. package/dist/components/stat-card.js +23 -0
  67. package/dist/components/state-view.js +75 -0
  68. package/dist/components/stats-table.js +17 -0
  69. package/dist/components/table.js +24 -0
  70. package/dist/components/tag-pill.d.ts +4 -1
  71. package/dist/components/tag-pill.js +69 -0
  72. package/dist/components/theme-editor.js +159 -0
  73. package/dist/components/toast.js +66 -0
  74. package/dist/components/toolbar.js +46 -0
  75. package/dist/components/utility.js +19 -0
  76. package/dist/components/widget-frame.js +41 -0
  77. package/dist/components/widget-picker.js +87 -0
  78. package/dist/components/workspace-grid.js +468 -0
  79. package/dist/focus-modality.js +3 -15
  80. package/dist/index.d.ts +1 -1
  81. package/dist/index.js +228 -5564
  82. package/dist/lib/cn.js +6 -0
  83. package/dist/lib/focus-modality.js +16 -0
  84. package/dist/lib/motion.js +27 -0
  85. package/dist/lib/viewport.js +13 -0
  86. package/dist/manifest.js +5 -7
  87. package/dist/styles.js +1 -1
  88. package/dist/theme.js +158 -0
  89. package/package.json +1 -1
@@ -0,0 +1,150 @@
1
+ import { jsx as n, jsxs as c, Fragment as R } from "react/jsx-runtime";
2
+ import { useRef as j, useId as C, useEffect as D, useState as O } from "react";
3
+ import { createPortal as P } from "react-dom";
4
+ import { AnimatePresence as A, motion as M } from "motion/react";
5
+ import { X as T } from "lucide-react";
6
+ import { transitions as S, fadeInOut as X, bottomSheet as B } from "../lib/motion.js";
7
+ import { cn as b } from "../lib/cn.js";
8
+ const G = {
9
+ initial: { x: "100%" },
10
+ animate: { x: 0 },
11
+ exit: { x: "100%" }
12
+ };
13
+ function H() {
14
+ const [o, r] = O(
15
+ () => typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(min-width: 640px)").matches
16
+ );
17
+ return D(() => {
18
+ if (typeof window.matchMedia != "function") return;
19
+ const t = window.matchMedia("(min-width: 640px)"), i = () => r(t.matches);
20
+ return t.addEventListener("change", i), () => t.removeEventListener("change", i);
21
+ }, []), o;
22
+ }
23
+ function ee({
24
+ open: o,
25
+ onClose: r,
26
+ title: t,
27
+ ariaLabel: i,
28
+ closeLabel: w = "Close",
29
+ description: p,
30
+ children: x,
31
+ footer: y,
32
+ size: u = "md",
33
+ bare: f = !1,
34
+ side: s = "right",
35
+ mobilePlacement: L = "bottom",
36
+ rootClassName: z,
37
+ panelClassName: I
38
+ }) {
39
+ const a = j(null), v = C(), g = j(r);
40
+ g.current = r;
41
+ const l = H() || L === "side", h = l ? s === "left" ? { initial: { x: "-100%" }, animate: { x: 0 }, exit: { x: "-100%" } } : G : B;
42
+ if (D(() => {
43
+ if (!o) return;
44
+ const d = document.activeElement, k = (e) => {
45
+ if (e.key === "Escape") {
46
+ g.current();
47
+ return;
48
+ }
49
+ if (e.key === "Tab" && a.current) {
50
+ const m = a.current.querySelectorAll(
51
+ 'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])'
52
+ );
53
+ if (m.length === 0) {
54
+ e.preventDefault();
55
+ return;
56
+ }
57
+ const E = m[0], N = m[m.length - 1];
58
+ e.shiftKey && (document.activeElement === E || document.activeElement === a.current) ? (e.preventDefault(), N.focus()) : !e.shiftKey && document.activeElement === N && (e.preventDefault(), E.focus());
59
+ }
60
+ };
61
+ document.addEventListener("keydown", k);
62
+ const F = document.body.style.overflow;
63
+ document.body.style.overflow = "hidden";
64
+ const K = requestAnimationFrame(() => {
65
+ var e;
66
+ return (e = a.current) == null ? void 0 : e.focus();
67
+ });
68
+ return () => {
69
+ var e;
70
+ document.removeEventListener("keydown", k), document.body.style.overflow = F, cancelAnimationFrame(K), (e = d == null ? void 0 : d.focus) == null || e.call(d);
71
+ };
72
+ }, [o]), typeof document > "u") return null;
73
+ const q = u === "xl" ? "sm:w-drawer-xl" : u === "lg" ? "sm:w-drawer-lg" : u === "sm" ? "sm:w-drawer-sm" : "sm:w-drawer-md";
74
+ return P(
75
+ /* @__PURE__ */ n(A, { children: o && /* @__PURE__ */ c(
76
+ "div",
77
+ {
78
+ className: b(
79
+ "fixed inset-0 z-50 flex",
80
+ l ? s === "left" ? "items-stretch justify-start" : "items-stretch justify-end" : "items-end justify-center sm:items-stretch sm:justify-end",
81
+ z
82
+ ),
83
+ role: "dialog",
84
+ "aria-modal": "true",
85
+ "aria-labelledby": !f && t ? v : void 0,
86
+ "aria-label": f ? i ?? t : t ? void 0 : i,
87
+ "data-overlay": "drawer",
88
+ "data-placement": l ? s : "bottom",
89
+ children: [
90
+ /* @__PURE__ */ n(
91
+ M.div,
92
+ {
93
+ ...X,
94
+ transition: S.fade,
95
+ "aria-hidden": "true",
96
+ onClick: r,
97
+ className: "absolute inset-0 bg-black/55 backdrop-blur-sm"
98
+ }
99
+ ),
100
+ /* @__PURE__ */ n(
101
+ M.div,
102
+ {
103
+ ref: a,
104
+ "data-testid": "drawer-panel",
105
+ tabIndex: -1,
106
+ initial: h.initial,
107
+ animate: h.animate,
108
+ exit: h.exit,
109
+ transition: S.drawer,
110
+ className: b(
111
+ "relative z-10 flex w-full min-w-0 flex-col overflow-hidden border border-border bg-surface-raised shadow-pop outline-none",
112
+ l ? b(
113
+ "h-full max-h-none pb-0",
114
+ s === "left" ? "rounded-r-overlay border-l-0" : "rounded-l-overlay border-r-0"
115
+ ) : "max-h-[90dvh] rounded-t-sheet border-b-0 pb-[env(safe-area-inset-bottom)] sm:h-full sm:max-h-none sm:rounded-none sm:rounded-l-overlay sm:border-b sm:border-r-0 sm:pb-0",
116
+ q,
117
+ I
118
+ ),
119
+ children: f ? x : /* @__PURE__ */ c(R, { children: [
120
+ t && /* @__PURE__ */ c("header", { className: "flex shrink-0 items-start justify-between gap-2 border-b border-divider px-5 py-3.5", children: [
121
+ /* @__PURE__ */ c("div", { className: "min-w-0", children: [
122
+ /* @__PURE__ */ n("h2", { id: v, className: "font-sohne text-body font-[500] text-ink", children: t }),
123
+ p && /* @__PURE__ */ n("p", { className: "mt-0.5 font-sohne text-caption text-graphite", children: p })
124
+ ] }),
125
+ /* @__PURE__ */ n(
126
+ "button",
127
+ {
128
+ type: "button",
129
+ onClick: r,
130
+ title: w,
131
+ "aria-label": w,
132
+ className: "-mr-1 grid size-8 place-items-center rounded-control text-graphite outline-none transition hover:bg-surface-hover hover:text-ink focus-visible:ring-2 focus-visible:ring-rust/35",
133
+ children: /* @__PURE__ */ n(T, { size: 16, "aria-hidden": !0 })
134
+ }
135
+ )
136
+ ] }),
137
+ /* @__PURE__ */ n("div", { className: "min-h-0 flex-1 overflow-y-auto px-5 py-4", children: x }),
138
+ y && /* @__PURE__ */ n("div", { className: "shrink-0 border-t border-divider px-5 py-3", children: y })
139
+ ] })
140
+ }
141
+ )
142
+ ]
143
+ }
144
+ ) }),
145
+ document.body
146
+ );
147
+ }
148
+ export {
149
+ ee as Drawer
150
+ };
@@ -0,0 +1,191 @@
1
+ import { jsx as c, jsxs as x } from "react/jsx-runtime";
2
+ import { useState as N, useRef as P, useId as q, useMemo as F, useEffect as I, useLayoutEffect as G } from "react";
3
+ import { createPortal as J } from "react-dom";
4
+ import { AnimatePresence as Q, motion as V } from "motion/react";
5
+ import { Check as X, ChevronDown as Y } from "lucide-react";
6
+ import { cn as h } from "../lib/cn.js";
7
+ import { transitions as Z } from "../lib/motion.js";
8
+ function ae({
9
+ value: p,
10
+ options: i,
11
+ onChange: R,
12
+ ariaLabel: M,
13
+ placeholder: S,
14
+ disabled: v = !1,
15
+ density: H = "default",
16
+ menuAlign: g = "start",
17
+ portaled: l = !1,
18
+ className: $
19
+ }) {
20
+ const [r, d] = N(!1), [a, u] = N(-1), y = P(null), k = P(null), [B, j] = N(), m = q(), f = F(() => i.find((e) => e.value === p), [i, p]), E = !v && i.length > 0, b = (e, t) => {
21
+ var n;
22
+ for (let o = 0; o < i.length; o += 1) {
23
+ const s = (e + t * o + i.length) % i.length;
24
+ if (!((n = i[s]) != null && n.disabled)) return s;
25
+ }
26
+ return -1;
27
+ }, T = () => {
28
+ if (!E) return;
29
+ const e = i.findIndex((t) => t.value === p && !t.disabled);
30
+ u(e >= 0 ? e : b(0, 1)), d(!0);
31
+ };
32
+ I(() => {
33
+ if (!r) return;
34
+ const e = (n) => {
35
+ var s, w;
36
+ const o = n.target;
37
+ !((s = y.current) != null && s.contains(o)) && !((w = k.current) != null && w.contains(o)) && d(!1);
38
+ }, t = (n) => {
39
+ n.key === "Escape" && d(!1);
40
+ };
41
+ return document.addEventListener("mousedown", e, !0), document.addEventListener("keydown", t), () => {
42
+ document.removeEventListener("mousedown", e, !0), document.removeEventListener("keydown", t);
43
+ };
44
+ }, [r]), G(() => {
45
+ if (!r || !l) return;
46
+ const e = () => {
47
+ var K;
48
+ const t = (K = y.current) == null ? void 0 : K.getBoundingClientRect();
49
+ if (!t) return;
50
+ const n = 8, o = Math.max(220, t.width), s = g === "end" ? t.right - o : t.left, w = Math.max(n, Math.min(s, window.innerWidth - o - n)), D = window.innerHeight - t.bottom - n - 6, L = D < 160 && t.top > D;
51
+ j({
52
+ position: "fixed",
53
+ left: w,
54
+ top: L ? void 0 : t.bottom + 6,
55
+ bottom: L ? window.innerHeight - t.top + 6 : void 0,
56
+ width: o,
57
+ maxHeight: Math.max(96, Math.min(256, L ? t.top - 14 : D))
58
+ });
59
+ };
60
+ return e(), window.addEventListener("resize", e), window.addEventListener("scroll", e, !0), () => {
61
+ window.removeEventListener("resize", e), window.removeEventListener("scroll", e, !0);
62
+ };
63
+ }, [g, r, l]), I(() => {
64
+ v && d(!1);
65
+ }, [v]), I(() => {
66
+ if (!r || a < 0) return;
67
+ const e = k.current, t = e == null ? void 0 : e.children.item(a);
68
+ if (!e || !t) return;
69
+ const n = t.offsetTop, o = n + t.offsetHeight;
70
+ n < e.scrollTop ? e.scrollTop = n : o > e.scrollTop + e.clientHeight && (e.scrollTop = o - e.clientHeight);
71
+ }, [a, m, r]);
72
+ const A = (e) => {
73
+ const t = i[e];
74
+ !t || t.disabled || (R(t.value), d(!1));
75
+ }, z = (e) => {
76
+ u((t) => b(t < 0 ? e === 1 ? -1 : 0 : t + e, e));
77
+ }, U = (e) => {
78
+ if (E) {
79
+ if (!r) {
80
+ (e.key === "ArrowDown" || e.key === "ArrowUp" || e.key === "Enter" || e.key === " ") && (e.preventDefault(), T());
81
+ return;
82
+ }
83
+ O(e);
84
+ }
85
+ }, O = (e) => {
86
+ switch (e.key) {
87
+ case "ArrowDown":
88
+ e.preventDefault(), z(1);
89
+ break;
90
+ case "ArrowUp":
91
+ e.preventDefault(), z(-1);
92
+ break;
93
+ case "Home":
94
+ e.preventDefault(), u(b(0, 1));
95
+ break;
96
+ case "End":
97
+ e.preventDefault(), u(b(i.length - 1, -1));
98
+ break;
99
+ case "Enter":
100
+ case " ":
101
+ e.preventDefault(), a >= 0 && A(a);
102
+ break;
103
+ }
104
+ }, W = r && a >= 0 ? `${m}-opt-${a}` : void 0, C = /* @__PURE__ */ c(Q, { children: r && /* @__PURE__ */ c(
105
+ V.div,
106
+ {
107
+ ref: k,
108
+ id: m,
109
+ initial: { opacity: 0, y: -4, scale: 0.98 },
110
+ animate: { opacity: 1, y: 0, scale: 1 },
111
+ exit: { opacity: 0, y: -4, scale: 0.98 },
112
+ transition: Z.fade,
113
+ style: l ? B : void 0,
114
+ className: h(
115
+ "z-[100] max-h-64 w-full min-w-[220px] overflow-y-auto rounded-panel border border-border bg-surface-raised p-1 shadow-pop",
116
+ l ? "fixed" : "absolute top-[calc(100%+6px)]",
117
+ !l && (g === "end" ? "right-0" : "left-0")
118
+ ),
119
+ role: "listbox",
120
+ "aria-label": M,
121
+ children: i.map((e, t) => {
122
+ const n = e.value === p, o = t === a;
123
+ return /* @__PURE__ */ x(
124
+ "button",
125
+ {
126
+ id: `${m}-opt-${t}`,
127
+ type: "button",
128
+ role: "option",
129
+ "aria-selected": n,
130
+ disabled: e.disabled,
131
+ tabIndex: -1,
132
+ onMouseEnter: () => !e.disabled && u(t),
133
+ onClick: () => {
134
+ e.disabled || A(t);
135
+ },
136
+ className: h(
137
+ "flex min-h-row-default w-full min-w-0 items-center gap-2 rounded-control px-2.5 py-1.5 text-left font-sohne text-body-sm transition-colors disabled:cursor-not-allowed disabled:opacity-45",
138
+ n ? "bg-surface-muted font-[500] text-ink" : "text-graphite hover:bg-surface-hover hover:text-ink",
139
+ o && !n && "bg-surface-hover text-ink"
140
+ ),
141
+ children: [
142
+ e.leading,
143
+ /* @__PURE__ */ x("span", { className: "min-w-0 flex-1", children: [
144
+ /* @__PURE__ */ c("span", { className: "block truncate", children: e.label }),
145
+ e.meta && /* @__PURE__ */ c("span", { className: "mt-0.5 block truncate text-caption font-[450] text-graphite", children: e.meta })
146
+ ] }),
147
+ n && /* @__PURE__ */ c(X, { size: 14, className: "shrink-0 text-ink" })
148
+ ]
149
+ },
150
+ e.value
151
+ );
152
+ })
153
+ }
154
+ ) });
155
+ return /* @__PURE__ */ x("div", { ref: y, className: h("relative min-w-0", $), children: [
156
+ /* @__PURE__ */ x(
157
+ "button",
158
+ {
159
+ type: "button",
160
+ "aria-label": M,
161
+ "aria-haspopup": "listbox",
162
+ "aria-expanded": r,
163
+ "aria-controls": r ? m : void 0,
164
+ "aria-activedescendant": W,
165
+ disabled: !E,
166
+ "data-density": H,
167
+ onClick: () => r ? d(!1) : T(),
168
+ onKeyDown: U,
169
+ className: h(
170
+ "flex w-full min-w-0 items-center gap-2 rounded-control border border-border bg-pure-white font-sohne font-[500] leading-none text-ink outline-none transition hover:border-graphite hover:bg-surface-hover disabled:cursor-not-allowed disabled:text-graphite focus-visible:ring-2 focus-visible:ring-rust/35",
171
+ H === "compact" ? "h-control-compact px-2 text-caption" : "h-control-default px-3 text-body-sm"
172
+ ),
173
+ children: [
174
+ f == null ? void 0 : f.leading,
175
+ /* @__PURE__ */ c("span", { className: "min-w-0 flex-1 truncate text-left", children: (f == null ? void 0 : f.label) ?? S }),
176
+ /* @__PURE__ */ c(
177
+ Y,
178
+ {
179
+ size: 12,
180
+ className: h("shrink-0 text-ink transition-transform", r && "rotate-180")
181
+ }
182
+ )
183
+ ]
184
+ }
185
+ ),
186
+ l && typeof document < "u" ? J(C, document.body) : C
187
+ ] });
188
+ }
189
+ export {
190
+ ae as DropdownSelect
191
+ };
@@ -0,0 +1,21 @@
1
+ import { jsxs as s, jsx as o } from "react/jsx-runtime";
2
+ import { useId as f, isValidElement as g, cloneElement as b } from "react";
3
+ function I({ label: r, children: e, hint: i, error: t, required: l = !1, className: c = "" }) {
4
+ const p = f(), a = e.props.id ?? p, d = i ? `${a}-hint` : void 0, n = t ? `${a}-error` : void 0, m = [e.props["aria-describedby"], d, n].filter(Boolean).join(" ") || void 0, x = g(e) ? b(e, {
5
+ id: a,
6
+ "aria-describedby": m,
7
+ "aria-invalid": !!t || void 0
8
+ }) : e;
9
+ return /* @__PURE__ */ s("div", { className: `grid min-w-0 gap-1.5 font-sohne text-caption ${c}`, "data-slot": "field", children: [
10
+ /* @__PURE__ */ s("label", { htmlFor: a, className: "font-[500] text-graphite", children: [
11
+ r,
12
+ l && /* @__PURE__ */ o("span", { className: "ml-1 text-danger", "aria-hidden": !0, children: "*" })
13
+ ] }),
14
+ x,
15
+ i && /* @__PURE__ */ o("p", { id: d, className: "text-caption text-graphite", children: i }),
16
+ t && /* @__PURE__ */ o("p", { id: n, className: "text-caption text-danger", children: t })
17
+ ] });
18
+ }
19
+ export {
20
+ I as Field
21
+ };
@@ -0,0 +1,159 @@
1
+ import { jsxs as m, jsx as r } from "react/jsx-runtime";
2
+ import { useState as g, useRef as D, useEffect as v } from "react";
3
+ import { createPortal as X } from "react-dom";
4
+ import { Pin as S, X as B } from "lucide-react";
5
+ import { cn as x } from "../lib/cn.js";
6
+ import { useWideViewport as F } from "../lib/viewport.js";
7
+ const c = (o, d, f) => Math.max(d, Math.min(f, o));
8
+ function J({
9
+ open: o,
10
+ onClose: d,
11
+ title: f,
12
+ children: j,
13
+ initialW: w = 560,
14
+ initialH: p = 440,
15
+ minW: E = 320,
16
+ minH: R = 260,
17
+ pinLabel: y = "Pin",
18
+ unpinLabel: P = "Unpin",
19
+ closeLabel: b = "Close"
20
+ }) {
21
+ const n = F(640), [i, W] = g(!1), [l, Y] = g({ w, h: p }), [t, k] = g(null), u = D(null), s = D(null);
22
+ if (v(() => {
23
+ !o || typeof window > "u" || !n || k(
24
+ (e) => e ?? {
25
+ x: c((window.innerWidth - w) / 2, 16, Math.max(16, window.innerWidth - w - 16)),
26
+ y: c((window.innerHeight - p) / 3, 16, Math.max(16, window.innerHeight - p - 16))
27
+ }
28
+ );
29
+ }, [o, w, p, n]), v(() => {
30
+ if (!o || n && i) return;
31
+ const e = (a) => {
32
+ a.key === "Escape" && d();
33
+ };
34
+ return document.addEventListener("keydown", e), () => document.removeEventListener("keydown", e);
35
+ }, [o, i, d, n]), v(() => {
36
+ if (!o || n || typeof document > "u") return;
37
+ const e = document.body.style.overflow;
38
+ return document.body.style.overflow = "hidden", () => {
39
+ document.body.style.overflow = e;
40
+ };
41
+ }, [o, n]), !o || typeof document > "u" || n && !t) return null;
42
+ const z = (e) => {
43
+ try {
44
+ e.currentTarget.setPointerCapture(e.pointerId);
45
+ } catch {
46
+ }
47
+ }, H = (e) => {
48
+ !n || e.button !== 0 || !t || (u.current = { ox: e.clientX - t.x, oy: e.clientY - t.y }, z(e));
49
+ }, I = (e) => {
50
+ !n || !u.current || !t || k({
51
+ x: c(e.clientX - u.current.ox, 0, window.innerWidth - l.w),
52
+ y: c(e.clientY - u.current.oy, 0, window.innerHeight - 40)
53
+ });
54
+ }, N = (e) => {
55
+ var a, h;
56
+ u.current = null, (h = (a = e.currentTarget).releasePointerCapture) == null || h.call(a, e.pointerId);
57
+ }, T = (e) => {
58
+ !n || !t || (e.stopPropagation(), s.current = { sx: e.clientX, sy: e.clientY, sw: l.w, sh: l.h }, z(e));
59
+ }, U = (e) => {
60
+ !n || !s.current || !t || Y({
61
+ w: c(s.current.sw + (e.clientX - s.current.sx), E, window.innerWidth - t.x - 8),
62
+ h: c(s.current.sh + (e.clientY - s.current.sy), R, window.innerHeight - t.y - 8)
63
+ });
64
+ }, M = (e) => {
65
+ var a, h;
66
+ s.current = null, (h = (a = e.currentTarget).releasePointerCapture) == null || h.call(a, e.pointerId);
67
+ }, C = /* @__PURE__ */ m(
68
+ "div",
69
+ {
70
+ role: "dialog",
71
+ "aria-label": f,
72
+ className: x(
73
+ "flex flex-col overflow-hidden bg-surface-raised shadow-subtle ring-1 ring-border",
74
+ n ? "fixed z-50 rounded-overlay" : "relative z-10 h-[min(92dvh,var(--spacing-overlay-dashboard))] w-full max-w-none rounded-t-sheet pb-[env(safe-area-inset-bottom)]"
75
+ ),
76
+ style: n && t ? { left: t.x, top: t.y, width: l.w, height: l.h } : void 0,
77
+ children: [
78
+ /* @__PURE__ */ m(
79
+ "header",
80
+ {
81
+ onPointerDown: H,
82
+ onPointerMove: I,
83
+ onPointerUp: N,
84
+ onPointerCancel: N,
85
+ className: x(
86
+ "flex shrink-0 select-none items-center justify-between gap-2 border-b border-border bg-fog/50 px-3 py-2",
87
+ n ? "cursor-move touch-none" : "cursor-default"
88
+ ),
89
+ children: [
90
+ !n && /* @__PURE__ */ r("span", { className: "absolute left-1/2 top-1.5 h-1 w-10 -translate-x-1/2 rounded-full bg-dove/80", "aria-hidden": !0 }),
91
+ /* @__PURE__ */ r("span", { className: x("truncate font-sohne text-caption font-[480] text-ink", !n && "pt-1"), children: f }),
92
+ /* @__PURE__ */ m("div", { className: "flex shrink-0 items-center gap-1", children: [
93
+ n && /* @__PURE__ */ r(
94
+ "button",
95
+ {
96
+ type: "button",
97
+ onPointerDown: (e) => e.stopPropagation(),
98
+ onClick: () => W((e) => !e),
99
+ "aria-pressed": i,
100
+ title: i ? P : y,
101
+ "aria-label": i ? P : y,
102
+ className: x(
103
+ "grid h-6 w-6 place-items-center rounded-full transition hover:bg-dove/50",
104
+ i ? "text-ink" : "text-graphite"
105
+ ),
106
+ children: /* @__PURE__ */ r(S, { size: 13, fill: i ? "currentColor" : "none" })
107
+ }
108
+ ),
109
+ /* @__PURE__ */ r(
110
+ "button",
111
+ {
112
+ type: "button",
113
+ onPointerDown: (e) => e.stopPropagation(),
114
+ onClick: d,
115
+ title: b,
116
+ "aria-label": b,
117
+ className: "grid h-6 w-6 place-items-center rounded-full text-graphite transition hover:bg-dove/50 hover:text-ink",
118
+ children: /* @__PURE__ */ r(B, { size: 14, "aria-hidden": !0 })
119
+ }
120
+ )
121
+ ] })
122
+ ]
123
+ }
124
+ ),
125
+ /* @__PURE__ */ r("div", { className: "relative flex min-h-0 flex-1 flex-col p-2", children: j }),
126
+ n && /* @__PURE__ */ r(
127
+ "div",
128
+ {
129
+ onPointerDown: T,
130
+ onPointerMove: U,
131
+ onPointerUp: M,
132
+ onPointerCancel: M,
133
+ "aria-hidden": !0,
134
+ className: "absolute bottom-0 right-0 h-4 w-4 cursor-nwse-resize touch-none",
135
+ children: /* @__PURE__ */ r("svg", { viewBox: "0 0 10 10", className: "h-full w-full text-graphite/60", "aria-hidden": !0, children: /* @__PURE__ */ r("path", { d: "M9 3 L3 9 M9 6 L6 9", stroke: "currentColor", strokeWidth: "1", strokeLinecap: "round", fill: "none" }) })
136
+ }
137
+ )
138
+ ]
139
+ }
140
+ );
141
+ return n ? X(C, document.body) : X(
142
+ /* @__PURE__ */ m("div", { className: "fixed inset-0 z-50 flex items-end justify-center", children: [
143
+ /* @__PURE__ */ r(
144
+ "button",
145
+ {
146
+ type: "button",
147
+ "aria-label": b,
148
+ onClick: d,
149
+ className: "absolute inset-0 bg-black/45 backdrop-blur-[2px]"
150
+ }
151
+ ),
152
+ C
153
+ ] }),
154
+ document.body
155
+ );
156
+ }
157
+ export {
158
+ J as FloatingWindow
159
+ };
@@ -0,0 +1,21 @@
1
+ import { jsx as n } from "react/jsx-runtime";
2
+ import { cn as i } from "../lib/cn.js";
3
+ function g({
4
+ level: t = "base",
5
+ as: e = "h2",
6
+ className: s,
7
+ children: a
8
+ }) {
9
+ return /* @__PURE__ */ n(e, { className: i("font-signifier font-[600] tracking-[0] text-ink", {
10
+ display: "text-display",
11
+ lg: "text-heading-lg",
12
+ base: "text-heading"
13
+ }[t], s), children: a });
14
+ }
15
+ function x({ children: t, className: e }) {
16
+ return /* @__PURE__ */ n("h3", { className: i("font-sohne text-subheading font-[450] text-ink", e), children: t });
17
+ }
18
+ export {
19
+ g as Heading,
20
+ x as Subheading
21
+ };
@@ -0,0 +1,90 @@
1
+ import { jsxs as j, Fragment as k, jsx as f } from "react/jsx-runtime";
2
+ import { useRef as H, useState as T, useCallback as W, useLayoutEffect as v } from "react";
3
+ import { createPortal as F } from "react-dom";
4
+ import { AnimatePresence as I, motion as $ } from "motion/react";
5
+ import { cn as z } from "../lib/cn.js";
6
+ import { transitions as G } from "../lib/motion.js";
7
+ const t = 8;
8
+ function A(s, h, i) {
9
+ return Math.min(Math.max(h, s), i);
10
+ }
11
+ function O({
12
+ content: s,
13
+ children: h,
14
+ width: i = 240,
15
+ variant: e = "panel"
16
+ }) {
17
+ const d = H(null), R = H(null), a = H(null), [o, x] = T(null), [g, y] = T(!1), M = () => {
18
+ a.current && clearTimeout(a.current), a.current = null;
19
+ }, B = W(() => {
20
+ M();
21
+ const r = d.current;
22
+ if (!r) return;
23
+ const c = r.getBoundingClientRect();
24
+ y(!1), x({
25
+ top: c.bottom + 5,
26
+ left: c.left,
27
+ maxH: e === "hint" ? 96 : 240
28
+ });
29
+ }, [e]), w = W(() => {
30
+ M(), a.current = setTimeout(() => {
31
+ x(null), y(!1);
32
+ }, 140);
33
+ }, []);
34
+ return v(() => {
35
+ if (!o) return;
36
+ const r = R.current, c = d.current;
37
+ if (!r || !c) return;
38
+ const n = c.getBoundingClientRect(), C = r.getBoundingClientRect(), E = C.width || (e === "hint" ? 160 : i), p = C.height || 32, L = window.innerWidth, b = window.innerHeight, N = b - n.bottom - t < p + 8 && n.top > p + t;
39
+ let u = N ? n.top - 5 - p : n.bottom + 5;
40
+ u = A(u, t, Math.max(t, b - t - p));
41
+ let l;
42
+ e === "hint" ? l = n.left + n.width / 2 - E / 2 : l = n.left, l = A(l, t, Math.max(t, L - t - E));
43
+ const P = N ? Math.max(e === "hint" ? 48 : 120, n.top - t * 2) : Math.max(e === "hint" ? 48 : 120, b - u - t), m = { top: u, left: l, maxH: P };
44
+ (!g || Math.abs(m.top - o.top) > 0.5 || Math.abs(m.left - o.left) > 0.5 || Math.abs(m.maxH - o.maxH) > 0.5) && (x(m), y(!0));
45
+ }, [o, g, e, i, s]), /* @__PURE__ */ j(k, { children: [
46
+ /* @__PURE__ */ f(
47
+ "span",
48
+ {
49
+ ref: d,
50
+ className: "inline-flex",
51
+ onMouseEnter: B,
52
+ onMouseLeave: w,
53
+ onFocus: B,
54
+ onBlur: w,
55
+ children: h
56
+ }
57
+ ),
58
+ typeof document < "u" && F(
59
+ /* @__PURE__ */ f(I, { children: o && /* @__PURE__ */ f(
60
+ $.div,
61
+ {
62
+ ref: R,
63
+ role: "tooltip",
64
+ initial: { opacity: 0, y: -4 },
65
+ animate: { opacity: g ? 1 : 0, y: 0 },
66
+ exit: { opacity: 0, y: -4 },
67
+ transition: G.fade,
68
+ onMouseEnter: M,
69
+ onMouseLeave: w,
70
+ style: {
71
+ position: "fixed",
72
+ top: o.top,
73
+ left: o.left,
74
+ maxHeight: o.maxH,
75
+ ...e === "hint" ? { maxWidth: `min(${i}px, calc(100vw - ${t * 2}px))` } : { width: i }
76
+ },
77
+ className: z(
78
+ "z-[60]",
79
+ e === "hint" ? "pointer-events-none w-max rounded-md bg-ink px-2 py-1 shadow-pop" : "overflow-y-auto rounded-panel bg-surface-raised p-3 shadow-pop ring-1 ring-border"
80
+ ),
81
+ children: e === "hint" ? /* @__PURE__ */ f("div", { className: "font-sohne text-[11px] font-[480] leading-snug text-pure-white", children: s }) : s
82
+ }
83
+ ) }),
84
+ document.body
85
+ )
86
+ ] });
87
+ }
88
+ export {
89
+ O as HoverTip
90
+ };
@@ -0,0 +1,12 @@
1
+ import { jsx as t } from "react/jsx-runtime";
2
+ import "react";
3
+ import { HoverTip as i } from "./hover-tip.js";
4
+ function e({
5
+ label: o,
6
+ children: r
7
+ }) {
8
+ return /* @__PURE__ */ t(i, { content: o, variant: "hint", children: r });
9
+ }
10
+ export {
11
+ e as IconTip
12
+ };
@@ -0,0 +1,16 @@
1
+ import { jsxs as d, jsx as t } from "react/jsx-runtime";
2
+ import { isValidElement as l, cloneElement as p } from "react";
3
+ import { cn as s } from "../lib/cn.js";
4
+ function m({ label: i, start: e, end: o, children: r, className: n }) {
5
+ const a = l(r) ? p(r, {
6
+ className: s("min-w-0 flex-1 !rounded-none !border-0 !bg-transparent focus:!border-0 focus-visible:!ring-0", r.props.className)
7
+ }) : r;
8
+ return /* @__PURE__ */ d("div", { role: "group", "aria-label": i, "data-focus-shell": !0, className: s("flex min-w-0 items-center overflow-hidden rounded-control border border-border bg-pure-white has-[input:focus-visible]:border-rust/70 has-[input:focus-visible]:ring-2 has-[input:focus-visible]:ring-rust/20", n), children: [
9
+ e && /* @__PURE__ */ t("span", { "data-slot": "input-start", className: "shrink-0 border-r border-divider px-2.5 font-product text-caption text-graphite", children: e }),
10
+ a,
11
+ o && /* @__PURE__ */ t("span", { "data-slot": "input-end", className: "shrink-0 border-l border-divider px-2.5 font-product text-caption text-graphite", children: o })
12
+ ] });
13
+ }
14
+ export {
15
+ m as InputGroup
16
+ };