@reopt-ai/opt-ui 1.4.1 → 1.6.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/COMPONENT_CATALOG.md +374 -84
  2. package/README.md +28 -7
  3. package/dist/app.css +146 -0
  4. package/dist/core/index.cjs +164 -324
  5. package/dist/core/index.d.cts +3 -5
  6. package/dist/core/index.d.ts +3 -5
  7. package/dist/core/index.js +3 -323
  8. package/dist/docs/01-getting-started.md +25 -5
  9. package/dist/docs/02-components/01-core.md +192 -46
  10. package/dist/docs/02-components/02-visuals.md +1 -1
  11. package/dist/docs/02-components/03-shells.md +177 -42
  12. package/dist/docs/02-components/04-surfaces.md +1 -1
  13. package/dist/docs/02-components/index.md +1 -1
  14. package/dist/docs/03-recipes/03-layouts.md +20 -12
  15. package/dist/docs/04-theming.md +3 -1
  16. package/dist/docs/05-migration/01-breaking-changes.md +28 -0
  17. package/dist/id-registry.cjs +1899 -1872
  18. package/dist/id-registry.d.cts +13 -10
  19. package/dist/id-registry.d.cts.map +1 -0
  20. package/dist/id-registry.d.ts +13 -10
  21. package/dist/id-registry.d.ts.map +1 -0
  22. package/dist/id-registry.js +1897 -1871
  23. package/dist/id-registry.js.map +1 -0
  24. package/dist/id-registry.json +44 -44
  25. package/dist/index.cjs +8294 -9613
  26. package/dist/index.d.cts +1486 -1438
  27. package/dist/index.d.cts.map +1 -0
  28. package/dist/index.d.ts +1486 -1438
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +7933 -9600
  31. package/dist/index.js.map +1 -0
  32. package/dist/meta.cjs +7461 -6765
  33. package/dist/meta.d.cts.map +1 -0
  34. package/dist/meta.d.ts.map +1 -0
  35. package/dist/meta.js +7460 -6736
  36. package/dist/meta.js.map +1 -0
  37. package/dist/pagination-By7Ozv3U.js +3788 -0
  38. package/dist/pagination-By7Ozv3U.js.map +1 -0
  39. package/dist/pagination-Uv3CnGJz.cjs +4677 -0
  40. package/dist/shader-surface-BK1GMt5_.d.cts +1788 -0
  41. package/dist/shader-surface-BK1GMt5_.d.cts.map +1 -0
  42. package/dist/shader-surface-BWhO2xkk.js +3715 -0
  43. package/dist/shader-surface-BWhO2xkk.js.map +1 -0
  44. package/dist/shader-surface-DIVWtpFl.d.ts +1788 -0
  45. package/dist/shader-surface-DIVWtpFl.d.ts.map +1 -0
  46. package/dist/shader-surface-DxLLfrE6.cjs +4108 -0
  47. package/dist/shells/index.cjs +51 -65
  48. package/dist/shells/index.d.cts +4 -5
  49. package/dist/shells/index.d.ts +4 -5
  50. package/dist/shells/index.js +3 -64
  51. package/dist/tailwind.css +54 -5
  52. package/dist/theme/presets/default.css +12 -12
  53. package/dist/theme/server.cjs +310 -0
  54. package/dist/theme/server.d.cts +117 -0
  55. package/dist/theme/server.d.cts.map +1 -0
  56. package/dist/theme/server.d.ts +117 -0
  57. package/dist/theme/server.d.ts.map +1 -0
  58. package/dist/theme/server.js +287 -0
  59. package/dist/theme/server.js.map +1 -0
  60. package/dist/types-D0FlcYnM.d.cts +301 -0
  61. package/dist/types-D0FlcYnM.d.cts.map +1 -0
  62. package/dist/types-D0FlcYnM.d.ts +301 -0
  63. package/dist/types-D0FlcYnM.d.ts.map +1 -0
  64. package/dist/visuals/index.cjs +10 -4
  65. package/dist/visuals/index.d.cts +2 -1
  66. package/dist/visuals/index.d.ts +2 -1
  67. package/dist/visuals/index.js +1 -2
  68. package/dist/workflow-canvas-3Jeevkgy.cjs +2599 -0
  69. package/dist/workflow-canvas-BGBAcjf-.js +2403 -0
  70. package/dist/workflow-canvas-BGBAcjf-.js.map +1 -0
  71. package/dist/workflow-canvas-Bar_O2SQ.d.ts +494 -0
  72. package/dist/workflow-canvas-Bar_O2SQ.d.ts.map +1 -0
  73. package/dist/workflow-canvas-DghDRtHn.d.cts +494 -0
  74. package/dist/workflow-canvas-DghDRtHn.d.cts.map +1 -0
  75. package/package.json +24 -8
  76. package/dist/chunk-3GWWZKX7.js +0 -38
  77. package/dist/chunk-AFF2HPE5.cjs +0 -5008
  78. package/dist/chunk-ELWICXYY.js +0 -4745
  79. package/dist/chunk-N4NDU5ET.cjs +0 -4745
  80. package/dist/chunk-ONE3C5RV.cjs +0 -38
  81. package/dist/chunk-QWBHD54V.js +0 -3218
  82. package/dist/chunk-RBM2RNC2.js +0 -5008
  83. package/dist/chunk-X5WCXJAF.cjs +0 -3218
  84. package/dist/index-BZ_lBlO1.d.ts +0 -474
  85. package/dist/index-BuvxoWHf.d.cts +0 -474
  86. package/dist/index-DlAcuvQp.d.cts +0 -1686
  87. package/dist/index-Slu5hOj1.d.ts +0 -1686
  88. package/dist/types-D4-0lwaE.d.cts +0 -298
  89. package/dist/types-D4-0lwaE.d.ts +0 -298
@@ -0,0 +1,3788 @@
1
+ "use client";
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ import * as React from "react";
6
+ import { createContext, forwardRef, useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from "react";
7
+ import { AlertDialogPanel, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxPopover, ComboboxRoot, Composite, CompositeItem, CompositeProvider, CompositeRow, DialogDescription, DialogDisclosure, DialogDismiss, DialogHeading, DialogPanel, DialogRoot, DisclosureContent, DisclosureRoot, DisclosureTrigger, FormCheckbox, FormControl, FormDescription, FormError, FormField, FormGroup, FormGroupLabel, FormInput, FormLabel, FormProvider, FormPush, FormRadio, FormRadioGroup, FormRemove, FormReset, FormRoot, FormSubmit, FormSwitch, MenuButtonArrow, MenuItem, MenuItemCheckbox, MenuItemRadio, MenuPopover, MenuRoot, MenuSeparator, MenuTrigger, MenubarContainer, MenubarRoot, PopoverClose, PopoverContent, PopoverRoot, PopoverTrigger, SelectItem, SelectLabel, SelectPopover, SelectRoot, SelectTrigger, Tab, TabList, TabPanel, TabsRoot, ToolbarButton, ToolbarContainer, ToolbarRoot, ToolbarSeparator, Tooltip, TooltipAnchor, TooltipProvider, useFieldValue, useFormContext, useFormStore } from "@reopt-ai/opt-ui-primitives";
8
+ import { Bell, CalendarDays, ChartColumn, Check, ChevronLeft, ChevronRight, CircleAlert, CircleCheck, CreditCard, Download, Eye, FileText, Flag, Folder, Globe, Heart, Info, Link2, LogIn, Mail, MessageCircle, MousePointerClick, Search, Settings, Share2, ShoppingCart, Star, TrendingUp, TriangleAlert, Upload, User, UserPlus, XCircle, Zap } from "lucide-react";
9
+ //#region src/lib/cn.ts
10
+ /** Handles cn. */
11
+ function cn(...inputs) {
12
+ return twMerge(clsx(inputs));
13
+ }
14
+ //#endregion
15
+ //#region src/core/kbd.tsx
16
+ /** Renders the kbd component. */
17
+ function Kbd({ children, hint = false, className }) {
18
+ return /* @__PURE__ */ jsx("kbd", {
19
+ className: cn("border-border bg-bg-subtle text-text-tertiary inline-flex h-5 items-center gap-0.5 rounded border px-1.5 text-[11px] font-medium", hint && "opt-shortcut-hint", className),
20
+ "data-opt-id": "NPHB8",
21
+ "data-opt-slug": "kbd.Kbd",
22
+ children
23
+ });
24
+ }
25
+ //#endregion
26
+ //#region \0@oxc-project+runtime@0.140.0/helpers/esm/objectWithoutPropertiesLoose.js
27
+ function _objectWithoutPropertiesLoose(r, e) {
28
+ if (null == r) return {};
29
+ var t = {};
30
+ for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
31
+ if (e.includes(n)) continue;
32
+ t[n] = r[n];
33
+ }
34
+ return t;
35
+ }
36
+ //#endregion
37
+ //#region \0@oxc-project+runtime@0.140.0/helpers/esm/objectWithoutProperties.js
38
+ function _objectWithoutProperties(e, t) {
39
+ if (null == e) return {};
40
+ var o, r, i = _objectWithoutPropertiesLoose(e, t);
41
+ if (Object.getOwnPropertySymbols) {
42
+ var s = Object.getOwnPropertySymbols(e);
43
+ for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
44
+ }
45
+ return i;
46
+ }
47
+ //#endregion
48
+ //#region \0@oxc-project+runtime@0.140.0/helpers/esm/typeof.js
49
+ function _typeof(o) {
50
+ "@babel/helpers - typeof";
51
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
52
+ return typeof o;
53
+ } : function(o) {
54
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
55
+ }, _typeof(o);
56
+ }
57
+ //#endregion
58
+ //#region \0@oxc-project+runtime@0.140.0/helpers/esm/toPrimitive.js
59
+ function toPrimitive(t, r) {
60
+ if ("object" != _typeof(t) || !t) return t;
61
+ var e = t[Symbol.toPrimitive];
62
+ if (void 0 !== e) {
63
+ var i = e.call(t, r || "default");
64
+ if ("object" != _typeof(i)) return i;
65
+ throw new TypeError("@@toPrimitive must return a primitive value.");
66
+ }
67
+ return ("string" === r ? String : Number)(t);
68
+ }
69
+ //#endregion
70
+ //#region \0@oxc-project+runtime@0.140.0/helpers/esm/toPropertyKey.js
71
+ function toPropertyKey(t) {
72
+ var i = toPrimitive(t, "string");
73
+ return "symbol" == _typeof(i) ? i : i + "";
74
+ }
75
+ //#endregion
76
+ //#region \0@oxc-project+runtime@0.140.0/helpers/esm/defineProperty.js
77
+ function _defineProperty(e, r, t) {
78
+ return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
79
+ value: t,
80
+ enumerable: !0,
81
+ configurable: !0,
82
+ writable: !0
83
+ }) : e[r] = t, e;
84
+ }
85
+ //#endregion
86
+ //#region \0@oxc-project+runtime@0.140.0/helpers/esm/objectSpread2.js
87
+ function ownKeys(e, r) {
88
+ var t = Object.keys(e);
89
+ if (Object.getOwnPropertySymbols) {
90
+ var o = Object.getOwnPropertySymbols(e);
91
+ r && (o = o.filter(function(r) {
92
+ return Object.getOwnPropertyDescriptor(e, r).enumerable;
93
+ })), t.push.apply(t, o);
94
+ }
95
+ return t;
96
+ }
97
+ function _objectSpread2(e) {
98
+ for (var r = 1; r < arguments.length; r++) {
99
+ var t = null != arguments[r] ? arguments[r] : {};
100
+ r % 2 ? ownKeys(Object(t), !0).forEach(function(r) {
101
+ _defineProperty(e, r, t[r]);
102
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r) {
103
+ Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
104
+ });
105
+ }
106
+ return e;
107
+ }
108
+ //#endregion
109
+ //#region src/lib/styles.ts
110
+ /**
111
+ * 공유 스타일 토큰 — Primitive 전체에서 중복되는 Tailwind 패턴을 상수화합니다.
112
+ * 각 primitive는 이 토큰을 조합하고, 컴포넌트별 특수 스타일만 로컬에 정의합니다.
113
+ *
114
+ * CSS 변수 기반 — dark: prefix 불필요. 테마 프리셋이 모드별 값을 자동 해석합니다.
115
+ */
116
+ const OPT_FOCUS = "outline-none data-[focus-visible]:outline-2 data-[focus-visible]:outline-ring data-[focus-visible]:-outline-offset-1";
117
+ const OPT_FOCUS_VISIBLE = "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset";
118
+ const OPT_ACTIVE_ITEM = "data-[active-item]:bg-accent data-[active-item]:text-accent-fg";
119
+ const OPT_HOVER_ITEM = "[@media(any-hover:hover)]:hover:bg-accent-subtle active:bg-accent-subtle";
120
+ const OPT_BORDER = "border border-border";
121
+ const OPT_DIVIDER = "divide-border-subtle";
122
+ const OPT_SURFACE = "rounded-lg bg-surface shadow-sm";
123
+ const OPT_SURFACE_POPOVER = "z-50 rounded-lg border border-border bg-surface-overlay p-2 shadow-lg";
124
+ const OPT_TEXT_PRIMARY = "text-text-primary";
125
+ const OPT_TEXT_SECONDARY = "text-text-secondary";
126
+ const OPT_TEXT_TERTIARY = "text-text-tertiary";
127
+ const OPT_TEXT_LABEL = "text-sm font-medium text-text-primary";
128
+ const OPT_ITEM_BASE = "cursor-default rounded px-2 py-2 text-sm outline-none text-text-primary";
129
+ const OPT_INPUT = "flex h-10 w-full rounded-lg border border-border bg-surface px-4 text-sm text-text-primary outline-none placeholder:text-text-tertiary focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset";
130
+ const OPT_INPUT_SIZE = {
131
+ sm: "h-8 px-3 text-xs",
132
+ md: "",
133
+ lg: "h-12 px-5 text-base"
134
+ };
135
+ const OPT_TEXTAREA_SIZE = {
136
+ sm: "px-3 py-2 text-xs",
137
+ md: "",
138
+ lg: "px-5 py-4 text-base"
139
+ };
140
+ const OPT_INPUT_ERROR = "border-danger focus-visible:outline-danger";
141
+ const OPT_BADGE = "inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium";
142
+ const OPT_BADGE_BLUE = `${OPT_BADGE} bg-info-subtle text-info-fg`;
143
+ const OPT_BADGE_GREEN = `${OPT_BADGE} bg-success-subtle text-success-fg`;
144
+ const OPT_BADGE_YELLOW = `${OPT_BADGE} bg-warning-subtle text-warning-fg`;
145
+ const OPT_BADGE_RED = `${OPT_BADGE} bg-danger-subtle text-danger-fg`;
146
+ const OPT_BADGE_NEUTRAL = `${OPT_BADGE} bg-bg-subtle text-text-secondary`;
147
+ const OPT_BUTTON_PRIMARY = "inline-flex h-10 items-center justify-center rounded-lg bg-accent px-4 text-sm font-medium text-accent-fg outline-none hover:bg-accent-hover active:bg-accent-active focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2";
148
+ const OPT_BUTTON_SECONDARY = "inline-flex h-10 items-center justify-center rounded-lg border border-border bg-surface px-4 text-sm font-medium text-text-primary outline-none hover:bg-bg-subtle active:bg-bg-muted focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1";
149
+ const OPT_TH = "px-3 py-2.5 text-left text-xs font-semibold uppercase tracking-wider text-text-tertiary";
150
+ const OPT_TD = "px-3 py-2.5 text-sm text-text-primary whitespace-nowrap";
151
+ const OPT_TD_MUTED = "px-3 py-2.5 text-sm text-text-tertiary whitespace-nowrap";
152
+ const OPT_TABLE_ROW_ACTIVE = "outline-none data-[active-item]:bg-accent-subtle data-[focus-visible]:outline-2 data-[focus-visible]:outline-ring data-[focus-visible]:-outline-offset-1";
153
+ const OPT_DISCLOSURE_TRIGGER = "flex w-full items-center justify-between px-4 py-3.5 text-left text-sm font-medium text-text-primary outline-none hover:underline decoration-border underline-offset-2 data-[focus-visible]:outline-2 data-[focus-visible]:outline-ring data-[focus-visible]:-outline-offset-2";
154
+ const OPT_DISCLOSURE_CONTENT = "overflow-hidden data-[enter]:animate-in data-[enter]:fade-in data-[leave]:animate-out data-[leave]:fade-out";
155
+ const OPT_ANIMATE_ENTER_EXIT = "data-[enter]:animate-in data-[enter]:fade-in data-[enter]:slide-in-from-top-1 data-[leave]:animate-out data-[leave]:fade-out";
156
+ const OPT_ANIMATE_DIALOG = "data-[enter]:animate-in data-[enter]:fade-in data-[enter]:slide-in-from-top-2 data-[leave]:animate-out data-[leave]:fade-out data-[leave]:slide-out-to-top-2";
157
+ /**
158
+ * Drawer slide-in/out animations per side. ariakit `data-[enter]/data-[leave]`
159
+ * 패턴으로 `animate-in/animate-out` + `slide-in-from-{side}` 조합을 노출한다.
160
+ *
161
+ * Drawer 컴포넌트가 직접 인라인으로 정의하지 않고 이 토큰을 참조하도록 일관화.
162
+ */
163
+ const OPT_ANIMATE_DRAWER = {
164
+ right: "data-[enter]:animate-in data-[enter]:slide-in-from-right data-[leave]:animate-out data-[leave]:slide-out-to-right",
165
+ left: "data-[enter]:animate-in data-[enter]:slide-in-from-left data-[leave]:animate-out data-[leave]:slide-out-to-left",
166
+ bottom: "data-[enter]:animate-in data-[enter]:slide-in-from-bottom data-[leave]:animate-out data-[leave]:slide-out-to-bottom"
167
+ };
168
+ const OPT_DOT_GREEN = "h-2 w-2 rounded-full bg-success";
169
+ const OPT_DOT_YELLOW = "h-2 w-2 rounded-full bg-warning";
170
+ const OPT_DOT_RED = "h-2 w-2 rounded-full bg-danger";
171
+ const OPT_DOT_GRAY = "h-2 w-2 rounded-full bg-bg-muted";
172
+ //#endregion
173
+ //#region src/lib/field-messages.tsx
174
+ /**
175
+ * Internal utilities for field label/error/hint rendering.
176
+ * Not exported from the package — used only by Core components.
177
+ */
178
+ /** Renders a red asterisk for required fields. */
179
+ function RequiredMark() {
180
+ return /* @__PURE__ */ jsx("span", {
181
+ className: "text-danger-fg ml-0.5",
182
+ "aria-hidden": "true",
183
+ children: "*"
184
+ });
185
+ }
186
+ /** Computes the aria-describedby value from error/hint state. */
187
+ function getDescribedBy(id, error, hint) {
188
+ if (!id) return void 0;
189
+ if (error) return `${id}-error`;
190
+ if (hint) return `${id}-hint`;
191
+ }
192
+ /** Renders error or hint message below a field. Error takes priority. */
193
+ function FieldMessages({ id, error, hint }) {
194
+ if (!error && !hint) return null;
195
+ return /* @__PURE__ */ jsxs(Fragment, { children: [error && /* @__PURE__ */ jsx("p", {
196
+ id: id ? `${id}-error` : void 0,
197
+ className: "text-danger-fg text-sm",
198
+ role: "alert",
199
+ children: error
200
+ }), hint && !error && /* @__PURE__ */ jsx("p", {
201
+ id: id ? `${id}-hint` : void 0,
202
+ className: "text-text-tertiary text-sm",
203
+ children: hint
204
+ })] });
205
+ }
206
+ //#endregion
207
+ //#region src/lib/use-controlled-state.ts
208
+ /**
209
+ * Manages controlled/uncontrolled state for input components.
210
+ * When `controlledValue` is provided, acts as controlled; otherwise uses internal state.
211
+ */
212
+ function useControlledState(defaultValue, controlledValue, onChange) {
213
+ const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
214
+ const isControlled = controlledValue !== void 0;
215
+ return [isControlled ? controlledValue : uncontrolledValue, useCallback((newValue) => {
216
+ if (!isControlled) setUncontrolledValue(newValue);
217
+ onChange === null || onChange === void 0 || onChange(newValue);
218
+ }, [isControlled, onChange])];
219
+ }
220
+ //#endregion
221
+ //#region src/core/stat-card.tsx
222
+ /** Renders the stat card component. */
223
+ function StatCard({ title, value, change, trend, sparklineData, className }) {
224
+ const trendColor = trend === "up" ? "text-success-fg" : trend === "down" ? "text-danger-fg" : "text-text-tertiary";
225
+ const trendIcon = trend === "up" ? "↑" : trend === "down" ? "↓" : "→";
226
+ const sparkColor = trend === "up" ? "var(--opt-chart-diverging-positive)" : trend === "down" ? "var(--opt-chart-diverging-negative)" : "var(--opt-chart-1)";
227
+ return /* @__PURE__ */ jsx("div", {
228
+ className: cn(OPT_SURFACE, OPT_BORDER, "flex flex-col gap-1 p-5", className),
229
+ "data-opt-id": "GAX47",
230
+ "data-opt-slug": "stat-card.StatCard",
231
+ children: /* @__PURE__ */ jsxs("div", {
232
+ className: "flex items-start justify-between gap-4",
233
+ children: [/* @__PURE__ */ jsxs("div", {
234
+ className: "flex min-w-0 flex-col gap-1",
235
+ children: [
236
+ /* @__PURE__ */ jsx("span", {
237
+ className: cn(OPT_TEXT_SECONDARY, "truncate text-sm"),
238
+ children: title
239
+ }),
240
+ /* @__PURE__ */ jsx("span", {
241
+ className: cn(OPT_TEXT_PRIMARY, "text-2xl font-bold"),
242
+ children: value
243
+ }),
244
+ /* @__PURE__ */ jsxs("span", {
245
+ className: cn("text-sm font-medium", trendColor),
246
+ children: [
247
+ trendIcon,
248
+ " ",
249
+ change
250
+ ]
251
+ })
252
+ ]
253
+ }), sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsx(MiniSparkline, {
254
+ data: sparklineData,
255
+ color: sparkColor
256
+ })]
257
+ })
258
+ });
259
+ }
260
+ function MiniSparkline({ data, color }) {
261
+ const width = 80;
262
+ const height = 32;
263
+ const padding = 2;
264
+ const min = Math.min(...data);
265
+ const range = Math.max(...data) - min || 1;
266
+ const points = data.map((v, i) => {
267
+ return `${padding + i / (data.length - 1) * (width - padding * 2)},${padding + (1 - (v - min) / range) * (height - padding * 2)}`;
268
+ }).join(" ");
269
+ return /* @__PURE__ */ jsx("svg", {
270
+ width,
271
+ height,
272
+ viewBox: `0 0 ${width} ${height}`,
273
+ className: "flex-shrink-0 self-center",
274
+ "aria-hidden": "true",
275
+ children: /* @__PURE__ */ jsx("polyline", {
276
+ points,
277
+ fill: "none",
278
+ stroke: color,
279
+ strokeWidth: 1.5,
280
+ strokeLinecap: "round",
281
+ strokeLinejoin: "round"
282
+ })
283
+ });
284
+ }
285
+ StatCard.displayName = "StatCard";
286
+ //#endregion
287
+ //#region src/i18n/ko.ts
288
+ /**
289
+ * opt-ui Korean default labels.
290
+ *
291
+ * Components consume these as defaults so consumers don't have to pass labels
292
+ * for the most common case. Korean is the package default — other locales
293
+ * should be imported explicitly (e.g. `enLabels`) and passed via component
294
+ * props or wrapped with a labels provider.
295
+ */
296
+ const koComboboxLabels = { empty: "결과가 없습니다." };
297
+ const koStarRatingLabels = {
298
+ /** {value}/{max}점 — readonly fallback aria-label */
299
+ readonlyAriaLabel: "{value}/{max}점",
300
+ /** rating group aria-label */
301
+ groupAriaLabel: "별점",
302
+ /** {star}점 — individual star aria-label */
303
+ starAriaLabel: "{star}점"
304
+ };
305
+ const koBreadcrumbLabels = {
306
+ /** {label}(으)로 이동 */
307
+ navAriaLabel: "{label}(으)로 이동" };
308
+ //#endregion
309
+ //#region src/core/button.tsx
310
+ const _excluded$14 = [
311
+ "variant",
312
+ "size",
313
+ "loading",
314
+ "leftIcon",
315
+ "rightIcon",
316
+ "className",
317
+ "disabled",
318
+ "children",
319
+ "aria-busy"
320
+ ];
321
+ const variantStyles$2 = {
322
+ primary: "bg-accent text-accent-fg hover:bg-accent-hover active:bg-accent-active focus-visible:ring-offset-2",
323
+ secondary: "border border-border bg-surface text-text-primary hover:bg-bg-subtle active:bg-bg-muted focus-visible:ring-offset-1",
324
+ ghost: "text-text-secondary hover:bg-bg-subtle active:bg-bg-muted focus-visible:ring-offset-1",
325
+ danger: "bg-danger text-danger-fg hover:bg-danger active:bg-danger focus-visible:ring-offset-2"
326
+ };
327
+ const sizeStyles$3 = {
328
+ sm: "h-[var(--opt-control-sm)] px-[var(--opt-control-padding-sm)] text-xs gap-[var(--opt-space-1-5)]",
329
+ md: "h-[var(--opt-control-md)] px-[var(--opt-control-padding-md)] text-sm gap-[var(--opt-space-2)]",
330
+ lg: "h-[var(--opt-control-lg)] px-[var(--opt-control-padding-lg)] text-base gap-[var(--opt-space-2)]"
331
+ };
332
+ /** Renders the button component. */
333
+ function Button(_ref) {
334
+ let { variant = "primary", size = "md", loading = false, leftIcon, rightIcon, className, disabled, children, "aria-busy": ariaBusy } = _ref, props = _objectWithoutProperties(_ref, _excluded$14);
335
+ const isDisabled = disabled || loading;
336
+ return /* @__PURE__ */ jsxs("button", _objectSpread2(_objectSpread2({
337
+ type: "button",
338
+ className: cn("inline-flex cursor-pointer items-center justify-center rounded-lg font-medium transition-colors", OPT_FOCUS_VISIBLE, variantStyles$2[variant], sizeStyles$3[size], isDisabled && "pointer-events-none cursor-not-allowed opacity-50", className),
339
+ disabled: isDisabled
340
+ }, props), {}, {
341
+ "aria-busy": loading ? true : ariaBusy,
342
+ "data-opt-id": "RGX84",
343
+ "data-opt-slug": "button.Button",
344
+ "data-opt-component": "button",
345
+ "data-opt-part": "root",
346
+ "data-variant": variant,
347
+ "data-size": size,
348
+ "data-state": loading ? "loading" : isDisabled ? "disabled" : "idle",
349
+ children: [
350
+ loading ? /* @__PURE__ */ jsxs("svg", {
351
+ className: "h-4 w-4 animate-spin",
352
+ viewBox: "0 0 24 24",
353
+ fill: "none",
354
+ "aria-hidden": "true",
355
+ children: [/* @__PURE__ */ jsx("circle", {
356
+ className: "opacity-25",
357
+ cx: "12",
358
+ cy: "12",
359
+ r: "10",
360
+ stroke: "currentColor",
361
+ strokeWidth: "4"
362
+ }), /* @__PURE__ */ jsx("path", {
363
+ className: "opacity-75",
364
+ fill: "currentColor",
365
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
366
+ })]
367
+ }) : leftIcon,
368
+ children,
369
+ !loading && rightIcon
370
+ ]
371
+ }));
372
+ }
373
+ //#endregion
374
+ //#region src/core/empty-state.tsx
375
+ const iconSizeClasses = {
376
+ sm: "text-3xl",
377
+ md: "text-4xl",
378
+ lg: "text-5xl"
379
+ };
380
+ /** Renders the empty state component. */
381
+ function EmptyState({ icon, title, description, actions, className, iconSize = "md", headingLevel = "h3" }) {
382
+ const HeadingTag = headingLevel;
383
+ return /* @__PURE__ */ jsxs("div", {
384
+ role: "status",
385
+ "aria-label": title,
386
+ className: cn("flex flex-col items-center justify-center px-4 py-12 text-center", className),
387
+ "data-opt-id": "5ZK92",
388
+ "data-opt-slug": "empty-state.EmptyState",
389
+ children: [
390
+ icon && /* @__PURE__ */ jsx("div", {
391
+ className: cn(`mb-4 text-text-tertiary`, iconSizeClasses[iconSize]),
392
+ "aria-hidden": "true",
393
+ children: icon
394
+ }),
395
+ /* @__PURE__ */ jsx(HeadingTag, {
396
+ className: `text-lg font-semibold ${OPT_TEXT_PRIMARY}`,
397
+ children: title
398
+ }),
399
+ description && /* @__PURE__ */ jsx("p", {
400
+ className: `mt-2 max-w-sm text-sm text-text-secondary`,
401
+ children: description
402
+ }),
403
+ actions && actions.length > 0 && /* @__PURE__ */ jsx("div", {
404
+ className: "mt-6 flex items-center gap-3",
405
+ children: actions.map((action) => /* @__PURE__ */ jsx(Button, {
406
+ onClick: action.onClick,
407
+ disabled: action.disabled,
408
+ variant: action.variant === "secondary" ? "secondary" : "primary",
409
+ children: action.label
410
+ }, action.id))
411
+ })
412
+ ]
413
+ });
414
+ }
415
+ //#endregion
416
+ //#region src/core/badge.tsx
417
+ const _excluded$13 = [
418
+ "variant",
419
+ "size",
420
+ "dot",
421
+ "progress",
422
+ "progressSize",
423
+ "className",
424
+ "children"
425
+ ];
426
+ const variantStyles$1 = {
427
+ default: "bg-bg-subtle text-text-secondary",
428
+ success: "bg-success-subtle text-success-fg",
429
+ warning: "bg-warning-subtle text-warning-fg",
430
+ error: "bg-danger-subtle text-danger-fg",
431
+ info: "bg-info-subtle text-info-fg"
432
+ };
433
+ const dotStyles = {
434
+ default: "bg-text-tertiary",
435
+ success: "bg-success",
436
+ warning: "bg-warning",
437
+ error: "bg-danger",
438
+ info: "bg-info"
439
+ };
440
+ const progressStroke = {
441
+ default: "stroke-text-tertiary",
442
+ success: "stroke-success",
443
+ warning: "stroke-warning",
444
+ error: "stroke-danger",
445
+ info: "stroke-info"
446
+ };
447
+ const sizeStyles$2 = {
448
+ sm: "px-1.5 py-0.5 text-[10px]",
449
+ md: "px-2 py-0.5 text-[11px]"
450
+ };
451
+ /** Renders the badge component. */
452
+ function Badge(_ref) {
453
+ let { variant = "default", size = "md", dot = false, progress, progressSize = 16, className, children } = _ref, props = _objectWithoutProperties(_ref, _excluded$13);
454
+ const hasProgress = progress != null;
455
+ const clampedProgress = hasProgress ? Math.min(100, Math.max(0, progress)) : 0;
456
+ const radius = (progressSize - 3) / 2;
457
+ const circumference = 2 * Math.PI * radius;
458
+ const offset = circumference - clampedProgress / 100 * circumference;
459
+ return /* @__PURE__ */ jsxs("span", _objectSpread2(_objectSpread2({ className: cn(OPT_BADGE, variantStyles$1[variant], sizeStyles$2[size], className) }, props), {}, {
460
+ "data-opt-id": "9GBGZ",
461
+ "data-opt-slug": "badge.Badge",
462
+ children: [
463
+ hasProgress && /* @__PURE__ */ jsxs("svg", {
464
+ width: progressSize,
465
+ height: progressSize,
466
+ viewBox: `0 0 ${progressSize} ${progressSize}`,
467
+ className: "mr-1 -ml-0.5 shrink-0",
468
+ "aria-hidden": "true",
469
+ children: [/* @__PURE__ */ jsx("circle", {
470
+ cx: progressSize / 2,
471
+ cy: progressSize / 2,
472
+ r: radius,
473
+ fill: "none",
474
+ strokeWidth: 2,
475
+ className: "stroke-current opacity-20"
476
+ }), /* @__PURE__ */ jsx("circle", {
477
+ cx: progressSize / 2,
478
+ cy: progressSize / 2,
479
+ r: radius,
480
+ fill: "none",
481
+ strokeWidth: 2,
482
+ strokeLinecap: "round",
483
+ strokeDasharray: circumference,
484
+ strokeDashoffset: offset,
485
+ className: cn(progressStroke[variant], "transition-all"),
486
+ transform: `rotate(-90 ${progressSize / 2} ${progressSize / 2})`
487
+ })]
488
+ }),
489
+ dot && !hasProgress && /* @__PURE__ */ jsx("span", {
490
+ className: cn("mr-1.5 h-1.5 w-1.5 rounded-full", dotStyles[variant]),
491
+ "aria-hidden": "true"
492
+ }),
493
+ children
494
+ ]
495
+ }));
496
+ }
497
+ //#endregion
498
+ //#region src/core/spinner.tsx
499
+ const _excluded$12 = [
500
+ "size",
501
+ "className",
502
+ "role",
503
+ "aria-hidden",
504
+ "aria-label"
505
+ ];
506
+ const sizeStyles$1 = {
507
+ sm: "h-4 w-4",
508
+ md: "h-6 w-6",
509
+ lg: "h-8 w-8"
510
+ };
511
+ /** Renders the spinner component. */
512
+ function Spinner(_ref) {
513
+ let { size = "md", className, role, "aria-hidden": ariaHidden, "aria-label": ariaLabel } = _ref, props = _objectWithoutProperties(_ref, _excluded$12);
514
+ const isDecorative = ariaHidden === true || ariaHidden === "true";
515
+ return /* @__PURE__ */ jsxs("svg", _objectSpread2(_objectSpread2({
516
+ className: cn("animate-spin text-current", sizeStyles$1[size], className),
517
+ viewBox: "0 0 24 24",
518
+ fill: "none",
519
+ role: isDecorative ? void 0 : role !== null && role !== void 0 ? role : "status",
520
+ "aria-hidden": ariaHidden,
521
+ "aria-label": isDecorative ? void 0 : ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : "Loading"
522
+ }, props), {}, {
523
+ "data-opt-id": "DJS29",
524
+ "data-opt-slug": "spinner.Spinner",
525
+ children: [/* @__PURE__ */ jsx("circle", {
526
+ className: "opacity-25",
527
+ cx: "12",
528
+ cy: "12",
529
+ r: "10",
530
+ stroke: "currentColor",
531
+ strokeWidth: "4"
532
+ }), /* @__PURE__ */ jsx("path", {
533
+ className: "opacity-75",
534
+ fill: "currentColor",
535
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
536
+ })]
537
+ }));
538
+ }
539
+ //#endregion
540
+ //#region src/core/alert.tsx
541
+ const _excluded$11 = [
542
+ "variant",
543
+ "title",
544
+ "icon",
545
+ "dismissible",
546
+ "onDismiss",
547
+ "className",
548
+ "children"
549
+ ];
550
+ const variantStyles = {
551
+ info: "border-info bg-info-subtle text-info-fg",
552
+ success: "border-success bg-success-subtle text-success-fg",
553
+ warning: "border-warning bg-warning-subtle text-warning-fg",
554
+ error: "border-danger bg-danger-subtle text-danger-fg"
555
+ };
556
+ const iconColors = {
557
+ info: "text-info-fg",
558
+ success: "text-success-fg",
559
+ warning: "text-warning-fg",
560
+ error: "text-danger-fg"
561
+ };
562
+ const defaultIcons = {
563
+ info: /* @__PURE__ */ jsx("svg", {
564
+ className: "h-5 w-5",
565
+ viewBox: "0 0 20 20",
566
+ fill: "currentColor",
567
+ "aria-hidden": "true",
568
+ children: /* @__PURE__ */ jsx("path", {
569
+ fillRule: "evenodd",
570
+ d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z",
571
+ clipRule: "evenodd"
572
+ })
573
+ }),
574
+ success: /* @__PURE__ */ jsx("svg", {
575
+ className: "h-5 w-5",
576
+ viewBox: "0 0 20 20",
577
+ fill: "currentColor",
578
+ "aria-hidden": "true",
579
+ children: /* @__PURE__ */ jsx("path", {
580
+ fillRule: "evenodd",
581
+ d: "M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z",
582
+ clipRule: "evenodd"
583
+ })
584
+ }),
585
+ warning: /* @__PURE__ */ jsx("svg", {
586
+ className: "h-5 w-5",
587
+ viewBox: "0 0 20 20",
588
+ fill: "currentColor",
589
+ "aria-hidden": "true",
590
+ children: /* @__PURE__ */ jsx("path", {
591
+ fillRule: "evenodd",
592
+ d: "M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z",
593
+ clipRule: "evenodd"
594
+ })
595
+ }),
596
+ error: /* @__PURE__ */ jsx("svg", {
597
+ className: "h-5 w-5",
598
+ viewBox: "0 0 20 20",
599
+ fill: "currentColor",
600
+ "aria-hidden": "true",
601
+ children: /* @__PURE__ */ jsx("path", {
602
+ fillRule: "evenodd",
603
+ d: "M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z",
604
+ clipRule: "evenodd"
605
+ })
606
+ })
607
+ };
608
+ /** Renders the alert component. */
609
+ function Alert(_ref) {
610
+ let { variant = "info", title, icon, dismissible = false, onDismiss, className, children } = _ref, props = _objectWithoutProperties(_ref, _excluded$11);
611
+ const displayIcon = icon !== null && icon !== void 0 ? icon : defaultIcons[variant];
612
+ return /* @__PURE__ */ jsx("div", _objectSpread2(_objectSpread2({
613
+ role: "alert",
614
+ className: cn("relative rounded-lg border p-4", variantStyles[variant], className)
615
+ }, props), {}, {
616
+ "data-opt-id": "4SPK6",
617
+ "data-opt-slug": "alert.Alert",
618
+ children: /* @__PURE__ */ jsxs("div", {
619
+ className: "flex",
620
+ children: [
621
+ displayIcon && /* @__PURE__ */ jsx("div", {
622
+ className: cn("flex-shrink-0", iconColors[variant]),
623
+ children: displayIcon
624
+ }),
625
+ /* @__PURE__ */ jsxs("div", {
626
+ className: cn("flex-1", displayIcon && "ml-3"),
627
+ children: [title && /* @__PURE__ */ jsx("h3", {
628
+ className: "text-sm font-medium",
629
+ children: title
630
+ }), children && /* @__PURE__ */ jsx("div", {
631
+ className: cn("text-sm", title && "mt-1", "opacity-90"),
632
+ children
633
+ })]
634
+ }),
635
+ dismissible && /* @__PURE__ */ jsx("div", {
636
+ className: "ml-auto pl-3",
637
+ children: /* @__PURE__ */ jsx("button", {
638
+ type: "button",
639
+ onClick: onDismiss,
640
+ className: cn("hover:bg-bg-subtle inline-flex rounded-md p-1.5 transition-colors", "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset"),
641
+ "aria-label": "Dismiss",
642
+ children: /* @__PURE__ */ jsx("svg", {
643
+ className: "h-4 w-4",
644
+ viewBox: "0 0 20 20",
645
+ fill: "currentColor",
646
+ "aria-hidden": "true",
647
+ children: /* @__PURE__ */ jsx("path", { d: "M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" })
648
+ })
649
+ })
650
+ })
651
+ ]
652
+ })
653
+ }));
654
+ }
655
+ //#endregion
656
+ //#region src/lib/use-input-id.ts
657
+ /**
658
+ * Generates a stable component ID from label text.
659
+ * Eliminates the duplicated `id ?? label?.replace(...)` pattern across input components.
660
+ */
661
+ function useInputId(id, label, prefix) {
662
+ return id !== null && id !== void 0 ? id : label ? `${prefix}-${label.replace(/\s+/g, "-").toLowerCase()}` : void 0;
663
+ }
664
+ //#endregion
665
+ //#region src/core/star-rating.tsx
666
+ function interpolate(template, values) {
667
+ return template.replace(/\{(\w+)\}/g, (_, key) => key in values ? String(values[key]) : `{${key}}`);
668
+ }
669
+ const sizeMap = {
670
+ sm: "h-4 w-4",
671
+ md: "h-5 w-5",
672
+ lg: "h-6 w-6"
673
+ };
674
+ const gapMap = {
675
+ sm: "gap-0.5",
676
+ md: "gap-1",
677
+ lg: "gap-1"
678
+ };
679
+ function StarIcon({ filled, className }) {
680
+ return /* @__PURE__ */ jsx("svg", {
681
+ viewBox: "0 0 24 24",
682
+ className: cn(filled ? "fill-amber-400 text-amber-400" : "text-text-tertiary fill-none", className),
683
+ stroke: "currentColor",
684
+ strokeWidth: 1.5,
685
+ strokeLinecap: "round",
686
+ strokeLinejoin: "round",
687
+ "aria-hidden": "true",
688
+ children: /* @__PURE__ */ jsx("path", { d: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" })
689
+ });
690
+ }
691
+ /** Renders the star rating component. */
692
+ function StarRating({ value = 0, onChange, max = 5, readOnly = false, size = "md", className, ariaLabel }) {
693
+ const id = useId();
694
+ const [hovered, setHovered] = useState(null);
695
+ const displayValue = hovered !== null && hovered !== void 0 ? hovered : value;
696
+ const iconSize = sizeMap[size];
697
+ const gap = gapMap[size];
698
+ const handleClick = useCallback((star) => {
699
+ if (!readOnly && onChange) onChange(star);
700
+ }, [readOnly, onChange]);
701
+ const handleKeyDown = useCallback((e) => {
702
+ if (readOnly || !onChange) return;
703
+ if (e.key === "ArrowRight" || e.key === "ArrowUp") {
704
+ e.preventDefault();
705
+ onChange(Math.min(value + 1, max));
706
+ } else if (e.key === "ArrowLeft" || e.key === "ArrowDown") {
707
+ e.preventDefault();
708
+ onChange(Math.max(value - 1, 1));
709
+ } else if (e.key === "Home") {
710
+ e.preventDefault();
711
+ onChange(1);
712
+ } else if (e.key === "End") {
713
+ e.preventDefault();
714
+ onChange(max);
715
+ }
716
+ }, [
717
+ readOnly,
718
+ onChange,
719
+ value,
720
+ max
721
+ ]);
722
+ if (readOnly) return /* @__PURE__ */ jsx("div", {
723
+ className: cn("inline-flex items-center", gap, className),
724
+ role: "img",
725
+ "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : interpolate(koStarRatingLabels.readonlyAriaLabel, {
726
+ value,
727
+ max
728
+ }),
729
+ "data-opt-id": "B6ZY4",
730
+ "data-opt-slug": "star-rating.StarRating",
731
+ children: Array.from({ length: max }, (_, i) => /* @__PURE__ */ jsx(StarIcon, {
732
+ filled: i < value,
733
+ className: iconSize
734
+ }, i))
735
+ });
736
+ return /* @__PURE__ */ jsxs("div", {
737
+ className: cn("inline-flex items-center", gap, className),
738
+ role: "radiogroup",
739
+ "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : koStarRatingLabels.groupAriaLabel,
740
+ onKeyDown: handleKeyDown,
741
+ onMouseLeave: () => setHovered(null),
742
+ "data-opt-id": "B6ZY4",
743
+ "data-opt-slug": "star-rating.StarRating",
744
+ children: [Array.from({ length: max }, (_, i) => {
745
+ const star = i + 1;
746
+ const checked = star === value;
747
+ return /* @__PURE__ */ jsx("button", {
748
+ type: "button",
749
+ role: "radio",
750
+ "aria-checked": checked,
751
+ "aria-label": interpolate(koStarRatingLabels.starAriaLabel, { star }),
752
+ tabIndex: checked || value === 0 && i === 0 ? 0 : -1,
753
+ className: cn("cursor-pointer rounded-sm transition-transform", "focus-visible:outline-accent hover:scale-110 focus-visible:outline-2 focus-visible:outline-offset-2"),
754
+ onClick: () => handleClick(star),
755
+ onMouseEnter: () => setHovered(star),
756
+ children: /* @__PURE__ */ jsx(StarIcon, {
757
+ filled: i < displayValue,
758
+ className: iconSize
759
+ })
760
+ }, i);
761
+ }), /* @__PURE__ */ jsx("input", {
762
+ type: "hidden",
763
+ name: `${id}-rating`,
764
+ value
765
+ })]
766
+ });
767
+ }
768
+ //#endregion
769
+ //#region src/core/composite-zone.tsx
770
+ /** Renders the composite zone component. */
771
+ function CompositeZone({ children, label, focusLoop = true, focusWrap = true, className }) {
772
+ return /* @__PURE__ */ jsx(CompositeProvider, {
773
+ focusLoop,
774
+ focusWrap,
775
+ "data-opt-id": "1JZXE",
776
+ "data-opt-slug": "composite-zone.CompositeZone",
777
+ children: /* @__PURE__ */ jsx(Composite, {
778
+ role: "grid",
779
+ "aria-label": label,
780
+ className,
781
+ children
782
+ })
783
+ });
784
+ }
785
+ //#endregion
786
+ //#region src/core/disclosure.tsx
787
+ const _excluded$10 = ["className"];
788
+ const _excluded2$8 = ["className"];
789
+ const triggerClass$1 = `flex w-full cursor-pointer items-center justify-between px-4 py-4 text-left text-sm font-medium text-text-primary transition-colors hover:bg-bg-subtle ${OPT_FOCUS} data-[active-item]:bg-bg-subtle data-[disabled]:cursor-not-allowed`;
790
+ const contentClass = `overflow-hidden ${OPT_ANIMATE_ENTER_EXIT}`;
791
+ /** Renders the disclosure root component. */
792
+ function DisclosureRoot$1(props) {
793
+ return /* @__PURE__ */ jsx(DisclosureRoot, _objectSpread2(_objectSpread2({ animated: true }, props), {}, {
794
+ "data-opt-id": "AS61F",
795
+ "data-opt-slug": "disclosure.DisclosureRoot"
796
+ }));
797
+ }
798
+ /** Renders the disclosure trigger component. */
799
+ function DisclosureTrigger$1(_ref) {
800
+ let { className } = _ref, props = _objectWithoutProperties(_ref, _excluded$10);
801
+ return /* @__PURE__ */ jsx(DisclosureTrigger, _objectSpread2(_objectSpread2({ className: cn(triggerClass$1, className) }, props), {}, {
802
+ "data-opt-id": "14EZW",
803
+ "data-opt-slug": "disclosure.DisclosureTrigger"
804
+ }));
805
+ }
806
+ /** Renders the disclosure content component. */
807
+ function DisclosureContent$1(_ref2) {
808
+ let { className } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$8);
809
+ return /* @__PURE__ */ jsx(DisclosureContent, _objectSpread2(_objectSpread2({ className: cn(contentClass, className) }, props), {}, {
810
+ "data-opt-id": "78HYF",
811
+ "data-opt-slug": "disclosure.DisclosureContent"
812
+ }));
813
+ }
814
+ //#endregion
815
+ //#region src/core/tabs.tsx
816
+ const _excluded$9 = ["variant"];
817
+ const _excluded2$7 = ["className", "actions"];
818
+ const _excluded3$7 = [
819
+ "className",
820
+ "icon",
821
+ "status",
822
+ "statusLabel",
823
+ "children"
824
+ ];
825
+ const _excluded4$5 = ["className"];
826
+ const TabsVariantContext = React.createContext("underline");
827
+ const tabClass = `cursor-pointer border-b-2 border-transparent px-4 py-2.5 text-sm text-text-tertiary transition-colors hover:text-text-primary data-[active-item]:text-text-primary data-[active-item]:border-text-primary data-[disabled]:cursor-not-allowed ${OPT_FOCUS}`;
828
+ const tabListClass = "flex border-b border-border-subtle";
829
+ const workspaceTabClass = `group relative inline-flex min-h-9 min-w-33 max-w-54 flex-none cursor-pointer items-center gap-element rounded-t-md border border-b-0 border-transparent px-group py-element font-mono text-xs text-text-tertiary transition-colors data-[disabled]:cursor-not-allowed [&:not([data-active-item]):hover]:bg-raised [&:not([data-active-item]):hover]:text-secondary data-[active-item]:z-10 data-[active-item]:-mb-px data-[active-item]:border-border data-[active-item]:bg-surface data-[active-item]:text-primary before:absolute before:inset-x-group before:top-0 before:h-0.5 before:rounded-b-sm before:bg-accent before:opacity-0 before:transition-opacity before:content-[''] data-[active-item]:before:opacity-100 ${OPT_FOCUS}`;
830
+ const workspaceTabListClass = "flex min-w-0 flex-1 items-end gap-element overflow-x-auto px-element [scrollbar-width:thin]";
831
+ const workspaceBarClass = "flex min-h-11 items-end border-b border-border bg-subtle pt-element";
832
+ const workspaceActionsClass = "flex flex-none items-center gap-element self-stretch border-l border-border-subtle bg-subtle px-element";
833
+ const barClass = "flex items-center justify-between gap-group";
834
+ const actionsClass = "flex flex-none items-center gap-element";
835
+ const tabPanelClass = `pt-4 ${OPT_FOCUS} data-[focus-visible]:rounded-lg`;
836
+ /** Renders the tabs root component. */
837
+ function TabsRoot$1(_ref) {
838
+ let { variant = "underline" } = _ref, props = _objectWithoutProperties(_ref, _excluded$9);
839
+ return /* @__PURE__ */ jsx(TabsVariantContext.Provider, {
840
+ value: variant,
841
+ children: /* @__PURE__ */ jsx(TabsRoot, _objectSpread2(_objectSpread2({}, props), {}, {
842
+ "data-opt-id": "DJ8K8",
843
+ "data-opt-slug": "tabs.TabsRoot"
844
+ }))
845
+ });
846
+ }
847
+ /** Renders the tab list component. */
848
+ function TabList$1(_ref2) {
849
+ let { className, actions } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$7);
850
+ const variant = React.useContext(TabsVariantContext);
851
+ const list = /* @__PURE__ */ jsx(TabList, _objectSpread2(_objectSpread2({ className: cn(variant === "workspace" ? workspaceTabListClass : tabListClass, className) }, props), {}, {
852
+ "data-opt-id": "68K7E",
853
+ "data-opt-slug": "tabs.TabList"
854
+ }));
855
+ if (!actions) return list;
856
+ return /* @__PURE__ */ jsxs("div", {
857
+ className: variant === "workspace" ? workspaceBarClass : barClass,
858
+ children: [list, /* @__PURE__ */ jsx("div", {
859
+ className: variant === "workspace" ? workspaceActionsClass : actionsClass,
860
+ children: actions
861
+ })]
862
+ });
863
+ }
864
+ /** Renders the tab component. */
865
+ function Tab$1(_ref3) {
866
+ let { className, icon, status, statusLabel, children } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$7);
867
+ const variant = React.useContext(TabsVariantContext);
868
+ const decorated = icon != null || status != null;
869
+ return /* @__PURE__ */ jsx(Tab, _objectSpread2(_objectSpread2({ className: cn(variant === "workspace" ? workspaceTabClass : tabClass, className) }, props), {}, {
870
+ "data-opt-id": "HZTNP",
871
+ "data-opt-slug": "tabs.Tab",
872
+ children: decorated ? /* @__PURE__ */ jsxs(Fragment, { children: [
873
+ icon != null && /* @__PURE__ */ jsx("span", {
874
+ "aria-hidden": "true",
875
+ className: "text-text-tertiary group-data-[active-item]:text-accent flex flex-none items-center transition-colors",
876
+ children: icon
877
+ }),
878
+ /* @__PURE__ */ jsx("span", {
879
+ className: "min-w-0 flex-1 truncate text-left",
880
+ children
881
+ }),
882
+ status != null && /* @__PURE__ */ jsx("span", {
883
+ role: "status",
884
+ "aria-label": statusLabel,
885
+ className: cn("size-element flex-none rounded-full", status === "running" ? "bg-accent ring-accent-subtle ring-2" : "bg-text-tertiary")
886
+ })
887
+ ] }) : children
888
+ }));
889
+ }
890
+ /** Renders the tab panel component. */
891
+ function TabPanel$1(_ref4) {
892
+ let { className } = _ref4, props = _objectWithoutProperties(_ref4, _excluded4$5);
893
+ return /* @__PURE__ */ jsx(TabPanel, _objectSpread2(_objectSpread2({ className: cn(tabPanelClass, className) }, props), {}, {
894
+ "data-opt-id": "C0MBP",
895
+ "data-opt-slug": "tabs.TabPanel"
896
+ }));
897
+ }
898
+ //#endregion
899
+ //#region src/core/select.tsx
900
+ const _excluded$8 = [
901
+ "className",
902
+ "minWidth",
903
+ "style"
904
+ ];
905
+ const _excluded2$6 = ["className"];
906
+ const _excluded3$6 = ["className"];
907
+ const triggerClass = `${OPT_INPUT} cursor-pointer items-center justify-between data-[disabled]:cursor-not-allowed ${OPT_FOCUS}`;
908
+ const popoverClass$1 = `${OPT_SURFACE_POPOVER} ${OPT_ANIMATE_ENTER_EXIT} z-[120]`;
909
+ const itemClass$1 = `flex cursor-pointer items-center gap-2 data-[disabled]:cursor-not-allowed ${OPT_ITEM_BASE} ${OPT_ACTIVE_ITEM}`;
910
+ /** Renders the select root component. */
911
+ function SelectRoot$1(props) {
912
+ return /* @__PURE__ */ jsx(SelectRoot, _objectSpread2(_objectSpread2({}, props), {}, {
913
+ "data-opt-id": "A5TYW",
914
+ "data-opt-slug": "select.SelectRoot"
915
+ }));
916
+ }
917
+ /** Renders the select label component. */
918
+ function SelectLabel$1(props) {
919
+ return /* @__PURE__ */ jsx(SelectLabel, _objectSpread2(_objectSpread2({}, props), {}, {
920
+ "data-opt-id": "SKM59",
921
+ "data-opt-slug": "select.SelectLabel"
922
+ }));
923
+ }
924
+ /** Renders the select trigger component. */
925
+ function SelectTrigger$1(_ref) {
926
+ let { className, minWidth = 140, style } = _ref, props = _objectWithoutProperties(_ref, _excluded$8);
927
+ return /* @__PURE__ */ jsx(SelectTrigger, _objectSpread2(_objectSpread2({
928
+ className: cn(triggerClass, className),
929
+ style: _objectSpread2({ minWidth: typeof minWidth === "number" ? `${minWidth}px` : minWidth }, style)
930
+ }, props), {}, {
931
+ "data-opt-id": "V6F86",
932
+ "data-opt-slug": "select.SelectTrigger"
933
+ }));
934
+ }
935
+ /** Renders the select popover component. */
936
+ function SelectPopover$1(_ref2) {
937
+ let { className } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$6);
938
+ return /* @__PURE__ */ jsx(SelectPopover, _objectSpread2(_objectSpread2({ className: cn(popoverClass$1, className) }, props), {}, {
939
+ "data-opt-id": "P152F",
940
+ "data-opt-slug": "select.SelectPopover"
941
+ }));
942
+ }
943
+ /** Renders the select item component. */
944
+ function SelectItem$1(_ref3) {
945
+ let { className } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$6);
946
+ return /* @__PURE__ */ jsx(SelectItem, _objectSpread2(_objectSpread2({ className: cn(itemClass$1, className) }, props), {}, {
947
+ "data-opt-id": "KKBAF",
948
+ "data-opt-slug": "select.SelectItem"
949
+ }));
950
+ }
951
+ //#endregion
952
+ //#region src/core/dialog.tsx
953
+ const _excluded$7 = ["className"];
954
+ const _excluded2$5 = ["className", "size"];
955
+ const _excluded3$5 = ["className", "size"];
956
+ const _excluded4$4 = ["className"];
957
+ const _excluded5$3 = ["className"];
958
+ const _excluded6$2 = ["className"];
959
+ const sizeClasses = {
960
+ xs: "max-w-xs",
961
+ sm: "max-w-sm",
962
+ md: "max-w-lg",
963
+ lg: "max-w-2xl",
964
+ xl: "max-w-4xl",
965
+ full: "max-w-[calc(100vw-2rem)]"
966
+ };
967
+ const panelBase = `fixed inset-auto left-1/2 top-[20%] z-50 m-0 w-full -translate-x-1/2 rounded-xl border border-border bg-surface p-0 shadow-2xl ${OPT_ANIMATE_DIALOG}`;
968
+ /** Renders the dialog root component. */
969
+ function DialogRoot$1(props) {
970
+ return /* @__PURE__ */ jsx(DialogRoot, _objectSpread2(_objectSpread2({ animated: true }, props), {}, {
971
+ "data-opt-id": "MDC91",
972
+ "data-opt-slug": "dialog.DialogRoot"
973
+ }));
974
+ }
975
+ /** Renders the dialog disclosure component. */
976
+ function DialogDisclosure$1(_ref) {
977
+ let { className } = _ref, props = _objectWithoutProperties(_ref, _excluded$7);
978
+ return /* @__PURE__ */ jsx(DialogDisclosure, _objectSpread2(_objectSpread2({ className: cn("inline-flex cursor-pointer items-center justify-center rounded-lg font-medium transition-colors", OPT_BUTTON_PRIMARY, OPT_FOCUS_VISIBLE, className) }, props), {}, {
979
+ "data-opt-id": "32QJK",
980
+ "data-opt-slug": "dialog.DialogDisclosure"
981
+ }));
982
+ }
983
+ /** Renders the dialog panel component. */
984
+ function DialogPanel$1(_ref2) {
985
+ let { className, size = "md" } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$5);
986
+ return /* @__PURE__ */ jsx(DialogPanel, _objectSpread2(_objectSpread2({ className: cn(panelBase, sizeClasses[size], className) }, props), {}, {
987
+ "data-opt-id": "BTMTG",
988
+ "data-opt-slug": "dialog.DialogPanel"
989
+ }));
990
+ }
991
+ /**
992
+ * A dialog that demands an explicit choice: `role="alertdialog"` with no
993
+ * backdrop/Escape dismissal. Use for destructive confirmations. Compose with
994
+ * the other Dialog parts (DialogRoot/Heading/Description/Dismiss/…).
995
+ */
996
+ function AlertDialogPanel$1(_ref3) {
997
+ let { className, size = "sm" } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$5);
998
+ return /* @__PURE__ */ jsx(AlertDialogPanel, _objectSpread2(_objectSpread2({ className: cn(panelBase, sizeClasses[size], className) }, props), {}, {
999
+ "data-opt-id": "80HGS",
1000
+ "data-opt-slug": "dialog.AlertDialogPanel"
1001
+ }));
1002
+ }
1003
+ /** Renders the dialog heading component. */
1004
+ function DialogHeading$1(_ref4) {
1005
+ let { className } = _ref4, props = _objectWithoutProperties(_ref4, _excluded4$4);
1006
+ return /* @__PURE__ */ jsx(DialogHeading, _objectSpread2(_objectSpread2({ className: cn(`text-lg font-semibold ${OPT_TEXT_PRIMARY}`, className) }, props), {}, {
1007
+ "data-opt-id": "4NW4H",
1008
+ "data-opt-slug": "dialog.DialogHeading"
1009
+ }));
1010
+ }
1011
+ /** Renders the dialog description component. */
1012
+ function DialogDescription$1(_ref5) {
1013
+ let { className } = _ref5, props = _objectWithoutProperties(_ref5, _excluded5$3);
1014
+ return /* @__PURE__ */ jsx(DialogDescription, _objectSpread2(_objectSpread2({ className: cn(`text-sm ${OPT_TEXT_SECONDARY}`, className) }, props), {}, {
1015
+ "data-opt-id": "2BN3X",
1016
+ "data-opt-slug": "dialog.DialogDescription"
1017
+ }));
1018
+ }
1019
+ /** Renders the dialog dismiss component. */
1020
+ function DialogDismiss$1(_ref6) {
1021
+ let { className } = _ref6, props = _objectWithoutProperties(_ref6, _excluded6$2);
1022
+ return /* @__PURE__ */ jsx(DialogDismiss, _objectSpread2(_objectSpread2({ className: cn("hover:bg-bg-subtle rounded-md p-1.5 transition-colors", "cursor-pointer data-[disabled]:cursor-not-allowed", OPT_FOCUS, className) }, props), {}, {
1023
+ "data-opt-id": "JXT0Y",
1024
+ "data-opt-slug": "dialog.DialogDismiss"
1025
+ }));
1026
+ }
1027
+ /** Renders the dialog header component. */
1028
+ function DialogHeader({ children, className }) {
1029
+ return /* @__PURE__ */ jsx("div", {
1030
+ className: cn("border-border flex items-start justify-between gap-4 border-b px-6 py-4", className),
1031
+ "data-opt-id": "K8NYY",
1032
+ "data-opt-slug": "dialog.DialogHeader",
1033
+ children: /* @__PURE__ */ jsx("div", {
1034
+ className: "gap-element flex min-w-0 flex-1 flex-col",
1035
+ children
1036
+ })
1037
+ });
1038
+ }
1039
+ /** Renders the dialog body component. */
1040
+ function DialogBody({ children, className }) {
1041
+ return /* @__PURE__ */ jsx("div", {
1042
+ className: cn("flex-1 overflow-y-auto px-6 py-4", className),
1043
+ "data-opt-id": "EE32H",
1044
+ "data-opt-slug": "dialog.DialogBody",
1045
+ children
1046
+ });
1047
+ }
1048
+ /** Renders the dialog footer component. */
1049
+ function DialogFooter({ children, className }) {
1050
+ return /* @__PURE__ */ jsx("div", {
1051
+ className: cn("border-border gap-element flex items-center justify-end border-t px-6 py-4", className),
1052
+ "data-opt-id": "AYQSR",
1053
+ "data-opt-slug": "dialog.DialogFooter",
1054
+ children
1055
+ });
1056
+ }
1057
+ //#endregion
1058
+ //#region src/core/combobox.tsx
1059
+ const _excluded$6 = ["className"];
1060
+ const _excluded2$4 = ["className"];
1061
+ const _excluded3$4 = ["className"];
1062
+ const _excluded4$3 = ["className"];
1063
+ const inputClass$1 = `${OPT_INPUT} ${OPT_FOCUS}`;
1064
+ const popoverClass = `${OPT_SURFACE_POPOVER} max-h-60 overflow-y-auto ${OPT_ANIMATE_ENTER_EXIT}`;
1065
+ const itemClass = `${OPT_ITEM_BASE} ${OPT_ACTIVE_ITEM}`;
1066
+ const groupLabelClass = "px-2 py-1.5 text-xs font-medium text-text-tertiary";
1067
+ const emptyClass = "py-4 text-center text-sm text-text-tertiary";
1068
+ /** Renders the combobox root component. */
1069
+ function ComboboxRoot$1(props) {
1070
+ return /* @__PURE__ */ jsx(ComboboxRoot, _objectSpread2(_objectSpread2({}, props), {}, {
1071
+ "data-opt-id": "VACXX",
1072
+ "data-opt-slug": "combobox.ComboboxRoot"
1073
+ }));
1074
+ }
1075
+ /** Renders the combobox input component. */
1076
+ function ComboboxInput$1(_ref) {
1077
+ let { className } = _ref, props = _objectWithoutProperties(_ref, _excluded$6);
1078
+ return /* @__PURE__ */ jsx(ComboboxInput, _objectSpread2(_objectSpread2({ className: cn(inputClass$1, className) }, props), {}, {
1079
+ "data-opt-id": "92FZS",
1080
+ "data-opt-slug": "combobox.ComboboxInput"
1081
+ }));
1082
+ }
1083
+ /** Renders the combobox popover component. */
1084
+ function ComboboxPopover$1(_ref2) {
1085
+ let { className } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$4);
1086
+ return /* @__PURE__ */ jsx(ComboboxPopover, _objectSpread2(_objectSpread2({ className: cn(popoverClass, className) }, props), {}, {
1087
+ "data-opt-id": "WS4PD",
1088
+ "data-opt-slug": "combobox.ComboboxPopover"
1089
+ }));
1090
+ }
1091
+ /** Renders the combobox item component. */
1092
+ function ComboboxItem$1(_ref3) {
1093
+ let { className } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$4);
1094
+ return /* @__PURE__ */ jsx(ComboboxItem, _objectSpread2(_objectSpread2({ className: cn(itemClass, className) }, props), {}, {
1095
+ "data-opt-id": "MAZJN",
1096
+ "data-opt-slug": "combobox.ComboboxItem"
1097
+ }));
1098
+ }
1099
+ /** Renders the combobox group component. */
1100
+ function ComboboxGroup$1(props) {
1101
+ return /* @__PURE__ */ jsx(ComboboxGroup, _objectSpread2(_objectSpread2({}, props), {}, {
1102
+ "data-opt-id": "SPJQC",
1103
+ "data-opt-slug": "combobox.ComboboxGroup"
1104
+ }));
1105
+ }
1106
+ /** Renders the combobox group label component. */
1107
+ function ComboboxGroupLabel$1(_ref4) {
1108
+ let { className } = _ref4, props = _objectWithoutProperties(_ref4, _excluded4$3);
1109
+ return /* @__PURE__ */ jsx(ComboboxGroupLabel, _objectSpread2(_objectSpread2({ className: cn(groupLabelClass, className) }, props), {}, {
1110
+ "data-opt-id": "512YF",
1111
+ "data-opt-slug": "combobox.ComboboxGroupLabel"
1112
+ }));
1113
+ }
1114
+ /** Renders the combobox empty component. */
1115
+ function ComboboxEmpty({ className, children = koComboboxLabels.empty }) {
1116
+ return /* @__PURE__ */ jsx("p", {
1117
+ className: cn(emptyClass, className),
1118
+ "data-opt-id": "RZ06M",
1119
+ "data-opt-slug": "combobox.ComboboxEmpty",
1120
+ children
1121
+ });
1122
+ }
1123
+ //#endregion
1124
+ //#region src/core/menu.tsx
1125
+ const _excluded$5 = ["className"];
1126
+ const _excluded2$3 = ["className"];
1127
+ const _excluded3$3 = ["className"];
1128
+ const _excluded4$2 = ["className"];
1129
+ const _excluded5$2 = ["className"];
1130
+ const _excluded6$1 = ["className"];
1131
+ const _excluded7$1 = ["className"];
1132
+ const menuButtonClass = `inline-flex cursor-pointer items-center gap-1 rounded px-3 py-1.5 text-sm text-text-primary hover:bg-bg-subtle data-[active]:bg-bg-subtle data-[disabled]:cursor-not-allowed ${OPT_FOCUS}`;
1133
+ const menuPopoverClass = `${OPT_SURFACE_POPOVER} min-w-[180px] ${OPT_ANIMATE_ENTER_EXIT}`;
1134
+ const menuItemClass = `flex cursor-pointer items-center justify-between rounded-md px-2 py-1.5 text-sm text-text-primary outline-none data-[disabled]:cursor-not-allowed ${OPT_ACTIVE_ITEM}`;
1135
+ const menuSeparatorClass = "my-1 border-t border-border-subtle";
1136
+ const menubarClass = `${OPT_SURFACE} ${OPT_BORDER} flex items-center gap-1 px-1 py-1`;
1137
+ /** Renders the menubar root component. */
1138
+ function MenubarRoot$1(props) {
1139
+ return /* @__PURE__ */ jsx(MenubarRoot, _objectSpread2(_objectSpread2({}, props), {}, {
1140
+ "data-opt-id": "2ERC6",
1141
+ "data-opt-slug": "menu.MenubarRoot"
1142
+ }));
1143
+ }
1144
+ /** Renders the menubar container component. */
1145
+ function MenubarContainer$1(_ref) {
1146
+ let { className } = _ref, props = _objectWithoutProperties(_ref, _excluded$5);
1147
+ return /* @__PURE__ */ jsx(MenubarContainer, _objectSpread2(_objectSpread2({ className: cn(menubarClass, className) }, props), {}, {
1148
+ "data-opt-id": "4MVQT",
1149
+ "data-opt-slug": "menu.MenubarContainer"
1150
+ }));
1151
+ }
1152
+ /** Renders the menu root component. */
1153
+ function MenuRoot$1(props) {
1154
+ return /* @__PURE__ */ jsx(MenuRoot, _objectSpread2(_objectSpread2({}, props), {}, {
1155
+ "data-opt-id": "H2WRF",
1156
+ "data-opt-slug": "menu.MenuRoot"
1157
+ }));
1158
+ }
1159
+ /** Renders the menu trigger component. */
1160
+ function MenuTrigger$1(_ref2) {
1161
+ let { className } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$3);
1162
+ return /* @__PURE__ */ jsx(MenuTrigger, _objectSpread2(_objectSpread2({ className: cn(menuButtonClass, className) }, props), {}, {
1163
+ "data-opt-id": "46BJG",
1164
+ "data-opt-slug": "menu.MenuTrigger"
1165
+ }));
1166
+ }
1167
+ /** Renders the menu button arrow component. */
1168
+ function MenuButtonArrow$1(props) {
1169
+ return /* @__PURE__ */ jsx(MenuButtonArrow, _objectSpread2(_objectSpread2({}, props), {}, {
1170
+ "data-opt-id": "J1AQH",
1171
+ "data-opt-slug": "menu.MenuButtonArrow"
1172
+ }));
1173
+ }
1174
+ /** Renders the menu popover component. */
1175
+ function MenuPopover$1(_ref3) {
1176
+ let { className } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$3);
1177
+ return /* @__PURE__ */ jsx(MenuPopover, _objectSpread2(_objectSpread2({ className: cn(menuPopoverClass, className) }, props), {}, {
1178
+ "data-opt-id": "Q1MFY",
1179
+ "data-opt-slug": "menu.MenuPopover"
1180
+ }));
1181
+ }
1182
+ /** Renders the menu item component. */
1183
+ function MenuItem$1(_ref4) {
1184
+ let { className } = _ref4, props = _objectWithoutProperties(_ref4, _excluded4$2);
1185
+ return /* @__PURE__ */ jsx(MenuItem, _objectSpread2(_objectSpread2({ className: cn(menuItemClass, className) }, props), {}, {
1186
+ "data-opt-id": "71JVB",
1187
+ "data-opt-slug": "menu.MenuItem"
1188
+ }));
1189
+ }
1190
+ /** Renders the menu item checkbox component. */
1191
+ function MenuItemCheckbox$1(_ref5) {
1192
+ let { className } = _ref5, props = _objectWithoutProperties(_ref5, _excluded5$2);
1193
+ return /* @__PURE__ */ jsx(MenuItemCheckbox, _objectSpread2(_objectSpread2({ className: cn(menuItemClass, className) }, props), {}, {
1194
+ "data-opt-id": "DG8B3",
1195
+ "data-opt-slug": "menu.MenuItemCheckbox"
1196
+ }));
1197
+ }
1198
+ /** Renders the menu item radio component. */
1199
+ function MenuItemRadio$1(_ref6) {
1200
+ let { className } = _ref6, props = _objectWithoutProperties(_ref6, _excluded6$1);
1201
+ return /* @__PURE__ */ jsx(MenuItemRadio, _objectSpread2(_objectSpread2({ className: cn(menuItemClass, className) }, props), {}, {
1202
+ "data-opt-id": "ZT759",
1203
+ "data-opt-slug": "menu.MenuItemRadio"
1204
+ }));
1205
+ }
1206
+ /** Renders the menu separator component. */
1207
+ function MenuSeparator$1(_ref7) {
1208
+ let { className } = _ref7, props = _objectWithoutProperties(_ref7, _excluded7$1);
1209
+ return /* @__PURE__ */ jsx(MenuSeparator, _objectSpread2(_objectSpread2({ className: cn(menuSeparatorClass, className) }, props), {}, {
1210
+ "data-opt-id": "AJV8K",
1211
+ "data-opt-slug": "menu.MenuSeparator"
1212
+ }));
1213
+ }
1214
+ //#endregion
1215
+ //#region src/core/toolbar.tsx
1216
+ const _excluded$4 = ["className"];
1217
+ const _excluded2$2 = ["className"];
1218
+ const _excluded3$2 = ["className"];
1219
+ const _excluded4$1 = ["className"];
1220
+ const _excluded5$1 = ["className"];
1221
+ const toolbarClass = `${OPT_SURFACE} ${OPT_BORDER} inline-flex w-fit items-center gap-0.5 px-1.5 py-1`;
1222
+ const buttonClass = `cursor-pointer rounded-md px-2.5 py-1.5 text-text-primary transition-colors data-[disabled]:cursor-not-allowed ${OPT_ACTIVE_ITEM} ${OPT_FOCUS}`;
1223
+ const separatorClass = "mx-1 h-6 w-px bg-border-subtle";
1224
+ const tooltipClass = "z-50 rounded-md bg-foreground px-2 py-1 text-xs text-background shadow-lg";
1225
+ /** Renders the toolbar root component. */
1226
+ function ToolbarRoot$1(props) {
1227
+ return /* @__PURE__ */ jsx(ToolbarRoot, _objectSpread2(_objectSpread2({}, props), {}, {
1228
+ "data-opt-id": "V33Y0",
1229
+ "data-opt-slug": "toolbar.ToolbarRoot"
1230
+ }));
1231
+ }
1232
+ /** Renders the toolbar container component. */
1233
+ function ToolbarContainer$1(_ref) {
1234
+ let { className } = _ref, props = _objectWithoutProperties(_ref, _excluded$4);
1235
+ return /* @__PURE__ */ jsx(ToolbarContainer, _objectSpread2(_objectSpread2({ className: cn(toolbarClass, className) }, props), {}, {
1236
+ "data-opt-id": "2AVXB",
1237
+ "data-opt-slug": "toolbar.ToolbarContainer"
1238
+ }));
1239
+ }
1240
+ /** Renders the toolbar button component. */
1241
+ function ToolbarButton$1(_ref2) {
1242
+ let { className } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$2);
1243
+ return /* @__PURE__ */ jsx(ToolbarButton, _objectSpread2(_objectSpread2({ className: cn(buttonClass, className) }, props), {}, {
1244
+ "data-opt-id": "C212C",
1245
+ "data-opt-slug": "toolbar.ToolbarButton"
1246
+ }));
1247
+ }
1248
+ /** Renders the toolbar separator component. */
1249
+ function ToolbarSeparator$1(_ref3) {
1250
+ let { className } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$2);
1251
+ return /* @__PURE__ */ jsx(ToolbarSeparator, _objectSpread2(_objectSpread2({ className: cn(separatorClass, className) }, props), {}, {
1252
+ "data-opt-id": "9J72S",
1253
+ "data-opt-slug": "toolbar.ToolbarSeparator"
1254
+ }));
1255
+ }
1256
+ /** Renders the tooltip provider component. */
1257
+ function TooltipProvider$1(props) {
1258
+ return /* @__PURE__ */ jsx(TooltipProvider, _objectSpread2(_objectSpread2({}, props), {}, {
1259
+ "data-opt-id": "6NKHT",
1260
+ "data-opt-slug": "toolbar.TooltipProvider"
1261
+ }));
1262
+ }
1263
+ /** Renders the tooltip anchor component. */
1264
+ function TooltipAnchor$1(_ref4) {
1265
+ let { className } = _ref4, props = _objectWithoutProperties(_ref4, _excluded4$1);
1266
+ return /* @__PURE__ */ jsx(TooltipAnchor, _objectSpread2(_objectSpread2({ className }, props), {}, {
1267
+ "data-opt-id": "SAW1B",
1268
+ "data-opt-slug": "toolbar.TooltipAnchor"
1269
+ }));
1270
+ }
1271
+ /** Renders the tooltip component. */
1272
+ function Tooltip$1(_ref5) {
1273
+ let { className } = _ref5, props = _objectWithoutProperties(_ref5, _excluded5$1);
1274
+ return /* @__PURE__ */ jsx(Tooltip, _objectSpread2(_objectSpread2({ className: cn(tooltipClass, className) }, props), {}, {
1275
+ "data-opt-id": "XSAT4",
1276
+ "data-opt-slug": "toolbar.Tooltip"
1277
+ }));
1278
+ }
1279
+ //#endregion
1280
+ //#region src/core/number-input.tsx
1281
+ /** Number of decimal places a finite number is written with (handles exponents). */
1282
+ function decimalPlaces(n) {
1283
+ if (!Number.isFinite(n)) return 0;
1284
+ const s = String(n);
1285
+ const exp = s.indexOf("e");
1286
+ if (exp >= 0) {
1287
+ const mantissa = s.slice(0, exp);
1288
+ const dot = mantissa.indexOf(".");
1289
+ const mantissaDecimals = dot >= 0 ? mantissa.length - dot - 1 : 0;
1290
+ return Math.max(0, mantissaDecimals - Number(s.slice(exp + 1)));
1291
+ }
1292
+ const dot = s.indexOf(".");
1293
+ return dot >= 0 ? s.length - dot - 1 : 0;
1294
+ }
1295
+ /**
1296
+ * Adds `delta` to `value` without binary floating-point drift (e.g. 0.1 + 0.2).
1297
+ * Rounds to the largest precision present among the operands and `step`.
1298
+ */
1299
+ function addPrecise(value, delta, step) {
1300
+ const decimals = Math.max(decimalPlaces(value), decimalPlaces(delta), decimalPlaces(step));
1301
+ if (decimals === 0) return value + delta;
1302
+ const factor = 10 ** Math.min(decimals, 15);
1303
+ return Math.round((value + delta) * factor) / factor;
1304
+ }
1305
+ const NUMBER_PATTERN = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/i;
1306
+ const PARTIAL_NUMBER_PATTERN = /^[+-]?$|^[+-]?\.$|^[+-]?(?:\d+\.?\d*|\.\d+)[eE][+-]?$/;
1307
+ function parseDraftValue(raw) {
1308
+ const value = raw.trim();
1309
+ if (value === "") return { kind: "empty" };
1310
+ if (PARTIAL_NUMBER_PATTERN.test(value)) return { kind: "partial" };
1311
+ if (!NUMBER_PATTERN.test(value)) return { kind: "invalid" };
1312
+ const parsed = Number(value);
1313
+ if (!Number.isFinite(parsed)) return { kind: "invalid" };
1314
+ return {
1315
+ kind: "valid",
1316
+ value: parsed
1317
+ };
1318
+ }
1319
+ const DEFAULT_LABELS$1 = {
1320
+ input: "Number",
1321
+ decrease: "Decrease",
1322
+ increase: "Increase",
1323
+ clear: "Clear value",
1324
+ invalid: "Enter a valid number"
1325
+ };
1326
+ /** Renders the number input component. */
1327
+ function NumberInput({ value: controlledValue, defaultValue, onChange, nullable, clearable = false, min, max, step = 1, largeStep, scrub = false, label, unit, required, error, hint, disabled = false, disabledReason, labels, className, id, "aria-label": ariaLabel }) {
1328
+ var _useInputId, _ref, _ref2;
1329
+ const generatedId = React.useId();
1330
+ const inputId = (_useInputId = useInputId(id, label, "number-input")) !== null && _useInputId !== void 0 ? _useInputId : `${generatedId}-number-input`;
1331
+ const resolvedLabels = _objectSpread2(_objectSpread2({}, DEFAULT_LABELS$1), labels);
1332
+ const isNullable = nullable === true;
1333
+ const nativeDisabled = disabled && !disabledReason;
1334
+ const interactionDisabled = disabled;
1335
+ const [invalidDraft, setInvalidDraft] = React.useState(false);
1336
+ const effectiveError = error !== null && error !== void 0 ? error : invalidDraft ? resolvedLabels.invalid : "";
1337
+ const hasError = Boolean(effectiveError);
1338
+ const clamp = React.useCallback((v) => {
1339
+ let clamped = v;
1340
+ if (min !== void 0) clamped = Math.max(min, clamped);
1341
+ if (max !== void 0) clamped = Math.min(max, clamped);
1342
+ return clamped;
1343
+ }, [min, max]);
1344
+ const [rawValue, setRawValue] = useControlledState((_ref = defaultValue) !== null && _ref !== void 0 ? _ref : isNullable ? null : 0, controlledValue, React.useCallback((next) => {
1345
+ if (isNullable) {
1346
+ onChange === null || onChange === void 0 || onChange(next);
1347
+ return;
1348
+ }
1349
+ if (next !== null) onChange === null || onChange === void 0 || onChange(next);
1350
+ }, [isNullable, onChange]));
1351
+ const value = rawValue;
1352
+ const numericValue = value !== null && value !== void 0 ? value : 0;
1353
+ const setValue = React.useCallback((next) => {
1354
+ setRawValue(next === null ? null : clamp(next));
1355
+ }, [clamp, setRawValue]);
1356
+ const format = React.useCallback((v) => {
1357
+ const decimals = Math.max(decimalPlaces(step), decimalPlaces(v));
1358
+ return v.toFixed(Math.min(decimals, 20));
1359
+ }, [step]);
1360
+ const [inputText, setInputText] = React.useState(null);
1361
+ const focusedRef = React.useRef(false);
1362
+ const displayValue = inputText !== null && inputText !== void 0 ? inputText : value === null ? "" : format(value);
1363
+ const stateRef = React.useRef({
1364
+ step,
1365
+ clamp,
1366
+ format
1367
+ });
1368
+ stateRef.current = {
1369
+ step,
1370
+ clamp,
1371
+ format
1372
+ };
1373
+ const valueRef = React.useRef(value);
1374
+ valueRef.current = value;
1375
+ const getSpinBase = React.useCallback(() => {
1376
+ if (valueRef.current !== null) return valueRef.current;
1377
+ return clamp(min !== null && min !== void 0 ? min : 0);
1378
+ }, [clamp, min]);
1379
+ const spin = React.useCallback((delta) => {
1380
+ if (interactionDisabled) return;
1381
+ const s = stateRef.current;
1382
+ const next = s.clamp(addPrecise(getSpinBase(), delta, s.step));
1383
+ valueRef.current = next;
1384
+ setInvalidDraft(false);
1385
+ setValue(next);
1386
+ if (focusedRef.current) setInputText(s.format(next));
1387
+ }, [
1388
+ getSpinBase,
1389
+ interactionDisabled,
1390
+ setValue
1391
+ ]);
1392
+ const setTo = React.useCallback((next) => {
1393
+ if (interactionDisabled) return;
1394
+ const s = stateRef.current;
1395
+ const clamped = s.clamp(next);
1396
+ valueRef.current = clamped;
1397
+ setInvalidDraft(false);
1398
+ setValue(clamped);
1399
+ if (focusedRef.current) setInputText(s.format(clamped));
1400
+ }, [interactionDisabled, setValue]);
1401
+ const handleChange = React.useCallback((e) => {
1402
+ const raw = e.target.value;
1403
+ setInputText(raw);
1404
+ const parsed = parseDraftValue(raw);
1405
+ if (parsed.kind === "empty") {
1406
+ setInvalidDraft(false);
1407
+ if (isNullable) {
1408
+ valueRef.current = null;
1409
+ setValue(null);
1410
+ }
1411
+ return;
1412
+ }
1413
+ if (parsed.kind === "partial") {
1414
+ setInvalidDraft(false);
1415
+ return;
1416
+ }
1417
+ if (parsed.kind === "invalid") {
1418
+ setInvalidDraft(true);
1419
+ return;
1420
+ }
1421
+ setInvalidDraft(false);
1422
+ setValue(parsed.value);
1423
+ }, [isNullable, setValue]);
1424
+ const handleFocus = React.useCallback(() => {
1425
+ focusedRef.current = true;
1426
+ }, []);
1427
+ const handleBlur = React.useCallback(() => {
1428
+ focusedRef.current = false;
1429
+ setInputText(null);
1430
+ setInvalidDraft(false);
1431
+ setValue(valueRef.current);
1432
+ }, [setValue]);
1433
+ const handleClear = React.useCallback(() => {
1434
+ if (!isNullable || interactionDisabled) return;
1435
+ valueRef.current = null;
1436
+ setInvalidDraft(false);
1437
+ setInputText(focusedRef.current ? "" : null);
1438
+ setValue(null);
1439
+ }, [
1440
+ interactionDisabled,
1441
+ isNullable,
1442
+ setValue
1443
+ ]);
1444
+ const repeatedRef = React.useRef(false);
1445
+ const timersRef = React.useRef({});
1446
+ const stopRepeat = React.useCallback(() => {
1447
+ const t = timersRef.current;
1448
+ if (t.timeout !== void 0) window.clearTimeout(t.timeout);
1449
+ if (t.interval !== void 0) window.clearInterval(t.interval);
1450
+ timersRef.current = {};
1451
+ }, []);
1452
+ React.useEffect(() => stopRepeat, [stopRepeat]);
1453
+ const handleStepPointerDown = React.useCallback((dir) => (e) => {
1454
+ if (e.button !== 0 || interactionDisabled) return;
1455
+ repeatedRef.current = false;
1456
+ stopRepeat();
1457
+ const delta = () => dir * stateRef.current.step;
1458
+ timersRef.current.timeout = window.setTimeout(() => {
1459
+ timersRef.current.interval = window.setInterval(() => {
1460
+ repeatedRef.current = true;
1461
+ spin(delta());
1462
+ }, 60);
1463
+ }, 300);
1464
+ }, [
1465
+ interactionDisabled,
1466
+ spin,
1467
+ stopRepeat
1468
+ ]);
1469
+ const handleStepClick = React.useCallback((dir) => () => {
1470
+ if (interactionDisabled) return;
1471
+ if (repeatedRef.current) {
1472
+ repeatedRef.current = false;
1473
+ return;
1474
+ }
1475
+ spin(dir * stateRef.current.step);
1476
+ }, [interactionDisabled, spin]);
1477
+ const handleKeyDown = React.useCallback((e) => {
1478
+ if (interactionDisabled) return;
1479
+ const s = stateRef.current;
1480
+ const big = largeStep !== null && largeStep !== void 0 ? largeStep : s.step * 10;
1481
+ switch (e.key) {
1482
+ case "ArrowUp":
1483
+ e.preventDefault();
1484
+ spin(s.step);
1485
+ break;
1486
+ case "ArrowDown":
1487
+ e.preventDefault();
1488
+ spin(-s.step);
1489
+ break;
1490
+ case "PageUp":
1491
+ e.preventDefault();
1492
+ spin(big);
1493
+ break;
1494
+ case "PageDown":
1495
+ e.preventDefault();
1496
+ spin(-big);
1497
+ break;
1498
+ case "Home":
1499
+ if (min !== void 0) {
1500
+ e.preventDefault();
1501
+ setTo(min);
1502
+ }
1503
+ break;
1504
+ case "End":
1505
+ if (max !== void 0) {
1506
+ e.preventDefault();
1507
+ setTo(max);
1508
+ }
1509
+ break;
1510
+ default: break;
1511
+ }
1512
+ }, [
1513
+ interactionDisabled,
1514
+ spin,
1515
+ setTo,
1516
+ largeStep,
1517
+ min,
1518
+ max
1519
+ ]);
1520
+ const scrubStartRef = React.useRef(null);
1521
+ const handleScrubPointerDown = React.useCallback((e) => {
1522
+ if (e.button !== 0 || interactionDisabled) return;
1523
+ e.preventDefault();
1524
+ scrubStartRef.current = {
1525
+ x: e.clientX,
1526
+ value: getSpinBase()
1527
+ };
1528
+ try {
1529
+ e.currentTarget.setPointerCapture(e.pointerId);
1530
+ } catch (_unused) {}
1531
+ }, [getSpinBase, interactionDisabled]);
1532
+ const handleScrubPointerMove = React.useCallback((e) => {
1533
+ const start = scrubStartRef.current;
1534
+ if (!start) return;
1535
+ const s = stateRef.current;
1536
+ const steps = Math.round((e.clientX - start.x) / 6);
1537
+ setInvalidDraft(false);
1538
+ setValue(s.clamp(addPrecise(start.value, steps * s.step, s.step)));
1539
+ }, [setValue]);
1540
+ const handleScrubPointerUp = React.useCallback((e) => {
1541
+ scrubStartRef.current = null;
1542
+ try {
1543
+ e.currentTarget.releasePointerCapture(e.pointerId);
1544
+ } catch (_unused2) {}
1545
+ }, []);
1546
+ const canDecrement = value === null || min === void 0 || numericValue > min;
1547
+ const canIncrement = value === null || max === void 0 || numericValue < max;
1548
+ const decrementUnavailable = interactionDisabled || !canDecrement;
1549
+ const incrementUnavailable = interactionDisabled || !canIncrement;
1550
+ const showClear = isNullable && clearable && value !== null;
1551
+ return /* @__PURE__ */ jsxs("div", {
1552
+ className: cn("flex flex-col gap-1.5", className),
1553
+ "data-opt-id": "GKPSV",
1554
+ "data-opt-slug": "number-input.NumberInput",
1555
+ children: [
1556
+ label && /* @__PURE__ */ jsxs("span", {
1557
+ className: cn("text-sm font-medium text-text-primary", scrub && !interactionDisabled && "w-fit cursor-ew-resize touch-none select-none"),
1558
+ onPointerDown: scrub ? handleScrubPointerDown : void 0,
1559
+ onPointerMove: scrub ? handleScrubPointerMove : void 0,
1560
+ onPointerUp: scrub ? handleScrubPointerUp : void 0,
1561
+ onPointerCancel: scrub ? handleScrubPointerUp : void 0,
1562
+ children: [label, required && /* @__PURE__ */ jsx(RequiredMark, {})]
1563
+ }),
1564
+ /* @__PURE__ */ jsxs("div", {
1565
+ className: "flex items-center",
1566
+ children: [
1567
+ /* @__PURE__ */ jsx("button", {
1568
+ type: "button",
1569
+ onClick: handleStepClick(-1),
1570
+ onPointerDown: handleStepPointerDown(-1),
1571
+ onPointerUp: stopRepeat,
1572
+ onPointerLeave: stopRepeat,
1573
+ onPointerCancel: stopRepeat,
1574
+ disabled: nativeDisabled || !canDecrement,
1575
+ "aria-disabled": decrementUnavailable || void 0,
1576
+ "aria-label": resolvedLabels.decrease,
1577
+ title: disabledReason,
1578
+ className: cn("border-border bg-surface text-text-secondary flex h-10 w-10 items-center justify-center rounded-l-lg border border-r-0 text-sm font-medium", decrementUnavailable ? "cursor-not-allowed opacity-40" : "hover:bg-bg-subtle cursor-pointer", nativeDisabled && "pointer-events-none", OPT_FOCUS_VISIBLE),
1579
+ children: "−"
1580
+ }),
1581
+ /* @__PURE__ */ jsxs("div", {
1582
+ className: "relative min-w-0 flex-1",
1583
+ children: [
1584
+ /* @__PURE__ */ jsx("input", {
1585
+ type: "text",
1586
+ inputMode: "decimal",
1587
+ id: inputId,
1588
+ value: displayValue,
1589
+ onChange: handleChange,
1590
+ onFocus: handleFocus,
1591
+ onBlur: handleBlur,
1592
+ onKeyDown: handleKeyDown,
1593
+ disabled: nativeDisabled,
1594
+ readOnly: interactionDisabled,
1595
+ "aria-disabled": interactionDisabled || void 0,
1596
+ "aria-label": (_ref2 = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : label) !== null && _ref2 !== void 0 ? _ref2 : resolvedLabels.input,
1597
+ "aria-invalid": hasError,
1598
+ "aria-required": required,
1599
+ "aria-describedby": getDescribedBy(inputId, effectiveError, hint),
1600
+ min,
1601
+ max,
1602
+ step,
1603
+ title: disabledReason,
1604
+ className: cn(OPT_INPUT, "[appearance:textfield] rounded-none border-x-0 text-center [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none", (unit || showClear) && "pr-10", unit && showClear && "pr-16", interactionDisabled && "cursor-not-allowed opacity-60", hasError && "border-danger focus-visible:outline-danger")
1605
+ }),
1606
+ unit && /* @__PURE__ */ jsx("span", {
1607
+ className: cn("text-text-tertiary pointer-events-none absolute top-1/2 -translate-y-1/2 text-sm", showClear ? "right-10" : "right-3"),
1608
+ "aria-hidden": "true",
1609
+ children: unit
1610
+ }),
1611
+ showClear && /* @__PURE__ */ jsx("button", {
1612
+ type: "button",
1613
+ onClick: handleClear,
1614
+ disabled: nativeDisabled,
1615
+ "aria-disabled": interactionDisabled || void 0,
1616
+ "aria-label": resolvedLabels.clear,
1617
+ title: disabledReason,
1618
+ className: cn("text-text-tertiary absolute top-1/2 right-2 flex h-6 w-6 -translate-y-1/2 items-center justify-center rounded text-sm", interactionDisabled ? "cursor-not-allowed opacity-40" : "hover:bg-bg-subtle hover:text-text-primary cursor-pointer", nativeDisabled && "pointer-events-none", "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset"),
1619
+ children: "×"
1620
+ })
1621
+ ]
1622
+ }),
1623
+ /* @__PURE__ */ jsx("button", {
1624
+ type: "button",
1625
+ onClick: handleStepClick(1),
1626
+ onPointerDown: handleStepPointerDown(1),
1627
+ onPointerUp: stopRepeat,
1628
+ onPointerLeave: stopRepeat,
1629
+ onPointerCancel: stopRepeat,
1630
+ disabled: nativeDisabled || !canIncrement,
1631
+ "aria-disabled": incrementUnavailable || void 0,
1632
+ "aria-label": resolvedLabels.increase,
1633
+ title: disabledReason,
1634
+ className: cn("border-border bg-surface text-text-secondary flex h-10 w-10 items-center justify-center rounded-r-lg border border-l-0 text-sm font-medium", incrementUnavailable ? "cursor-not-allowed opacity-40" : "hover:bg-bg-subtle cursor-pointer", nativeDisabled && "pointer-events-none", OPT_FOCUS_VISIBLE),
1635
+ children: "+"
1636
+ })
1637
+ ]
1638
+ }),
1639
+ /* @__PURE__ */ jsx(FieldMessages, {
1640
+ id: inputId,
1641
+ error: effectiveError,
1642
+ hint
1643
+ })
1644
+ ]
1645
+ });
1646
+ }
1647
+ NumberInput.displayName = "NumberInput";
1648
+ //#endregion
1649
+ //#region src/core/slider.tsx
1650
+ function getSliderState(value, min, max, step) {
1651
+ const safeMin = Number.isFinite(min) ? min : 0;
1652
+ const rawMax = Number.isFinite(max) ? max : 100;
1653
+ const safeMax = rawMax >= safeMin ? rawMax : safeMin;
1654
+ const safeStep = Number.isFinite(step) && step > 0 ? step : 1;
1655
+ const clampedValue = Math.min(Math.max(Number.isFinite(value) ? value : safeMin, safeMin), safeMax);
1656
+ return {
1657
+ value: clampedValue,
1658
+ min: safeMin,
1659
+ max: safeMax,
1660
+ step: safeStep,
1661
+ percentage: safeMax === safeMin ? 0 : (clampedValue - safeMin) / (safeMax - safeMin) * 100
1662
+ };
1663
+ }
1664
+ /** Renders the slider component. */
1665
+ function Slider({ value: controlledValue, defaultValue = 0, onChange, min = 0, max = 100, step = 1, label, showValue = false, formatValue, disabled = false, className, "aria-label": ariaLabel }) {
1666
+ var _ref;
1667
+ const [localValue, setLocalValue] = useState(defaultValue);
1668
+ const sliderState = getSliderState(controlledValue !== null && controlledValue !== void 0 ? controlledValue : localValue, min, max, step);
1669
+ const handleChange = useCallback((e) => {
1670
+ const next = getSliderState(parseFloat(e.target.value), min, max, step).value;
1671
+ if (controlledValue === void 0) setLocalValue(next);
1672
+ onChange === null || onChange === void 0 || onChange(next);
1673
+ }, [
1674
+ controlledValue,
1675
+ min,
1676
+ max,
1677
+ step,
1678
+ onChange
1679
+ ]);
1680
+ const displayValue = formatValue ? formatValue(sliderState.value) : String(sliderState.value);
1681
+ return /* @__PURE__ */ jsxs("div", {
1682
+ className: cn("flex flex-col gap-1.5", className),
1683
+ "data-opt-id": "VJCDH",
1684
+ "data-opt-slug": "slider.Slider",
1685
+ children: [(label || showValue) && /* @__PURE__ */ jsxs("div", {
1686
+ className: "flex items-center justify-between",
1687
+ children: [label && /* @__PURE__ */ jsx("span", {
1688
+ className: "text-sm font-medium text-text-primary",
1689
+ children: label
1690
+ }), showValue && /* @__PURE__ */ jsx("span", {
1691
+ className: "text-text-tertiary text-sm",
1692
+ children: displayValue
1693
+ })]
1694
+ }), /* @__PURE__ */ jsx("input", {
1695
+ type: "range",
1696
+ min: sliderState.min,
1697
+ max: sliderState.max,
1698
+ step: sliderState.step,
1699
+ value: sliderState.value,
1700
+ onChange: handleChange,
1701
+ disabled,
1702
+ "aria-label": (_ref = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : label) !== null && _ref !== void 0 ? _ref : "Slider",
1703
+ "aria-valuemin": sliderState.min,
1704
+ "aria-valuemax": sliderState.max,
1705
+ "aria-valuenow": sliderState.value,
1706
+ "aria-valuetext": displayValue,
1707
+ className: cn("h-2 w-full cursor-pointer appearance-none rounded-full", "bg-bg-subtle", "[&::-webkit-slider-thumb]:bg-accent [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:shadow-sm", "[&::-moz-range-thumb]:bg-accent [&::-moz-range-thumb]:h-4 [&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-0 [&::-moz-range-thumb]:shadow-sm", "disabled:cursor-not-allowed disabled:opacity-40", OPT_FOCUS_VISIBLE),
1708
+ style: { background: disabled ? void 0 : `linear-gradient(to right, var(--color-accent) ${sliderState.percentage}%, var(--color-bg-subtle) ${sliderState.percentage}%)` }
1709
+ })]
1710
+ });
1711
+ }
1712
+ Slider.displayName = "Slider";
1713
+ //#endregion
1714
+ //#region src/core/popover.tsx
1715
+ const _excluded$3 = ["className"];
1716
+ const _excluded2$1 = ["className"];
1717
+ const _excluded3$1 = ["className"];
1718
+ /** Renders the popover root component. */
1719
+ function PopoverRoot$1(props) {
1720
+ return /* @__PURE__ */ jsx(PopoverRoot, _objectSpread2(_objectSpread2({}, props), {}, {
1721
+ "data-opt-id": "DWJD5",
1722
+ "data-opt-slug": "popover.PopoverRoot"
1723
+ }));
1724
+ }
1725
+ const PopoverTrigger$1 = forwardRef((_ref, ref) => {
1726
+ let { className } = _ref, props = _objectWithoutProperties(_ref, _excluded$3);
1727
+ return /* @__PURE__ */ jsx(PopoverTrigger, _objectSpread2(_objectSpread2({
1728
+ ref,
1729
+ className: cn("inline-flex items-center gap-1.5 rounded-lg px-3 py-2 text-sm", "cursor-pointer data-[disabled]:cursor-not-allowed", OPT_FOCUS_VISIBLE, className)
1730
+ }, props), {}, {
1731
+ "data-opt-id": "2W9BZ",
1732
+ "data-opt-slug": "popover.PopoverTrigger"
1733
+ }));
1734
+ });
1735
+ PopoverTrigger$1.displayName = "PopoverTrigger";
1736
+ /** Renders the popover content component. */
1737
+ function PopoverContent$1(_ref2) {
1738
+ let { className } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$1);
1739
+ return /* @__PURE__ */ jsx(PopoverContent, _objectSpread2(_objectSpread2({ className: cn("bg-surface-overlay z-50 rounded-lg p-4 shadow-lg", OPT_BORDER, OPT_ANIMATE_ENTER_EXIT, className) }, props), {}, {
1740
+ "data-opt-id": "E03EY",
1741
+ "data-opt-slug": "popover.PopoverContent"
1742
+ }));
1743
+ }
1744
+ /** Renders the popover close component. */
1745
+ function PopoverClose$1(_ref3) {
1746
+ let { className } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$1);
1747
+ return /* @__PURE__ */ jsx(PopoverClose, _objectSpread2(_objectSpread2({ className: cn("text-text-tertiary hover:bg-bg-subtle inline-flex items-center justify-center rounded-md p-1 text-sm", "cursor-pointer data-[disabled]:cursor-not-allowed", OPT_FOCUS_VISIBLE, className) }, props), {}, {
1748
+ "data-opt-id": "FP4KF",
1749
+ "data-opt-slug": "popover.PopoverClose"
1750
+ }));
1751
+ }
1752
+ //#endregion
1753
+ //#region src/core/color-picker.tsx
1754
+ const DEFAULT_PRESETS$1 = [
1755
+ "#3b82f6",
1756
+ "#10b981",
1757
+ "#f59e0b",
1758
+ "#8b5cf6",
1759
+ "#ef4444",
1760
+ "#06b6d4",
1761
+ "#f97316",
1762
+ "#ec4899",
1763
+ "#84cc16",
1764
+ "#6366f1",
1765
+ "#14b8a6",
1766
+ "#a855f7",
1767
+ "#78716c",
1768
+ "#000000",
1769
+ "#6b7280",
1770
+ "#ffffff"
1771
+ ];
1772
+ const ColorPicker = forwardRef(({ value, onChange, presets = DEFAULT_PRESETS$1, label, required, error, hint, placeholder = "#000000", disabled = false, className, id, "aria-label": ariaLabel }, ref) => {
1773
+ var _useInputId, _ref;
1774
+ const [color, setColor] = useControlledState("#3b82f6", value, onChange);
1775
+ const fallbackId = useId().replace(/:/g, "");
1776
+ const pickerId = (_useInputId = useInputId(id, label, "color-picker")) !== null && _useInputId !== void 0 ? _useInputId : `color-picker-${fallbackId}`;
1777
+ const hasError = Boolean(error);
1778
+ const [inputValue, setInputValue] = useState(color);
1779
+ const inputRef = useRef(null);
1780
+ const handlePresetClick = useCallback((preset) => {
1781
+ setColor(preset);
1782
+ setInputValue(preset);
1783
+ }, [setColor]);
1784
+ const handleInputChange = useCallback((e) => {
1785
+ const val = e.target.value;
1786
+ setInputValue(val);
1787
+ if (/^#[0-9a-fA-F]{6}$/.test(val)) setColor(val);
1788
+ }, [setColor]);
1789
+ const handleInputBlur = useCallback(() => {
1790
+ if (!/^#[0-9a-fA-F]{6}$/.test(inputValue)) setInputValue(color);
1791
+ }, [inputValue, color]);
1792
+ const lastValueRef = useRef(value);
1793
+ if (value !== void 0 && value !== lastValueRef.current) {
1794
+ lastValueRef.current = value;
1795
+ if (value !== inputValue) setInputValue(value);
1796
+ }
1797
+ return /* @__PURE__ */ jsxs("div", {
1798
+ className: cn("flex flex-col gap-1.5", className),
1799
+ "data-opt-id": "V2CSG",
1800
+ "data-opt-slug": "color-picker.ColorPicker",
1801
+ children: [
1802
+ label && /* @__PURE__ */ jsxs("span", {
1803
+ className: "text-sm font-medium text-text-primary",
1804
+ children: [label, required && /* @__PURE__ */ jsx(RequiredMark, {})]
1805
+ }),
1806
+ /* @__PURE__ */ jsxs(PopoverRoot$1, { children: [/* @__PURE__ */ jsxs(PopoverTrigger$1, {
1807
+ id: pickerId,
1808
+ className: cn(OPT_INPUT, "cursor-pointer items-center gap-2", hasError && "border-danger focus-visible:outline-danger", disabled && "pointer-events-none opacity-50"),
1809
+ disabled,
1810
+ "aria-label": (_ref = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : label) !== null && _ref !== void 0 ? _ref : "Color picker",
1811
+ "aria-required": required,
1812
+ "aria-invalid": hasError,
1813
+ "aria-describedby": getDescribedBy(pickerId, error, hint),
1814
+ children: [/* @__PURE__ */ jsx("span", {
1815
+ className: "border-border inline-block h-5 w-5 rounded border",
1816
+ style: { backgroundColor: color },
1817
+ "aria-hidden": "true"
1818
+ }), /* @__PURE__ */ jsx("span", {
1819
+ className: OPT_TEXT_PRIMARY,
1820
+ children: color
1821
+ })]
1822
+ }), /* @__PURE__ */ jsxs(PopoverContent$1, {
1823
+ className: cn("bg-surface-overlay z-50 rounded-lg p-3 shadow-lg", OPT_BORDER),
1824
+ children: [/* @__PURE__ */ jsx("div", {
1825
+ className: "mb-3 grid grid-cols-8 gap-1.5",
1826
+ role: "listbox",
1827
+ "aria-label": "Color presets",
1828
+ children: presets.map((preset) => /* @__PURE__ */ jsx("button", {
1829
+ type: "button",
1830
+ onClick: () => handlePresetClick(preset),
1831
+ className: cn("h-7 w-7 rounded-md border transition-transform hover:scale-110", OPT_FOCUS_VISIBLE, preset === color ? "border-accent ring-ring ring-offset-ring-offset ring-2 ring-offset-1" : "border-border", preset === "#ffffff" && "border-black/20"),
1832
+ style: { backgroundColor: preset },
1833
+ role: "option",
1834
+ "aria-selected": preset === color,
1835
+ "aria-label": preset
1836
+ }, preset))
1837
+ }), /* @__PURE__ */ jsxs("div", {
1838
+ className: "flex items-center gap-2",
1839
+ children: [/* @__PURE__ */ jsx("span", {
1840
+ className: "border-border h-8 w-8 rounded-md border",
1841
+ style: { backgroundColor: color },
1842
+ "aria-hidden": "true"
1843
+ }), /* @__PURE__ */ jsx("input", {
1844
+ ref: ref !== null && ref !== void 0 ? ref : inputRef,
1845
+ type: "text",
1846
+ value: inputValue,
1847
+ onChange: handleInputChange,
1848
+ onBlur: handleInputBlur,
1849
+ placeholder,
1850
+ maxLength: 7,
1851
+ className: cn("border-border bg-surface flex-1 rounded-md border px-2 py-1.5 font-mono text-sm", OPT_TEXT_PRIMARY, OPT_FOCUS_VISIBLE),
1852
+ "aria-label": "Hex color value"
1853
+ })]
1854
+ })]
1855
+ })] }),
1856
+ /* @__PURE__ */ jsx(FieldMessages, {
1857
+ id: pickerId,
1858
+ error,
1859
+ hint
1860
+ })
1861
+ ]
1862
+ });
1863
+ });
1864
+ ColorPicker.displayName = "ColorPicker";
1865
+ //#endregion
1866
+ //#region src/lib/icon-registry.tsx
1867
+ const defaultIconEntries = [
1868
+ {
1869
+ id: "click",
1870
+ label: "Click",
1871
+ Icon: MousePointerClick,
1872
+ group: "Actions"
1873
+ },
1874
+ {
1875
+ id: "view",
1876
+ label: "View",
1877
+ Icon: Eye,
1878
+ group: "Actions"
1879
+ },
1880
+ {
1881
+ id: "cart",
1882
+ label: "Cart",
1883
+ Icon: ShoppingCart,
1884
+ group: "Actions"
1885
+ },
1886
+ {
1887
+ id: "purchase",
1888
+ label: "Purchase",
1889
+ Icon: CreditCard,
1890
+ group: "Actions"
1891
+ },
1892
+ {
1893
+ id: "signup",
1894
+ label: "Sign Up",
1895
+ Icon: UserPlus,
1896
+ group: "Actions"
1897
+ },
1898
+ {
1899
+ id: "login",
1900
+ label: "Login",
1901
+ Icon: LogIn,
1902
+ group: "Actions"
1903
+ },
1904
+ {
1905
+ id: "search",
1906
+ label: "Search",
1907
+ Icon: Search,
1908
+ group: "Actions"
1909
+ },
1910
+ {
1911
+ id: "download",
1912
+ label: "Download",
1913
+ Icon: Download,
1914
+ group: "Actions"
1915
+ },
1916
+ {
1917
+ id: "share",
1918
+ label: "Share",
1919
+ Icon: Share2,
1920
+ group: "Social"
1921
+ },
1922
+ {
1923
+ id: "like",
1924
+ label: "Like",
1925
+ Icon: Heart,
1926
+ group: "Social"
1927
+ },
1928
+ {
1929
+ id: "comment",
1930
+ label: "Comment",
1931
+ Icon: MessageCircle,
1932
+ group: "Social"
1933
+ },
1934
+ {
1935
+ id: "follow",
1936
+ label: "Follow",
1937
+ Icon: UserPlus,
1938
+ group: "Social"
1939
+ },
1940
+ {
1941
+ id: "star",
1942
+ label: "Star",
1943
+ Icon: Star,
1944
+ group: "Status"
1945
+ },
1946
+ {
1947
+ id: "flag",
1948
+ label: "Flag",
1949
+ Icon: Flag,
1950
+ group: "Status"
1951
+ },
1952
+ {
1953
+ id: "check",
1954
+ label: "Check",
1955
+ Icon: Check,
1956
+ group: "Status"
1957
+ },
1958
+ {
1959
+ id: "error",
1960
+ label: "Error",
1961
+ Icon: CircleAlert,
1962
+ group: "Status"
1963
+ },
1964
+ {
1965
+ id: "warning",
1966
+ label: "Warning",
1967
+ Icon: TriangleAlert,
1968
+ group: "Status"
1969
+ },
1970
+ {
1971
+ id: "info",
1972
+ label: "Info",
1973
+ Icon: Info,
1974
+ group: "Status"
1975
+ },
1976
+ {
1977
+ id: "bell",
1978
+ label: "Bell",
1979
+ Icon: Bell,
1980
+ group: "Objects"
1981
+ },
1982
+ {
1983
+ id: "mail",
1984
+ label: "Mail",
1985
+ Icon: Mail,
1986
+ group: "Objects"
1987
+ },
1988
+ {
1989
+ id: "file",
1990
+ label: "File",
1991
+ Icon: FileText,
1992
+ group: "Objects"
1993
+ },
1994
+ {
1995
+ id: "folder",
1996
+ label: "Folder",
1997
+ Icon: Folder,
1998
+ group: "Objects"
1999
+ },
2000
+ {
2001
+ id: "settings",
2002
+ label: "Settings",
2003
+ Icon: Settings,
2004
+ group: "Objects"
2005
+ },
2006
+ {
2007
+ id: "link",
2008
+ label: "Link",
2009
+ Icon: Link2,
2010
+ group: "Objects"
2011
+ }
2012
+ ];
2013
+ const extraIconEntries = [
2014
+ {
2015
+ id: "eye",
2016
+ label: "Eye",
2017
+ Icon: Eye
2018
+ },
2019
+ {
2020
+ id: "user",
2021
+ label: "User",
2022
+ Icon: User
2023
+ },
2024
+ {
2025
+ id: "shopping-cart",
2026
+ label: "Shopping Cart",
2027
+ Icon: ShoppingCart
2028
+ },
2029
+ {
2030
+ id: "credit-card",
2031
+ label: "Credit Card",
2032
+ Icon: CreditCard
2033
+ },
2034
+ {
2035
+ id: "heart",
2036
+ label: "Heart",
2037
+ Icon: Heart
2038
+ },
2039
+ {
2040
+ id: "upload",
2041
+ label: "Upload",
2042
+ Icon: Upload
2043
+ },
2044
+ {
2045
+ id: "globe",
2046
+ label: "Globe",
2047
+ Icon: Globe
2048
+ },
2049
+ {
2050
+ id: "zap",
2051
+ label: "Zap",
2052
+ Icon: Zap
2053
+ },
2054
+ {
2055
+ id: "trending-up",
2056
+ label: "Trending Up",
2057
+ Icon: TrendingUp
2058
+ },
2059
+ {
2060
+ id: "bar-chart",
2061
+ label: "Bar Chart",
2062
+ Icon: ChartColumn
2063
+ },
2064
+ {
2065
+ id: "check-circle",
2066
+ label: "Check Circle",
2067
+ Icon: CircleCheck
2068
+ },
2069
+ {
2070
+ id: "x-circle",
2071
+ label: "X Circle",
2072
+ Icon: XCircle
2073
+ }
2074
+ ];
2075
+ const iconRegistry = new Map([...defaultIconEntries, ...extraIconEntries].map((entry) => [entry.id, entry]));
2076
+ const defaultIconRegistry = defaultIconEntries;
2077
+ /** Returns icon registry entry. */
2078
+ function getIconRegistryEntry(id) {
2079
+ return iconRegistry.get(id);
2080
+ }
2081
+ //#endregion
2082
+ //#region src/core/icon-picker.tsx
2083
+ const DEFAULT_ICONS = [...defaultIconRegistry.map(({ id, label, Icon, group }) => ({
2084
+ id,
2085
+ label,
2086
+ group,
2087
+ icon: /* @__PURE__ */ jsx(Icon, {})
2088
+ }))];
2089
+ function renderIconPreview(icon, options) {
2090
+ if (typeof icon === "string" || typeof icon === "number") return /* @__PURE__ */ jsx("span", {
2091
+ className: cn(options.textClassName, "leading-none"),
2092
+ "aria-hidden": true,
2093
+ children: icon
2094
+ });
2095
+ if (React.isValidElement(icon)) return React.cloneElement(icon, {
2096
+ "aria-hidden": true,
2097
+ className: cn(options.elementClassName, icon.props.className)
2098
+ });
2099
+ return /* @__PURE__ */ jsx("span", {
2100
+ className: cn("flex items-center justify-center", options.elementClassName),
2101
+ "aria-hidden": true,
2102
+ children: icon
2103
+ });
2104
+ }
2105
+ /** Renders the icon picker component. */
2106
+ function IconPicker({ value, onChange, icons = DEFAULT_ICONS, label, required, error, hint, placeholder = "Select icon", disabled = false, className, id, "aria-label": ariaLabel }) {
2107
+ var _useInputId, _ref;
2108
+ const [selected, setSelected] = useControlledState("", value, onChange);
2109
+ const fallbackId = React.useId().replace(/:/g, "");
2110
+ const pickerId = (_useInputId = useInputId(id, label, "icon-picker")) !== null && _useInputId !== void 0 ? _useInputId : `icon-picker-${fallbackId}`;
2111
+ const hasError = Boolean(error);
2112
+ const [search, setSearch] = React.useState("");
2113
+ const selectedIcon = React.useMemo(() => icons.find((i) => i.id === selected), [icons, selected]);
2114
+ const filteredIcons = React.useMemo(() => {
2115
+ if (!search) return icons;
2116
+ const q = search.toLowerCase();
2117
+ return icons.filter((i) => {
2118
+ var _i$group;
2119
+ return i.label.toLowerCase().includes(q) || i.id.toLowerCase().includes(q) || ((_i$group = i.group) === null || _i$group === void 0 ? void 0 : _i$group.toLowerCase().includes(q));
2120
+ });
2121
+ }, [icons, search]);
2122
+ const groups = React.useMemo(() => {
2123
+ const map = /* @__PURE__ */ new Map();
2124
+ for (const icon of filteredIcons) {
2125
+ var _icon$group;
2126
+ const group = (_icon$group = icon.group) !== null && _icon$group !== void 0 ? _icon$group : "Other";
2127
+ if (!map.has(group)) map.set(group, []);
2128
+ map.get(group).push(icon);
2129
+ }
2130
+ return map;
2131
+ }, [filteredIcons]);
2132
+ const handleSelect = React.useCallback((iconId) => {
2133
+ setSelected(iconId);
2134
+ }, [setSelected]);
2135
+ return /* @__PURE__ */ jsxs("div", {
2136
+ className: cn("flex flex-col gap-1.5", className),
2137
+ "data-opt-id": "0DRGP",
2138
+ "data-opt-slug": "icon-picker.IconPicker",
2139
+ children: [
2140
+ label && /* @__PURE__ */ jsxs("span", {
2141
+ className: "text-sm font-medium text-text-primary",
2142
+ children: [label, required && /* @__PURE__ */ jsx(RequiredMark, {})]
2143
+ }),
2144
+ /* @__PURE__ */ jsxs(PopoverRoot$1, { children: [/* @__PURE__ */ jsx(PopoverTrigger$1, {
2145
+ id: pickerId,
2146
+ className: cn(OPT_INPUT, "cursor-pointer items-center gap-2", !selectedIcon && "text-text-tertiary", hasError && "border-danger focus-visible:outline-danger", disabled && "pointer-events-none opacity-50"),
2147
+ disabled,
2148
+ "aria-label": (_ref = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : label) !== null && _ref !== void 0 ? _ref : "Icon picker",
2149
+ "aria-required": required,
2150
+ "aria-invalid": hasError,
2151
+ "aria-describedby": getDescribedBy(pickerId, error, hint),
2152
+ children: selectedIcon ? /* @__PURE__ */ jsxs(Fragment, { children: [renderIconPreview(selectedIcon.icon, {
2153
+ elementClassName: "size-5 shrink-0",
2154
+ textClassName: "text-lg"
2155
+ }), /* @__PURE__ */ jsx("span", {
2156
+ className: OPT_TEXT_PRIMARY,
2157
+ children: selectedIcon.label
2158
+ })] }) : /* @__PURE__ */ jsx("span", { children: placeholder })
2159
+ }), /* @__PURE__ */ jsxs(PopoverContent$1, {
2160
+ className: cn("bg-surface-overlay z-50 w-72 rounded-lg p-3 shadow-lg", OPT_BORDER),
2161
+ children: [/* @__PURE__ */ jsx("input", {
2162
+ type: "text",
2163
+ value: search,
2164
+ onChange: (e) => setSearch(e.target.value),
2165
+ placeholder: "Search icons...",
2166
+ className: cn("border-border bg-surface mb-2 w-full rounded-md border px-3 py-1.5 text-sm outline-transparent", OPT_TEXT_PRIMARY, "placeholder:text-text-tertiary", OPT_FOCUS_VISIBLE),
2167
+ "aria-label": "Search icons"
2168
+ }), /* @__PURE__ */ jsx("div", {
2169
+ className: "max-h-56 overflow-y-auto",
2170
+ children: filteredIcons.length === 0 ? /* @__PURE__ */ jsx("div", {
2171
+ className: cn(OPT_TEXT_SECONDARY, "py-4 text-center text-sm"),
2172
+ children: "No icons found"
2173
+ }) : Array.from(groups.entries()).map(([groupName, groupIcons]) => /* @__PURE__ */ jsxs("div", {
2174
+ className: "mb-2",
2175
+ children: [/* @__PURE__ */ jsx("span", {
2176
+ className: cn(OPT_TEXT_TERTIARY, "mb-1 block text-[10px] font-semibold tracking-wider uppercase"),
2177
+ children: groupName
2178
+ }), /* @__PURE__ */ jsx("div", {
2179
+ className: "grid grid-cols-6 gap-1",
2180
+ children: groupIcons.map((icon) => /* @__PURE__ */ jsx("button", {
2181
+ type: "button",
2182
+ onClick: () => handleSelect(icon.id),
2183
+ className: cn("flex h-9 w-9 items-center justify-center rounded-md text-lg transition-colors", OPT_FOCUS_VISIBLE, icon.id === selected ? "bg-accent-subtle ring-ring ring-2" : "hover:bg-bg-subtle"),
2184
+ title: icon.label,
2185
+ "aria-label": icon.label,
2186
+ "aria-selected": icon.id === selected || void 0,
2187
+ children: renderIconPreview(icon.icon, {
2188
+ elementClassName: "size-4",
2189
+ textClassName: "text-lg"
2190
+ })
2191
+ }, icon.id))
2192
+ })]
2193
+ }, groupName))
2194
+ })]
2195
+ })] }),
2196
+ /* @__PURE__ */ jsx(FieldMessages, {
2197
+ id: pickerId,
2198
+ error,
2199
+ hint
2200
+ })
2201
+ ]
2202
+ });
2203
+ }
2204
+ IconPicker.displayName = "IconPicker";
2205
+ //#endregion
2206
+ //#region src/core/tag-input.tsx
2207
+ const DEFAULT_DELIMITERS = [
2208
+ ",",
2209
+ ";",
2210
+ "\n"
2211
+ ];
2212
+ function splitByDelimiters(text, delimiters) {
2213
+ const pattern = delimiters.map((d) => d instanceof RegExp ? d.source : d.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
2214
+ return text.split(new RegExp(pattern)).map((s) => s.trim()).filter(Boolean);
2215
+ }
2216
+ const TagInput = forwardRef(({ value, onChange, placeholder = "Add tag...", label, required, error, hint, maxTags, disabled = false, className, id, "aria-label": ariaLabel, suggestions, delimiters = DEFAULT_DELIMITERS, allowDuplicates = false }, ref) => {
2217
+ var _useInputId, _ref, _ref2, _ref3, _ref4;
2218
+ const [tags, setTags] = useControlledState([], value, onChange);
2219
+ const fallbackId = useId().replace(/:/g, "");
2220
+ const tagInputId = (_useInputId = useInputId(id, label, "tag-input")) !== null && _useInputId !== void 0 ? _useInputId : `tag-input-${fallbackId}`;
2221
+ const hasError = Boolean(error);
2222
+ const describedBy = getDescribedBy(tagInputId, error, hint);
2223
+ const [inputValue, setInputValue] = useState("");
2224
+ const [highlightIndex, setHighlightIndex] = useState(-1);
2225
+ const [showSuggestions, setShowSuggestions] = useState(false);
2226
+ const innerRef = useRef(null);
2227
+ const inputRef = (_ref = ref) !== null && _ref !== void 0 ? _ref : innerRef;
2228
+ const listboxRef = useRef(null);
2229
+ const listboxId = useId();
2230
+ const undoStack = useRef([]);
2231
+ const redoStack = useRef([]);
2232
+ const tagRefs = useRef(/* @__PURE__ */ new Map());
2233
+ function pushUndo(prev) {
2234
+ undoStack.current.push(prev);
2235
+ redoStack.current = [];
2236
+ }
2237
+ const undo = useCallback(() => {
2238
+ if (undoStack.current.length === 0) return;
2239
+ const prev = undoStack.current.pop();
2240
+ redoStack.current.push([...tags]);
2241
+ setTags(prev);
2242
+ }, [tags, setTags]);
2243
+ const redo = useCallback(() => {
2244
+ if (redoStack.current.length === 0) return;
2245
+ const next = redoStack.current.pop();
2246
+ undoStack.current.push([...tags]);
2247
+ setTags(next);
2248
+ }, [tags, setTags]);
2249
+ const filtered = suggestions && inputValue.trim() ? suggestions.filter((s) => s.toLowerCase().includes(inputValue.trim().toLowerCase()) && (allowDuplicates || !tags.includes(s))) : [];
2250
+ const isOpen = showSuggestions && filtered.length > 0;
2251
+ useEffect(() => {
2252
+ setHighlightIndex(-1);
2253
+ }, [inputValue]);
2254
+ const addTag = useCallback((tag) => {
2255
+ const trimmed = tag.trim();
2256
+ if (!trimmed) return;
2257
+ if (!allowDuplicates && tags.includes(trimmed)) return;
2258
+ if (maxTags && tags.length >= maxTags) return;
2259
+ pushUndo([...tags]);
2260
+ setTags([...tags, trimmed]);
2261
+ setInputValue("");
2262
+ setShowSuggestions(false);
2263
+ }, [
2264
+ tags,
2265
+ setTags,
2266
+ maxTags,
2267
+ allowDuplicates
2268
+ ]);
2269
+ const removeTag = useCallback((index) => {
2270
+ pushUndo([...tags]);
2271
+ setTags(tags.filter((_, i) => i !== index));
2272
+ }, [tags, setTags]);
2273
+ const handleTagKeyDown = useCallback((e, index) => {
2274
+ if (e.key === "Backspace" || e.key === "Delete") {
2275
+ e.preventDefault();
2276
+ const nextTags = tags.filter((_, i) => i !== index);
2277
+ pushUndo([...tags]);
2278
+ setTags(nextTags);
2279
+ requestAnimationFrame(() => {
2280
+ if (nextTags.length === 0) {
2281
+ var _inputRef$current;
2282
+ (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || _inputRef$current.focus();
2283
+ } else if (index < nextTags.length) {
2284
+ var _tagRefs$current$get;
2285
+ (_tagRefs$current$get = tagRefs.current.get(index)) === null || _tagRefs$current$get === void 0 || _tagRefs$current$get.focus();
2286
+ } else {
2287
+ var _tagRefs$current$get2;
2288
+ (_tagRefs$current$get2 = tagRefs.current.get(nextTags.length - 1)) === null || _tagRefs$current$get2 === void 0 || _tagRefs$current$get2.focus();
2289
+ }
2290
+ });
2291
+ return;
2292
+ }
2293
+ if ((e.ctrlKey || e.metaKey) && e.key === "z" && !e.shiftKey) {
2294
+ e.preventDefault();
2295
+ undo();
2296
+ requestAnimationFrame(() => {
2297
+ var _inputRef$current2;
2298
+ return (_inputRef$current2 = inputRef.current) === null || _inputRef$current2 === void 0 ? void 0 : _inputRef$current2.focus();
2299
+ });
2300
+ return;
2301
+ }
2302
+ if ((e.ctrlKey || e.metaKey) && (e.key === "Z" || e.key === "z" && e.shiftKey || e.key === "y")) {
2303
+ e.preventDefault();
2304
+ redo();
2305
+ requestAnimationFrame(() => {
2306
+ var _inputRef$current3;
2307
+ return (_inputRef$current3 = inputRef.current) === null || _inputRef$current3 === void 0 ? void 0 : _inputRef$current3.focus();
2308
+ });
2309
+ return;
2310
+ }
2311
+ if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
2312
+ var _inputRef$current4;
2313
+ (_inputRef$current4 = inputRef.current) === null || _inputRef$current4 === void 0 || _inputRef$current4.focus();
2314
+ }
2315
+ }, [
2316
+ tags,
2317
+ setTags,
2318
+ undo,
2319
+ redo,
2320
+ inputRef
2321
+ ]);
2322
+ const handleInputKeyDown = useCallback((e) => {
2323
+ var _inputRef$current5;
2324
+ if ((e.ctrlKey || e.metaKey) && e.key === "z" && !e.shiftKey) {
2325
+ e.preventDefault();
2326
+ undo();
2327
+ return;
2328
+ }
2329
+ if ((e.ctrlKey || e.metaKey) && (e.key === "Z" || e.key === "z" && e.shiftKey || e.key === "y")) {
2330
+ e.preventDefault();
2331
+ redo();
2332
+ return;
2333
+ }
2334
+ if (isOpen) {
2335
+ if (e.key === "ArrowDown") {
2336
+ e.preventDefault();
2337
+ setHighlightIndex((prev) => prev < filtered.length - 1 ? prev + 1 : 0);
2338
+ return;
2339
+ }
2340
+ if (e.key === "ArrowUp") {
2341
+ e.preventDefault();
2342
+ setHighlightIndex((prev) => prev > 0 ? prev - 1 : filtered.length - 1);
2343
+ return;
2344
+ }
2345
+ if (e.key === "Enter" && highlightIndex >= 0) {
2346
+ e.preventDefault();
2347
+ addTag(filtered[highlightIndex]);
2348
+ return;
2349
+ }
2350
+ if (e.key === "Escape") {
2351
+ e.preventDefault();
2352
+ setShowSuggestions(false);
2353
+ return;
2354
+ }
2355
+ }
2356
+ if (e.key === "Enter") {
2357
+ e.preventDefault();
2358
+ addTag(inputValue);
2359
+ } else if (e.key === "Backspace" && inputValue === "" && tags.length > 0) removeTag(tags.length - 1);
2360
+ else if (e.key === "ArrowLeft" && ((_inputRef$current5 = inputRef.current) === null || _inputRef$current5 === void 0 ? void 0 : _inputRef$current5.selectionStart) === 0 && tags.length > 0) {
2361
+ var _tagRefs$current$get3;
2362
+ e.preventDefault();
2363
+ (_tagRefs$current$get3 = tagRefs.current.get(tags.length - 1)) === null || _tagRefs$current$get3 === void 0 || _tagRefs$current$get3.focus();
2364
+ }
2365
+ }, [
2366
+ inputValue,
2367
+ tags,
2368
+ addTag,
2369
+ removeTag,
2370
+ isOpen,
2371
+ highlightIndex,
2372
+ filtered,
2373
+ undo,
2374
+ redo,
2375
+ inputRef
2376
+ ]);
2377
+ const handlePaste = useCallback((e) => {
2378
+ const parts = splitByDelimiters(e.clipboardData.getData("text/plain"), delimiters);
2379
+ if (parts.length < 2) return;
2380
+ e.preventDefault();
2381
+ const prev = [...tags];
2382
+ let next = [...tags];
2383
+ const remaining = maxTags ? maxTags - next.length : Infinity;
2384
+ for (const part of parts.slice(0, remaining)) {
2385
+ if (!allowDuplicates && next.includes(part)) continue;
2386
+ next = [...next, part];
2387
+ }
2388
+ if (next.length !== prev.length) {
2389
+ pushUndo(prev);
2390
+ setTags(next);
2391
+ setInputValue("");
2392
+ }
2393
+ }, [
2394
+ tags,
2395
+ setTags,
2396
+ maxTags,
2397
+ delimiters,
2398
+ allowDuplicates
2399
+ ]);
2400
+ useEffect(() => {
2401
+ if (highlightIndex >= 0 && listboxRef.current) {
2402
+ var _el$scrollIntoView;
2403
+ const el = listboxRef.current.children[highlightIndex];
2404
+ el === null || el === void 0 || (_el$scrollIntoView = el.scrollIntoView) === null || _el$scrollIntoView === void 0 || _el$scrollIntoView.call(el, { block: "nearest" });
2405
+ }
2406
+ }, [highlightIndex]);
2407
+ const atLimit = Boolean(maxTags && tags.length >= maxTags);
2408
+ return /* @__PURE__ */ jsxs("div", {
2409
+ className: cn("relative flex flex-col gap-1.5", className),
2410
+ "data-opt-id": "3TDWF",
2411
+ "data-opt-slug": "tag-input.TagInput",
2412
+ children: [
2413
+ label && /* @__PURE__ */ jsxs("span", {
2414
+ className: "text-sm font-medium text-text-primary",
2415
+ children: [label, required && /* @__PURE__ */ jsx(RequiredMark, {})]
2416
+ }),
2417
+ /* @__PURE__ */ jsxs("div", {
2418
+ className: cn("border-border bg-surface flex min-h-10 flex-wrap items-center gap-1.5 rounded-lg border px-3 py-1.5", "focus-within:ring-ring focus-within:ring-offset-ring-offset focus-within:ring-2 focus-within:ring-offset-1", hasError && "border-danger", disabled && "pointer-events-none opacity-50"),
2419
+ onMouseDown: () => {
2420
+ var _inputRef$current6;
2421
+ return (_inputRef$current6 = inputRef.current) === null || _inputRef$current6 === void 0 ? void 0 : _inputRef$current6.focus();
2422
+ },
2423
+ role: "group",
2424
+ "aria-label": (_ref2 = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : label) !== null && _ref2 !== void 0 ? _ref2 : "Tag input",
2425
+ "aria-required": required,
2426
+ "aria-invalid": hasError,
2427
+ "aria-describedby": describedBy,
2428
+ children: [tags.length > 0 && /* @__PURE__ */ jsx(CompositeProvider, {
2429
+ focusLoop: true,
2430
+ children: /* @__PURE__ */ jsx(Composite, {
2431
+ "aria-label": "Selected tags",
2432
+ className: "contents",
2433
+ children: tags.map((tag, i) => /* @__PURE__ */ jsxs(CompositeItem, {
2434
+ render: /* @__PURE__ */ jsx("span", { ref: (el) => {
2435
+ if (el) tagRefs.current.set(i, el);
2436
+ else tagRefs.current.delete(i);
2437
+ } }),
2438
+ className: cn(OPT_BADGE_BLUE, "flex items-center gap-1 py-1", "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset", "rounded-md"),
2439
+ onKeyDown: (e) => handleTagKeyDown(e, i),
2440
+ children: [tag, !disabled && /* @__PURE__ */ jsx("button", {
2441
+ type: "button",
2442
+ tabIndex: -1,
2443
+ onClick: (e) => {
2444
+ var _inputRef$current7;
2445
+ e.stopPropagation();
2446
+ removeTag(i);
2447
+ (_inputRef$current7 = inputRef.current) === null || _inputRef$current7 === void 0 || _inputRef$current7.focus();
2448
+ },
2449
+ className: "hover:bg-accent-subtle ml-0.5 rounded-full p-0.5",
2450
+ "aria-label": `Remove ${tag}`,
2451
+ children: /* @__PURE__ */ jsx("svg", {
2452
+ width: "10",
2453
+ height: "10",
2454
+ viewBox: "0 0 10 10",
2455
+ fill: "none",
2456
+ stroke: "currentColor",
2457
+ strokeWidth: "1.5",
2458
+ strokeLinecap: "round",
2459
+ children: /* @__PURE__ */ jsx("path", { d: "M2.5 2.5L7.5 7.5M7.5 2.5L2.5 7.5" })
2460
+ })
2461
+ })]
2462
+ }, `${tag}-${i}`))
2463
+ })
2464
+ }), /* @__PURE__ */ jsx("input", {
2465
+ ref: inputRef,
2466
+ type: "text",
2467
+ value: inputValue,
2468
+ onChange: (e) => {
2469
+ setInputValue(e.target.value);
2470
+ setShowSuggestions(true);
2471
+ },
2472
+ onKeyDown: handleInputKeyDown,
2473
+ onPaste: handlePaste,
2474
+ onFocus: () => setShowSuggestions(true),
2475
+ onBlur: () => {
2476
+ setTimeout(() => setShowSuggestions(false), 150);
2477
+ },
2478
+ placeholder: tags.length === 0 ? placeholder : atLimit ? "" : "",
2479
+ disabled: disabled || atLimit,
2480
+ className: cn("min-w-[60px] flex-1 border-none bg-transparent text-sm outline-transparent", OPT_TEXT_PRIMARY, OPT_FOCUS_VISIBLE, "placeholder:text-text-tertiary"),
2481
+ "aria-label": (_ref3 = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : label) !== null && _ref3 !== void 0 ? _ref3 : "Tag input",
2482
+ role: suggestions ? "combobox" : void 0,
2483
+ "aria-describedby": describedBy,
2484
+ "aria-expanded": suggestions ? isOpen : void 0,
2485
+ "aria-controls": suggestions ? listboxId : void 0,
2486
+ "aria-activedescendant": isOpen && highlightIndex >= 0 ? `${listboxId}-${highlightIndex}` : void 0,
2487
+ "aria-autocomplete": suggestions ? "list" : void 0
2488
+ })]
2489
+ }),
2490
+ isOpen && /* @__PURE__ */ jsx("ul", {
2491
+ ref: listboxRef,
2492
+ id: listboxId,
2493
+ role: "listbox",
2494
+ "aria-label": (_ref4 = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : label) !== null && _ref4 !== void 0 ? _ref4 : "Tag suggestions",
2495
+ className: "border-border bg-surface absolute top-full z-50 mt-1 max-h-48 w-full overflow-auto rounded-lg border shadow-md",
2496
+ children: filtered.map((suggestion, i) => /* @__PURE__ */ jsx("li", {
2497
+ id: `${listboxId}-${i}`,
2498
+ role: "option",
2499
+ "aria-selected": i === highlightIndex,
2500
+ className: cn("cursor-pointer px-3 py-1.5 text-sm", "text-text-primary", i === highlightIndex && "bg-accent-subtle"),
2501
+ onMouseDown: (e) => {
2502
+ e.preventDefault();
2503
+ addTag(suggestion);
2504
+ },
2505
+ onMouseEnter: () => setHighlightIndex(i),
2506
+ children: suggestion
2507
+ }, suggestion))
2508
+ }),
2509
+ maxTags && /* @__PURE__ */ jsxs("span", {
2510
+ className: "text-text-tertiary text-xs",
2511
+ children: [
2512
+ tags.length,
2513
+ "/",
2514
+ maxTags
2515
+ ]
2516
+ }),
2517
+ /* @__PURE__ */ jsx(FieldMessages, {
2518
+ id: tagInputId,
2519
+ error,
2520
+ hint
2521
+ })
2522
+ ]
2523
+ });
2524
+ });
2525
+ TagInput.displayName = "TagInput";
2526
+ //#endregion
2527
+ //#region src/core/date-range-picker.tsx
2528
+ const DAYS = [
2529
+ "Su",
2530
+ "Mo",
2531
+ "Tu",
2532
+ "We",
2533
+ "Th",
2534
+ "Fr",
2535
+ "Sa"
2536
+ ];
2537
+ function defaultFormat(date) {
2538
+ return date.toLocaleDateString("en-US", {
2539
+ year: "numeric",
2540
+ month: "short",
2541
+ day: "numeric"
2542
+ });
2543
+ }
2544
+ function isSameDay(a, b) {
2545
+ return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
2546
+ }
2547
+ function isInRange(date, start, end) {
2548
+ if (!start || !end) return false;
2549
+ const t = date.getTime();
2550
+ return t >= start.getTime() && t <= end.getTime();
2551
+ }
2552
+ function getDaysInMonth(year, month) {
2553
+ return new Date(year, month + 1, 0).getDate();
2554
+ }
2555
+ function getFirstDayOfMonth(year, month) {
2556
+ return new Date(year, month, 1).getDay();
2557
+ }
2558
+ function startOfDay(date) {
2559
+ const normalized = new Date(date);
2560
+ normalized.setHours(0, 0, 0, 0);
2561
+ return normalized;
2562
+ }
2563
+ function getDateKey(date) {
2564
+ return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
2565
+ }
2566
+ function createDateInMonth(year, month, day) {
2567
+ return startOfDay(new Date(year, month, Math.min(day, getDaysInMonth(year, month))));
2568
+ }
2569
+ const DEFAULT_PRESETS = [
2570
+ {
2571
+ label: "Today",
2572
+ range: () => {
2573
+ const now = /* @__PURE__ */ new Date();
2574
+ now.setHours(0, 0, 0, 0);
2575
+ return {
2576
+ start: now,
2577
+ end: new Date(now)
2578
+ };
2579
+ }
2580
+ },
2581
+ {
2582
+ label: "Last 7 days",
2583
+ range: () => {
2584
+ const end = /* @__PURE__ */ new Date();
2585
+ end.setHours(0, 0, 0, 0);
2586
+ const start = new Date(end);
2587
+ start.setDate(start.getDate() - 6);
2588
+ return {
2589
+ start,
2590
+ end
2591
+ };
2592
+ }
2593
+ },
2594
+ {
2595
+ label: "Last 30 days",
2596
+ range: () => {
2597
+ const end = /* @__PURE__ */ new Date();
2598
+ end.setHours(0, 0, 0, 0);
2599
+ const start = new Date(end);
2600
+ start.setDate(start.getDate() - 29);
2601
+ return {
2602
+ start,
2603
+ end
2604
+ };
2605
+ }
2606
+ },
2607
+ {
2608
+ label: "Last 90 days",
2609
+ range: () => {
2610
+ const end = /* @__PURE__ */ new Date();
2611
+ end.setHours(0, 0, 0, 0);
2612
+ const start = new Date(end);
2613
+ start.setDate(start.getDate() - 89);
2614
+ return {
2615
+ start,
2616
+ end
2617
+ };
2618
+ }
2619
+ },
2620
+ {
2621
+ label: "This month",
2622
+ range: () => {
2623
+ const now = /* @__PURE__ */ new Date();
2624
+ now.setHours(0, 0, 0, 0);
2625
+ return {
2626
+ start: new Date(now.getFullYear(), now.getMonth(), 1),
2627
+ end: now
2628
+ };
2629
+ }
2630
+ },
2631
+ {
2632
+ label: "Last month",
2633
+ range: () => {
2634
+ const now = /* @__PURE__ */ new Date();
2635
+ return {
2636
+ start: new Date(now.getFullYear(), now.getMonth() - 1, 1),
2637
+ end: new Date(now.getFullYear(), now.getMonth(), 0)
2638
+ };
2639
+ }
2640
+ }
2641
+ ];
2642
+ const GRANULARITY_OPTIONS = [
2643
+ {
2644
+ value: "hour",
2645
+ label: "Hour"
2646
+ },
2647
+ {
2648
+ value: "day",
2649
+ label: "Day"
2650
+ },
2651
+ {
2652
+ value: "week",
2653
+ label: "Week"
2654
+ },
2655
+ {
2656
+ value: "month",
2657
+ label: "Month"
2658
+ }
2659
+ ];
2660
+ const COMPARISON_OPTIONS = [{
2661
+ value: "previous",
2662
+ label: "vs Previous period"
2663
+ }, {
2664
+ value: "year-over-year",
2665
+ label: "vs Same period last year"
2666
+ }];
2667
+ /** Renders the date range picker component. */
2668
+ function DateRangePicker({ value, onChange, presets = DEFAULT_PRESETS, placeholder = "Select date range", label, required, error, hint, className, id, triggerClassName, "aria-label": ariaLabel, disabled = false, format = defaultFormat, comparison = false, comparisonMode, onComparisonChange, showGranularity = false, granularity, onGranularityChange }) {
2669
+ var _useInputId, _ref3;
2670
+ const fallbackId = useId().replace(/:/g, "");
2671
+ const pickerId = (_useInputId = useInputId(id, label, "date-range-picker")) !== null && _useInputId !== void 0 ? _useInputId : `date-range-picker-${fallbackId}`;
2672
+ const hasError = Boolean(error);
2673
+ const [range, setRange] = useControlledState({
2674
+ start: null,
2675
+ end: null
2676
+ }, value, onChange);
2677
+ const [selecting, setSelecting] = useState("start");
2678
+ const [viewDate, setViewDate] = useState(() => {
2679
+ var _range$start;
2680
+ const d = (_range$start = range.start) !== null && _range$start !== void 0 ? _range$start : /* @__PURE__ */ new Date();
2681
+ return {
2682
+ year: d.getFullYear(),
2683
+ month: d.getMonth()
2684
+ };
2685
+ });
2686
+ const [focusedDate, setFocusedDate] = useState(() => {
2687
+ var _ref, _range$start2;
2688
+ return startOfDay((_ref = (_range$start2 = range.start) !== null && _range$start2 !== void 0 ? _range$start2 : range.end) !== null && _ref !== void 0 ? _ref : /* @__PURE__ */ new Date());
2689
+ });
2690
+ const dayButtonRefs = useRef({});
2691
+ const granularityButtonRefs = useRef({
2692
+ hour: null,
2693
+ day: null,
2694
+ week: null,
2695
+ month: null
2696
+ });
2697
+ const pendingFocusDateRef = useRef(null);
2698
+ const displayText = useMemo(() => {
2699
+ if (range.start && range.end) return `${format(range.start)} — ${format(range.end)}`;
2700
+ if (range.start) return `${format(range.start)} — ...`;
2701
+ return placeholder;
2702
+ }, [
2703
+ range,
2704
+ format,
2705
+ placeholder
2706
+ ]);
2707
+ const handleDayClick = useCallback((day) => {
2708
+ setFocusedDate(day);
2709
+ if (selecting === "start") {
2710
+ setRange({
2711
+ start: day,
2712
+ end: null
2713
+ });
2714
+ setSelecting("end");
2715
+ } else {
2716
+ if (range.start && day.getTime() < range.start.getTime()) setRange({
2717
+ start: day,
2718
+ end: range.start
2719
+ });
2720
+ else setRange({
2721
+ start: range.start,
2722
+ end: day
2723
+ });
2724
+ setSelecting("start");
2725
+ }
2726
+ }, [
2727
+ selecting,
2728
+ range.start,
2729
+ setRange
2730
+ ]);
2731
+ const handlePresetClick = useCallback((preset) => {
2732
+ var _ref2, _newRange$start;
2733
+ const newRange = preset.range();
2734
+ const nextFocusDate = startOfDay((_ref2 = (_newRange$start = newRange.start) !== null && _newRange$start !== void 0 ? _newRange$start : newRange.end) !== null && _ref2 !== void 0 ? _ref2 : /* @__PURE__ */ new Date());
2735
+ setRange(newRange);
2736
+ setViewDate({
2737
+ year: nextFocusDate.getFullYear(),
2738
+ month: nextFocusDate.getMonth()
2739
+ });
2740
+ setFocusedDate(nextFocusDate);
2741
+ setSelecting("start");
2742
+ }, [setRange]);
2743
+ const moveFocusToDate = useCallback((date) => {
2744
+ const nextDate = startOfDay(date);
2745
+ pendingFocusDateRef.current = nextDate;
2746
+ setViewDate({
2747
+ year: nextDate.getFullYear(),
2748
+ month: nextDate.getMonth()
2749
+ });
2750
+ setFocusedDate(nextDate);
2751
+ }, []);
2752
+ const prevMonth = useCallback(() => {
2753
+ setViewDate((v) => {
2754
+ const m = v.month - 1;
2755
+ const nextViewDate = m < 0 ? {
2756
+ year: v.year - 1,
2757
+ month: 11
2758
+ } : {
2759
+ year: v.year,
2760
+ month: m
2761
+ };
2762
+ setFocusedDate((currentFocusedDate) => createDateInMonth(nextViewDate.year, nextViewDate.month, currentFocusedDate.getDate()));
2763
+ return nextViewDate;
2764
+ });
2765
+ }, []);
2766
+ const nextMonth = useCallback(() => {
2767
+ setViewDate((v) => {
2768
+ const m = v.month + 1;
2769
+ const nextViewDate = m > 11 ? {
2770
+ year: v.year + 1,
2771
+ month: 0
2772
+ } : {
2773
+ year: v.year,
2774
+ month: m
2775
+ };
2776
+ setFocusedDate((currentFocusedDate) => createDateInMonth(nextViewDate.year, nextViewDate.month, currentFocusedDate.getDate()));
2777
+ return nextViewDate;
2778
+ });
2779
+ }, []);
2780
+ const { daysInMonth, firstDay, monthLabel } = useMemo(() => {
2781
+ return {
2782
+ daysInMonth: getDaysInMonth(viewDate.year, viewDate.month),
2783
+ firstDay: getFirstDayOfMonth(viewDate.year, viewDate.month),
2784
+ monthLabel: new Date(viewDate.year, viewDate.month).toLocaleDateString("en-US", {
2785
+ month: "long",
2786
+ year: "numeric"
2787
+ })
2788
+ };
2789
+ }, [viewDate.year, viewDate.month]);
2790
+ const today = useMemo(() => {
2791
+ const d = /* @__PURE__ */ new Date();
2792
+ d.setHours(0, 0, 0, 0);
2793
+ return d;
2794
+ }, []);
2795
+ const calendarWeeks = useMemo(() => {
2796
+ const leadingDays = Array.from({ length: firstDay }, () => null);
2797
+ const monthDays = Array.from({ length: daysInMonth }, (_, index) => startOfDay(new Date(viewDate.year, viewDate.month, index + 1)));
2798
+ const trailingDays = Array.from({ length: (7 - ((leadingDays.length + monthDays.length) % 7 || 7)) % 7 }, () => null);
2799
+ const cells = [
2800
+ ...leadingDays,
2801
+ ...monthDays,
2802
+ ...trailingDays
2803
+ ];
2804
+ return Array.from({ length: cells.length / 7 }, (_, rowIndex) => cells.slice(rowIndex * 7, rowIndex * 7 + 7));
2805
+ }, [
2806
+ daysInMonth,
2807
+ firstDay,
2808
+ viewDate.month,
2809
+ viewDate.year
2810
+ ]);
2811
+ const handleDayKeyDown = useCallback((event, day) => {
2812
+ const nextDateFactory = {
2813
+ ArrowLeft: () => startOfDay(new Date(day.getFullYear(), day.getMonth(), day.getDate() - 1)),
2814
+ ArrowRight: () => startOfDay(new Date(day.getFullYear(), day.getMonth(), day.getDate() + 1)),
2815
+ ArrowUp: () => startOfDay(new Date(day.getFullYear(), day.getMonth(), day.getDate() - 7)),
2816
+ ArrowDown: () => startOfDay(new Date(day.getFullYear(), day.getMonth(), day.getDate() + 7)),
2817
+ Home: () => startOfDay(new Date(day.getFullYear(), day.getMonth(), day.getDate() - day.getDay())),
2818
+ End: () => startOfDay(new Date(day.getFullYear(), day.getMonth(), day.getDate() + (6 - day.getDay()))),
2819
+ PageUp: () => createDateInMonth(day.getFullYear(), day.getMonth() - 1, day.getDate()),
2820
+ PageDown: () => createDateInMonth(day.getFullYear(), day.getMonth() + 1, day.getDate())
2821
+ }[event.key];
2822
+ if (!nextDateFactory) return;
2823
+ event.preventDefault();
2824
+ moveFocusToDate(nextDateFactory());
2825
+ }, [moveFocusToDate]);
2826
+ const handleGranularityKeyDown = useCallback((event, currentValue) => {
2827
+ const currentIndex = GRANULARITY_OPTIONS.findIndex((opt) => opt.value === currentValue);
2828
+ if (currentIndex < 0) return;
2829
+ let nextIndex = -1;
2830
+ switch (event.key) {
2831
+ case "ArrowRight":
2832
+ case "ArrowDown":
2833
+ nextIndex = (currentIndex + 1) % GRANULARITY_OPTIONS.length;
2834
+ break;
2835
+ case "ArrowLeft":
2836
+ case "ArrowUp":
2837
+ nextIndex = (currentIndex - 1 + GRANULARITY_OPTIONS.length) % GRANULARITY_OPTIONS.length;
2838
+ break;
2839
+ case "Home":
2840
+ nextIndex = 0;
2841
+ break;
2842
+ case "End":
2843
+ nextIndex = GRANULARITY_OPTIONS.length - 1;
2844
+ break;
2845
+ default: return;
2846
+ }
2847
+ event.preventDefault();
2848
+ const nextValue = GRANULARITY_OPTIONS[nextIndex].value;
2849
+ onGranularityChange === null || onGranularityChange === void 0 || onGranularityChange(nextValue);
2850
+ requestAnimationFrame(() => {
2851
+ var _granularityButtonRef;
2852
+ (_granularityButtonRef = granularityButtonRefs.current[nextValue]) === null || _granularityButtonRef === void 0 || _granularityButtonRef.focus();
2853
+ });
2854
+ }, [onGranularityChange]);
2855
+ useEffect(() => {
2856
+ var _dayButtonRefs$curren;
2857
+ if (!pendingFocusDateRef.current) return;
2858
+ const button = (_dayButtonRefs$curren = dayButtonRefs.current[getDateKey(pendingFocusDateRef.current)]) !== null && _dayButtonRefs$curren !== void 0 ? _dayButtonRefs$curren : null;
2859
+ if (!button) return;
2860
+ button.focus();
2861
+ pendingFocusDateRef.current = null;
2862
+ }, [
2863
+ calendarWeeks,
2864
+ focusedDate,
2865
+ monthLabel
2866
+ ]);
2867
+ return /* @__PURE__ */ jsxs("div", {
2868
+ className: cn("flex flex-col gap-1.5", className),
2869
+ "data-opt-id": "0KKZ0",
2870
+ "data-opt-slug": "date-range-picker.DateRangePicker",
2871
+ children: [
2872
+ label && /* @__PURE__ */ jsxs("span", {
2873
+ className: "text-text-primary text-sm font-medium",
2874
+ children: [label, required && /* @__PURE__ */ jsx(RequiredMark, {})]
2875
+ }),
2876
+ /* @__PURE__ */ jsxs(PopoverRoot$1, { children: [/* @__PURE__ */ jsxs(PopoverTrigger$1, {
2877
+ id: pickerId,
2878
+ className: cn(triggerClassName !== null && triggerClassName !== void 0 ? triggerClassName : OPT_INPUT, "cursor-pointer justify-between gap-2 text-left", !range.start && "text-text-tertiary", hasError && "border-danger focus-visible:outline-danger", disabled && "pointer-events-none opacity-50"),
2879
+ disabled,
2880
+ "aria-label": (_ref3 = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : label) !== null && _ref3 !== void 0 ? _ref3 : "Date range picker",
2881
+ "aria-required": required,
2882
+ "aria-invalid": hasError,
2883
+ "aria-describedby": getDescribedBy(pickerId, error, hint),
2884
+ children: [/* @__PURE__ */ jsx("span", {
2885
+ className: "truncate",
2886
+ children: displayText
2887
+ }), /* @__PURE__ */ jsx(CalendarDays, {
2888
+ "aria-hidden": "true",
2889
+ className: "text-text-tertiary size-4 shrink-0"
2890
+ })]
2891
+ }), /* @__PURE__ */ jsxs(PopoverContent$1, {
2892
+ className: cn("bg-surface-overlay z-50 rounded-lg p-4 shadow-lg", OPT_BORDER),
2893
+ children: [/* @__PURE__ */ jsxs("div", {
2894
+ className: "flex gap-4",
2895
+ children: [presets.length > 0 && /* @__PURE__ */ jsxs("div", {
2896
+ className: "border-border-subtle flex flex-col gap-1 border-r pr-4",
2897
+ children: [/* @__PURE__ */ jsx("span", {
2898
+ className: cn("text-text-secondary", "mb-1 text-xs font-semibold tracking-wider uppercase"),
2899
+ children: "Presets"
2900
+ }), presets.map((preset) => /* @__PURE__ */ jsx("button", {
2901
+ type: "button",
2902
+ onClick: () => handlePresetClick(preset),
2903
+ className: cn("rounded-md px-3 py-1.5 text-left text-sm", "text-text-primary", "hover:bg-accent-subtle", "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset"),
2904
+ children: preset.label
2905
+ }, preset.label))]
2906
+ }), /* @__PURE__ */ jsxs("div", {
2907
+ className: "flex flex-col gap-2",
2908
+ children: [/* @__PURE__ */ jsxs("div", {
2909
+ className: "flex items-center justify-between",
2910
+ children: [
2911
+ /* @__PURE__ */ jsx("button", {
2912
+ type: "button",
2913
+ onClick: prevMonth,
2914
+ className: cn("rounded-md p-1", OPT_TEXT_SECONDARY, "hover:bg-bg-subtle", OPT_FOCUS_VISIBLE),
2915
+ "aria-label": "Previous month",
2916
+ children: /* @__PURE__ */ jsx(ChevronLeft, {
2917
+ "aria-hidden": "true",
2918
+ className: "size-4 rtl:-scale-x-100"
2919
+ })
2920
+ }),
2921
+ /* @__PURE__ */ jsx("span", {
2922
+ className: cn(OPT_TEXT_PRIMARY, "text-sm font-medium"),
2923
+ children: monthLabel
2924
+ }),
2925
+ /* @__PURE__ */ jsx("button", {
2926
+ type: "button",
2927
+ onClick: nextMonth,
2928
+ className: cn("rounded-md p-1", OPT_TEXT_SECONDARY, "hover:bg-bg-subtle", OPT_FOCUS_VISIBLE),
2929
+ "aria-label": "Next month",
2930
+ children: /* @__PURE__ */ jsx(ChevronRight, {
2931
+ "aria-hidden": "true",
2932
+ className: "size-4 rtl:-scale-x-100"
2933
+ })
2934
+ })
2935
+ ]
2936
+ }), /* @__PURE__ */ jsxs("div", {
2937
+ className: "flex flex-col gap-0",
2938
+ role: "grid",
2939
+ "aria-label": monthLabel,
2940
+ children: [/* @__PURE__ */ jsx("div", {
2941
+ className: "grid grid-cols-7 gap-0",
2942
+ role: "row",
2943
+ children: DAYS.map((d) => /* @__PURE__ */ jsx("div", {
2944
+ className: cn(OPT_TEXT_TERTIARY, "flex h-8 w-8 items-center justify-center text-xs font-medium"),
2945
+ role: "columnheader",
2946
+ children: d
2947
+ }, d))
2948
+ }), calendarWeeks.map((week, weekIndex) => /* @__PURE__ */ jsx("div", {
2949
+ className: "grid grid-cols-7 gap-0",
2950
+ role: "row",
2951
+ children: week.map((day, dayIndex) => {
2952
+ if (!day) return /* @__PURE__ */ jsx("div", {
2953
+ className: "h-8 w-8",
2954
+ role: "gridcell",
2955
+ "aria-hidden": "true"
2956
+ }, `${monthLabel}-empty-${weekIndex + 1}-${dayIndex + 1}`);
2957
+ const isToday = isSameDay(day, today);
2958
+ const isSelected = range.start && isSameDay(day, range.start) || range.end && isSameDay(day, range.end);
2959
+ const inRange = isInRange(day, range.start, range.end);
2960
+ const isFocused = isSameDay(day, focusedDate);
2961
+ const dayLabel = day.toLocaleDateString("en-US", {
2962
+ weekday: "long",
2963
+ year: "numeric",
2964
+ month: "long",
2965
+ day: "numeric"
2966
+ });
2967
+ const dateKey = getDateKey(day);
2968
+ return /* @__PURE__ */ jsx("div", {
2969
+ role: "gridcell",
2970
+ "aria-selected": isSelected || void 0,
2971
+ className: "flex h-8 w-8 items-center justify-center",
2972
+ children: /* @__PURE__ */ jsx("button", {
2973
+ ref: (node) => {
2974
+ dayButtonRefs.current[dateKey] = node;
2975
+ },
2976
+ type: "button",
2977
+ onClick: () => handleDayClick(day),
2978
+ onFocus: () => setFocusedDate(day),
2979
+ onKeyDown: (event) => handleDayKeyDown(event, day),
2980
+ tabIndex: isFocused ? 0 : -1,
2981
+ className: cn("flex h-8 w-8 items-center justify-center rounded-md text-sm", OPT_FOCUS_VISIBLE, isSelected && "bg-accent text-accent-fg font-medium", !isSelected && inRange && "bg-accent-subtle text-accent-fg", !isSelected && !inRange && "text-text-primary hover:bg-bg-subtle", isToday && !isSelected && "decoration-accent font-semibold underline underline-offset-2"),
2982
+ "aria-label": dayLabel,
2983
+ "aria-current": isToday ? "date" : void 0,
2984
+ children: day.getDate()
2985
+ })
2986
+ }, dateKey);
2987
+ })
2988
+ }, `${monthLabel}-week-${weekIndex + 1}`))]
2989
+ })]
2990
+ })]
2991
+ }), (showGranularity || comparison) && /* @__PURE__ */ jsxs("div", {
2992
+ className: "border-border-subtle mt-3 flex flex-wrap items-center gap-3 border-t pt-3",
2993
+ children: [showGranularity && /* @__PURE__ */ jsxs("div", {
2994
+ className: "flex items-center gap-1.5",
2995
+ role: "radiogroup",
2996
+ "aria-label": "Time granularity",
2997
+ children: [/* @__PURE__ */ jsx("span", {
2998
+ className: cn("text-text-secondary", "text-xs font-medium"),
2999
+ children: "Granularity"
3000
+ }), GRANULARITY_OPTIONS.map((opt) => /* @__PURE__ */ jsx("button", {
3001
+ ref: (node) => {
3002
+ granularityButtonRefs.current[opt.value] = node;
3003
+ },
3004
+ type: "button",
3005
+ role: "radio",
3006
+ "aria-checked": granularity === opt.value,
3007
+ onKeyDown: (event) => handleGranularityKeyDown(event, opt.value),
3008
+ onClick: () => onGranularityChange === null || onGranularityChange === void 0 ? void 0 : onGranularityChange(opt.value),
3009
+ className: cn("rounded-md px-2 py-1 text-xs", "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset", granularity === opt.value ? "bg-accent text-accent-fg font-medium" : cn("text-text-primary", "hover:bg-bg-subtle")),
3010
+ children: opt.label
3011
+ }, opt.value))]
3012
+ }), comparison && /* @__PURE__ */ jsxs("div", {
3013
+ className: "flex items-center gap-1.5",
3014
+ role: "group",
3015
+ "aria-label": "Comparison mode",
3016
+ children: [/* @__PURE__ */ jsx("span", {
3017
+ className: cn("text-text-secondary", "text-xs font-medium"),
3018
+ children: "Compare"
3019
+ }), COMPARISON_OPTIONS.map((opt) => /* @__PURE__ */ jsx("button", {
3020
+ type: "button",
3021
+ "aria-pressed": comparisonMode === opt.value,
3022
+ onClick: () => onComparisonChange === null || onComparisonChange === void 0 ? void 0 : onComparisonChange(comparisonMode === opt.value ? null : opt.value),
3023
+ className: cn("rounded-md px-2 py-1 text-xs", "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-ring-offset", comparisonMode === opt.value ? "bg-accent text-accent-fg font-medium" : cn("text-text-primary", "hover:bg-bg-subtle")),
3024
+ children: opt.label
3025
+ }, opt.value))]
3026
+ })]
3027
+ })]
3028
+ })] }),
3029
+ /* @__PURE__ */ jsx(FieldMessages, {
3030
+ id: pickerId,
3031
+ error,
3032
+ hint
3033
+ })
3034
+ ]
3035
+ });
3036
+ }
3037
+ DateRangePicker.displayName = "DateRangePicker";
3038
+ //#endregion
3039
+ //#region src/core/form.tsx
3040
+ const _excluded$2 = ["className", "store"];
3041
+ const _excluded2 = ["className"];
3042
+ const _excluded3 = [
3043
+ "className",
3044
+ "resize",
3045
+ "rows",
3046
+ "name"
3047
+ ];
3048
+ const _excluded4 = ["className"];
3049
+ const _excluded5 = ["className"];
3050
+ const _excluded6 = [
3051
+ "className",
3052
+ "size",
3053
+ "name"
3054
+ ];
3055
+ const _excluded7 = ["className"];
3056
+ const _excluded8 = ["className"];
3057
+ const _excluded9 = [
3058
+ "className",
3059
+ "disabled",
3060
+ "children"
3061
+ ];
3062
+ const _excluded10 = ["className"];
3063
+ const _excluded11 = ["className"];
3064
+ const _excluded12 = ["className"];
3065
+ const _excluded13 = ["className"];
3066
+ const _excluded14 = ["className"];
3067
+ const _excluded15 = ["className"];
3068
+ const _excluded16 = ["className"];
3069
+ const _excluded17 = ["className"];
3070
+ const _excluded18 = ["className"];
3071
+ const _excluded19 = ["className"];
3072
+ const _excluded20 = ["className"];
3073
+ const _excluded21 = ["name"];
3074
+ const _excluded22 = ["name"];
3075
+ const _excluded23 = ["name"];
3076
+ const _excluded24 = ["name"];
3077
+ const _excluded25 = ["name"];
3078
+ const _excluded26 = ["name"];
3079
+ const _excluded27 = ["name"];
3080
+ const inputClass = `${OPT_INPUT} aria-[invalid=true]:border-danger`;
3081
+ const labelClass = OPT_TEXT_LABEL;
3082
+ const descriptionClass = "text-xs text-text-tertiary";
3083
+ const errorClass = "text-xs text-danger-fg";
3084
+ const submitClass = OPT_BUTTON_PRIMARY;
3085
+ const checkboxClass = `h-4 w-4 rounded accent-accent ${OPT_FOCUS_VISIBLE}`;
3086
+ const radioClass = `h-4 w-4 accent-accent ${OPT_FOCUS_VISIBLE}`;
3087
+ function useRequiredFormContext(componentName) {
3088
+ const form = useFormContext();
3089
+ if (!form) throw new Error(`${componentName} must be used within FormRoot or FormProvider with a store.`);
3090
+ return form;
3091
+ }
3092
+ /** Renders the form root component. */
3093
+ function FormRoot$1(_ref) {
3094
+ let { className, store } = _ref, props = _objectWithoutProperties(_ref, _excluded$2);
3095
+ const form = /* @__PURE__ */ jsx(FormRoot, _objectSpread2({ className: cn("gap-section flex flex-col", className) }, props));
3096
+ if (store) return /* @__PURE__ */ jsx(FormProvider, {
3097
+ store,
3098
+ "data-opt-id": "YBT1H",
3099
+ "data-opt-slug": "form.FormRoot",
3100
+ children: form
3101
+ });
3102
+ return form;
3103
+ }
3104
+ /** Renders the form input component. */
3105
+ function FormInput$1(_ref2) {
3106
+ let { className } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2);
3107
+ return /* @__PURE__ */ jsx(FormInput, _objectSpread2(_objectSpread2({ className: cn(inputClass, className) }, props), {}, {
3108
+ "data-opt-id": "D7Z8F",
3109
+ "data-opt-slug": "form.FormInput"
3110
+ }));
3111
+ }
3112
+ const resizeStyles = {
3113
+ none: "resize-none",
3114
+ vertical: "resize-y",
3115
+ horizontal: "resize-x",
3116
+ both: "resize"
3117
+ };
3118
+ /** Renders the form textarea component. */
3119
+ function FormTextarea(_ref3) {
3120
+ var _ref4;
3121
+ let { className, resize = "vertical", rows = 4, name } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3);
3122
+ const form = useRequiredFormContext("FormTextarea");
3123
+ const value = (_ref4 = useFieldValue(form, name)) !== null && _ref4 !== void 0 ? _ref4 : "";
3124
+ const error = form === null || form === void 0 ? void 0 : form.getError(name);
3125
+ const touched = form === null || form === void 0 ? void 0 : form.getFieldTouched(name);
3126
+ const hasError = Boolean(error && touched);
3127
+ return /* @__PURE__ */ jsx("textarea", _objectSpread2(_objectSpread2({
3128
+ name,
3129
+ value,
3130
+ onChange: (e) => form === null || form === void 0 ? void 0 : form.setValue(name, e.target.value),
3131
+ className: cn("border-border bg-surface flex w-full rounded-lg border px-4 py-3", "text-text-primary placeholder:text-text-tertiary focus-visible:ring-ring focus-visible:ring-offset-ring-offset text-sm outline-none focus-visible:ring-2 focus-visible:ring-offset-1", OPT_FOCUS_VISIBLE, resizeStyles[resize], hasError && "border-danger", className),
3132
+ rows,
3133
+ "aria-invalid": hasError || void 0
3134
+ }, props), {}, {
3135
+ "data-opt-id": "Q8G2A",
3136
+ "data-opt-slug": "form.FormTextarea"
3137
+ }));
3138
+ }
3139
+ /** Renders the form select component. */
3140
+ function FormSelect({ name, children, className, placeholder, minWidth = 140, "aria-label": ariaLabel }) {
3141
+ var _ref5;
3142
+ const form = useRequiredFormContext("FormSelect");
3143
+ const value = (_ref5 = useFieldValue(form, name)) !== null && _ref5 !== void 0 ? _ref5 : "";
3144
+ const error = form === null || form === void 0 ? void 0 : form.getError(name);
3145
+ const touched = form === null || form === void 0 ? void 0 : form.getFieldTouched(name);
3146
+ const hasError = Boolean(error && touched);
3147
+ return /* @__PURE__ */ jsxs(SelectRoot$1, {
3148
+ value,
3149
+ onValueChange: useCallback((v) => {
3150
+ var _v$;
3151
+ return form.setValue(name, Array.isArray(v) ? (_v$ = v[0]) !== null && _v$ !== void 0 ? _v$ : "" : v);
3152
+ }, [form, name]),
3153
+ "data-opt-id": "A2XF7",
3154
+ "data-opt-slug": "form.FormSelect",
3155
+ children: [/* @__PURE__ */ jsx(SelectTrigger$1, {
3156
+ "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : name,
3157
+ "aria-invalid": hasError || void 0,
3158
+ className: cn("inline-flex cursor-pointer items-center justify-between data-[disabled]:cursor-not-allowed", hasError && "border-danger", className),
3159
+ style: { minWidth: typeof minWidth === "number" ? `${minWidth}px` : minWidth },
3160
+ children: value || placeholder || "Select…"
3161
+ }), children]
3162
+ });
3163
+ }
3164
+ /** Renders the form select popover component. */
3165
+ function FormSelectPopover(_ref6) {
3166
+ let { className } = _ref6, props = _objectWithoutProperties(_ref6, _excluded4);
3167
+ return /* @__PURE__ */ jsx(SelectPopover$1, _objectSpread2(_objectSpread2({ className: cn(OPT_SURFACE_POPOVER, OPT_ANIMATE_ENTER_EXIT, "z-[120]", className) }, props), {}, {
3168
+ "data-opt-id": "CQSPJ",
3169
+ "data-opt-slug": "form.FormSelectPopover"
3170
+ }));
3171
+ }
3172
+ /** Renders the form select item component. */
3173
+ function FormSelectItem(_ref7) {
3174
+ let { className } = _ref7, props = _objectWithoutProperties(_ref7, _excluded5);
3175
+ return /* @__PURE__ */ jsx(SelectItem$1, _objectSpread2(_objectSpread2({ className: cn("flex cursor-pointer items-center gap-2 data-[disabled]:cursor-not-allowed", OPT_ITEM_BASE, OPT_ACTIVE_ITEM, className) }, props), {}, {
3176
+ "data-opt-id": "J3970",
3177
+ "data-opt-slug": "form.FormSelectItem"
3178
+ }));
3179
+ }
3180
+ const switchSizeStyles = {
3181
+ sm: {
3182
+ track: "h-5 w-9",
3183
+ thumb: "h-4 w-4"
3184
+ },
3185
+ md: {
3186
+ track: "h-6 w-11",
3187
+ thumb: "h-5 w-5"
3188
+ },
3189
+ lg: {
3190
+ track: "h-7 w-14",
3191
+ thumb: "h-6 w-6"
3192
+ }
3193
+ };
3194
+ /** Renders the form switch component. */
3195
+ function FormSwitch$1(_ref8) {
3196
+ let { className, size = "md", name } = _ref8, props = _objectWithoutProperties(_ref8, _excluded6);
3197
+ const styles = switchSizeStyles[size];
3198
+ const form = useRequiredFormContext("FormSwitch");
3199
+ const checked = Boolean(useFieldValue(form, name));
3200
+ return /* @__PURE__ */ jsx(FormSwitch, _objectSpread2(_objectSpread2({
3201
+ name,
3202
+ className: cn("group relative inline-flex shrink-0 cursor-pointer rounded-full p-0.5 transition-colors", styles.track, "bg-bg-muted", "aria-[checked=true]:bg-accent", "disabled:cursor-not-allowed disabled:opacity-50", OPT_FOCUS_VISIBLE, className),
3203
+ "aria-checked": checked
3204
+ }, props), {}, {
3205
+ "data-opt-id": "48T40",
3206
+ "data-opt-slug": "form.FormSwitch",
3207
+ children: /* @__PURE__ */ jsx("span", { className: cn("pointer-events-none inline-block transform rounded-full bg-white shadow-sm ring-0 transition-transform", styles.thumb, "translate-x-0", size === "sm" && "group-aria-[checked=true]:translate-x-4", size === "md" && "group-aria-[checked=true]:translate-x-5", size === "lg" && "group-aria-[checked=true]:translate-x-7") })
3208
+ }));
3209
+ }
3210
+ /** Renders the form label component. */
3211
+ function FormLabel$1(_ref9) {
3212
+ let { className } = _ref9, props = _objectWithoutProperties(_ref9, _excluded7);
3213
+ return /* @__PURE__ */ jsx(FormLabel, _objectSpread2(_objectSpread2({ className: cn(labelClass, className) }, props), {}, {
3214
+ "data-opt-id": "JHRKM",
3215
+ "data-opt-slug": "form.FormLabel"
3216
+ }));
3217
+ }
3218
+ /** Renders the form error component. */
3219
+ function FormError$1(_ref10) {
3220
+ let { className } = _ref10, props = _objectWithoutProperties(_ref10, _excluded8);
3221
+ return /* @__PURE__ */ jsx(FormError, _objectSpread2(_objectSpread2({ className: cn(errorClass, className) }, props), {}, {
3222
+ "data-opt-id": "E9NM4",
3223
+ "data-opt-slug": "form.FormError"
3224
+ }));
3225
+ }
3226
+ /** Renders the form submit component. */
3227
+ function FormSubmit$1(_ref11) {
3228
+ var _form$isSubmitting;
3229
+ let { className, disabled, children } = _ref11, props = _objectWithoutProperties(_ref11, _excluded9);
3230
+ const form = useFormContext();
3231
+ const isSubmitting = (_form$isSubmitting = form === null || form === void 0 ? void 0 : form.isSubmitting()) !== null && _form$isSubmitting !== void 0 ? _form$isSubmitting : false;
3232
+ return /* @__PURE__ */ jsx(FormSubmit, _objectSpread2(_objectSpread2({
3233
+ className: cn(submitClass, className),
3234
+ disabled: disabled !== null && disabled !== void 0 ? disabled : isSubmitting
3235
+ }, props), {}, {
3236
+ "data-opt-id": "K580M",
3237
+ "data-opt-slug": "form.FormSubmit",
3238
+ children
3239
+ }));
3240
+ }
3241
+ /** Renders the form provider component. */
3242
+ function FormProvider$1(props) {
3243
+ return /* @__PURE__ */ jsx(FormProvider, _objectSpread2(_objectSpread2({}, props), {}, {
3244
+ "data-opt-id": "G0DQ4",
3245
+ "data-opt-slug": "form.FormProvider"
3246
+ }));
3247
+ }
3248
+ /** Renders the form group component. */
3249
+ function FormGroup$1(_ref12) {
3250
+ let { className } = _ref12, props = _objectWithoutProperties(_ref12, _excluded10);
3251
+ return /* @__PURE__ */ jsx(FormGroup, _objectSpread2(_objectSpread2({ className: cn("gap-group flex flex-col", className) }, props), {}, {
3252
+ "data-opt-id": "89E8Q",
3253
+ "data-opt-slug": "form.FormGroup"
3254
+ }));
3255
+ }
3256
+ /** Renders the form group label component. */
3257
+ function FormGroupLabel$1(_ref13) {
3258
+ let { className } = _ref13, props = _objectWithoutProperties(_ref13, _excluded11);
3259
+ return /* @__PURE__ */ jsx(FormGroupLabel, _objectSpread2(_objectSpread2({ className: cn(labelClass, "font-semibold", className) }, props), {}, {
3260
+ "data-opt-id": "W95BH",
3261
+ "data-opt-slug": "form.FormGroupLabel"
3262
+ }));
3263
+ }
3264
+ /** Renders the form description component. */
3265
+ function FormDescription$1(_ref14) {
3266
+ let { className } = _ref14, props = _objectWithoutProperties(_ref14, _excluded12);
3267
+ return /* @__PURE__ */ jsx(FormDescription, _objectSpread2(_objectSpread2({ className: cn(descriptionClass, className) }, props), {}, {
3268
+ "data-opt-id": "RFB40",
3269
+ "data-opt-slug": "form.FormDescription"
3270
+ }));
3271
+ }
3272
+ /** Renders the form field component. */
3273
+ function FormField$1(_ref15) {
3274
+ let { className } = _ref15, props = _objectWithoutProperties(_ref15, _excluded13);
3275
+ return /* @__PURE__ */ jsx(FormField, _objectSpread2(_objectSpread2({ className: cn("gap-element flex flex-col", className) }, props), {}, {
3276
+ "data-opt-id": "C68GP",
3277
+ "data-opt-slug": "form.FormField"
3278
+ }));
3279
+ }
3280
+ /** Renders the form control component. */
3281
+ function FormControl$1(_ref16) {
3282
+ let { className } = _ref16, props = _objectWithoutProperties(_ref16, _excluded14);
3283
+ return /* @__PURE__ */ jsx(FormControl, _objectSpread2(_objectSpread2({ className: cn(inputClass, className) }, props), {}, {
3284
+ "data-opt-id": "XNF0F",
3285
+ "data-opt-slug": "form.FormControl"
3286
+ }));
3287
+ }
3288
+ /** Renders the form push component. */
3289
+ function FormPush$1(_ref17) {
3290
+ let { className } = _ref17, props = _objectWithoutProperties(_ref17, _excluded15);
3291
+ return /* @__PURE__ */ jsx(FormPush, _objectSpread2(_objectSpread2({ className: cn(OPT_BUTTON_SECONDARY, className) }, props), {}, {
3292
+ "data-opt-id": "5SV8S",
3293
+ "data-opt-slug": "form.FormPush"
3294
+ }));
3295
+ }
3296
+ /** Renders the form remove component. */
3297
+ function FormRemove$1(_ref18) {
3298
+ let { className } = _ref18, props = _objectWithoutProperties(_ref18, _excluded16);
3299
+ return /* @__PURE__ */ jsx(FormRemove, _objectSpread2(_objectSpread2({ className: cn("text-danger-fg hover:text-danger focus-visible:ring-ring focus-visible:ring-offset-ring-offset inline-flex items-center text-sm outline-none focus-visible:ring-2 focus-visible:ring-offset-1", OPT_FOCUS_VISIBLE, className) }, props), {}, {
3300
+ "data-opt-id": "FEW6V",
3301
+ "data-opt-slug": "form.FormRemove"
3302
+ }));
3303
+ }
3304
+ /** Renders the form reset component. */
3305
+ function FormReset$1(_ref19) {
3306
+ let { className } = _ref19, props = _objectWithoutProperties(_ref19, _excluded17);
3307
+ return /* @__PURE__ */ jsx(FormReset, _objectSpread2(_objectSpread2({ className: cn(OPT_BUTTON_SECONDARY, className) }, props), {}, {
3308
+ "data-opt-id": "M3FVB",
3309
+ "data-opt-slug": "form.FormReset"
3310
+ }));
3311
+ }
3312
+ /** Renders the form checkbox component. */
3313
+ function FormCheckbox$1(_ref20) {
3314
+ let { className } = _ref20, props = _objectWithoutProperties(_ref20, _excluded18);
3315
+ return /* @__PURE__ */ jsx(FormCheckbox, _objectSpread2(_objectSpread2({ className: cn(checkboxClass, className) }, props), {}, {
3316
+ "data-opt-id": "3BZS1",
3317
+ "data-opt-slug": "form.FormCheckbox"
3318
+ }));
3319
+ }
3320
+ /** Renders the form radio group component. */
3321
+ function FormRadioGroup$1(_ref21) {
3322
+ let { className } = _ref21, props = _objectWithoutProperties(_ref21, _excluded19);
3323
+ return /* @__PURE__ */ jsx(FormRadioGroup, _objectSpread2(_objectSpread2({ className: cn("gap-group flex flex-col", className) }, props), {}, {
3324
+ "data-opt-id": "J8XRP",
3325
+ "data-opt-slug": "form.FormRadioGroup"
3326
+ }));
3327
+ }
3328
+ /** Renders the form radio component. */
3329
+ function FormRadio$1(_ref22) {
3330
+ let { className } = _ref22, props = _objectWithoutProperties(_ref22, _excluded20);
3331
+ return /* @__PURE__ */ jsx(FormRadio, _objectSpread2(_objectSpread2({ className: cn(radioClass, className) }, props), {}, {
3332
+ "data-opt-id": "YTN4Q",
3333
+ "data-opt-slug": "form.FormRadio"
3334
+ }));
3335
+ }
3336
+ /** Renders the form number input component. */
3337
+ function FormNumberInput(_ref23) {
3338
+ var _ref24;
3339
+ let { name } = _ref23, props = _objectWithoutProperties(_ref23, _excluded21);
3340
+ const form = useRequiredFormContext("FormNumberInput");
3341
+ const value = (_ref24 = useFieldValue(form, name)) !== null && _ref24 !== void 0 ? _ref24 : 0;
3342
+ const error = form === null || form === void 0 ? void 0 : form.getError(name);
3343
+ const touched = form === null || form === void 0 ? void 0 : form.getFieldTouched(name);
3344
+ return /* @__PURE__ */ jsx(NumberInput, _objectSpread2(_objectSpread2({
3345
+ value,
3346
+ onChange: (v) => form.setValue(name, v),
3347
+ error: error && touched ? error : void 0
3348
+ }, props), {}, {
3349
+ "data-opt-id": "FJ2A2",
3350
+ "data-opt-slug": "form.FormNumberInput"
3351
+ }));
3352
+ }
3353
+ /** Renders the form slider component. */
3354
+ function FormSlider(_ref25) {
3355
+ var _ref26;
3356
+ let { name } = _ref25, props = _objectWithoutProperties(_ref25, _excluded22);
3357
+ const form = useRequiredFormContext("FormSlider");
3358
+ return /* @__PURE__ */ jsx(Slider, _objectSpread2(_objectSpread2({
3359
+ value: (_ref26 = useFieldValue(form, name)) !== null && _ref26 !== void 0 ? _ref26 : 0,
3360
+ onChange: (v) => form.setValue(name, v)
3361
+ }, props), {}, {
3362
+ "data-opt-id": "3XQ3A",
3363
+ "data-opt-slug": "form.FormSlider"
3364
+ }));
3365
+ }
3366
+ /** Renders the form star rating component. */
3367
+ function FormStarRating(_ref27) {
3368
+ var _ref28;
3369
+ let { name } = _ref27, props = _objectWithoutProperties(_ref27, _excluded23);
3370
+ const form = useRequiredFormContext("FormStarRating");
3371
+ return /* @__PURE__ */ jsx(StarRating, _objectSpread2(_objectSpread2({
3372
+ value: (_ref28 = useFieldValue(form, name)) !== null && _ref28 !== void 0 ? _ref28 : 0,
3373
+ onChange: (v) => form.setValue(name, v)
3374
+ }, props), {}, {
3375
+ "data-opt-id": "EKNJJ",
3376
+ "data-opt-slug": "form.FormStarRating"
3377
+ }));
3378
+ }
3379
+ /** Renders the form color picker component. */
3380
+ function FormColorPicker(_ref29) {
3381
+ var _ref30;
3382
+ let { name } = _ref29, props = _objectWithoutProperties(_ref29, _excluded24);
3383
+ const form = useRequiredFormContext("FormColorPicker");
3384
+ const value = (_ref30 = useFieldValue(form, name)) !== null && _ref30 !== void 0 ? _ref30 : "#000000";
3385
+ const error = form === null || form === void 0 ? void 0 : form.getError(name);
3386
+ const touched = form === null || form === void 0 ? void 0 : form.getFieldTouched(name);
3387
+ return /* @__PURE__ */ jsx(ColorPicker, _objectSpread2(_objectSpread2({
3388
+ value,
3389
+ onChange: (v) => form.setValue(name, v),
3390
+ error: error && touched ? error : void 0
3391
+ }, props), {}, {
3392
+ "data-opt-id": "4ATTC",
3393
+ "data-opt-slug": "form.FormColorPicker"
3394
+ }));
3395
+ }
3396
+ /** Renders the form icon picker component. */
3397
+ function FormIconPicker(_ref31) {
3398
+ var _ref32;
3399
+ let { name } = _ref31, props = _objectWithoutProperties(_ref31, _excluded25);
3400
+ const form = useRequiredFormContext("FormIconPicker");
3401
+ const value = (_ref32 = useFieldValue(form, name)) !== null && _ref32 !== void 0 ? _ref32 : "";
3402
+ const error = form === null || form === void 0 ? void 0 : form.getError(name);
3403
+ const touched = form === null || form === void 0 ? void 0 : form.getFieldTouched(name);
3404
+ return /* @__PURE__ */ jsx(IconPicker, _objectSpread2(_objectSpread2({
3405
+ value,
3406
+ onChange: (v) => form.setValue(name, v),
3407
+ error: error && touched ? error : void 0
3408
+ }, props), {}, {
3409
+ "data-opt-id": "7Q41M",
3410
+ "data-opt-slug": "form.FormIconPicker"
3411
+ }));
3412
+ }
3413
+ /** Renders the form tag input component. */
3414
+ function FormTagInput(_ref33) {
3415
+ var _ref34;
3416
+ let { name } = _ref33, props = _objectWithoutProperties(_ref33, _excluded26);
3417
+ const form = useRequiredFormContext("FormTagInput");
3418
+ const value = (_ref34 = useFieldValue(form, name)) !== null && _ref34 !== void 0 ? _ref34 : [];
3419
+ const error = form === null || form === void 0 ? void 0 : form.getError(name);
3420
+ const touched = form === null || form === void 0 ? void 0 : form.getFieldTouched(name);
3421
+ return /* @__PURE__ */ jsx(TagInput, _objectSpread2(_objectSpread2({
3422
+ value,
3423
+ onChange: (v) => form.setValue(name, v),
3424
+ error: error && touched ? error : void 0
3425
+ }, props), {}, {
3426
+ "data-opt-id": "W05M1",
3427
+ "data-opt-slug": "form.FormTagInput"
3428
+ }));
3429
+ }
3430
+ /** Renders the form date range picker component. */
3431
+ function FormDateRangePicker(_ref35) {
3432
+ var _ref36;
3433
+ let { name } = _ref35, props = _objectWithoutProperties(_ref35, _excluded27);
3434
+ const form = useRequiredFormContext("FormDateRangePicker");
3435
+ const value = (_ref36 = useFieldValue(form, name)) !== null && _ref36 !== void 0 ? _ref36 : {
3436
+ start: null,
3437
+ end: null
3438
+ };
3439
+ const error = form === null || form === void 0 ? void 0 : form.getError(name);
3440
+ const touched = form === null || form === void 0 ? void 0 : form.getFieldTouched(name);
3441
+ return /* @__PURE__ */ jsx(DateRangePicker, _objectSpread2(_objectSpread2({
3442
+ value,
3443
+ onChange: (v) => form.setValue(name, v),
3444
+ error: error && touched ? error : void 0
3445
+ }, props), {}, {
3446
+ "data-opt-id": "4NE9A",
3447
+ "data-opt-slug": "form.FormDateRangePicker"
3448
+ }));
3449
+ }
3450
+ //#endregion
3451
+ //#region src/core/checkbox.tsx
3452
+ const _excluded$1 = [
3453
+ "label",
3454
+ "required",
3455
+ "error",
3456
+ "hint",
3457
+ "description",
3458
+ "checked",
3459
+ "defaultChecked",
3460
+ "onChange",
3461
+ "size",
3462
+ "disabled",
3463
+ "className",
3464
+ "id",
3465
+ "value",
3466
+ "indeterminate"
3467
+ ];
3468
+ const CheckboxGroupContext = createContext(null);
3469
+ function setForwardedRef(ref, value) {
3470
+ if (typeof ref === "function") ref(value);
3471
+ else if (ref) ref.current = value;
3472
+ }
3473
+ const sizeStyles = {
3474
+ sm: {
3475
+ box: "h-4 w-4",
3476
+ icon: "h-3 w-3",
3477
+ text: "text-sm"
3478
+ },
3479
+ md: {
3480
+ box: "h-5 w-5",
3481
+ icon: "h-3.5 w-3.5",
3482
+ text: "text-sm"
3483
+ },
3484
+ lg: {
3485
+ box: "h-6 w-6",
3486
+ icon: "h-4 w-4",
3487
+ text: "text-base"
3488
+ }
3489
+ };
3490
+ function CheckIcon({ className }) {
3491
+ return /* @__PURE__ */ jsx("svg", {
3492
+ "aria-hidden": "true",
3493
+ className,
3494
+ viewBox: "0 0 16 16",
3495
+ fill: "none",
3496
+ stroke: "currentColor",
3497
+ strokeWidth: 2.5,
3498
+ strokeLinecap: "round",
3499
+ strokeLinejoin: "round",
3500
+ children: /* @__PURE__ */ jsx("path", { d: "M3.5 8.5L6.5 11.5L12.5 4.5" })
3501
+ });
3502
+ }
3503
+ function IndeterminateIcon({ className }) {
3504
+ return /* @__PURE__ */ jsx("svg", {
3505
+ "aria-hidden": "true",
3506
+ className,
3507
+ viewBox: "0 0 16 16",
3508
+ fill: "none",
3509
+ stroke: "currentColor",
3510
+ strokeWidth: 2.5,
3511
+ strokeLinecap: "round",
3512
+ children: /* @__PURE__ */ jsx("path", { d: "M4 8H12" })
3513
+ });
3514
+ }
3515
+ const Checkbox = forwardRef((_ref, ref) => {
3516
+ var _groupContext$size, _groupContext$disable, _useInputId;
3517
+ let { label, required, error, hint, description, checked: checkedProp, defaultChecked, onChange, size: sizeProp = "md", disabled: disabledProp, className, id, value, indeterminate } = _ref, props = _objectWithoutProperties(_ref, _excluded$1);
3518
+ const groupContext = useContext(CheckboxGroupContext);
3519
+ const size = (_groupContext$size = groupContext === null || groupContext === void 0 ? void 0 : groupContext.size) !== null && _groupContext$size !== void 0 ? _groupContext$size : sizeProp;
3520
+ const disabled = (_groupContext$disable = groupContext === null || groupContext === void 0 ? void 0 : groupContext.disabled) !== null && _groupContext$disable !== void 0 ? _groupContext$disable : disabledProp;
3521
+ const isInGroup = groupContext !== null && value !== void 0;
3522
+ const [internalChecked, setInternalChecked] = useState(defaultChecked !== null && defaultChecked !== void 0 ? defaultChecked : false);
3523
+ const checked = isInGroup ? groupContext.value.includes(value) : checkedProp !== null && checkedProp !== void 0 ? checkedProp : internalChecked;
3524
+ const handleChange = (event) => {
3525
+ const newChecked = event.target.checked;
3526
+ if (isInGroup && value) {
3527
+ const newValue = newChecked ? [...groupContext.value, value] : groupContext.value.filter((v) => v !== value);
3528
+ groupContext.onChange(newValue);
3529
+ } else if (checkedProp !== void 0) onChange === null || onChange === void 0 || onChange(newChecked);
3530
+ else {
3531
+ setInternalChecked(newChecked);
3532
+ onChange === null || onChange === void 0 || onChange(newChecked);
3533
+ }
3534
+ };
3535
+ const fallbackId = useId().replace(/:/g, "");
3536
+ const checkboxId = (_useInputId = useInputId(id, label, "checkbox")) !== null && _useInputId !== void 0 ? _useInputId : `checkbox-${fallbackId}`;
3537
+ const hintText = hint !== null && hint !== void 0 ? hint : description;
3538
+ const hasError = Boolean(error);
3539
+ const styles = sizeStyles[size];
3540
+ const isIndeterminate = Boolean(indeterminate);
3541
+ const inputRef = useCallback((node) => {
3542
+ if (node) node.indeterminate = isIndeterminate;
3543
+ setForwardedRef(ref, node);
3544
+ }, [isIndeterminate, ref]);
3545
+ return /* @__PURE__ */ jsxs("div", {
3546
+ className: cn("flex flex-col gap-1.5", className),
3547
+ "data-opt-id": "3P3MA",
3548
+ "data-opt-slug": "checkbox.Checkbox",
3549
+ children: [/* @__PURE__ */ jsxs("div", {
3550
+ className: "flex items-start gap-3",
3551
+ children: [/* @__PURE__ */ jsxs("label", {
3552
+ className: cn("relative inline-flex shrink-0 cursor-pointer items-center justify-center", disabled && "cursor-not-allowed"),
3553
+ children: [/* @__PURE__ */ jsx("input", _objectSpread2({
3554
+ ref: inputRef,
3555
+ type: "checkbox",
3556
+ id: checkboxId,
3557
+ checked,
3558
+ onChange: handleChange,
3559
+ disabled,
3560
+ "aria-invalid": hasError,
3561
+ "aria-required": required,
3562
+ "aria-describedby": getDescribedBy(checkboxId, error, hintText),
3563
+ className: "peer sr-only"
3564
+ }, props)), /* @__PURE__ */ jsx("span", {
3565
+ className: cn("inline-flex items-center justify-center rounded", styles.box, "border-border border-2", "bg-surface", "peer-checked:border-accent peer-checked:bg-accent", isIndeterminate && "border-accent bg-accent", "peer-disabled:cursor-not-allowed peer-disabled:opacity-50", "peer-focus-visible:ring-ring peer-focus-visible:ring-2 peer-focus-visible:ring-offset-1", "transition-colors"),
3566
+ children: isIndeterminate ? /* @__PURE__ */ jsx(IndeterminateIcon, { className: cn(styles.icon, "text-accent-fg opacity-0 transition-opacity", "opacity-100") }) : /* @__PURE__ */ jsx(CheckIcon, { className: cn(styles.icon, "text-accent-fg opacity-0 transition-opacity", checked && "opacity-100") })
3567
+ })]
3568
+ }), (label || hintText) && /* @__PURE__ */ jsxs("div", {
3569
+ className: "flex flex-col",
3570
+ children: [label && /* @__PURE__ */ jsxs("label", {
3571
+ htmlFor: checkboxId,
3572
+ className: cn("text-text-primary cursor-pointer font-medium", styles.text, disabled && "cursor-not-allowed opacity-50"),
3573
+ children: [label, required && /* @__PURE__ */ jsx(RequiredMark, {})]
3574
+ }), hintText && /* @__PURE__ */ jsx("p", {
3575
+ id: `${checkboxId}-hint`,
3576
+ className: cn("text-text-tertiary text-sm", disabled && "opacity-50"),
3577
+ children: hintText
3578
+ })]
3579
+ })]
3580
+ }), /* @__PURE__ */ jsx(FieldMessages, {
3581
+ id: checkboxId,
3582
+ error
3583
+ })]
3584
+ });
3585
+ });
3586
+ Checkbox.displayName = "Checkbox";
3587
+ const EMPTY_STRING_ARRAY = [];
3588
+ /** Renders the checkbox group component. */
3589
+ function CheckboxGroup({ children, value: valueProp, defaultValue = EMPTY_STRING_ARRAY, onChange, disabled, size = "md", error, required, className, orientation = "vertical", label }) {
3590
+ const [value, setValue] = useControlledState(defaultValue, valueProp, onChange);
3591
+ const hasError = Boolean(error);
3592
+ const groupId = label ? `checkbox-group-${label.replace(/\s+/g, "-").toLowerCase()}` : void 0;
3593
+ const ctxValue = useMemo(() => ({
3594
+ value,
3595
+ onChange: setValue,
3596
+ disabled,
3597
+ size
3598
+ }), [
3599
+ value,
3600
+ setValue,
3601
+ disabled,
3602
+ size
3603
+ ]);
3604
+ return /* @__PURE__ */ jsx(CheckboxGroupContext.Provider, {
3605
+ value: ctxValue,
3606
+ children: /* @__PURE__ */ jsxs("div", {
3607
+ className: cn("flex flex-col gap-1.5", className),
3608
+ "data-opt-id": "V6NSW",
3609
+ "data-opt-slug": "checkbox.CheckboxGroup",
3610
+ children: [/* @__PURE__ */ jsxs("div", {
3611
+ role: "group",
3612
+ "aria-label": label,
3613
+ "aria-required": required,
3614
+ "aria-invalid": hasError,
3615
+ "aria-describedby": hasError && groupId ? `${groupId}-error` : void 0,
3616
+ className: cn("flex", orientation === "vertical" ? "flex-col gap-3" : "flex-row gap-6"),
3617
+ children: [label && /* @__PURE__ */ jsxs("div", {
3618
+ className: "text-text-secondary mb-1 text-sm font-medium",
3619
+ children: [label, required && /* @__PURE__ */ jsx(RequiredMark, {})]
3620
+ }), children]
3621
+ }), /* @__PURE__ */ jsx(FieldMessages, {
3622
+ id: groupId,
3623
+ error
3624
+ })]
3625
+ })
3626
+ });
3627
+ }
3628
+ //#endregion
3629
+ //#region src/core/pagination.tsx
3630
+ const _excluded = [
3631
+ "totalItems",
3632
+ "totalPages",
3633
+ "hasMore",
3634
+ "pageSize",
3635
+ "currentPage",
3636
+ "onPageChange",
3637
+ "showPageNumbers",
3638
+ "siblingCount",
3639
+ "variant",
3640
+ "isDisabled",
3641
+ "label",
3642
+ "labels",
3643
+ "className"
3644
+ ];
3645
+ const DEFAULT_LABELS = {
3646
+ previous: "Previous page",
3647
+ next: "Next page",
3648
+ page: (page) => `Go to page ${page}`,
3649
+ currentPage: (page) => `Page ${page}, current page`,
3650
+ compact: (page, totalPages) => totalPages === void 0 ? `Page ${page}` : `Page ${page} of ${totalPages}`,
3651
+ count: (start, end, totalItems) => `${start}-${end} of ${totalItems}`
3652
+ };
3653
+ function buildPageRange(current, total, siblings) {
3654
+ if (total <= 1) return [1];
3655
+ const range = [];
3656
+ const left = Math.max(2, current - siblings);
3657
+ const right = Math.min(total - 1, current + siblings);
3658
+ range.push(1);
3659
+ if (left > 2) range.push("ellipsis");
3660
+ for (let i = left; i <= right; i++) range.push(i);
3661
+ if (right < total - 1) range.push("ellipsis");
3662
+ if (total > 1) range.push(total);
3663
+ return range;
3664
+ }
3665
+ function positiveInteger(value) {
3666
+ if (!Number.isFinite(value) || value === void 0 || value <= 0) return;
3667
+ return Math.max(1, Math.floor(value));
3668
+ }
3669
+ function resolveTotalPages({ totalItems, totalPages, pageSize, currentPage, hasMore }) {
3670
+ const explicitTotalPages = positiveInteger(totalPages);
3671
+ if (explicitTotalPages !== void 0) return explicitTotalPages;
3672
+ const safePageSize = positiveInteger(pageSize);
3673
+ if (safePageSize !== void 0 && Number.isFinite(totalItems) && totalItems !== void 0) return Math.max(1, Math.ceil(Math.max(0, totalItems) / safePageSize));
3674
+ if (hasMore) return Math.max(1, Math.floor(currentPage) + 1);
3675
+ return Math.max(1, Math.floor(currentPage));
3676
+ }
3677
+ function clampPage(page, totalPages) {
3678
+ if (!Number.isFinite(page)) return 1;
3679
+ return Math.min(Math.max(1, Math.floor(page)), totalPages);
3680
+ }
3681
+ const btnBase = `inline-flex h-8 min-w-8 items-center justify-center rounded-md px-2 text-sm transition-colors ${OPT_FOCUS_VISIBLE}`;
3682
+ const btnEnabled = "text-text-primary hover:bg-bg-subtle active:bg-bg-muted cursor-pointer";
3683
+ const btnDisabled = "text-text-tertiary cursor-not-allowed opacity-50";
3684
+ const btnActive = "bg-accent text-accent-fg hover:bg-accent-hover cursor-default";
3685
+ /** Renders the pagination component. */
3686
+ function Pagination(_ref) {
3687
+ let { totalItems, totalPages: totalPagesProp, hasMore, pageSize, currentPage, onPageChange, showPageNumbers = true, siblingCount = 1, variant, isDisabled = false, label = "Pagination", labels, className } = _ref, props = _objectWithoutProperties(_ref, _excluded);
3688
+ const resolvedLabels = _objectSpread2(_objectSpread2({}, DEFAULT_LABELS), labels);
3689
+ const totalPages = resolveTotalPages({
3690
+ totalItems,
3691
+ totalPages: totalPagesProp,
3692
+ pageSize,
3693
+ currentPage,
3694
+ hasMore
3695
+ });
3696
+ const safeCurrentPage = clampPage(currentPage, totalPages);
3697
+ const resolvedVariant = variant !== null && variant !== void 0 ? variant : showPageNumbers ? "pages" : "none";
3698
+ const itemRange = Number.isFinite(totalItems) && totalItems !== void 0 && positiveInteger(pageSize) !== void 0 ? {
3699
+ start: totalItems === 0 ? 0 : (safeCurrentPage - 1) * pageSize + 1,
3700
+ end: Math.min(safeCurrentPage * pageSize, totalItems)
3701
+ } : null;
3702
+ const pages = useMemo(() => buildPageRange(safeCurrentPage, totalPages, siblingCount), [
3703
+ safeCurrentPage,
3704
+ totalPages,
3705
+ siblingCount
3706
+ ]);
3707
+ const hasPrev = safeCurrentPage > 1;
3708
+ const hasNext = hasMore === true || safeCurrentPage < totalPages;
3709
+ const prevDisabled = isDisabled || !hasPrev;
3710
+ const nextDisabled = isDisabled || !hasNext;
3711
+ const handlePageChange = (page) => {
3712
+ if (isDisabled) return;
3713
+ const next = hasMore ? Math.max(1, Math.floor(page)) : clampPage(page, totalPages);
3714
+ if (next !== safeCurrentPage) onPageChange(next);
3715
+ };
3716
+ return /* @__PURE__ */ jsxs("nav", _objectSpread2(_objectSpread2({
3717
+ "aria-label": label,
3718
+ className: cn("gap-element flex items-center", className)
3719
+ }, props), {}, {
3720
+ "data-opt-id": "QBEE2",
3721
+ "data-opt-slug": "pagination.Pagination",
3722
+ children: [
3723
+ /* @__PURE__ */ jsx("button", {
3724
+ type: "button",
3725
+ className: cn(btnBase, prevDisabled ? btnDisabled : btnEnabled),
3726
+ disabled: prevDisabled,
3727
+ onClick: () => handlePageChange(safeCurrentPage - 1),
3728
+ "aria-label": resolvedLabels.previous,
3729
+ children: /* @__PURE__ */ jsx("svg", {
3730
+ width: "16",
3731
+ height: "16",
3732
+ viewBox: "0 0 16 16",
3733
+ fill: "none",
3734
+ stroke: "currentColor",
3735
+ strokeWidth: "2",
3736
+ strokeLinecap: "round",
3737
+ strokeLinejoin: "round",
3738
+ children: /* @__PURE__ */ jsx("path", { d: "M10 12 6 8l4-4" })
3739
+ })
3740
+ }),
3741
+ resolvedVariant === "pages" && pages.map((p, i) => p === "ellipsis" ? /* @__PURE__ */ jsx("span", {
3742
+ className: "text-text-tertiary px-1",
3743
+ "aria-hidden": "true",
3744
+ children: "…"
3745
+ }, `e${i}`) : /* @__PURE__ */ jsx("button", {
3746
+ type: "button",
3747
+ className: cn(btnBase, p === safeCurrentPage ? btnActive : btnEnabled),
3748
+ "aria-current": p === safeCurrentPage ? "page" : void 0,
3749
+ "aria-label": p === safeCurrentPage ? resolvedLabels.currentPage(p) : resolvedLabels.page(p),
3750
+ disabled: isDisabled,
3751
+ onClick: () => handlePageChange(p),
3752
+ children: p
3753
+ }, p)),
3754
+ resolvedVariant === "count" && itemRange && totalItems !== void 0 && /* @__PURE__ */ jsx("span", {
3755
+ className: "text-text-secondary px-2 text-sm",
3756
+ "aria-live": "polite",
3757
+ children: resolvedLabels.count(itemRange.start, itemRange.end, totalItems)
3758
+ }),
3759
+ resolvedVariant === "compact" && /* @__PURE__ */ jsx("span", {
3760
+ className: "text-text-secondary px-2 text-sm",
3761
+ "aria-live": "polite",
3762
+ children: resolvedLabels.compact(safeCurrentPage, hasMore && totalPages === safeCurrentPage + 1 ? void 0 : totalPages)
3763
+ }),
3764
+ /* @__PURE__ */ jsx("button", {
3765
+ type: "button",
3766
+ className: cn(btnBase, nextDisabled ? btnDisabled : btnEnabled),
3767
+ disabled: nextDisabled,
3768
+ onClick: () => handlePageChange(safeCurrentPage + 1),
3769
+ "aria-label": resolvedLabels.next,
3770
+ children: /* @__PURE__ */ jsx("svg", {
3771
+ width: "16",
3772
+ height: "16",
3773
+ viewBox: "0 0 16 16",
3774
+ fill: "none",
3775
+ stroke: "currentColor",
3776
+ strokeWidth: "2",
3777
+ strokeLinecap: "round",
3778
+ strokeLinejoin: "round",
3779
+ children: /* @__PURE__ */ jsx("path", { d: "M6 4l4 4-4 4" })
3780
+ })
3781
+ })
3782
+ ]
3783
+ }));
3784
+ }
3785
+ //#endregion
3786
+ export { TooltipAnchor$1 as $, koComboboxLabels as $t, FormSwitch$1 as A, OPT_SURFACE_POPOVER as An, SelectPopover$1 as At, getIconRegistryEntry as B, _objectSpread2 as Bn, Composite as Bt, FormRoot$1 as C, OPT_FOCUS_VISIBLE as Cn, DialogFooter as Ct, FormSlider as D, OPT_INPUT_SIZE as Dn, DialogRoot$1 as Dt, FormSelectPopover as E, OPT_INPUT_ERROR as En, DialogPanel$1 as Et, useFormStore as F, OPT_TEXT_LABEL as Fn, TabPanel$1 as Ft, PopoverTrigger$1 as G, StarRating as Gt, PopoverClose$1 as H, Kbd as Hn, CompositeProvider as Ht, DEFAULT_PRESETS as I, OPT_TEXT_PRIMARY as In, TabsRoot$1 as It, ToolbarButton$1 as J, Spinner as Jt, Slider as K, useInputId as Kt, DateRangePicker as L, OPT_TEXT_SECONDARY as Ln, DisclosureContent$1 as Lt, FormTextarea as M, OPT_TD as Mn, SelectTrigger$1 as Mt, useFieldValue as N, OPT_TD_MUTED as Nn, Tab$1 as Nt, FormStarRating as O, OPT_ITEM_BASE as On, SelectItem$1 as Ot, useFormContext as P, OPT_TEXTAREA_SIZE as Pn, TabList$1 as Pt, Tooltip$1 as Q, koBreadcrumbLabels as Qt, TagInput as R, OPT_TEXT_TERTIARY as Rn, DisclosureRoot$1 as Rt, FormReset$1 as S, OPT_FOCUS as Sn, DialogDismiss$1 as St, FormSelectItem as T, OPT_INPUT as Tn, DialogHeading$1 as Tt, PopoverContent$1 as U, cn as Un, CompositeRow as Ut, ColorPicker as V, _objectWithoutProperties as Vn, CompositeItem as Vt, PopoverRoot$1 as W, CompositeZone as Wt, ToolbarRoot$1 as X, EmptyState as Xt, ToolbarContainer$1 as Y, Badge as Yt, ToolbarSeparator$1 as Z, Button as Zt, FormProvider$1 as _, OPT_DIVIDER as _n, ComboboxRoot$1 as _t, FormColorPicker as a, getDescribedBy as an, MenuPopover$1 as at, FormRadioGroup$1 as b, OPT_DOT_RED as bn, DialogDescription$1 as bt, FormDescription$1 as c, OPT_ANIMATE_ENTER_EXIT as cn, MenuTrigger$1 as ct, FormGroup$1 as d, OPT_BADGE_NEUTRAL as dn, ComboboxEmpty as dt, koStarRatingLabels as en, TooltipProvider$1 as et, FormGroupLabel$1 as f, OPT_BADGE_RED as fn, ComboboxGroup$1 as ft, FormNumberInput as g, OPT_DISCLOSURE_TRIGGER as gn, ComboboxPopover$1 as gt, FormLabel$1 as h, OPT_DISCLOSURE_CONTENT as hn, ComboboxItem$1 as ht, FormCheckbox$1 as i, RequiredMark as in, MenuItemRadio$1 as it, FormTagInput as j, OPT_TABLE_ROW_ACTIVE as jn, SelectRoot$1 as jt, FormSubmit$1 as k, OPT_SURFACE as kn, SelectLabel$1 as kt, FormError$1 as l, OPT_BADGE_BLUE as ln, MenubarContainer$1 as lt, FormInput$1 as m, OPT_BORDER as mn, ComboboxInput$1 as mt, Checkbox as n, useControlledState as nn, MenuItem$1 as nt, FormControl$1 as o, OPT_ACTIVE_ITEM as on, MenuRoot$1 as ot, FormIconPicker as p, OPT_BADGE_YELLOW as pn, ComboboxGroupLabel$1 as pt, NumberInput as q, Alert as qt, CheckboxGroup as r, FieldMessages as rn, MenuItemCheckbox$1 as rt, FormDateRangePicker as s, OPT_ANIMATE_DRAWER as sn, MenuSeparator$1 as st, Pagination as t, StatCard as tn, MenuButtonArrow$1 as tt, FormField$1 as u, OPT_BADGE_GREEN as un, MenubarRoot$1 as ut, FormPush$1 as v, OPT_DOT_GRAY as vn, AlertDialogPanel$1 as vt, FormSelect as w, OPT_HOVER_ITEM as wn, DialogHeader as wt, FormRemove$1 as x, OPT_DOT_YELLOW as xn, DialogDisclosure$1 as xt, FormRadio$1 as y, OPT_DOT_GREEN as yn, DialogBody as yt, IconPicker as z, OPT_TH as zn, DisclosureTrigger$1 as zt };
3787
+
3788
+ //# sourceMappingURL=pagination-By7Ozv3U.js.map