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