@thangnqdev/ui 0.1.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 (253) hide show
  1. package/README.md +196 -0
  2. package/dist/Label-DWOlgSNW.d.cts +14 -0
  3. package/dist/Label-DWOlgSNW.d.ts +14 -0
  4. package/dist/bento/index.cjs +140 -0
  5. package/dist/bento/index.cjs.map +1 -0
  6. package/dist/bento/index.d.cts +4 -0
  7. package/dist/bento/index.d.ts +4 -0
  8. package/dist/bento/index.js +4 -0
  9. package/dist/bento/index.js.map +1 -0
  10. package/dist/bento/styles.css +46 -0
  11. package/dist/buttons/index.cjs +365 -0
  12. package/dist/buttons/index.cjs.map +1 -0
  13. package/dist/buttons/index.d.cts +4 -0
  14. package/dist/buttons/index.d.ts +4 -0
  15. package/dist/buttons/index.js +5 -0
  16. package/dist/buttons/index.js.map +1 -0
  17. package/dist/buttons/styles.css +6 -0
  18. package/dist/chunk-2OXZK6IP.js +514 -0
  19. package/dist/chunk-2OXZK6IP.js.map +1 -0
  20. package/dist/chunk-4S6L5V7X.js +15 -0
  21. package/dist/chunk-4S6L5V7X.js.map +1 -0
  22. package/dist/chunk-5FZ6ZFII.js +728 -0
  23. package/dist/chunk-5FZ6ZFII.js.map +1 -0
  24. package/dist/chunk-66VWUJEI.js +86 -0
  25. package/dist/chunk-66VWUJEI.js.map +1 -0
  26. package/dist/chunk-A7P3O5Z5.js +163 -0
  27. package/dist/chunk-A7P3O5Z5.js.map +1 -0
  28. package/dist/chunk-ATYGDTMK.js +257 -0
  29. package/dist/chunk-ATYGDTMK.js.map +1 -0
  30. package/dist/chunk-C4SUXMI3.js +138 -0
  31. package/dist/chunk-C4SUXMI3.js.map +1 -0
  32. package/dist/chunk-EU2LPUYP.js +25 -0
  33. package/dist/chunk-EU2LPUYP.js.map +1 -0
  34. package/dist/chunk-F5Q7BTMH.js +1991 -0
  35. package/dist/chunk-F5Q7BTMH.js.map +1 -0
  36. package/dist/chunk-GXI2H5XA.js +46 -0
  37. package/dist/chunk-GXI2H5XA.js.map +1 -0
  38. package/dist/chunk-H3LCNPMC.js +101 -0
  39. package/dist/chunk-H3LCNPMC.js.map +1 -0
  40. package/dist/chunk-IABPUCAQ.js +19 -0
  41. package/dist/chunk-IABPUCAQ.js.map +1 -0
  42. package/dist/chunk-KJRBRTQE.js +101 -0
  43. package/dist/chunk-KJRBRTQE.js.map +1 -0
  44. package/dist/chunk-LBUBXUYQ.js +40 -0
  45. package/dist/chunk-LBUBXUYQ.js.map +1 -0
  46. package/dist/chunk-LWFRUJRU.js +537 -0
  47. package/dist/chunk-LWFRUJRU.js.map +1 -0
  48. package/dist/chunk-NFVONJUK.js +882 -0
  49. package/dist/chunk-NFVONJUK.js.map +1 -0
  50. package/dist/chunk-PF4ZHGVW.js +284 -0
  51. package/dist/chunk-PF4ZHGVW.js.map +1 -0
  52. package/dist/chunk-WAFHC4DQ.js +366 -0
  53. package/dist/chunk-WAFHC4DQ.js.map +1 -0
  54. package/dist/chunk-X76KBH4Y.js +71 -0
  55. package/dist/chunk-X76KBH4Y.js.map +1 -0
  56. package/dist/core/index.cjs +103 -0
  57. package/dist/core/index.cjs.map +1 -0
  58. package/dist/core/index.d.cts +3 -0
  59. package/dist/core/index.d.ts +3 -0
  60. package/dist/core/index.js +4 -0
  61. package/dist/core/index.js.map +1 -0
  62. package/dist/core/styles.css +128 -0
  63. package/dist/data-display/index.cjs +1023 -0
  64. package/dist/data-display/index.cjs.map +1 -0
  65. package/dist/data-display/index.d.cts +4 -0
  66. package/dist/data-display/index.d.ts +4 -0
  67. package/dist/data-display/index.js +6 -0
  68. package/dist/data-display/index.js.map +1 -0
  69. package/dist/data-display/styles.css +4 -0
  70. package/dist/feedback/index.cjs +368 -0
  71. package/dist/feedback/index.cjs.map +1 -0
  72. package/dist/feedback/index.d.cts +4 -0
  73. package/dist/feedback/index.d.ts +4 -0
  74. package/dist/feedback/index.js +4 -0
  75. package/dist/feedback/index.js.map +1 -0
  76. package/dist/feedback/styles.css +4 -0
  77. package/dist/forms/index.cjs +2287 -0
  78. package/dist/forms/index.cjs.map +1 -0
  79. package/dist/forms/index.d.cts +5 -0
  80. package/dist/forms/index.d.ts +5 -0
  81. package/dist/forms/index.js +10 -0
  82. package/dist/forms/index.js.map +1 -0
  83. package/dist/forms/styles.css +6 -0
  84. package/dist/glass/index.cjs +165 -0
  85. package/dist/glass/index.cjs.map +1 -0
  86. package/dist/glass/index.d.cts +4 -0
  87. package/dist/glass/index.d.ts +4 -0
  88. package/dist/glass/index.js +4 -0
  89. package/dist/glass/index.js.map +1 -0
  90. package/dist/glass/styles.css +81 -0
  91. package/dist/index-BTvkbCIj.d.cts +146 -0
  92. package/dist/index-BTvkbCIj.d.ts +146 -0
  93. package/dist/index-BkRqGNG1.d.cts +201 -0
  94. package/dist/index-BkRqGNG1.d.ts +201 -0
  95. package/dist/index-BlPcGeW-.d.cts +45 -0
  96. package/dist/index-BlPcGeW-.d.ts +45 -0
  97. package/dist/index-BzOCqvC6.d.cts +32 -0
  98. package/dist/index-BzOCqvC6.d.ts +32 -0
  99. package/dist/index-CCeWYAvn.d.cts +83 -0
  100. package/dist/index-COQ7uwt9.d.cts +44 -0
  101. package/dist/index-COQ7uwt9.d.ts +44 -0
  102. package/dist/index-CenuF_P2.d.cts +221 -0
  103. package/dist/index-CenuF_P2.d.ts +221 -0
  104. package/dist/index-Cle6QzQl.d.ts +371 -0
  105. package/dist/index-D6fE7w-b.d.cts +90 -0
  106. package/dist/index-D6fE7w-b.d.ts +90 -0
  107. package/dist/index-DR8cfJUG.d.ts +83 -0
  108. package/dist/index-DzcWh1Hs.d.cts +131 -0
  109. package/dist/index-DzcWh1Hs.d.ts +131 -0
  110. package/dist/index-TyK-Ldpy.d.cts +371 -0
  111. package/dist/index-ugj5s6a3.d.cts +95 -0
  112. package/dist/index-ugj5s6a3.d.ts +95 -0
  113. package/dist/index.cjs +6400 -0
  114. package/dist/index.cjs.map +1 -0
  115. package/dist/index.d.cts +16 -0
  116. package/dist/index.d.ts +16 -0
  117. package/dist/index.js +21 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/layout/index.cjs +516 -0
  120. package/dist/layout/index.cjs.map +1 -0
  121. package/dist/layout/index.d.cts +4 -0
  122. package/dist/layout/index.d.ts +4 -0
  123. package/dist/layout/index.js +4 -0
  124. package/dist/layout/index.js.map +1 -0
  125. package/dist/layout/styles.css +8 -0
  126. package/dist/navigation/index.cjs +673 -0
  127. package/dist/navigation/index.cjs.map +1 -0
  128. package/dist/navigation/index.d.cts +2 -0
  129. package/dist/navigation/index.d.ts +2 -0
  130. package/dist/navigation/index.js +8 -0
  131. package/dist/navigation/index.js.map +1 -0
  132. package/dist/navigation/styles.css +4 -0
  133. package/dist/overlays/index.cjs +954 -0
  134. package/dist/overlays/index.cjs.map +1 -0
  135. package/dist/overlays/index.d.cts +4 -0
  136. package/dist/overlays/index.d.ts +4 -0
  137. package/dist/overlays/index.js +9 -0
  138. package/dist/overlays/index.js.map +1 -0
  139. package/dist/overlays/styles.css +8 -0
  140. package/dist/styles.css +333 -0
  141. package/dist/typography/index.cjs +311 -0
  142. package/dist/typography/index.cjs.map +1 -0
  143. package/dist/typography/index.d.cts +5 -0
  144. package/dist/typography/index.d.ts +5 -0
  145. package/dist/typography/index.js +6 -0
  146. package/dist/typography/index.js.map +1 -0
  147. package/dist/typography/styles.css +5 -0
  148. package/llms.txt +113 -0
  149. package/package.json +116 -0
  150. package/src/bento/BentoCard.tsx +140 -0
  151. package/src/bento/BentoGrid.tsx +50 -0
  152. package/src/bento/index.ts +2 -0
  153. package/src/bento/tokens.css +46 -0
  154. package/src/buttons/Button.tsx +104 -0
  155. package/src/buttons/ButtonGroup.tsx +43 -0
  156. package/src/buttons/IconButton.tsx +79 -0
  157. package/src/buttons/SplitButton.tsx +86 -0
  158. package/src/buttons/ToggleButton.tsx +157 -0
  159. package/src/buttons/index.ts +5 -0
  160. package/src/buttons/tokens.css +6 -0
  161. package/src/core/ThemeProvider.tsx +123 -0
  162. package/src/core/index.ts +2 -0
  163. package/src/core/tokens.css +128 -0
  164. package/src/data-display/Accordion.tsx +147 -0
  165. package/src/data-display/Avatar.tsx +134 -0
  166. package/src/data-display/Card.tsx +112 -0
  167. package/src/data-display/Carousel.tsx +130 -0
  168. package/src/data-display/Chip.tsx +74 -0
  169. package/src/data-display/DataTablePro.tsx +356 -0
  170. package/src/data-display/StatCard.tsx +60 -0
  171. package/src/data-display/Table.tsx +74 -0
  172. package/src/data-display/Timeline.tsx +62 -0
  173. package/src/data-display/TreeView.tsx +140 -0
  174. package/src/data-display/index.ts +10 -0
  175. package/src/data-display/tokens.css +4 -0
  176. package/src/feedback/Alert.tsx +80 -0
  177. package/src/feedback/EmptyState.tsx +45 -0
  178. package/src/feedback/ProgressBar.tsx +174 -0
  179. package/src/feedback/Skeleton.tsx +66 -0
  180. package/src/feedback/Spinner.tsx +65 -0
  181. package/src/feedback/index.ts +5 -0
  182. package/src/feedback/tokens.css +4 -0
  183. package/src/forms/Checkbox.tsx +69 -0
  184. package/src/forms/CheckboxGroup.tsx +29 -0
  185. package/src/forms/Combobox.tsx +368 -0
  186. package/src/forms/DatePicker.tsx +480 -0
  187. package/src/forms/FileUpload.tsx +222 -0
  188. package/src/forms/FormField.tsx +115 -0
  189. package/src/forms/Input.tsx +151 -0
  190. package/src/forms/MaskedInput.tsx +97 -0
  191. package/src/forms/NumberInput.tsx +248 -0
  192. package/src/forms/PasswordInput.tsx +35 -0
  193. package/src/forms/PinInput.tsx +125 -0
  194. package/src/forms/Radio.tsx +142 -0
  195. package/src/forms/RangeSlider.tsx +111 -0
  196. package/src/forms/SearchInput.tsx +34 -0
  197. package/src/forms/Select.tsx +103 -0
  198. package/src/forms/Slider.tsx +85 -0
  199. package/src/forms/Switch.tsx +95 -0
  200. package/src/forms/Textarea.tsx +114 -0
  201. package/src/forms/index.ts +18 -0
  202. package/src/forms/tokens.css +6 -0
  203. package/src/glass/GlassBadge.tsx +61 -0
  204. package/src/glass/GlassButton.tsx +59 -0
  205. package/src/glass/GlassCard.tsx +71 -0
  206. package/src/glass/index.ts +3 -0
  207. package/src/glass/tokens.css +81 -0
  208. package/src/index.ts +26 -0
  209. package/src/layout/AspectRatio.tsx +39 -0
  210. package/src/layout/Container.tsx +53 -0
  211. package/src/layout/Divider.tsx +61 -0
  212. package/src/layout/Flex.tsx +79 -0
  213. package/src/layout/Grid.tsx +124 -0
  214. package/src/layout/PageLayout.tsx +59 -0
  215. package/src/layout/ScrollArea.tsx +43 -0
  216. package/src/layout/Section.tsx +47 -0
  217. package/src/layout/Spacer.tsx +30 -0
  218. package/src/layout/Stack.tsx +88 -0
  219. package/src/layout/index.ts +10 -0
  220. package/src/layout/tokens.css +8 -0
  221. package/src/navigation/Breadcrumb.tsx +73 -0
  222. package/src/navigation/CommandPalette.tsx +142 -0
  223. package/src/navigation/DropdownMenu.tsx +160 -0
  224. package/src/navigation/Pagination.tsx +114 -0
  225. package/src/navigation/Stepper.tsx +93 -0
  226. package/src/navigation/Tabs.tsx +133 -0
  227. package/src/navigation/index.ts +6 -0
  228. package/src/navigation/tokens.css +4 -0
  229. package/src/overlays/AlertDialog.tsx +54 -0
  230. package/src/overlays/BottomSheet.tsx +123 -0
  231. package/src/overlays/ContextMenu.tsx +119 -0
  232. package/src/overlays/Drawer.tsx +145 -0
  233. package/src/overlays/FocusTrap.tsx +49 -0
  234. package/src/overlays/HoverCard.tsx +72 -0
  235. package/src/overlays/Modal.tsx +219 -0
  236. package/src/overlays/Popover.tsx +126 -0
  237. package/src/overlays/Portal.tsx +23 -0
  238. package/src/overlays/Toast.tsx +137 -0
  239. package/src/overlays/Tooltip.tsx +100 -0
  240. package/src/overlays/index.ts +11 -0
  241. package/src/overlays/tokens.css +8 -0
  242. package/src/styles/tokens.css +2 -0
  243. package/src/typography/Blockquote.tsx +32 -0
  244. package/src/typography/Code.tsx +89 -0
  245. package/src/typography/Heading.tsx +56 -0
  246. package/src/typography/Kbd.tsx +25 -0
  247. package/src/typography/Label.tsx +47 -0
  248. package/src/typography/Link.tsx +56 -0
  249. package/src/typography/Text.tsx +62 -0
  250. package/src/typography/index.ts +7 -0
  251. package/src/typography/tokens.css +5 -0
  252. package/src/utils/cn.ts +6 -0
  253. package/ui-contract.json +62 -0
@@ -0,0 +1,1991 @@
1
+ import { Chip } from './chunk-X76KBH4Y.js';
2
+ import { Label } from './chunk-GXI2H5XA.js';
3
+ import { Popover } from './chunk-H3LCNPMC.js';
4
+ import { Kbd } from './chunk-EU2LPUYP.js';
5
+ import { Button } from './chunk-66VWUJEI.js';
6
+ import { __export, cn } from './chunk-4S6L5V7X.js';
7
+ import React2, { createContext, useContext, forwardRef, useId, useState, useRef, useEffect } from 'react';
8
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
+ import { cva } from 'class-variance-authority';
10
+ import { X, Search, EyeOff, Eye, ChevronDown, Minus, Check, ChevronLeft, ChevronRight, Calendar, Clock, ChevronsUpDown, UploadCloud, FileText, File, CheckCircle2, AlertCircle, Plus } from 'lucide-react';
11
+
12
+ // src/forms/index.ts
13
+ var forms_exports = {};
14
+ __export(forms_exports, {
15
+ Checkbox: () => Checkbox,
16
+ CheckboxGroup: () => CheckboxGroup,
17
+ Combobox: () => Combobox,
18
+ CurrencyInput: () => CurrencyInput,
19
+ DatePicker: () => DatePicker,
20
+ DateRangePicker: () => DateRangePicker,
21
+ FileUpload: () => FileUpload,
22
+ FormErrorMessage: () => FormErrorMessage,
23
+ FormField: () => FormField,
24
+ FormHelperText: () => FormHelperText,
25
+ FormLabel: () => FormLabel,
26
+ Input: () => Input,
27
+ MaskedInput: () => MaskedInput,
28
+ MultiSelect: () => MultiSelect,
29
+ NumberInput: () => NumberInput,
30
+ PasswordInput: () => PasswordInput,
31
+ PinInput: () => PinInput,
32
+ Radio: () => Radio,
33
+ RadioGroup: () => RadioGroup,
34
+ RangeSlider: () => RangeSlider,
35
+ SearchInput: () => SearchInput,
36
+ Select: () => Select,
37
+ Slider: () => Slider,
38
+ Switch: () => Switch,
39
+ Textarea: () => Textarea,
40
+ TimePicker: () => TimePicker,
41
+ applyMask: () => applyMask,
42
+ checkboxVariants: () => checkboxVariants,
43
+ formatCurrencyString: () => formatCurrencyString,
44
+ formatDate: () => formatDate,
45
+ formatDisplayDate: () => formatDisplayDate,
46
+ formatFileSize: () => formatFileSize,
47
+ inputVariants: () => inputVariants,
48
+ radioVariants: () => radioVariants,
49
+ selectVariants: () => selectVariants,
50
+ switchThumbVariants: () => switchThumbVariants,
51
+ switchVariants: () => switchVariants,
52
+ textareaVariants: () => textareaVariants,
53
+ useFormField: () => useFormField
54
+ });
55
+ var FormFieldContext = createContext(null);
56
+ function useFormField() {
57
+ const context = useContext(FormFieldContext);
58
+ return context;
59
+ }
60
+ var FormField = forwardRef(
61
+ ({ className, isRequired, isInvalid, isDisabled, children, ...props }, ref) => {
62
+ const generatedId = useId();
63
+ const id = props.id || generatedId;
64
+ const labelId = `${id}-label`;
65
+ const descriptionId = `${id}-description`;
66
+ const errorId = `${id}-error`;
67
+ return /* @__PURE__ */ jsx(
68
+ FormFieldContext.Provider,
69
+ {
70
+ value: {
71
+ id,
72
+ labelId,
73
+ descriptionId,
74
+ errorId,
75
+ isRequired,
76
+ isInvalid,
77
+ isDisabled
78
+ },
79
+ children: /* @__PURE__ */ jsx("div", { ref, className: cn("space-y-1.5 w-full", className), ...props, children })
80
+ }
81
+ );
82
+ }
83
+ );
84
+ FormField.displayName = "FormField";
85
+ var FormLabel = forwardRef(
86
+ ({ className, required, children, ...props }, ref) => {
87
+ const context = useFormField();
88
+ const isRequired = required ?? context?.isRequired;
89
+ const isError = context?.isInvalid;
90
+ return /* @__PURE__ */ jsx(
91
+ Label,
92
+ {
93
+ ref,
94
+ id: context?.labelId,
95
+ htmlFor: context?.id,
96
+ required: isRequired,
97
+ error: isError,
98
+ className,
99
+ ...props,
100
+ children
101
+ }
102
+ );
103
+ }
104
+ );
105
+ FormLabel.displayName = "FormLabel";
106
+ var FormHelperText = forwardRef(
107
+ ({ className, children, ...props }, ref) => {
108
+ const context = useFormField();
109
+ return /* @__PURE__ */ jsx(
110
+ "p",
111
+ {
112
+ ref,
113
+ id: context?.descriptionId,
114
+ className: cn("text-xs text-[var(--ui-text-muted)]", className),
115
+ ...props,
116
+ children
117
+ }
118
+ );
119
+ }
120
+ );
121
+ FormHelperText.displayName = "FormHelperText";
122
+ var FormErrorMessage = forwardRef(
123
+ ({ className, children, ...props }, ref) => {
124
+ const context = useFormField();
125
+ if (!context?.isInvalid && !children) return null;
126
+ return /* @__PURE__ */ jsx(
127
+ "p",
128
+ {
129
+ ref,
130
+ id: context?.errorId,
131
+ role: "alert",
132
+ className: cn("text-xs font-medium text-[var(--ui-error)]", className),
133
+ ...props,
134
+ children
135
+ }
136
+ );
137
+ }
138
+ );
139
+ FormErrorMessage.displayName = "FormErrorMessage";
140
+ var inputVariants = cva(
141
+ "w-full rounded-[var(--ui-radius-md)] border bg-[var(--ui-bg-surface)]/70 backdrop-blur-md text-[var(--ui-text-primary)] placeholder:text-[var(--ui-text-muted)] transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary)]/70 focus-visible:border-[var(--ui-primary)] focus-visible:shadow-[0_0_16px_rgba(99,102,241,0.2)] disabled:cursor-not-allowed disabled:opacity-50 shadow-inner",
142
+ {
143
+ variants: {
144
+ size: {
145
+ sm: "h-8 px-2.5 text-xs",
146
+ md: "h-10 px-3.5 text-sm",
147
+ lg: "h-12 px-4 text-base"
148
+ },
149
+ variant: {
150
+ default: "border-[var(--ui-border-default)] hover:border-[var(--ui-border-strong)]",
151
+ filled: "bg-[var(--ui-bg-secondary)] border-transparent hover:bg-[var(--ui-bg-tertiary)]"
152
+ },
153
+ isInvalid: {
154
+ true: "border-[var(--ui-error)] focus-visible:ring-[var(--ui-error)]/70 focus-visible:shadow-[0_0_16px_rgba(244,63,94,0.25)]",
155
+ false: ""
156
+ }
157
+ },
158
+ defaultVariants: {
159
+ size: "md",
160
+ variant: "default",
161
+ isInvalid: false
162
+ }
163
+ }
164
+ );
165
+ var Input = forwardRef(
166
+ ({
167
+ className,
168
+ type = "text",
169
+ size,
170
+ variant,
171
+ isInvalid: customInvalid,
172
+ prefixIcon,
173
+ suffixIcon,
174
+ clearable,
175
+ onClear,
176
+ value,
177
+ onChange,
178
+ disabled,
179
+ id,
180
+ ...props
181
+ }, ref) => {
182
+ const formField = useFormField();
183
+ const isInvalid = customInvalid ?? formField?.isInvalid ?? false;
184
+ const isDisabled = disabled ?? formField?.isDisabled ?? false;
185
+ const inputId = id || formField?.id;
186
+ const isControlled = value !== void 0;
187
+ const [uncontrolledVal, setUncontrolledVal] = useState(
188
+ props.defaultValue !== void 0 ? String(props.defaultValue) : ""
189
+ );
190
+ const innerRef = React2.useRef(null);
191
+ const handleRef = (node) => {
192
+ innerRef.current = node;
193
+ if (typeof ref === "function") {
194
+ ref(node);
195
+ } else if (ref) {
196
+ ref.current = node;
197
+ }
198
+ };
199
+ const handleChange = (e) => {
200
+ if (!isControlled) {
201
+ setUncontrolledVal(e.target.value);
202
+ }
203
+ onChange?.(e);
204
+ };
205
+ const handleClear = () => {
206
+ if (!isControlled && innerRef.current) {
207
+ innerRef.current.value = "";
208
+ setUncontrolledVal("");
209
+ const event = new Event("input", { bubbles: true });
210
+ innerRef.current.dispatchEvent(event);
211
+ }
212
+ onClear?.();
213
+ };
214
+ const hasValue = isControlled ? Boolean(value) : Boolean(uncontrolledVal || innerRef.current?.value);
215
+ return /* @__PURE__ */ jsxs("div", { className: "relative w-full flex items-center", children: [
216
+ prefixIcon && /* @__PURE__ */ jsx("div", { className: "absolute left-3 flex items-center pointer-events-none text-[var(--ui-text-muted)]", children: prefixIcon }),
217
+ /* @__PURE__ */ jsx(
218
+ "input",
219
+ {
220
+ ref: handleRef,
221
+ id: inputId,
222
+ type,
223
+ disabled: isDisabled,
224
+ ...isControlled ? { value } : {},
225
+ onChange: handleChange,
226
+ "aria-invalid": isInvalid,
227
+ "aria-describedby": isInvalid ? formField?.errorId : formField?.descriptionId || void 0,
228
+ className: cn(
229
+ inputVariants({ size, variant, isInvalid }),
230
+ prefixIcon && "pl-9",
231
+ (suffixIcon || clearable && hasValue) && "pr-9",
232
+ className
233
+ ),
234
+ ...props
235
+ }
236
+ ),
237
+ /* @__PURE__ */ jsxs("div", { className: "absolute right-3 flex items-center gap-1 text-[var(--ui-text-muted)]", children: [
238
+ clearable && hasValue && !isDisabled && /* @__PURE__ */ jsx(
239
+ "button",
240
+ {
241
+ type: "button",
242
+ onClick: handleClear,
243
+ className: "p-0.5 rounded-full hover:bg-[var(--ui-bg-tertiary)] hover:text-[var(--ui-text-primary)] transition-colors",
244
+ "aria-label": "Clear input",
245
+ children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5" })
246
+ }
247
+ ),
248
+ suffixIcon && /* @__PURE__ */ jsx("span", { className: "pointer-events-none flex items-center", children: suffixIcon })
249
+ ] })
250
+ ] });
251
+ }
252
+ );
253
+ Input.displayName = "Input";
254
+ var SearchInput = forwardRef(
255
+ ({ shortcut, clearable = true, suffixIcon, ...props }, ref) => {
256
+ return /* @__PURE__ */ jsx(
257
+ Input,
258
+ {
259
+ ref,
260
+ type: "search",
261
+ clearable,
262
+ prefixIcon: /* @__PURE__ */ jsx(Search, { className: "w-4 h-4" }),
263
+ suffixIcon: shortcut ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
264
+ /* @__PURE__ */ jsx(Kbd, { children: shortcut }),
265
+ suffixIcon
266
+ ] }) : suffixIcon,
267
+ ...props
268
+ }
269
+ );
270
+ }
271
+ );
272
+ SearchInput.displayName = "SearchInput";
273
+ var PasswordInput = forwardRef(
274
+ ({ showToggle = true, ...props }, ref) => {
275
+ const [showPassword, setShowPassword] = useState(false);
276
+ return /* @__PURE__ */ jsx(
277
+ Input,
278
+ {
279
+ ref,
280
+ type: showPassword ? "text" : "password",
281
+ suffixIcon: showToggle ? /* @__PURE__ */ jsx(
282
+ "button",
283
+ {
284
+ type: "button",
285
+ onClick: () => setShowPassword(!showPassword),
286
+ className: "p-1 rounded hover:bg-[var(--ui-bg-tertiary)] text-[var(--ui-text-muted)] hover:text-[var(--ui-text-primary)] pointer-events-auto transition-colors",
287
+ "aria-label": showPassword ? "Hide password" : "Show password",
288
+ children: showPassword ? /* @__PURE__ */ jsx(EyeOff, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx(Eye, { className: "w-4 h-4" })
289
+ }
290
+ ) : void 0,
291
+ ...props
292
+ }
293
+ );
294
+ }
295
+ );
296
+ PasswordInput.displayName = "PasswordInput";
297
+ var textareaVariants = cva(
298
+ "w-full rounded-[var(--ui-radius-md)] border bg-[var(--ui-bg-surface)] p-3 text-sm text-[var(--ui-text-primary)] placeholder:text-[var(--ui-text-muted)] transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary)] disabled:cursor-not-allowed disabled:opacity-50 min-h-[80px]",
299
+ {
300
+ variants: {
301
+ variant: {
302
+ default: "border-[var(--ui-border-default)] hover:border-[var(--ui-border-strong)]",
303
+ filled: "bg-[var(--ui-bg-secondary)] border-transparent hover:bg-[var(--ui-bg-tertiary)]"
304
+ },
305
+ isInvalid: {
306
+ true: "border-[var(--ui-error)] focus-visible:ring-[var(--ui-error)]",
307
+ false: ""
308
+ },
309
+ resize: {
310
+ none: "resize-none",
311
+ vertical: "resize-y",
312
+ horizontal: "resize-x",
313
+ both: "resize"
314
+ }
315
+ },
316
+ defaultVariants: {
317
+ variant: "default",
318
+ isInvalid: false,
319
+ resize: "vertical"
320
+ }
321
+ }
322
+ );
323
+ var Textarea = forwardRef(
324
+ ({
325
+ className,
326
+ variant,
327
+ isInvalid: customInvalid,
328
+ resize,
329
+ autoResize = false,
330
+ disabled,
331
+ value,
332
+ onChange,
333
+ id,
334
+ ...props
335
+ }, ref) => {
336
+ const formField = useFormField();
337
+ const isInvalid = customInvalid ?? formField?.isInvalid ?? false;
338
+ const isDisabled = disabled ?? formField?.isDisabled ?? false;
339
+ const inputId = id || formField?.id;
340
+ const innerRef = useRef(null);
341
+ const setMergedRef = (element) => {
342
+ innerRef.current = element;
343
+ if (typeof ref === "function") {
344
+ ref(element);
345
+ } else if (ref) {
346
+ ref.current = element;
347
+ }
348
+ };
349
+ const handleInput = () => {
350
+ if (autoResize && innerRef.current) {
351
+ innerRef.current.style.height = "auto";
352
+ innerRef.current.style.height = `${innerRef.current.scrollHeight}px`;
353
+ }
354
+ };
355
+ useEffect(() => {
356
+ if (autoResize && innerRef.current) {
357
+ handleInput();
358
+ }
359
+ }, [value, autoResize]);
360
+ return /* @__PURE__ */ jsx(
361
+ "textarea",
362
+ {
363
+ ref: setMergedRef,
364
+ id: inputId,
365
+ disabled: isDisabled,
366
+ value,
367
+ onChange: (e) => {
368
+ handleInput();
369
+ onChange?.(e);
370
+ },
371
+ "aria-invalid": isInvalid,
372
+ "aria-describedby": isInvalid ? formField?.errorId : formField?.descriptionId || void 0,
373
+ className: cn(
374
+ textareaVariants({
375
+ variant,
376
+ isInvalid,
377
+ resize: autoResize ? "none" : resize
378
+ }),
379
+ className
380
+ ),
381
+ ...props
382
+ }
383
+ );
384
+ }
385
+ );
386
+ Textarea.displayName = "Textarea";
387
+ var selectVariants = cva(
388
+ "w-full rounded-[var(--ui-radius-md)] border bg-[var(--ui-bg-surface)] text-[var(--ui-text-primary)] transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary)] disabled:cursor-not-allowed disabled:opacity-50 appearance-none pr-10",
389
+ {
390
+ variants: {
391
+ size: {
392
+ sm: "h-8 px-2.5 text-xs",
393
+ md: "h-10 px-3.5 text-sm",
394
+ lg: "h-12 px-4 text-base"
395
+ },
396
+ variant: {
397
+ default: "border-[var(--ui-border-default)] hover:border-[var(--ui-border-strong)]",
398
+ filled: "bg-[var(--ui-bg-secondary)] border-transparent hover:bg-[var(--ui-bg-tertiary)]"
399
+ },
400
+ isInvalid: {
401
+ true: "border-[var(--ui-error)] focus-visible:ring-[var(--ui-error)]",
402
+ false: ""
403
+ }
404
+ },
405
+ defaultVariants: {
406
+ size: "md",
407
+ variant: "default",
408
+ isInvalid: false
409
+ }
410
+ }
411
+ );
412
+ var Select = forwardRef(
413
+ ({
414
+ className,
415
+ size,
416
+ variant,
417
+ isInvalid: customInvalid,
418
+ options,
419
+ placeholder,
420
+ disabled,
421
+ children,
422
+ id,
423
+ ...props
424
+ }, ref) => {
425
+ const formField = useFormField();
426
+ const isInvalid = customInvalid ?? formField?.isInvalid ?? false;
427
+ const isDisabled = disabled ?? formField?.isDisabled ?? false;
428
+ const inputId = id || formField?.id;
429
+ return /* @__PURE__ */ jsxs("div", { className: "relative w-full flex items-center", children: [
430
+ /* @__PURE__ */ jsxs(
431
+ "select",
432
+ {
433
+ ref,
434
+ id: inputId,
435
+ disabled: isDisabled,
436
+ "aria-invalid": isInvalid,
437
+ "aria-describedby": isInvalid ? formField?.errorId : formField?.descriptionId || void 0,
438
+ className: cn(selectVariants({ size, variant, isInvalid }), className),
439
+ ...props,
440
+ children: [
441
+ placeholder && /* @__PURE__ */ jsx("option", { value: "", disabled: true, hidden: true, children: placeholder }),
442
+ options ? options.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, disabled: opt.disabled, children: opt.label }, opt.value)) : children
443
+ ]
444
+ }
445
+ ),
446
+ /* @__PURE__ */ jsx("div", { className: "absolute right-3 flex items-center pointer-events-none text-[var(--ui-text-muted)]", children: /* @__PURE__ */ jsx(ChevronDown, { className: "w-4 h-4" }) })
447
+ ] });
448
+ }
449
+ );
450
+ Select.displayName = "Select";
451
+ var checkboxVariants = cva(
452
+ "peer shrink-0 rounded-[var(--ui-radius-sm)] border border-[var(--ui-border-default)] bg-[var(--ui-bg-surface)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary)] disabled:cursor-not-allowed disabled:opacity-50 transition-all cursor-pointer flex items-center justify-center text-[var(--ui-primary-fg)]",
453
+ {
454
+ variants: {
455
+ size: {
456
+ sm: "w-4 h-4 text-xs",
457
+ md: "w-5 h-5 text-sm",
458
+ lg: "w-6 h-6 text-base"
459
+ }
460
+ },
461
+ defaultVariants: {
462
+ size: "md"
463
+ }
464
+ }
465
+ );
466
+ var Checkbox = forwardRef(
467
+ ({ className, size, indeterminate = false, label, checked, disabled, id, onChange, ...props }, ref) => {
468
+ const formField = useFormField();
469
+ const isDisabled = disabled ?? formField?.isDisabled ?? false;
470
+ const checkboxId = id || formField?.id;
471
+ return /* @__PURE__ */ jsxs("label", { className: cn("inline-flex items-center gap-2 select-none cursor-pointer", isDisabled && "cursor-not-allowed opacity-50"), children: [
472
+ /* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center", children: [
473
+ /* @__PURE__ */ jsx(
474
+ "input",
475
+ {
476
+ ref,
477
+ type: "checkbox",
478
+ id: checkboxId,
479
+ disabled: isDisabled,
480
+ checked,
481
+ onChange,
482
+ className: "sr-only peer",
483
+ ...props
484
+ }
485
+ ),
486
+ /* @__PURE__ */ jsx(
487
+ "div",
488
+ {
489
+ className: cn(
490
+ checkboxVariants({ size }),
491
+ (checked || indeterminate) && "bg-[var(--ui-primary)] border-[var(--ui-primary)]",
492
+ className
493
+ ),
494
+ children: indeterminate ? /* @__PURE__ */ jsx(Minus, { className: "w-3.5 h-3.5 stroke-[3]" }) : checked && /* @__PURE__ */ jsx(Check, { className: "w-3.5 h-3.5 stroke-[3]" })
495
+ }
496
+ )
497
+ ] }),
498
+ label && /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--ui-text-primary)]", children: label })
499
+ ] });
500
+ }
501
+ );
502
+ Checkbox.displayName = "Checkbox";
503
+ var CheckboxGroup = forwardRef(
504
+ ({ className, orientation = "vertical", children, value, onChange, ...props }, ref) => {
505
+ return /* @__PURE__ */ jsx(
506
+ "div",
507
+ {
508
+ ref,
509
+ role: "group",
510
+ className: cn(
511
+ "flex gap-2",
512
+ orientation === "vertical" ? "flex-col" : "flex-row flex-wrap items-center",
513
+ className
514
+ ),
515
+ ...props,
516
+ children
517
+ }
518
+ );
519
+ }
520
+ );
521
+ CheckboxGroup.displayName = "CheckboxGroup";
522
+ var RadioGroupContext = createContext(null);
523
+ var radioVariants = cva(
524
+ "peer shrink-0 rounded-full border border-[var(--ui-border-default)] bg-[var(--ui-bg-surface)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary)] disabled:cursor-not-allowed disabled:opacity-50 transition-all cursor-pointer flex items-center justify-center",
525
+ {
526
+ variants: {
527
+ size: {
528
+ sm: "w-4 h-4",
529
+ md: "w-5 h-5",
530
+ lg: "w-6 h-6"
531
+ }
532
+ },
533
+ defaultVariants: {
534
+ size: "md"
535
+ }
536
+ }
537
+ );
538
+ var Radio = forwardRef(
539
+ ({ className, size, label, value, checked, disabled, id, onChange, ...props }, ref) => {
540
+ const group = useContext(RadioGroupContext);
541
+ const isChecked = checked ?? (group?.value !== void 0 ? group.value === value : false);
542
+ const isDisabled = disabled ?? group?.disabled ?? false;
543
+ const name = props.name || group?.name;
544
+ const handleChange = (e) => {
545
+ onChange?.(e);
546
+ if (group?.onChange) {
547
+ group.onChange(value);
548
+ }
549
+ };
550
+ return /* @__PURE__ */ jsxs("label", { className: cn("inline-flex items-center gap-2 select-none cursor-pointer", isDisabled && "cursor-not-allowed opacity-50"), children: [
551
+ /* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center", children: [
552
+ /* @__PURE__ */ jsx(
553
+ "input",
554
+ {
555
+ ref,
556
+ type: "radio",
557
+ name,
558
+ value,
559
+ id,
560
+ disabled: isDisabled,
561
+ checked: isChecked,
562
+ onChange: handleChange,
563
+ className: "sr-only peer",
564
+ ...props
565
+ }
566
+ ),
567
+ /* @__PURE__ */ jsx(
568
+ "div",
569
+ {
570
+ className: cn(
571
+ radioVariants({ size }),
572
+ isChecked && "border-[var(--ui-primary)]",
573
+ className
574
+ ),
575
+ children: isChecked && /* @__PURE__ */ jsx("span", { className: "w-2.5 h-2.5 rounded-full bg-[var(--ui-primary)] animate-in zoom-in-75 duration-150" })
576
+ }
577
+ )
578
+ ] }),
579
+ label && /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--ui-text-primary)]", children: label })
580
+ ] });
581
+ }
582
+ );
583
+ Radio.displayName = "Radio";
584
+ var RadioGroup = forwardRef(
585
+ ({
586
+ className,
587
+ name,
588
+ value: controlledValue,
589
+ defaultValue,
590
+ onValueChange,
591
+ orientation = "vertical",
592
+ disabled,
593
+ children,
594
+ ...props
595
+ }, ref) => {
596
+ const [val, setVal] = React2.useState(defaultValue || "");
597
+ const currentValue = controlledValue !== void 0 ? controlledValue : val;
598
+ const handleChange = (newValue) => {
599
+ setVal(newValue);
600
+ onValueChange?.(newValue);
601
+ };
602
+ return /* @__PURE__ */ jsx(
603
+ RadioGroupContext.Provider,
604
+ {
605
+ value: {
606
+ name,
607
+ value: currentValue,
608
+ onChange: handleChange,
609
+ disabled
610
+ },
611
+ children: /* @__PURE__ */ jsx(
612
+ "div",
613
+ {
614
+ ref,
615
+ role: "radiogroup",
616
+ className: cn(
617
+ "flex gap-2",
618
+ orientation === "vertical" ? "flex-col" : "flex-row flex-wrap items-center",
619
+ className
620
+ ),
621
+ ...props,
622
+ children
623
+ }
624
+ )
625
+ }
626
+ );
627
+ }
628
+ );
629
+ RadioGroup.displayName = "RadioGroup";
630
+ var switchVariants = cva(
631
+ "peer inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-all duration-200 focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-[#34c759]/30 disabled:cursor-not-allowed disabled:opacity-50 bg-[var(--ui-border-strong)] data-[state=checked]:bg-[#34c759] dark:data-[state=checked]:bg-[#30d158] shadow-inner",
632
+ {
633
+ variants: {
634
+ size: {
635
+ sm: "h-5 w-9 p-0.5",
636
+ md: "h-6.5 w-12 p-0.5",
637
+ lg: "h-8 w-15 p-1"
638
+ }
639
+ },
640
+ defaultVariants: {
641
+ size: "md"
642
+ }
643
+ }
644
+ );
645
+ var switchThumbVariants = cva(
646
+ "pointer-events-none block rounded-full bg-white shadow-[0_2px_4px_rgba(0,0,0,0.25)] ring-0 transition-transform duration-200 ease-out data-[state=unchecked]:translate-x-0",
647
+ {
648
+ variants: {
649
+ size: {
650
+ sm: "h-4 w-4 data-[state=checked]:translate-x-4",
651
+ md: "h-5.5 w-5.5 data-[state=checked]:translate-x-5.5",
652
+ lg: "h-6 w-6 data-[state=checked]:translate-x-7"
653
+ }
654
+ },
655
+ defaultVariants: {
656
+ size: "md"
657
+ }
658
+ }
659
+ );
660
+ var Switch = forwardRef(
661
+ ({ className, size, label, checked, defaultChecked, onCheckedChange, disabled, id, onChange, ...props }, ref) => {
662
+ const isControlled = checked !== void 0;
663
+ const [internalChecked, setInternalChecked] = useState(defaultChecked ?? false);
664
+ const isChecked = isControlled ? checked : internalChecked;
665
+ const formField = useFormField();
666
+ const isDisabled = disabled ?? formField?.isDisabled ?? false;
667
+ const switchId = id || formField?.id;
668
+ const handleChange = (e) => {
669
+ if (!isControlled) {
670
+ setInternalChecked(e.target.checked);
671
+ }
672
+ onChange?.(e);
673
+ onCheckedChange?.(e.target.checked);
674
+ };
675
+ return /* @__PURE__ */ jsxs("label", { className: cn("inline-flex items-center gap-3 select-none cursor-pointer", isDisabled && "cursor-not-allowed opacity-50"), children: [
676
+ /* @__PURE__ */ jsxs("div", { className: "relative flex items-center", children: [
677
+ /* @__PURE__ */ jsx(
678
+ "input",
679
+ {
680
+ ref,
681
+ type: "checkbox",
682
+ role: "switch",
683
+ id: switchId,
684
+ disabled: isDisabled,
685
+ checked: isChecked,
686
+ onChange: handleChange,
687
+ className: "sr-only peer",
688
+ ...props
689
+ }
690
+ ),
691
+ /* @__PURE__ */ jsx(
692
+ "div",
693
+ {
694
+ "data-state": isChecked ? "checked" : "unchecked",
695
+ className: cn(switchVariants({ size }), className),
696
+ children: /* @__PURE__ */ jsx(
697
+ "span",
698
+ {
699
+ "data-state": isChecked ? "checked" : "unchecked",
700
+ className: cn(switchThumbVariants({ size }))
701
+ }
702
+ )
703
+ }
704
+ )
705
+ ] }),
706
+ label && /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--ui-text-primary)]", children: label })
707
+ ] });
708
+ }
709
+ );
710
+ Switch.displayName = "Switch";
711
+ var Slider = forwardRef(
712
+ ({
713
+ className,
714
+ value: controlledValue,
715
+ defaultValue = 0,
716
+ min = 0,
717
+ max = 100,
718
+ step = 1,
719
+ showValue = false,
720
+ formatValue = (v) => `${v}`,
721
+ onChange,
722
+ disabled,
723
+ ...props
724
+ }, ref) => {
725
+ const [val, setVal] = React2.useState(defaultValue);
726
+ const currentValue = controlledValue !== void 0 ? controlledValue : val;
727
+ const percentage = Math.min(100, Math.max(0, (currentValue - min) / (max - min) * 100));
728
+ const handleChange = (e) => {
729
+ const num = Number(e.target.value);
730
+ setVal(num);
731
+ onChange?.(num);
732
+ };
733
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full flex items-center gap-4", className), children: [
734
+ /* @__PURE__ */ jsxs("div", { className: "relative w-full flex items-center h-6 select-none touch-none", children: [
735
+ /* @__PURE__ */ jsx("div", { className: "w-full h-2 rounded-full bg-[var(--ui-border-default)] overflow-hidden relative", children: /* @__PURE__ */ jsx(
736
+ "div",
737
+ {
738
+ className: "h-full bg-[var(--ui-primary)] transition-all duration-75",
739
+ style: { width: `${percentage}%` }
740
+ }
741
+ ) }),
742
+ /* @__PURE__ */ jsx(
743
+ "input",
744
+ {
745
+ ref,
746
+ type: "range",
747
+ min,
748
+ max,
749
+ step,
750
+ value: currentValue,
751
+ disabled,
752
+ onChange: handleChange,
753
+ className: "absolute inset-0 w-full h-full opacity-0 cursor-pointer disabled:cursor-not-allowed",
754
+ ...props
755
+ }
756
+ ),
757
+ /* @__PURE__ */ jsx(
758
+ "div",
759
+ {
760
+ className: "absolute w-5 h-5 rounded-full bg-white border-2 border-[var(--ui-primary)] shadow-md pointer-events-none transition-transform duration-75 -translate-x-1/2",
761
+ style: { left: `${percentage}%` }
762
+ }
763
+ )
764
+ ] }),
765
+ showValue && /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold font-mono text-[var(--ui-text-secondary)] min-w-[2.5rem] text-right", children: formatValue(currentValue) })
766
+ ] });
767
+ }
768
+ );
769
+ Slider.displayName = "Slider";
770
+ var RangeSlider = forwardRef(
771
+ ({
772
+ min = 0,
773
+ max = 100,
774
+ step = 1,
775
+ value: controlledValue,
776
+ defaultValue = [20, 80],
777
+ onChange,
778
+ showValue = false,
779
+ formatValue = (v) => `${v}`,
780
+ className,
781
+ disabled = false
782
+ }, ref) => {
783
+ const [stateValue, setStateValue] = useState(defaultValue);
784
+ const [minVal, maxVal] = controlledValue || stateValue;
785
+ const minPercentage = Math.min(100, Math.max(0, (minVal - min) / (max - min) * 100));
786
+ const maxPercentage = Math.min(100, Math.max(0, (maxVal - min) / (max - min) * 100));
787
+ const handleMinChange = (e) => {
788
+ const val = Math.min(Number(e.target.value), maxVal - step);
789
+ setStateValue([val, maxVal]);
790
+ onChange?.([val, maxVal]);
791
+ };
792
+ const handleMaxChange = (e) => {
793
+ const val = Math.max(Number(e.target.value), minVal + step);
794
+ setStateValue([minVal, val]);
795
+ onChange?.([minVal, val]);
796
+ };
797
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("w-full flex items-center gap-4", className), children: [
798
+ /* @__PURE__ */ jsxs("div", { className: "relative w-full flex items-center h-6 select-none touch-none", children: [
799
+ /* @__PURE__ */ jsx("div", { className: "w-full h-2 rounded-full bg-[var(--ui-border-default)] overflow-hidden relative", children: /* @__PURE__ */ jsx(
800
+ "div",
801
+ {
802
+ className: "absolute h-full bg-[var(--ui-primary)]",
803
+ style: {
804
+ left: `${minPercentage}%`,
805
+ width: `${maxPercentage - minPercentage}%`
806
+ }
807
+ }
808
+ ) }),
809
+ /* @__PURE__ */ jsx(
810
+ "input",
811
+ {
812
+ type: "range",
813
+ min,
814
+ max,
815
+ step,
816
+ value: minVal,
817
+ disabled,
818
+ onChange: handleMinChange,
819
+ className: "absolute inset-0 w-full h-full opacity-0 pointer-events-auto cursor-pointer z-20"
820
+ }
821
+ ),
822
+ /* @__PURE__ */ jsx(
823
+ "input",
824
+ {
825
+ type: "range",
826
+ min,
827
+ max,
828
+ step,
829
+ value: maxVal,
830
+ disabled,
831
+ onChange: handleMaxChange,
832
+ className: "absolute inset-0 w-full h-full opacity-0 pointer-events-auto cursor-pointer z-30"
833
+ }
834
+ ),
835
+ /* @__PURE__ */ jsx(
836
+ "div",
837
+ {
838
+ className: "absolute w-5 h-5 rounded-full bg-white border-2 border-[var(--ui-primary)] shadow-md pointer-events-none -translate-x-1/2 z-10",
839
+ style: { left: `${minPercentage}%` }
840
+ }
841
+ ),
842
+ /* @__PURE__ */ jsx(
843
+ "div",
844
+ {
845
+ className: "absolute w-5 h-5 rounded-full bg-white border-2 border-[var(--ui-primary)] shadow-md pointer-events-none -translate-x-1/2 z-10",
846
+ style: { left: `${maxPercentage}%` }
847
+ }
848
+ )
849
+ ] }),
850
+ showValue && /* @__PURE__ */ jsxs("span", { className: "text-xs font-semibold font-mono text-[var(--ui-text-secondary)] min-w-[5rem] text-right", children: [
851
+ formatValue(minVal),
852
+ " - ",
853
+ formatValue(maxVal)
854
+ ] })
855
+ ] });
856
+ }
857
+ );
858
+ RangeSlider.displayName = "RangeSlider";
859
+ var PinInput = forwardRef(
860
+ ({
861
+ className,
862
+ length = 4,
863
+ value: controlledValue,
864
+ defaultValue = "",
865
+ onChange,
866
+ onComplete,
867
+ mask = false,
868
+ disabled = false,
869
+ isInvalid = false,
870
+ autoFocus = false,
871
+ ...props
872
+ }, ref) => {
873
+ const [pins, setPins] = useState(() => {
874
+ const initial = (controlledValue !== void 0 ? controlledValue : defaultValue).slice(0, length);
875
+ return Array.from({ length }, (_, i) => initial[i] || "");
876
+ });
877
+ const inputsRef = useRef([]);
878
+ useEffect(() => {
879
+ if (controlledValue !== void 0) {
880
+ setPins(Array.from({ length }, (_, i) => controlledValue[i] || ""));
881
+ }
882
+ }, [controlledValue, length]);
883
+ useEffect(() => {
884
+ if (autoFocus && inputsRef.current[0]) {
885
+ inputsRef.current[0].focus();
886
+ }
887
+ }, [autoFocus]);
888
+ const handleDigitChange = (index, val) => {
889
+ const sanitized = val.replace(/[^0-9a-zA-Z]/g, "").slice(-1);
890
+ const newPins = [...pins];
891
+ newPins[index] = sanitized;
892
+ setPins(newPins);
893
+ const combined = newPins.join("");
894
+ onChange?.(combined);
895
+ if (sanitized && index < length - 1) {
896
+ inputsRef.current[index + 1]?.focus();
897
+ }
898
+ if (combined.length === length && !newPins.includes("")) {
899
+ onComplete?.(combined);
900
+ }
901
+ };
902
+ const handleKeyDown = (index, e) => {
903
+ if (e.key === "Backspace" && !pins[index] && index > 0) {
904
+ inputsRef.current[index - 1]?.focus();
905
+ }
906
+ };
907
+ const handlePaste = (e) => {
908
+ e.preventDefault();
909
+ const pasted = e.clipboardData.getData("text").slice(0, length);
910
+ if (!pasted) return;
911
+ const newPins = Array.from({ length }, (_, i) => pasted[i] || "");
912
+ setPins(newPins);
913
+ const combined = newPins.join("");
914
+ onChange?.(combined);
915
+ const nextEmptyIndex = newPins.findIndex((p) => !p);
916
+ const focusIndex = nextEmptyIndex === -1 ? length - 1 : nextEmptyIndex;
917
+ inputsRef.current[focusIndex]?.focus();
918
+ if (combined.length === length && !newPins.includes("")) {
919
+ onComplete?.(combined);
920
+ }
921
+ };
922
+ return /* @__PURE__ */ jsx("div", { ref, role: "group", "aria-label": "PIN Code Input", className: cn("flex items-center gap-2", className), ...props, children: Array.from({ length }).map((_, index) => /* @__PURE__ */ jsx(
923
+ "input",
924
+ {
925
+ ref: (el) => {
926
+ inputsRef.current[index] = el;
927
+ },
928
+ type: mask ? "password" : "text",
929
+ inputMode: "numeric",
930
+ maxLength: 1,
931
+ disabled,
932
+ value: pins[index],
933
+ onChange: (e) => handleDigitChange(index, e.target.value),
934
+ onKeyDown: (e) => handleKeyDown(index, e),
935
+ onPaste: handlePaste,
936
+ className: cn(
937
+ "w-11 h-12 text-center text-lg font-bold font-mono rounded-[var(--ui-radius-md)] border bg-[var(--ui-bg-surface)] text-[var(--ui-text-primary)] transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary)] disabled:opacity-50 disabled:cursor-not-allowed",
938
+ isInvalid ? "border-[var(--ui-error)] focus-visible:ring-[var(--ui-error)]" : "border-[var(--ui-border-default)] hover:border-[var(--ui-border-strong)]"
939
+ )
940
+ },
941
+ index
942
+ )) });
943
+ }
944
+ );
945
+ PinInput.displayName = "PinInput";
946
+ function formatDate(d) {
947
+ if (!d) return "";
948
+ const year = d.getFullYear();
949
+ const month = String(d.getMonth() + 1).padStart(2, "0");
950
+ const day = String(d.getDate()).padStart(2, "0");
951
+ return `${year}-${month}-${day}`;
952
+ }
953
+ function formatDisplayDate(d) {
954
+ if (!d) return "";
955
+ return d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
956
+ }
957
+ var DatePicker = forwardRef(
958
+ ({
959
+ value: controlledValue,
960
+ defaultValue,
961
+ onChange,
962
+ placeholder = "Select date...",
963
+ minDate,
964
+ maxDate,
965
+ disabled = false,
966
+ clearable = true,
967
+ className,
968
+ presets
969
+ }, ref) => {
970
+ const [internalDate, setInternalDate] = useState(
971
+ defaultValue !== void 0 ? defaultValue : null
972
+ );
973
+ const selectedDate = controlledValue !== void 0 ? controlledValue : internalDate;
974
+ const [viewDate, setViewDate] = useState(selectedDate || /* @__PURE__ */ new Date());
975
+ const [isOpen, setIsOpen] = useState(false);
976
+ useEffect(() => {
977
+ if (selectedDate) {
978
+ setViewDate(selectedDate);
979
+ }
980
+ }, [selectedDate]);
981
+ const handleSelectDate = (d) => {
982
+ setInternalDate(d);
983
+ onChange?.(d);
984
+ setIsOpen(false);
985
+ };
986
+ const handleClear = (e) => {
987
+ e.stopPropagation();
988
+ setInternalDate(null);
989
+ onChange?.(null);
990
+ };
991
+ const prevMonth = () => {
992
+ setViewDate(new Date(viewDate.getFullYear(), viewDate.getMonth() - 1, 1));
993
+ };
994
+ const nextMonth = () => {
995
+ setViewDate(new Date(viewDate.getFullYear(), viewDate.getMonth() + 1, 1));
996
+ };
997
+ const year = viewDate.getFullYear();
998
+ const month = viewDate.getMonth();
999
+ const firstDayIndex = new Date(year, month, 1).getDay();
1000
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
1001
+ const daysInPrevMonth = new Date(year, month, 0).getDate();
1002
+ const days = [];
1003
+ for (let i = firstDayIndex - 1; i >= 0; i--) {
1004
+ const d = new Date(year, month - 1, daysInPrevMonth - i);
1005
+ const isDis = minDate && d < minDate || maxDate && d > maxDate;
1006
+ days.push({ date: d, currentMonth: false, disabled: Boolean(isDis) });
1007
+ }
1008
+ for (let i = 1; i <= daysInMonth; i++) {
1009
+ const d = new Date(year, month, i);
1010
+ const isDis = minDate && d < minDate || maxDate && d > maxDate;
1011
+ days.push({ date: d, currentMonth: true, disabled: Boolean(isDis) });
1012
+ }
1013
+ const totalSlots = days.length > 35 ? 42 : 35;
1014
+ const remainingSlots = totalSlots - days.length;
1015
+ for (let i = 1; i <= remainingSlots; i++) {
1016
+ const d = new Date(year, month + 1, i);
1017
+ const isDis = minDate && d < minDate || maxDate && d > maxDate;
1018
+ days.push({ date: d, currentMonth: false, disabled: Boolean(isDis) });
1019
+ }
1020
+ const todayStr = formatDate(/* @__PURE__ */ new Date());
1021
+ const selectedStr = selectedDate ? formatDate(selectedDate) : "";
1022
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("relative inline-block w-full", className), children: /* @__PURE__ */ jsx(
1023
+ Popover,
1024
+ {
1025
+ isOpen,
1026
+ onClose: () => setIsOpen(false),
1027
+ trigger: /* @__PURE__ */ jsxs(
1028
+ "button",
1029
+ {
1030
+ type: "button",
1031
+ disabled,
1032
+ onClick: () => !disabled && setIsOpen(!isOpen),
1033
+ className: cn(
1034
+ "w-full h-10 px-3.5 rounded-[var(--ui-radius-md)] border bg-[var(--ui-bg-surface)] text-left flex items-center justify-between text-sm transition-all shadow-inner cursor-pointer",
1035
+ disabled ? "opacity-50 cursor-not-allowed border-[var(--ui-border-subtle)]" : "border-[var(--ui-border-default)] hover:border-[var(--ui-border-strong)] focus:ring-2 focus:ring-[var(--ui-primary)]/50"
1036
+ ),
1037
+ children: [
1038
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 truncate", children: [
1039
+ /* @__PURE__ */ jsx(Calendar, { className: "w-4 h-4 text-[var(--ui-text-muted)] shrink-0" }),
1040
+ /* @__PURE__ */ jsx("span", { className: selectedDate ? "text-[var(--ui-text-primary)] font-medium" : "text-[var(--ui-text-muted)]", children: selectedDate ? formatDisplayDate(selectedDate) : placeholder })
1041
+ ] }),
1042
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1 text-[var(--ui-text-muted)]", children: clearable && selectedDate && !disabled && /* @__PURE__ */ jsx(
1043
+ "span",
1044
+ {
1045
+ onClick: handleClear,
1046
+ className: "p-1 rounded-full hover:bg-[var(--ui-bg-tertiary)] hover:text-[var(--ui-text-primary)] transition-colors",
1047
+ children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5" })
1048
+ }
1049
+ ) })
1050
+ ]
1051
+ }
1052
+ ),
1053
+ children: /* @__PURE__ */ jsxs("div", { className: "p-4 w-72 rounded-2xl bg-[var(--ui-bg-surface)] backdrop-blur-2xl border border-[var(--ui-border-default)] shadow-2xl space-y-3", children: [
1054
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1055
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-bold text-[var(--ui-text-primary)] font-mono uppercase tracking-wider", children: viewDate.toLocaleString("default", { month: "long", year: "numeric" }) }),
1056
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
1057
+ /* @__PURE__ */ jsx(
1058
+ "button",
1059
+ {
1060
+ type: "button",
1061
+ onClick: prevMonth,
1062
+ className: "p-1 rounded-lg hover:bg-[var(--ui-bg-tertiary)] text-[var(--ui-text-muted)] hover:text-[var(--ui-text-primary)] transition-colors",
1063
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "w-4 h-4" })
1064
+ }
1065
+ ),
1066
+ /* @__PURE__ */ jsx(
1067
+ "button",
1068
+ {
1069
+ type: "button",
1070
+ onClick: nextMonth,
1071
+ className: "p-1 rounded-lg hover:bg-[var(--ui-bg-tertiary)] text-[var(--ui-text-muted)] hover:text-[var(--ui-text-primary)] transition-colors",
1072
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "w-4 h-4" })
1073
+ }
1074
+ )
1075
+ ] })
1076
+ ] }),
1077
+ presets && presets.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1 pb-2 border-b border-[var(--ui-border-subtle)]", children: presets.map((preset, idx) => /* @__PURE__ */ jsx(
1078
+ "button",
1079
+ {
1080
+ type: "button",
1081
+ onClick: () => handleSelectDate(preset.date),
1082
+ className: "px-2 py-0.5 rounded-md text-[10px] font-semibold bg-[var(--ui-bg-secondary)] hover:bg-[var(--ui-bg-tertiary)] text-[var(--ui-text-secondary)] transition-colors",
1083
+ children: preset.label
1084
+ },
1085
+ idx
1086
+ )) }),
1087
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 text-center text-[10px] font-bold text-[var(--ui-text-muted)] font-mono", children: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((d) => /* @__PURE__ */ jsx("div", { className: "py-1", children: d }, d)) }),
1088
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-1", children: days.map((item, idx) => {
1089
+ const itemStr = formatDate(item.date);
1090
+ const isSelected = itemStr === selectedStr;
1091
+ const isToday = itemStr === todayStr;
1092
+ return /* @__PURE__ */ jsx(
1093
+ "button",
1094
+ {
1095
+ type: "button",
1096
+ disabled: item.disabled,
1097
+ onClick: () => handleSelectDate(item.date),
1098
+ className: cn(
1099
+ "h-8 w-8 rounded-full text-xs font-semibold flex items-center justify-center transition-all cursor-pointer",
1100
+ item.disabled && "opacity-25 cursor-not-allowed pointer-events-none",
1101
+ !item.currentMonth && "text-[var(--ui-text-muted)] opacity-50",
1102
+ isSelected ? "bg-[var(--ui-primary)] text-white font-bold shadow-md shadow-blue-500/30" : isToday ? "border border-[var(--ui-primary)] text-[var(--ui-primary)]" : "hover:bg-[var(--ui-bg-tertiary)] text-[var(--ui-text-primary)]"
1103
+ ),
1104
+ children: item.date.getDate()
1105
+ },
1106
+ idx
1107
+ );
1108
+ }) })
1109
+ ] })
1110
+ }
1111
+ ) });
1112
+ }
1113
+ );
1114
+ DatePicker.displayName = "DatePicker";
1115
+ var DateRangePicker = forwardRef(
1116
+ ({ value: controlledVal, defaultValue, onChange, placeholder = "Select date range...", className, disabled = false }, ref) => {
1117
+ const [internalRange, setInternalRange] = useState(
1118
+ defaultValue || { from: null, to: null }
1119
+ );
1120
+ const range = controlledVal || internalRange;
1121
+ const [viewDate, setViewDate] = useState(range.from || /* @__PURE__ */ new Date());
1122
+ const [isOpen, setIsOpen] = useState(false);
1123
+ const handleDayClick = (d) => {
1124
+ let next;
1125
+ if (!range.from || range.from && range.to) {
1126
+ next = { from: d, to: null };
1127
+ } else {
1128
+ if (d < range.from) {
1129
+ next = { from: d, to: range.from };
1130
+ } else {
1131
+ next = { from: range.from, to: d };
1132
+ setIsOpen(false);
1133
+ }
1134
+ }
1135
+ setInternalRange(next);
1136
+ onChange?.(next);
1137
+ };
1138
+ const displayText = range.from && range.to ? `${formatDisplayDate(range.from)} \u2013 ${formatDisplayDate(range.to)}` : range.from ? `${formatDisplayDate(range.from)} \u2013 ...` : placeholder;
1139
+ const year = viewDate.getFullYear();
1140
+ const month = viewDate.getMonth();
1141
+ const firstDayIndex = new Date(year, month, 1).getDay();
1142
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
1143
+ const days = [];
1144
+ for (let i = 1; i <= daysInMonth; i++) {
1145
+ days.push(new Date(year, month, i));
1146
+ }
1147
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("relative inline-block w-full", className), children: /* @__PURE__ */ jsx(
1148
+ Popover,
1149
+ {
1150
+ isOpen,
1151
+ onClose: () => setIsOpen(false),
1152
+ trigger: /* @__PURE__ */ jsx(
1153
+ "button",
1154
+ {
1155
+ type: "button",
1156
+ disabled,
1157
+ onClick: () => !disabled && setIsOpen(!isOpen),
1158
+ className: "w-full h-10 px-3.5 rounded-[var(--ui-radius-md)] border border-[var(--ui-border-default)] hover:border-[var(--ui-border-strong)] bg-[var(--ui-bg-surface)] text-left flex items-center justify-between text-sm shadow-inner cursor-pointer",
1159
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 truncate", children: [
1160
+ /* @__PURE__ */ jsx(Calendar, { className: "w-4 h-4 text-[var(--ui-text-muted)] shrink-0" }),
1161
+ /* @__PURE__ */ jsx("span", { className: range.from ? "text-[var(--ui-text-primary)] font-medium" : "text-[var(--ui-text-muted)]", children: displayText })
1162
+ ] })
1163
+ }
1164
+ ),
1165
+ children: /* @__PURE__ */ jsxs("div", { className: "p-4 w-76 rounded-2xl bg-[var(--ui-bg-surface)] backdrop-blur-2xl border border-[var(--ui-border-default)] shadow-2xl space-y-3", children: [
1166
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1167
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-bold text-[var(--ui-text-primary)] font-mono uppercase tracking-wider", children: viewDate.toLocaleString("default", { month: "long", year: "numeric" }) }),
1168
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
1169
+ /* @__PURE__ */ jsx(
1170
+ "button",
1171
+ {
1172
+ type: "button",
1173
+ onClick: () => setViewDate(new Date(year, month - 1, 1)),
1174
+ className: "p-1 rounded-lg hover:bg-[var(--ui-bg-tertiary)]",
1175
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "w-4 h-4" })
1176
+ }
1177
+ ),
1178
+ /* @__PURE__ */ jsx(
1179
+ "button",
1180
+ {
1181
+ type: "button",
1182
+ onClick: () => setViewDate(new Date(year, month + 1, 1)),
1183
+ className: "p-1 rounded-lg hover:bg-[var(--ui-bg-tertiary)]",
1184
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "w-4 h-4" })
1185
+ }
1186
+ )
1187
+ ] })
1188
+ ] }),
1189
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-7 gap-1 text-center", children: [
1190
+ Array.from({ length: firstDayIndex }).map((_, i) => /* @__PURE__ */ jsx("div", {}, `empty-${i}`)),
1191
+ days.map((d, idx) => {
1192
+ const dStr = formatDate(d);
1193
+ const fromStr = range.from ? formatDate(range.from) : "";
1194
+ const toStr = range.to ? formatDate(range.to) : "";
1195
+ const isFrom = dStr === fromStr;
1196
+ const isTo = dStr === toStr;
1197
+ const isInRange = range.from && range.to && d > range.from && d < range.to;
1198
+ return /* @__PURE__ */ jsx(
1199
+ "button",
1200
+ {
1201
+ type: "button",
1202
+ onClick: () => handleDayClick(d),
1203
+ className: cn(
1204
+ "h-8 w-8 rounded-full text-xs font-semibold flex items-center justify-center transition-all cursor-pointer",
1205
+ (isFrom || isTo) && "bg-[var(--ui-primary)] text-white shadow-md",
1206
+ isInRange && "bg-[var(--ui-primary)]/20 text-[var(--ui-primary)] rounded-none",
1207
+ !isFrom && !isTo && !isInRange && "hover:bg-[var(--ui-bg-tertiary)] text-[var(--ui-text-primary)]"
1208
+ ),
1209
+ children: d.getDate()
1210
+ },
1211
+ idx
1212
+ );
1213
+ })
1214
+ ] })
1215
+ ] })
1216
+ }
1217
+ ) });
1218
+ }
1219
+ );
1220
+ DateRangePicker.displayName = "DateRangePicker";
1221
+ var TimePicker = forwardRef(
1222
+ ({ value: controlledVal, defaultValue = "12:00", onChange, format = "24h", className, disabled = false }, ref) => {
1223
+ const [internalTime, setInternalTime] = useState(defaultValue);
1224
+ const time = controlledVal !== void 0 ? controlledVal : internalTime;
1225
+ const [hours, setHours] = useState(time.split(":")[0] || "12");
1226
+ const [minutes, setMinutes] = useState(time.split(":")[1] || "00");
1227
+ const [isOpen, setIsOpen] = useState(false);
1228
+ const updateTime = (newH, newM) => {
1229
+ const full = `${newH.padStart(2, "0")}:${newM.padStart(2, "0")}`;
1230
+ setHours(newH);
1231
+ setMinutes(newM);
1232
+ setInternalTime(full);
1233
+ onChange?.(full);
1234
+ };
1235
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("relative inline-block w-full", className), children: /* @__PURE__ */ jsx(
1236
+ Popover,
1237
+ {
1238
+ isOpen,
1239
+ onClose: () => setIsOpen(false),
1240
+ trigger: /* @__PURE__ */ jsx(
1241
+ "button",
1242
+ {
1243
+ type: "button",
1244
+ disabled,
1245
+ onClick: () => !disabled && setIsOpen(!isOpen),
1246
+ className: "w-full h-10 px-3.5 rounded-[var(--ui-radius-md)] border border-[var(--ui-border-default)] hover:border-[var(--ui-border-strong)] bg-[var(--ui-bg-surface)] text-left flex items-center justify-between text-sm shadow-inner cursor-pointer",
1247
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5", children: [
1248
+ /* @__PURE__ */ jsx(Clock, { className: "w-4 h-4 text-[var(--ui-text-muted)]" }),
1249
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-sm font-semibold text-[var(--ui-text-primary)]", children: time })
1250
+ ] })
1251
+ }
1252
+ ),
1253
+ children: /* @__PURE__ */ jsxs("div", { className: "p-4 w-52 rounded-2xl bg-[var(--ui-bg-surface)] backdrop-blur-2xl border border-[var(--ui-border-default)] shadow-2xl space-y-3", children: [
1254
+ /* @__PURE__ */ jsxs("span", { className: "text-xs font-bold text-[var(--ui-text-muted)] uppercase tracking-wider font-mono", children: [
1255
+ "Select Time (",
1256
+ format,
1257
+ ")"
1258
+ ] }),
1259
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2", children: [
1260
+ /* @__PURE__ */ jsx("div", { className: "h-36 overflow-y-auto border border-[var(--ui-border-subtle)] rounded-xl p-1 w-16 text-center space-y-1", children: Array.from({ length: 24 }).map((_, i) => {
1261
+ const h = String(i).padStart(2, "0");
1262
+ return /* @__PURE__ */ jsx(
1263
+ "div",
1264
+ {
1265
+ onClick: () => updateTime(h, minutes),
1266
+ className: cn(
1267
+ "text-xs py-1 rounded-lg font-mono font-semibold cursor-pointer transition-colors",
1268
+ hours === h ? "bg-[var(--ui-primary)] text-white" : "hover:bg-[var(--ui-bg-tertiary)] text-[var(--ui-text-primary)]"
1269
+ ),
1270
+ children: h
1271
+ },
1272
+ h
1273
+ );
1274
+ }) }),
1275
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-bold", children: ":" }),
1276
+ /* @__PURE__ */ jsx("div", { className: "h-36 overflow-y-auto border border-[var(--ui-border-subtle)] rounded-xl p-1 w-16 text-center space-y-1", children: ["00", "05", "10", "15", "20", "25", "30", "35", "40", "41", "45", "50", "55"].map((m) => /* @__PURE__ */ jsx(
1277
+ "div",
1278
+ {
1279
+ onClick: () => updateTime(hours, m),
1280
+ className: cn(
1281
+ "text-xs py-1 rounded-lg font-mono font-semibold cursor-pointer transition-colors",
1282
+ minutes === m ? "bg-[var(--ui-primary)] text-white" : "hover:bg-[var(--ui-bg-tertiary)] text-[var(--ui-text-primary)]"
1283
+ ),
1284
+ children: m
1285
+ },
1286
+ m
1287
+ )) })
1288
+ ] })
1289
+ ] })
1290
+ }
1291
+ ) });
1292
+ }
1293
+ );
1294
+ TimePicker.displayName = "TimePicker";
1295
+ var Combobox = forwardRef(
1296
+ ({
1297
+ options,
1298
+ value: controlledVal,
1299
+ defaultValue = "",
1300
+ onChange,
1301
+ placeholder = "Select option...",
1302
+ searchPlaceholder = "Search items...",
1303
+ emptyText = "No items found.",
1304
+ disabled = false,
1305
+ clearable = true,
1306
+ className
1307
+ }, ref) => {
1308
+ const [internalVal, setInternalVal] = useState(defaultValue);
1309
+ const selectedValue = controlledVal !== void 0 ? controlledVal : internalVal;
1310
+ const [search, setSearch] = useState("");
1311
+ const [isOpen, setIsOpen] = useState(false);
1312
+ const [highlightIndex, setHighlightIndex] = useState(0);
1313
+ const filteredOptions = options.filter(
1314
+ (opt) => opt.label.toLowerCase().includes(search.toLowerCase()) || opt.value.toLowerCase().includes(search.toLowerCase()) || opt.description && opt.description.toLowerCase().includes(search.toLowerCase())
1315
+ );
1316
+ const selectedOption = options.find((opt) => opt.value === selectedValue);
1317
+ const handleSelect = (val) => {
1318
+ setInternalVal(val);
1319
+ onChange?.(val);
1320
+ setIsOpen(false);
1321
+ setSearch("");
1322
+ };
1323
+ const handleClear = (e) => {
1324
+ e.stopPropagation();
1325
+ setInternalVal("");
1326
+ onChange?.("");
1327
+ };
1328
+ const handleKeyDown = (e) => {
1329
+ if (!isOpen) {
1330
+ if (e.key === "ArrowDown" || e.key === "Enter") {
1331
+ setIsOpen(true);
1332
+ }
1333
+ return;
1334
+ }
1335
+ if (e.key === "ArrowDown") {
1336
+ e.preventDefault();
1337
+ setHighlightIndex((prev) => (prev + 1) % Math.max(1, filteredOptions.length));
1338
+ } else if (e.key === "ArrowUp") {
1339
+ e.preventDefault();
1340
+ setHighlightIndex((prev) => (prev - 1 + filteredOptions.length) % Math.max(1, filteredOptions.length));
1341
+ } else if (e.key === "Enter") {
1342
+ e.preventDefault();
1343
+ if (filteredOptions[highlightIndex] && !filteredOptions[highlightIndex].disabled) {
1344
+ handleSelect(filteredOptions[highlightIndex].value);
1345
+ }
1346
+ } else if (e.key === "Escape") {
1347
+ setIsOpen(false);
1348
+ }
1349
+ };
1350
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("relative w-full", className), children: /* @__PURE__ */ jsx(
1351
+ Popover,
1352
+ {
1353
+ isOpen,
1354
+ onClose: () => setIsOpen(false),
1355
+ trigger: /* @__PURE__ */ jsxs(
1356
+ "button",
1357
+ {
1358
+ type: "button",
1359
+ disabled,
1360
+ onClick: () => !disabled && setIsOpen(!isOpen),
1361
+ onKeyDown: handleKeyDown,
1362
+ className: cn(
1363
+ "w-full h-10 px-3.5 rounded-[var(--ui-radius-md)] border bg-[var(--ui-bg-surface)] text-left flex items-center justify-between text-sm transition-all shadow-inner cursor-pointer",
1364
+ disabled ? "opacity-50 cursor-not-allowed border-[var(--ui-border-subtle)]" : "border-[var(--ui-border-default)] hover:border-[var(--ui-border-strong)] focus:ring-2 focus:ring-[var(--ui-primary)]/50"
1365
+ ),
1366
+ children: [
1367
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 truncate", children: [
1368
+ selectedOption?.icon,
1369
+ /* @__PURE__ */ jsx("span", { className: selectedOption ? "text-[var(--ui-text-primary)] font-medium" : "text-[var(--ui-text-muted)]", children: selectedOption ? selectedOption.label : placeholder })
1370
+ ] }),
1371
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-[var(--ui-text-muted)]", children: [
1372
+ clearable && selectedValue && !disabled && /* @__PURE__ */ jsx(
1373
+ "span",
1374
+ {
1375
+ onClick: handleClear,
1376
+ className: "p-1 rounded-full hover:bg-[var(--ui-bg-tertiary)] hover:text-[var(--ui-text-primary)] transition-colors",
1377
+ children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5" })
1378
+ }
1379
+ ),
1380
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: "w-4 h-4 opacity-50 shrink-0" })
1381
+ ] })
1382
+ ]
1383
+ }
1384
+ ),
1385
+ children: /* @__PURE__ */ jsxs("div", { className: "p-2 w-72 rounded-2xl bg-[var(--ui-bg-surface)] backdrop-blur-2xl border border-[var(--ui-border-default)] shadow-2xl space-y-2", children: [
1386
+ /* @__PURE__ */ jsxs("div", { className: "relative flex items-center", children: [
1387
+ /* @__PURE__ */ jsx(Search, { className: "absolute left-2.5 w-3.5 h-3.5 text-[var(--ui-text-muted)] pointer-events-none" }),
1388
+ /* @__PURE__ */ jsx(
1389
+ "input",
1390
+ {
1391
+ type: "text",
1392
+ autoFocus: true,
1393
+ placeholder: searchPlaceholder,
1394
+ value: search,
1395
+ onChange: (e) => {
1396
+ setSearch(e.target.value);
1397
+ setHighlightIndex(0);
1398
+ },
1399
+ className: "w-full h-8 pl-8 pr-3 text-xs rounded-xl bg-[var(--ui-bg-secondary)] border border-[var(--ui-border-subtle)] focus:outline-none focus:border-[var(--ui-primary)] text-[var(--ui-text-primary)] placeholder:text-[var(--ui-text-muted)]"
1400
+ }
1401
+ )
1402
+ ] }),
1403
+ /* @__PURE__ */ jsx("div", { className: "max-h-56 overflow-y-auto space-y-0.5", role: "listbox", children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx("div", { className: "py-4 text-center text-xs text-[var(--ui-text-muted)]", children: emptyText }) : filteredOptions.map((opt, idx) => {
1404
+ const isSelected = opt.value === selectedValue;
1405
+ const isHighlighted = idx === highlightIndex;
1406
+ return /* @__PURE__ */ jsxs(
1407
+ "div",
1408
+ {
1409
+ role: "option",
1410
+ "aria-selected": isSelected,
1411
+ onClick: () => !opt.disabled && handleSelect(opt.value),
1412
+ onMouseEnter: () => setHighlightIndex(idx),
1413
+ className: cn(
1414
+ "flex items-center justify-between px-3 py-2 rounded-xl text-xs font-medium cursor-pointer transition-colors",
1415
+ opt.disabled && "opacity-40 cursor-not-allowed pointer-events-none",
1416
+ isSelected ? "bg-[var(--ui-primary)] text-white font-semibold shadow-xs" : isHighlighted ? "bg-[var(--ui-bg-tertiary)] text-[var(--ui-text-primary)]" : "text-[var(--ui-text-primary)]"
1417
+ ),
1418
+ children: [
1419
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 truncate", children: [
1420
+ opt.icon,
1421
+ /* @__PURE__ */ jsxs("div", { children: [
1422
+ /* @__PURE__ */ jsx("span", { className: "block truncate", children: opt.label }),
1423
+ opt.description && /* @__PURE__ */ jsx("span", { className: cn("text-[10px] block truncate", isSelected ? "text-white/80" : "text-[var(--ui-text-muted)]"), children: opt.description })
1424
+ ] })
1425
+ ] }),
1426
+ isSelected && /* @__PURE__ */ jsx(Check, { className: "w-3.5 h-3.5 shrink-0" })
1427
+ ]
1428
+ },
1429
+ opt.value
1430
+ );
1431
+ }) })
1432
+ ] })
1433
+ }
1434
+ ) });
1435
+ }
1436
+ );
1437
+ Combobox.displayName = "Combobox";
1438
+ var MultiSelect = forwardRef(
1439
+ ({
1440
+ options,
1441
+ value: controlledVal,
1442
+ defaultValue = [],
1443
+ onChange,
1444
+ placeholder = "Select items...",
1445
+ searchPlaceholder = "Search options...",
1446
+ maxCount = 3,
1447
+ disabled = false,
1448
+ className
1449
+ }, ref) => {
1450
+ const [internalVal, setInternalVal] = useState(defaultValue);
1451
+ const selectedValues = controlledVal !== void 0 ? controlledVal : internalVal;
1452
+ const [search, setSearch] = useState("");
1453
+ const [isOpen, setIsOpen] = useState(false);
1454
+ const filteredOptions = options.filter(
1455
+ (opt) => opt.label.toLowerCase().includes(search.toLowerCase()) || opt.value.toLowerCase().includes(search.toLowerCase())
1456
+ );
1457
+ const toggleOption = (val) => {
1458
+ const next = selectedValues.includes(val) ? selectedValues.filter((v) => v !== val) : [...selectedValues, val];
1459
+ setInternalVal(next);
1460
+ onChange?.(next);
1461
+ };
1462
+ const removeTag = (val, e) => {
1463
+ e?.stopPropagation?.();
1464
+ const next = selectedValues.filter((v) => v !== val);
1465
+ setInternalVal(next);
1466
+ onChange?.(next);
1467
+ };
1468
+ const clearAll = (e) => {
1469
+ e?.stopPropagation?.();
1470
+ setInternalVal([]);
1471
+ onChange?.([]);
1472
+ };
1473
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("relative w-full", className), children: /* @__PURE__ */ jsx(
1474
+ Popover,
1475
+ {
1476
+ isOpen,
1477
+ onClose: () => setIsOpen(false),
1478
+ trigger: /* @__PURE__ */ jsxs(
1479
+ "div",
1480
+ {
1481
+ onClick: () => !disabled && setIsOpen(!isOpen),
1482
+ className: cn(
1483
+ "min-h-10 py-1.5 px-3 rounded-[var(--ui-radius-md)] border bg-[var(--ui-bg-surface)] flex flex-wrap items-center justify-between gap-1.5 text-sm transition-all shadow-inner cursor-pointer",
1484
+ disabled ? "opacity-50 cursor-not-allowed border-[var(--ui-border-subtle)]" : "border-[var(--ui-border-default)] hover:border-[var(--ui-border-strong)]"
1485
+ ),
1486
+ children: [
1487
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-1.5 flex-1", children: selectedValues.length === 0 ? /* @__PURE__ */ jsx("span", { className: "text-[var(--ui-text-muted)] text-sm", children: placeholder }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1488
+ selectedValues.slice(0, maxCount).map((val) => {
1489
+ const opt = options.find((o) => o.value === val);
1490
+ return /* @__PURE__ */ jsx(
1491
+ Chip,
1492
+ {
1493
+ size: "sm",
1494
+ variant: "primary",
1495
+ onRemove: () => removeTag(val, {}),
1496
+ children: opt?.label || val
1497
+ },
1498
+ val
1499
+ );
1500
+ }),
1501
+ selectedValues.length > maxCount && /* @__PURE__ */ jsxs(Chip, { size: "sm", variant: "secondary", children: [
1502
+ "+",
1503
+ selectedValues.length - maxCount,
1504
+ " more"
1505
+ ] })
1506
+ ] }) }),
1507
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-[var(--ui-text-muted)]", children: [
1508
+ selectedValues.length > 0 && !disabled && /* @__PURE__ */ jsx(
1509
+ "span",
1510
+ {
1511
+ onClick: clearAll,
1512
+ className: "p-1 rounded-full hover:bg-[var(--ui-bg-tertiary)] hover:text-[var(--ui-text-primary)] transition-colors",
1513
+ children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5" })
1514
+ }
1515
+ ),
1516
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: "w-4 h-4 opacity-50 shrink-0" })
1517
+ ] })
1518
+ ]
1519
+ }
1520
+ ),
1521
+ children: /* @__PURE__ */ jsxs("div", { className: "p-2 w-76 rounded-2xl bg-[var(--ui-bg-surface)] backdrop-blur-2xl border border-[var(--ui-border-default)] shadow-2xl space-y-2", children: [
1522
+ /* @__PURE__ */ jsxs("div", { className: "relative flex items-center", children: [
1523
+ /* @__PURE__ */ jsx(Search, { className: "absolute left-2.5 w-3.5 h-3.5 text-[var(--ui-text-muted)] pointer-events-none" }),
1524
+ /* @__PURE__ */ jsx(
1525
+ "input",
1526
+ {
1527
+ type: "text",
1528
+ autoFocus: true,
1529
+ placeholder: searchPlaceholder,
1530
+ value: search,
1531
+ onChange: (e) => setSearch(e.target.value),
1532
+ className: "w-full h-8 pl-8 pr-3 text-xs rounded-xl bg-[var(--ui-bg-secondary)] border border-[var(--ui-border-subtle)] focus:outline-none focus:border-[var(--ui-primary)] text-[var(--ui-text-primary)]"
1533
+ }
1534
+ )
1535
+ ] }),
1536
+ /* @__PURE__ */ jsx("div", { className: "max-h-56 overflow-y-auto space-y-0.5", children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx("div", { className: "py-4 text-center text-xs text-[var(--ui-text-muted)]", children: "No options found." }) : filteredOptions.map((opt) => {
1537
+ const isChecked = selectedValues.includes(opt.value);
1538
+ return /* @__PURE__ */ jsxs(
1539
+ "div",
1540
+ {
1541
+ onClick: () => toggleOption(opt.value),
1542
+ className: cn(
1543
+ "flex items-center justify-between px-3 py-2 rounded-xl text-xs font-medium cursor-pointer transition-colors",
1544
+ isChecked ? "bg-[var(--ui-primary)]/15 text-[var(--ui-primary)] font-semibold" : "hover:bg-[var(--ui-bg-tertiary)] text-[var(--ui-text-primary)]"
1545
+ ),
1546
+ children: [
1547
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 truncate", children: [
1548
+ opt.icon,
1549
+ /* @__PURE__ */ jsx("span", { children: opt.label })
1550
+ ] }),
1551
+ isChecked && /* @__PURE__ */ jsx(Check, { className: "w-3.5 h-3.5 text-[var(--ui-primary)] shrink-0" })
1552
+ ]
1553
+ },
1554
+ opt.value
1555
+ );
1556
+ }) })
1557
+ ] })
1558
+ }
1559
+ ) });
1560
+ }
1561
+ );
1562
+ MultiSelect.displayName = "MultiSelect";
1563
+ function formatFileSize(bytes) {
1564
+ if (bytes === 0) return "0 B";
1565
+ const k = 1024;
1566
+ const sizes = ["B", "KB", "MB", "GB"];
1567
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
1568
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
1569
+ }
1570
+ var FileUpload = forwardRef(
1571
+ ({
1572
+ accept,
1573
+ maxSizeMB = 10,
1574
+ multiple = true,
1575
+ maxFiles = 5,
1576
+ disabled = false,
1577
+ onFilesSelected,
1578
+ onFileRemove,
1579
+ className,
1580
+ label = "Drag & drop files here, or browse",
1581
+ description = "Supports images, documents, and media up to 10MB"
1582
+ }, ref) => {
1583
+ const [isDragOver, setIsDragOver] = useState(false);
1584
+ const [fileList, setFileList] = useState([]);
1585
+ const inputRef = useRef(null);
1586
+ const processFiles = (incoming) => {
1587
+ if (!incoming) return;
1588
+ const validFiles = [];
1589
+ const newUploaded = [];
1590
+ Array.from(incoming).forEach((file) => {
1591
+ if (fileList.length + newUploaded.length >= maxFiles) return;
1592
+ const isOversized = file.size > maxSizeMB * 1024 * 1024;
1593
+ const fileObj = {
1594
+ id: `${file.name}-${Date.now()}-${Math.random()}`,
1595
+ file,
1596
+ name: file.name,
1597
+ size: file.size,
1598
+ type: file.type,
1599
+ progress: isOversized ? 0 : 100,
1600
+ status: isOversized ? "error" : "completed",
1601
+ errorMessage: isOversized ? `File exceeds ${maxSizeMB}MB limit` : void 0,
1602
+ previewUrl: file.type.startsWith("image/") ? URL.createObjectURL(file) : void 0
1603
+ };
1604
+ newUploaded.push(fileObj);
1605
+ if (!isOversized) validFiles.push(file);
1606
+ });
1607
+ setFileList((prev) => [...prev, ...newUploaded]);
1608
+ if (validFiles.length > 0) {
1609
+ onFilesSelected?.(validFiles);
1610
+ }
1611
+ };
1612
+ const handleDragOver = (e) => {
1613
+ e.preventDefault();
1614
+ if (!disabled) setIsDragOver(true);
1615
+ };
1616
+ const handleDragLeave = (e) => {
1617
+ e.preventDefault();
1618
+ setIsDragOver(false);
1619
+ };
1620
+ const handleDrop = (e) => {
1621
+ e.preventDefault();
1622
+ setIsDragOver(false);
1623
+ if (disabled) return;
1624
+ processFiles(e.dataTransfer.files);
1625
+ };
1626
+ const handleFileChange = (e) => {
1627
+ processFiles(e.target.files);
1628
+ if (inputRef.current) inputRef.current.value = "";
1629
+ };
1630
+ const removeFile = (id) => {
1631
+ setFileList((prev) => prev.filter((f) => f.id !== id));
1632
+ onFileRemove?.(id);
1633
+ };
1634
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("w-full space-y-4", className), children: [
1635
+ /* @__PURE__ */ jsxs(
1636
+ "div",
1637
+ {
1638
+ onDragOver: handleDragOver,
1639
+ onDragLeave: handleDragLeave,
1640
+ onDrop: handleDrop,
1641
+ onClick: () => !disabled && inputRef.current?.click(),
1642
+ className: cn(
1643
+ "relative rounded-2xl p-6 sm:p-8 text-center border-2 border-dashed transition-all cursor-pointer flex flex-col items-center justify-center gap-3 select-none",
1644
+ disabled ? "opacity-50 cursor-not-allowed border-[var(--ui-border-subtle)] bg-[var(--ui-bg-secondary)]/30" : isDragOver ? "border-[var(--ui-primary)] bg-[var(--ui-primary)]/10 shadow-lg shadow-blue-500/20 scale-[0.99]" : "border-[var(--ui-border-default)] hover:border-[var(--ui-border-strong)] bg-[var(--ui-bg-surface)]/60 hover:bg-[var(--ui-bg-secondary)]"
1645
+ ),
1646
+ children: [
1647
+ /* @__PURE__ */ jsx(
1648
+ "input",
1649
+ {
1650
+ ref: inputRef,
1651
+ type: "file",
1652
+ accept,
1653
+ multiple,
1654
+ disabled,
1655
+ onChange: handleFileChange,
1656
+ className: "hidden"
1657
+ }
1658
+ ),
1659
+ /* @__PURE__ */ jsx("div", { className: "w-12 h-12 rounded-2xl bg-[var(--ui-primary)]/15 text-[var(--ui-primary)] flex items-center justify-center shadow-inner", children: /* @__PURE__ */ jsx(UploadCloud, { className: "w-6 h-6" }) }),
1660
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1661
+ /* @__PURE__ */ jsx("h4", { className: "text-sm font-bold text-[var(--ui-text-primary)]", children: label }),
1662
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--ui-text-muted)]", children: description })
1663
+ ] }),
1664
+ /* @__PURE__ */ jsx(Button, { size: "xs", variant: "outline", className: "rounded-full px-4 mt-1 pointer-events-none", children: "Browse Files" })
1665
+ ]
1666
+ }
1667
+ ),
1668
+ fileList.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1669
+ /* @__PURE__ */ jsxs("span", { className: "text-xs font-mono font-bold text-[var(--ui-text-muted)] uppercase tracking-wider", children: [
1670
+ "Files (",
1671
+ fileList.length,
1672
+ "/",
1673
+ maxFiles,
1674
+ ")"
1675
+ ] }),
1676
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: fileList.map((item) => /* @__PURE__ */ jsxs(
1677
+ "div",
1678
+ {
1679
+ className: "p-3 rounded-2xl bg-[var(--ui-bg-surface)] border border-[var(--ui-border-default)] flex items-center justify-between gap-3 shadow-xs animate-in fade-in duration-200",
1680
+ children: [
1681
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 truncate", children: [
1682
+ item.previewUrl ? /* @__PURE__ */ jsx(
1683
+ "img",
1684
+ {
1685
+ src: item.previewUrl,
1686
+ alt: item.name,
1687
+ className: "w-10 h-10 rounded-xl object-cover border border-[var(--ui-border-subtle)] shrink-0"
1688
+ }
1689
+ ) : /* @__PURE__ */ jsx("div", { className: "w-10 h-10 rounded-xl bg-[var(--ui-bg-tertiary)] flex items-center justify-center text-[var(--ui-text-muted)] shrink-0", children: item.type.includes("pdf") ? /* @__PURE__ */ jsx(FileText, { className: "w-5 h-5" }) : /* @__PURE__ */ jsx(File, { className: "w-5 h-5" }) }),
1690
+ /* @__PURE__ */ jsxs("div", { className: "truncate space-y-0.5", children: [
1691
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-[var(--ui-text-primary)] block truncate", children: item.name }),
1692
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[11px] text-[var(--ui-text-muted)] font-mono", children: [
1693
+ /* @__PURE__ */ jsx("span", { children: formatFileSize(item.size) }),
1694
+ item.status === "completed" && /* @__PURE__ */ jsxs("span", { className: "text-emerald-500 font-semibold flex items-center gap-0.5", children: [
1695
+ /* @__PURE__ */ jsx(CheckCircle2, { className: "w-3 h-3" }),
1696
+ " Ready"
1697
+ ] }),
1698
+ item.status === "error" && /* @__PURE__ */ jsxs("span", { className: "text-rose-500 font-semibold flex items-center gap-0.5", children: [
1699
+ /* @__PURE__ */ jsx(AlertCircle, { className: "w-3 h-3" }),
1700
+ " ",
1701
+ item.errorMessage
1702
+ ] })
1703
+ ] })
1704
+ ] })
1705
+ ] }),
1706
+ /* @__PURE__ */ jsx(
1707
+ "button",
1708
+ {
1709
+ type: "button",
1710
+ onClick: () => removeFile(item.id),
1711
+ className: "p-1.5 rounded-full hover:bg-[var(--ui-bg-tertiary)] text-[var(--ui-text-muted)] hover:text-rose-500 transition-colors",
1712
+ children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
1713
+ }
1714
+ )
1715
+ ]
1716
+ },
1717
+ item.id
1718
+ )) })
1719
+ ] })
1720
+ ] });
1721
+ }
1722
+ );
1723
+ FileUpload.displayName = "FileUpload";
1724
+ var NumberInput = forwardRef(
1725
+ ({
1726
+ value: controlledVal,
1727
+ defaultValue = 0,
1728
+ onChange,
1729
+ min = -Infinity,
1730
+ max = Infinity,
1731
+ step = 1,
1732
+ precision = 0,
1733
+ size = "md",
1734
+ stepperPosition = "right",
1735
+ disabled = false,
1736
+ className,
1737
+ ...props
1738
+ }, ref) => {
1739
+ const [internalVal, setInternalVal] = useState(defaultValue);
1740
+ const value = controlledVal !== void 0 ? controlledVal : internalVal;
1741
+ const clamp = (num) => {
1742
+ let clamped = Math.min(max, Math.max(min, num));
1743
+ if (precision > 0) {
1744
+ clamped = parseFloat(clamped.toFixed(precision));
1745
+ }
1746
+ return clamped;
1747
+ };
1748
+ const handleIncrement = () => {
1749
+ if (disabled) return;
1750
+ const next = clamp(value + step);
1751
+ setInternalVal(next);
1752
+ onChange?.(next);
1753
+ };
1754
+ const handleDecrement = () => {
1755
+ if (disabled) return;
1756
+ const next = clamp(value - step);
1757
+ setInternalVal(next);
1758
+ onChange?.(next);
1759
+ };
1760
+ const handleInputChange = (e) => {
1761
+ const val = e.target.value;
1762
+ if (val === "" || val === "-") {
1763
+ return;
1764
+ }
1765
+ const parsed = parseFloat(val);
1766
+ if (!isNaN(parsed)) {
1767
+ const next = clamp(parsed);
1768
+ setInternalVal(next);
1769
+ onChange?.(next);
1770
+ }
1771
+ };
1772
+ const handleKeyDown = (e) => {
1773
+ if (e.key === "ArrowUp") {
1774
+ e.preventDefault();
1775
+ handleIncrement();
1776
+ } else if (e.key === "ArrowDown") {
1777
+ e.preventDefault();
1778
+ handleDecrement();
1779
+ }
1780
+ };
1781
+ const heightClass = size === "sm" ? "h-8 text-xs" : size === "lg" ? "h-12 text-base" : "h-10 text-sm";
1782
+ if (stepperPosition === "split") {
1783
+ return /* @__PURE__ */ jsxs("div", { className: cn("inline-flex items-center rounded-[var(--ui-radius-md)] border border-[var(--ui-border-default)] bg-[var(--ui-bg-surface)] overflow-hidden shadow-inner", className), children: [
1784
+ /* @__PURE__ */ jsx(
1785
+ "button",
1786
+ {
1787
+ type: "button",
1788
+ disabled: disabled || value <= min,
1789
+ onClick: handleDecrement,
1790
+ className: "px-3 h-full flex items-center justify-center hover:bg-[var(--ui-bg-tertiary)] disabled:opacity-30 disabled:pointer-events-none text-[var(--ui-text-muted)] hover:text-[var(--ui-text-primary)] transition-colors border-r border-[var(--ui-border-subtle)]",
1791
+ children: /* @__PURE__ */ jsx(Minus, { className: "w-3.5 h-3.5" })
1792
+ }
1793
+ ),
1794
+ /* @__PURE__ */ jsx(
1795
+ "input",
1796
+ {
1797
+ ref,
1798
+ type: "number",
1799
+ value,
1800
+ disabled,
1801
+ onChange: handleInputChange,
1802
+ onKeyDown: handleKeyDown,
1803
+ className: cn("w-20 text-center font-mono font-semibold bg-transparent text-[var(--ui-text-primary)] focus:outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none", heightClass),
1804
+ ...props
1805
+ }
1806
+ ),
1807
+ /* @__PURE__ */ jsx(
1808
+ "button",
1809
+ {
1810
+ type: "button",
1811
+ disabled: disabled || value >= max,
1812
+ onClick: handleIncrement,
1813
+ className: "px-3 h-full flex items-center justify-center hover:bg-[var(--ui-bg-tertiary)] disabled:opacity-30 disabled:pointer-events-none text-[var(--ui-text-muted)] hover:text-[var(--ui-text-primary)] transition-colors border-l border-[var(--ui-border-subtle)]",
1814
+ children: /* @__PURE__ */ jsx(Plus, { className: "w-3.5 h-3.5" })
1815
+ }
1816
+ )
1817
+ ] });
1818
+ }
1819
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative w-full inline-flex items-center", className), children: [
1820
+ /* @__PURE__ */ jsx(
1821
+ "input",
1822
+ {
1823
+ ref,
1824
+ type: "number",
1825
+ value,
1826
+ disabled,
1827
+ onChange: handleInputChange,
1828
+ onKeyDown: handleKeyDown,
1829
+ className: cn(
1830
+ "w-full rounded-[var(--ui-radius-md)] border border-[var(--ui-border-default)] hover:border-[var(--ui-border-strong)] bg-[var(--ui-bg-surface)] px-3.5 pr-10 font-mono font-semibold text-[var(--ui-text-primary)] transition-all shadow-inner focus:outline-none focus:ring-2 focus:ring-[var(--ui-primary)]/50 [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
1831
+ heightClass,
1832
+ disabled && "opacity-50 cursor-not-allowed"
1833
+ ),
1834
+ ...props
1835
+ }
1836
+ ),
1837
+ /* @__PURE__ */ jsxs("div", { className: "absolute right-1 top-1 bottom-1 flex flex-col justify-center border-l border-[var(--ui-border-subtle)] pl-1 pr-1", children: [
1838
+ /* @__PURE__ */ jsx(
1839
+ "button",
1840
+ {
1841
+ type: "button",
1842
+ disabled: disabled || value >= max,
1843
+ onClick: handleIncrement,
1844
+ className: "px-1.5 h-1/2 flex items-center justify-center hover:bg-[var(--ui-bg-tertiary)] rounded-t text-[var(--ui-text-muted)] hover:text-[var(--ui-text-primary)] disabled:opacity-30 transition-colors",
1845
+ children: /* @__PURE__ */ jsx(Plus, { className: "w-3 h-3" })
1846
+ }
1847
+ ),
1848
+ /* @__PURE__ */ jsx(
1849
+ "button",
1850
+ {
1851
+ type: "button",
1852
+ disabled: disabled || value <= min,
1853
+ onClick: handleDecrement,
1854
+ className: "px-1.5 h-1/2 flex items-center justify-center hover:bg-[var(--ui-bg-tertiary)] rounded-b text-[var(--ui-text-muted)] hover:text-[var(--ui-text-primary)] disabled:opacity-30 transition-colors",
1855
+ children: /* @__PURE__ */ jsx(Minus, { className: "w-3 h-3" })
1856
+ }
1857
+ )
1858
+ ] })
1859
+ ] });
1860
+ }
1861
+ );
1862
+ NumberInput.displayName = "NumberInput";
1863
+ function formatCurrencyString(val, separator = ",") {
1864
+ if (isNaN(val)) return "0";
1865
+ const parts = val.toString().split(".");
1866
+ parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, separator);
1867
+ return parts.join(".");
1868
+ }
1869
+ var CurrencyInput = forwardRef(
1870
+ ({
1871
+ value: controlledVal,
1872
+ defaultValue = 0,
1873
+ onChange,
1874
+ currency = "USD",
1875
+ currencySymbol,
1876
+ position = "prefix",
1877
+ disabled = false,
1878
+ className,
1879
+ ...props
1880
+ }, ref) => {
1881
+ const symbol = currencySymbol || (currency === "VND" ? "\u20AB" : currency === "EUR" ? "\u20AC" : "$");
1882
+ const isSuffix = position === "suffix" || currency === "VND";
1883
+ const [internalVal, setInternalVal] = useState(defaultValue);
1884
+ const value = controlledVal !== void 0 ? controlledVal : internalVal;
1885
+ const [displayVal, setDisplayVal] = useState(formatCurrencyString(value));
1886
+ useEffect(() => {
1887
+ setDisplayVal(formatCurrencyString(value));
1888
+ }, [value]);
1889
+ const handleInputChange = (e) => {
1890
+ const raw = e.target.value.replace(/[^0-9.]/g, "");
1891
+ const parsed = parseFloat(raw);
1892
+ const num = isNaN(parsed) ? 0 : parsed;
1893
+ setDisplayVal(raw ? formatCurrencyString(num) : "");
1894
+ setInternalVal(num);
1895
+ onChange?.(num);
1896
+ };
1897
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative w-full flex items-center", className), children: [
1898
+ !isSuffix && /* @__PURE__ */ jsx("span", { className: "absolute left-3.5 text-sm font-bold text-[var(--ui-text-muted)] pointer-events-none font-mono", children: symbol }),
1899
+ /* @__PURE__ */ jsx(
1900
+ "input",
1901
+ {
1902
+ ref,
1903
+ type: "text",
1904
+ value: displayVal,
1905
+ disabled,
1906
+ onChange: handleInputChange,
1907
+ className: cn(
1908
+ "w-full h-10 rounded-[var(--ui-radius-md)] border border-[var(--ui-border-default)] hover:border-[var(--ui-border-strong)] bg-[var(--ui-bg-surface)] px-3.5 font-mono font-bold text-sm text-[var(--ui-text-primary)] transition-all shadow-inner focus:outline-none focus:ring-2 focus:ring-[var(--ui-primary)]/50",
1909
+ !isSuffix && "pl-8",
1910
+ isSuffix && "pr-12",
1911
+ disabled && "opacity-50 cursor-not-allowed"
1912
+ ),
1913
+ ...props
1914
+ }
1915
+ ),
1916
+ isSuffix && /* @__PURE__ */ jsx("span", { className: "absolute right-3.5 text-xs font-bold text-[var(--ui-text-muted)] pointer-events-none font-mono uppercase", children: currency })
1917
+ ] });
1918
+ }
1919
+ );
1920
+ CurrencyInput.displayName = "CurrencyInput";
1921
+ function applyMask(rawVal, mask, maskChar = "#") {
1922
+ const digitsOnly = rawVal.replace(/\D/g, "");
1923
+ if (!digitsOnly) return { formatted: "", unmasked: "" };
1924
+ let formatted = "";
1925
+ let digitIndex = 0;
1926
+ for (let i = 0; i < mask.length; i++) {
1927
+ const char = mask[i];
1928
+ if (char === maskChar) {
1929
+ if (digitIndex < digitsOnly.length) {
1930
+ formatted += digitsOnly[digitIndex++];
1931
+ } else {
1932
+ break;
1933
+ }
1934
+ } else {
1935
+ if (digitIndex < digitsOnly.length) {
1936
+ formatted += char;
1937
+ }
1938
+ }
1939
+ }
1940
+ return { formatted, unmasked: digitsOnly };
1941
+ }
1942
+ var MaskedInput = forwardRef(
1943
+ ({
1944
+ mask,
1945
+ maskChar = "#",
1946
+ value: controlledVal,
1947
+ defaultValue = "",
1948
+ onValueChange,
1949
+ prefixIcon,
1950
+ suffixIcon,
1951
+ disabled = false,
1952
+ className,
1953
+ ...props
1954
+ }, ref) => {
1955
+ const [internalVal, setInternalVal] = useState(
1956
+ applyMask(defaultValue, mask, maskChar).formatted
1957
+ );
1958
+ const displayValue = controlledVal !== void 0 ? applyMask(controlledVal, mask, maskChar).formatted : internalVal;
1959
+ const handleInputChange = (e) => {
1960
+ const { formatted, unmasked } = applyMask(e.target.value, mask, maskChar);
1961
+ setInternalVal(formatted);
1962
+ onValueChange?.(unmasked, formatted);
1963
+ };
1964
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative w-full flex items-center", className), children: [
1965
+ prefixIcon && /* @__PURE__ */ jsx("div", { className: "absolute left-3.5 flex items-center pointer-events-none text-[var(--ui-text-muted)]", children: prefixIcon }),
1966
+ /* @__PURE__ */ jsx(
1967
+ "input",
1968
+ {
1969
+ ref,
1970
+ type: "text",
1971
+ value: displayValue,
1972
+ disabled,
1973
+ onChange: handleInputChange,
1974
+ className: cn(
1975
+ "w-full h-10 rounded-[var(--ui-radius-md)] border border-[var(--ui-border-default)] hover:border-[var(--ui-border-strong)] bg-[var(--ui-bg-surface)] px-3.5 font-mono text-sm text-[var(--ui-text-primary)] transition-all shadow-inner focus:outline-none focus:ring-2 focus:ring-[var(--ui-primary)]/50",
1976
+ prefixIcon && "pl-9",
1977
+ suffixIcon && "pr-9",
1978
+ disabled && "opacity-50 cursor-not-allowed"
1979
+ ),
1980
+ ...props
1981
+ }
1982
+ ),
1983
+ suffixIcon && /* @__PURE__ */ jsx("div", { className: "absolute right-3.5 flex items-center pointer-events-none text-[var(--ui-text-muted)]", children: suffixIcon })
1984
+ ] });
1985
+ }
1986
+ );
1987
+ MaskedInput.displayName = "MaskedInput";
1988
+
1989
+ export { Checkbox, CheckboxGroup, Combobox, CurrencyInput, DatePicker, DateRangePicker, FileUpload, FormErrorMessage, FormField, FormHelperText, FormLabel, Input, MaskedInput, MultiSelect, NumberInput, PasswordInput, PinInput, Radio, RadioGroup, RangeSlider, SearchInput, Select, Slider, Switch, Textarea, TimePicker, applyMask, checkboxVariants, formatCurrencyString, formatDate, formatDisplayDate, formatFileSize, forms_exports, inputVariants, radioVariants, selectVariants, switchThumbVariants, switchVariants, textareaVariants, useFormField };
1990
+ //# sourceMappingURL=chunk-F5Q7BTMH.js.map
1991
+ //# sourceMappingURL=chunk-F5Q7BTMH.js.map