@page-speed/forms 0.4.3 → 0.4.4

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.cjs CHANGED
@@ -1,8 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var React7 = require('react');
3
+ var React8 = require('react');
4
4
  var clsx = require('clsx');
5
5
  var tailwindMerge = require('tailwind-merge');
6
+ var useOnClickOutside = require('@opensite/hooks/useOnClickOutside');
6
7
 
7
8
  function _interopNamespace(e) {
8
9
  if (e && e.__esModule) return e;
@@ -22,7 +23,13 @@ function _interopNamespace(e) {
22
23
  return Object.freeze(n);
23
24
  }
24
25
 
25
- var React7__namespace = /*#__PURE__*/_interopNamespace(React7);
26
+ var React8__namespace = /*#__PURE__*/_interopNamespace(React8);
27
+
28
+ // src/inputs/TextInput.tsx
29
+ function cn(...inputs) {
30
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
31
+ }
32
+ var INPUT_AUTOFILL_RESET_CLASSES = "autofill:bg-transparent autofill:text-foreground [&:-webkit-autofill]:[-webkit-text-fill-color:hsl(var(--foreground))] [&:-webkit-autofill]:[caret-color:hsl(var(--foreground))] [&:-webkit-autofill]:[box-shadow:0_0_0px_1000px_hsl(var(--background))_inset] [&:-webkit-autofill:hover]:[box-shadow:0_0_0px_1000px_hsl(var(--background))_inset] [&:-webkit-autofill:focus]:[box-shadow:0_0_0px_1000px_hsl(var(--background))_inset] [&:-webkit-autofill]:[transition:background-color_9999s_ease-out,color_9999s_ease-out]";
26
33
 
27
34
  // src/inputs/TextInput.tsx
28
35
  function TextInput({
@@ -45,10 +52,17 @@ function TextInput({
45
52
  const handleBlur = () => {
46
53
  onBlur?.();
47
54
  };
48
- 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";
49
- const errorClassName = error ? "border-red-500 ring-1 ring-red-500" : "";
50
- const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
51
- return /* @__PURE__ */ React7__namespace.createElement(
55
+ const hasValue = String(value ?? "").trim().length > 0;
56
+ const combinedClassName = cn(
57
+ "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors",
58
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
59
+ "disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
60
+ INPUT_AUTOFILL_RESET_CLASSES,
61
+ !error && hasValue && "ring-2 ring-ring",
62
+ error && "border-destructive ring-1 ring-destructive",
63
+ className
64
+ );
65
+ return /* @__PURE__ */ React8__namespace.createElement(
52
66
  "input",
53
67
  {
54
68
  type,
@@ -92,10 +106,17 @@ function TextArea({
92
106
  const handleBlur = () => {
93
107
  onBlur?.();
94
108
  };
95
- 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";
96
- const errorClassName = error ? "border-red-500 ring-1 ring-red-500" : "";
97
- const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
98
- return /* @__PURE__ */ React7__namespace.createElement(
109
+ const hasValue = String(value ?? "").trim().length > 0;
110
+ const combinedClassName = cn(
111
+ "flex min-h-20 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm transition-colors",
112
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
113
+ "disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
114
+ INPUT_AUTOFILL_RESET_CLASSES,
115
+ !error && hasValue && "ring-2 ring-ring",
116
+ error && "border-destructive ring-1 ring-destructive",
117
+ className
118
+ );
119
+ return /* @__PURE__ */ React8__namespace.createElement(
99
120
  "textarea",
100
121
  {
101
122
  name,
@@ -119,9 +140,53 @@ function TextArea({
119
140
  );
120
141
  }
121
142
  TextArea.displayName = "TextArea";
122
- function cn(...inputs) {
123
- return tailwindMerge.twMerge(clsx.clsx(inputs));
124
- }
143
+ var LabelGroup = ({
144
+ labelHtmlFor,
145
+ required = false,
146
+ variant = "label",
147
+ secondaryId,
148
+ secondary,
149
+ primary,
150
+ primaryClassName,
151
+ secondaryClassName
152
+ }) => {
153
+ const primaryClasses = cn(
154
+ "text-sm font-medium leading-snug",
155
+ variant === "legend" ? "mb-1.5" : "mb-1 block",
156
+ primaryClassName
157
+ );
158
+ const requiredIndicator = required ? /* @__PURE__ */ React8__namespace.createElement("span", { className: "text-destructive pl-0.5", "aria-label": "required" }, "*") : null;
159
+ let primaryElement = null;
160
+ if (primary) {
161
+ if (variant === "label") {
162
+ primaryElement = /* @__PURE__ */ React8__namespace.createElement(
163
+ "label",
164
+ {
165
+ htmlFor: labelHtmlFor,
166
+ "data-slot": "field-label",
167
+ className: primaryClasses
168
+ },
169
+ primary,
170
+ requiredIndicator
171
+ );
172
+ } else if (variant === "legend") {
173
+ primaryElement = /* @__PURE__ */ React8__namespace.createElement("legend", { "data-slot": "field-legend", className: primaryClasses }, primary, requiredIndicator);
174
+ } else {
175
+ primaryElement = /* @__PURE__ */ React8__namespace.createElement("div", { "data-slot": "field-label", className: primaryClasses }, primary, requiredIndicator);
176
+ }
177
+ }
178
+ const secondaryElement = secondary ? /* @__PURE__ */ React8__namespace.createElement(
179
+ "p",
180
+ {
181
+ "data-slot": "field-description",
182
+ id: secondaryId,
183
+ className: cn("text-sm leading-normal font-normal", secondaryClassName)
184
+ },
185
+ secondary
186
+ ) : null;
187
+ if (!primaryElement && !secondaryElement) return null;
188
+ return /* @__PURE__ */ React8__namespace.createElement(React8__namespace.Fragment, null, primaryElement, secondaryElement);
189
+ };
125
190
 
126
191
  // src/inputs/Checkbox.tsx
127
192
  function Checkbox({
@@ -136,12 +201,12 @@ function Checkbox({
136
201
  indeterminate = false,
137
202
  label,
138
203
  description,
139
- checkboxVariant = "boxed",
204
+ useChoiceCard = false,
140
205
  ...props
141
206
  }) {
142
- const inputRef = React7__namespace.useRef(null);
207
+ const inputRef = React8__namespace.useRef(null);
143
208
  const checkboxId = props.id || `checkbox-${name}`;
144
- React7__namespace.useEffect(() => {
209
+ React8__namespace.useEffect(() => {
145
210
  if (inputRef.current) {
146
211
  inputRef.current.indeterminate = indeterminate;
147
212
  }
@@ -153,7 +218,7 @@ function Checkbox({
153
218
  onBlur?.();
154
219
  };
155
220
  const isActive = value || indeterminate && !value;
156
- const checkbox = /* @__PURE__ */ React7__namespace.createElement(
221
+ const checkbox = /* @__PURE__ */ React8__namespace.createElement(
157
222
  "div",
158
223
  {
159
224
  className: cn(
@@ -161,7 +226,7 @@ function Checkbox({
161
226
  !label && className
162
227
  )
163
228
  },
164
- /* @__PURE__ */ React7__namespace.createElement(
229
+ /* @__PURE__ */ React8__namespace.createElement(
165
230
  "input",
166
231
  {
167
232
  ref: inputRef,
@@ -180,7 +245,7 @@ function Checkbox({
180
245
  ...props
181
246
  }
182
247
  ),
183
- /* @__PURE__ */ React7__namespace.createElement(
248
+ /* @__PURE__ */ React8__namespace.createElement(
184
249
  "div",
185
250
  {
186
251
  className: cn(
@@ -193,7 +258,7 @@ function Checkbox({
193
258
  "peer-focus-visible:ring-2 peer-focus-visible:ring-ring/50 peer-focus-visible:ring-offset-1"
194
259
  )
195
260
  },
196
- value && /* @__PURE__ */ React7__namespace.createElement(
261
+ value && /* @__PURE__ */ React8__namespace.createElement(
197
262
  "svg",
198
263
  {
199
264
  className: "size-3.5",
@@ -204,9 +269,9 @@ function Checkbox({
204
269
  strokeLinecap: "round",
205
270
  strokeLinejoin: "round"
206
271
  },
207
- /* @__PURE__ */ React7__namespace.createElement("polyline", { points: "20 6 9 17 4 12" })
272
+ /* @__PURE__ */ React8__namespace.createElement("polyline", { points: "20 6 9 17 4 12" })
208
273
  ),
209
- indeterminate && !value && /* @__PURE__ */ React7__namespace.createElement(
274
+ indeterminate && !value && /* @__PURE__ */ React8__namespace.createElement(
210
275
  "svg",
211
276
  {
212
277
  className: "size-3.5",
@@ -217,31 +282,44 @@ function Checkbox({
217
282
  strokeLinecap: "round",
218
283
  strokeLinejoin: "round"
219
284
  },
220
- /* @__PURE__ */ React7__namespace.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
285
+ /* @__PURE__ */ React8__namespace.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
221
286
  )
222
287
  )
223
288
  );
224
289
  if (label) {
225
- return /* @__PURE__ */ React7__namespace.createElement(
290
+ return /* @__PURE__ */ React8__namespace.createElement(
226
291
  "label",
227
292
  {
228
293
  className: cn(
229
294
  "w-full h-full flex gap-3 p-3 duration-200",
230
- checkboxVariant === "boxed" && "border rounded-lg hover:ring-2",
231
- checkboxVariant === "boxed" && value && "ring-2",
295
+ useChoiceCard && "border rounded-lg hover:ring-2",
296
+ useChoiceCard && value && "ring-2",
232
297
  disabled ? "opacity-50 cursor-not-allowed hover:ring-0" : "cursor-pointer",
233
298
  className
234
299
  ),
235
300
  htmlFor: checkboxId
236
301
  },
237
- /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex w-full flex-row gap-2" }, checkbox, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-sm font-medium" }, label), description && /* @__PURE__ */ React7__namespace.createElement(
238
- "p",
302
+ /* @__PURE__ */ React8__namespace.createElement(
303
+ "div",
239
304
  {
240
- className: "text-xs opacity-75",
241
- id: `${checkboxId}-description`
305
+ className: cn(
306
+ "flex w-full flex-row gap-2",
307
+ useChoiceCard ? "items-start" : "items-center"
308
+ )
242
309
  },
243
- description
244
- )))
310
+ checkbox,
311
+ /* @__PURE__ */ React8__namespace.createElement(
312
+ LabelGroup,
313
+ {
314
+ variant: "text",
315
+ primary: label,
316
+ secondary: description,
317
+ secondaryId: description ? `${checkboxId}-description` : void 0,
318
+ primaryClassName: "mb-0",
319
+ secondaryClassName: "text-xs opacity-75"
320
+ }
321
+ )
322
+ )
245
323
  );
246
324
  }
247
325
  return checkbox;
@@ -275,13 +353,11 @@ function CheckboxGroup({
275
353
  ).length;
276
354
  const allSelected = selectedEnabledCount === enabledOptions.length;
277
355
  const someSelected = selectedEnabledCount > 0 && !allSelected;
278
- const checkboxVariant = React7__namespace.useMemo(() => {
279
- if (options.some((opt) => opt.description)) {
280
- return "boxed";
281
- }
282
- return "inline";
356
+ const useChoiceCard = React8__namespace.useMemo(() => {
357
+ if (!options) return false;
358
+ return options?.some((opt) => opt.description);
283
359
  }, [options]);
284
- const countableValue = React7__namespace.useMemo(() => {
360
+ const countableValue = React8__namespace.useMemo(() => {
285
361
  if (value?.length > 0) {
286
362
  return value.length;
287
363
  }
@@ -306,29 +382,37 @@ function CheckboxGroup({
306
382
  onBlur?.();
307
383
  };
308
384
  const maxReached = Boolean(maxSelections && countableValue >= maxSelections);
309
- const containerClass = cn(
310
- "w-full gap-3",
311
- layout === "stacked" && "flex flex-col",
312
- layout === "inline" && "flex flex-row flex-wrap",
313
- layout === "grid" && "grid",
314
- className
315
- );
316
- return /* @__PURE__ */ React7__namespace.createElement(
317
- "div",
385
+ const containerClass = React8__namespace.useMemo(() => {
386
+ return cn(
387
+ "w-full gap-3 grid grid-cols-1 border-0 m-0 p-0 min-w-0",
388
+ (layout === "grid" || layout === "inline") && "md:grid-cols-2",
389
+ className
390
+ );
391
+ }, [layout, className]);
392
+ const groupDescriptionId = description ? `${name}-description` : void 0;
393
+ const groupAriaDescribedBy = [props["aria-describedby"], groupDescriptionId].filter(Boolean).join(" ") || void 0;
394
+ return /* @__PURE__ */ React8__namespace.createElement(
395
+ "fieldset",
318
396
  {
319
397
  className: containerClass,
320
398
  role: "group",
321
399
  "aria-invalid": error || props["aria-invalid"],
322
- "aria-describedby": props["aria-describedby"],
400
+ "aria-describedby": groupAriaDescribedBy,
323
401
  "aria-required": required || props["aria-required"],
324
- "aria-label": typeof label === "string" ? label : props["aria-label"],
325
- style: layout === "grid" ? {
326
- gridTemplateColumns: `repeat(${gridColumns}, 1fr)`
327
- } : void 0
402
+ "aria-label": typeof label === "string" ? label : props["aria-label"]
328
403
  },
329
- label ? /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-sm font-medium" }, label) : null,
330
- description ? /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-xs opacity-70" }, description) : null,
331
- showSelectAll && enabledOptions.length > 0 && /* @__PURE__ */ React7__namespace.createElement(
404
+ /* @__PURE__ */ React8__namespace.createElement(
405
+ LabelGroup,
406
+ {
407
+ labelHtmlFor: name,
408
+ required,
409
+ variant: "legend",
410
+ secondaryId: groupDescriptionId,
411
+ secondary: description,
412
+ primary: label
413
+ }
414
+ ),
415
+ showSelectAll && enabledOptions.length > 0 && /* @__PURE__ */ React8__namespace.createElement(
332
416
  Checkbox,
333
417
  {
334
418
  name: `${name}-select-all`,
@@ -338,7 +422,7 @@ function CheckboxGroup({
338
422
  onBlur: handleBlur,
339
423
  indeterminate: someSelected,
340
424
  label: selectAllLabel,
341
- checkboxVariant: "inline",
425
+ useChoiceCard,
342
426
  disabled,
343
427
  "aria-label": selectAllLabel
344
428
  }
@@ -346,7 +430,7 @@ function CheckboxGroup({
346
430
  options.map((option) => {
347
431
  const isChecked = value.includes(option.value);
348
432
  const isDisabled = disabled || option.disabled || maxReached && !isChecked;
349
- return /* @__PURE__ */ React7__namespace.createElement(
433
+ return /* @__PURE__ */ React8__namespace.createElement(
350
434
  Checkbox,
351
435
  {
352
436
  key: option.value,
@@ -360,11 +444,11 @@ function CheckboxGroup({
360
444
  error,
361
445
  label: renderOption ? renderOption(option) : option.label,
362
446
  description: renderOption ? void 0 : option.description,
363
- checkboxVariant
447
+ useChoiceCard
364
448
  }
365
449
  );
366
450
  }),
367
- (minSelections || maxSelections) && /* @__PURE__ */ React7__namespace.createElement(
451
+ (minSelections || maxSelections) && /* @__PURE__ */ React8__namespace.createElement(
368
452
  "div",
369
453
  {
370
454
  className: cn(
@@ -373,8 +457,8 @@ function CheckboxGroup({
373
457
  ),
374
458
  "aria-live": "polite"
375
459
  },
376
- minSelections && countableValue < minSelections && /* @__PURE__ */ React7__namespace.createElement("span", null, "Select at least ", minSelections, " option", minSelections !== 1 ? "s" : ""),
377
- maxSelections && /* @__PURE__ */ React7__namespace.createElement("span", null, countableValue, "/", maxSelections, " selected")
460
+ minSelections && countableValue < minSelections && /* @__PURE__ */ React8__namespace.createElement("span", null, "Select at least ", minSelections, " option", minSelections !== 1 ? "s" : ""),
461
+ maxSelections && /* @__PURE__ */ React8__namespace.createElement("span", null, countableValue, "/", maxSelections, " selected")
378
462
  )
379
463
  );
380
464
  }
@@ -390,6 +474,7 @@ function Radio({
390
474
  className = "",
391
475
  layout = "stacked",
392
476
  label,
477
+ description,
393
478
  options,
394
479
  ...props
395
480
  }) {
@@ -424,33 +509,43 @@ function Radio({
424
509
  const handleBlur = () => {
425
510
  onBlur?.();
426
511
  };
427
- const useChoiceCard = React7__namespace.useMemo(() => {
512
+ const useChoiceCard = React8__namespace.useMemo(() => {
428
513
  return options.some((option) => option.description);
429
514
  }, [options]);
430
- const containerClass = React7__namespace.useMemo(() => {
515
+ const containerClass = React8__namespace.useMemo(() => {
431
516
  return cn(
432
- "w-full gap-3 grid grid-cols-1",
433
- layout === "inline" && "md:grid-cols-2",
517
+ "w-full gap-3 grid grid-cols-1 border-0 m-0 p-0 min-w-0",
518
+ (layout === "grid" || layout === "inline") && "md:grid-cols-2",
434
519
  className
435
520
  );
436
521
  }, [layout, className]);
437
- return /* @__PURE__ */ React7__namespace.createElement(
438
- "div",
522
+ const groupDescriptionId = description ? `${name}-description` : void 0;
523
+ const groupAriaDescribedBy = [props["aria-describedby"], groupDescriptionId].filter(Boolean).join(" ") || void 0;
524
+ return /* @__PURE__ */ React8__namespace.createElement(
525
+ "fieldset",
439
526
  {
440
527
  className: containerClass,
441
528
  role: "radiogroup",
442
529
  "aria-invalid": error || props["aria-invalid"],
443
- "aria-describedby": props["aria-describedby"],
530
+ "aria-describedby": groupAriaDescribedBy,
444
531
  "aria-required": required || props["aria-required"],
445
532
  "aria-label": typeof label === "string" ? label : props["aria-label"]
446
533
  },
447
- label && /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-sm font-medium mb-2" }, label),
534
+ /* @__PURE__ */ React8__namespace.createElement(
535
+ LabelGroup,
536
+ {
537
+ variant: "legend",
538
+ primary: label,
539
+ secondary: description,
540
+ secondaryId: groupDescriptionId
541
+ }
542
+ ),
448
543
  options.map((option, index) => {
449
544
  const isChecked = value === option.value;
450
545
  const isDisabled = disabled || option.disabled;
451
546
  const radioId = `${name}-${option.value}`;
452
547
  const hasDescription = option.description != null && option.description !== "";
453
- const radioIndicator = /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative inline-flex items-center justify-center" }, /* @__PURE__ */ React7__namespace.createElement(
548
+ const radioIndicator = /* @__PURE__ */ React8__namespace.createElement("div", { className: "relative inline-flex items-center justify-center" }, /* @__PURE__ */ React8__namespace.createElement(
454
549
  "input",
455
550
  {
456
551
  type: "radio",
@@ -465,7 +560,7 @@ function Radio({
465
560
  className: "peer sr-only",
466
561
  "aria-describedby": hasDescription ? `${radioId}-description` : props["aria-describedby"]
467
562
  }
468
- ), /* @__PURE__ */ React7__namespace.createElement(
563
+ ), /* @__PURE__ */ React8__namespace.createElement(
469
564
  "div",
470
565
  {
471
566
  className: cn(
@@ -478,10 +573,20 @@ function Radio({
478
573
  "peer-focus-visible:ring-2 peer-focus-visible:ring-ring/50 peer-focus-visible:ring-offset-1"
479
574
  )
480
575
  },
481
- isChecked && /* @__PURE__ */ React7__namespace.createElement("div", { className: "size-3 rounded-full bg-primary" })
576
+ isChecked && /* @__PURE__ */ React8__namespace.createElement("div", { className: "size-3 rounded-full bg-primary" })
482
577
  ));
483
- const labelContent = /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-sm font-medium" }, option.label), hasDescription && /* @__PURE__ */ React7__namespace.createElement("p", { className: "text-xs opacity-75", id: `${radioId}-description` }, option.description));
484
- return /* @__PURE__ */ React7__namespace.createElement(
578
+ const labelContent = /* @__PURE__ */ React8__namespace.createElement(
579
+ LabelGroup,
580
+ {
581
+ variant: "text",
582
+ primary: option.label,
583
+ secondary: hasDescription ? option.description : void 0,
584
+ secondaryId: hasDescription ? `${radioId}-description` : void 0,
585
+ primaryClassName: "mb-0",
586
+ secondaryClassName: "text-xs opacity-75"
587
+ }
588
+ );
589
+ return /* @__PURE__ */ React8__namespace.createElement(
485
590
  "label",
486
591
  {
487
592
  key: option.value,
@@ -495,7 +600,18 @@ function Radio({
495
600
  onKeyDown: (e) => handleKeyDown(e, index),
496
601
  tabIndex: isDisabled ? -1 : 0
497
602
  },
498
- /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, !useChoiceCard && radioIndicator, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, labelContent), useChoiceCard && radioIndicator)
603
+ /* @__PURE__ */ React8__namespace.createElement(
604
+ "div",
605
+ {
606
+ className: cn(
607
+ "flex w-full flex-row gap-2",
608
+ useChoiceCard ? "items-start" : "items-center"
609
+ )
610
+ },
611
+ !useChoiceCard && radioIndicator,
612
+ /* @__PURE__ */ React8__namespace.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, labelContent),
613
+ useChoiceCard && radioIndicator
614
+ )
499
615
  );
500
616
  })
501
617
  );
@@ -520,19 +636,19 @@ function Select({
520
636
  renderOption,
521
637
  ...props
522
638
  }) {
523
- const [isOpen, setIsOpen] = React7__namespace.useState(false);
524
- const [searchQuery, setSearchQuery] = React7__namespace.useState("");
525
- const [focusedIndex, setFocusedIndex] = React7__namespace.useState(-1);
526
- const selectRef = React7__namespace.useRef(null);
527
- const searchInputRef = React7__namespace.useRef(null);
639
+ const [isOpen, setIsOpen] = React8__namespace.useState(false);
640
+ const [searchQuery, setSearchQuery] = React8__namespace.useState("");
641
+ const [focusedIndex, setFocusedIndex] = React8__namespace.useState(-1);
642
+ const selectRef = React8__namespace.useRef(null);
643
+ const searchInputRef = React8__namespace.useRef(null);
528
644
  const dropdownId = `${name}-dropdown`;
529
- const allOptions = React7__namespace.useMemo(() => {
645
+ const allOptions = React8__namespace.useMemo(() => {
530
646
  if (optionGroups.length > 0) {
531
647
  return optionGroups.flatMap((group) => group.options);
532
648
  }
533
649
  return options;
534
650
  }, [options, optionGroups]);
535
- const filteredOptions = React7__namespace.useMemo(() => {
651
+ const filteredOptions = React8__namespace.useMemo(() => {
536
652
  if (!searchQuery.trim()) {
537
653
  return allOptions;
538
654
  }
@@ -542,9 +658,10 @@ function Select({
542
658
  return label.toLowerCase().includes(query);
543
659
  });
544
660
  }, [allOptions, searchQuery]);
545
- const selectedOption = React7__namespace.useMemo(() => {
661
+ const selectedOption = React8__namespace.useMemo(() => {
546
662
  return allOptions.find((opt) => opt.value === value);
547
663
  }, [allOptions, value]);
664
+ const hasValue = Boolean(value);
548
665
  const handleSelect = (optionValue) => {
549
666
  onChange(optionValue);
550
667
  setIsOpen(false);
@@ -639,27 +756,22 @@ function Select({
639
756
  break;
640
757
  }
641
758
  };
642
- const handleBlur = () => {
643
- onBlur?.();
644
- };
645
- React7__namespace.useEffect(() => {
646
- const handleClickOutside = (event) => {
647
- if (selectRef.current && !selectRef.current.contains(event.target)) {
648
- setIsOpen(false);
649
- setSearchQuery("");
650
- setFocusedIndex(-1);
651
- handleBlur();
652
- }
653
- };
654
- if (isOpen) {
655
- document.addEventListener("mousedown", handleClickOutside);
656
- return () => {
657
- document.removeEventListener("mousedown", handleClickOutside);
658
- };
759
+ const handleBlur = (event) => {
760
+ const nextTarget = event?.relatedTarget;
761
+ if (!nextTarget || !selectRef.current?.contains(nextTarget)) {
762
+ onBlur?.();
659
763
  }
660
- }, [isOpen]);
661
- const combinedClassName = `relative w-full ${className}`.trim();
662
- return /* @__PURE__ */ React7__namespace.createElement(
764
+ };
765
+ const closeDropdown = React8__namespace.useCallback(() => {
766
+ if (!isOpen) return;
767
+ setIsOpen(false);
768
+ setSearchQuery("");
769
+ setFocusedIndex(-1);
770
+ onBlur?.();
771
+ }, [isOpen, onBlur]);
772
+ useOnClickOutside.useOnClickOutside(selectRef, closeDropdown, "pointerdown", true);
773
+ const combinedClassName = cn("relative w-full", className);
774
+ return /* @__PURE__ */ React8__namespace.createElement(
663
775
  "div",
664
776
  {
665
777
  ref: selectRef,
@@ -667,7 +779,7 @@ function Select({
667
779
  onKeyDown: handleKeyDown,
668
780
  onBlur: handleBlur
669
781
  },
670
- /* @__PURE__ */ React7__namespace.createElement(
782
+ /* @__PURE__ */ React8__namespace.createElement(
671
783
  "select",
672
784
  {
673
785
  name,
@@ -680,13 +792,19 @@ function Select({
680
792
  tabIndex: -1,
681
793
  style: { display: "none" }
682
794
  },
683
- /* @__PURE__ */ React7__namespace.createElement("option", { value: "" }, "Select..."),
684
- allOptions.map((option) => /* @__PURE__ */ React7__namespace.createElement("option", { key: option.value, value: option.value }, typeof option.label === "string" ? option.label : option.value))
795
+ /* @__PURE__ */ React8__namespace.createElement("option", { value: "" }, "Select..."),
796
+ allOptions.map((option) => /* @__PURE__ */ React8__namespace.createElement("option", { key: option.value, value: option.value }, typeof option.label === "string" ? option.label : option.value))
685
797
  ),
686
- /* @__PURE__ */ React7__namespace.createElement(
798
+ /* @__PURE__ */ React8__namespace.createElement(
687
799
  "div",
688
800
  {
689
- 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" : ""}`,
801
+ className: cn(
802
+ "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",
803
+ "cursor-pointer transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
804
+ !error && hasValue && "ring-2 ring-ring",
805
+ disabled && "cursor-not-allowed opacity-50 pointer-events-none",
806
+ error && "border-destructive ring-1 ring-destructive"
807
+ ),
690
808
  onClick: handleToggle,
691
809
  role: "combobox",
692
810
  "aria-expanded": isOpen,
@@ -697,8 +815,8 @@ function Select({
697
815
  "aria-disabled": disabled,
698
816
  tabIndex: disabled ? -1 : 0
699
817
  },
700
- /* @__PURE__ */ React7__namespace.createElement("span", { className: "flex items-center flex-1 overflow-hidden text-ellipsis" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React7__namespace.createElement("span", { className: "relative" }, placeholder)),
701
- /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center gap-1 ml-2" }, loading && /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-xs" }, "\u23F3"), clearable && value && !disabled && !loading && /* @__PURE__ */ React7__namespace.createElement(
818
+ /* @__PURE__ */ React8__namespace.createElement("span", { className: "flex items-center flex-1 overflow-hidden text-ellipsis" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React8__namespace.createElement("span", { className: "relative" }, placeholder)),
819
+ /* @__PURE__ */ React8__namespace.createElement("div", { className: "flex items-center gap-1 ml-2" }, loading && /* @__PURE__ */ React8__namespace.createElement("span", { className: "text-xs" }, "\u23F3"), clearable && value && !disabled && !loading && /* @__PURE__ */ React8__namespace.createElement(
702
820
  "button",
703
821
  {
704
822
  type: "button",
@@ -708,21 +826,24 @@ function Select({
708
826
  tabIndex: -1
709
827
  },
710
828
  "\u2715"
711
- ), /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-xs leading-none", "aria-hidden": "true" }, isOpen ? "\u25B2" : "\u25BC"))
829
+ ), /* @__PURE__ */ React8__namespace.createElement("span", { className: "text-xs leading-none", "aria-hidden": "true" }, isOpen ? "\u25B2" : "\u25BC"))
712
830
  ),
713
- isOpen && /* @__PURE__ */ React7__namespace.createElement(
831
+ isOpen && /* @__PURE__ */ React8__namespace.createElement(
714
832
  "div",
715
833
  {
716
834
  id: dropdownId,
717
835
  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",
718
836
  role: "listbox"
719
837
  },
720
- searchable && /* @__PURE__ */ React7__namespace.createElement("div", { className: "p-2 border-b border-border" }, /* @__PURE__ */ React7__namespace.createElement(
838
+ searchable && /* @__PURE__ */ React8__namespace.createElement("div", { className: "p-2 border-b border-border" }, /* @__PURE__ */ React8__namespace.createElement(
721
839
  "input",
722
840
  {
723
841
  ref: searchInputRef,
724
842
  type: "text",
725
- className: "w-full border border-input rounded px-2 py-1 text-sm bg-transparent outline-none focus:ring-1 focus:ring-ring",
843
+ className: cn(
844
+ "w-full border border-input rounded px-2 py-1 text-sm bg-transparent outline-none focus:ring-1 focus:ring-ring",
845
+ INPUT_AUTOFILL_RESET_CLASSES
846
+ ),
726
847
  placeholder: "Search...",
727
848
  value: searchQuery,
728
849
  onChange: handleSearchChange,
@@ -730,19 +851,19 @@ function Select({
730
851
  "aria-label": "Search options"
731
852
  }
732
853
  )),
733
- /* @__PURE__ */ React7__namespace.createElement("div", { className: "max-h-64 overflow-y-auto p-1" }, filteredOptions.length === 0 ? /* @__PURE__ */ React7__namespace.createElement("div", { className: "py-2 px-3 text-center text-sm " }, "No options found") : optionGroups.length > 0 ? (
854
+ /* @__PURE__ */ React8__namespace.createElement("div", { className: "max-h-64 overflow-y-auto p-1" }, filteredOptions.length === 0 ? /* @__PURE__ */ React8__namespace.createElement("div", { className: "py-2 px-3 text-center text-sm " }, "No options found") : optionGroups.length > 0 ? (
734
855
  // Render grouped options
735
856
  optionGroups.map((group, groupIndex) => {
736
857
  const groupOptions = group.options.filter(
737
858
  (opt) => filteredOptions.includes(opt)
738
859
  );
739
860
  if (groupOptions.length === 0) return null;
740
- return /* @__PURE__ */ React7__namespace.createElement("div", { key: groupIndex, className: "py-1" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "py-1.5 px-2 text-xs font-semibold " }, group.label), groupOptions.map((option) => {
861
+ return /* @__PURE__ */ React8__namespace.createElement("div", { key: groupIndex, className: "py-1" }, /* @__PURE__ */ React8__namespace.createElement("div", { className: "py-1.5 px-2 text-xs font-semibold " }, group.label), groupOptions.map((option) => {
741
862
  const globalIndex = filteredOptions.indexOf(option);
742
863
  const isSelected = value === option.value;
743
864
  const isFocused = globalIndex === focusedIndex;
744
865
  const isDisabled = option.disabled;
745
- return /* @__PURE__ */ React7__namespace.createElement(
866
+ return /* @__PURE__ */ React8__namespace.createElement(
746
867
  "div",
747
868
  {
748
869
  key: option.value,
@@ -762,7 +883,7 @@ function Select({
762
883
  const isSelected = value === option.value;
763
884
  const isFocused = index === focusedIndex;
764
885
  const isDisabled = option.disabled;
765
- return /* @__PURE__ */ React7__namespace.createElement(
886
+ return /* @__PURE__ */ React8__namespace.createElement(
766
887
  "div",
767
888
  {
768
889
  key: option.value,
@@ -805,14 +926,14 @@ function FileInput({
805
926
  onFileRemove,
806
927
  ...props
807
928
  }) {
808
- const inputRef = React7__namespace.useRef(null);
809
- const [dragActive, setDragActive] = React7__namespace.useState(false);
810
- const [cropperOpen, setCropperOpen] = React7__namespace.useState(false);
811
- const [imageToCrop, setImageToCrop] = React7__namespace.useState(null);
812
- const [crop, setCrop] = React7__namespace.useState({ x: 0, y: 0 });
813
- const [zoom, setZoom] = React7__namespace.useState(1);
814
- const [croppedAreaPixels, setCroppedAreaPixels] = React7__namespace.useState(null);
815
- const validateFile = React7__namespace.useCallback(
929
+ const inputRef = React8__namespace.useRef(null);
930
+ const [dragActive, setDragActive] = React8__namespace.useState(false);
931
+ const [cropperOpen, setCropperOpen] = React8__namespace.useState(false);
932
+ const [imageToCrop, setImageToCrop] = React8__namespace.useState(null);
933
+ const [crop, setCrop] = React8__namespace.useState({ x: 0, y: 0 });
934
+ const [zoom, setZoom] = React8__namespace.useState(1);
935
+ const [croppedAreaPixels, setCroppedAreaPixels] = React8__namespace.useState(null);
936
+ const validateFile = React8__namespace.useCallback(
816
937
  (file) => {
817
938
  if (accept) {
818
939
  const acceptedTypes = accept.split(",").map((t) => t.trim());
@@ -847,7 +968,7 @@ function FileInput({
847
968
  },
848
969
  [accept, maxSize]
849
970
  );
850
- const handleFiles = React7__namespace.useCallback(
971
+ const handleFiles = React8__namespace.useCallback(
851
972
  (fileList) => {
852
973
  if (!fileList || fileList.length === 0) return;
853
974
  const newFiles = Array.from(fileList);
@@ -898,7 +1019,7 @@ function FileInput({
898
1019
  onValidationError
899
1020
  ]
900
1021
  );
901
- const createCroppedImage = React7__namespace.useCallback(
1022
+ const createCroppedImage = React8__namespace.useCallback(
902
1023
  async (imageUrl, cropArea) => {
903
1024
  return new Promise((resolve, reject) => {
904
1025
  const image = new Image();
@@ -942,7 +1063,7 @@ function FileInput({
942
1063
  },
943
1064
  []
944
1065
  );
945
- const handleCropSave = React7__namespace.useCallback(async () => {
1066
+ const handleCropSave = React8__namespace.useCallback(async () => {
946
1067
  if (!imageToCrop || !croppedAreaPixels) return;
947
1068
  try {
948
1069
  const croppedBlob = await createCroppedImage(
@@ -975,7 +1096,7 @@ function FileInput({
975
1096
  onChange,
976
1097
  multiple
977
1098
  ]);
978
- const handleCropCancel = React7__namespace.useCallback(() => {
1099
+ const handleCropCancel = React8__namespace.useCallback(() => {
979
1100
  if (imageToCrop) {
980
1101
  URL.revokeObjectURL(imageToCrop.url);
981
1102
  }
@@ -985,13 +1106,13 @@ function FileInput({
985
1106
  setZoom(1);
986
1107
  setCroppedAreaPixels(null);
987
1108
  }, [imageToCrop]);
988
- const onCropChange = React7__namespace.useCallback((crop2) => {
1109
+ const onCropChange = React8__namespace.useCallback((crop2) => {
989
1110
  setCrop(crop2);
990
1111
  }, []);
991
- const onZoomChange = React7__namespace.useCallback((zoom2) => {
1112
+ const onZoomChange = React8__namespace.useCallback((zoom2) => {
992
1113
  setZoom(zoom2);
993
1114
  }, []);
994
- const onCropCompleteInternal = React7__namespace.useCallback(
1115
+ const onCropCompleteInternal = React8__namespace.useCallback(
995
1116
  (_, croppedAreaPixels2) => {
996
1117
  setCroppedAreaPixels(croppedAreaPixels2);
997
1118
  },
@@ -1052,7 +1173,7 @@ function FileInput({
1052
1173
  }
1053
1174
  return null;
1054
1175
  };
1055
- React7__namespace.useEffect(() => {
1176
+ React8__namespace.useEffect(() => {
1056
1177
  return () => {
1057
1178
  value.forEach((file) => {
1058
1179
  const previewUrl = getPreviewUrl(file);
@@ -1066,7 +1187,7 @@ function FileInput({
1066
1187
  };
1067
1188
  }, [value, imageToCrop]);
1068
1189
  const combinedClassName = `${className}`.trim();
1069
- return /* @__PURE__ */ React7__namespace.createElement("div", { className: combinedClassName }, /* @__PURE__ */ React7__namespace.createElement(
1190
+ return /* @__PURE__ */ React8__namespace.createElement("div", { className: combinedClassName }, /* @__PURE__ */ React8__namespace.createElement(
1070
1191
  "input",
1071
1192
  {
1072
1193
  ref: inputRef,
@@ -1083,10 +1204,10 @@ function FileInput({
1083
1204
  "aria-required": required || props["aria-required"],
1084
1205
  style: { display: "none" }
1085
1206
  }
1086
- ), /* @__PURE__ */ React7__namespace.createElement(
1207
+ ), /* @__PURE__ */ React8__namespace.createElement(
1087
1208
  "div",
1088
1209
  {
1089
- 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" : ""}`,
1210
+ 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-destructive" : ""}`,
1090
1211
  onDragEnter: handleDrag,
1091
1212
  onDragLeave: handleDrag,
1092
1213
  onDragOver: handleDrag,
@@ -1098,7 +1219,7 @@ function FileInput({
1098
1219
  "aria-label": placeholder,
1099
1220
  "aria-disabled": disabled
1100
1221
  },
1101
- /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col items-center gap-2 text-center" }, /* @__PURE__ */ React7__namespace.createElement(
1222
+ /* @__PURE__ */ React8__namespace.createElement("div", { className: "flex flex-col items-center gap-2 text-center" }, /* @__PURE__ */ React8__namespace.createElement(
1102
1223
  "svg",
1103
1224
  {
1104
1225
  width: "48",
@@ -1111,19 +1232,19 @@ function FileInput({
1111
1232
  strokeLinejoin: "round",
1112
1233
  "aria-hidden": "true"
1113
1234
  },
1114
- /* @__PURE__ */ React7__namespace.createElement("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
1115
- /* @__PURE__ */ React7__namespace.createElement("polyline", { points: "17 8 12 3 7 8" }),
1116
- /* @__PURE__ */ React7__namespace.createElement("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
1117
- ), /* @__PURE__ */ React7__namespace.createElement("p", { className: "text-sm font-medium" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React7__namespace.createElement("p", { className: "text-xs" }, "Accepted: ", accept), maxSize && /* @__PURE__ */ React7__namespace.createElement("p", { className: "text-xs " }, "Max size: ", formatFileSize(maxSize)))
1118
- ), value.length > 0 && /* @__PURE__ */ React7__namespace.createElement("ul", { className: "flex flex-col gap-2 mt-4", role: "list" }, value.map((file, index) => {
1235
+ /* @__PURE__ */ React8__namespace.createElement("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
1236
+ /* @__PURE__ */ React8__namespace.createElement("polyline", { points: "17 8 12 3 7 8" }),
1237
+ /* @__PURE__ */ React8__namespace.createElement("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
1238
+ ), /* @__PURE__ */ React8__namespace.createElement("p", { className: "text-sm font-medium" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React8__namespace.createElement("p", { className: "text-xs" }, "Accepted: ", accept), maxSize && /* @__PURE__ */ React8__namespace.createElement("p", { className: "text-xs " }, "Max size: ", formatFileSize(maxSize)))
1239
+ ), value.length > 0 && /* @__PURE__ */ React8__namespace.createElement("ul", { className: "flex flex-col gap-2 mt-4", role: "list" }, value.map((file, index) => {
1119
1240
  const previewUrl = showPreview ? getPreviewUrl(file) : null;
1120
- return /* @__PURE__ */ React7__namespace.createElement(
1241
+ return /* @__PURE__ */ React8__namespace.createElement(
1121
1242
  "li",
1122
1243
  {
1123
1244
  key: `${file.name}-${index}`,
1124
1245
  className: "flex items-center gap-3 p-3 rounded-md border border-border bg-card text-card-foreground hover:bg-primary/50 transition-colors"
1125
1246
  },
1126
- previewUrl && /* @__PURE__ */ React7__namespace.createElement(
1247
+ previewUrl && /* @__PURE__ */ React8__namespace.createElement(
1127
1248
  "img",
1128
1249
  {
1129
1250
  src: previewUrl,
@@ -1133,7 +1254,7 @@ function FileInput({
1133
1254
  height: "48"
1134
1255
  }
1135
1256
  ),
1136
- /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-sm font-medium truncate" }, file.name), /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-xs" }, formatFileSize(file.size)), showProgress && uploadProgress[file.name] !== void 0 && /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center gap-2 mt-1" }, /* @__PURE__ */ React7__namespace.createElement(
1257
+ /* @__PURE__ */ React8__namespace.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React8__namespace.createElement("span", { className: "text-sm font-medium truncate" }, file.name), /* @__PURE__ */ React8__namespace.createElement("span", { className: "text-xs" }, formatFileSize(file.size)), showProgress && uploadProgress[file.name] !== void 0 && /* @__PURE__ */ React8__namespace.createElement("div", { className: "flex items-center gap-2 mt-1" }, /* @__PURE__ */ React8__namespace.createElement(
1137
1258
  "div",
1138
1259
  {
1139
1260
  className: "h-1.5 bg-muted rounded-full overflow-hidden flex-1",
@@ -1143,15 +1264,15 @@ function FileInput({
1143
1264
  "aria-valuemax": 100,
1144
1265
  "aria-label": `Upload progress: ${uploadProgress[file.name]}%`
1145
1266
  },
1146
- /* @__PURE__ */ React7__namespace.createElement(
1267
+ /* @__PURE__ */ React8__namespace.createElement(
1147
1268
  "div",
1148
1269
  {
1149
1270
  className: "h-full bg-primary transition-all",
1150
1271
  style: { width: `${uploadProgress[file.name]}%` }
1151
1272
  }
1152
1273
  )
1153
- ), /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-xs " }, uploadProgress[file.name], "%"))),
1154
- enableCropping && file.type.startsWith("image/") && /* @__PURE__ */ React7__namespace.createElement(
1274
+ ), /* @__PURE__ */ React8__namespace.createElement("span", { className: "text-xs " }, uploadProgress[file.name], "%"))),
1275
+ enableCropping && file.type.startsWith("image/") && /* @__PURE__ */ React8__namespace.createElement(
1155
1276
  "button",
1156
1277
  {
1157
1278
  type: "button",
@@ -1163,7 +1284,7 @@ function FileInput({
1163
1284
  className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
1164
1285
  "aria-label": `Crop ${file.name}`
1165
1286
  },
1166
- /* @__PURE__ */ React7__namespace.createElement(
1287
+ /* @__PURE__ */ React8__namespace.createElement(
1167
1288
  "svg",
1168
1289
  {
1169
1290
  width: "20",
@@ -1176,11 +1297,11 @@ function FileInput({
1176
1297
  strokeLinejoin: "round",
1177
1298
  "aria-hidden": "true"
1178
1299
  },
1179
- /* @__PURE__ */ React7__namespace.createElement("path", { d: "M6.13 1L6 16a2 2 0 0 0 2 2h15" }),
1180
- /* @__PURE__ */ React7__namespace.createElement("path", { d: "M1 6.13L16 6a2 2 0 0 1 2 2v15" })
1300
+ /* @__PURE__ */ React8__namespace.createElement("path", { d: "M6.13 1L6 16a2 2 0 0 0 2 2h15" }),
1301
+ /* @__PURE__ */ React8__namespace.createElement("path", { d: "M1 6.13L16 6a2 2 0 0 1 2 2v15" })
1181
1302
  )
1182
1303
  ),
1183
- /* @__PURE__ */ React7__namespace.createElement(
1304
+ /* @__PURE__ */ React8__namespace.createElement(
1184
1305
  "button",
1185
1306
  {
1186
1307
  type: "button",
@@ -1192,7 +1313,7 @@ function FileInput({
1192
1313
  className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
1193
1314
  "aria-label": `Remove ${file.name}`
1194
1315
  },
1195
- /* @__PURE__ */ React7__namespace.createElement(
1316
+ /* @__PURE__ */ React8__namespace.createElement(
1196
1317
  "svg",
1197
1318
  {
1198
1319
  width: "20",
@@ -1205,19 +1326,19 @@ function FileInput({
1205
1326
  strokeLinejoin: "round",
1206
1327
  "aria-hidden": "true"
1207
1328
  },
1208
- /* @__PURE__ */ React7__namespace.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1209
- /* @__PURE__ */ React7__namespace.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1329
+ /* @__PURE__ */ React8__namespace.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1330
+ /* @__PURE__ */ React8__namespace.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1210
1331
  )
1211
1332
  )
1212
1333
  );
1213
- })), cropperOpen && imageToCrop && /* @__PURE__ */ React7__namespace.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center" }, /* @__PURE__ */ React7__namespace.createElement(
1334
+ })), cropperOpen && imageToCrop && /* @__PURE__ */ React8__namespace.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center" }, /* @__PURE__ */ React8__namespace.createElement(
1214
1335
  "div",
1215
1336
  {
1216
1337
  className: "absolute inset-0 bg-black/50",
1217
1338
  onClick: handleCropCancel,
1218
1339
  "aria-label": "Close cropper"
1219
1340
  }
1220
- ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative bg-popover border border-border rounded-lg shadow-lg max-w-3xl w-full mx-4" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center justify-between p-4 border-b border-border" }, /* @__PURE__ */ React7__namespace.createElement("h3", { className: "text-lg font-semibold" }, "Crop Image"), /* @__PURE__ */ React7__namespace.createElement(
1341
+ ), /* @__PURE__ */ React8__namespace.createElement("div", { className: "relative bg-popover border border-border rounded-lg shadow-lg max-w-3xl w-full mx-4" }, /* @__PURE__ */ React8__namespace.createElement("div", { className: "flex items-center justify-between p-4 border-b border-border" }, /* @__PURE__ */ React8__namespace.createElement("h3", { className: "text-lg font-semibold" }, "Crop Image"), /* @__PURE__ */ React8__namespace.createElement(
1221
1342
  "button",
1222
1343
  {
1223
1344
  type: "button",
@@ -1226,7 +1347,7 @@ function FileInput({
1226
1347
  "aria-label": "Close"
1227
1348
  },
1228
1349
  "\u2715"
1229
- )), /* @__PURE__ */ React7__namespace.createElement("div", { className: "p-4" }, /* @__PURE__ */ React7__namespace.createElement(
1350
+ )), /* @__PURE__ */ React8__namespace.createElement("div", { className: "p-4" }, /* @__PURE__ */ React8__namespace.createElement(
1230
1351
  "div",
1231
1352
  {
1232
1353
  className: "relative w-full h-96 bg-muted rounded-md overflow-hidden",
@@ -1248,7 +1369,7 @@ function FileInput({
1248
1369
  document.addEventListener("mouseup", handleMouseUp);
1249
1370
  }
1250
1371
  },
1251
- /* @__PURE__ */ React7__namespace.createElement(
1372
+ /* @__PURE__ */ React8__namespace.createElement(
1252
1373
  "img",
1253
1374
  {
1254
1375
  src: imageToCrop.url,
@@ -1283,7 +1404,7 @@ function FileInput({
1283
1404
  }
1284
1405
  }
1285
1406
  ),
1286
- /* @__PURE__ */ React7__namespace.createElement(
1407
+ /* @__PURE__ */ React8__namespace.createElement(
1287
1408
  "div",
1288
1409
  {
1289
1410
  className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 border-2 border-primary rounded pointer-events-none",
@@ -1292,9 +1413,9 @@ function FileInput({
1292
1413
  aspectRatio: cropAspectRatio ? String(cropAspectRatio) : void 0
1293
1414
  }
1294
1415
  },
1295
- /* @__PURE__ */ React7__namespace.createElement("div", { className: "absolute inset-0 grid grid-cols-3 grid-rows-3" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", null))
1416
+ /* @__PURE__ */ React8__namespace.createElement("div", { className: "absolute inset-0 grid grid-cols-3 grid-rows-3" }, /* @__PURE__ */ React8__namespace.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React8__namespace.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React8__namespace.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React8__namespace.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React8__namespace.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React8__namespace.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React8__namespace.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React8__namespace.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React8__namespace.createElement("div", null))
1296
1417
  )
1297
- ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center gap-3 mt-4" }, /* @__PURE__ */ React7__namespace.createElement(
1418
+ ), /* @__PURE__ */ React8__namespace.createElement("div", { className: "flex items-center gap-3 mt-4" }, /* @__PURE__ */ React8__namespace.createElement(
1298
1419
  "label",
1299
1420
  {
1300
1421
  htmlFor: "zoom-slider",
@@ -1303,7 +1424,7 @@ function FileInput({
1303
1424
  "Zoom: ",
1304
1425
  zoom.toFixed(1),
1305
1426
  "x"
1306
- ), /* @__PURE__ */ React7__namespace.createElement(
1427
+ ), /* @__PURE__ */ React8__namespace.createElement(
1307
1428
  "input",
1308
1429
  {
1309
1430
  id: "zoom-slider",
@@ -1316,7 +1437,7 @@ function FileInput({
1316
1437
  className: "flex-1 h-2 bg-muted rounded-lg appearance-none cursor-pointer",
1317
1438
  "aria-label": "Zoom level"
1318
1439
  }
1319
- ))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center justify-end gap-2 p-4 border-t border-border" }, /* @__PURE__ */ React7__namespace.createElement(
1440
+ ))), /* @__PURE__ */ React8__namespace.createElement("div", { className: "flex items-center justify-end gap-2 p-4 border-t border-border" }, /* @__PURE__ */ React8__namespace.createElement(
1320
1441
  "button",
1321
1442
  {
1322
1443
  type: "button",
@@ -1324,7 +1445,7 @@ function FileInput({
1324
1445
  onClick: handleCropCancel
1325
1446
  },
1326
1447
  "Cancel"
1327
- ), /* @__PURE__ */ React7__namespace.createElement(
1448
+ ), /* @__PURE__ */ React8__namespace.createElement(
1328
1449
  "button",
1329
1450
  {
1330
1451
  type: "button",
@@ -1343,27 +1464,6 @@ function formatDate(date, format) {
1343
1464
  const year = d.getFullYear();
1344
1465
  return format.replace("MM", month).replace("dd", day).replace("yyyy", String(year)).replace("yy", String(year).slice(2));
1345
1466
  }
1346
- function parseDate(dateString, format) {
1347
- if (!dateString) return null;
1348
- try {
1349
- if (format === "MM/dd/yyyy" || format === "MM-dd-yyyy") {
1350
- const parts = dateString.split(/[/-]/);
1351
- if (parts.length === 3) {
1352
- const month = parseInt(parts[0], 10) - 1;
1353
- const day = parseInt(parts[1], 10);
1354
- const year = parseInt(parts[2], 10);
1355
- const date2 = new Date(year, month, day);
1356
- if (!isNaN(date2.getTime())) {
1357
- return date2;
1358
- }
1359
- }
1360
- }
1361
- const date = new Date(dateString);
1362
- return isNaN(date.getTime()) ? null : date;
1363
- } catch {
1364
- return null;
1365
- }
1366
- }
1367
1467
  function isDateInArray(date, dates) {
1368
1468
  const dateStr = date.toDateString();
1369
1469
  return dates.some((d) => d.toDateString() === dateStr);
@@ -1387,43 +1487,30 @@ function DatePicker({
1387
1487
  showIcon = true,
1388
1488
  ...props
1389
1489
  }) {
1390
- const [isOpen, setIsOpen] = React7__namespace.useState(false);
1391
- const [inputValue, setInputValue] = React7__namespace.useState("");
1392
- const [selectedMonth, setSelectedMonth] = React7__namespace.useState(
1490
+ const [isOpen, setIsOpen] = React8__namespace.useState(false);
1491
+ const [selectedMonth, setSelectedMonth] = React8__namespace.useState(
1393
1492
  value || /* @__PURE__ */ new Date()
1394
1493
  );
1395
- const containerRef = React7__namespace.useRef(null);
1396
- const inputRef = React7__namespace.useRef(null);
1397
- React7__namespace.useEffect(() => {
1398
- setInputValue(formatDate(value, format));
1494
+ const containerRef = React8__namespace.useRef(null);
1495
+ const inputRef = React8__namespace.useRef(null);
1496
+ React8__namespace.useEffect(() => {
1399
1497
  if (value) {
1400
1498
  setSelectedMonth(value);
1401
1499
  }
1402
- }, [value, format]);
1500
+ }, [value]);
1403
1501
  const handleDateSelect = (date) => {
1404
1502
  onChange(date);
1405
1503
  setIsOpen(false);
1406
1504
  onBlur?.();
1407
1505
  };
1408
- const handleInputChange = (e) => {
1409
- const newValue = e.target.value;
1410
- setInputValue(newValue);
1411
- const parsedDate = parseDate(newValue, format);
1412
- if (parsedDate && !isNaN(parsedDate.getTime())) {
1413
- onChange(parsedDate);
1414
- } else if (newValue === "") {
1415
- onChange(null);
1416
- }
1417
- };
1418
1506
  const handleClear = (e) => {
1419
1507
  e.stopPropagation();
1420
1508
  onChange(null);
1421
- setInputValue("");
1422
1509
  inputRef.current?.focus();
1423
1510
  };
1424
1511
  const handleToggle = () => {
1425
1512
  if (disabled) return;
1426
- setIsOpen(!isOpen);
1513
+ setIsOpen((prev) => !prev);
1427
1514
  };
1428
1515
  const isDisabled = (date) => {
1429
1516
  if (minDate && date < minDate) return true;
@@ -1432,20 +1519,17 @@ function DatePicker({
1432
1519
  if (isDateDisabled && isDateDisabled(date)) return true;
1433
1520
  return false;
1434
1521
  };
1435
- React7__namespace.useEffect(() => {
1436
- const handleClickOutside = (event) => {
1437
- if (containerRef.current && !containerRef.current.contains(event.target)) {
1438
- setIsOpen(false);
1439
- onBlur?.();
1440
- }
1441
- };
1442
- if (isOpen) {
1443
- document.addEventListener("mousedown", handleClickOutside);
1444
- return () => {
1445
- document.removeEventListener("mousedown", handleClickOutside);
1446
- };
1447
- }
1522
+ const closeCalendar = React8__namespace.useCallback(() => {
1523
+ if (!isOpen) return;
1524
+ setIsOpen(false);
1525
+ onBlur?.();
1448
1526
  }, [isOpen, onBlur]);
1527
+ useOnClickOutside.useOnClickOutside(containerRef, closeCalendar, "pointerdown", true);
1528
+ const dayGridStyle = {
1529
+ gridTemplateColumns: "repeat(7, minmax(0, 1fr))"
1530
+ };
1531
+ const hasValue = Boolean(value);
1532
+ const displayValue = formatDate(value, format);
1449
1533
  const renderCalendar = () => {
1450
1534
  const year = selectedMonth.getFullYear();
1451
1535
  const month = selectedMonth.getMonth();
@@ -1478,44 +1562,57 @@ function DatePicker({
1478
1562
  const handleNextMonth = () => {
1479
1563
  setSelectedMonth(new Date(year, month + 1, 1));
1480
1564
  };
1481
- return /* @__PURE__ */ React7__namespace.createElement("div", { role: "grid", "aria-label": "Calendar" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center justify-between pb-2 border-b border-border" }, /* @__PURE__ */ React7__namespace.createElement(
1565
+ return /* @__PURE__ */ React8__namespace.createElement("div", { role: "grid", "aria-label": "Calendar", className: "w-[248px] max-w-full" }, /* @__PURE__ */ React8__namespace.createElement("div", { className: "flex items-center justify-between pb-3" }, /* @__PURE__ */ React8__namespace.createElement(
1482
1566
  "button",
1483
1567
  {
1484
1568
  type: "button",
1485
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
1569
+ className: "flex items-center justify-center h-8 w-8 rounded-md border-none bg-transparent hover:bg-muted cursor-pointer transition-colors",
1486
1570
  onClick: handlePrevMonth,
1487
1571
  "aria-label": "Previous month"
1488
1572
  },
1489
- "\u2190"
1490
- ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "font-medium text-sm" }, `${monthNames[month]} ${year}`), /* @__PURE__ */ React7__namespace.createElement(
1573
+ "\u2039"
1574
+ ), /* @__PURE__ */ React8__namespace.createElement("div", { className: "font-medium text-sm" }, `${monthNames[month]} ${year}`), /* @__PURE__ */ React8__namespace.createElement(
1491
1575
  "button",
1492
1576
  {
1493
1577
  type: "button",
1494
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
1578
+ className: "flex items-center justify-center h-8 w-8 rounded-md border-none bg-transparent hover:bg-muted cursor-pointer transition-colors",
1495
1579
  onClick: handleNextMonth,
1496
1580
  "aria-label": "Next month"
1497
1581
  },
1498
- "\u2192"
1499
- )), /* @__PURE__ */ React7__namespace.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7__namespace.createElement(
1582
+ "\u203A"
1583
+ )), /* @__PURE__ */ React8__namespace.createElement(
1500
1584
  "div",
1501
1585
  {
1502
- key: day,
1503
- className: "flex items-center justify-center h-8 w-full text-xs font-medium"
1586
+ className: "grid gap-1 text-xs text-muted-foreground",
1587
+ style: dayGridStyle
1504
1588
  },
1505
- day
1506
- ))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
1589
+ ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React8__namespace.createElement(
1590
+ "div",
1591
+ {
1592
+ key: day,
1593
+ className: "flex items-center justify-center h-8 w-8 font-medium"
1594
+ },
1595
+ day
1596
+ ))
1597
+ ), /* @__PURE__ */ React8__namespace.createElement("div", { className: "grid gap-1", style: dayGridStyle }, days.map((date, index) => {
1507
1598
  if (!date) {
1508
- return /* @__PURE__ */ React7__namespace.createElement("div", { key: `empty-${index}` });
1599
+ return /* @__PURE__ */ React8__namespace.createElement("div", { key: `empty-${index}`, className: "h-8 w-8" });
1509
1600
  }
1510
1601
  const isSelected = value && date.toDateString() === value.toDateString();
1511
1602
  const isToday = date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
1512
1603
  const disabled2 = isDisabled(date);
1513
- return /* @__PURE__ */ React7__namespace.createElement(
1604
+ return /* @__PURE__ */ React8__namespace.createElement(
1514
1605
  "button",
1515
1606
  {
1516
1607
  key: date.toISOString(),
1517
1608
  type: "button",
1518
- 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" : ""}`,
1609
+ className: cn(
1610
+ "flex items-center justify-center h-8 w-8 rounded-md border-none bg-transparent cursor-pointer text-sm transition-colors",
1611
+ "hover:bg-muted",
1612
+ isSelected && "bg-primary text-primary-foreground font-semibold",
1613
+ !isSelected && isToday && "border border-primary",
1614
+ disabled2 && "cursor-not-allowed opacity-50 pointer-events-none"
1615
+ ),
1519
1616
  onClick: () => !disabled2 && handleDateSelect(date),
1520
1617
  disabled: disabled2,
1521
1618
  "aria-label": formatDate(date, format)
@@ -1524,21 +1621,21 @@ function DatePicker({
1524
1621
  );
1525
1622
  })));
1526
1623
  };
1527
- const combinedClassName = `relative ${className}`.trim();
1528
- return /* @__PURE__ */ React7__namespace.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7__namespace.createElement(
1624
+ const combinedClassName = cn("relative", className);
1625
+ return /* @__PURE__ */ React8__namespace.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React8__namespace.createElement(
1529
1626
  "input",
1530
1627
  {
1531
1628
  type: "hidden",
1532
1629
  name,
1533
1630
  value: value ? value.toISOString() : ""
1534
1631
  }
1535
- ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7__namespace.createElement(
1632
+ ), /* @__PURE__ */ React8__namespace.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React8__namespace.createElement(
1536
1633
  "span",
1537
1634
  {
1538
1635
  className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
1539
1636
  "aria-hidden": "true"
1540
1637
  },
1541
- /* @__PURE__ */ React7__namespace.createElement(
1638
+ /* @__PURE__ */ React8__namespace.createElement(
1542
1639
  "svg",
1543
1640
  {
1544
1641
  xmlns: "http://www.w3.org/2000/svg",
@@ -1551,16 +1648,24 @@ function DatePicker({
1551
1648
  strokeLinejoin: "round",
1552
1649
  strokeWidth: "2"
1553
1650
  },
1554
- /* @__PURE__ */ React7__namespace.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" })
1651
+ /* @__PURE__ */ React8__namespace.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" })
1555
1652
  )
1556
- ), /* @__PURE__ */ React7__namespace.createElement(
1653
+ ), /* @__PURE__ */ React8__namespace.createElement(
1557
1654
  "input",
1558
1655
  {
1559
1656
  ref: inputRef,
1560
1657
  type: "text",
1561
- 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" : ""}`,
1562
- value: inputValue,
1563
- onChange: handleInputChange,
1658
+ className: cn(
1659
+ "flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
1660
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
1661
+ "disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1662
+ INPUT_AUTOFILL_RESET_CLASSES,
1663
+ showIcon ? "pl-10" : "pl-3",
1664
+ clearable && value ? "pr-10" : "pr-3",
1665
+ !error && hasValue && "ring-2 ring-ring",
1666
+ error && "border-destructive ring-1 ring-destructive"
1667
+ ),
1668
+ value: displayValue,
1564
1669
  onClick: handleToggle,
1565
1670
  onBlur,
1566
1671
  disabled,
@@ -1571,7 +1676,7 @@ function DatePicker({
1571
1676
  "aria-required": required || props["aria-required"],
1572
1677
  readOnly: true
1573
1678
  }
1574
- ), clearable && value && !disabled && /* @__PURE__ */ React7__namespace.createElement(
1679
+ ), clearable && value && !disabled && /* @__PURE__ */ React8__namespace.createElement(
1575
1680
  "button",
1576
1681
  {
1577
1682
  type: "button",
@@ -1581,49 +1686,49 @@ function DatePicker({
1581
1686
  tabIndex: -1
1582
1687
  },
1583
1688
  "\u2715"
1584
- )), isOpen && !disabled && /* @__PURE__ */ React7__namespace.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()));
1689
+ )), isOpen && !disabled && /* @__PURE__ */ React8__namespace.createElement("div", { className: "absolute z-50 top-full mt-1 w-fit rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, renderCalendar()));
1585
1690
  }
1586
1691
  DatePicker.displayName = "DatePicker";
1587
- function parseTimeString(timeStr, use24Hour) {
1588
- if (!timeStr) return null;
1589
- try {
1590
- if (use24Hour) {
1591
- const [hourStr, minuteStr] = timeStr.split(":");
1592
- const hour24 = parseInt(hourStr, 10);
1593
- const minute = parseInt(minuteStr, 10);
1594
- if (isNaN(hour24) || isNaN(minute)) return null;
1595
- if (hour24 < 0 || hour24 > 23) return null;
1596
- if (minute < 0 || minute > 59) return null;
1597
- const period = hour24 >= 12 ? "PM" : "AM";
1598
- const hour = hour24 === 0 ? 12 : hour24 > 12 ? hour24 - 12 : hour24;
1599
- return { hour, minute, period };
1600
- } else {
1601
- const match = timeStr.match(/^(\d{1,2}):(\d{2})\s*(AM|PM)$/i);
1602
- if (!match) return null;
1603
- const hour = parseInt(match[1], 10);
1604
- const minute = parseInt(match[2], 10);
1605
- const period = match[3].toUpperCase();
1606
- if (hour < 1 || hour > 12) return null;
1607
- if (minute < 0 || minute > 59) return null;
1608
- return { hour, minute, period };
1692
+ function normalizeToNativeTime(value) {
1693
+ if (!value) return "";
1694
+ const twelveHourMatch = value.match(
1695
+ /^(\d{1,2}):(\d{2})(?::(\d{2}))?\s*(AM|PM)$/i
1696
+ );
1697
+ if (twelveHourMatch) {
1698
+ const rawHour = parseInt(twelveHourMatch[1], 10);
1699
+ const minute = parseInt(twelveHourMatch[2], 10);
1700
+ const period = twelveHourMatch[4].toUpperCase();
1701
+ if (Number.isNaN(rawHour) || Number.isNaN(minute) || rawHour < 1 || rawHour > 12 || minute < 0 || minute > 59) {
1702
+ return "";
1609
1703
  }
1610
- } catch {
1611
- return null;
1704
+ const normalizedHour = period === "PM" ? rawHour === 12 ? 12 : rawHour + 12 : rawHour === 12 ? 0 : rawHour;
1705
+ return `${String(normalizedHour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
1612
1706
  }
1707
+ const twentyFourHourMatch = value.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/);
1708
+ if (twentyFourHourMatch) {
1709
+ const hour = parseInt(twentyFourHourMatch[1], 10);
1710
+ const minute = parseInt(twentyFourHourMatch[2], 10);
1711
+ if (Number.isNaN(hour) || Number.isNaN(minute) || hour < 0 || hour > 23 || minute < 0 || minute > 59) {
1712
+ return "";
1713
+ }
1714
+ return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
1715
+ }
1716
+ return "";
1613
1717
  }
1614
- function formatTimeValue(time, use24Hour) {
1615
- if (!time) return "";
1718
+ function formatFromNativeTime(nativeValue, use24Hour) {
1719
+ if (!nativeValue) return "";
1720
+ const [hourValue, minuteValue] = nativeValue.split(":");
1721
+ const hour = parseInt(hourValue, 10);
1722
+ const minute = parseInt(minuteValue, 10);
1723
+ if (Number.isNaN(hour) || Number.isNaN(minute)) {
1724
+ return "";
1725
+ }
1616
1726
  if (use24Hour) {
1617
- let hour24 = time.hour;
1618
- if (time.period === "PM" && time.hour !== 12) {
1619
- hour24 = time.hour + 12;
1620
- } else if (time.period === "AM" && time.hour === 12) {
1621
- hour24 = 0;
1622
- }
1623
- return `${String(hour24).padStart(2, "0")}:${String(time.minute).padStart(2, "0")}`;
1624
- } else {
1625
- return `${time.hour}:${String(time.minute).padStart(2, "0")} ${time.period}`;
1727
+ return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
1626
1728
  }
1729
+ const period = hour >= 12 ? "PM" : "AM";
1730
+ const hour12 = hour % 12 || 12;
1731
+ return `${hour12}:${String(minute).padStart(2, "0")} ${period}`;
1627
1732
  }
1628
1733
  function TimePicker({
1629
1734
  name,
@@ -1641,88 +1746,33 @@ function TimePicker({
1641
1746
  showIcon = true,
1642
1747
  ...props
1643
1748
  }) {
1644
- const [isOpen, setIsOpen] = React7__namespace.useState(false);
1645
- const [timeValue, setTimeValue] = React7__namespace.useState(null);
1646
- const containerRef = React7__namespace.useRef(null);
1647
- const inputRef = React7__namespace.useRef(null);
1648
- React7__namespace.useEffect(() => {
1649
- const parsed = parseTimeString(value, use24Hour);
1650
- setTimeValue(parsed);
1651
- }, [value, use24Hour]);
1652
- const handleHourChange = (hour) => {
1653
- const newTime = {
1654
- hour,
1655
- minute: timeValue?.minute || 0,
1656
- period: timeValue?.period || "AM"
1657
- };
1658
- setTimeValue(newTime);
1659
- onChange(formatTimeValue(newTime, use24Hour));
1660
- };
1661
- const handleMinuteChange = (minute) => {
1662
- const newTime = {
1663
- hour: timeValue?.hour || 12,
1664
- minute,
1665
- period: timeValue?.period || "AM"
1666
- };
1667
- setTimeValue(newTime);
1668
- onChange(formatTimeValue(newTime, use24Hour));
1669
- };
1670
- const handlePeriodChange = (period) => {
1671
- const newTime = {
1672
- hour: timeValue?.hour || 12,
1673
- minute: timeValue?.minute || 0,
1674
- period
1675
- };
1676
- setTimeValue(newTime);
1677
- onChange(formatTimeValue(newTime, use24Hour));
1749
+ const inputRef = React8__namespace.useRef(null);
1750
+ const [nativeValue, setNativeValue] = React8__namespace.useState(
1751
+ normalizeToNativeTime(value)
1752
+ );
1753
+ React8__namespace.useEffect(() => {
1754
+ setNativeValue(normalizeToNativeTime(value));
1755
+ }, [value]);
1756
+ const handleChange = (e) => {
1757
+ const nextNativeValue = e.target.value;
1758
+ setNativeValue(nextNativeValue);
1759
+ onChange(formatFromNativeTime(nextNativeValue, use24Hour));
1678
1760
  };
1679
1761
  const handleClear = (e) => {
1680
1762
  e.stopPropagation();
1763
+ setNativeValue("");
1681
1764
  onChange("");
1682
- setTimeValue(null);
1683
1765
  inputRef.current?.focus();
1684
1766
  };
1685
- const handleToggle = () => {
1686
- if (disabled) return;
1687
- setIsOpen(!isOpen);
1688
- };
1689
- React7__namespace.useEffect(() => {
1690
- const handleClickOutside = (event) => {
1691
- if (containerRef.current && !containerRef.current.contains(event.target)) {
1692
- setIsOpen(false);
1693
- onBlur?.();
1694
- }
1695
- };
1696
- if (isOpen) {
1697
- document.addEventListener("mousedown", handleClickOutside);
1698
- return () => {
1699
- document.removeEventListener("mousedown", handleClickOutside);
1700
- };
1701
- }
1702
- }, [isOpen, onBlur]);
1703
- const hours = React7__namespace.useMemo(() => {
1704
- if (use24Hour) {
1705
- return Array.from({ length: 24 }, (_, i) => i);
1706
- } else {
1707
- return Array.from({ length: 12 }, (_, i) => i + 1);
1708
- }
1709
- }, [use24Hour]);
1710
- const minutes = React7__namespace.useMemo(() => {
1711
- const mins = [];
1712
- for (let i = 0; i < 60; i += minuteStep) {
1713
- mins.push(i);
1714
- }
1715
- return mins;
1716
- }, [minuteStep]);
1717
- const combinedClassName = cn("relative", className);
1718
- const displayValue = formatTimeValue(timeValue, use24Hour);
1719
- return /* @__PURE__ */ React7__namespace.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7__namespace.createElement("input", { type: "hidden", name, value }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7__namespace.createElement(
1767
+ const hasValue = Boolean(value);
1768
+ const stepInSeconds = Math.max(1, minuteStep * 60);
1769
+ return /* @__PURE__ */ React8__namespace.createElement("div", { className: cn("relative", className) }, /* @__PURE__ */ React8__namespace.createElement("input", { type: "hidden", name, value }), /* @__PURE__ */ React8__namespace.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React8__namespace.createElement(
1720
1770
  "span",
1721
1771
  {
1722
1772
  className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
1723
1773
  "aria-hidden": "true"
1724
1774
  },
1725
- /* @__PURE__ */ React7__namespace.createElement(
1775
+ /* @__PURE__ */ React8__namespace.createElement(
1726
1776
  "svg",
1727
1777
  {
1728
1778
  xmlns: "http://www.w3.org/2000/svg",
@@ -1735,34 +1785,38 @@ function TimePicker({
1735
1785
  strokeLinejoin: "round",
1736
1786
  strokeWidth: "2"
1737
1787
  },
1738
- /* @__PURE__ */ React7__namespace.createElement("circle", { cx: "12", cy: "12", r: "10" }),
1739
- /* @__PURE__ */ React7__namespace.createElement("path", { d: "M12 6v6l4 2" })
1788
+ /* @__PURE__ */ React8__namespace.createElement("circle", { cx: "12", cy: "12", r: "10" }),
1789
+ /* @__PURE__ */ React8__namespace.createElement("path", { d: "M12 6v6l4 2" })
1740
1790
  )
1741
- ), /* @__PURE__ */ React7__namespace.createElement(
1791
+ ), /* @__PURE__ */ React8__namespace.createElement(
1742
1792
  "input",
1743
1793
  {
1744
1794
  ref: inputRef,
1745
- type: "text",
1795
+ type: "time",
1746
1796
  className: cn(
1747
1797
  "flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
1748
1798
  "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
1749
1799
  "disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1800
+ "appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none",
1801
+ INPUT_AUTOFILL_RESET_CLASSES,
1750
1802
  showIcon ? "pl-10" : "pl-3",
1751
1803
  clearable && value ? "pr-10" : "pr-3",
1752
- error && "border-red-500 ring-1 ring-red-500"
1804
+ !error && hasValue && "ring-2 ring-ring",
1805
+ error && "border-destructive ring-1 ring-destructive"
1753
1806
  ),
1754
- value: displayValue,
1755
- onClick: handleToggle,
1807
+ value: nativeValue,
1808
+ onChange: handleChange,
1756
1809
  onBlur,
1757
1810
  disabled,
1758
1811
  required,
1812
+ step: stepInSeconds,
1759
1813
  placeholder,
1760
1814
  "aria-invalid": error || props["aria-invalid"] ? "true" : "false",
1761
1815
  "aria-describedby": props["aria-describedby"],
1762
1816
  "aria-required": required || props["aria-required"],
1763
- readOnly: true
1817
+ ...props
1764
1818
  }
1765
- ), clearable && value && !disabled && /* @__PURE__ */ React7__namespace.createElement(
1819
+ ), clearable && value && !disabled && /* @__PURE__ */ React8__namespace.createElement(
1766
1820
  "button",
1767
1821
  {
1768
1822
  type: "button",
@@ -1772,84 +1826,7 @@ function TimePicker({
1772
1826
  tabIndex: -1
1773
1827
  },
1774
1828
  "\u2715"
1775
- )), isOpen && !disabled && /* @__PURE__ */ React7__namespace.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__namespace.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, use24Hour ? "Hour" : "Hour"), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, hours.map((hour) => {
1776
- const displayHour = use24Hour ? hour : hour;
1777
- const isSelected = use24Hour ? timeValue?.hour === (hour === 0 ? 12 : hour > 12 ? hour - 12 : hour) && timeValue?.period === (hour >= 12 ? "PM" : "AM") : timeValue?.hour === hour;
1778
- return /* @__PURE__ */ React7__namespace.createElement(
1779
- "button",
1780
- {
1781
- key: hour,
1782
- type: "button",
1783
- className: cn(
1784
- "flex items-center justify-center h-8 w-full rounded",
1785
- "border-none bg-transparent cursor-pointer text-sm transition-colors",
1786
- "hover:bg-primary hover:text-primary-foreground",
1787
- isSelected ? "bg-primary text-primary-foreground font-semibold" : ""
1788
- ),
1789
- onClick: () => {
1790
- if (use24Hour) {
1791
- const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
1792
- const period = hour >= 12 ? "PM" : "AM";
1793
- const newTime = {
1794
- hour: hour12,
1795
- minute: timeValue?.minute || 0,
1796
- period
1797
- };
1798
- setTimeValue(newTime);
1799
- onChange(formatTimeValue(newTime, use24Hour));
1800
- } else {
1801
- handleHourChange(hour);
1802
- }
1803
- },
1804
- "aria-label": `${String(displayHour).padStart(2, "0")} hours`
1805
- },
1806
- String(displayHour).padStart(2, "0")
1807
- );
1808
- }))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, "Minute"), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, minutes.map((minute) => {
1809
- const isSelected = timeValue?.minute === minute;
1810
- return /* @__PURE__ */ React7__namespace.createElement(
1811
- "button",
1812
- {
1813
- key: minute,
1814
- type: "button",
1815
- className: cn(
1816
- "flex items-center justify-center h-8 w-full",
1817
- "rounded border-none bg-transparent cursor-pointer text-sm transition-colors",
1818
- "hover:bg-primary hover:text-primary-foreground",
1819
- isSelected ? "bg-primary text-primary-foreground font-semibold" : ""
1820
- ),
1821
- onClick: () => handleMinuteChange(minute),
1822
- "aria-label": `${String(minute).padStart(2, "0")} minutes`
1823
- },
1824
- String(minute).padStart(2, "0")
1825
- );
1826
- }))), !use24Hour && /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col w-20" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, "Period"), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React7__namespace.createElement(
1827
- "button",
1828
- {
1829
- type: "button",
1830
- className: cn(
1831
- "flex items-center justify-center h-8 w-full",
1832
- "rounded border-none bg-transparent cursor-pointer text-sm",
1833
- "transition-colors hover:bg-primary hover:text-primary-foreground",
1834
- timeValue?.period === "AM" ? "bg-muted font-semibold" : ""
1835
- ),
1836
- onClick: () => handlePeriodChange("AM")
1837
- },
1838
- "AM"
1839
- ), /* @__PURE__ */ React7__namespace.createElement(
1840
- "button",
1841
- {
1842
- type: "button",
1843
- className: cn(
1844
- "flex items-center justify-center h-8 w-full",
1845
- "rounded border-none bg-transparent cursor-pointer text-sm",
1846
- "transition-colors hover:bg-primary hover:text-primary-foreground",
1847
- timeValue?.period === "PM" ? "bg-muted font-semibold" : ""
1848
- ),
1849
- onClick: () => handlePeriodChange("PM")
1850
- },
1851
- "PM"
1852
- ))))));
1829
+ )));
1853
1830
  }
1854
1831
  TimePicker.displayName = "TimePicker";
1855
1832
  function formatDate2(date, format) {
@@ -1869,6 +1846,9 @@ function isDateInRange(date, start, end) {
1869
1846
  const time = date.getTime();
1870
1847
  return time >= start.getTime() && time <= end.getTime();
1871
1848
  }
1849
+ function addMonths(date, delta) {
1850
+ return new Date(date.getFullYear(), date.getMonth() + delta, 1);
1851
+ }
1872
1852
  function DateRangePicker({
1873
1853
  name,
1874
1854
  value = { start: null, end: null },
@@ -1889,15 +1869,15 @@ function DateRangePicker({
1889
1869
  separator = " - ",
1890
1870
  ...props
1891
1871
  }) {
1892
- const [isOpen, setIsOpen] = React7__namespace.useState(false);
1893
- const [selectedMonth, setSelectedMonth] = React7__namespace.useState(
1872
+ const [isOpen, setIsOpen] = React8__namespace.useState(false);
1873
+ const [selectedMonth, setSelectedMonth] = React8__namespace.useState(
1894
1874
  value.start || /* @__PURE__ */ new Date()
1895
1875
  );
1896
- const [rangeStart, setRangeStart] = React7__namespace.useState(value.start);
1897
- const [rangeEnd, setRangeEnd] = React7__namespace.useState(value.end);
1898
- const [hoverDate, setHoverDate] = React7__namespace.useState(null);
1899
- const containerRef = React7__namespace.useRef(null);
1900
- React7__namespace.useEffect(() => {
1876
+ const [rangeStart, setRangeStart] = React8__namespace.useState(value.start);
1877
+ const [rangeEnd, setRangeEnd] = React8__namespace.useState(value.end);
1878
+ const [hoverDate, setHoverDate] = React8__namespace.useState(null);
1879
+ const containerRef = React8__namespace.useRef(null);
1880
+ React8__namespace.useEffect(() => {
1901
1881
  setRangeStart(value.start);
1902
1882
  setRangeEnd(value.end);
1903
1883
  if (value.start) {
@@ -1931,7 +1911,7 @@ function DateRangePicker({
1931
1911
  };
1932
1912
  const handleToggle = () => {
1933
1913
  if (disabled) return;
1934
- setIsOpen(!isOpen);
1914
+ setIsOpen((prev) => !prev);
1935
1915
  };
1936
1916
  const isDisabled = (date) => {
1937
1917
  if (minDate && date < minDate) return true;
@@ -1940,23 +1920,36 @@ function DateRangePicker({
1940
1920
  if (isDateDisabled && isDateDisabled(date)) return true;
1941
1921
  return false;
1942
1922
  };
1943
- React7__namespace.useEffect(() => {
1944
- const handleClickOutside = (event) => {
1945
- if (containerRef.current && !containerRef.current.contains(event.target)) {
1946
- setIsOpen(false);
1947
- onBlur?.();
1948
- }
1949
- };
1950
- if (isOpen) {
1951
- document.addEventListener("mousedown", handleClickOutside);
1952
- return () => {
1953
- document.removeEventListener("mousedown", handleClickOutside);
1954
- };
1955
- }
1923
+ const closeCalendar = React8__namespace.useCallback(() => {
1924
+ if (!isOpen) return;
1925
+ setIsOpen(false);
1926
+ onBlur?.();
1956
1927
  }, [isOpen, onBlur]);
1957
- const renderCalendar = () => {
1958
- const year = selectedMonth.getFullYear();
1959
- const month = selectedMonth.getMonth();
1928
+ useOnClickOutside.useOnClickOutside(containerRef, closeCalendar, "pointerdown", true);
1929
+ const dayGridStyle = {
1930
+ gridTemplateColumns: "repeat(7, minmax(0, 1fr))"
1931
+ };
1932
+ const monthsGridStyle = {
1933
+ gridTemplateColumns: "repeat(auto-fit, minmax(240px, 1fr))"
1934
+ };
1935
+ const monthNames = [
1936
+ "January",
1937
+ "February",
1938
+ "March",
1939
+ "April",
1940
+ "May",
1941
+ "June",
1942
+ "July",
1943
+ "August",
1944
+ "September",
1945
+ "October",
1946
+ "November",
1947
+ "December"
1948
+ ];
1949
+ const hasValue = Boolean(rangeStart || rangeEnd);
1950
+ const renderMonth = (monthDate, controls) => {
1951
+ const year = monthDate.getFullYear();
1952
+ const month = monthDate.getMonth();
1960
1953
  const daysInMonth = new Date(year, month + 1, 0).getDate();
1961
1954
  const firstDayOfMonth = new Date(year, month, 1).getDay();
1962
1955
  const days = [];
@@ -1966,54 +1959,41 @@ function DateRangePicker({
1966
1959
  for (let day = 1; day <= daysInMonth; day++) {
1967
1960
  days.push(new Date(year, month, day));
1968
1961
  }
1969
- const monthNames = [
1970
- "January",
1971
- "February",
1972
- "March",
1973
- "April",
1974
- "May",
1975
- "June",
1976
- "July",
1977
- "August",
1978
- "September",
1979
- "October",
1980
- "November",
1981
- "December"
1982
- ];
1983
- const handlePrevMonth = () => {
1984
- setSelectedMonth(new Date(year, month - 1, 1));
1985
- };
1986
- const handleNextMonth = () => {
1987
- setSelectedMonth(new Date(year, month + 1, 1));
1988
- };
1989
- return /* @__PURE__ */ React7__namespace.createElement("div", { role: "grid", "aria-label": "Calendar" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center justify-between pb-2 border-b border-border" }, /* @__PURE__ */ React7__namespace.createElement(
1962
+ return /* @__PURE__ */ React8__namespace.createElement("div", { className: "w-[240px] max-w-full" }, /* @__PURE__ */ React8__namespace.createElement("div", { className: "flex items-center justify-between pb-3" }, controls?.prev ? /* @__PURE__ */ React8__namespace.createElement(
1990
1963
  "button",
1991
1964
  {
1992
1965
  type: "button",
1993
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
1994
- onClick: handlePrevMonth,
1966
+ className: "flex items-center justify-center h-8 w-8 rounded-md border-none bg-transparent hover:bg-muted cursor-pointer transition-colors",
1967
+ onClick: () => setSelectedMonth((prev) => addMonths(prev, -1)),
1995
1968
  "aria-label": "Previous month"
1996
1969
  },
1997
- "\u2190"
1998
- ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "font-medium text-sm" }, `${monthNames[month]} ${year}`), /* @__PURE__ */ React7__namespace.createElement(
1970
+ "\u2039"
1971
+ ) : /* @__PURE__ */ React8__namespace.createElement("div", { className: "h-8 w-8", "aria-hidden": "true" }), /* @__PURE__ */ React8__namespace.createElement("div", { className: "font-medium text-sm" }, `${monthNames[month]} ${year}`), controls?.next ? /* @__PURE__ */ React8__namespace.createElement(
1999
1972
  "button",
2000
1973
  {
2001
1974
  type: "button",
2002
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
2003
- onClick: handleNextMonth,
1975
+ className: "flex items-center justify-center h-8 w-8 rounded-md border-none bg-transparent hover:bg-muted cursor-pointer transition-colors",
1976
+ onClick: () => setSelectedMonth((prev) => addMonths(prev, 1)),
2004
1977
  "aria-label": "Next month"
2005
1978
  },
2006
- "\u2192"
2007
- )), /* @__PURE__ */ React7__namespace.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7__namespace.createElement(
1979
+ "\u203A"
1980
+ ) : /* @__PURE__ */ React8__namespace.createElement("div", { className: "h-8 w-8", "aria-hidden": "true" })), /* @__PURE__ */ React8__namespace.createElement(
2008
1981
  "div",
2009
1982
  {
2010
- key: day,
2011
- className: "flex items-center justify-center h-8 w-full text-xs font-medium"
1983
+ className: "grid gap-1 text-xs text-muted-foreground",
1984
+ style: dayGridStyle
2012
1985
  },
2013
- day
2014
- ))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
1986
+ ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React8__namespace.createElement(
1987
+ "div",
1988
+ {
1989
+ key: `${month}-${day}`,
1990
+ className: "flex items-center justify-center h-8 w-8 font-medium"
1991
+ },
1992
+ day
1993
+ ))
1994
+ ), /* @__PURE__ */ React8__namespace.createElement("div", { className: "grid gap-1", style: dayGridStyle }, days.map((date, index) => {
2015
1995
  if (!date) {
2016
- return /* @__PURE__ */ React7__namespace.createElement("div", { key: `empty-${index}` });
1996
+ return /* @__PURE__ */ React8__namespace.createElement("div", { key: `empty-${month}-${index}`, className: "h-8 w-8" });
2017
1997
  }
2018
1998
  const isStart = rangeStart && date.toDateString() === rangeStart.toDateString();
2019
1999
  const isEnd = rangeEnd && date.toDateString() === rangeEnd.toDateString();
@@ -2025,17 +2005,17 @@ function DateRangePicker({
2025
2005
  );
2026
2006
  const isToday = date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
2027
2007
  const disabled2 = isDisabled(date);
2028
- return /* @__PURE__ */ React7__namespace.createElement(
2008
+ return /* @__PURE__ */ React8__namespace.createElement(
2029
2009
  "button",
2030
2010
  {
2031
2011
  key: date.toISOString(),
2032
2012
  type: "button",
2033
2013
  className: cn(
2034
- "flex items-center justify-center h-8 w-full rounded border-none bg-transparent",
2035
- "cursor-pointer text-sm transition-colors hover:bg-muted",
2036
- isRangeEndpoint && "bg-muted font-semibold",
2037
- isRangeHighlight && "bg-muted/70",
2038
- isToday && "border border-primary",
2014
+ "flex items-center justify-center h-8 w-8 rounded-md border-none bg-transparent cursor-pointer text-sm transition-colors",
2015
+ "hover:bg-muted",
2016
+ isRangeEndpoint && "bg-primary text-primary-foreground font-semibold",
2017
+ isRangeHighlight && "bg-muted",
2018
+ !isRangeEndpoint && !isRangeHighlight && isToday && "border border-primary",
2039
2019
  disabled2 && "cursor-not-allowed opacity-50 pointer-events-none"
2040
2020
  ),
2041
2021
  onClick: () => !disabled2 && handleDateSelect(date),
@@ -2050,27 +2030,27 @@ function DateRangePicker({
2050
2030
  };
2051
2031
  const combinedClassName = cn("relative", className);
2052
2032
  const displayValue = rangeStart && rangeEnd ? `${formatDate2(rangeStart, format)}${separator}${formatDate2(rangeEnd, format)}` : rangeStart ? formatDate2(rangeStart, format) : "";
2053
- return /* @__PURE__ */ React7__namespace.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7__namespace.createElement(
2033
+ return /* @__PURE__ */ React8__namespace.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React8__namespace.createElement(
2054
2034
  "input",
2055
2035
  {
2056
2036
  type: "hidden",
2057
2037
  name: `${name}[start]`,
2058
2038
  value: rangeStart ? rangeStart.toISOString() : ""
2059
2039
  }
2060
- ), /* @__PURE__ */ React7__namespace.createElement(
2040
+ ), /* @__PURE__ */ React8__namespace.createElement(
2061
2041
  "input",
2062
2042
  {
2063
2043
  type: "hidden",
2064
2044
  name: `${name}[end]`,
2065
2045
  value: rangeEnd ? rangeEnd.toISOString() : ""
2066
2046
  }
2067
- ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7__namespace.createElement(
2047
+ ), /* @__PURE__ */ React8__namespace.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React8__namespace.createElement(
2068
2048
  "span",
2069
2049
  {
2070
2050
  className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
2071
2051
  "aria-hidden": "true"
2072
2052
  },
2073
- /* @__PURE__ */ React7__namespace.createElement(
2053
+ /* @__PURE__ */ React8__namespace.createElement(
2074
2054
  "svg",
2075
2055
  {
2076
2056
  xmlns: "http://www.w3.org/2000/svg",
@@ -2083,9 +2063,9 @@ function DateRangePicker({
2083
2063
  strokeLinejoin: "round",
2084
2064
  strokeWidth: "2"
2085
2065
  },
2086
- /* @__PURE__ */ React7__namespace.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" })
2066
+ /* @__PURE__ */ React8__namespace.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" })
2087
2067
  )
2088
- ), /* @__PURE__ */ React7__namespace.createElement(
2068
+ ), /* @__PURE__ */ React8__namespace.createElement(
2089
2069
  "input",
2090
2070
  {
2091
2071
  type: "text",
@@ -2093,9 +2073,11 @@ function DateRangePicker({
2093
2073
  "flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
2094
2074
  "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
2095
2075
  "disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
2076
+ INPUT_AUTOFILL_RESET_CLASSES,
2096
2077
  showIcon ? "pl-10" : "pl-3",
2097
2078
  clearable && (rangeStart || rangeEnd) ? "pr-10" : "pr-3",
2098
- error && "border-red-500 ring-1 ring-red-500"
2079
+ !error && hasValue && "ring-2 ring-ring",
2080
+ error && "border-destructive ring-1 ring-destructive"
2099
2081
  ),
2100
2082
  value: displayValue,
2101
2083
  onClick: handleToggle,
@@ -2108,7 +2090,7 @@ function DateRangePicker({
2108
2090
  "aria-required": required || props["aria-required"],
2109
2091
  readOnly: true
2110
2092
  }
2111
- ), clearable && (rangeStart || rangeEnd) && !disabled && /* @__PURE__ */ React7__namespace.createElement(
2093
+ ), clearable && (rangeStart || rangeEnd) && !disabled && /* @__PURE__ */ React8__namespace.createElement(
2112
2094
  "button",
2113
2095
  {
2114
2096
  type: "button",
@@ -2118,7 +2100,7 @@ function DateRangePicker({
2118
2100
  tabIndex: -1
2119
2101
  },
2120
2102
  "\u2715"
2121
- )), isOpen && !disabled && /* @__PURE__ */ React7__namespace.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__namespace.createElement("div", { className: "text-xs text-center pt-2 border-t border-border mt-2" }, "Select end date")));
2103
+ )), isOpen && !disabled && /* @__PURE__ */ React8__namespace.createElement("div", { className: "absolute z-50 top-full mt-1 w-fit rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, /* @__PURE__ */ React8__namespace.createElement("div", { role: "grid", "aria-label": "Calendar" }, /* @__PURE__ */ React8__namespace.createElement("div", { className: "grid gap-4", style: monthsGridStyle }, renderMonth(selectedMonth, { prev: true }), renderMonth(addMonths(selectedMonth, 1), { next: true }))), rangeStart && !rangeEnd && /* @__PURE__ */ React8__namespace.createElement("div", { className: "text-xs text-center pt-2 border-t border-border mt-2" }, "Select end date")));
2122
2104
  }
2123
2105
  DateRangePicker.displayName = "DateRangePicker";
2124
2106
  function htmlToMarkdown(html) {
@@ -2189,11 +2171,11 @@ function RichTextEditor({
2189
2171
  ],
2190
2172
  ...props
2191
2173
  }) {
2192
- const [currentMode, setCurrentMode] = React7__namespace.useState(mode);
2193
- const [content, setContent] = React7__namespace.useState(value);
2194
- const editorRef = React7__namespace.useRef(null);
2195
- const textareaRef = React7__namespace.useRef(null);
2196
- React7__namespace.useEffect(() => {
2174
+ const [currentMode, setCurrentMode] = React8__namespace.useState(mode);
2175
+ const [content, setContent] = React8__namespace.useState(value);
2176
+ const editorRef = React8__namespace.useRef(null);
2177
+ const textareaRef = React8__namespace.useRef(null);
2178
+ React8__namespace.useEffect(() => {
2197
2179
  setContent(value);
2198
2180
  if (currentMode === "wysiwyg" && editorRef.current) {
2199
2181
  editorRef.current.innerHTML = value;
@@ -2281,16 +2263,27 @@ function RichTextEditor({
2281
2263
  }
2282
2264
  }
2283
2265
  };
2284
- const combinedClassName = `rounded-md border border-input ${error ? "border-red-500 ring-1 ring-red-500" : ""} ${disabled ? "opacity-50 cursor-not-allowed" : ""} ${className}`.trim();
2266
+ const hasValue = React8__namespace.useMemo(() => {
2267
+ if (!content) return false;
2268
+ const stripped = content.replace(/<[^>]+>/g, "").trim();
2269
+ return stripped.length > 0;
2270
+ }, [content]);
2271
+ const combinedClassName = cn(
2272
+ "rounded-md border border-input",
2273
+ !error && hasValue && "ring-2 ring-ring",
2274
+ error && "border-destructive ring-1 ring-destructive",
2275
+ disabled && "opacity-50 cursor-not-allowed",
2276
+ className
2277
+ );
2285
2278
  const editorStyle = {
2286
2279
  minHeight,
2287
2280
  maxHeight,
2288
2281
  overflowY: maxHeight ? "auto" : void 0
2289
2282
  };
2290
- return /* @__PURE__ */ React7__namespace.createElement("div", { className: combinedClassName }, /* @__PURE__ */ React7__namespace.createElement("input", { type: "hidden", name, value: content }), showToolbar && /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center justify-between p-2 border-b border-border bg-muted/50" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center gap-1" }, toolbarButtons.map((buttonName) => {
2283
+ return /* @__PURE__ */ React8__namespace.createElement("div", { className: combinedClassName }, /* @__PURE__ */ React8__namespace.createElement("input", { type: "hidden", name, value: content }), showToolbar && /* @__PURE__ */ React8__namespace.createElement("div", { className: "flex items-center justify-between p-2 border-b border-border bg-muted/50" }, /* @__PURE__ */ React8__namespace.createElement("div", { className: "flex items-center gap-1" }, toolbarButtons.map((buttonName) => {
2291
2284
  const button = toolbarConfig[buttonName];
2292
2285
  if (!button) return null;
2293
- return /* @__PURE__ */ React7__namespace.createElement(
2286
+ return /* @__PURE__ */ React8__namespace.createElement(
2294
2287
  "button",
2295
2288
  {
2296
2289
  key: buttonName,
@@ -2303,7 +2296,7 @@ function RichTextEditor({
2303
2296
  },
2304
2297
  button.icon
2305
2298
  );
2306
- })), allowModeSwitch && /* @__PURE__ */ React7__namespace.createElement(
2299
+ })), allowModeSwitch && /* @__PURE__ */ React8__namespace.createElement(
2307
2300
  "button",
2308
2301
  {
2309
2302
  type: "button",
@@ -2314,7 +2307,7 @@ function RichTextEditor({
2314
2307
  "aria-label": `Switch to ${currentMode === "wysiwyg" ? "Markdown" : "WYSIWYG"}`
2315
2308
  },
2316
2309
  currentMode === "wysiwyg" ? "MD" : "WYSIWYG"
2317
- )), /* @__PURE__ */ React7__namespace.createElement("div", { style: editorStyle }, currentMode === "wysiwyg" ? /* @__PURE__ */ React7__namespace.createElement(
2310
+ )), /* @__PURE__ */ React8__namespace.createElement("div", { style: editorStyle }, currentMode === "wysiwyg" ? /* @__PURE__ */ React8__namespace.createElement(
2318
2311
  "div",
2319
2312
  {
2320
2313
  ref: editorRef,
@@ -2329,11 +2322,14 @@ function RichTextEditor({
2329
2322
  "aria-required": required || props["aria-required"],
2330
2323
  suppressContentEditableWarning: true
2331
2324
  }
2332
- ) : /* @__PURE__ */ React7__namespace.createElement(
2325
+ ) : /* @__PURE__ */ React8__namespace.createElement(
2333
2326
  "textarea",
2334
2327
  {
2335
2328
  ref: textareaRef,
2336
- 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",
2329
+ className: cn(
2330
+ "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",
2331
+ INPUT_AUTOFILL_RESET_CLASSES
2332
+ ),
2337
2333
  value: content,
2338
2334
  onChange: handleMarkdownChange,
2339
2335
  onBlur,