@page-speed/forms 0.4.1 → 0.4.3

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.
package/dist/inputs.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import * as React7 from 'react';
2
+ import { clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
2
4
 
3
5
  // src/inputs/TextInput.tsx
4
6
  function TextInput({
@@ -21,7 +23,7 @@ function TextInput({
21
23
  const handleBlur = () => {
22
24
  onBlur?.();
23
25
  };
24
- const baseClassName = "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm";
26
+ const baseClassName = "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm";
25
27
  const errorClassName = error ? "border-red-500 ring-1 ring-red-500" : "";
26
28
  const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
27
29
  return /* @__PURE__ */ React7.createElement(
@@ -68,7 +70,7 @@ function TextArea({
68
70
  const handleBlur = () => {
69
71
  onBlur?.();
70
72
  };
71
- const baseClassName = "flex min-h-20 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm";
73
+ const baseClassName = "flex min-h-20 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm";
72
74
  const errorClassName = error ? "border-red-500 ring-1 ring-red-500" : "";
73
75
  const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
74
76
  return /* @__PURE__ */ React7.createElement(
@@ -95,6 +97,11 @@ function TextArea({
95
97
  );
96
98
  }
97
99
  TextArea.displayName = "TextArea";
100
+ function cn(...inputs) {
101
+ return twMerge(clsx(inputs));
102
+ }
103
+
104
+ // src/inputs/Checkbox.tsx
98
105
  function Checkbox({
99
106
  name,
100
107
  value,
@@ -107,6 +114,7 @@ function Checkbox({
107
114
  indeterminate = false,
108
115
  label,
109
116
  description,
117
+ checkboxVariant = "boxed",
110
118
  ...props
111
119
  }) {
112
120
  const inputRef = React7.useRef(null);
@@ -122,36 +130,92 @@ function Checkbox({
122
130
  const handleBlur = () => {
123
131
  onBlur?.();
124
132
  };
125
- const checkbox = /* @__PURE__ */ React7.createElement("div", { className: "relative inline-flex" }, /* @__PURE__ */ React7.createElement(
126
- "input",
133
+ const isActive = value || indeterminate && !value;
134
+ const checkbox = /* @__PURE__ */ React7.createElement(
135
+ "div",
127
136
  {
128
- ref: inputRef,
129
- type: "checkbox",
130
- id: checkboxId,
131
- name,
132
- checked: value,
133
- onChange: handleChange,
134
- onBlur: handleBlur,
135
- disabled,
136
- required,
137
- className: `peer relative flex size-4 shrink-0 appearance-none items-center justify-center rounded-lg border border-input bg-transparent outline-none transition-colors focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 ${error ? "border-destructive ring-3 ring-destructive/20" : ""} ${value ? "bg-primary border-primary" : ""} ${className}`,
138
- "aria-invalid": error || props["aria-invalid"],
139
- "aria-describedby": description ? `${checkboxId}-description` : props["aria-describedby"],
140
- "aria-required": required || props["aria-required"],
141
- ...props
142
- }
143
- ), value && /* @__PURE__ */ React7.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary-foreground" }, /* @__PURE__ */ React7.createElement("svg", { className: "size-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3" }, /* @__PURE__ */ React7.createElement("polyline", { points: "20 6 9 17 4 12" }))), indeterminate && !value && /* @__PURE__ */ React7.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary" }, /* @__PURE__ */ React7.createElement("svg", { className: "size-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3" }, /* @__PURE__ */ React7.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" }))));
137
+ className: cn(
138
+ "relative inline-flex items-center justify-center",
139
+ !label && className
140
+ )
141
+ },
142
+ /* @__PURE__ */ React7.createElement(
143
+ "input",
144
+ {
145
+ ref: inputRef,
146
+ type: "checkbox",
147
+ id: checkboxId,
148
+ name,
149
+ checked: value,
150
+ onChange: handleChange,
151
+ onBlur: handleBlur,
152
+ disabled,
153
+ required,
154
+ className: "peer sr-only",
155
+ "aria-invalid": error || props["aria-invalid"],
156
+ "aria-describedby": description ? `${checkboxId}-description` : props["aria-describedby"],
157
+ "aria-required": required || props["aria-required"],
158
+ ...props
159
+ }
160
+ ),
161
+ /* @__PURE__ */ React7.createElement(
162
+ "div",
163
+ {
164
+ className: cn(
165
+ "flex shrink-0 items-center justify-center rounded-full border-2 transition-colors size-6",
166
+ !error && isActive && "border-primary bg-primary text-primary-foreground",
167
+ !error && !isActive && "border-input bg-transparent",
168
+ error && isActive && "border-destructive bg-destructive text-destructive-foreground",
169
+ error && !isActive && "border-destructive bg-transparent",
170
+ disabled && "opacity-50",
171
+ "peer-focus-visible:ring-2 peer-focus-visible:ring-ring/50 peer-focus-visible:ring-offset-1"
172
+ )
173
+ },
174
+ value && /* @__PURE__ */ React7.createElement(
175
+ "svg",
176
+ {
177
+ className: "size-3.5",
178
+ viewBox: "0 0 24 24",
179
+ fill: "none",
180
+ stroke: "currentColor",
181
+ strokeWidth: "3",
182
+ strokeLinecap: "round",
183
+ strokeLinejoin: "round"
184
+ },
185
+ /* @__PURE__ */ React7.createElement("polyline", { points: "20 6 9 17 4 12" })
186
+ ),
187
+ indeterminate && !value && /* @__PURE__ */ React7.createElement(
188
+ "svg",
189
+ {
190
+ className: "size-3.5",
191
+ viewBox: "0 0 24 24",
192
+ fill: "none",
193
+ stroke: "currentColor",
194
+ strokeWidth: "3",
195
+ strokeLinecap: "round",
196
+ strokeLinejoin: "round"
197
+ },
198
+ /* @__PURE__ */ React7.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
199
+ )
200
+ )
201
+ );
144
202
  if (label) {
145
203
  return /* @__PURE__ */ React7.createElement(
146
204
  "label",
147
205
  {
148
- className: `flex w-fit gap-2 items-center ${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}`,
206
+ className: cn(
207
+ "w-full h-full flex gap-3 p-3 duration-200",
208
+ checkboxVariant === "boxed" && "border rounded-lg hover:ring-2",
209
+ checkboxVariant === "boxed" && value && "ring-2",
210
+ disabled ? "opacity-50 cursor-not-allowed hover:ring-0" : "cursor-pointer",
211
+ className
212
+ ),
149
213
  htmlFor: checkboxId
150
214
  },
151
- /* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, checkbox, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-2 text-sm font-medium" }, label), description && /* @__PURE__ */ React7.createElement(
215
+ /* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row gap-2" }, checkbox, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium" }, label), description && /* @__PURE__ */ React7.createElement(
152
216
  "p",
153
217
  {
154
- className: "text-muted-foreground text-sm",
218
+ className: "text-xs opacity-75",
155
219
  id: `${checkboxId}-description`
156
220
  },
157
221
  description
@@ -189,6 +253,18 @@ function CheckboxGroup({
189
253
  ).length;
190
254
  const allSelected = selectedEnabledCount === enabledOptions.length;
191
255
  const someSelected = selectedEnabledCount > 0 && !allSelected;
256
+ const checkboxVariant = React7.useMemo(() => {
257
+ if (options.some((opt) => opt.description)) {
258
+ return "boxed";
259
+ }
260
+ return "inline";
261
+ }, [options]);
262
+ const countableValue = React7.useMemo(() => {
263
+ if (value?.length > 0) {
264
+ return value.length;
265
+ }
266
+ return 0;
267
+ }, [value]);
192
268
  const handleChange = (optionValue, checked) => {
193
269
  const newValues = checked ? [...value, optionValue] : value.filter((v) => v !== optionValue);
194
270
  if (maxSelections && checked && newValues.length > maxSelections) {
@@ -207,9 +283,14 @@ function CheckboxGroup({
207
283
  const handleBlur = () => {
208
284
  onBlur?.();
209
285
  };
210
- const layoutClass = layout === "inline" ? "flex flex-row flex-wrap gap-4" : layout === "grid" ? `grid gap-3` : "flex flex-col gap-3";
211
- const containerClass = `w-full ${layoutClass} ${className}`.trim();
212
- const maxReached = Boolean(maxSelections && value.length >= maxSelections);
286
+ const maxReached = Boolean(maxSelections && countableValue >= maxSelections);
287
+ const containerClass = cn(
288
+ "w-full gap-3",
289
+ layout === "stacked" && "flex flex-col",
290
+ layout === "inline" && "flex flex-row flex-wrap",
291
+ layout === "grid" && "grid",
292
+ className
293
+ );
213
294
  return /* @__PURE__ */ React7.createElement(
214
295
  "div",
215
296
  {
@@ -223,68 +304,56 @@ function CheckboxGroup({
223
304
  gridTemplateColumns: `repeat(${gridColumns}, 1fr)`
224
305
  } : void 0
225
306
  },
226
- label && /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium" }, label),
227
- description && /* @__PURE__ */ React7.createElement("div", { className: "text-muted-foreground text-sm" }, description),
307
+ label ? /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium" }, label) : null,
308
+ description ? /* @__PURE__ */ React7.createElement("div", { className: "text-xs opacity-70" }, description) : null,
228
309
  showSelectAll && enabledOptions.length > 0 && /* @__PURE__ */ React7.createElement(
229
- "label",
310
+ Checkbox,
230
311
  {
231
- className: `flex w-fit gap-2 items-center ${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}`
232
- },
233
- /* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, /* @__PURE__ */ React7.createElement("div", { className: "relative inline-flex" }, /* @__PURE__ */ React7.createElement(
234
- "input",
235
- {
236
- type: "checkbox",
237
- checked: allSelected,
238
- ref: (input) => {
239
- if (input) {
240
- input.indeterminate = someSelected;
241
- }
242
- },
243
- onChange: (e) => handleSelectAll(e.target.checked),
244
- onBlur: handleBlur,
245
- disabled,
246
- className: "peer relative flex size-4 shrink-0 appearance-none items-center justify-center rounded-lg border border-input bg-transparent outline-none transition-colors focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50",
247
- "aria-label": selectAllLabel
248
- }
249
- ), allSelected && /* @__PURE__ */ React7.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary-foreground" }, /* @__PURE__ */ React7.createElement("svg", { className: "size-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3" }, /* @__PURE__ */ React7.createElement("polyline", { points: "20 6 9 17 4 12" }))), someSelected && !allSelected && /* @__PURE__ */ React7.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary" }, /* @__PURE__ */ React7.createElement("svg", { className: "size-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3" }, /* @__PURE__ */ React7.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" })))), /* @__PURE__ */ React7.createElement("span", { className: "text-sm font-medium" }, selectAllLabel))
312
+ name: `${name}-select-all`,
313
+ id: `${name}-select-all`,
314
+ value: allSelected,
315
+ onChange: handleSelectAll,
316
+ onBlur: handleBlur,
317
+ indeterminate: someSelected,
318
+ label: selectAllLabel,
319
+ checkboxVariant: "inline",
320
+ disabled,
321
+ "aria-label": selectAllLabel
322
+ }
250
323
  ),
251
324
  options.map((option) => {
252
325
  const isChecked = value.includes(option.value);
253
326
  const isDisabled = disabled || option.disabled || maxReached && !isChecked;
254
- const checkboxId = `${name}-${option.value}`;
255
327
  return /* @__PURE__ */ React7.createElement(
256
- "label",
328
+ Checkbox,
257
329
  {
258
330
  key: option.value,
259
- className: `flex w-fit gap-2 items-center ${isDisabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}`,
260
- htmlFor: checkboxId
261
- },
262
- /* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, /* @__PURE__ */ React7.createElement("div", { className: "relative inline-flex" }, /* @__PURE__ */ React7.createElement(
263
- "input",
264
- {
265
- type: "checkbox",
266
- id: checkboxId,
267
- name,
268
- value: option.value,
269
- checked: isChecked,
270
- onChange: (e) => handleChange(option.value, e.target.checked),
271
- onBlur: handleBlur,
272
- disabled: isDisabled,
273
- required: required && minSelections ? value.length < minSelections : false,
274
- className: `peer relative flex size-4 shrink-0 appearance-none items-center justify-center rounded-lg border border-input bg-transparent outline-none transition-colors focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 ${error ? "border-destructive ring-3 ring-destructive/20" : ""} ${isChecked ? "bg-primary border-primary" : ""}`,
275
- "aria-describedby": option.description ? `${checkboxId}-description` : props["aria-describedby"]
276
- }
277
- ), isChecked && /* @__PURE__ */ React7.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary-foreground" }, /* @__PURE__ */ React7.createElement("svg", { className: "size-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3" }, /* @__PURE__ */ React7.createElement("polyline", { points: "20 6 9 17 4 12" })))), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, renderOption ? renderOption(option) : /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-2 text-sm font-medium" }, option.label), option.description && /* @__PURE__ */ React7.createElement(
278
- "p",
279
- {
280
- className: "text-muted-foreground text-sm",
281
- id: `${checkboxId}-description`
282
- },
283
- option.description
284
- ))))
331
+ name,
332
+ id: `${name}-${option.value}`,
333
+ value: isChecked,
334
+ onChange: (checked) => handleChange(option.value, checked),
335
+ onBlur: handleBlur,
336
+ disabled: isDisabled,
337
+ required: required && minSelections ? value.length < minSelections : false,
338
+ error,
339
+ label: renderOption ? renderOption(option) : option.label,
340
+ description: renderOption ? void 0 : option.description,
341
+ checkboxVariant
342
+ }
285
343
  );
286
344
  }),
287
- (minSelections || maxSelections) && /* @__PURE__ */ React7.createElement("div", { className: "text-sm text-muted-foreground mt-2", "aria-live": "polite" }, minSelections && value.length < minSelections && /* @__PURE__ */ React7.createElement("span", { className: "text-destructive" }, "Select at least ", minSelections, " option", minSelections !== 1 ? "s" : ""), maxSelections && /* @__PURE__ */ React7.createElement("span", null, value.length, "/", maxSelections, " selected"))
345
+ (minSelections || maxSelections) && /* @__PURE__ */ React7.createElement(
346
+ "div",
347
+ {
348
+ className: cn(
349
+ "text-sm p-2 rounded-lg border font-semibold mt-2",
350
+ minSelections && countableValue < minSelections ? "border-destructive bg-destructive/80 text-destructive-foreground" : "border-border bg-card text-card-foreground"
351
+ ),
352
+ "aria-live": "polite"
353
+ },
354
+ minSelections && countableValue < minSelections && /* @__PURE__ */ React7.createElement("span", null, "Select at least ", minSelections, " option", minSelections !== 1 ? "s" : ""),
355
+ maxSelections && /* @__PURE__ */ React7.createElement("span", null, countableValue, "/", maxSelections, " selected")
356
+ )
288
357
  );
289
358
  }
290
359
  CheckboxGroup.displayName = "CheckboxGroup";
@@ -333,8 +402,16 @@ function Radio({
333
402
  const handleBlur = () => {
334
403
  onBlur?.();
335
404
  };
336
- const layoutClass = layout === "inline" ? "flex flex-row flex-wrap gap-4" : "grid w-full gap-2";
337
- const containerClass = `${layoutClass} ${className}`.trim();
405
+ const useChoiceCard = React7.useMemo(() => {
406
+ return options.some((option) => option.description);
407
+ }, [options]);
408
+ const containerClass = React7.useMemo(() => {
409
+ return cn(
410
+ "w-full gap-3 grid grid-cols-1",
411
+ layout === "inline" && "md:grid-cols-2",
412
+ className
413
+ );
414
+ }, [layout, className]);
338
415
  return /* @__PURE__ */ React7.createElement(
339
416
  "div",
340
417
  {
@@ -350,38 +427,53 @@ function Radio({
350
427
  const isChecked = value === option.value;
351
428
  const isDisabled = disabled || option.disabled;
352
429
  const radioId = `${name}-${option.value}`;
430
+ const hasDescription = option.description != null && option.description !== "";
431
+ const radioIndicator = /* @__PURE__ */ React7.createElement("div", { className: "relative inline-flex items-center justify-center" }, /* @__PURE__ */ React7.createElement(
432
+ "input",
433
+ {
434
+ type: "radio",
435
+ id: radioId,
436
+ name,
437
+ value: option.value,
438
+ checked: isChecked,
439
+ onChange: (e) => handleChange(e.target.value),
440
+ onBlur: handleBlur,
441
+ disabled: isDisabled,
442
+ required,
443
+ className: "peer sr-only",
444
+ "aria-describedby": hasDescription ? `${radioId}-description` : props["aria-describedby"]
445
+ }
446
+ ), /* @__PURE__ */ React7.createElement(
447
+ "div",
448
+ {
449
+ className: cn(
450
+ "flex shrink-0 items-center justify-center rounded-full border-2 transition-colors size-6",
451
+ !error && isChecked && "border-primary bg-transparent",
452
+ !error && !isChecked && "border-input bg-transparent",
453
+ error && isChecked && "border-destructive bg-transparent",
454
+ error && !isChecked && "border-destructive bg-transparent",
455
+ isDisabled && "opacity-50",
456
+ "peer-focus-visible:ring-2 peer-focus-visible:ring-ring/50 peer-focus-visible:ring-offset-1"
457
+ )
458
+ },
459
+ isChecked && /* @__PURE__ */ React7.createElement("div", { className: "size-3 rounded-full bg-primary" })
460
+ ));
461
+ const labelContent = /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium" }, option.label), hasDescription && /* @__PURE__ */ React7.createElement("p", { className: "text-xs opacity-75", id: `${radioId}-description` }, option.description));
353
462
  return /* @__PURE__ */ React7.createElement(
354
463
  "label",
355
464
  {
356
465
  key: option.value,
357
- className: `flex w-fit gap-2 items-center ${isDisabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}`,
466
+ className: cn(
467
+ "w-full h-full flex gap-3 p-3 duration-200",
468
+ useChoiceCard && "border rounded-lg hover:ring-2",
469
+ useChoiceCard && isChecked && "ring-2",
470
+ isDisabled ? "opacity-50 cursor-not-allowed hover:ring-0" : "cursor-pointer"
471
+ ),
358
472
  htmlFor: radioId,
359
473
  onKeyDown: (e) => handleKeyDown(e, index),
360
474
  tabIndex: isDisabled ? -1 : 0
361
475
  },
362
- /* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, option.description ? /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-2 text-sm font-medium" }, option.label), /* @__PURE__ */ React7.createElement(
363
- "p",
364
- {
365
- className: "text-muted-foreground text-sm",
366
- id: `${radioId}-description`
367
- },
368
- option.description
369
- )) : /* @__PURE__ */ React7.createElement("span", { className: "text-sm font-medium" }, option.label)), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, /* @__PURE__ */ React7.createElement(
370
- "input",
371
- {
372
- type: "radio",
373
- id: radioId,
374
- name,
375
- value: option.value,
376
- checked: isChecked,
377
- onChange: (e) => handleChange(e.target.value),
378
- onBlur: handleBlur,
379
- disabled: isDisabled,
380
- required,
381
- className: `peer relative flex aspect-square size-4 shrink-0 appearance-none rounded-full border border-input outline-none transition-colors focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 ${error ? "border-destructive" : ""} ${isChecked ? "border-primary bg-primary" : "bg-transparent"}`,
382
- "aria-describedby": option.description ? `${radioId}-description` : props["aria-describedby"]
383
- }
384
- ), isChecked && /* @__PURE__ */ React7.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex size-4 -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary-foreground" }, /* @__PURE__ */ React7.createElement("svg", { className: "size-2 fill-current", viewBox: "0 0 24 24" }, /* @__PURE__ */ React7.createElement("circle", { cx: "12", cy: "12", r: "10" })))))
476
+ /* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, !useChoiceCard && radioIndicator, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, labelContent), useChoiceCard && radioIndicator)
385
477
  );
386
478
  })
387
479
  );
@@ -471,9 +563,7 @@ function Select({
471
563
  if (enabledOptions.length > 0) {
472
564
  const currentIndexInFiltered = focusedIndex;
473
565
  const nextIndex = (currentIndexInFiltered + 1) % enabledOptions.length;
474
- setFocusedIndex(
475
- filteredOptions.indexOf(enabledOptions[nextIndex])
476
- );
566
+ setFocusedIndex(filteredOptions.indexOf(enabledOptions[nextIndex]));
477
567
  }
478
568
  }
479
569
  break;
@@ -484,9 +574,7 @@ function Select({
484
574
  if (enabledOptions.length > 0) {
485
575
  const currentIndexInFiltered = focusedIndex;
486
576
  const prevIndex = (currentIndexInFiltered - 1 + enabledOptions.length) % enabledOptions.length;
487
- setFocusedIndex(
488
- filteredOptions.indexOf(enabledOptions[prevIndex])
489
- );
577
+ setFocusedIndex(filteredOptions.indexOf(enabledOptions[prevIndex]));
490
578
  }
491
579
  }
492
580
  break;
@@ -576,7 +664,7 @@ function Select({
576
664
  /* @__PURE__ */ React7.createElement(
577
665
  "div",
578
666
  {
579
- className: `flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm cursor-pointer transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring ${disabled ? "cursor-not-allowed opacity-50 pointer-events-none" : ""} ${error ? "border-red-500 ring-1 ring-red-500" : ""}`,
667
+ className: `flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm cursor-pointer transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring ${disabled ? "cursor-not-allowed opacity-50 pointer-events-none" : ""} ${error ? "border-red-500 ring-1 ring-red-500" : ""}`,
580
668
  onClick: handleToggle,
581
669
  role: "combobox",
582
670
  "aria-expanded": isOpen,
@@ -587,48 +675,76 @@ function Select({
587
675
  "aria-disabled": disabled,
588
676
  tabIndex: disabled ? -1 : 0
589
677
  },
590
- /* @__PURE__ */ React7.createElement("span", { className: "flex items-center flex-1 overflow-hidden text-ellipsis" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React7.createElement("span", { className: "text-muted-foreground" }, placeholder)),
678
+ /* @__PURE__ */ React7.createElement("span", { className: "flex items-center flex-1 overflow-hidden text-ellipsis" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React7.createElement("span", { className: "relative" }, placeholder)),
591
679
  /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-1 ml-2" }, loading && /* @__PURE__ */ React7.createElement("span", { className: "text-xs" }, "\u23F3"), clearable && value && !disabled && !loading && /* @__PURE__ */ React7.createElement(
592
680
  "button",
593
681
  {
594
682
  type: "button",
595
- className: "flex items-center justify-center h-4 w-4 rounded-sm border-none bg-transparent text-muted-foreground cursor-pointer text-xs p-0 transition-opacity hover:opacity-70",
683
+ className: "flex items-center justify-center h-4 w-4 rounded-sm border-none bg-transparent cursor-pointer text-xs p-0 transition-opacity hover:opacity-70",
596
684
  onClick: handleClear,
597
685
  "aria-label": "Clear selection",
598
686
  tabIndex: -1
599
687
  },
600
688
  "\u2715"
601
- ), /* @__PURE__ */ React7.createElement("span", { className: "text-muted-foreground text-xs leading-none", "aria-hidden": "true" }, isOpen ? "\u25B2" : "\u25BC"))
689
+ ), /* @__PURE__ */ React7.createElement("span", { className: "text-xs leading-none", "aria-hidden": "true" }, isOpen ? "\u25B2" : "\u25BC"))
602
690
  ),
603
- isOpen && /* @__PURE__ */ React7.createElement("div", { id: dropdownId, className: "absolute z-50 top-full mt-1 min-w-full overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md", role: "listbox" }, searchable && /* @__PURE__ */ React7.createElement("div", { className: "p-2 border-b border-border" }, /* @__PURE__ */ React7.createElement(
604
- "input",
691
+ isOpen && /* @__PURE__ */ React7.createElement(
692
+ "div",
605
693
  {
606
- ref: searchInputRef,
607
- type: "text",
608
- className: "w-full border border-input rounded px-2 py-1 text-sm bg-transparent outline-none focus:ring-1 focus:ring-ring",
609
- placeholder: "Search...",
610
- value: searchQuery,
611
- onChange: handleSearchChange,
612
- onClick: (e) => e.stopPropagation(),
613
- "aria-label": "Search options"
614
- }
615
- )), /* @__PURE__ */ React7.createElement("div", { className: "max-h-64 overflow-y-auto p-1" }, filteredOptions.length === 0 ? /* @__PURE__ */ React7.createElement("div", { className: "py-2 px-3 text-center text-sm text-muted-foreground" }, "No options found") : optionGroups.length > 0 ? (
616
- // Render grouped options
617
- optionGroups.map((group, groupIndex) => {
618
- const groupOptions = group.options.filter(
619
- (opt) => filteredOptions.includes(opt)
620
- );
621
- if (groupOptions.length === 0) return null;
622
- return /* @__PURE__ */ React7.createElement("div", { key: groupIndex, className: "py-1" }, /* @__PURE__ */ React7.createElement("div", { className: "py-1.5 px-2 text-xs font-semibold text-muted-foreground" }, group.label), groupOptions.map((option) => {
623
- const globalIndex = filteredOptions.indexOf(option);
694
+ id: dropdownId,
695
+ className: "absolute z-50 top-full mt-1 min-w-full overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md",
696
+ role: "listbox"
697
+ },
698
+ searchable && /* @__PURE__ */ React7.createElement("div", { className: "p-2 border-b border-border" }, /* @__PURE__ */ React7.createElement(
699
+ "input",
700
+ {
701
+ ref: searchInputRef,
702
+ type: "text",
703
+ className: "w-full border border-input rounded px-2 py-1 text-sm bg-transparent outline-none focus:ring-1 focus:ring-ring",
704
+ placeholder: "Search...",
705
+ value: searchQuery,
706
+ onChange: handleSearchChange,
707
+ onClick: (e) => e.stopPropagation(),
708
+ "aria-label": "Search options"
709
+ }
710
+ )),
711
+ /* @__PURE__ */ React7.createElement("div", { className: "max-h-64 overflow-y-auto p-1" }, filteredOptions.length === 0 ? /* @__PURE__ */ React7.createElement("div", { className: "py-2 px-3 text-center text-sm " }, "No options found") : optionGroups.length > 0 ? (
712
+ // Render grouped options
713
+ optionGroups.map((group, groupIndex) => {
714
+ const groupOptions = group.options.filter(
715
+ (opt) => filteredOptions.includes(opt)
716
+ );
717
+ if (groupOptions.length === 0) return null;
718
+ return /* @__PURE__ */ React7.createElement("div", { key: groupIndex, className: "py-1" }, /* @__PURE__ */ React7.createElement("div", { className: "py-1.5 px-2 text-xs font-semibold " }, group.label), groupOptions.map((option) => {
719
+ const globalIndex = filteredOptions.indexOf(option);
720
+ const isSelected = value === option.value;
721
+ const isFocused = globalIndex === focusedIndex;
722
+ const isDisabled = option.disabled;
723
+ return /* @__PURE__ */ React7.createElement(
724
+ "div",
725
+ {
726
+ key: option.value,
727
+ className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-muted ${isFocused ? "bg-muted" : ""} ${isSelected ? "font-medium bg-muted" : ""} ${isDisabled ? "pointer-events-none opacity-50" : ""}`,
728
+ onClick: () => !isDisabled && handleSelect(option.value),
729
+ role: "option",
730
+ "aria-selected": isSelected,
731
+ "aria-disabled": isDisabled
732
+ },
733
+ renderOption ? renderOption(option) : option.label
734
+ );
735
+ }));
736
+ })
737
+ ) : (
738
+ // Render flat options
739
+ filteredOptions.map((option, index) => {
624
740
  const isSelected = value === option.value;
625
- const isFocused = globalIndex === focusedIndex;
741
+ const isFocused = index === focusedIndex;
626
742
  const isDisabled = option.disabled;
627
743
  return /* @__PURE__ */ React7.createElement(
628
744
  "div",
629
745
  {
630
746
  key: option.value,
631
- className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground ${isFocused ? "bg-accent text-accent-foreground" : ""} ${isSelected ? "font-medium bg-accent" : ""} ${isDisabled ? "pointer-events-none opacity-50" : ""}`,
747
+ className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-muted ${isFocused ? "bg-muted" : ""} ${isSelected ? "font-medium bg-muted" : ""} ${isDisabled ? "pointer-events-none opacity-50" : ""}`,
632
748
  onClick: () => !isDisabled && handleSelect(option.value),
633
749
  role: "option",
634
750
  "aria-selected": isSelected,
@@ -636,28 +752,9 @@ function Select({
636
752
  },
637
753
  renderOption ? renderOption(option) : option.label
638
754
  );
639
- }));
640
- })
641
- ) : (
642
- // Render flat options
643
- filteredOptions.map((option, index) => {
644
- const isSelected = value === option.value;
645
- const isFocused = index === focusedIndex;
646
- const isDisabled = option.disabled;
647
- return /* @__PURE__ */ React7.createElement(
648
- "div",
649
- {
650
- key: option.value,
651
- className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground ${isFocused ? "bg-accent text-accent-foreground" : ""} ${isSelected ? "font-medium bg-accent" : ""} ${isDisabled ? "pointer-events-none opacity-50" : ""}`,
652
- onClick: () => !isDisabled && handleSelect(option.value),
653
- role: "option",
654
- "aria-selected": isSelected,
655
- "aria-disabled": isDisabled
656
- },
657
- renderOption ? renderOption(option) : option.label
658
- );
659
- })
660
- )))
755
+ })
756
+ ))
757
+ )
661
758
  );
662
759
  }
663
760
  Select.displayName = "Select";
@@ -666,7 +763,7 @@ function FileInput({
666
763
  value = [],
667
764
  onChange,
668
765
  onBlur,
669
- placeholder = "Choose file(s)...",
766
+ placeholder = "Choose file...",
670
767
  disabled = false,
671
768
  required = false,
672
769
  error = false,
@@ -769,7 +866,15 @@ function FileInput({
769
866
  inputRef.current.value = "";
770
867
  }
771
868
  },
772
- [value, onChange, validateFile, maxFiles, multiple, enableCropping, onValidationError]
869
+ [
870
+ value,
871
+ onChange,
872
+ validateFile,
873
+ maxFiles,
874
+ multiple,
875
+ enableCropping,
876
+ onValidationError
877
+ ]
773
878
  );
774
879
  const createCroppedImage = React7.useCallback(
775
880
  async (imageUrl, cropArea) => {
@@ -795,13 +900,17 @@ function FileInput({
795
900
  cropArea.width,
796
901
  cropArea.height
797
902
  );
798
- canvas.toBlob((blob) => {
799
- if (blob) {
800
- resolve(blob);
801
- } else {
802
- reject(new Error("Failed to create blob from canvas"));
803
- }
804
- }, "image/jpeg", 0.95);
903
+ canvas.toBlob(
904
+ (blob) => {
905
+ if (blob) {
906
+ resolve(blob);
907
+ } else {
908
+ reject(new Error("Failed to create blob from canvas"));
909
+ }
910
+ },
911
+ "image/jpeg",
912
+ 0.95
913
+ );
805
914
  };
806
915
  image.onerror = () => {
807
916
  reject(new Error("Failed to load image"));
@@ -821,11 +930,9 @@ function FileInput({
821
930
  if (onCropComplete) {
822
931
  onCropComplete(croppedBlob, imageToCrop.file);
823
932
  }
824
- const croppedFile = new File(
825
- [croppedBlob],
826
- imageToCrop.file.name,
827
- { type: "image/jpeg" }
828
- );
933
+ const croppedFile = new File([croppedBlob], imageToCrop.file.name, {
934
+ type: "image/jpeg"
935
+ });
829
936
  const updatedFiles = multiple ? [...value, croppedFile] : [croppedFile];
830
937
  onChange(updatedFiles);
831
938
  setCropperOpen(false);
@@ -837,7 +944,15 @@ function FileInput({
837
944
  } catch (error2) {
838
945
  console.error("Failed to crop image:", error2);
839
946
  }
840
- }, [imageToCrop, croppedAreaPixels, createCroppedImage, onCropComplete, value, onChange, multiple]);
947
+ }, [
948
+ imageToCrop,
949
+ croppedAreaPixels,
950
+ createCroppedImage,
951
+ onCropComplete,
952
+ value,
953
+ onChange,
954
+ multiple
955
+ ]);
841
956
  const handleCropCancel = React7.useCallback(() => {
842
957
  if (imageToCrop) {
843
958
  URL.revokeObjectURL(imageToCrop.url);
@@ -949,7 +1064,7 @@ function FileInput({
949
1064
  ), /* @__PURE__ */ React7.createElement(
950
1065
  "div",
951
1066
  {
952
- className: `flex min-h-32 w-full cursor-pointer items-center justify-center rounded-md border-2 border-dashed border-input bg-transparent p-6 transition-colors hover:bg-accent/50 hover:border-ring ${dragActive ? "bg-accent border-ring" : ""} ${disabled ? "cursor-not-allowed opacity-50" : ""} ${error ? "border-red-500" : ""}`,
1067
+ className: `flex min-h-32 w-full cursor-pointer items-center justify-center rounded-md border-2 border-dashed border-input bg-transparent p-6 transition-colors hover:bg-primary/50 hover:border-ring ${dragActive ? "bg-primary text-primary-foreground border-ring" : ""} ${disabled ? "cursor-not-allowed opacity-50" : ""} ${error ? "border-red-500" : ""}`,
953
1068
  onDragEnter: handleDrag,
954
1069
  onDragLeave: handleDrag,
955
1070
  onDragOver: handleDrag,
@@ -964,7 +1079,6 @@ function FileInput({
964
1079
  /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col items-center gap-2 text-center" }, /* @__PURE__ */ React7.createElement(
965
1080
  "svg",
966
1081
  {
967
- className: "text-muted-foreground",
968
1082
  width: "48",
969
1083
  height: "48",
970
1084
  viewBox: "0 0 24 24",
@@ -978,92 +1092,102 @@ function FileInput({
978
1092
  /* @__PURE__ */ React7.createElement("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
979
1093
  /* @__PURE__ */ React7.createElement("polyline", { points: "17 8 12 3 7 8" }),
980
1094
  /* @__PURE__ */ React7.createElement("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
981
- ), /* @__PURE__ */ React7.createElement("p", { className: "text-sm font-medium" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React7.createElement("p", { className: "text-xs text-muted-foreground" }, "Accepted: ", accept), maxSize && /* @__PURE__ */ React7.createElement("p", { className: "text-xs text-muted-foreground" }, "Max size: ", formatFileSize(maxSize)))
1095
+ ), /* @__PURE__ */ React7.createElement("p", { className: "text-sm font-medium" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React7.createElement("p", { className: "text-xs" }, "Accepted: ", accept), maxSize && /* @__PURE__ */ React7.createElement("p", { className: "text-xs " }, "Max size: ", formatFileSize(maxSize)))
982
1096
  ), value.length > 0 && /* @__PURE__ */ React7.createElement("ul", { className: "flex flex-col gap-2 mt-4", role: "list" }, value.map((file, index) => {
983
1097
  const previewUrl = showPreview ? getPreviewUrl(file) : null;
984
- return /* @__PURE__ */ React7.createElement("li", { key: `${file.name}-${index}`, className: "flex items-center gap-3 p-3 rounded-md border border-border bg-card hover:bg-accent/50 transition-colors" }, previewUrl && /* @__PURE__ */ React7.createElement(
985
- "img",
986
- {
987
- src: previewUrl,
988
- alt: file.name,
989
- className: "w-12 h-12 rounded object-cover",
990
- width: "48",
991
- height: "48"
992
- }
993
- ), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React7.createElement("span", { className: "text-sm font-medium truncate" }, file.name), /* @__PURE__ */ React7.createElement("span", { className: "text-xs text-muted-foreground" }, formatFileSize(file.size)), showProgress && uploadProgress[file.name] !== void 0 && /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-2 mt-1" }, /* @__PURE__ */ React7.createElement(
994
- "div",
1098
+ return /* @__PURE__ */ React7.createElement(
1099
+ "li",
995
1100
  {
996
- className: "h-1.5 bg-muted rounded-full overflow-hidden flex-1",
997
- role: "progressbar",
998
- "aria-valuenow": uploadProgress[file.name],
999
- "aria-valuemin": 0,
1000
- "aria-valuemax": 100,
1001
- "aria-label": `Upload progress: ${uploadProgress[file.name]}%`
1101
+ key: `${file.name}-${index}`,
1102
+ className: "flex items-center gap-3 p-3 rounded-md border border-border bg-card text-card-foreground hover:bg-primary/50 transition-colors"
1002
1103
  },
1003
- /* @__PURE__ */ React7.createElement(
1004
- "div",
1104
+ previewUrl && /* @__PURE__ */ React7.createElement(
1105
+ "img",
1005
1106
  {
1006
- className: "h-full bg-primary transition-all",
1007
- style: { width: `${uploadProgress[file.name]}%` }
1107
+ src: previewUrl,
1108
+ alt: file.name,
1109
+ className: "w-12 h-12 rounded object-cover",
1110
+ width: "48",
1111
+ height: "48"
1008
1112
  }
1009
- )
1010
- ), /* @__PURE__ */ React7.createElement("span", { className: "text-xs text-muted-foreground" }, uploadProgress[file.name], "%"))), enableCropping && file.type.startsWith("image/") && /* @__PURE__ */ React7.createElement(
1011
- "button",
1012
- {
1013
- type: "button",
1014
- onClick: (e) => {
1015
- e.stopPropagation();
1016
- handleCrop(file);
1017
- },
1018
- disabled,
1019
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
1020
- "aria-label": `Crop ${file.name}`
1021
- },
1022
- /* @__PURE__ */ React7.createElement(
1023
- "svg",
1113
+ ),
1114
+ /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React7.createElement("span", { className: "text-sm font-medium truncate" }, file.name), /* @__PURE__ */ React7.createElement("span", { className: "text-xs" }, formatFileSize(file.size)), showProgress && uploadProgress[file.name] !== void 0 && /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-2 mt-1" }, /* @__PURE__ */ React7.createElement(
1115
+ "div",
1024
1116
  {
1025
- width: "20",
1026
- height: "20",
1027
- viewBox: "0 0 24 24",
1028
- fill: "none",
1029
- stroke: "currentColor",
1030
- strokeWidth: "2",
1031
- strokeLinecap: "round",
1032
- strokeLinejoin: "round",
1033
- "aria-hidden": "true"
1117
+ className: "h-1.5 bg-muted rounded-full overflow-hidden flex-1",
1118
+ role: "progressbar",
1119
+ "aria-valuenow": uploadProgress[file.name],
1120
+ "aria-valuemin": 0,
1121
+ "aria-valuemax": 100,
1122
+ "aria-label": `Upload progress: ${uploadProgress[file.name]}%`
1034
1123
  },
1035
- /* @__PURE__ */ React7.createElement("path", { d: "M6.13 1L6 16a2 2 0 0 0 2 2h15" }),
1036
- /* @__PURE__ */ React7.createElement("path", { d: "M1 6.13L16 6a2 2 0 0 1 2 2v15" })
1037
- )
1038
- ), /* @__PURE__ */ React7.createElement(
1039
- "button",
1040
- {
1041
- type: "button",
1042
- onClick: (e) => {
1043
- e.stopPropagation();
1044
- handleRemove(index);
1124
+ /* @__PURE__ */ React7.createElement(
1125
+ "div",
1126
+ {
1127
+ className: "h-full bg-primary transition-all",
1128
+ style: { width: `${uploadProgress[file.name]}%` }
1129
+ }
1130
+ )
1131
+ ), /* @__PURE__ */ React7.createElement("span", { className: "text-xs " }, uploadProgress[file.name], "%"))),
1132
+ enableCropping && file.type.startsWith("image/") && /* @__PURE__ */ React7.createElement(
1133
+ "button",
1134
+ {
1135
+ type: "button",
1136
+ onClick: (e) => {
1137
+ e.stopPropagation();
1138
+ handleCrop(file);
1139
+ },
1140
+ disabled,
1141
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
1142
+ "aria-label": `Crop ${file.name}`
1045
1143
  },
1046
- disabled,
1047
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
1048
- "aria-label": `Remove ${file.name}`
1049
- },
1144
+ /* @__PURE__ */ React7.createElement(
1145
+ "svg",
1146
+ {
1147
+ width: "20",
1148
+ height: "20",
1149
+ viewBox: "0 0 24 24",
1150
+ fill: "none",
1151
+ stroke: "currentColor",
1152
+ strokeWidth: "2",
1153
+ strokeLinecap: "round",
1154
+ strokeLinejoin: "round",
1155
+ "aria-hidden": "true"
1156
+ },
1157
+ /* @__PURE__ */ React7.createElement("path", { d: "M6.13 1L6 16a2 2 0 0 0 2 2h15" }),
1158
+ /* @__PURE__ */ React7.createElement("path", { d: "M1 6.13L16 6a2 2 0 0 1 2 2v15" })
1159
+ )
1160
+ ),
1050
1161
  /* @__PURE__ */ React7.createElement(
1051
- "svg",
1162
+ "button",
1052
1163
  {
1053
- width: "20",
1054
- height: "20",
1055
- viewBox: "0 0 24 24",
1056
- fill: "none",
1057
- stroke: "currentColor",
1058
- strokeWidth: "2",
1059
- strokeLinecap: "round",
1060
- strokeLinejoin: "round",
1061
- "aria-hidden": "true"
1164
+ type: "button",
1165
+ onClick: (e) => {
1166
+ e.stopPropagation();
1167
+ handleRemove(index);
1168
+ },
1169
+ disabled,
1170
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
1171
+ "aria-label": `Remove ${file.name}`
1062
1172
  },
1063
- /* @__PURE__ */ React7.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1064
- /* @__PURE__ */ React7.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1173
+ /* @__PURE__ */ React7.createElement(
1174
+ "svg",
1175
+ {
1176
+ width: "20",
1177
+ height: "20",
1178
+ viewBox: "0 0 24 24",
1179
+ fill: "none",
1180
+ stroke: "currentColor",
1181
+ strokeWidth: "2",
1182
+ strokeLinecap: "round",
1183
+ strokeLinejoin: "round",
1184
+ "aria-hidden": "true"
1185
+ },
1186
+ /* @__PURE__ */ React7.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1187
+ /* @__PURE__ */ React7.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1188
+ )
1065
1189
  )
1066
- ));
1190
+ );
1067
1191
  })), cropperOpen && imageToCrop && /* @__PURE__ */ React7.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center" }, /* @__PURE__ */ React7.createElement(
1068
1192
  "div",
1069
1193
  {
@@ -1075,7 +1199,7 @@ function FileInput({
1075
1199
  "button",
1076
1200
  {
1077
1201
  type: "button",
1078
- className: "flex items-center justify-center h-8 w-8 rounded hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
1202
+ className: "flex items-center justify-center h-8 w-8 rounded hover:bg-primary hover:text-primary-foreground transition-colors",
1079
1203
  onClick: handleCropCancel,
1080
1204
  "aria-label": "Close"
1081
1205
  },
@@ -1116,7 +1240,10 @@ function FileInput({
1116
1240
  const img = e.currentTarget;
1117
1241
  const containerWidth = 600;
1118
1242
  const containerHeight = 400;
1119
- const cropWidth = cropAspectRatio ? Math.min(containerWidth * 0.8, containerHeight * 0.8 * cropAspectRatio) : containerWidth * 0.8;
1243
+ const cropWidth = cropAspectRatio ? Math.min(
1244
+ containerWidth * 0.8,
1245
+ containerHeight * 0.8 * cropAspectRatio
1246
+ ) : containerWidth * 0.8;
1120
1247
  const cropHeight = cropAspectRatio ? cropWidth / cropAspectRatio : containerHeight * 0.8;
1121
1248
  const scale = zoom;
1122
1249
  const imgWidth = img.naturalWidth;
@@ -1145,7 +1272,16 @@ function FileInput({
1145
1272
  },
1146
1273
  /* @__PURE__ */ React7.createElement("div", { className: "absolute inset-0 grid grid-cols-3 grid-rows-3" }, /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React7.createElement("div", null))
1147
1274
  )
1148
- ), /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-3 mt-4" }, /* @__PURE__ */ React7.createElement("label", { htmlFor: "zoom-slider", className: "text-sm font-medium whitespace-nowrap" }, "Zoom: ", zoom.toFixed(1), "x"), /* @__PURE__ */ React7.createElement(
1275
+ ), /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-3 mt-4" }, /* @__PURE__ */ React7.createElement(
1276
+ "label",
1277
+ {
1278
+ htmlFor: "zoom-slider",
1279
+ className: "text-sm font-medium whitespace-nowrap"
1280
+ },
1281
+ "Zoom: ",
1282
+ zoom.toFixed(1),
1283
+ "x"
1284
+ ), /* @__PURE__ */ React7.createElement(
1149
1285
  "input",
1150
1286
  {
1151
1287
  id: "zoom-slider",
@@ -1162,7 +1298,7 @@ function FileInput({
1162
1298
  "button",
1163
1299
  {
1164
1300
  type: "button",
1165
- className: "inline-flex items-center justify-center h-9 rounded-md px-4 text-sm font-medium border border-input bg-transparent hover:bg-accent hover:text-accent-foreground transition-colors",
1301
+ className: "inline-flex items-center justify-center h-9 rounded-md px-4 text-sm font-medium border border-input bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
1166
1302
  onClick: handleCropCancel
1167
1303
  },
1168
1304
  "Cancel"
@@ -1231,7 +1367,9 @@ function DatePicker({
1231
1367
  }) {
1232
1368
  const [isOpen, setIsOpen] = React7.useState(false);
1233
1369
  const [inputValue, setInputValue] = React7.useState("");
1234
- const [selectedMonth, setSelectedMonth] = React7.useState(value || /* @__PURE__ */ new Date());
1370
+ const [selectedMonth, setSelectedMonth] = React7.useState(
1371
+ value || /* @__PURE__ */ new Date()
1372
+ );
1235
1373
  const containerRef = React7.useRef(null);
1236
1374
  const inputRef = React7.useRef(null);
1237
1375
  React7.useEffect(() => {
@@ -1322,7 +1460,7 @@ function DatePicker({
1322
1460
  "button",
1323
1461
  {
1324
1462
  type: "button",
1325
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent cursor-pointer",
1463
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
1326
1464
  onClick: handlePrevMonth,
1327
1465
  "aria-label": "Previous month"
1328
1466
  },
@@ -1331,12 +1469,19 @@ function DatePicker({
1331
1469
  "button",
1332
1470
  {
1333
1471
  type: "button",
1334
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent cursor-pointer",
1472
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
1335
1473
  onClick: handleNextMonth,
1336
1474
  "aria-label": "Next month"
1337
1475
  },
1338
1476
  "\u2192"
1339
- )), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7.createElement("div", { key: day, className: "flex items-center justify-center h-8 w-full text-xs text-muted-foreground font-medium" }, day))), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
1477
+ )), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7.createElement(
1478
+ "div",
1479
+ {
1480
+ key: day,
1481
+ className: "flex items-center justify-center h-8 w-full text-xs font-medium"
1482
+ },
1483
+ day
1484
+ ))), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
1340
1485
  if (!date) {
1341
1486
  return /* @__PURE__ */ React7.createElement("div", { key: `empty-${index}` });
1342
1487
  }
@@ -1348,7 +1493,7 @@ function DatePicker({
1348
1493
  {
1349
1494
  key: date.toISOString(),
1350
1495
  type: "button",
1351
- className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-accent hover:text-accent-foreground ${isSelected ? "bg-primary text-primary-foreground font-semibold" : ""} ${isToday ? "border border-primary" : ""} ${disabled2 ? "cursor-not-allowed opacity-50 pointer-events-none" : ""}`,
1496
+ className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-primary hover:text-primary-foreground ${isSelected ? "bg-primary text-primary-foreground font-semibold" : ""} ${isToday ? "border border-primary" : ""} ${disabled2 ? "cursor-not-allowed opacity-50 pointer-events-none" : ""}`,
1352
1497
  onClick: () => !disabled2 && handleDateSelect(date),
1353
1498
  disabled: disabled2,
1354
1499
  "aria-label": formatDate(date, format)
@@ -1365,26 +1510,33 @@ function DatePicker({
1365
1510
  name,
1366
1511
  value: value ? value.toISOString() : ""
1367
1512
  }
1368
- ), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement("span", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none", "aria-hidden": "true" }, /* @__PURE__ */ React7.createElement(
1369
- "svg",
1513
+ ), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement(
1514
+ "span",
1370
1515
  {
1371
- xmlns: "http://www.w3.org/2000/svg",
1372
- width: "18",
1373
- height: "18",
1374
- viewBox: "0 0 24 24",
1375
- fill: "none",
1376
- stroke: "currentColor",
1377
- strokeLinecap: "round",
1378
- strokeLinejoin: "round",
1379
- strokeWidth: "2"
1516
+ className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
1517
+ "aria-hidden": "true"
1380
1518
  },
1381
- /* @__PURE__ */ React7.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
1382
- )), /* @__PURE__ */ React7.createElement(
1519
+ /* @__PURE__ */ React7.createElement(
1520
+ "svg",
1521
+ {
1522
+ xmlns: "http://www.w3.org/2000/svg",
1523
+ width: "18",
1524
+ height: "18",
1525
+ viewBox: "0 0 24 24",
1526
+ fill: "none",
1527
+ stroke: "currentColor",
1528
+ strokeLinecap: "round",
1529
+ strokeLinejoin: "round",
1530
+ strokeWidth: "2"
1531
+ },
1532
+ /* @__PURE__ */ React7.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
1533
+ )
1534
+ ), /* @__PURE__ */ React7.createElement(
1383
1535
  "input",
1384
1536
  {
1385
1537
  ref: inputRef,
1386
1538
  type: "text",
1387
- className: `flex h-9 w-full rounded-md border border-input bg-transparent ${showIcon ? "pl-10" : "pl-3"} ${clearable && value ? "pr-10" : "pr-3"} py-1 text-base shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm ${error ? "border-red-500 ring-1 ring-red-500" : ""}`,
1539
+ className: `flex h-9 w-full rounded-md border border-input bg-transparent ${showIcon ? "pl-10" : "pl-3"} ${clearable && value ? "pr-10" : "pr-3"} py-1 text-base shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm ${error ? "border-red-500 ring-1 ring-red-500" : ""}`,
1388
1540
  value: inputValue,
1389
1541
  onChange: handleInputChange,
1390
1542
  onClick: handleToggle,
@@ -1401,7 +1553,7 @@ function DatePicker({
1401
1553
  "button",
1402
1554
  {
1403
1555
  type: "button",
1404
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors",
1556
+ className: "absolute right-3 top-1/2 -translate-y-1/2 transition-colors",
1405
1557
  onClick: handleClear,
1406
1558
  "aria-label": "Clear date",
1407
1559
  tabIndex: -1
@@ -1540,36 +1692,43 @@ function TimePicker({
1540
1692
  }
1541
1693
  return mins;
1542
1694
  }, [minuteStep]);
1543
- const combinedClassName = `relative ${className}`.trim();
1695
+ const combinedClassName = cn("relative", className);
1544
1696
  const displayValue = formatTimeValue(timeValue, use24Hour);
1545
- return /* @__PURE__ */ React7.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7.createElement(
1546
- "input",
1697
+ return /* @__PURE__ */ React7.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7.createElement("input", { type: "hidden", name, value }), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement(
1698
+ "span",
1547
1699
  {
1548
- type: "hidden",
1549
- name,
1550
- value
1551
- }
1552
- ), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement("span", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none", "aria-hidden": "true" }, /* @__PURE__ */ React7.createElement(
1553
- "svg",
1554
- {
1555
- xmlns: "http://www.w3.org/2000/svg",
1556
- width: "18",
1557
- height: "18",
1558
- viewBox: "0 0 24 24",
1559
- fill: "none",
1560
- stroke: "currentColor",
1561
- strokeLinecap: "round",
1562
- strokeLinejoin: "round",
1563
- strokeWidth: "2"
1700
+ className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
1701
+ "aria-hidden": "true"
1564
1702
  },
1565
- /* @__PURE__ */ React7.createElement("circle", { cx: "12", cy: "12", r: "10" }),
1566
- /* @__PURE__ */ React7.createElement("path", { d: "M12 6v6l4 2" })
1567
- )), /* @__PURE__ */ React7.createElement(
1703
+ /* @__PURE__ */ React7.createElement(
1704
+ "svg",
1705
+ {
1706
+ xmlns: "http://www.w3.org/2000/svg",
1707
+ width: "18",
1708
+ height: "18",
1709
+ viewBox: "0 0 24 24",
1710
+ fill: "none",
1711
+ stroke: "currentColor",
1712
+ strokeLinecap: "round",
1713
+ strokeLinejoin: "round",
1714
+ strokeWidth: "2"
1715
+ },
1716
+ /* @__PURE__ */ React7.createElement("circle", { cx: "12", cy: "12", r: "10" }),
1717
+ /* @__PURE__ */ React7.createElement("path", { d: "M12 6v6l4 2" })
1718
+ )
1719
+ ), /* @__PURE__ */ React7.createElement(
1568
1720
  "input",
1569
1721
  {
1570
1722
  ref: inputRef,
1571
1723
  type: "text",
1572
- className: `flex h-9 w-full rounded-md border border-input bg-transparent ${showIcon ? "pl-10" : "pl-3"} ${clearable && value ? "pr-10" : "pr-3"} py-1 text-base shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm ${error ? "border-red-500 ring-1 ring-red-500" : ""}`,
1724
+ className: cn(
1725
+ "flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
1726
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
1727
+ "disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1728
+ showIcon ? "pl-10" : "pl-3",
1729
+ clearable && value ? "pr-10" : "pr-3",
1730
+ error && "border-red-500 ring-1 ring-red-500"
1731
+ ),
1573
1732
  value: displayValue,
1574
1733
  onClick: handleToggle,
1575
1734
  onBlur,
@@ -1585,13 +1744,13 @@ function TimePicker({
1585
1744
  "button",
1586
1745
  {
1587
1746
  type: "button",
1588
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors",
1747
+ className: "absolute right-3 top-1/2 -translate-y-1/2 transition-colors",
1589
1748
  onClick: handleClear,
1590
1749
  "aria-label": "Clear time",
1591
1750
  tabIndex: -1
1592
1751
  },
1593
1752
  "\u2715"
1594
- )), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, /* @__PURE__ */ React7.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium text-muted-foreground mb-2 text-center" }, use24Hour ? "Hour" : "Hour"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, hours.map((hour) => {
1753
+ )), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, /* @__PURE__ */ React7.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, use24Hour ? "Hour" : "Hour"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, hours.map((hour) => {
1595
1754
  const displayHour = use24Hour ? hour : hour;
1596
1755
  const isSelected = use24Hour ? timeValue?.hour === (hour === 0 ? 12 : hour > 12 ? hour - 12 : hour) && timeValue?.period === (hour >= 12 ? "PM" : "AM") : timeValue?.hour === hour;
1597
1756
  return /* @__PURE__ */ React7.createElement(
@@ -1599,7 +1758,12 @@ function TimePicker({
1599
1758
  {
1600
1759
  key: hour,
1601
1760
  type: "button",
1602
- className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-accent hover:text-accent-foreground ${isSelected ? "bg-primary text-primary-foreground font-semibold" : ""}`,
1761
+ className: cn(
1762
+ "flex items-center justify-center h-8 w-full rounded",
1763
+ "border-none bg-transparent cursor-pointer text-sm transition-colors",
1764
+ "hover:bg-primary hover:text-primary-foreground",
1765
+ isSelected ? "bg-primary text-primary-foreground font-semibold" : ""
1766
+ ),
1603
1767
  onClick: () => {
1604
1768
  if (use24Hour) {
1605
1769
  const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
@@ -1619,24 +1783,34 @@ function TimePicker({
1619
1783
  },
1620
1784
  String(displayHour).padStart(2, "0")
1621
1785
  );
1622
- }))), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium text-muted-foreground mb-2 text-center" }, "Minute"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, minutes.map((minute) => {
1786
+ }))), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, "Minute"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, minutes.map((minute) => {
1623
1787
  const isSelected = timeValue?.minute === minute;
1624
1788
  return /* @__PURE__ */ React7.createElement(
1625
1789
  "button",
1626
1790
  {
1627
1791
  key: minute,
1628
1792
  type: "button",
1629
- className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-accent hover:text-accent-foreground ${isSelected ? "bg-primary text-primary-foreground font-semibold" : ""}`,
1793
+ className: cn(
1794
+ "flex items-center justify-center h-8 w-full",
1795
+ "rounded border-none bg-transparent cursor-pointer text-sm transition-colors",
1796
+ "hover:bg-primary hover:text-primary-foreground",
1797
+ isSelected ? "bg-primary text-primary-foreground font-semibold" : ""
1798
+ ),
1630
1799
  onClick: () => handleMinuteChange(minute),
1631
1800
  "aria-label": `${String(minute).padStart(2, "0")} minutes`
1632
1801
  },
1633
1802
  String(minute).padStart(2, "0")
1634
1803
  );
1635
- }))), !use24Hour && /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col w-20" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium text-muted-foreground mb-2 text-center" }, "Period"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React7.createElement(
1804
+ }))), !use24Hour && /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col w-20" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, "Period"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React7.createElement(
1636
1805
  "button",
1637
1806
  {
1638
1807
  type: "button",
1639
- className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-accent hover:text-accent-foreground ${timeValue?.period === "AM" ? "bg-primary text-primary-foreground font-semibold" : ""}`,
1808
+ className: cn(
1809
+ "flex items-center justify-center h-8 w-full",
1810
+ "rounded border-none bg-transparent cursor-pointer text-sm",
1811
+ "transition-colors hover:bg-primary hover:text-primary-foreground",
1812
+ timeValue?.period === "AM" ? "bg-muted font-semibold" : ""
1813
+ ),
1640
1814
  onClick: () => handlePeriodChange("AM")
1641
1815
  },
1642
1816
  "AM"
@@ -1644,7 +1818,12 @@ function TimePicker({
1644
1818
  "button",
1645
1819
  {
1646
1820
  type: "button",
1647
- className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-accent hover:text-accent-foreground ${timeValue?.period === "PM" ? "bg-primary text-primary-foreground font-semibold" : ""}`,
1821
+ className: cn(
1822
+ "flex items-center justify-center h-8 w-full",
1823
+ "rounded border-none bg-transparent cursor-pointer text-sm",
1824
+ "transition-colors hover:bg-primary hover:text-primary-foreground",
1825
+ timeValue?.period === "PM" ? "bg-muted font-semibold" : ""
1826
+ ),
1648
1827
  onClick: () => handlePeriodChange("PM")
1649
1828
  },
1650
1829
  "PM"
@@ -1689,7 +1868,9 @@ function DateRangePicker({
1689
1868
  ...props
1690
1869
  }) {
1691
1870
  const [isOpen, setIsOpen] = React7.useState(false);
1692
- const [selectedMonth, setSelectedMonth] = React7.useState(value.start || /* @__PURE__ */ new Date());
1871
+ const [selectedMonth, setSelectedMonth] = React7.useState(
1872
+ value.start || /* @__PURE__ */ new Date()
1873
+ );
1693
1874
  const [rangeStart, setRangeStart] = React7.useState(value.start);
1694
1875
  const [rangeEnd, setRangeEnd] = React7.useState(value.end);
1695
1876
  const [hoverDate, setHoverDate] = React7.useState(null);
@@ -1787,7 +1968,7 @@ function DateRangePicker({
1787
1968
  "button",
1788
1969
  {
1789
1970
  type: "button",
1790
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent cursor-pointer",
1971
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
1791
1972
  onClick: handlePrevMonth,
1792
1973
  "aria-label": "Previous month"
1793
1974
  },
@@ -1796,19 +1977,30 @@ function DateRangePicker({
1796
1977
  "button",
1797
1978
  {
1798
1979
  type: "button",
1799
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent cursor-pointer",
1980
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
1800
1981
  onClick: handleNextMonth,
1801
1982
  "aria-label": "Next month"
1802
1983
  },
1803
1984
  "\u2192"
1804
- )), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7.createElement("div", { key: day, className: "flex items-center justify-center h-8 w-full text-xs text-muted-foreground font-medium" }, day))), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
1985
+ )), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7.createElement(
1986
+ "div",
1987
+ {
1988
+ key: day,
1989
+ className: "flex items-center justify-center h-8 w-full text-xs font-medium"
1990
+ },
1991
+ day
1992
+ ))), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
1805
1993
  if (!date) {
1806
1994
  return /* @__PURE__ */ React7.createElement("div", { key: `empty-${index}` });
1807
1995
  }
1808
1996
  const isStart = rangeStart && date.toDateString() === rangeStart.toDateString();
1809
1997
  const isEnd = rangeEnd && date.toDateString() === rangeEnd.toDateString();
1998
+ const isRangeEndpoint = Boolean(isStart || isEnd);
1810
1999
  const isInRange = rangeStart && rangeEnd && isDateInRange(date, rangeStart, rangeEnd);
1811
2000
  const isInHoverRange = rangeStart && !rangeEnd && hoverDate && (date >= rangeStart && date <= hoverDate || date <= rangeStart && date >= hoverDate);
2001
+ const isRangeHighlight = Boolean(
2002
+ (isInRange || isInHoverRange) && !isRangeEndpoint
2003
+ );
1812
2004
  const isToday = date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
1813
2005
  const disabled2 = isDisabled(date);
1814
2006
  return /* @__PURE__ */ React7.createElement(
@@ -1816,7 +2008,14 @@ function DateRangePicker({
1816
2008
  {
1817
2009
  key: date.toISOString(),
1818
2010
  type: "button",
1819
- className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-accent hover:text-accent-foreground ${isStart || isEnd ? "bg-primary text-primary-foreground font-semibold" : ""} ${isInRange || isInHoverRange ? "bg-accent/50" : ""} ${isToday ? "border border-primary" : ""} ${disabled2 ? "cursor-not-allowed opacity-50 pointer-events-none" : ""}`,
2011
+ className: cn(
2012
+ "flex items-center justify-center h-8 w-full rounded border-none bg-transparent",
2013
+ "cursor-pointer text-sm transition-colors hover:bg-muted",
2014
+ isRangeEndpoint && "bg-muted font-semibold",
2015
+ isRangeHighlight && "bg-muted/70",
2016
+ isToday && "border border-primary",
2017
+ disabled2 && "cursor-not-allowed opacity-50 pointer-events-none"
2018
+ ),
1820
2019
  onClick: () => !disabled2 && handleDateSelect(date),
1821
2020
  onMouseEnter: () => setHoverDate(date),
1822
2021
  onMouseLeave: () => setHoverDate(null),
@@ -1827,7 +2026,7 @@ function DateRangePicker({
1827
2026
  );
1828
2027
  })));
1829
2028
  };
1830
- const combinedClassName = `relative ${className}`.trim();
2029
+ const combinedClassName = cn("relative", className);
1831
2030
  const displayValue = rangeStart && rangeEnd ? `${formatDate2(rangeStart, format)}${separator}${formatDate2(rangeEnd, format)}` : rangeStart ? formatDate2(rangeStart, format) : "";
1832
2031
  return /* @__PURE__ */ React7.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7.createElement(
1833
2032
  "input",
@@ -1843,25 +2042,39 @@ function DateRangePicker({
1843
2042
  name: `${name}[end]`,
1844
2043
  value: rangeEnd ? rangeEnd.toISOString() : ""
1845
2044
  }
1846
- ), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement("span", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none", "aria-hidden": "true" }, /* @__PURE__ */ React7.createElement(
1847
- "svg",
2045
+ ), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement(
2046
+ "span",
1848
2047
  {
1849
- xmlns: "http://www.w3.org/2000/svg",
1850
- width: "18",
1851
- height: "18",
1852
- viewBox: "0 0 24 24",
1853
- fill: "none",
1854
- stroke: "currentColor",
1855
- strokeLinecap: "round",
1856
- strokeLinejoin: "round",
1857
- strokeWidth: "2"
2048
+ className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
2049
+ "aria-hidden": "true"
1858
2050
  },
1859
- /* @__PURE__ */ React7.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
1860
- )), /* @__PURE__ */ React7.createElement(
2051
+ /* @__PURE__ */ React7.createElement(
2052
+ "svg",
2053
+ {
2054
+ xmlns: "http://www.w3.org/2000/svg",
2055
+ width: "18",
2056
+ height: "18",
2057
+ viewBox: "0 0 24 24",
2058
+ fill: "none",
2059
+ stroke: "currentColor",
2060
+ strokeLinecap: "round",
2061
+ strokeLinejoin: "round",
2062
+ strokeWidth: "2"
2063
+ },
2064
+ /* @__PURE__ */ React7.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
2065
+ )
2066
+ ), /* @__PURE__ */ React7.createElement(
1861
2067
  "input",
1862
2068
  {
1863
2069
  type: "text",
1864
- className: `flex h-9 w-full rounded-md border border-input bg-transparent ${showIcon ? "pl-10" : "pl-3"} ${clearable && (rangeStart || rangeEnd) ? "pr-10" : "pr-3"} py-1 text-base shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm ${error ? "border-red-500 ring-1 ring-red-500" : ""}`,
2070
+ className: cn(
2071
+ "flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
2072
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
2073
+ "disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
2074
+ showIcon ? "pl-10" : "pl-3",
2075
+ clearable && (rangeStart || rangeEnd) ? "pr-10" : "pr-3",
2076
+ error && "border-red-500 ring-1 ring-red-500"
2077
+ ),
1865
2078
  value: displayValue,
1866
2079
  onClick: handleToggle,
1867
2080
  onBlur,
@@ -1877,13 +2090,13 @@ function DateRangePicker({
1877
2090
  "button",
1878
2091
  {
1879
2092
  type: "button",
1880
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors",
2093
+ className: "absolute right-3 top-1/2 -translate-y-1/2 transition-colors",
1881
2094
  onClick: handleClear,
1882
2095
  "aria-label": "Clear date range",
1883
2096
  tabIndex: -1
1884
2097
  },
1885
2098
  "\u2715"
1886
- )), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, renderCalendar(), rangeStart && !rangeEnd && /* @__PURE__ */ React7.createElement("div", { className: "text-xs text-muted-foreground text-center pt-2 border-t border-border mt-2" }, "Select end date")));
2099
+ )), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, renderCalendar(), rangeStart && !rangeEnd && /* @__PURE__ */ React7.createElement("div", { className: "text-xs text-center pt-2 border-t border-border mt-2" }, "Select end date")));
1887
2100
  }
1888
2101
  DateRangePicker.displayName = "DateRangePicker";
1889
2102
  function htmlToMarkdown(html) {
@@ -1939,11 +2152,19 @@ function RichTextEditor({
1939
2152
  className = "",
1940
2153
  mode = "wysiwyg",
1941
2154
  allowModeSwitch = false,
1942
- placeholder = "Start typing...",
2155
+ placeholder = "Your message...",
1943
2156
  minHeight = "200px",
1944
2157
  maxHeight,
1945
2158
  showToolbar = true,
1946
- toolbarButtons = ["bold", "italic", "underline", "heading", "bulletList", "orderedList", "link"],
2159
+ toolbarButtons = [
2160
+ "bold",
2161
+ "italic",
2162
+ "underline",
2163
+ "heading",
2164
+ "bulletList",
2165
+ "orderedList",
2166
+ "link"
2167
+ ],
1947
2168
  ...props
1948
2169
  }) {
1949
2170
  const [currentMode, setCurrentMode] = React7.useState(mode);
@@ -2052,7 +2273,7 @@ function RichTextEditor({
2052
2273
  {
2053
2274
  key: buttonName,
2054
2275
  type: "button",
2055
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent text-muted-foreground hover:text-foreground cursor-pointer transition-colors disabled:cursor-not-allowed disabled:opacity-50",
2276
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-muted cursor-pointer transition-colors disabled:cursor-not-allowed disabled:opacity-50",
2056
2277
  onClick: () => editorRef.current && button.action(editorRef.current),
2057
2278
  title: button.title,
2058
2279
  disabled: disabled || currentMode === "markdown",
@@ -2064,7 +2285,7 @@ function RichTextEditor({
2064
2285
  "button",
2065
2286
  {
2066
2287
  type: "button",
2067
- className: "flex items-center justify-center h-8 px-3 rounded border-none bg-transparent hover:bg-accent text-xs font-medium text-muted-foreground hover:text-foreground cursor-pointer transition-colors disabled:cursor-not-allowed disabled:opacity-50",
2288
+ className: "flex items-center justify-center h-8 px-3 rounded border-none bg-transparent hover:bg-muted text-xs font-medium cursor-pointer transition-colors disabled:cursor-not-allowed disabled:opacity-50",
2068
2289
  onClick: handleModeToggle,
2069
2290
  disabled,
2070
2291
  title: `Switch to ${currentMode === "wysiwyg" ? "Markdown" : "WYSIWYG"}`,
@@ -2075,7 +2296,7 @@ function RichTextEditor({
2075
2296
  "div",
2076
2297
  {
2077
2298
  ref: editorRef,
2078
- className: "w-full p-3 text-base md:text-sm outline-none bg-transparent focus-visible:outline-none [&:empty:before]:content-[attr(data-placeholder)] [&:empty:before]:text-muted-foreground",
2299
+ className: "w-full p-3 text-base md:text-sm outline-none bg-transparent focus-visible:outline-none [&:empty:before]:content-[attr(data-placeholder)]",
2079
2300
  role: "textbox",
2080
2301
  contentEditable: !disabled,
2081
2302
  onInput: handleWysiwygChange,
@@ -2090,7 +2311,7 @@ function RichTextEditor({
2090
2311
  "textarea",
2091
2312
  {
2092
2313
  ref: textareaRef,
2093
- className: "w-full p-3 text-base md:text-sm outline-none bg-transparent resize-none focus-visible:outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
2314
+ className: "w-full p-3 text-base md:text-sm outline-none bg-transparent resize-none focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
2094
2315
  value: content,
2095
2316
  onChange: handleMarkdownChange,
2096
2317
  onBlur,