@neuronection/assistant-ui 0.7.0 → 0.8.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 (56) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +1 -0
  3. package/dist/ai-button.d.ts +8 -0
  4. package/dist/ai-button.js +1 -1
  5. package/dist/ai-magic-fill.js +1 -1
  6. package/dist/{chunk-TKKHWO6C.js → chunk-2YQSA5AE.js} +3 -3
  7. package/dist/{chunk-TKKHWO6C.js.map → chunk-2YQSA5AE.js.map} +1 -1
  8. package/dist/{chunk-XHHEAJHN.js → chunk-3RDFWXX6.js} +3 -3
  9. package/dist/{chunk-XHHEAJHN.js.map → chunk-3RDFWXX6.js.map} +1 -1
  10. package/dist/{chunk-L56KGPGS.js → chunk-3VCFRIIK.js} +16 -4
  11. package/dist/chunk-3VCFRIIK.js.map +1 -0
  12. package/dist/{chunk-2EPZAT3X.js → chunk-62GIJMWT.js} +3 -3
  13. package/dist/{chunk-2EPZAT3X.js.map → chunk-62GIJMWT.js.map} +1 -1
  14. package/dist/{chunk-UU2V5FGF.js → chunk-6VCJX4CP.js} +3 -3
  15. package/dist/{chunk-UU2V5FGF.js.map → chunk-6VCJX4CP.js.map} +1 -1
  16. package/dist/{chunk-I2RXO6ZU.js → chunk-EODV6JK7.js} +3 -3
  17. package/dist/{chunk-I2RXO6ZU.js.map → chunk-EODV6JK7.js.map} +1 -1
  18. package/dist/chunk-ERK53RFJ.js +463 -0
  19. package/dist/chunk-ERK53RFJ.js.map +1 -0
  20. package/dist/{chunk-BWPNEQ3T.js → chunk-G6557MEN.js} +3 -3
  21. package/dist/{chunk-BWPNEQ3T.js.map → chunk-G6557MEN.js.map} +1 -1
  22. package/dist/chunk-KLWKZSYM.js +3 -0
  23. package/dist/chunk-KLWKZSYM.js.map +1 -0
  24. package/dist/{chunk-FE26R5RN.js → chunk-OPTH3VUY.js} +3 -3
  25. package/dist/{chunk-FE26R5RN.js.map → chunk-OPTH3VUY.js.map} +1 -1
  26. package/dist/{chunk-5AVBKEDQ.js → chunk-PFAH25VU.js} +3 -3
  27. package/dist/{chunk-5AVBKEDQ.js.map → chunk-PFAH25VU.js.map} +1 -1
  28. package/dist/chunk-TJLELOAW.js +163 -0
  29. package/dist/chunk-TJLELOAW.js.map +1 -0
  30. package/dist/{chunk-W2HORE44.js → chunk-TN35RR2R.js} +3 -3
  31. package/dist/{chunk-W2HORE44.js.map → chunk-TN35RR2R.js.map} +1 -1
  32. package/dist/{chunk-SXVOJ7WE.js → chunk-Y7BKBG57.js} +3 -3
  33. package/dist/{chunk-SXVOJ7WE.js.map → chunk-Y7BKBG57.js.map} +1 -1
  34. package/dist/{chunk-75QQR2VT.js → chunk-YMCMUAIF.js} +3 -3
  35. package/dist/{chunk-75QQR2VT.js.map → chunk-YMCMUAIF.js.map} +1 -1
  36. package/dist/combobox.js +1 -1
  37. package/dist/confirmation-modal.js +1 -1
  38. package/dist/date-picker.js +1 -1
  39. package/dist/form-modal.js +1 -1
  40. package/dist/index.d.ts +2 -0
  41. package/dist/index.js +16 -14
  42. package/dist/index.js.map +1 -1
  43. package/dist/modal.js +2 -2
  44. package/dist/model-picker.js +1 -1
  45. package/dist/range-bar.js +1 -1
  46. package/dist/styles.css +1 -1
  47. package/dist/task-assignment-picker.js +1 -1
  48. package/dist/time-list.d.ts +30 -0
  49. package/dist/time-list.js +3 -0
  50. package/dist/time-list.js.map +1 -0
  51. package/dist/time-picker.d.ts +39 -0
  52. package/dist/time-picker.js +3 -0
  53. package/dist/time-picker.js.map +1 -0
  54. package/dist/wizard.js +1 -1
  55. package/package.json +9 -1
  56. package/dist/chunk-L56KGPGS.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/ai-magic-fill/AiMagicFill.tsx"],"names":[],"mappings":";;;;;;AAqBO,SAAS,WAAA,CAAY;AAAA,EAC1B,IAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,IAAA,GAAO,KAAA;AAAA,EACP,KAAA;AAAA,EACA,KAAA,GAAQ,YAAA;AAAA,EACR,QAAA,GAAW,4BAAA;AAAA,EACX,WAAA;AAAA,EACA,WAAA,GAAc,kBAAA;AAAA,EACd,WAAA,GAAc,8BAAA;AAAA,EACd,WAAA;AAAA,EACA,WAAA,GAAc,QAAA;AAAA,EACd;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAU,eAAS,EAAE,CAAA;AAE7C,EAAA,MAAM,SAAS,MAAM;AACnB,IAAA,MAAM,OAAA,GAAU,OAAO,IAAA,EAAK;AAC5B,IAAA,IAAI,CAAC,WAAW,IAAA,EAAM;AACtB,IAAA,QAAA,CAAS,OAAO,CAAA;AAChB,IAAA,SAAA,CAAU,EAAE,CAAA;AAAA,EACd,CAAA;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,YAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAA,EAAa,QAAA;AAAA,MACb,IAAA,EAAM,QAAA;AAAA,MACN,WAAA,EAAa,WAAA,IAAe,CAAA,MAAA,EAAS,KAAK,CAAA,CAAA;AAAA,MAC1C,WAAA;AAAA,MACA,UAAA,EAAY,IAAA;AAAA,MACZ,cAAA,EAAgB,CAAC,MAAA,CAAO,IAAA,EAAK;AAAA,MAC7B,QAAA,EAAU,MAAA;AAAA,MACV,gBAAA,EAAkB,SAAA;AAAA,MAElB,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAQ,eAAA,EAAgB,WAAU,qBAAA,EACrC,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,uBAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAQ,sBAAA;AAAA,cACR,SAAA,EAAU,6EAAA;AAAA,cAET,QAAA,EAAA;AAAA;AAAA,WACH;AAAA,0BACA,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,EAAA,EAAG,sBAAA;AAAA,cACH,IAAA,EAAM,CAAA;AAAA,cACN,KAAA,EAAO,MAAA;AAAA,cACP,UAAU,CAAC,KAAA,KACT,SAAA,CAAU,KAAA,CAAM,OAAO,KAAK,CAAA;AAAA,cAE9B,WAAA;AAAA,cACA,SAAA,EAAU;AAAA;AAAA;AACZ,SAAA,EACF,CAAA;AAAA,QACC,8BACC,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,4MAAA,EACV,uBACH,CAAA,GACE,IAAA;AAAA,QACH,KAAA,uBACE,GAAA,EAAA,EAAE,IAAA,EAAK,SAAQ,SAAA,EAAU,+CAAA,EACvB,iBACH,CAAA,GACE;AAAA,OAAA,EACN;AAAA;AAAA,GACF;AAEJ","file":"chunk-I2RXO6ZU.js","sourcesContent":["import * as React from 'react'\nimport { Sparkles } from 'lucide-react'\nimport { FormModal } from '../form-modal/FormModal'\nimport { Textarea } from '../textarea/Textarea'\n\nexport interface AiMagicFillProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n onSubmit: (prompt: string) => void\n busy?: boolean\n error?: string | null\n title?: string\n subtitle?: string\n description?: string\n promptLabel?: string\n placeholder?: string\n submitLabel?: string\n cancelLabel?: string\n className?: string\n}\n\nexport function AiMagicFill({\n open,\n onOpenChange,\n onSubmit,\n busy = false,\n error,\n title = 'Magic Fill',\n subtitle = 'AI-powered data extraction',\n description,\n promptLabel = 'Describe details',\n placeholder = 'Describe the data here…',\n submitLabel,\n cancelLabel = 'Cancel',\n className,\n}: AiMagicFillProps) {\n const [prompt, setPrompt] = React.useState('')\n\n const submit = () => {\n const trimmed = prompt.trim()\n if (!trimmed || busy) return\n onSubmit(trimmed)\n setPrompt('')\n }\n\n return (\n <FormModal\n open={open}\n onOpenChange={onOpenChange}\n title={title}\n description={subtitle}\n icon={Sparkles}\n submitLabel={submitLabel ?? `Apply ${title}`}\n cancelLabel={cancelLabel}\n submitting={busy}\n submitDisabled={!prompt.trim()}\n onSubmit={submit}\n contentClassName={className}\n >\n <div data-as=\"ai-magic-fill\" className=\"flex flex-col gap-4\">\n <div className=\"flex flex-col gap-1.5\">\n <label\n htmlFor=\"ai-magic-fill-prompt\"\n className=\"text-[11px] font-bold uppercase tracking-[0.18em] text-[var(--as-muted-fg)]\"\n >\n {promptLabel}\n </label>\n <Textarea\n id=\"ai-magic-fill-prompt\"\n rows={5}\n value={prompt}\n onChange={(event: React.ChangeEvent<HTMLTextAreaElement>) =>\n setPrompt(event.target.value)\n }\n placeholder={placeholder}\n className=\"resize-none leading-relaxed\"\n />\n </div>\n {description ? (\n <p className=\"rounded-[var(--as-radius)] border border-[color-mix(in_srgb,var(--as-ai)_25%,transparent)] bg-[color-mix(in_srgb,var(--as-ai)_8%,transparent)] p-3 text-xs font-medium leading-relaxed text-[var(--as-fg)]\">\n {description}\n </p>\n ) : null}\n {error ? (\n <p role=\"alert\" className=\"text-xs font-semibold text-[var(--as-danger)]\">\n {error}\n </p>\n ) : null}\n </div>\n </FormModal>\n )\n}\n"]}
1
+ {"version":3,"sources":["../src/components/ai-magic-fill/AiMagicFill.tsx"],"names":[],"mappings":";;;;;;AAqBO,SAAS,WAAA,CAAY;AAAA,EAC1B,IAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,IAAA,GAAO,KAAA;AAAA,EACP,KAAA;AAAA,EACA,KAAA,GAAQ,YAAA;AAAA,EACR,QAAA,GAAW,4BAAA;AAAA,EACX,WAAA;AAAA,EACA,WAAA,GAAc,kBAAA;AAAA,EACd,WAAA,GAAc,8BAAA;AAAA,EACd,WAAA;AAAA,EACA,WAAA,GAAc,QAAA;AAAA,EACd;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAU,eAAS,EAAE,CAAA;AAE7C,EAAA,MAAM,SAAS,MAAM;AACnB,IAAA,MAAM,OAAA,GAAU,OAAO,IAAA,EAAK;AAC5B,IAAA,IAAI,CAAC,WAAW,IAAA,EAAM;AACtB,IAAA,QAAA,CAAS,OAAO,CAAA;AAChB,IAAA,SAAA,CAAU,EAAE,CAAA;AAAA,EACd,CAAA;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,YAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAA,EAAa,QAAA;AAAA,MACb,IAAA,EAAM,QAAA;AAAA,MACN,WAAA,EAAa,WAAA,IAAe,CAAA,MAAA,EAAS,KAAK,CAAA,CAAA;AAAA,MAC1C,WAAA;AAAA,MACA,UAAA,EAAY,IAAA;AAAA,MACZ,cAAA,EAAgB,CAAC,MAAA,CAAO,IAAA,EAAK;AAAA,MAC7B,QAAA,EAAU,MAAA;AAAA,MACV,gBAAA,EAAkB,SAAA;AAAA,MAElB,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAQ,eAAA,EAAgB,WAAU,qBAAA,EACrC,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,uBAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAQ,sBAAA;AAAA,cACR,SAAA,EAAU,6EAAA;AAAA,cAET,QAAA,EAAA;AAAA;AAAA,WACH;AAAA,0BACA,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,EAAA,EAAG,sBAAA;AAAA,cACH,IAAA,EAAM,CAAA;AAAA,cACN,KAAA,EAAO,MAAA;AAAA,cACP,UAAU,CAAC,KAAA,KACT,SAAA,CAAU,KAAA,CAAM,OAAO,KAAK,CAAA;AAAA,cAE9B,WAAA;AAAA,cACA,SAAA,EAAU;AAAA;AAAA;AACZ,SAAA,EACF,CAAA;AAAA,QACC,8BACC,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,4MAAA,EACV,uBACH,CAAA,GACE,IAAA;AAAA,QACH,KAAA,uBACE,GAAA,EAAA,EAAE,IAAA,EAAK,SAAQ,SAAA,EAAU,+CAAA,EACvB,iBACH,CAAA,GACE;AAAA,OAAA,EACN;AAAA;AAAA,GACF;AAEJ","file":"chunk-EODV6JK7.js","sourcesContent":["import * as React from 'react'\nimport { Sparkles } from 'lucide-react'\nimport { FormModal } from '../form-modal/FormModal'\nimport { Textarea } from '../textarea/Textarea'\n\nexport interface AiMagicFillProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n onSubmit: (prompt: string) => void\n busy?: boolean\n error?: string | null\n title?: string\n subtitle?: string\n description?: string\n promptLabel?: string\n placeholder?: string\n submitLabel?: string\n cancelLabel?: string\n className?: string\n}\n\nexport function AiMagicFill({\n open,\n onOpenChange,\n onSubmit,\n busy = false,\n error,\n title = 'Magic Fill',\n subtitle = 'AI-powered data extraction',\n description,\n promptLabel = 'Describe details',\n placeholder = 'Describe the data here…',\n submitLabel,\n cancelLabel = 'Cancel',\n className,\n}: AiMagicFillProps) {\n const [prompt, setPrompt] = React.useState('')\n\n const submit = () => {\n const trimmed = prompt.trim()\n if (!trimmed || busy) return\n onSubmit(trimmed)\n setPrompt('')\n }\n\n return (\n <FormModal\n open={open}\n onOpenChange={onOpenChange}\n title={title}\n description={subtitle}\n icon={Sparkles}\n submitLabel={submitLabel ?? `Apply ${title}`}\n cancelLabel={cancelLabel}\n submitting={busy}\n submitDisabled={!prompt.trim()}\n onSubmit={submit}\n contentClassName={className}\n >\n <div data-as=\"ai-magic-fill\" className=\"flex flex-col gap-4\">\n <div className=\"flex flex-col gap-1.5\">\n <label\n htmlFor=\"ai-magic-fill-prompt\"\n className=\"text-[11px] font-bold uppercase tracking-[0.18em] text-[var(--as-muted-fg)]\"\n >\n {promptLabel}\n </label>\n <Textarea\n id=\"ai-magic-fill-prompt\"\n rows={5}\n value={prompt}\n onChange={(event: React.ChangeEvent<HTMLTextAreaElement>) =>\n setPrompt(event.target.value)\n }\n placeholder={placeholder}\n className=\"resize-none leading-relaxed\"\n />\n </div>\n {description ? (\n <p className=\"rounded-[var(--as-radius)] border border-[color-mix(in_srgb,var(--as-ai)_25%,transparent)] bg-[color-mix(in_srgb,var(--as-ai)_8%,transparent)] p-3 text-xs font-medium leading-relaxed text-[var(--as-fg)]\">\n {description}\n </p>\n ) : null}\n {error ? (\n <p role=\"alert\" className=\"text-xs font-semibold text-[var(--as-danger)]\">\n {error}\n </p>\n ) : null}\n </div>\n </FormModal>\n )\n}\n"]}
@@ -0,0 +1,463 @@
1
+ import { Popover, PopoverTrigger, PopoverContent } from './chunk-SIIY2EGI.js';
2
+ import { cn } from './chunk-BLJWR4ZV.js';
3
+ import * as React from 'react';
4
+ import { Clock, Check } from 'lucide-react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function parse24(value) {
8
+ if (!value) return null;
9
+ const m = /^(\d{1,2}):(\d{1,2})$/.exec(value.trim());
10
+ if (!m) return null;
11
+ const h = parseInt(m[1], 10);
12
+ const min = parseInt(m[2], 10);
13
+ if (Number.isNaN(h) || Number.isNaN(min) || h < 0 || h > 23 || min < 0 || min > 59) return null;
14
+ return { hour24: h, minute: min };
15
+ }
16
+ function to24(hour12, period) {
17
+ if (period === "AM") return hour12 === 12 ? 0 : hour12;
18
+ return hour12 === 12 ? 12 : hour12 + 12;
19
+ }
20
+ function from24(hour24) {
21
+ if (hour24 === 0) return { hour12: 12, period: "AM" };
22
+ if (hour24 === 12) return { hour12: 12, period: "PM" };
23
+ if (hour24 < 12) return { hour12: hour24, period: "AM" };
24
+ return { hour12: hour24 - 12, period: "PM" };
25
+ }
26
+ function format12(hour24, minute) {
27
+ const { hour12, period } = from24(hour24);
28
+ const mm = minute.toString().padStart(2, "0");
29
+ return `${hour12}:${mm} ${period}`;
30
+ }
31
+ function format24(hour24, minute) {
32
+ return `${hour24.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}`;
33
+ }
34
+ var ClockFace = ({
35
+ mode,
36
+ hour12,
37
+ minute,
38
+ size,
39
+ onPickHour,
40
+ onPickMinute
41
+ }) => {
42
+ const cx = size / 2;
43
+ const cy = size / 2;
44
+ const radius = size / 2 - 22;
45
+ const ticks = mode === "hours" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
46
+ const selectedValue = mode === "hours" ? hour12 : minute;
47
+ const angleFor = React.useCallback(
48
+ (val) => {
49
+ if (mode === "hours") {
50
+ return val / 12 * 360 - 90;
51
+ }
52
+ return val / 60 * 360 - 90;
53
+ },
54
+ [mode]
55
+ );
56
+ const pointFor = React.useCallback(
57
+ (val, r) => {
58
+ const rad = angleFor(val) * Math.PI / 180;
59
+ return { x: cx + r * Math.cos(rad), y: cy + r * Math.sin(rad) };
60
+ },
61
+ [angleFor, cx, cy]
62
+ );
63
+ const handTarget = pointFor(selectedValue, radius - 22);
64
+ const labelPoint = (val) => pointFor(val, radius);
65
+ const handleClick = (e) => {
66
+ const svg = e.currentTarget;
67
+ const rect = svg.getBoundingClientRect();
68
+ const x = e.clientX - rect.left - cx;
69
+ const y = e.clientY - rect.top - cy;
70
+ let deg = Math.atan2(y, x) * 180 / Math.PI + 90;
71
+ if (deg < 0) deg += 360;
72
+ if (mode === "hours") {
73
+ const h = Math.round(deg / 30) || 12;
74
+ onPickHour(h);
75
+ } else {
76
+ const m = (Math.round(deg / 30) || 12) * 5;
77
+ onPickMinute(m === 60 ? 0 : m);
78
+ }
79
+ };
80
+ const handleKeyDown = (e) => {
81
+ if (mode === "hours") {
82
+ if (e.key === "ArrowRight" || e.key === "ArrowUp") {
83
+ e.preventDefault();
84
+ onPickHour(hour12 >= 12 ? 1 : hour12 + 1);
85
+ } else if (e.key === "ArrowLeft" || e.key === "ArrowDown") {
86
+ e.preventDefault();
87
+ onPickHour(hour12 <= 1 ? 12 : hour12 - 1);
88
+ }
89
+ } else {
90
+ if (e.key === "ArrowRight" || e.key === "ArrowUp") {
91
+ e.preventDefault();
92
+ onPickMinute(minute >= 55 ? 0 : minute + 5);
93
+ } else if (e.key === "ArrowLeft" || e.key === "ArrowDown") {
94
+ e.preventDefault();
95
+ onPickMinute(minute <= 0 ? 55 : minute - 5);
96
+ }
97
+ }
98
+ };
99
+ return /* @__PURE__ */ jsxs(
100
+ "svg",
101
+ {
102
+ width: size,
103
+ height: size,
104
+ viewBox: `0 0 ${size} ${size}`,
105
+ onClick: handleClick,
106
+ onKeyDown: handleKeyDown,
107
+ tabIndex: 0,
108
+ role: "slider",
109
+ "aria-label": mode === "hours" ? "Hour" : "Minute",
110
+ "aria-valuemin": mode === "hours" ? 1 : 0,
111
+ "aria-valuemax": mode === "hours" ? 12 : 59,
112
+ "aria-valuenow": selectedValue,
113
+ className: "cursor-pointer rounded-full outline-none focus-visible:ring-2 focus-visible:ring-[var(--as-focus-ring)]",
114
+ children: [
115
+ /* @__PURE__ */ jsx("circle", { cx, cy, r: radius + 4, className: "fill-[var(--as-muted)] stroke-[var(--as-border)]", strokeWidth: 1 }),
116
+ ticks.map((val) => {
117
+ const p = labelPoint(val);
118
+ const isSelected = val === selectedValue;
119
+ return /* @__PURE__ */ jsxs("g", { children: [
120
+ /* @__PURE__ */ jsx(
121
+ "circle",
122
+ {
123
+ cx: p.x,
124
+ cy: p.y,
125
+ r: isSelected ? 17 : 15,
126
+ className: cn(
127
+ "transition-all",
128
+ isSelected ? "fill-[var(--as-primary)]" : "fill-[var(--as-surface-raised)] stroke-[var(--as-border)]"
129
+ ),
130
+ strokeWidth: 1
131
+ }
132
+ ),
133
+ /* @__PURE__ */ jsx(
134
+ "text",
135
+ {
136
+ x: p.x,
137
+ y: p.y,
138
+ textAnchor: "middle",
139
+ dominantBaseline: "central",
140
+ className: cn(
141
+ "font-medium",
142
+ isSelected ? "fill-[var(--as-primary-fg)] font-bold" : "fill-[var(--as-fg)]"
143
+ ),
144
+ style: { fontSize: 13, userSelect: "none" },
145
+ children: val.toString().padStart(2, "0")
146
+ }
147
+ )
148
+ ] }, val);
149
+ }),
150
+ /* @__PURE__ */ jsx(
151
+ "line",
152
+ {
153
+ x1: cx,
154
+ y1: cy,
155
+ x2: handTarget.x,
156
+ y2: handTarget.y,
157
+ className: "stroke-[var(--as-primary)]",
158
+ strokeWidth: 2,
159
+ strokeLinecap: "round"
160
+ }
161
+ ),
162
+ /* @__PURE__ */ jsx("circle", { cx, cy, r: 5, className: "fill-[var(--as-primary)]" })
163
+ ]
164
+ }
165
+ );
166
+ };
167
+ var TimeInput = ({
168
+ value,
169
+ min,
170
+ max,
171
+ active,
172
+ onChange,
173
+ onFocus,
174
+ onConvertFrom24,
175
+ ariaLabel
176
+ }) => {
177
+ const pad = (n) => n.toString().padStart(2, "0");
178
+ const [text, setText] = React.useState(pad(value));
179
+ const [focused, setFocused] = React.useState(false);
180
+ React.useEffect(() => {
181
+ if (!focused) setText(pad(value));
182
+ }, [value, focused]);
183
+ const commit = (raw) => {
184
+ const digits = raw.replace(/\D/g, "");
185
+ if (digits === "") {
186
+ setText(pad(value));
187
+ return;
188
+ }
189
+ const n = parseInt(digits, 10);
190
+ if (Number.isNaN(n)) {
191
+ setText(pad(value));
192
+ return;
193
+ }
194
+ if (onConvertFrom24 && (n > max || n === 0)) {
195
+ onConvertFrom24(n);
196
+ return;
197
+ }
198
+ const clamped = Math.max(min, Math.min(max, n));
199
+ onChange(clamped);
200
+ setText(pad(clamped));
201
+ };
202
+ return /* @__PURE__ */ jsx(
203
+ "input",
204
+ {
205
+ type: "text",
206
+ inputMode: "numeric",
207
+ pattern: "[0-9]*",
208
+ maxLength: 2,
209
+ value: text,
210
+ "aria-label": ariaLabel,
211
+ onFocus: () => {
212
+ setFocused(true);
213
+ onFocus();
214
+ requestAnimationFrame(() => {
215
+ const el = document.activeElement;
216
+ if (el) el.select();
217
+ });
218
+ },
219
+ onBlur: () => {
220
+ setFocused(false);
221
+ commit(text);
222
+ },
223
+ onChange: (e) => setText(e.target.value.replace(/\D/g, "").slice(0, 2)),
224
+ onKeyDown: (e) => {
225
+ if (e.key === "Enter") {
226
+ e.preventDefault();
227
+ e.target.blur();
228
+ } else if (e.key === "ArrowUp") {
229
+ e.preventDefault();
230
+ const next = value >= max ? min : value + 1;
231
+ onChange(next);
232
+ } else if (e.key === "ArrowDown") {
233
+ e.preventDefault();
234
+ const next = value <= min ? max : value - 1;
235
+ onChange(next);
236
+ }
237
+ },
238
+ className: cn(
239
+ "h-10 w-12 rounded-[var(--as-radius-sm)] bg-transparent text-center text-2xl font-bold tabular-nums outline-none transition-colors",
240
+ active ? "bg-[color-mix(in_srgb,var(--as-primary)_12%,transparent)] text-[var(--as-primary)]" : "text-[var(--as-fg)] hover:bg-[var(--as-muted)]"
241
+ )
242
+ }
243
+ );
244
+ };
245
+ var TimePickerContent = ({
246
+ value,
247
+ onChange,
248
+ onDone,
249
+ size = 240,
250
+ hourLabel = "Hour",
251
+ minuteLabel = "Minute",
252
+ doneLabel = "Done",
253
+ className
254
+ }) => {
255
+ const seedRef = React.useRef(null);
256
+ if (seedRef.current === null) {
257
+ const p = parse24(value);
258
+ if (p) {
259
+ seedRef.current = { h24: p.hour24, min: p.minute };
260
+ } else {
261
+ const now = /* @__PURE__ */ new Date();
262
+ seedRef.current = { h24: now.getHours(), min: now.getMinutes() };
263
+ }
264
+ }
265
+ const seed = seedRef.current;
266
+ const [hour12, setHour12] = React.useState(() => from24(seed.h24).hour12);
267
+ const [minute, setMinute] = React.useState(seed.min);
268
+ const [period, setPeriod] = React.useState(() => from24(seed.h24).period);
269
+ const [mode, setMode] = React.useState("hours");
270
+ const commit = React.useCallback(
271
+ (h12, min, p) => {
272
+ onChange(format24(to24(h12, p), min));
273
+ },
274
+ [onChange]
275
+ );
276
+ const pickHour = (h) => {
277
+ setHour12(h);
278
+ commit(h, minute, period);
279
+ };
280
+ const pickMinute = (m) => {
281
+ setMinute(m);
282
+ commit(hour12, m, period);
283
+ };
284
+ const togglePeriod = (p) => {
285
+ if (p === period) return;
286
+ setPeriod(p);
287
+ commit(hour12, minute, p);
288
+ };
289
+ return /* @__PURE__ */ jsxs(
290
+ "div",
291
+ {
292
+ "data-as": "time-picker-content",
293
+ className: cn("flex flex-col gap-2 p-4", className),
294
+ children: [
295
+ /* @__PURE__ */ jsxs("div", { className: "mb-1 flex select-none items-center justify-center gap-2", children: [
296
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 rounded-[var(--as-radius)] bg-[var(--as-muted)] px-1 py-0.5", children: [
297
+ /* @__PURE__ */ jsx(
298
+ TimeInput,
299
+ {
300
+ value: hour12,
301
+ min: 1,
302
+ max: 12,
303
+ active: mode === "hours",
304
+ ariaLabel: hourLabel,
305
+ onChange: (h) => {
306
+ setHour12(h);
307
+ commit(h, minute, period);
308
+ },
309
+ onConvertFrom24: (n24) => {
310
+ const f = from24(n24);
311
+ setHour12(f.hour12);
312
+ setPeriod(f.period);
313
+ commit(f.hour12, minute, f.period);
314
+ },
315
+ onFocus: () => setMode("hours")
316
+ }
317
+ ),
318
+ /* @__PURE__ */ jsx("span", { className: "px-0.5 text-2xl font-bold text-[var(--as-muted-fg)]", children: ":" }),
319
+ /* @__PURE__ */ jsx(
320
+ TimeInput,
321
+ {
322
+ value: minute,
323
+ min: 0,
324
+ max: 59,
325
+ active: mode === "minutes",
326
+ ariaLabel: minuteLabel,
327
+ onChange: (m) => {
328
+ setMinute(m);
329
+ commit(hour12, m, period);
330
+ },
331
+ onFocus: () => setMode("minutes")
332
+ }
333
+ )
334
+ ] }),
335
+ /* @__PURE__ */ jsx("div", { className: "flex overflow-hidden rounded-[var(--as-radius)] border border-[var(--as-border)]", children: ["AM", "PM"].map((p) => /* @__PURE__ */ jsx(
336
+ "button",
337
+ {
338
+ type: "button",
339
+ onClick: () => togglePeriod(p),
340
+ "aria-pressed": period === p,
341
+ className: cn(
342
+ "cursor-pointer px-3 py-1.5 text-xs font-bold uppercase tracking-widest transition-colors",
343
+ period === p ? "bg-[var(--as-primary)] text-[var(--as-primary-fg)]" : "bg-[var(--as-surface)] text-[var(--as-muted-fg)] hover:bg-[var(--as-muted)]"
344
+ ),
345
+ children: p
346
+ },
347
+ p
348
+ )) })
349
+ ] }),
350
+ /* @__PURE__ */ jsx("p", { className: "mb-1 text-center text-[10px] font-bold uppercase tracking-widest text-[var(--as-muted-fg)]", children: mode === "hours" ? hourLabel : minuteLabel }),
351
+ /* @__PURE__ */ jsx("div", { className: "mb-2 flex justify-center", children: /* @__PURE__ */ jsx(
352
+ ClockFace,
353
+ {
354
+ mode,
355
+ hour12,
356
+ minute,
357
+ size,
358
+ onPickHour: pickHour,
359
+ onPickMinute: pickMinute
360
+ }
361
+ ) }),
362
+ /* @__PURE__ */ jsx("div", { className: "flex justify-end border-t border-[var(--as-border)] pt-2", children: /* @__PURE__ */ jsxs(
363
+ "button",
364
+ {
365
+ type: "button",
366
+ onClick: onDone,
367
+ className: "flex cursor-pointer items-center gap-1.5 rounded-[var(--as-radius)] bg-[var(--as-primary)] px-4 py-2 text-xs font-bold text-[var(--as-primary-fg)] transition-[filter] hover:brightness-110",
368
+ children: [
369
+ /* @__PURE__ */ jsx(Check, { className: "size-3.5", "aria-hidden": true }),
370
+ doneLabel
371
+ ]
372
+ }
373
+ ) })
374
+ ]
375
+ }
376
+ );
377
+ };
378
+ var TimePicker = React.forwardRef(
379
+ function TimePicker2({
380
+ value,
381
+ onChange,
382
+ className,
383
+ placeholder = "Select time",
384
+ disabled = false,
385
+ id,
386
+ size = 240,
387
+ label,
388
+ hourLabel,
389
+ minuteLabel,
390
+ doneLabel,
391
+ variant = "default"
392
+ }, ref) {
393
+ const [open, setOpen] = React.useState(false);
394
+ const parsed = parse24(value);
395
+ const display = parsed ? format12(parsed.hour24, parsed.minute) : null;
396
+ return /* @__PURE__ */ jsxs(
397
+ "div",
398
+ {
399
+ ref,
400
+ "data-as": "time-picker",
401
+ className: cn(!className?.includes("w-") && "w-full", "flex flex-col", className),
402
+ children: [
403
+ label ? /* @__PURE__ */ jsx("label", { className: "mb-1.5 ml-1 block text-[10px] font-bold uppercase tracking-widest text-[var(--as-muted-fg)]", children: label }) : null,
404
+ /* @__PURE__ */ jsxs(Popover, { open: open && !disabled, onOpenChange: setOpen, children: [
405
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxs(
406
+ "button",
407
+ {
408
+ type: "button",
409
+ "aria-label": label ?? "Choose time",
410
+ className: cn(
411
+ "flex items-center gap-2 text-left text-sm outline-none transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50",
412
+ !className?.includes("w-") && "w-full",
413
+ variant === "default" && "rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] px-3 py-2.5 hover:border-[var(--as-primary)]"
414
+ ),
415
+ children: [
416
+ variant === "default" ? /* @__PURE__ */ jsx(Clock, { className: "size-4 shrink-0 text-[var(--as-muted-fg)]", "aria-hidden": true }) : null,
417
+ /* @__PURE__ */ jsx(
418
+ "span",
419
+ {
420
+ className: cn(
421
+ "flex-1 truncate",
422
+ !parsed && (variant === "default" ? "text-[var(--as-muted-fg)]" : "opacity-70"),
423
+ parsed && variant === "default" && "font-medium text-[var(--as-fg)]"
424
+ ),
425
+ children: display ?? placeholder
426
+ }
427
+ )
428
+ ]
429
+ }
430
+ ) }),
431
+ /* @__PURE__ */ jsx(
432
+ PopoverContent,
433
+ {
434
+ align: "start",
435
+ sideOffset: 4,
436
+ collisionPadding: 8,
437
+ "aria-label": label ?? "Choose time",
438
+ className: "w-[300px] p-0",
439
+ children: /* @__PURE__ */ jsx(
440
+ TimePickerContent,
441
+ {
442
+ value,
443
+ onChange,
444
+ onDone: () => setOpen(false),
445
+ size,
446
+ hourLabel,
447
+ minuteLabel,
448
+ doneLabel
449
+ }
450
+ )
451
+ }
452
+ )
453
+ ] }),
454
+ /* @__PURE__ */ jsx("input", { type: "hidden", value: value ?? "", id, name: id })
455
+ ]
456
+ }
457
+ );
458
+ }
459
+ );
460
+
461
+ export { TimePicker, TimePickerContent };
462
+ //# sourceMappingURL=chunk-ERK53RFJ.js.map
463
+ //# sourceMappingURL=chunk-ERK53RFJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/time-picker/TimePicker.tsx"],"names":["TimePicker","ClockIcon"],"mappings":"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","file":"chunk-ERK53RFJ.js","sourcesContent":["import * as React from 'react'\nimport { Check, Clock as ClockIcon } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport { Popover, PopoverContent, PopoverTrigger } from '../popover'\n\ntype ViewMode = 'hours' | 'minutes'\n\nexport interface TimePickerProps {\n /** 24-hour `HH:MM` string, or null/undefined when empty. */\n value: string | null | undefined\n /** Fired with a 24-hour `HH:MM` string. */\n onChange: (value: string) => void\n className?: string\n placeholder?: string\n disabled?: boolean\n id?: string\n /** Diameter of the clock face in px (default 240). */\n size?: number\n /** Accessible name for the trigger (also an optional visible label). */\n label?: string\n hourLabel?: string\n minuteLabel?: string\n doneLabel?: string\n variant?: 'default' | 'unstyled'\n}\n\ninterface Hms {\n hour24: number\n minute: number\n}\n\nfunction parse24(value: string | null | undefined): Hms | null {\n if (!value) return null\n const m = /^(\\d{1,2}):(\\d{1,2})$/.exec(value.trim())\n if (!m) return null\n const h = parseInt(m[1]!, 10)\n const min = parseInt(m[2]!, 10)\n if (Number.isNaN(h) || Number.isNaN(min) || h < 0 || h > 23 || min < 0 || min > 59) return null\n return { hour24: h, minute: min }\n}\n\nfunction to24(hour12: number, period: 'AM' | 'PM'): number {\n if (period === 'AM') return hour12 === 12 ? 0 : hour12\n return hour12 === 12 ? 12 : hour12 + 12\n}\n\nfunction from24(hour24: number): { hour12: number; period: 'AM' | 'PM' } {\n if (hour24 === 0) return { hour12: 12, period: 'AM' }\n if (hour24 === 12) return { hour12: 12, period: 'PM' }\n if (hour24 < 12) return { hour12: hour24, period: 'AM' }\n return { hour12: hour24 - 12, period: 'PM' }\n}\n\nfunction format12(hour24: number, minute: number): string {\n const { hour12, period } = from24(hour24)\n const mm = minute.toString().padStart(2, '0')\n return `${hour12}:${mm} ${period}`\n}\n\nfunction format24(hour24: number, minute: number): string {\n return `${hour24.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`\n}\n\ninterface ClockProps {\n mode: ViewMode\n hour12: number\n minute: number\n size: number\n onPickHour: (h: number) => void\n onPickMinute: (m: number) => void\n}\n\n/**\n * SVG clock face. Hours (1–12) and minutes (0,5,…,55) sit on a ring; the\n * selected tick is highlighted and a hand points to it. Click anywhere on the\n * face to snap to the nearest tick of the active mode.\n */\nconst ClockFace: React.FC<ClockProps> = ({\n mode,\n hour12,\n minute,\n size,\n onPickHour,\n onPickMinute,\n}) => {\n const cx = size / 2\n const cy = size / 2\n const radius = size / 2 - 22\n\n const ticks =\n mode === 'hours'\n ? Array.from({ length: 12 }, (_, i) => i + 1)\n : Array.from({ length: 12 }, (_, i) => i * 5)\n\n const selectedValue = mode === 'hours' ? hour12 : minute\n\n const angleFor = React.useCallback(\n (val: number) => {\n if (mode === 'hours') {\n return (val / 12) * 360 - 90\n }\n return (val / 60) * 360 - 90\n },\n [mode],\n )\n\n const pointFor = React.useCallback(\n (val: number, r: number) => {\n const rad = (angleFor(val) * Math.PI) / 180\n return { x: cx + r * Math.cos(rad), y: cy + r * Math.sin(rad) }\n },\n [angleFor, cx, cy],\n )\n\n const handTarget = pointFor(selectedValue, radius - 22)\n const labelPoint = (val: number) => pointFor(val, radius)\n\n const handleClick = (e: React.MouseEvent<SVGSVGElement>) => {\n const svg = e.currentTarget\n const rect = svg.getBoundingClientRect()\n const x = e.clientX - rect.left - cx\n const y = e.clientY - rect.top - cy\n let deg = (Math.atan2(y, x) * 180) / Math.PI + 90\n if (deg < 0) deg += 360\n if (mode === 'hours') {\n const h = Math.round(deg / 30) || 12\n onPickHour(h)\n } else {\n const m = (Math.round(deg / 30) || 12) * 5\n onPickMinute(m === 60 ? 0 : m)\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<SVGSVGElement>) => {\n if (mode === 'hours') {\n if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {\n e.preventDefault()\n onPickHour(hour12 >= 12 ? 1 : hour12 + 1)\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {\n e.preventDefault()\n onPickHour(hour12 <= 1 ? 12 : hour12 - 1)\n }\n } else {\n if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {\n e.preventDefault()\n onPickMinute(minute >= 55 ? 0 : minute + 5)\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {\n e.preventDefault()\n onPickMinute(minute <= 0 ? 55 : minute - 5)\n }\n }\n }\n\n return (\n <svg\n width={size}\n height={size}\n viewBox={`0 0 ${size} ${size}`}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n tabIndex={0}\n role=\"slider\"\n aria-label={mode === 'hours' ? 'Hour' : 'Minute'}\n aria-valuemin={mode === 'hours' ? 1 : 0}\n aria-valuemax={mode === 'hours' ? 12 : 59}\n aria-valuenow={selectedValue}\n className=\"cursor-pointer rounded-full outline-none focus-visible:ring-2 focus-visible:ring-[var(--as-focus-ring)]\"\n >\n <circle cx={cx} cy={cy} r={radius + 4} className=\"fill-[var(--as-muted)] stroke-[var(--as-border)]\" strokeWidth={1} />\n\n {ticks.map((val) => {\n const p = labelPoint(val)\n const isSelected = val === selectedValue\n return (\n <g key={val}>\n <circle\n cx={p.x}\n cy={p.y}\n r={isSelected ? 17 : 15}\n className={cn(\n 'transition-all',\n isSelected\n ? 'fill-[var(--as-primary)]'\n : 'fill-[var(--as-surface-raised)] stroke-[var(--as-border)]',\n )}\n strokeWidth={1}\n />\n <text\n x={p.x}\n y={p.y}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className={cn(\n 'font-medium',\n isSelected ? 'fill-[var(--as-primary-fg)] font-bold' : 'fill-[var(--as-fg)]',\n )}\n style={{ fontSize: 13, userSelect: 'none' }}\n >\n {val.toString().padStart(2, '0')}\n </text>\n </g>\n )\n })}\n\n <line\n x1={cx}\n y1={cy}\n x2={handTarget.x}\n y2={handTarget.y}\n className=\"stroke-[var(--as-primary)]\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n />\n <circle cx={cx} cy={cy} r={5} className=\"fill-[var(--as-primary)]\" />\n </svg>\n )\n}\n\ninterface TimeInputProps {\n value: number\n min: number\n max: number\n active?: boolean\n onChange: (n: number) => void\n onFocus: () => void\n onConvertFrom24?: (n24: number) => void\n ariaLabel?: string\n}\n\n/**\n * A 2-digit, keyboard-editable numeric field. Accepts only digits, clamps on\n * blur/Enter, and supports Arrow Up/Down to step. While focused it holds the\n * raw text; it re-syncs from `value` when not focused.\n */\nconst TimeInput: React.FC<TimeInputProps> = ({\n value,\n min,\n max,\n active,\n onChange,\n onFocus,\n onConvertFrom24,\n ariaLabel,\n}) => {\n const pad = (n: number) => n.toString().padStart(2, '0')\n const [text, setText] = React.useState<string>(pad(value))\n const [focused, setFocused] = React.useState(false)\n\n React.useEffect(() => {\n if (!focused) setText(pad(value))\n }, [value, focused])\n\n const commit = (raw: string) => {\n const digits = raw.replace(/\\D/g, '')\n if (digits === '') {\n setText(pad(value))\n return\n }\n const n = parseInt(digits, 10)\n if (Number.isNaN(n)) {\n setText(pad(value))\n return\n }\n if (onConvertFrom24 && (n > max || n === 0)) {\n onConvertFrom24(n)\n return\n }\n const clamped = Math.max(min, Math.min(max, n))\n onChange(clamped)\n setText(pad(clamped))\n }\n\n return (\n <input\n type=\"text\"\n inputMode=\"numeric\"\n pattern=\"[0-9]*\"\n maxLength={2}\n value={text}\n aria-label={ariaLabel}\n onFocus={() => {\n setFocused(true)\n onFocus()\n requestAnimationFrame(() => {\n const el = document.activeElement as HTMLInputElement | null\n if (el) el.select()\n })\n }}\n onBlur={() => {\n setFocused(false)\n commit(text)\n }}\n onChange={(e) => setText(e.target.value.replace(/\\D/g, '').slice(0, 2))}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n ;(e.target as HTMLInputElement).blur()\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n const next = value >= max ? min : value + 1\n onChange(next)\n } else if (e.key === 'ArrowDown') {\n e.preventDefault()\n const next = value <= min ? max : value - 1\n onChange(next)\n }\n }}\n className={cn(\n 'h-10 w-12 rounded-[var(--as-radius-sm)] bg-transparent text-center text-2xl font-bold tabular-nums outline-none transition-colors',\n active\n ? 'bg-[color-mix(in_srgb,var(--as-primary)_12%,transparent)] text-[var(--as-primary)]'\n : 'text-[var(--as-fg)] hover:bg-[var(--as-muted)]',\n )}\n />\n )\n}\n\nexport interface TimePickerContentProps {\n value: string | null | undefined\n onChange: (value: string) => void\n onDone?: () => void\n size?: number\n hourLabel?: string\n minuteLabel?: string\n doneLabel?: string\n className?: string\n}\n\n/**\n * The popover body: editable HH:MM inputs + AM/PM segmented control + clock\n * face + Done button. Owns a working copy of the time, seeded from `value`\n * once on mount (the parent unmounts it when the popover closes).\n */\nexport const TimePickerContent: React.FC<TimePickerContentProps> = ({\n value,\n onChange,\n onDone,\n size = 240,\n hourLabel = 'Hour',\n minuteLabel = 'Minute',\n doneLabel = 'Done',\n className,\n}) => {\n const seedRef = React.useRef<{ h24: number; min: number } | null>(null)\n if (seedRef.current === null) {\n const p = parse24(value)\n if (p) {\n seedRef.current = { h24: p.hour24, min: p.minute }\n } else {\n const now = new Date()\n seedRef.current = { h24: now.getHours(), min: now.getMinutes() }\n }\n }\n const seed = seedRef.current\n\n const [hour12, setHour12] = React.useState<number>(() => from24(seed.h24).hour12)\n const [minute, setMinute] = React.useState<number>(seed.min)\n const [period, setPeriod] = React.useState<'AM' | 'PM'>(() => from24(seed.h24).period)\n const [mode, setMode] = React.useState<ViewMode>('hours')\n\n const commit = React.useCallback(\n (h12: number, min: number, p: 'AM' | 'PM') => {\n onChange(format24(to24(h12, p), min))\n },\n [onChange],\n )\n\n const pickHour = (h: number) => {\n setHour12(h)\n commit(h, minute, period)\n }\n const pickMinute = (m: number) => {\n setMinute(m)\n commit(hour12, m, period)\n }\n const togglePeriod = (p: 'AM' | 'PM') => {\n if (p === period) return\n setPeriod(p)\n commit(hour12, minute, p)\n }\n\n return (\n <div\n data-as=\"time-picker-content\"\n className={cn('flex flex-col gap-2 p-4', className)}\n >\n <div className=\"mb-1 flex select-none items-center justify-center gap-2\">\n <div className=\"flex items-center gap-0.5 rounded-[var(--as-radius)] bg-[var(--as-muted)] px-1 py-0.5\">\n <TimeInput\n value={hour12}\n min={1}\n max={12}\n active={mode === 'hours'}\n ariaLabel={hourLabel}\n onChange={(h) => {\n setHour12(h)\n commit(h, minute, period)\n }}\n onConvertFrom24={(n24) => {\n const f = from24(n24)\n setHour12(f.hour12)\n setPeriod(f.period)\n commit(f.hour12, minute, f.period)\n }}\n onFocus={() => setMode('hours')}\n />\n <span className=\"px-0.5 text-2xl font-bold text-[var(--as-muted-fg)]\">:</span>\n <TimeInput\n value={minute}\n min={0}\n max={59}\n active={mode === 'minutes'}\n ariaLabel={minuteLabel}\n onChange={(m) => {\n setMinute(m)\n commit(hour12, m, period)\n }}\n onFocus={() => setMode('minutes')}\n />\n </div>\n\n <div className=\"flex overflow-hidden rounded-[var(--as-radius)] border border-[var(--as-border)]\">\n {(['AM', 'PM'] as const).map((p) => (\n <button\n key={p}\n type=\"button\"\n onClick={() => togglePeriod(p)}\n aria-pressed={period === p}\n className={cn(\n 'cursor-pointer px-3 py-1.5 text-xs font-bold uppercase tracking-widest transition-colors',\n period === p\n ? 'bg-[var(--as-primary)] text-[var(--as-primary-fg)]'\n : 'bg-[var(--as-surface)] text-[var(--as-muted-fg)] hover:bg-[var(--as-muted)]',\n )}\n >\n {p}\n </button>\n ))}\n </div>\n </div>\n\n <p className=\"mb-1 text-center text-[10px] font-bold uppercase tracking-widest text-[var(--as-muted-fg)]\">\n {mode === 'hours' ? hourLabel : minuteLabel}\n </p>\n\n <div className=\"mb-2 flex justify-center\">\n <ClockFace\n mode={mode}\n hour12={hour12}\n minute={minute}\n size={size}\n onPickHour={pickHour}\n onPickMinute={pickMinute}\n />\n </div>\n\n <div className=\"flex justify-end border-t border-[var(--as-border)] pt-2\">\n <button\n type=\"button\"\n onClick={onDone}\n className=\"flex cursor-pointer items-center gap-1.5 rounded-[var(--as-radius)] bg-[var(--as-primary)] px-4 py-2 text-xs font-bold text-[var(--as-primary-fg)] transition-[filter] hover:brightness-110\"\n >\n <Check className=\"size-3.5\" aria-hidden />\n {doneLabel}\n </button>\n </div>\n </div>\n )\n}\n\nexport const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>(\n function TimePicker(\n {\n value,\n onChange,\n className,\n placeholder = 'Select time',\n disabled = false,\n id,\n size = 240,\n label,\n hourLabel,\n minuteLabel,\n doneLabel,\n variant = 'default',\n },\n ref,\n ) {\n const [open, setOpen] = React.useState(false)\n\n const parsed = parse24(value)\n const display = parsed ? format12(parsed.hour24, parsed.minute) : null\n\n return (\n <div\n ref={ref}\n data-as=\"time-picker\"\n className={cn(!className?.includes('w-') && 'w-full', 'flex flex-col', className)}\n >\n {label ? (\n <label className=\"mb-1.5 ml-1 block text-[10px] font-bold uppercase tracking-widest text-[var(--as-muted-fg)]\">\n {label}\n </label>\n ) : null}\n <Popover open={open && !disabled} onOpenChange={setOpen}>\n <PopoverTrigger asChild disabled={disabled}>\n <button\n type=\"button\"\n aria-label={label ?? 'Choose time'}\n className={cn(\n 'flex items-center gap-2 text-left text-sm outline-none transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50',\n !className?.includes('w-') && 'w-full',\n variant === 'default' &&\n 'rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] px-3 py-2.5 hover:border-[var(--as-primary)]',\n )}\n >\n {variant === 'default' ? (\n <ClockIcon className=\"size-4 shrink-0 text-[var(--as-muted-fg)]\" aria-hidden />\n ) : null}\n <span\n className={cn(\n 'flex-1 truncate',\n !parsed && (variant === 'default' ? 'text-[var(--as-muted-fg)]' : 'opacity-70'),\n parsed && variant === 'default' && 'font-medium text-[var(--as-fg)]',\n )}\n >\n {display ?? placeholder}\n </span>\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n sideOffset={4}\n collisionPadding={8}\n aria-label={label ?? 'Choose time'}\n className=\"w-[300px] p-0\"\n >\n <TimePickerContent\n value={value}\n onChange={onChange}\n onDone={() => setOpen(false)}\n size={size}\n hourLabel={hourLabel}\n minuteLabel={minuteLabel}\n doneLabel={doneLabel}\n />\n </PopoverContent>\n </Popover>\n\n <input type=\"hidden\" value={value ?? ''} id={id} name={id} />\n </div>\n )\n },\n)\n"]}
@@ -49,7 +49,7 @@ var PanelModal = React.forwardRef(function PanelModal2({
49
49
  "aria-describedby": void 0,
50
50
  className: cn(
51
51
  "as-anim-pop fixed inset-0 z-[var(--as-z-modal)] flex flex-col overflow-y-auto bg-[var(--as-surface-raised)] text-[var(--as-fg)] shadow-[var(--as-shadow-3)] focus:outline-none",
52
- "sm:inset-auto sm:left-1/2 sm:top-1/2 sm:h-auto sm:max-h-[90vh] sm:w-auto sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-[var(--as-radius-lg)] sm:border sm:border-[var(--as-border)]",
52
+ "sm:inset-0 sm:mx-auto sm:my-auto sm:h-fit sm:max-h-[90vh] sm:w-fit sm:rounded-[var(--as-radius-lg)] sm:border sm:border-[var(--as-border)]",
53
53
  panelModalVariants({ size }),
54
54
  className
55
55
  ),
@@ -88,5 +88,5 @@ var PanelModal = React.forwardRef(function PanelModal2({
88
88
  });
89
89
 
90
90
  export { PanelModal };
91
- //# sourceMappingURL=chunk-BWPNEQ3T.js.map
92
- //# sourceMappingURL=chunk-BWPNEQ3T.js.map
91
+ //# sourceMappingURL=chunk-G6557MEN.js.map
92
+ //# sourceMappingURL=chunk-G6557MEN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/modal/PanelModal.tsx"],"names":["PanelModal"],"mappings":"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","file":"chunk-BWPNEQ3T.js","sourcesContent":["import * as React from 'react'\nimport * as DialogPrimitive from '@radix-ui/react-dialog'\nimport { X } from 'lucide-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\n\nconst panelModalVariants = cva('', {\n variants: {\n size: {\n sm: 'sm:max-w-md',\n md: 'sm:max-w-2xl',\n lg: 'sm:max-w-4xl',\n xl: 'sm:max-w-6xl',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n})\n\nexport interface PanelModalProps\n extends Omit<\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>,\n 'title'\n >,\n VariantProps<typeof panelModalVariants> {\n open: boolean\n onOpenChange: (open: boolean) => void\n title?: React.ReactNode\n headerIcon?: React.ReactNode\n headerActions?: React.ReactNode\n footer?: React.ReactNode\n hideHeader?: boolean\n bodyClassName?: string\n closeLabel?: string\n}\n\n/**\n * Dialog panel with a header (icon, title, actions, close), scrollable body\n * and optional sticky footer — full-screen on mobile, centered card on\n * desktop. For plain dialogs prefer the `Modal` parts; for forms prefer\n * `FormModal`.\n */\nexport const PanelModal = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Content>,\n PanelModalProps\n>(function PanelModal(\n {\n open,\n onOpenChange,\n title,\n headerIcon,\n headerActions,\n footer,\n hideHeader = false,\n bodyClassName,\n closeLabel = 'Close',\n size,\n className,\n children,\n ...props\n },\n ref,\n) {\n return (\n <DialogPrimitive.Root open={open} onOpenChange={onOpenChange}>\n <DialogPrimitive.Portal>\n <DialogPrimitive.Overlay\n data-as=\"modal-overlay\"\n className=\"as-anim-fade fixed inset-0 z-[var(--as-z-modal)] bg-[var(--as-overlay)]\"\n />\n <DialogPrimitive.Content\n ref={ref}\n data-as=\"panel-modal\"\n aria-describedby={undefined}\n className={cn(\n 'as-anim-pop fixed inset-0 z-[var(--as-z-modal)] flex flex-col overflow-y-auto bg-[var(--as-surface-raised)] text-[var(--as-fg)] shadow-[var(--as-shadow-3)] focus:outline-none',\n 'sm:inset-auto sm:left-1/2 sm:top-1/2 sm:h-auto sm:max-h-[90vh] sm:w-auto sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-[var(--as-radius-lg)] sm:border sm:border-[var(--as-border)]',\n panelModalVariants({ size }),\n className,\n )}\n {...props}\n >\n {hideHeader ? (\n <DialogPrimitive.Close\n aria-label={closeLabel}\n className=\"absolute right-3 top-3 z-10 rounded-[var(--as-radius-sm)] bg-[var(--as-surface-raised)] p-1.5 text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-secondary)] hover:text-[var(--as-fg)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <X aria-hidden=\"true\" className=\"size-4\" />\n </DialogPrimitive.Close>\n ) : (\n <div className=\"flex shrink-0 items-center justify-between gap-3 border-b border-[var(--as-border)] px-5 py-4 sm:px-6\">\n <div className=\"flex min-w-0 items-center gap-2\">\n {headerIcon}\n {title ? (\n <DialogPrimitive.Title className=\"truncate font-semibold text-[var(--as-fg)]\">\n {title}\n </DialogPrimitive.Title>\n ) : null}\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n {headerActions}\n <DialogPrimitive.Close\n aria-label={closeLabel}\n className=\"rounded-[var(--as-radius-sm)] p-1.5 text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-secondary)] hover:text-[var(--as-fg)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <X aria-hidden=\"true\" className=\"size-5\" />\n </DialogPrimitive.Close>\n </div>\n </div>\n )}\n <div className={cn('min-h-0 flex-1', hideHeader && 'pt-10', bodyClassName ?? 'p-5 sm:p-6')}>\n {children}\n </div>\n {footer ? (\n <div className=\"shrink-0 border-t border-[var(--as-border)] px-5 py-4 sm:px-6\">\n {footer}\n </div>\n ) : null}\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n </DialogPrimitive.Root>\n )\n})\n"]}
1
+ {"version":3,"sources":["../src/components/modal/PanelModal.tsx"],"names":["PanelModal"],"mappings":"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","file":"chunk-G6557MEN.js","sourcesContent":["import * as React from 'react'\nimport * as DialogPrimitive from '@radix-ui/react-dialog'\nimport { X } from 'lucide-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../../lib/utils'\n\nconst panelModalVariants = cva('', {\n variants: {\n size: {\n sm: 'sm:max-w-md',\n md: 'sm:max-w-2xl',\n lg: 'sm:max-w-4xl',\n xl: 'sm:max-w-6xl',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n})\n\nexport interface PanelModalProps\n extends Omit<\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>,\n 'title'\n >,\n VariantProps<typeof panelModalVariants> {\n open: boolean\n onOpenChange: (open: boolean) => void\n title?: React.ReactNode\n headerIcon?: React.ReactNode\n headerActions?: React.ReactNode\n footer?: React.ReactNode\n hideHeader?: boolean\n bodyClassName?: string\n closeLabel?: string\n}\n\n/**\n * Dialog panel with a header (icon, title, actions, close), scrollable body\n * and optional sticky footer — full-screen on mobile, centered card on\n * desktop. For plain dialogs prefer the `Modal` parts; for forms prefer\n * `FormModal`.\n */\nexport const PanelModal = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Content>,\n PanelModalProps\n>(function PanelModal(\n {\n open,\n onOpenChange,\n title,\n headerIcon,\n headerActions,\n footer,\n hideHeader = false,\n bodyClassName,\n closeLabel = 'Close',\n size,\n className,\n children,\n ...props\n },\n ref,\n) {\n return (\n <DialogPrimitive.Root open={open} onOpenChange={onOpenChange}>\n <DialogPrimitive.Portal>\n <DialogPrimitive.Overlay\n data-as=\"modal-overlay\"\n className=\"as-anim-fade fixed inset-0 z-[var(--as-z-modal)] bg-[var(--as-overlay)]\"\n />\n <DialogPrimitive.Content\n ref={ref}\n data-as=\"panel-modal\"\n aria-describedby={undefined}\n className={cn(\n 'as-anim-pop fixed inset-0 z-[var(--as-z-modal)] flex flex-col overflow-y-auto bg-[var(--as-surface-raised)] text-[var(--as-fg)] shadow-[var(--as-shadow-3)] focus:outline-none',\n 'sm:inset-0 sm:mx-auto sm:my-auto sm:h-fit sm:max-h-[90vh] sm:w-fit sm:rounded-[var(--as-radius-lg)] sm:border sm:border-[var(--as-border)]',\n panelModalVariants({ size }),\n className,\n )}\n {...props}\n >\n {hideHeader ? (\n <DialogPrimitive.Close\n aria-label={closeLabel}\n className=\"absolute right-3 top-3 z-10 rounded-[var(--as-radius-sm)] bg-[var(--as-surface-raised)] p-1.5 text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-secondary)] hover:text-[var(--as-fg)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <X aria-hidden=\"true\" className=\"size-4\" />\n </DialogPrimitive.Close>\n ) : (\n <div className=\"flex shrink-0 items-center justify-between gap-3 border-b border-[var(--as-border)] px-5 py-4 sm:px-6\">\n <div className=\"flex min-w-0 items-center gap-2\">\n {headerIcon}\n {title ? (\n <DialogPrimitive.Title className=\"truncate font-semibold text-[var(--as-fg)]\">\n {title}\n </DialogPrimitive.Title>\n ) : null}\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n {headerActions}\n <DialogPrimitive.Close\n aria-label={closeLabel}\n className=\"rounded-[var(--as-radius-sm)] p-1.5 text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-secondary)] hover:text-[var(--as-fg)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <X aria-hidden=\"true\" className=\"size-5\" />\n </DialogPrimitive.Close>\n </div>\n </div>\n )}\n <div className={cn('min-h-0 flex-1', hideHeader && 'pt-10', bodyClassName ?? 'p-5 sm:p-6')}>\n {children}\n </div>\n {footer ? (\n <div className=\"shrink-0 border-t border-[var(--as-border)] px-5 py-4 sm:px-6\">\n {footer}\n </div>\n ) : null}\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n </DialogPrimitive.Root>\n )\n})\n"]}
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-KLWKZSYM.js.map
3
+ //# sourceMappingURL=chunk-KLWKZSYM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-KLWKZSYM.js"}
@@ -1,4 +1,4 @@
1
- import { Combobox } from './chunk-XHHEAJHN.js';
1
+ import { Combobox } from './chunk-3RDFWXX6.js';
2
2
  import { cn } from './chunk-BLJWR4ZV.js';
3
3
  import * as React from 'react';
4
4
  import { jsx } from 'react/jsx-runtime';
@@ -59,5 +59,5 @@ var ModelPicker = React.forwardRef(
59
59
  );
60
60
 
61
61
  export { ModelPicker };
62
- //# sourceMappingURL=chunk-FE26R5RN.js.map
63
- //# sourceMappingURL=chunk-FE26R5RN.js.map
62
+ //# sourceMappingURL=chunk-OPTH3VUY.js.map
63
+ //# sourceMappingURL=chunk-OPTH3VUY.js.map