@dimasbaguspm/versaur 0.0.17 → 0.0.19

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 (62) hide show
  1. package/dist/{js → assets}/styles.css +37 -0
  2. package/dist/js/{bottom-sheet-CHRSxXRE.js → bottom-sheet-BRv-oJL-.js} +285 -140
  3. package/dist/js/feedbacks/index.js +1 -1
  4. package/dist/js/{form-layout-Dhlv-FZL.js → form-layout-4ASWdXn8.js} +1 -1
  5. package/dist/js/forms/index.js +15 -16
  6. package/dist/js/{tile-B9bt2AY6.js → image-rectangle-CLU-GVtw.js} +855 -658
  7. package/dist/js/{index-C1uJQB34.js → index-DOdDlCoL.js} +2 -2
  8. package/dist/js/index.js +54 -47
  9. package/dist/js/layouts/index.js +1 -1
  10. package/dist/js/navigation/index.js +1 -1
  11. package/dist/js/overlays/index.js +4 -5
  12. package/dist/js/primitive/index.js +22 -16
  13. package/dist/js/providers/index.js +5 -0
  14. package/dist/js/selectable-multiple-input-CJXfqy1Z.js +1901 -0
  15. package/dist/js/{skeleton-QEyPZAuF.js → skeleton-BNZyaRjo.js} +1 -1
  16. package/dist/js/snackbar-DH8jCh2V.js +50 -0
  17. package/dist/js/{tabs-DYcTvVao.js → tabs-BbOkYchB.js} +1 -1
  18. package/dist/js/use-snackbars-oPoF7J5t.js +94 -0
  19. package/dist/types/feedbacks/loading-indicator/index.d.ts +2 -1
  20. package/dist/types/forms/chip-single-input/index.d.ts +2 -1
  21. package/dist/types/forms/index.d.ts +2 -1
  22. package/dist/types/forms/price-input/index.d.ts +1 -1
  23. package/dist/types/forms/selectable-multiple-input/index.d.ts +2 -0
  24. package/dist/types/forms/selectable-multiple-input/selectable-multiple-input.d.ts +6 -0
  25. package/dist/types/forms/selectable-multiple-input/types.d.ts +18 -0
  26. package/dist/types/forms/selectable-single-input/index.d.ts +2 -0
  27. package/dist/types/forms/selectable-single-input/selectable-single-input.d.ts +6 -0
  28. package/dist/types/forms/selectable-single-input/types.d.ts +18 -0
  29. package/dist/types/forms/switch-input/index.d.ts +2 -3
  30. package/dist/types/forms/time-picker-input/time-picker-input.d.ts +4 -4
  31. package/dist/types/forms/time-picker-input/types.d.ts +2 -38
  32. package/dist/types/index.d.ts +1 -0
  33. package/dist/types/layouts/page-layout/index.d.ts +2 -1
  34. package/dist/types/overlays/menu/index.d.ts +2 -2
  35. package/dist/types/primitive/description-list/description-list.atoms.d.ts +13 -0
  36. package/dist/types/primitive/description-list/description-list.d.ts +6 -0
  37. package/dist/types/primitive/description-list/index.d.ts +2 -0
  38. package/dist/types/primitive/description-list/types.d.ts +46 -0
  39. package/dist/types/primitive/image/base-image.atoms.d.ts +6 -0
  40. package/dist/types/primitive/image/base-image.d.ts +6 -0
  41. package/dist/types/primitive/image/image-circle.d.ts +6 -0
  42. package/dist/types/primitive/image/image-rectangle.d.ts +6 -0
  43. package/dist/types/primitive/image/image-square.d.ts +6 -0
  44. package/dist/types/primitive/image/index.d.ts +5 -0
  45. package/dist/types/primitive/image/types.d.ts +48 -0
  46. package/dist/types/primitive/image/use-image.d.ts +13 -0
  47. package/dist/types/primitive/index.d.ts +2 -0
  48. package/dist/types/providers/index.d.ts +1 -0
  49. package/dist/types/providers/snackbars-provider/index.d.ts +3 -0
  50. package/dist/types/providers/snackbars-provider/provider.d.ts +7 -0
  51. package/dist/types/providers/snackbars-provider/types.d.ts +28 -0
  52. package/dist/types/providers/snackbars-provider/use-snackbars-queue.d.ts +9 -0
  53. package/dist/types/providers/snackbars-provider/use-snackbars.d.ts +4 -0
  54. package/dist/{js → utils}/enforce-subpath-import.js +67 -54
  55. package/package.json +8 -4
  56. package/dist/js/email-input-CVyrFzqL.js +0 -1820
  57. package/dist/js/modal-FqewbVts.js +0 -150
  58. package/dist/types/forms/calculator-input/calculator-input.atoms.d.ts +0 -11
  59. package/dist/types/forms/calculator-input/calculator-input.d.ts +0 -8
  60. package/dist/types/forms/calculator-input/index.d.ts +0 -1
  61. package/dist/types/forms/calculator-input/types.d.ts +0 -51
  62. package/dist/types/forms/time-picker-input/time-picker-input.atoms.d.ts +0 -15
@@ -1,146 +1,9 @@
1
- import { a as cva, j as jsxRuntimeExports, c as cn } from "./index-C1uJQB34.js";
1
+ import { c as cva, j as jsxRuntimeExports, a as cn } from "./index-DOdDlCoL.js";
2
2
  import * as React from "react";
3
- import React__default, { forwardRef, useState, useRef, useEffect, useCallback, createContext, useContext, useMemo } from "react";
4
- import { X, ChevronLeft, ChevronRight } from "lucide-react";
5
- const calculatorRootVariants = cva(
6
- "flex flex-col w-full max-w-xs rounded-lg bg-background",
7
- {
8
- variants: {
9
- disabled: {
10
- true: "opacity-60 pointer-events-none",
11
- false: ""
12
- }
13
- },
14
- defaultVariants: {
15
- disabled: !1
16
- }
17
- }
18
- ), calculatorButtonVariants = cva(
19
- "flex-1 min-w-0 h-12 m-0.5 rounded text-lg font-medium transition-colors select-none",
20
- {
21
- variants: {
22
- variant: {
23
- default: "bg-neutral text-foreground hover:bg-neutral-soft hover:text-neutral",
24
- action: "bg-primary text-white hover:bg-primary-soft hover:text-primary",
25
- operator: "bg-secondary text-white hover:bg-secondary-soft hover:text-secondary",
26
- danger: "bg-danger text-white hover:bg-danger-soft hover:text-danger"
27
- },
28
- disabled: {
29
- true: "opacity-50 pointer-events-none",
30
- false: ""
31
- }
32
- },
33
- defaultVariants: {
34
- variant: "default",
35
- disabled: !1
36
- }
37
- }
38
- ), CalculatorButton = forwardRef(({ variant: e = "default", className: t, ...r }, s) => /* @__PURE__ */ jsxRuntimeExports.jsx(
39
- "button",
40
- {
41
- ref: s,
42
- type: "button",
43
- className: cn(
44
- calculatorButtonVariants({ variant: e, disabled: r.disabled }),
45
- t
46
- ),
47
- ...r
48
- }
49
- ));
50
- function getIconColorFromVariant(e = "primary") {
51
- const t = e.split("-");
52
- if (t.length === 1)
53
- switch (t[0]) {
54
- case "ghost":
55
- case "neutral":
56
- case "outline":
57
- return "ghost";
58
- default:
59
- return "neutral";
60
- }
61
- if (t?.[1] === "outline") return "inherit";
62
- switch (t[0]) {
63
- case "primary":
64
- return "primary";
65
- case "secondary":
66
- return "secondary";
67
- case "tertiary":
68
- return "tertiary";
69
- case "ghost":
70
- return "ghost";
71
- case "neutral":
72
- return "ghost";
73
- case "success":
74
- return "success";
75
- case "info":
76
- return "info";
77
- case "warning":
78
- return "warning";
79
- case "danger":
80
- return "danger";
81
- default:
82
- return "neutral";
83
- }
84
- }
85
- const buttonIconVariants = cva(
86
- "inline-flex items-center justify-center font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none active:scale-[0.98] select-none",
87
- {
88
- variants: {
89
- variant: {
90
- // Core variants using Versaur color system
91
- primary: "bg-primary text-white hover:bg-primary/90 focus-visible:ring-primary-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
92
- secondary: "bg-secondary text-white hover:bg-secondary/90 focus-visible:ring-secondary-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
93
- tertiary: "bg-tertiary text-white hover:bg-tertiary/90 focus-visible:ring-tertiary-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
94
- ghost: "bg-white text-foreground hover:bg-ghost-soft focus-visible:ring-ghost-soft focus-visible:ring-offset-white",
95
- neutral: "bg-neutral text-foreground border border-border hover:bg-neutral/80 focus-visible:ring-foreground-soft focus-visible:ring-offset-white shadow-sm",
96
- // Outline variants
97
- "primary-outline": "border border-primary text-primary bg-white hover:bg-primary hover:text-white focus-visible:ring-primary-soft focus-visible:ring-offset-white transition-all",
98
- "secondary-outline": "border border-secondary text-secondary bg-white hover:bg-secondary hover:text-white focus-visible:ring-secondary-soft focus-visible:ring-offset-white transition-all",
99
- "tertiary-outline": "border border-tertiary text-tertiary bg-white hover:bg-tertiary hover:text-white focus-visible:ring-tertiary-soft focus-visible:ring-offset-white transition-all",
100
- "ghost-outline": "border border-ghost text-ghost bg-white hover:bg-ghost hover:text-white focus-visible:ring-ghost-soft focus-visible:ring-offset-white transition-all",
101
- "neutral-outline": "border border-neutral text-foreground bg-white hover:bg-neutral hover:text-foreground focus-visible:ring-foreground-soft focus-visible:ring-offset-white transition-all",
102
- // Ghost variants (subtle)
103
- "primary-ghost": "text-primary bg-white hover:bg-primary-light focus-visible:ring-primary-light focus-visible:ring-offset-white",
104
- "secondary-ghost": "text-secondary bg-white hover:bg-secondary-light focus-visible:ring-secondary-light focus-visible:ring-offset-white",
105
- "tertiary-ghost": "text-tertiary bg-white hover:bg-tertiary-light focus-visible:ring-tertiary-light focus-visible:ring-offset-white",
106
- "neutral-ghost": "text-foreground bg-white hover:bg-neutral-light focus-visible:ring-foreground-light focus-visible:ring-offset-white",
107
- // Semantic variants
108
- success: "bg-success text-white hover:bg-success/90 focus-visible:ring-success-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
109
- "success-outline": "border border-success text-success bg-white hover:bg-success hover:text-white focus-visible:ring-success-soft focus-visible:ring-offset-white transition-all",
110
- "success-ghost": "text-success bg-white hover:bg-success-light focus-visible:ring-success-light focus-visible:ring-offset-white",
111
- info: "bg-info text-white hover:bg-info/90 focus-visible:ring-info-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
112
- "info-outline": "border border-info text-info bg-white hover:bg-info hover:text-white focus-visible:ring-info-soft focus-visible:ring-offset-white transition-all",
113
- "info-ghost": "text-info bg-white hover:bg-info-light focus-visible:ring-info-light focus-visible:ring-offset-white",
114
- warning: "bg-warning text-white hover:bg-warning/90 focus-visible:ring-warning-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
115
- "warning-outline": "border border-warning text-warning bg-white hover:bg-warning hover:text-white focus-visible:ring-warning-soft focus-visible:ring-offset-white transition-all",
116
- "warning-ghost": "text-warning bg-white hover:bg-warning-light focus-visible:ring-warning-light focus-visible:ring-offset-white",
117
- danger: "bg-danger text-white hover:bg-danger/90 focus-visible:ring-danger-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
118
- "danger-outline": "border border-danger text-danger bg-white hover:bg-danger hover:text-white focus-visible:ring-danger-soft focus-visible:ring-offset-white transition-all",
119
- "danger-ghost": "text-danger bg-white hover:bg-danger-light focus-visible:ring-danger-light focus-visible:ring-offset-white",
120
- // Utility variants
121
- outline: "border border-border text-foreground bg-white hover:bg-accent-soft focus-visible:ring-accent-soft focus-visible:ring-offset-white transition-all",
122
- destructive: "bg-danger text-white hover:bg-danger/90 focus-visible:ring-danger-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md"
123
- },
124
- size: {
125
- xs: "h-6 w-6",
126
- sm: "h-8 w-8",
127
- md: "h-10 w-10",
128
- lg: "h-12 w-12",
129
- xl: "h-14 w-14"
130
- },
131
- shape: {
132
- rounded: "rounded-md",
133
- square: "rounded-sm",
134
- circle: "rounded-full"
135
- }
136
- },
137
- defaultVariants: {
138
- variant: "primary",
139
- size: "md",
140
- shape: "rounded"
141
- }
142
- }
143
- ), iconVariants = cva("inline-flex items-center justify-center", {
3
+ import React__default, { forwardRef, useState, useEffect, useCallback, useRef, createContext, useContext, useMemo } from "react";
4
+ import { X, ChevronLeft, ChevronRight, ImageOff } from "lucide-react";
5
+ import { S as Skeleton } from "./skeleton-BNZyaRjo.js";
6
+ const iconVariants = cva("inline-flex items-center justify-center", {
144
7
  variants: {
145
8
  size: {
146
9
  xs: "w-3 h-3",
@@ -166,257 +29,16 @@ const buttonIconVariants = cva(
166
29
  size: "md",
167
30
  color: "primary"
168
31
  }
169
- }), Icon = React__default.forwardRef(function({ as: t, color: r = "primary", size: s = "md", className: o, ...n }, a) {
32
+ }), Icon = React__default.forwardRef(function({ as: t, color: r = "primary", size: s = "md", className: n, ...o }, i) {
170
33
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
171
34
  t,
172
35
  {
173
- ref: a,
174
- className: iconVariants({ color: r, size: s, className: o }),
175
- ...n
176
- }
177
- );
178
- }), ButtonIcon = React__default.forwardRef(
179
- function({
180
- className: t,
181
- variant: r = "primary",
182
- size: s = "md",
183
- shape: o = "rounded",
184
- disabled: n = !1,
185
- as: a,
186
- "aria-label": i,
187
- ...u
188
- }, c) {
189
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
190
- "button",
191
- {
192
- ref: c,
193
- type: "button",
194
- className: cn(
195
- buttonIconVariants({
196
- variant: r,
197
- size: s,
198
- shape: o
199
- }),
200
- t
201
- ),
202
- disabled: n,
203
- "aria-disabled": n,
204
- "aria-label": i,
205
- inert: n ? !0 : void 0,
206
- ...u,
207
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(
208
- Icon,
209
- {
210
- as: a,
211
- size: s,
212
- color: getIconColorFromVariant(r)
213
- }
214
- )
215
- }
216
- );
217
- }
218
- );
219
- function useCalculator({
220
- initialValue = "",
221
- disabled,
222
- onChange
223
- }) {
224
- const [input, setInput] = useState(String(initialValue)), inputRef = useRef(null);
225
- useEffect(() => {
226
- setInput(String(initialValue));
227
- }, [initialValue]);
228
- const evaluate = useCallback((expr) => {
229
- try {
230
- if (!/^[-+*/.\d\s]+$/.test(expr)) return "";
231
- const result = eval(expr);
232
- return result?.toString() ?? "";
233
- } catch {
234
- return "";
36
+ ref: i,
37
+ className: iconVariants({ color: r, size: s, className: n }),
38
+ ...o
235
39
  }
236
- }, []), handleButton = useCallback(
237
- (e) => {
238
- if (!disabled)
239
- if (e === "C")
240
- setInput("");
241
- else if (e === "⌫")
242
- setInput((t) => t.slice(0, -1));
243
- else if (e === "=") {
244
- const t = evaluate(input);
245
- setInput(t);
246
- } else
247
- setInput((t) => t + e);
248
- },
249
- [disabled, input, evaluate]
250
40
  );
251
- useEffect(() => {
252
- if (onChange) {
253
- const e = evaluate(input);
254
- onChange(e);
255
- }
256
- }, [evaluate, input, onChange]), useEffect(() => {
257
- if (disabled) return;
258
- const e = (t) => {
259
- if (document.activeElement !== inputRef.current && document.activeElement?.tagName !== "BODY")
260
- return;
261
- const r = t.key;
262
- r === "Enter" || r === "=" ? (handleButton("="), t.preventDefault()) : r === "Backspace" ? (handleButton("⌫"), t.preventDefault()) : r === "Escape" || r === "C" || r === "c" ? (handleButton("C"), t.preventDefault()) : (/^[0-9]$/.test(r) || ["/", "*", "-", "+", "."].includes(r)) && (handleButton(r), t.preventDefault());
263
- };
264
- return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
265
- }, [handleButton, disabled]), useEffect(() => {
266
- disabled || inputRef.current?.focus();
267
- }, [disabled]);
268
- const handleInput = (e) => {
269
- const t = e.target.value.replace(/[^\d+\-*/.]/g, "");
270
- setInput(t);
271
- };
272
- return {
273
- input,
274
- inputRef,
275
- handleButton,
276
- handleInput
277
- };
278
- }
279
- const BUTTONS = [
280
- ["7", "8", "9", "/"],
281
- ["4", "5", "6", "*"],
282
- ["1", "2", "3", "-"],
283
- ["0", ".", "=", "+"]
284
- ], Calculator = forwardRef(
285
- ({
286
- initialValue: e = "",
287
- onChange: t,
288
- disabled: r,
289
- className: s,
290
- "aria-label": o
291
- }, n) => {
292
- const { input: a, inputRef: i, handleButton: u, handleInput: c } = useCalculator({
293
- initialValue: e,
294
- disabled: r,
295
- onChange: t
296
- });
297
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
298
- "div",
299
- {
300
- ref: n,
301
- className: cn(calculatorRootVariants({ disabled: r }), s),
302
- "aria-label": o || "Calculator",
303
- role: "region",
304
- children: [
305
- /* @__PURE__ */ jsxRuntimeExports.jsx(
306
- "input",
307
- {
308
- ref: i,
309
- className: "w-full mb-3 px-3 py-2 rounded border border-[var(--color-neutral)] bg-[var(--color-neutral-soft)] text-right text-xl font-mono focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)]",
310
- value: a,
311
- onChange: c,
312
- disabled: r,
313
- inputMode: "decimal",
314
- "aria-label": "Calculator input"
315
- }
316
- ),
317
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col gap-1 mb-3", children: BUTTONS.map((x, b) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex w-full", children: x.map((f) => f === "⌫" ? /* @__PURE__ */ jsxRuntimeExports.jsx(
318
- ButtonIcon,
319
- {
320
- as: X,
321
- variant: "danger-ghost",
322
- "aria-label": "Backspace",
323
- size: "md",
324
- onClick: () => u("⌫"),
325
- disabled: r
326
- },
327
- "backspace"
328
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
329
- CalculatorButton,
330
- {
331
- variant: f === "=" ? "action" : f === "C" ? "danger" : ["/", "*", "-", "+", "/"].includes(f) ? "operator" : "default",
332
- onClick: () => u(f),
333
- disabled: r,
334
- "aria-label": f,
335
- children: f
336
- },
337
- f
338
- )) }, b)) })
339
- ]
340
- }
341
- );
342
- }
343
- );
344
- Calculator.displayName = "Calculator";
345
- const buttonVariants = cva(
346
- "inline-flex items-center justify-center gap-2 rounded-md font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none active:scale-[0.98] select-none",
347
- {
348
- variants: {
349
- variant: {
350
- // Core variants using Versaur color system
351
- primary: "bg-primary text-white hover:bg-primary/90 focus-visible:ring-primary-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
352
- secondary: "bg-secondary text-white hover:bg-secondary/90 focus-visible:ring-secondary-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
353
- tertiary: "bg-tertiary text-white hover:bg-tertiary/90 focus-visible:ring-tertiary-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
354
- ghost: "bg-white text-foreground hover:bg-ghost-soft focus-visible:ring-ghost-soft focus-visible:ring-offset-white",
355
- neutral: "bg-neutral text-foreground border border-border hover:bg-neutral/80 focus-visible:ring-foreground-soft focus-visible:ring-offset-white shadow-sm",
356
- // Outline variants
357
- "primary-outline": "border border-primary text-primary bg-white hover:bg-primary hover:text-white focus-visible:ring-primary-soft focus-visible:ring-offset-white transition-all",
358
- "secondary-outline": "border border-secondary text-secondary bg-white hover:bg-secondary hover:text-white focus-visible:ring-secondary-soft focus-visible:ring-offset-white transition-all",
359
- "tertiary-outline": "border border-tertiary text-tertiary bg-white hover:bg-tertiary hover:text-white focus-visible:ring-tertiary-soft focus-visible:ring-offset-white transition-all",
360
- "ghost-outline": "border border-ghost text-ghost bg-white hover:bg-ghost hover:text-white focus-visible:ring-ghost-soft focus-visible:ring-offset-white transition-all",
361
- "neutral-outline": "border border-neutral text-foreground bg-white hover:bg-neutral hover:text-foreground focus-visible:ring-foreground-soft focus-visible:ring-offset-white transition-all",
362
- // Ghost variants (subtle)
363
- "primary-ghost": "text-primary bg-white hover:bg-primary-light focus-visible:ring-primary-light focus-visible:ring-offset-white",
364
- "secondary-ghost": "text-secondary bg-white hover:bg-secondary-light focus-visible:ring-secondary-light focus-visible:ring-offset-white",
365
- "tertiary-ghost": "text-tertiary bg-white hover:bg-tertiary-light focus-visible:ring-tertiary-light focus-visible:ring-offset-white",
366
- "neutral-ghost": "text-foreground bg-white hover:bg-neutral/70 focus-visible:ring-foreground-soft focus-visible:ring-offset-white",
367
- // Semantic variants
368
- success: "bg-success text-white hover:bg-success/90 focus-visible:ring-success-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
369
- "success-outline": "border border-success text-success bg-white hover:bg-success hover:text-white focus-visible:ring-success-soft focus-visible:ring-offset-white transition-all",
370
- "success-ghost": "text-success bg-white hover:bg-success-light focus-visible:ring-success-light focus-visible:ring-offset-white",
371
- info: "bg-info text-white hover:bg-info/90 focus-visible:ring-info-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
372
- "info-outline": "border border-info text-info bg-white hover:bg-info hover:text-white focus-visible:ring-info-soft focus-visible:ring-offset-white transition-all",
373
- "info-ghost": "text-info bg-white hover:bg-info-light focus-visible:ring-info-light focus-visible:ring-offset-white",
374
- warning: "bg-warning text-white hover:bg-warning/90 focus-visible:ring-warning-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
375
- "warning-outline": "border border-warning text-warning bg-white hover:bg-warning hover:text-white focus-visible:ring-warning-soft focus-visible:ring-offset-white transition-all",
376
- "warning-ghost": "text-warning bg-white hover:bg-warning-light focus-visible:ring-warning-light focus-visible:ring-offset-white",
377
- danger: "bg-danger text-white hover:bg-danger/90 focus-visible:ring-danger-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
378
- "danger-outline": "border border-danger text-danger bg-white hover:bg-danger hover:text-white focus-visible:ring-danger-soft focus-visible:ring-offset-white transition-all",
379
- "danger-ghost": "text-danger bg-white hover:bg-danger-light focus-visible:ring-danger-light focus-visible:ring-offset-white",
380
- // Utility variants
381
- outline: "border border-border text-foreground bg-white hover:bg-accent-soft focus-visible:ring-accent-soft focus-visible:ring-offset-white transition-all",
382
- destructive: "bg-danger text-white hover:bg-danger/90 focus-visible:ring-danger-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md"
383
- },
384
- size: {
385
- sm: "h-8 px-3 text-sm min-w-[2.25rem]",
386
- md: "h-10 px-4 text-sm min-w-[2.5rem]",
387
- lg: "h-12 px-8 text-lg min-w-[2.75rem]"
388
- }
389
- },
390
- defaultVariants: {
391
- variant: "primary",
392
- size: "md"
393
- }
394
- }
395
- ), Button = React__default.forwardRef(
396
- function e({
397
- className: t,
398
- variant: r = "primary",
399
- size: s = "md",
400
- disabled: o = !1,
401
- type: n = "button",
402
- children: a,
403
- ...i
404
- }, u) {
405
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
406
- "button",
407
- {
408
- ref: u,
409
- type: n,
410
- className: cn(buttonVariants({ variant: r, size: s }), t),
411
- disabled: o,
412
- "aria-disabled": o,
413
- inert: o ? !0 : void 0,
414
- ...i,
415
- children: a
416
- }
417
- );
418
- }
419
- ), alertVariants = cva(
41
+ }), alertVariants = cva(
420
42
  "relative flex items-center gap-2 rounded-md p-2 text-sm transition-all duration-200",
421
43
  {
422
44
  variants: {
@@ -559,18 +181,18 @@ const buttonVariants = cva(
559
181
  color: t = "neutral",
560
182
  icon: r,
561
183
  className: s,
562
- children: o,
563
- ...n
564
- }, a) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
184
+ children: n,
185
+ ...o
186
+ }, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
565
187
  "div",
566
188
  {
567
- ref: a,
189
+ ref: i,
568
190
  role: "alert",
569
191
  className: cn(alertVariants({ variant: e, color: t }), s),
570
- ...n,
192
+ ...o,
571
193
  children: [
572
194
  r && /* @__PURE__ */ jsxRuntimeExports.jsx(AlertIcon, { children: r }),
573
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1", children: o })
195
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1", children: n })
574
196
  ]
575
197
  }
576
198
  )
@@ -639,18 +261,18 @@ const buttonVariants = cva(
639
261
  className: t,
640
262
  color: r = "primary",
641
263
  fontSize: s = "base",
642
- fontWeight: o = "medium",
643
- quiet: n = !1,
644
- ...a
645
- }, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(
264
+ fontWeight: n = "medium",
265
+ quiet: o = !1,
266
+ ...i
267
+ }, a) => /* @__PURE__ */ jsxRuntimeExports.jsx(
646
268
  "a",
647
269
  {
648
- ref: i,
270
+ ref: a,
649
271
  className: cn(
650
- anchorVariants({ color: r, fontSize: s, fontWeight: o, quiet: n }),
272
+ anchorVariants({ color: r, fontSize: s, fontWeight: n, quiet: o }),
651
273
  t
652
274
  ),
653
- ...a,
275
+ ...i,
654
276
  children: e
655
277
  }
656
278
  )
@@ -698,38 +320,38 @@ const buttonVariants = cva(
698
320
  size: t = "md",
699
321
  shape: r = "circle",
700
322
  className: s,
701
- children: o,
702
- ...n
703
- }, a) => /* @__PURE__ */ jsxRuntimeExports.jsx(
323
+ children: n,
324
+ ...o
325
+ }, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(
704
326
  "div",
705
327
  {
706
- ref: a,
328
+ ref: i,
707
329
  className: cn(avatarVariants({ variant: e, size: t, shape: r }), s),
708
- ...n,
709
- children: o
330
+ ...o,
331
+ children: n
710
332
  }
711
333
  )
712
334
  ), AvatarImage = forwardRef(
713
- ({ src: e, alt: t, className: r, onError: s, ...o }, n) => {
714
- const [a, i] = useState(!1);
335
+ ({ src: e, alt: t, className: r, onError: s, ...n }, o) => {
336
+ const [i, a] = useState(!1);
715
337
  useEffect(() => {
716
- i(!1);
338
+ a(!1);
717
339
  }, [e]);
718
340
  const u = useCallback(
719
- (c) => {
720
- i(!0), s?.(c);
341
+ (l) => {
342
+ a(!0), s?.(l);
721
343
  },
722
344
  [s]
723
345
  );
724
- return a ? null : /* @__PURE__ */ jsxRuntimeExports.jsx(
346
+ return i ? null : /* @__PURE__ */ jsxRuntimeExports.jsx(
725
347
  "img",
726
348
  {
727
- ref: n,
349
+ ref: o,
728
350
  src: e,
729
351
  alt: t,
730
352
  className: cn(avatarImageVariants(), r),
731
353
  onError: u,
732
- ...o
354
+ ...n
733
355
  }
734
356
  );
735
357
  }
@@ -897,17 +519,17 @@ const buttonVariants = cva(
897
519
  shape: t = "square",
898
520
  color: r = "primary",
899
521
  size: s = "md",
900
- iconLeft: o,
901
- iconRight: n,
902
- className: a,
903
- children: i,
522
+ iconLeft: n,
523
+ iconRight: o,
524
+ className: i,
525
+ children: a,
904
526
  ...u
905
- }, c) => {
906
- const f = !(i != null && i !== "") && !!(o || n);
527
+ }, l) => {
528
+ const f = !(a != null && a !== "") && !!(n || o);
907
529
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
908
530
  "span",
909
531
  {
910
- ref: c,
532
+ ref: l,
911
533
  className: cn(
912
534
  badgeVariants({
913
535
  variant: e,
@@ -916,18 +538,18 @@ const buttonVariants = cva(
916
538
  size: s,
917
539
  iconOnly: f
918
540
  }),
919
- a
541
+ i
920
542
  ),
921
543
  ...u,
922
544
  children: f ? (
923
545
  // Icon-only mode: display only the icon
924
- o || n
546
+ n || o
925
547
  ) : (
926
548
  // Normal mode: display icon(s) and text
927
549
  /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
928
- o,
929
- i,
930
- n
550
+ n,
551
+ a,
552
+ o
931
553
  ] })
932
554
  )
933
555
  }
@@ -944,36 +566,110 @@ const SvgSpenicleSquare = (e) => /* @__PURE__ */ React.createElement("svg", { wi
944
566
  lg: "h-10 w-10",
945
567
  xl: "h-12 w-12"
946
568
  }
947
- },
948
- defaultVariants: {
949
- size: "md"
569
+ },
570
+ defaultVariants: {
571
+ size: "md"
572
+ }
573
+ }), BrandLogo = forwardRef(
574
+ ({ shape: e = "square", size: t, ...r }, s) => {
575
+ const o = {
576
+ square: SvgSpenicleSquare,
577
+ rounded: SvgSpenicleRounded,
578
+ circle: SvgSpenicleCircle
579
+ }[e] || SvgSpenicleSquare;
580
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
581
+ o,
582
+ {
583
+ ref: s,
584
+ ...r,
585
+ className: cn("inline-block", brandSizeClass({ size: t }))
586
+ }
587
+ );
588
+ }
589
+ ), Brand = forwardRef(
590
+ ({ name: e = "spenicle", size: t = "md", shape: r, ...s }, n) => /* @__PURE__ */ jsxRuntimeExports.jsx(
591
+ "span",
592
+ {
593
+ ref: n,
594
+ className: cn("inline-flex items-center gap-2"),
595
+ ...s,
596
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(BrandLogo, { shape: r, size: t, "aria-hidden": "true" })
597
+ }
598
+ )
599
+ ), buttonVariants = cva(
600
+ "inline-flex items-center justify-center gap-2 rounded-md font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none active:scale-[0.98] select-none",
601
+ {
602
+ variants: {
603
+ variant: {
604
+ // Core variants using Versaur color system
605
+ primary: "bg-primary text-white hover:bg-primary/90 focus-visible:ring-primary-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
606
+ secondary: "bg-secondary text-white hover:bg-secondary/90 focus-visible:ring-secondary-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
607
+ tertiary: "bg-tertiary text-white hover:bg-tertiary/90 focus-visible:ring-tertiary-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
608
+ ghost: "bg-white text-foreground hover:bg-ghost-soft focus-visible:ring-ghost-soft focus-visible:ring-offset-white",
609
+ neutral: "bg-neutral text-foreground border border-border hover:bg-neutral/80 focus-visible:ring-foreground-soft focus-visible:ring-offset-white shadow-sm",
610
+ // Outline variants
611
+ "primary-outline": "border border-primary text-primary bg-white hover:bg-primary hover:text-white focus-visible:ring-primary-soft focus-visible:ring-offset-white transition-all",
612
+ "secondary-outline": "border border-secondary text-secondary bg-white hover:bg-secondary hover:text-white focus-visible:ring-secondary-soft focus-visible:ring-offset-white transition-all",
613
+ "tertiary-outline": "border border-tertiary text-tertiary bg-white hover:bg-tertiary hover:text-white focus-visible:ring-tertiary-soft focus-visible:ring-offset-white transition-all",
614
+ "ghost-outline": "border border-ghost text-ghost bg-white hover:bg-ghost hover:text-white focus-visible:ring-ghost-soft focus-visible:ring-offset-white transition-all",
615
+ "neutral-outline": "border border-neutral text-foreground bg-white hover:bg-neutral hover:text-foreground focus-visible:ring-foreground-soft focus-visible:ring-offset-white transition-all",
616
+ // Ghost variants (subtle)
617
+ "primary-ghost": "text-primary bg-white hover:bg-primary-light focus-visible:ring-primary-light focus-visible:ring-offset-white",
618
+ "secondary-ghost": "text-secondary bg-white hover:bg-secondary-light focus-visible:ring-secondary-light focus-visible:ring-offset-white",
619
+ "tertiary-ghost": "text-tertiary bg-white hover:bg-tertiary-light focus-visible:ring-tertiary-light focus-visible:ring-offset-white",
620
+ "neutral-ghost": "text-foreground bg-white hover:bg-neutral/70 focus-visible:ring-foreground-soft focus-visible:ring-offset-white",
621
+ // Semantic variants
622
+ success: "bg-success text-white hover:bg-success/90 focus-visible:ring-success-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
623
+ "success-outline": "border border-success text-success bg-white hover:bg-success hover:text-white focus-visible:ring-success-soft focus-visible:ring-offset-white transition-all",
624
+ "success-ghost": "text-success bg-white hover:bg-success-light focus-visible:ring-success-light focus-visible:ring-offset-white",
625
+ info: "bg-info text-white hover:bg-info/90 focus-visible:ring-info-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
626
+ "info-outline": "border border-info text-info bg-white hover:bg-info hover:text-white focus-visible:ring-info-soft focus-visible:ring-offset-white transition-all",
627
+ "info-ghost": "text-info bg-white hover:bg-info-light focus-visible:ring-info-light focus-visible:ring-offset-white",
628
+ warning: "bg-warning text-white hover:bg-warning/90 focus-visible:ring-warning-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
629
+ "warning-outline": "border border-warning text-warning bg-white hover:bg-warning hover:text-white focus-visible:ring-warning-soft focus-visible:ring-offset-white transition-all",
630
+ "warning-ghost": "text-warning bg-white hover:bg-warning-light focus-visible:ring-warning-light focus-visible:ring-offset-white",
631
+ danger: "bg-danger text-white hover:bg-danger/90 focus-visible:ring-danger-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
632
+ "danger-outline": "border border-danger text-danger bg-white hover:bg-danger hover:text-white focus-visible:ring-danger-soft focus-visible:ring-offset-white transition-all",
633
+ "danger-ghost": "text-danger bg-white hover:bg-danger-light focus-visible:ring-danger-light focus-visible:ring-offset-white",
634
+ // Utility variants
635
+ outline: "border border-border text-foreground bg-white hover:bg-accent-soft focus-visible:ring-accent-soft focus-visible:ring-offset-white transition-all",
636
+ destructive: "bg-danger text-white hover:bg-danger/90 focus-visible:ring-danger-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md"
637
+ },
638
+ size: {
639
+ sm: "h-8 px-3 text-sm min-w-[2.25rem]",
640
+ md: "h-10 px-4 text-sm min-w-[2.5rem]",
641
+ lg: "h-12 px-8 text-lg min-w-[2.75rem]"
642
+ }
643
+ },
644
+ defaultVariants: {
645
+ variant: "primary",
646
+ size: "md"
647
+ }
950
648
  }
951
- }), BrandLogo = forwardRef(
952
- ({ shape: e = "square", size: t, ...r }, s) => {
953
- const n = {
954
- square: SvgSpenicleSquare,
955
- rounded: SvgSpenicleRounded,
956
- circle: SvgSpenicleCircle
957
- }[e] || SvgSpenicleSquare;
649
+ ), Button = React__default.forwardRef(
650
+ function({
651
+ className: t,
652
+ variant: r = "primary",
653
+ size: s = "md",
654
+ disabled: n = !1,
655
+ type: o = "button",
656
+ children: i,
657
+ ...a
658
+ }, u) {
958
659
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
959
- n,
660
+ "button",
960
661
  {
961
- ref: s,
962
- ...r,
963
- className: cn("inline-block", brandSizeClass({ size: t }))
662
+ ref: u,
663
+ type: o,
664
+ className: cn(buttonVariants({ variant: r, size: s }), t),
665
+ disabled: n,
666
+ "aria-disabled": n,
667
+ inert: n ? !0 : void 0,
668
+ ...a,
669
+ children: i
964
670
  }
965
671
  );
966
672
  }
967
- ), Brand = forwardRef(
968
- ({ name: e = "spenicle", size: t = "md", shape: r, ...s }, o) => /* @__PURE__ */ jsxRuntimeExports.jsx(
969
- "span",
970
- {
971
- ref: o,
972
- className: cn("inline-flex items-center gap-2"),
973
- ...s,
974
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(BrandLogo, { shape: r, size: t, "aria-hidden": "true" })
975
- }
976
- )
977
673
  ), buttonFloatVariants = cva(
978
674
  [
979
675
  "inline-flex items-center justify-center gap-2",
@@ -1035,76 +731,381 @@ const SvgSpenicleSquare = (e) => /* @__PURE__ */ React.createElement("svg", { wi
1035
731
  lg: "h-16 w-16 min-w-16 min-h-16 text-xl"
1036
732
  }
1037
733
  },
1038
- defaultVariants: {
1039
- variant: "primary",
1040
- size: "md"
734
+ defaultVariants: {
735
+ variant: "primary",
736
+ size: "md"
737
+ }
738
+ }
739
+ );
740
+ function useFloatingPosition(e, t = "1rem") {
741
+ const r = useRef(null), [s, n] = useState({}), [o, i] = useState("fixed bottom-4 right-4"), a = useCallback(() => {
742
+ const l = r.current;
743
+ if (!l) return;
744
+ const h = l.getBoundingClientRect().height > window.innerHeight;
745
+ let f = {}, p = "";
746
+ h ? (f = {
747
+ position: "fixed",
748
+ bottom: t,
749
+ zIndex: 50,
750
+ transform: `translateY(${l.scrollTop}px)`
751
+ }, p = `fixed bottom-4 ${e}-4`) : (f = {
752
+ position: "fixed",
753
+ bottom: t,
754
+ zIndex: 50
755
+ }, p = `fixed bottom-4 ${e}-4`), n(f), i(p);
756
+ }, [e, t]);
757
+ return useEffect(() => {
758
+ a();
759
+ const l = r.current;
760
+ return l && l.addEventListener("scroll", a), window.addEventListener("resize", a), () => {
761
+ l && l.removeEventListener("scroll", a), window.removeEventListener("resize", a);
762
+ };
763
+ }, [a]), useEffect(() => {
764
+ r.current && a();
765
+ }, [e, t, a]), [useCallback(
766
+ (l) => {
767
+ r.current = l, l && a();
768
+ },
769
+ [a]
770
+ ), s, o];
771
+ }
772
+ const ButtonFloat = forwardRef(
773
+ function({
774
+ className: t,
775
+ variant: r = "primary",
776
+ size: s = "md",
777
+ side: n = "right",
778
+ offset: o = "1rem",
779
+ ...i
780
+ }, a) {
781
+ const [u, l, x] = useFloatingPosition(
782
+ n,
783
+ o
784
+ ), [h, f] = useState(!1);
785
+ return useEffect(() => {
786
+ f(!0);
787
+ }, []), /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: u, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
788
+ "button",
789
+ {
790
+ ref: a,
791
+ type: i.type || "button",
792
+ className: cn(
793
+ buttonFloatVariants({ variant: r, size: s }),
794
+ x,
795
+ h && "animate-fab-in",
796
+ t
797
+ ),
798
+ style: l,
799
+ ...i
800
+ }
801
+ ) });
802
+ }
803
+ );
804
+ function getIconColorFromVariant(e = "primary") {
805
+ const t = e.split("-");
806
+ if (t.length === 1)
807
+ switch (t[0]) {
808
+ case "ghost":
809
+ case "neutral":
810
+ case "outline":
811
+ return "ghost";
812
+ default:
813
+ return "neutral";
814
+ }
815
+ if (t?.[1] === "outline") return "inherit";
816
+ switch (t[0]) {
817
+ case "primary":
818
+ return "primary";
819
+ case "secondary":
820
+ return "secondary";
821
+ case "tertiary":
822
+ return "tertiary";
823
+ case "ghost":
824
+ return "ghost";
825
+ case "neutral":
826
+ return "ghost";
827
+ case "success":
828
+ return "success";
829
+ case "info":
830
+ return "info";
831
+ case "warning":
832
+ return "warning";
833
+ case "danger":
834
+ return "danger";
835
+ default:
836
+ return "neutral";
837
+ }
838
+ }
839
+ const buttonIconVariants = cva(
840
+ "inline-flex items-center justify-center font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none active:scale-[0.98] select-none",
841
+ {
842
+ variants: {
843
+ variant: {
844
+ // Core variants using Versaur color system
845
+ primary: "bg-primary text-white hover:bg-primary/90 focus-visible:ring-primary-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
846
+ secondary: "bg-secondary text-white hover:bg-secondary/90 focus-visible:ring-secondary-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
847
+ tertiary: "bg-tertiary text-white hover:bg-tertiary/90 focus-visible:ring-tertiary-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
848
+ ghost: "bg-white text-foreground hover:bg-ghost-soft focus-visible:ring-ghost-soft focus-visible:ring-offset-white",
849
+ neutral: "bg-neutral text-foreground border border-border hover:bg-neutral/80 focus-visible:ring-foreground-soft focus-visible:ring-offset-white shadow-sm",
850
+ // Outline variants
851
+ "primary-outline": "border border-primary text-primary bg-white hover:bg-primary hover:text-white focus-visible:ring-primary-soft focus-visible:ring-offset-white transition-all",
852
+ "secondary-outline": "border border-secondary text-secondary bg-white hover:bg-secondary hover:text-white focus-visible:ring-secondary-soft focus-visible:ring-offset-white transition-all",
853
+ "tertiary-outline": "border border-tertiary text-tertiary bg-white hover:bg-tertiary hover:text-white focus-visible:ring-tertiary-soft focus-visible:ring-offset-white transition-all",
854
+ "ghost-outline": "border border-ghost text-ghost bg-white hover:bg-ghost hover:text-white focus-visible:ring-ghost-soft focus-visible:ring-offset-white transition-all",
855
+ "neutral-outline": "border border-neutral text-foreground bg-white hover:bg-neutral hover:text-foreground focus-visible:ring-foreground-soft focus-visible:ring-offset-white transition-all",
856
+ // Ghost variants (subtle)
857
+ "primary-ghost": "text-primary bg-white hover:bg-primary-light focus-visible:ring-primary-light focus-visible:ring-offset-white",
858
+ "secondary-ghost": "text-secondary bg-white hover:bg-secondary-light focus-visible:ring-secondary-light focus-visible:ring-offset-white",
859
+ "tertiary-ghost": "text-tertiary bg-white hover:bg-tertiary-light focus-visible:ring-tertiary-light focus-visible:ring-offset-white",
860
+ "neutral-ghost": "text-foreground bg-white hover:bg-neutral-light focus-visible:ring-foreground-light focus-visible:ring-offset-white",
861
+ // Semantic variants
862
+ success: "bg-success text-white hover:bg-success/90 focus-visible:ring-success-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
863
+ "success-outline": "border border-success text-success bg-white hover:bg-success hover:text-white focus-visible:ring-success-soft focus-visible:ring-offset-white transition-all",
864
+ "success-ghost": "text-success bg-white hover:bg-success-light focus-visible:ring-success-light focus-visible:ring-offset-white",
865
+ info: "bg-info text-white hover:bg-info/90 focus-visible:ring-info-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
866
+ "info-outline": "border border-info text-info bg-white hover:bg-info hover:text-white focus-visible:ring-info-soft focus-visible:ring-offset-white transition-all",
867
+ "info-ghost": "text-info bg-white hover:bg-info-light focus-visible:ring-info-light focus-visible:ring-offset-white",
868
+ warning: "bg-warning text-white hover:bg-warning/90 focus-visible:ring-warning-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
869
+ "warning-outline": "border border-warning text-warning bg-white hover:bg-warning hover:text-white focus-visible:ring-warning-soft focus-visible:ring-offset-white transition-all",
870
+ "warning-ghost": "text-warning bg-white hover:bg-warning-light focus-visible:ring-warning-light focus-visible:ring-offset-white",
871
+ danger: "bg-danger text-white hover:bg-danger/90 focus-visible:ring-danger-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md",
872
+ "danger-outline": "border border-danger text-danger bg-white hover:bg-danger hover:text-white focus-visible:ring-danger-soft focus-visible:ring-offset-white transition-all",
873
+ "danger-ghost": "text-danger bg-white hover:bg-danger-light focus-visible:ring-danger-light focus-visible:ring-offset-white",
874
+ // Utility variants
875
+ outline: "border border-border text-foreground bg-white hover:bg-accent-soft focus-visible:ring-accent-soft focus-visible:ring-offset-white transition-all",
876
+ destructive: "bg-danger text-white hover:bg-danger/90 focus-visible:ring-danger-soft focus-visible:ring-offset-white shadow-sm hover:shadow-md"
877
+ },
878
+ size: {
879
+ xs: "h-6 w-6",
880
+ sm: "h-8 w-8",
881
+ md: "h-10 w-10",
882
+ lg: "h-12 w-12",
883
+ xl: "h-14 w-14"
884
+ },
885
+ shape: {
886
+ rounded: "rounded-md",
887
+ square: "rounded-sm",
888
+ circle: "rounded-full"
889
+ }
890
+ },
891
+ defaultVariants: {
892
+ variant: "primary",
893
+ size: "md",
894
+ shape: "rounded"
895
+ }
896
+ }
897
+ ), ButtonIcon = React__default.forwardRef(
898
+ function({
899
+ className: t,
900
+ variant: r = "primary",
901
+ size: s = "md",
902
+ shape: n = "rounded",
903
+ disabled: o = !1,
904
+ as: i,
905
+ "aria-label": a,
906
+ ...u
907
+ }, l) {
908
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
909
+ "button",
910
+ {
911
+ ref: l,
912
+ type: "button",
913
+ className: cn(
914
+ buttonIconVariants({
915
+ variant: r,
916
+ size: s,
917
+ shape: n
918
+ }),
919
+ t
920
+ ),
921
+ disabled: o,
922
+ "aria-disabled": o,
923
+ "aria-label": a,
924
+ inert: o ? !0 : void 0,
925
+ ...u,
926
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
927
+ Icon,
928
+ {
929
+ as: i,
930
+ size: s,
931
+ color: getIconColorFromVariant(r)
932
+ }
933
+ )
934
+ }
935
+ );
936
+ }
937
+ ), calculatorRootVariants = cva(
938
+ "flex flex-col w-full max-w-xs rounded-lg bg-background",
939
+ {
940
+ variants: {
941
+ disabled: {
942
+ true: "opacity-60 pointer-events-none",
943
+ false: ""
944
+ }
945
+ },
946
+ defaultVariants: {
947
+ disabled: !1
948
+ }
949
+ }
950
+ ), calculatorButtonVariants = cva(
951
+ "flex-1 min-w-0 h-12 m-0.5 rounded text-lg font-medium transition-colors select-none",
952
+ {
953
+ variants: {
954
+ variant: {
955
+ default: "bg-neutral text-foreground hover:bg-neutral-soft hover:text-neutral",
956
+ action: "bg-primary text-white hover:bg-primary-soft hover:text-primary",
957
+ operator: "bg-secondary text-white hover:bg-secondary-soft hover:text-secondary",
958
+ danger: "bg-danger text-white hover:bg-danger-soft hover:text-danger"
959
+ },
960
+ disabled: {
961
+ true: "opacity-50 pointer-events-none",
962
+ false: ""
963
+ }
964
+ },
965
+ defaultVariants: {
966
+ variant: "default",
967
+ disabled: !1
968
+ }
969
+ }
970
+ ), CalculatorButton = forwardRef(({ variant: e = "default", className: t, ...r }, s) => /* @__PURE__ */ jsxRuntimeExports.jsx(
971
+ "button",
972
+ {
973
+ ref: s,
974
+ type: "button",
975
+ className: cn(
976
+ calculatorButtonVariants({ variant: e, disabled: r.disabled }),
977
+ t
978
+ ),
979
+ ...r
980
+ }
981
+ ));
982
+ function useCalculator({
983
+ initialValue = "",
984
+ disabled,
985
+ onChange
986
+ }) {
987
+ const [input, setInput] = useState(String(initialValue)), inputRef = useRef(null);
988
+ useEffect(() => {
989
+ setInput(String(initialValue));
990
+ }, [initialValue]);
991
+ const evaluate = useCallback((expr) => {
992
+ try {
993
+ if (!/^[-+*/.\d\s]+$/.test(expr)) return "";
994
+ const result = eval(expr);
995
+ return result?.toString() ?? "";
996
+ } catch {
997
+ return "";
998
+ }
999
+ }, []), handleButton = useCallback(
1000
+ (e) => {
1001
+ if (!disabled)
1002
+ if (e === "C")
1003
+ setInput("");
1004
+ else if (e === "⌫")
1005
+ setInput((t) => t.slice(0, -1));
1006
+ else if (e === "=") {
1007
+ const t = evaluate(input);
1008
+ setInput(t);
1009
+ } else
1010
+ setInput((t) => t + e);
1011
+ },
1012
+ [disabled, input, evaluate]
1013
+ );
1014
+ useEffect(() => {
1015
+ if (onChange) {
1016
+ const e = evaluate(input);
1017
+ onChange(e);
1041
1018
  }
1042
- }
1043
- );
1044
- function useFloatingPosition(e, t = "1rem") {
1045
- const r = useRef(null), [s, o] = useState({}), [n, a] = useState("fixed bottom-4 right-4"), i = useCallback(() => {
1046
- const c = r.current;
1047
- if (!c) return;
1048
- const b = c.getBoundingClientRect().height > window.innerHeight;
1049
- let f = {}, w = "";
1050
- b ? (f = {
1051
- position: "fixed",
1052
- bottom: t,
1053
- zIndex: 50,
1054
- transform: `translateY(${c.scrollTop}px)`
1055
- }, w = `fixed bottom-4 ${e}-4`) : (f = {
1056
- position: "fixed",
1057
- bottom: t,
1058
- zIndex: 50
1059
- }, w = `fixed bottom-4 ${e}-4`), o(f), a(w);
1060
- }, [e, t]);
1061
- return useEffect(() => {
1062
- i();
1063
- const c = r.current;
1064
- return c && c.addEventListener("scroll", i), window.addEventListener("resize", i), () => {
1065
- c && c.removeEventListener("scroll", i), window.removeEventListener("resize", i);
1019
+ }, [evaluate, input, onChange]), useEffect(() => {
1020
+ if (disabled) return;
1021
+ const e = (t) => {
1022
+ if (document.activeElement !== inputRef.current && document.activeElement?.tagName !== "BODY")
1023
+ return;
1024
+ const r = t.key;
1025
+ r === "Enter" || r === "=" ? (handleButton("="), t.preventDefault()) : r === "Backspace" ? (handleButton("⌫"), t.preventDefault()) : r === "Escape" || r === "C" || r === "c" ? (handleButton("C"), t.preventDefault()) : (/^[0-9]$/.test(r) || ["/", "*", "-", "+", "."].includes(r)) && (handleButton(r), t.preventDefault());
1066
1026
  };
1067
- }, [i]), useEffect(() => {
1068
- r.current && i();
1069
- }, [e, t, i]), [useCallback(
1070
- (c) => {
1071
- r.current = c, c && i();
1072
- },
1073
- [i]
1074
- ), s, n];
1027
+ return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
1028
+ }, [handleButton, disabled]), useEffect(() => {
1029
+ disabled || inputRef.current?.focus();
1030
+ }, [disabled]);
1031
+ const handleInput = (e) => {
1032
+ const t = e.target.value.replace(/[^\d+\-*/.]/g, "");
1033
+ setInput(t);
1034
+ };
1035
+ return {
1036
+ input,
1037
+ inputRef,
1038
+ handleButton,
1039
+ handleInput
1040
+ };
1075
1041
  }
1076
- const ButtonFloat = forwardRef(
1077
- function e({
1078
- className: t,
1079
- variant: r = "primary",
1080
- size: s = "md",
1081
- side: o = "right",
1082
- offset: n = "1rem",
1083
- ...a
1084
- }, i) {
1085
- const [u, c, x] = useFloatingPosition(
1086
- o,
1087
- n
1088
- ), [b, f] = useState(!1);
1089
- return useEffect(() => {
1090
- f(!0);
1091
- }, []), /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: u, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1092
- "button",
1042
+ const BUTTONS = [
1043
+ ["7", "8", "9", "/"],
1044
+ ["4", "5", "6", "*"],
1045
+ ["1", "2", "3", "-"],
1046
+ ["0", ".", "=", "+"]
1047
+ ], Calculator = forwardRef(
1048
+ ({
1049
+ initialValue: e = "",
1050
+ onChange: t,
1051
+ disabled: r,
1052
+ className: s,
1053
+ "aria-label": n
1054
+ }, o) => {
1055
+ const { input: i, inputRef: a, handleButton: u, handleInput: l } = useCalculator({
1056
+ initialValue: e,
1057
+ disabled: r,
1058
+ onChange: t
1059
+ });
1060
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1061
+ "div",
1093
1062
  {
1094
- ref: i,
1095
- type: a.type || "button",
1096
- className: cn(
1097
- buttonFloatVariants({ variant: r, size: s }),
1098
- x,
1099
- b && "animate-fab-in",
1100
- t
1101
- ),
1102
- style: c,
1103
- ...a
1063
+ ref: o,
1064
+ className: cn(calculatorRootVariants({ disabled: r }), s),
1065
+ "aria-label": n || "Calculator",
1066
+ role: "region",
1067
+ children: [
1068
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1069
+ "input",
1070
+ {
1071
+ ref: a,
1072
+ className: "w-full mb-3 px-3 py-2 rounded border border-[var(--color-neutral)] bg-[var(--color-neutral-soft)] text-right text-xl font-mono focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)]",
1073
+ value: i,
1074
+ onChange: l,
1075
+ disabled: r,
1076
+ inputMode: "decimal",
1077
+ "aria-label": "Calculator input"
1078
+ }
1079
+ ),
1080
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col gap-1 mb-3", children: BUTTONS.map((x, h) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex w-full", children: x.map((f) => f === "⌫" ? /* @__PURE__ */ jsxRuntimeExports.jsx(
1081
+ ButtonIcon,
1082
+ {
1083
+ as: X,
1084
+ variant: "danger-ghost",
1085
+ "aria-label": "Backspace",
1086
+ size: "md",
1087
+ onClick: () => u("⌫"),
1088
+ disabled: r
1089
+ },
1090
+ "backspace"
1091
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
1092
+ CalculatorButton,
1093
+ {
1094
+ variant: f === "=" ? "action" : f === "C" ? "danger" : ["/", "*", "-", "+", "/"].includes(f) ? "operator" : "default",
1095
+ onClick: () => u(f),
1096
+ disabled: r,
1097
+ "aria-label": f,
1098
+ children: f
1099
+ },
1100
+ f
1101
+ )) }, h)) })
1102
+ ]
1104
1103
  }
1105
- ) });
1104
+ );
1106
1105
  }
1107
- ), textVariants = cva("", {
1106
+ );
1107
+ Calculator.displayName = "Calculator";
1108
+ const textVariants = cva("", {
1108
1109
  variants: {
1109
1110
  color: {
1110
1111
  primary: "text-primary",
@@ -1179,16 +1180,16 @@ const ButtonFloat = forwardRef(
1179
1180
  color: t = "ghost",
1180
1181
  hasUnderline: r = !1,
1181
1182
  isCapitalize: s = !1,
1182
- align: o = "left",
1183
- italic: n = !1,
1184
- clamp: a = "none",
1185
- ellipsis: i = !1,
1183
+ align: n = "left",
1184
+ italic: o = !1,
1185
+ clamp: i = "none",
1186
+ ellipsis: a = !1,
1186
1187
  fontSize: u,
1187
- fontWeight: c,
1188
+ fontWeight: l,
1188
1189
  className: x,
1189
- children: b,
1190
+ children: h,
1190
1191
  ...f
1191
- }, w) => {
1192
+ }, p) => {
1192
1193
  const d = [
1193
1194
  "h1",
1194
1195
  "h2",
@@ -1199,29 +1200,29 @@ const ButtonFloat = forwardRef(
1199
1200
  "p",
1200
1201
  "span",
1201
1202
  "label"
1202
- ].includes(e) ? e : "span", v = u ? `text-${u}` : "", p = c ? `font-${c}` : "";
1203
+ ].includes(e) ? e : "span", v = u ? `text-${u}` : "", w = l ? `font-${l}` : "";
1203
1204
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
1204
1205
  e,
1205
1206
  {
1206
- ref: w,
1207
+ ref: p,
1207
1208
  className: cn(
1208
1209
  textVariants({
1209
1210
  color: t,
1210
1211
  hasUnderline: r,
1211
1212
  isCapitalize: s,
1212
- align: o,
1213
- italic: n,
1214
- clamp: a,
1215
- ellipsis: i,
1213
+ align: n,
1214
+ italic: o,
1215
+ clamp: i,
1216
+ ellipsis: a,
1216
1217
  // @ts-expect-error - `as` is not a valid variant
1217
1218
  as: d
1218
1219
  }),
1219
1220
  v,
1220
- p,
1221
+ w,
1221
1222
  x
1222
1223
  ),
1223
1224
  ...f,
1224
- children: b
1225
+ children: h
1225
1226
  }
1226
1227
  );
1227
1228
  }
@@ -1268,9 +1269,9 @@ const CalendarHeader = () => {
1268
1269
  ] })
1269
1270
  ] });
1270
1271
  }, CalendarWeekdays = () => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-7 px-4 text-ghost-500 mb-3", children: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((e) => /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { fontSize: "xs", color: "ghost", align: "center", children: e }, e)) }), CalendarDaysSingle = () => {
1271
- const e = useCalendarContext(), { year: t, month: r, value: s, onChange: o, setMonth: n, setYear: a } = e, i = (g, m) => new Date(g, m + 1, 0).getDate(), c = ((g, m) => new Date(g, m, 1).getDay())(t, r), x = i(t, r), b = r - 1 < 0 ? 11 : r - 1, f = r === 0 ? t - 1 : t, w = i(t, b), y = r === 11 ? 0 : r + 1, d = r === 11 ? t + 1 : t, v = [];
1272
- for (let g = 0; g < c; g++) {
1273
- const m = w - c + g + 1;
1272
+ const e = useCalendarContext(), { year: t, month: r, value: s, onChange: n, setMonth: o, setYear: i } = e, a = (g, m) => new Date(g, m + 1, 0).getDate(), l = ((g, m) => new Date(g, m, 1).getDay())(t, r), x = a(t, r), h = r - 1 < 0 ? 11 : r - 1, f = r === 0 ? t - 1 : t, p = a(t, h), y = r === 11 ? 0 : r + 1, d = r === 11 ? t + 1 : t, v = [];
1273
+ for (let g = 0; g < l; g++) {
1274
+ const m = p - l + g + 1;
1274
1275
  v.push(
1275
1276
  /* @__PURE__ */ jsxRuntimeExports.jsx(
1276
1277
  ButtonIcon,
@@ -1280,7 +1281,7 @@ const CalendarHeader = () => {
1280
1281
  "aria-label": "Previous month day",
1281
1282
  variant: "ghost",
1282
1283
  onClick: () => {
1283
- o?.(new Date(f, b, m)), n(b), a(f);
1284
+ n?.(new Date(f, h, m)), o(h), i(f);
1284
1285
  }
1285
1286
  },
1286
1287
  "prev-" + g
@@ -1308,15 +1309,15 @@ const CalendarHeader = () => {
1308
1309
  "aria-label": `Select ${t}-${r + 1}-${g}`,
1309
1310
  "aria-current": m ? "date" : void 0,
1310
1311
  onClick: () => {
1311
- o?.(new Date(t, r, g));
1312
+ n?.(new Date(t, r, g));
1312
1313
  }
1313
1314
  },
1314
1315
  g
1315
1316
  )
1316
1317
  );
1317
1318
  }
1318
- const p = c + x;
1319
- for (let g = 0; g < (p % 7 === 0 ? 0 : 7 - p % 7); g++)
1319
+ const w = l + x;
1320
+ for (let g = 0; g < (w % 7 === 0 ? 0 : 7 - w % 7); g++)
1320
1321
  v.push(
1321
1322
  /* @__PURE__ */ jsxRuntimeExports.jsx(
1322
1323
  ButtonIcon,
@@ -1326,7 +1327,7 @@ const CalendarHeader = () => {
1326
1327
  "aria-label": "Next month day",
1327
1328
  variant: "ghost",
1328
1329
  onClick: () => {
1329
- o?.(new Date(d, y, g + 1)), n(y), a(d);
1330
+ n?.(new Date(d, y, g + 1)), o(y), i(d);
1330
1331
  }
1331
1332
  },
1332
1333
  "next-" + g
@@ -1334,35 +1335,35 @@ const CalendarHeader = () => {
1334
1335
  );
1335
1336
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-7 gap-2 px-4 pb-4", children: v });
1336
1337
  }, CalendarDaysRange = () => {
1337
- const { year: e, month: t, value: r, onChange: s, setMonth: o, setYear: n } = useCalendarContext(), a = (l, h) => new Date(l, h + 1, 0).getDate(), u = ((l, h) => new Date(l, h, 1).getDay())(e, t), c = a(e, t), x = t - 1 < 0 ? 11 : t - 1, b = t === 0 ? e - 1 : e, f = a(e, x), w = t === 11 ? 0 : t + 1, y = t === 11 ? e + 1 : e, d = [], v = () => {
1338
+ const { year: e, month: t, value: r, onChange: s, setMonth: n, setYear: o } = useCalendarContext(), i = (c, b) => new Date(c, b + 1, 0).getDate(), u = ((c, b) => new Date(c, b, 1).getDay())(e, t), l = i(e, t), x = t - 1 < 0 ? 11 : t - 1, h = t === 0 ? e - 1 : e, f = i(e, x), p = t === 11 ? 0 : t + 1, y = t === 11 ? e + 1 : e, d = [], v = () => {
1338
1339
  if (!Array.isArray(r)) return [null, null];
1339
- const [l, h] = r;
1340
- return !l && !h ? [null, null] : l && h ? l <= h ? [l, h] : [h, l] : [l, h];
1341
- }, [p, g] = v(), m = (l) => {
1342
- if (!p || !g) return !1;
1343
- const h = new Date(e, t, l);
1344
- return h >= p && h <= g;
1345
- }, N = (l) => p ? p.getFullYear() === e && p.getMonth() === t && p.getDate() === l : !1, T = (l) => g ? g.getFullYear() === e && g.getMonth() === t && g.getDate() === l : !1;
1346
- for (let l = 0; l < u; l++) {
1347
- const h = f - u + l + 1;
1340
+ const [c, b] = r;
1341
+ return !c && !b ? [null, null] : c && b ? c <= b ? [c, b] : [b, c] : [c, b];
1342
+ }, [w, g] = v(), m = (c) => {
1343
+ if (!w || !g) return !1;
1344
+ const b = new Date(e, t, c);
1345
+ return b >= w && b <= g;
1346
+ }, I = (c) => w ? w.getFullYear() === e && w.getMonth() === t && w.getDate() === c : !1, N = (c) => g ? g.getFullYear() === e && g.getMonth() === t && g.getDate() === c : !1;
1347
+ for (let c = 0; c < u; c++) {
1348
+ const b = f - u + c + 1;
1348
1349
  d.push(
1349
1350
  /* @__PURE__ */ jsxRuntimeExports.jsx(
1350
1351
  ButtonIcon,
1351
1352
  {
1352
- as: () => /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { as: "span", fontSize: "sm", color: "tertiary", children: h }),
1353
+ as: () => /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { as: "span", fontSize: "sm", color: "tertiary", children: b }),
1353
1354
  size: "sm",
1354
1355
  "aria-label": "Previous month day",
1355
1356
  variant: "ghost",
1356
1357
  onClick: () => {
1357
- s?.([null, null]), o(x), n(b);
1358
+ s?.([null, null]), n(x), o(h);
1358
1359
  }
1359
1360
  },
1360
- "prev-" + l
1361
+ "prev-" + c
1361
1362
  )
1362
1363
  );
1363
1364
  }
1364
- for (let l = 1; l <= c; l++) {
1365
- const h = m(l), C = N(l), E = T(l);
1365
+ for (let c = 1; c <= l; c++) {
1366
+ const b = m(c), C = I(c), E = N(c);
1366
1367
  d.push(
1367
1368
  /* @__PURE__ */ jsxRuntimeExports.jsx(
1368
1369
  ButtonIcon,
@@ -1372,47 +1373,47 @@ const CalendarHeader = () => {
1372
1373
  {
1373
1374
  as: "span",
1374
1375
  fontSize: "sm",
1375
- color: h || C || E ? "inherit" : "ghost",
1376
+ color: b || C || E ? "inherit" : "ghost",
1376
1377
  className: cn(
1377
- h && " bg-primary text-white",
1378
+ b && " bg-primary text-white",
1378
1379
  C && "rounded-l-full bg-primary text-white",
1379
1380
  E && "rounded-r-full bg-primary text-white"
1380
1381
  ),
1381
- children: l
1382
+ children: c
1382
1383
  }
1383
1384
  ),
1384
- variant: C || E || h ? "primary" : "ghost",
1385
+ variant: C || E || b ? "primary" : "ghost",
1385
1386
  size: "sm",
1386
- "aria-label": `Select ${e}-${t + 1}-${l}`,
1387
+ "aria-label": `Select ${e}-${t + 1}-${c}`,
1387
1388
  "aria-current": C || E ? "date" : void 0,
1388
1389
  onClick: () => {
1389
1390
  if (!Array.isArray(r) || !r[0] || r[0] && r[1])
1390
- s?.([new Date(e, t, l), null]);
1391
+ s?.([new Date(e, t, c), null]);
1391
1392
  else if (r[0] && !r[1]) {
1392
- const j = r[0], R = new Date(e, t, l);
1393
+ const j = r[0], R = new Date(e, t, c);
1393
1394
  j.getTime() === R.getTime() ? s?.([j, R]) : s?.(j < R ? [j, R] : [R, j]);
1394
1395
  }
1395
1396
  }
1396
1397
  },
1397
- l
1398
+ c
1398
1399
  )
1399
1400
  );
1400
1401
  }
1401
- const S = u + c;
1402
- for (let l = 0; l < (S % 7 === 0 ? 0 : 7 - S % 7); l++)
1402
+ const S = u + l;
1403
+ for (let c = 0; c < (S % 7 === 0 ? 0 : 7 - S % 7); c++)
1403
1404
  d.push(
1404
1405
  /* @__PURE__ */ jsxRuntimeExports.jsx(
1405
1406
  ButtonIcon,
1406
1407
  {
1407
- as: () => /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { as: "span", fontSize: "sm", color: "tertiary", children: l + 1 }),
1408
+ as: () => /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { as: "span", fontSize: "sm", color: "tertiary", children: c + 1 }),
1408
1409
  size: "sm",
1409
1410
  "aria-label": "Next month day",
1410
1411
  variant: "ghost",
1411
1412
  onClick: () => {
1412
- s?.([null, null]), o(w), n(y);
1413
+ s?.([null, null]), n(p), o(y);
1413
1414
  }
1414
1415
  },
1415
- "next-" + l
1416
+ "next-" + c
1416
1417
  )
1417
1418
  );
1418
1419
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-7 gap-2 px-4 pb-4", children: d });
@@ -1425,35 +1426,35 @@ function useCalendar({
1425
1426
  type: t,
1426
1427
  onChange: r,
1427
1428
  initialYear: s,
1428
- initialMonth: o
1429
+ initialMonth: n
1429
1430
  }) {
1430
- const [n, a] = useState(o), [i, u] = useState(s), [c, x] = useState([
1431
+ const [o, i] = useState(n), [a, u] = useState(s), [l, x] = useState([
1431
1432
  null,
1432
1433
  null
1433
1434
  ]);
1434
- let b = e;
1435
- t === "range" && !e && (b = c);
1435
+ let h = e;
1436
+ t === "range" && !e && (h = l);
1436
1437
  const f = useCallback(() => {
1437
- const d = n === 0 ? 11 : n - 1, v = n === 0 ? i - 1 : i;
1438
- a(d), u(v), t === "single" && r?.(new Date(v, d, 1));
1439
- }, [n, i, t, r]), w = useCallback(() => {
1440
- const d = n === 11 ? 0 : n + 1, v = n === 11 ? i + 1 : i;
1441
- a(d), u(v), t === "single" && r?.(new Date(v, d, 1));
1442
- }, [n, i, t, r]), y = useCallback(
1438
+ const d = o === 0 ? 11 : o - 1, v = o === 0 ? a - 1 : a;
1439
+ i(d), u(v), t === "single" && r?.(new Date(v, d, 1));
1440
+ }, [o, a, t, r]), p = useCallback(() => {
1441
+ const d = o === 11 ? 0 : o + 1, v = o === 11 ? a + 1 : a;
1442
+ i(d), u(v), t === "single" && r?.(new Date(v, d, 1));
1443
+ }, [o, a, t, r]), y = useCallback(
1443
1444
  (d) => {
1444
1445
  t === "single" ? r?.(d) : t === "range" && (x(d), r?.(d));
1445
1446
  },
1446
1447
  [t, r]
1447
1448
  );
1448
1449
  return {
1449
- year: i,
1450
- month: n,
1451
- value: b,
1452
- setMonth: a,
1450
+ year: a,
1451
+ month: o,
1452
+ value: h,
1453
+ setMonth: i,
1453
1454
  setYear: u,
1454
1455
  onChange: y,
1455
1456
  handlePrevMonth: f,
1456
- handleNextMonth: w
1457
+ handleNextMonth: p
1457
1458
  };
1458
1459
  }
1459
1460
  const CalendarRoot = ({
@@ -1461,79 +1462,35 @@ const CalendarRoot = ({
1461
1462
  onChange: t,
1462
1463
  className: r,
1463
1464
  type: s = "single",
1464
- ...o
1465
+ ...n
1465
1466
  }) => {
1466
- const n = /* @__PURE__ */ new Date(), a = useCalendar({
1467
+ const o = /* @__PURE__ */ new Date(), i = useCalendar({
1467
1468
  value: e,
1468
1469
  onChange: t,
1469
1470
  type: s,
1470
- initialYear: n.getFullYear(),
1471
- initialMonth: n.getMonth()
1471
+ initialYear: o.getFullYear(),
1472
+ initialMonth: o.getMonth()
1472
1473
  });
1473
1474
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
1474
1475
  CalendarContext.Provider,
1475
1476
  {
1476
1477
  value: {
1477
- year: a.year,
1478
- month: a.month,
1479
- value: a.value,
1478
+ year: i.year,
1479
+ month: i.month,
1480
+ value: i.value,
1480
1481
  type: s,
1481
- setMonth: a.setMonth,
1482
- setYear: a.setYear,
1483
- onChange: a.onChange
1482
+ setMonth: i.setMonth,
1483
+ setYear: i.setYear,
1484
+ onChange: i.onChange
1484
1485
  },
1485
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn("select-none", r), ...o, children: [
1486
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn("select-none", r), ...n, children: [
1486
1487
  /* @__PURE__ */ jsxRuntimeExports.jsx(CalendarHeader, {}),
1487
1488
  /* @__PURE__ */ jsxRuntimeExports.jsx(CalendarWeekdays, {}),
1488
1489
  /* @__PURE__ */ jsxRuntimeExports.jsx(CalendarDays, {})
1489
1490
  ] })
1490
1491
  }
1491
1492
  );
1492
- }, Calendar = Object.assign(CalendarRoot, {}), snackbarVariants = cva(
1493
- "flex items-center gap-2 px-4 py-2 rounded-sm w-fit relative shadow-sm",
1494
- {
1495
- variants: {
1496
- color: {
1497
- success: "text-success-bold bg-success-soft border-l-4 border-success",
1498
- info: "text-info-bold bg-info-soft border-l-4 border-info",
1499
- warning: "text-warning-bold bg-warning-soft border-l-4 border-warning",
1500
- danger: "text-danger-bold bg-danger-soft border-l-4 border-danger"
1501
- }
1502
- },
1503
- defaultVariants: {
1504
- color: "success"
1505
- }
1506
- }
1507
- ), SnackbarText = ({
1508
- children: e,
1509
- ...t
1510
- }) => /* @__PURE__ */ jsxRuntimeExports.jsx(
1511
- "span",
1512
- {
1513
- className: "flex-1 truncate text-sm",
1514
- "data-testid": "snackbar-text",
1515
- ...t,
1516
- children: e
1517
- }
1518
- ), SnackbarAction = ({
1519
- children: e,
1520
- ...t
1521
- }) => /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-2", "data-testid": "snackbar-action", ...t, children: e }), Snackbar = forwardRef(
1522
- ({ children: e, action: t, color: r, className: s, ...o }, n) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
1523
- "div",
1524
- {
1525
- ref: n,
1526
- role: "status",
1527
- "aria-live": "polite",
1528
- className: cn(snackbarVariants({ color: r }), s),
1529
- ...o,
1530
- children: [
1531
- /* @__PURE__ */ jsxRuntimeExports.jsx(SnackbarText, { children: e }),
1532
- t && /* @__PURE__ */ jsxRuntimeExports.jsx(SnackbarAction, { children: t })
1533
- ]
1534
- }
1535
- )
1536
- ), TableContext = createContext(null), TableProvider = TableContext.Provider;
1493
+ }, Calendar = Object.assign(CalendarRoot, {}), TableContext = createContext(null), TableProvider = TableContext.Provider;
1537
1494
  function useTableContext() {
1538
1495
  const e = useContext(TableContext);
1539
1496
  if (!e)
@@ -1604,7 +1561,7 @@ const getTableColumnClass = (e) => {
1604
1561
  }
1605
1562
  }, TableHeader = forwardRef(
1606
1563
  ({ children: e, className: t, ...r }, s) => {
1607
- const { maxColumns: o } = useTableContext();
1564
+ const { maxColumns: n } = useTableContext();
1608
1565
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
1609
1566
  "div",
1610
1567
  {
@@ -1616,7 +1573,7 @@ const getTableColumnClass = (e) => {
1616
1573
  "div",
1617
1574
  {
1618
1575
  role: "row",
1619
- className: cn("grid gap-4", getTableColumnClass(o)),
1576
+ className: cn("grid gap-4", getTableColumnClass(n)),
1620
1577
  children: e
1621
1578
  }
1622
1579
  )
@@ -1627,7 +1584,7 @@ const getTableColumnClass = (e) => {
1627
1584
  ({ children: e, className: t, ...r }, s) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { role: "rowgroup", ref: s, className: cn(t), ...r, children: e })
1628
1585
  ), TableFooter = forwardRef(
1629
1586
  ({ children: e, className: t, ...r }, s) => {
1630
- const { maxColumns: o } = useTableContext();
1587
+ const { maxColumns: n } = useTableContext();
1631
1588
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
1632
1589
  "div",
1633
1590
  {
@@ -1639,7 +1596,7 @@ const getTableColumnClass = (e) => {
1639
1596
  "div",
1640
1597
  {
1641
1598
  role: "row",
1642
- className: cn("grid gap-4", getTableColumnClass(o)),
1599
+ className: cn("grid gap-4", getTableColumnClass(n)),
1643
1600
  children: e
1644
1601
  }
1645
1602
  )
@@ -1648,14 +1605,14 @@ const getTableColumnClass = (e) => {
1648
1605
  }
1649
1606
  ), TableRow = forwardRef(
1650
1607
  ({ children: e, className: t, ...r }, s) => {
1651
- const { maxColumns: o } = useTableContext();
1608
+ const { maxColumns: n } = useTableContext();
1652
1609
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
1653
1610
  "div",
1654
1611
  {
1655
1612
  role: "row",
1656
1613
  className: cn(
1657
1614
  "grid gap-4",
1658
- getTableColumnClass(o),
1615
+ getTableColumnClass(n),
1659
1616
  "border-b border-border last:border-0",
1660
1617
  t
1661
1618
  ),
@@ -1666,36 +1623,36 @@ const getTableColumnClass = (e) => {
1666
1623
  );
1667
1624
  }
1668
1625
  ), TableColumn = forwardRef(
1669
- ({ as: e = "td", span: t, align: r = "left", children: s, className: o, ...n }, a) => {
1670
- const i = e === "th" ? "columnheader" : "cell";
1626
+ ({ as: e = "td", span: t, align: r = "left", children: s, className: n, ...o }, i) => {
1627
+ const a = e === "th" ? "columnheader" : "cell";
1671
1628
  let u = "text-left";
1672
1629
  return r === "center" ? u = "text-center" : r === "right" && (u = "text-right"), /* @__PURE__ */ jsxRuntimeExports.jsx(
1673
1630
  "div",
1674
1631
  {
1675
- ref: a,
1676
- role: i,
1632
+ ref: i,
1633
+ role: a,
1677
1634
  className: cn(
1678
1635
  "px-4 py-2",
1679
1636
  "[&:not(:last-child)]:border-r [&:not(:last-child)]:border-border",
1680
1637
  getRowSpanClass(t),
1681
1638
  u,
1682
- o
1639
+ n
1683
1640
  ),
1684
- ...n,
1641
+ ...o,
1685
1642
  children: s
1686
1643
  }
1687
1644
  );
1688
1645
  }
1689
1646
  ), TableRoot = forwardRef(
1690
- ({ children: e, className: t, maxColumns: r = 12, ...s }, o) => {
1691
- const n = useMemo(
1647
+ ({ children: e, className: t, maxColumns: r = 12, ...s }, n) => {
1648
+ const o = useMemo(
1692
1649
  () => ({ maxColumns: r }),
1693
1650
  [r]
1694
1651
  );
1695
- return /* @__PURE__ */ jsxRuntimeExports.jsx(TableProvider, { value: n, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1652
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(TableProvider, { value: o, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1696
1653
  "div",
1697
1654
  {
1698
- ref: o,
1655
+ ref: n,
1699
1656
  role: "table",
1700
1657
  className: cn(
1701
1658
  "w-full overflow-x-auto rounded-lg border border-border",
@@ -1748,21 +1705,257 @@ const getTableColumnClass = (e) => {
1748
1705
  }
1749
1706
  }
1750
1707
  ), Tile = forwardRef(
1751
- ({ variant: e = "white", size: t = "md", shape: r = "rounded", className: s, ...o }, n) => /* @__PURE__ */ jsxRuntimeExports.jsx(
1708
+ ({ variant: e = "white", size: t = "md", shape: r = "rounded", className: s, ...n }, o) => /* @__PURE__ */ jsxRuntimeExports.jsx(
1752
1709
  "div",
1753
1710
  {
1754
- ref: n,
1711
+ ref: o,
1755
1712
  className: cn(tileVariants({ variant: e, size: t, shape: r }), s),
1756
- ...o
1713
+ ...n
1757
1714
  }
1758
1715
  )
1759
1716
  );
1717
+ function getColSpan(e = 4) {
1718
+ switch (e) {
1719
+ case 1:
1720
+ return "col-span-1";
1721
+ case 2:
1722
+ return "col-span-2";
1723
+ case 3:
1724
+ return "col-span-3";
1725
+ case 4:
1726
+ return "col-span-4";
1727
+ case 5:
1728
+ return "col-span-5";
1729
+ case 6:
1730
+ return "col-span-6";
1731
+ case 7:
1732
+ return "col-span-7";
1733
+ case 8:
1734
+ return "col-span-8";
1735
+ case 9:
1736
+ return "col-span-9";
1737
+ case 10:
1738
+ return "col-span-10";
1739
+ case 11:
1740
+ return "col-span-11";
1741
+ case 12:
1742
+ return "col-span-12";
1743
+ default:
1744
+ return "col-span-4";
1745
+ }
1746
+ }
1747
+ const DescriptionListItem = forwardRef(function e({ children: t, className: r, span: s = 4, ...n }, o) {
1748
+ const i = getColSpan(s);
1749
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: o, className: cn(i, r), ...n, children: t });
1750
+ }), DescriptionListTerm = forwardRef(function e({ children: t, ...r }, s) {
1751
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("dt", { ref: s, ...r, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { as: "span", fontSize: "sm", fontWeight: "medium", color: "gray", children: t }) });
1752
+ }), DescriptionListDetails = forwardRef(function e({ children: t, color: r = "black", ...s }, n) {
1753
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("dd", { ref: n, ...s, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { as: "span", fontSize: "base", fontWeight: "medium", color: r, children: t }) });
1754
+ }), DescriptionListRoot = forwardRef(
1755
+ function e({ children: t, className: r, ...s }, n) {
1756
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
1757
+ "dl",
1758
+ {
1759
+ ref: n,
1760
+ className: cn("grid grid-cols-12 gap-y-4", r),
1761
+ ...s,
1762
+ children: t
1763
+ }
1764
+ );
1765
+ }
1766
+ ), DescriptionList = Object.assign(DescriptionListRoot, {
1767
+ Item: DescriptionListItem,
1768
+ Term: DescriptionListTerm,
1769
+ Details: DescriptionListDetails
1770
+ });
1771
+ function useImage({ src: e }) {
1772
+ const [t, r] = useState(!1), [s, n] = useState(!1), o = useRef(!1), i = () => {
1773
+ r(!0);
1774
+ }, a = () => {
1775
+ n(!0);
1776
+ };
1777
+ return useEffect(() => {
1778
+ if (!e) return;
1779
+ const u = new Image();
1780
+ return u.src = e, u.onload = () => {
1781
+ o.current || r(!0);
1782
+ }, u.onerror = () => {
1783
+ o.current || n(!0);
1784
+ }, () => {
1785
+ o.current = !0;
1786
+ };
1787
+ }, [e]), {
1788
+ loaded: t,
1789
+ errored: s,
1790
+ handleLoad: i,
1791
+ handleError: a
1792
+ };
1793
+ }
1794
+ const imageVariants = cva("block object-cover", {
1795
+ variants: {
1796
+ position: {
1797
+ cover: "object-cover",
1798
+ contain: "object-contain",
1799
+ center: "object-center",
1800
+ top: "object-top",
1801
+ bottom: "object-bottom",
1802
+ left: "object-left",
1803
+ right: "object-right",
1804
+ none: ""
1805
+ },
1806
+ size: {
1807
+ sm: "w-16 h-16",
1808
+ md: "w-32 h-32",
1809
+ lg: "w-48 h-48",
1810
+ full: "w-full h-full",
1811
+ auto: ""
1812
+ },
1813
+ shape: {
1814
+ rectangle: "rounded",
1815
+ square: "aspect-square rounded",
1816
+ circle: "rounded-full aspect-square"
1817
+ }
1818
+ },
1819
+ defaultVariants: {
1820
+ position: "cover",
1821
+ size: "auto",
1822
+ shape: "rectangle"
1823
+ }
1824
+ }), imageAtomVariants = cva(
1825
+ "flex items-center justify-center bg-neutral-soft text-ghost border border-border",
1826
+ {
1827
+ variants: {
1828
+ shape: {
1829
+ rectangle: "rounded",
1830
+ square: "aspect-square rounded",
1831
+ circle: "rounded-full aspect-square"
1832
+ },
1833
+ size: {
1834
+ sm: "w-16 h-16",
1835
+ md: "w-32 h-32",
1836
+ lg: "w-48 h-48",
1837
+ full: "w-full h-full",
1838
+ auto: "w-full h-full"
1839
+ }
1840
+ },
1841
+ defaultVariants: {
1842
+ shape: "rectangle",
1843
+ size: "auto"
1844
+ }
1845
+ }
1846
+ );
1847
+ function BaseImageSkeleton({
1848
+ className: e,
1849
+ shape: t,
1850
+ size: r,
1851
+ height: s,
1852
+ width: n
1853
+ }) {
1854
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
1855
+ Skeleton,
1856
+ {
1857
+ className: cn(imageAtomVariants({ shape: t, size: r }), e),
1858
+ style: { height: s, width: n }
1859
+ }
1860
+ );
1861
+ }
1862
+ function BaseImageFallback({
1863
+ alt: e,
1864
+ width: t,
1865
+ height: r,
1866
+ className: s,
1867
+ style: n,
1868
+ shape: o,
1869
+ size: i
1870
+ }) {
1871
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1872
+ "div",
1873
+ {
1874
+ className: imageAtomVariants({ shape: o, size: i, className: s }),
1875
+ style: { width: t, height: r, ...n },
1876
+ "aria-label": e,
1877
+ role: "img",
1878
+ children: [
1879
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1880
+ ImageOff,
1881
+ {
1882
+ size: 32,
1883
+ style: { opacity: 0.5, marginRight: 4 },
1884
+ "aria-hidden": "true"
1885
+ }
1886
+ ),
1887
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { opacity: 0.7 }, children: e })
1888
+ ]
1889
+ }
1890
+ );
1891
+ }
1892
+ const BaseImage = forwardRef(
1893
+ ({
1894
+ src: e,
1895
+ alt: t,
1896
+ onLoad: r,
1897
+ onError: s,
1898
+ width: n,
1899
+ height: o,
1900
+ loading: i = "lazy",
1901
+ position: a = "cover",
1902
+ size: u = "auto",
1903
+ shape: l,
1904
+ className: x,
1905
+ ...h
1906
+ }, f) => {
1907
+ const { loaded: p, errored: y, handleLoad: d, handleError: v } = useImage({
1908
+ src: e
1909
+ }), w = typeof n == "number" ? n : Number(n), g = typeof o == "number" ? o : Number(o);
1910
+ return !p && !y ? /* @__PURE__ */ jsxRuntimeExports.jsx(
1911
+ BaseImageSkeleton,
1912
+ {
1913
+ shape: l,
1914
+ width: w,
1915
+ height: g
1916
+ }
1917
+ ) : y ? /* @__PURE__ */ jsxRuntimeExports.jsx(
1918
+ BaseImageFallback,
1919
+ {
1920
+ shape: l,
1921
+ alt: t,
1922
+ width: w,
1923
+ height: g
1924
+ }
1925
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
1926
+ "img",
1927
+ {
1928
+ ref: f,
1929
+ src: e,
1930
+ alt: t,
1931
+ width: w,
1932
+ height: g,
1933
+ loading: i,
1934
+ className: cn(
1935
+ imageVariants({
1936
+ position: a,
1937
+ size: u,
1938
+ shape: l
1939
+ }),
1940
+ x
1941
+ ),
1942
+ onLoad: (m) => {
1943
+ d(), r?.(m);
1944
+ },
1945
+ onError: (m) => {
1946
+ v(), s?.(m);
1947
+ },
1948
+ ...h
1949
+ }
1950
+ );
1951
+ }
1952
+ ), ImageCircle = forwardRef((e, t) => /* @__PURE__ */ jsxRuntimeExports.jsx(BaseImage, { ref: t, ...e, shape: "circle" })), ImageSquare = forwardRef((e, t) => /* @__PURE__ */ jsxRuntimeExports.jsx(BaseImage, { ref: t, ...e, shape: "square" })), ImageRectangle = forwardRef((e, t) => /* @__PURE__ */ jsxRuntimeExports.jsx(BaseImage, { ref: t, ...e, shape: "rectangle" }));
1760
1953
  export {
1761
1954
  Alert as A,
1762
1955
  Badge as B,
1763
1956
  Calculator as C,
1957
+ DescriptionList as D,
1764
1958
  Icon as I,
1765
- Snackbar as S,
1766
1959
  Table as T,
1767
1960
  Anchor as a,
1768
1961
  Avatar as b,
@@ -1772,5 +1965,9 @@ export {
1772
1965
  ButtonIcon as f,
1773
1966
  Calendar as g,
1774
1967
  Text as h,
1775
- Tile as i
1968
+ Tile as i,
1969
+ ImageCircle as j,
1970
+ ImageSquare as k,
1971
+ ImageRectangle as l,
1972
+ BaseImage as m
1776
1973
  };