@page-speed/forms 0.4.2 → 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.js CHANGED
@@ -1,6 +1,13 @@
1
- import * as React7 from 'react';
1
+ import * as React8 from 'react';
2
2
  import { clsx } from 'clsx';
3
3
  import { twMerge } from 'tailwind-merge';
4
+ import { useOnClickOutside } from '@opensite/hooks/useOnClickOutside';
5
+
6
+ // src/inputs/TextInput.tsx
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+ 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]";
4
11
 
5
12
  // src/inputs/TextInput.tsx
6
13
  function TextInput({
@@ -23,10 +30,17 @@ function TextInput({
23
30
  const handleBlur = () => {
24
31
  onBlur?.();
25
32
  };
26
- const baseClassName = "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm";
27
- const errorClassName = error ? "border-red-500 ring-1 ring-red-500" : "";
28
- const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
29
- return /* @__PURE__ */ React7.createElement(
33
+ const hasValue = String(value ?? "").trim().length > 0;
34
+ const combinedClassName = cn(
35
+ "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors",
36
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
37
+ "disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
38
+ INPUT_AUTOFILL_RESET_CLASSES,
39
+ !error && hasValue && "ring-2 ring-ring",
40
+ error && "border-destructive ring-1 ring-destructive",
41
+ className
42
+ );
43
+ return /* @__PURE__ */ React8.createElement(
30
44
  "input",
31
45
  {
32
46
  type,
@@ -70,10 +84,17 @@ function TextArea({
70
84
  const handleBlur = () => {
71
85
  onBlur?.();
72
86
  };
73
- const baseClassName = "flex min-h-20 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm";
74
- const errorClassName = error ? "border-red-500 ring-1 ring-red-500" : "";
75
- const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
76
- return /* @__PURE__ */ React7.createElement(
87
+ const hasValue = String(value ?? "").trim().length > 0;
88
+ const combinedClassName = cn(
89
+ "flex min-h-20 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm transition-colors",
90
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
91
+ "disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
92
+ INPUT_AUTOFILL_RESET_CLASSES,
93
+ !error && hasValue && "ring-2 ring-ring",
94
+ error && "border-destructive ring-1 ring-destructive",
95
+ className
96
+ );
97
+ return /* @__PURE__ */ React8.createElement(
77
98
  "textarea",
78
99
  {
79
100
  name,
@@ -97,9 +118,53 @@ function TextArea({
97
118
  );
98
119
  }
99
120
  TextArea.displayName = "TextArea";
100
- function cn(...inputs) {
101
- return twMerge(clsx(inputs));
102
- }
121
+ var LabelGroup = ({
122
+ labelHtmlFor,
123
+ required = false,
124
+ variant = "label",
125
+ secondaryId,
126
+ secondary,
127
+ primary,
128
+ primaryClassName,
129
+ secondaryClassName
130
+ }) => {
131
+ const primaryClasses = cn(
132
+ "text-sm font-medium leading-snug",
133
+ variant === "legend" ? "mb-1.5" : "mb-1 block",
134
+ primaryClassName
135
+ );
136
+ const requiredIndicator = required ? /* @__PURE__ */ React8.createElement("span", { className: "text-destructive pl-0.5", "aria-label": "required" }, "*") : null;
137
+ let primaryElement = null;
138
+ if (primary) {
139
+ if (variant === "label") {
140
+ primaryElement = /* @__PURE__ */ React8.createElement(
141
+ "label",
142
+ {
143
+ htmlFor: labelHtmlFor,
144
+ "data-slot": "field-label",
145
+ className: primaryClasses
146
+ },
147
+ primary,
148
+ requiredIndicator
149
+ );
150
+ } else if (variant === "legend") {
151
+ primaryElement = /* @__PURE__ */ React8.createElement("legend", { "data-slot": "field-legend", className: primaryClasses }, primary, requiredIndicator);
152
+ } else {
153
+ primaryElement = /* @__PURE__ */ React8.createElement("div", { "data-slot": "field-label", className: primaryClasses }, primary, requiredIndicator);
154
+ }
155
+ }
156
+ const secondaryElement = secondary ? /* @__PURE__ */ React8.createElement(
157
+ "p",
158
+ {
159
+ "data-slot": "field-description",
160
+ id: secondaryId,
161
+ className: cn("text-sm leading-normal font-normal", secondaryClassName)
162
+ },
163
+ secondary
164
+ ) : null;
165
+ if (!primaryElement && !secondaryElement) return null;
166
+ return /* @__PURE__ */ React8.createElement(React8.Fragment, null, primaryElement, secondaryElement);
167
+ };
103
168
 
104
169
  // src/inputs/Checkbox.tsx
105
170
  function Checkbox({
@@ -114,12 +179,12 @@ function Checkbox({
114
179
  indeterminate = false,
115
180
  label,
116
181
  description,
117
- checkboxVariant = "boxed",
182
+ useChoiceCard = false,
118
183
  ...props
119
184
  }) {
120
- const inputRef = React7.useRef(null);
185
+ const inputRef = React8.useRef(null);
121
186
  const checkboxId = props.id || `checkbox-${name}`;
122
- React7.useEffect(() => {
187
+ React8.useEffect(() => {
123
188
  if (inputRef.current) {
124
189
  inputRef.current.indeterminate = indeterminate;
125
190
  }
@@ -131,7 +196,7 @@ function Checkbox({
131
196
  onBlur?.();
132
197
  };
133
198
  const isActive = value || indeterminate && !value;
134
- const checkbox = /* @__PURE__ */ React7.createElement(
199
+ const checkbox = /* @__PURE__ */ React8.createElement(
135
200
  "div",
136
201
  {
137
202
  className: cn(
@@ -139,7 +204,7 @@ function Checkbox({
139
204
  !label && className
140
205
  )
141
206
  },
142
- /* @__PURE__ */ React7.createElement(
207
+ /* @__PURE__ */ React8.createElement(
143
208
  "input",
144
209
  {
145
210
  ref: inputRef,
@@ -158,7 +223,7 @@ function Checkbox({
158
223
  ...props
159
224
  }
160
225
  ),
161
- /* @__PURE__ */ React7.createElement(
226
+ /* @__PURE__ */ React8.createElement(
162
227
  "div",
163
228
  {
164
229
  className: cn(
@@ -171,7 +236,7 @@ function Checkbox({
171
236
  "peer-focus-visible:ring-2 peer-focus-visible:ring-ring/50 peer-focus-visible:ring-offset-1"
172
237
  )
173
238
  },
174
- value && /* @__PURE__ */ React7.createElement(
239
+ value && /* @__PURE__ */ React8.createElement(
175
240
  "svg",
176
241
  {
177
242
  className: "size-3.5",
@@ -182,9 +247,9 @@ function Checkbox({
182
247
  strokeLinecap: "round",
183
248
  strokeLinejoin: "round"
184
249
  },
185
- /* @__PURE__ */ React7.createElement("polyline", { points: "20 6 9 17 4 12" })
250
+ /* @__PURE__ */ React8.createElement("polyline", { points: "20 6 9 17 4 12" })
186
251
  ),
187
- indeterminate && !value && /* @__PURE__ */ React7.createElement(
252
+ indeterminate && !value && /* @__PURE__ */ React8.createElement(
188
253
  "svg",
189
254
  {
190
255
  className: "size-3.5",
@@ -195,31 +260,44 @@ function Checkbox({
195
260
  strokeLinecap: "round",
196
261
  strokeLinejoin: "round"
197
262
  },
198
- /* @__PURE__ */ React7.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
263
+ /* @__PURE__ */ React8.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
199
264
  )
200
265
  )
201
266
  );
202
267
  if (label) {
203
- return /* @__PURE__ */ React7.createElement(
268
+ return /* @__PURE__ */ React8.createElement(
204
269
  "label",
205
270
  {
206
271
  className: cn(
207
272
  "w-full h-full flex gap-3 p-3 duration-200",
208
- checkboxVariant === "boxed" && "border rounded-lg hover:ring-2",
209
- checkboxVariant === "boxed" && value && "ring-2",
273
+ useChoiceCard && "border rounded-lg hover:ring-2",
274
+ useChoiceCard && value && "ring-2",
210
275
  disabled ? "opacity-50 cursor-not-allowed hover:ring-0" : "cursor-pointer",
211
276
  className
212
277
  ),
213
278
  htmlFor: checkboxId
214
279
  },
215
- /* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row gap-2" }, checkbox, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium" }, label), description && /* @__PURE__ */ React7.createElement(
216
- "p",
280
+ /* @__PURE__ */ React8.createElement(
281
+ "div",
217
282
  {
218
- className: "text-xs opacity-75",
219
- id: `${checkboxId}-description`
283
+ className: cn(
284
+ "flex w-full flex-row gap-2",
285
+ useChoiceCard ? "items-start" : "items-center"
286
+ )
220
287
  },
221
- description
222
- )))
288
+ checkbox,
289
+ /* @__PURE__ */ React8.createElement(
290
+ LabelGroup,
291
+ {
292
+ variant: "text",
293
+ primary: label,
294
+ secondary: description,
295
+ secondaryId: description ? `${checkboxId}-description` : void 0,
296
+ primaryClassName: "mb-0",
297
+ secondaryClassName: "text-xs opacity-75"
298
+ }
299
+ )
300
+ )
223
301
  );
224
302
  }
225
303
  return checkbox;
@@ -253,13 +331,11 @@ function CheckboxGroup({
253
331
  ).length;
254
332
  const allSelected = selectedEnabledCount === enabledOptions.length;
255
333
  const someSelected = selectedEnabledCount > 0 && !allSelected;
256
- const checkboxVariant = React7.useMemo(() => {
257
- if (options.some((opt) => opt.description)) {
258
- return "boxed";
259
- }
260
- return "inline";
334
+ const useChoiceCard = React8.useMemo(() => {
335
+ if (!options) return false;
336
+ return options?.some((opt) => opt.description);
261
337
  }, [options]);
262
- const countableValue = React7.useMemo(() => {
338
+ const countableValue = React8.useMemo(() => {
263
339
  if (value?.length > 0) {
264
340
  return value.length;
265
341
  }
@@ -284,29 +360,37 @@ function CheckboxGroup({
284
360
  onBlur?.();
285
361
  };
286
362
  const maxReached = Boolean(maxSelections && countableValue >= maxSelections);
287
- const containerClass = cn(
288
- "w-full gap-3",
289
- layout === "stacked" && "flex flex-col",
290
- layout === "inline" && "flex flex-row flex-wrap",
291
- layout === "grid" && "grid",
292
- className
293
- );
294
- return /* @__PURE__ */ React7.createElement(
295
- "div",
363
+ const containerClass = React8.useMemo(() => {
364
+ return cn(
365
+ "w-full gap-3 grid grid-cols-1 border-0 m-0 p-0 min-w-0",
366
+ (layout === "grid" || layout === "inline") && "md:grid-cols-2",
367
+ className
368
+ );
369
+ }, [layout, className]);
370
+ const groupDescriptionId = description ? `${name}-description` : void 0;
371
+ const groupAriaDescribedBy = [props["aria-describedby"], groupDescriptionId].filter(Boolean).join(" ") || void 0;
372
+ return /* @__PURE__ */ React8.createElement(
373
+ "fieldset",
296
374
  {
297
375
  className: containerClass,
298
376
  role: "group",
299
377
  "aria-invalid": error || props["aria-invalid"],
300
- "aria-describedby": props["aria-describedby"],
378
+ "aria-describedby": groupAriaDescribedBy,
301
379
  "aria-required": required || props["aria-required"],
302
- "aria-label": typeof label === "string" ? label : props["aria-label"],
303
- style: layout === "grid" ? {
304
- gridTemplateColumns: `repeat(${gridColumns}, 1fr)`
305
- } : void 0
380
+ "aria-label": typeof label === "string" ? label : props["aria-label"]
306
381
  },
307
- label && /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium" }, label),
308
- description && /* @__PURE__ */ React7.createElement("div", { className: "text-muted-foreground text-sm" }, description),
309
- showSelectAll && enabledOptions.length > 0 && /* @__PURE__ */ React7.createElement(
382
+ /* @__PURE__ */ React8.createElement(
383
+ LabelGroup,
384
+ {
385
+ labelHtmlFor: name,
386
+ required,
387
+ variant: "legend",
388
+ secondaryId: groupDescriptionId,
389
+ secondary: description,
390
+ primary: label
391
+ }
392
+ ),
393
+ showSelectAll && enabledOptions.length > 0 && /* @__PURE__ */ React8.createElement(
310
394
  Checkbox,
311
395
  {
312
396
  name: `${name}-select-all`,
@@ -316,7 +400,7 @@ function CheckboxGroup({
316
400
  onBlur: handleBlur,
317
401
  indeterminate: someSelected,
318
402
  label: selectAllLabel,
319
- checkboxVariant: "inline",
403
+ useChoiceCard,
320
404
  disabled,
321
405
  "aria-label": selectAllLabel
322
406
  }
@@ -324,7 +408,7 @@ function CheckboxGroup({
324
408
  options.map((option) => {
325
409
  const isChecked = value.includes(option.value);
326
410
  const isDisabled = disabled || option.disabled || maxReached && !isChecked;
327
- return /* @__PURE__ */ React7.createElement(
411
+ return /* @__PURE__ */ React8.createElement(
328
412
  Checkbox,
329
413
  {
330
414
  key: option.value,
@@ -338,11 +422,11 @@ function CheckboxGroup({
338
422
  error,
339
423
  label: renderOption ? renderOption(option) : option.label,
340
424
  description: renderOption ? void 0 : option.description,
341
- checkboxVariant
425
+ useChoiceCard
342
426
  }
343
427
  );
344
428
  }),
345
- (minSelections || maxSelections) && /* @__PURE__ */ React7.createElement(
429
+ (minSelections || maxSelections) && /* @__PURE__ */ React8.createElement(
346
430
  "div",
347
431
  {
348
432
  className: cn(
@@ -351,8 +435,8 @@ function CheckboxGroup({
351
435
  ),
352
436
  "aria-live": "polite"
353
437
  },
354
- minSelections && countableValue < minSelections && /* @__PURE__ */ React7.createElement("span", null, "Select at least ", minSelections, " option", minSelections !== 1 ? "s" : ""),
355
- maxSelections && /* @__PURE__ */ React7.createElement("span", null, countableValue, "/", maxSelections, " selected")
438
+ minSelections && countableValue < minSelections && /* @__PURE__ */ React8.createElement("span", null, "Select at least ", minSelections, " option", minSelections !== 1 ? "s" : ""),
439
+ maxSelections && /* @__PURE__ */ React8.createElement("span", null, countableValue, "/", maxSelections, " selected")
356
440
  )
357
441
  );
358
442
  }
@@ -367,8 +451,8 @@ function Radio({
367
451
  error = false,
368
452
  className = "",
369
453
  layout = "stacked",
370
- radioVariant = "inline",
371
454
  label,
455
+ description,
372
456
  options,
373
457
  ...props
374
458
  }) {
@@ -403,29 +487,43 @@ function Radio({
403
487
  const handleBlur = () => {
404
488
  onBlur?.();
405
489
  };
406
- const containerClass = cn(
407
- "w-full gap-3",
408
- layout === "stacked" && "flex flex-col",
409
- layout === "inline" && "flex flex-row flex-wrap",
410
- className
411
- );
412
- return /* @__PURE__ */ React7.createElement(
413
- "div",
490
+ const useChoiceCard = React8.useMemo(() => {
491
+ return options.some((option) => option.description);
492
+ }, [options]);
493
+ const containerClass = React8.useMemo(() => {
494
+ return cn(
495
+ "w-full gap-3 grid grid-cols-1 border-0 m-0 p-0 min-w-0",
496
+ (layout === "grid" || layout === "inline") && "md:grid-cols-2",
497
+ className
498
+ );
499
+ }, [layout, className]);
500
+ const groupDescriptionId = description ? `${name}-description` : void 0;
501
+ const groupAriaDescribedBy = [props["aria-describedby"], groupDescriptionId].filter(Boolean).join(" ") || void 0;
502
+ return /* @__PURE__ */ React8.createElement(
503
+ "fieldset",
414
504
  {
415
505
  className: containerClass,
416
506
  role: "radiogroup",
417
507
  "aria-invalid": error || props["aria-invalid"],
418
- "aria-describedby": props["aria-describedby"],
508
+ "aria-describedby": groupAriaDescribedBy,
419
509
  "aria-required": required || props["aria-required"],
420
510
  "aria-label": typeof label === "string" ? label : props["aria-label"]
421
511
  },
422
- label && /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium mb-2" }, label),
512
+ /* @__PURE__ */ React8.createElement(
513
+ LabelGroup,
514
+ {
515
+ variant: "legend",
516
+ primary: label,
517
+ secondary: description,
518
+ secondaryId: groupDescriptionId
519
+ }
520
+ ),
423
521
  options.map((option, index) => {
424
522
  const isChecked = value === option.value;
425
523
  const isDisabled = disabled || option.disabled;
426
524
  const radioId = `${name}-${option.value}`;
427
525
  const hasDescription = option.description != null && option.description !== "";
428
- const radioIndicator = /* @__PURE__ */ React7.createElement("div", { className: "relative inline-flex items-center justify-center" }, /* @__PURE__ */ React7.createElement(
526
+ const radioIndicator = /* @__PURE__ */ React8.createElement("div", { className: "relative inline-flex items-center justify-center" }, /* @__PURE__ */ React8.createElement(
429
527
  "input",
430
528
  {
431
529
  type: "radio",
@@ -440,7 +538,7 @@ function Radio({
440
538
  className: "peer sr-only",
441
539
  "aria-describedby": hasDescription ? `${radioId}-description` : props["aria-describedby"]
442
540
  }
443
- ), /* @__PURE__ */ React7.createElement(
541
+ ), /* @__PURE__ */ React8.createElement(
444
542
  "div",
445
543
  {
446
544
  className: cn(
@@ -453,31 +551,45 @@ function Radio({
453
551
  "peer-focus-visible:ring-2 peer-focus-visible:ring-ring/50 peer-focus-visible:ring-offset-1"
454
552
  )
455
553
  },
456
- isChecked && /* @__PURE__ */ React7.createElement("div", { className: "size-3 rounded-full bg-primary" })
554
+ isChecked && /* @__PURE__ */ React8.createElement("div", { className: "size-3 rounded-full bg-primary" })
457
555
  ));
458
- const labelContent = /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium" }, option.label), hasDescription && /* @__PURE__ */ React7.createElement(
459
- "p",
556
+ const labelContent = /* @__PURE__ */ React8.createElement(
557
+ LabelGroup,
460
558
  {
461
- className: "text-xs opacity-75",
462
- id: `${radioId}-description`
463
- },
464
- option.description
465
- ));
466
- return /* @__PURE__ */ React7.createElement(
559
+ variant: "text",
560
+ primary: option.label,
561
+ secondary: hasDescription ? option.description : void 0,
562
+ secondaryId: hasDescription ? `${radioId}-description` : void 0,
563
+ primaryClassName: "mb-0",
564
+ secondaryClassName: "text-xs opacity-75"
565
+ }
566
+ );
567
+ return /* @__PURE__ */ React8.createElement(
467
568
  "label",
468
569
  {
469
570
  key: option.value,
470
571
  className: cn(
471
572
  "w-full h-full flex gap-3 p-3 duration-200",
472
- radioVariant === "boxed" && "border rounded-lg hover:ring-2",
473
- radioVariant === "boxed" && isChecked && "ring-2",
573
+ useChoiceCard && "border rounded-lg hover:ring-2",
574
+ useChoiceCard && isChecked && "ring-2",
474
575
  isDisabled ? "opacity-50 cursor-not-allowed hover:ring-0" : "cursor-pointer"
475
576
  ),
476
577
  htmlFor: radioId,
477
578
  onKeyDown: (e) => handleKeyDown(e, index),
478
579
  tabIndex: isDisabled ? -1 : 0
479
580
  },
480
- /* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, radioVariant === "inline" && radioIndicator, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, labelContent), radioVariant === "boxed" && radioIndicator)
581
+ /* @__PURE__ */ React8.createElement(
582
+ "div",
583
+ {
584
+ className: cn(
585
+ "flex w-full flex-row gap-2",
586
+ useChoiceCard ? "items-start" : "items-center"
587
+ )
588
+ },
589
+ !useChoiceCard && radioIndicator,
590
+ /* @__PURE__ */ React8.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, labelContent),
591
+ useChoiceCard && radioIndicator
592
+ )
481
593
  );
482
594
  })
483
595
  );
@@ -502,19 +614,19 @@ function Select({
502
614
  renderOption,
503
615
  ...props
504
616
  }) {
505
- const [isOpen, setIsOpen] = React7.useState(false);
506
- const [searchQuery, setSearchQuery] = React7.useState("");
507
- const [focusedIndex, setFocusedIndex] = React7.useState(-1);
508
- const selectRef = React7.useRef(null);
509
- const searchInputRef = React7.useRef(null);
617
+ const [isOpen, setIsOpen] = React8.useState(false);
618
+ const [searchQuery, setSearchQuery] = React8.useState("");
619
+ const [focusedIndex, setFocusedIndex] = React8.useState(-1);
620
+ const selectRef = React8.useRef(null);
621
+ const searchInputRef = React8.useRef(null);
510
622
  const dropdownId = `${name}-dropdown`;
511
- const allOptions = React7.useMemo(() => {
623
+ const allOptions = React8.useMemo(() => {
512
624
  if (optionGroups.length > 0) {
513
625
  return optionGroups.flatMap((group) => group.options);
514
626
  }
515
627
  return options;
516
628
  }, [options, optionGroups]);
517
- const filteredOptions = React7.useMemo(() => {
629
+ const filteredOptions = React8.useMemo(() => {
518
630
  if (!searchQuery.trim()) {
519
631
  return allOptions;
520
632
  }
@@ -524,9 +636,10 @@ function Select({
524
636
  return label.toLowerCase().includes(query);
525
637
  });
526
638
  }, [allOptions, searchQuery]);
527
- const selectedOption = React7.useMemo(() => {
639
+ const selectedOption = React8.useMemo(() => {
528
640
  return allOptions.find((opt) => opt.value === value);
529
641
  }, [allOptions, value]);
642
+ const hasValue = Boolean(value);
530
643
  const handleSelect = (optionValue) => {
531
644
  onChange(optionValue);
532
645
  setIsOpen(false);
@@ -567,9 +680,7 @@ function Select({
567
680
  if (enabledOptions.length > 0) {
568
681
  const currentIndexInFiltered = focusedIndex;
569
682
  const nextIndex = (currentIndexInFiltered + 1) % enabledOptions.length;
570
- setFocusedIndex(
571
- filteredOptions.indexOf(enabledOptions[nextIndex])
572
- );
683
+ setFocusedIndex(filteredOptions.indexOf(enabledOptions[nextIndex]));
573
684
  }
574
685
  }
575
686
  break;
@@ -580,9 +691,7 @@ function Select({
580
691
  if (enabledOptions.length > 0) {
581
692
  const currentIndexInFiltered = focusedIndex;
582
693
  const prevIndex = (currentIndexInFiltered - 1 + enabledOptions.length) % enabledOptions.length;
583
- setFocusedIndex(
584
- filteredOptions.indexOf(enabledOptions[prevIndex])
585
- );
694
+ setFocusedIndex(filteredOptions.indexOf(enabledOptions[prevIndex]));
586
695
  }
587
696
  }
588
697
  break;
@@ -625,27 +734,22 @@ function Select({
625
734
  break;
626
735
  }
627
736
  };
628
- const handleBlur = () => {
629
- onBlur?.();
630
- };
631
- React7.useEffect(() => {
632
- const handleClickOutside = (event) => {
633
- if (selectRef.current && !selectRef.current.contains(event.target)) {
634
- setIsOpen(false);
635
- setSearchQuery("");
636
- setFocusedIndex(-1);
637
- handleBlur();
638
- }
639
- };
640
- if (isOpen) {
641
- document.addEventListener("mousedown", handleClickOutside);
642
- return () => {
643
- document.removeEventListener("mousedown", handleClickOutside);
644
- };
737
+ const handleBlur = (event) => {
738
+ const nextTarget = event?.relatedTarget;
739
+ if (!nextTarget || !selectRef.current?.contains(nextTarget)) {
740
+ onBlur?.();
645
741
  }
646
- }, [isOpen]);
647
- const combinedClassName = `relative w-full ${className}`.trim();
648
- return /* @__PURE__ */ React7.createElement(
742
+ };
743
+ const closeDropdown = React8.useCallback(() => {
744
+ if (!isOpen) return;
745
+ setIsOpen(false);
746
+ setSearchQuery("");
747
+ setFocusedIndex(-1);
748
+ onBlur?.();
749
+ }, [isOpen, onBlur]);
750
+ useOnClickOutside(selectRef, closeDropdown, "pointerdown", true);
751
+ const combinedClassName = cn("relative w-full", className);
752
+ return /* @__PURE__ */ React8.createElement(
649
753
  "div",
650
754
  {
651
755
  ref: selectRef,
@@ -653,7 +757,7 @@ function Select({
653
757
  onKeyDown: handleKeyDown,
654
758
  onBlur: handleBlur
655
759
  },
656
- /* @__PURE__ */ React7.createElement(
760
+ /* @__PURE__ */ React8.createElement(
657
761
  "select",
658
762
  {
659
763
  name,
@@ -666,13 +770,19 @@ function Select({
666
770
  tabIndex: -1,
667
771
  style: { display: "none" }
668
772
  },
669
- /* @__PURE__ */ React7.createElement("option", { value: "" }, "Select..."),
670
- allOptions.map((option) => /* @__PURE__ */ React7.createElement("option", { key: option.value, value: option.value }, typeof option.label === "string" ? option.label : option.value))
773
+ /* @__PURE__ */ React8.createElement("option", { value: "" }, "Select..."),
774
+ allOptions.map((option) => /* @__PURE__ */ React8.createElement("option", { key: option.value, value: option.value }, typeof option.label === "string" ? option.label : option.value))
671
775
  ),
672
- /* @__PURE__ */ React7.createElement(
776
+ /* @__PURE__ */ React8.createElement(
673
777
  "div",
674
778
  {
675
- className: `flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm cursor-pointer transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring ${disabled ? "cursor-not-allowed opacity-50 pointer-events-none" : ""} ${error ? "border-red-500 ring-1 ring-red-500" : ""}`,
779
+ className: cn(
780
+ "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",
781
+ "cursor-pointer transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
782
+ !error && hasValue && "ring-2 ring-ring",
783
+ disabled && "cursor-not-allowed opacity-50 pointer-events-none",
784
+ error && "border-destructive ring-1 ring-destructive"
785
+ ),
676
786
  onClick: handleToggle,
677
787
  role: "combobox",
678
788
  "aria-expanded": isOpen,
@@ -683,48 +793,79 @@ function Select({
683
793
  "aria-disabled": disabled,
684
794
  tabIndex: disabled ? -1 : 0
685
795
  },
686
- /* @__PURE__ */ React7.createElement("span", { className: "flex items-center flex-1 overflow-hidden text-ellipsis" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React7.createElement("span", { className: "text-muted-foreground" }, placeholder)),
687
- /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-1 ml-2" }, loading && /* @__PURE__ */ React7.createElement("span", { className: "text-xs" }, "\u23F3"), clearable && value && !disabled && !loading && /* @__PURE__ */ React7.createElement(
796
+ /* @__PURE__ */ React8.createElement("span", { className: "flex items-center flex-1 overflow-hidden text-ellipsis" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React8.createElement("span", { className: "relative" }, placeholder)),
797
+ /* @__PURE__ */ React8.createElement("div", { className: "flex items-center gap-1 ml-2" }, loading && /* @__PURE__ */ React8.createElement("span", { className: "text-xs" }, "\u23F3"), clearable && value && !disabled && !loading && /* @__PURE__ */ React8.createElement(
688
798
  "button",
689
799
  {
690
800
  type: "button",
691
- className: "flex items-center justify-center h-4 w-4 rounded-sm border-none bg-transparent text-muted-foreground cursor-pointer text-xs p-0 transition-opacity hover:opacity-70",
801
+ className: "flex items-center justify-center h-4 w-4 rounded-sm border-none bg-transparent cursor-pointer text-xs p-0 transition-opacity hover:opacity-70",
692
802
  onClick: handleClear,
693
803
  "aria-label": "Clear selection",
694
804
  tabIndex: -1
695
805
  },
696
806
  "\u2715"
697
- ), /* @__PURE__ */ React7.createElement("span", { className: "text-muted-foreground text-xs leading-none", "aria-hidden": "true" }, isOpen ? "\u25B2" : "\u25BC"))
807
+ ), /* @__PURE__ */ React8.createElement("span", { className: "text-xs leading-none", "aria-hidden": "true" }, isOpen ? "\u25B2" : "\u25BC"))
698
808
  ),
699
- isOpen && /* @__PURE__ */ React7.createElement("div", { id: dropdownId, className: "absolute z-50 top-full mt-1 min-w-full overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md", role: "listbox" }, searchable && /* @__PURE__ */ React7.createElement("div", { className: "p-2 border-b border-border" }, /* @__PURE__ */ React7.createElement(
700
- "input",
809
+ isOpen && /* @__PURE__ */ React8.createElement(
810
+ "div",
701
811
  {
702
- ref: searchInputRef,
703
- type: "text",
704
- className: "w-full border border-input rounded px-2 py-1 text-sm bg-transparent outline-none focus:ring-1 focus:ring-ring",
705
- placeholder: "Search...",
706
- value: searchQuery,
707
- onChange: handleSearchChange,
708
- onClick: (e) => e.stopPropagation(),
709
- "aria-label": "Search options"
710
- }
711
- )), /* @__PURE__ */ React7.createElement("div", { className: "max-h-64 overflow-y-auto p-1" }, filteredOptions.length === 0 ? /* @__PURE__ */ React7.createElement("div", { className: "py-2 px-3 text-center text-sm text-muted-foreground" }, "No options found") : optionGroups.length > 0 ? (
712
- // Render grouped options
713
- optionGroups.map((group, groupIndex) => {
714
- const groupOptions = group.options.filter(
715
- (opt) => filteredOptions.includes(opt)
716
- );
717
- if (groupOptions.length === 0) return null;
718
- return /* @__PURE__ */ React7.createElement("div", { key: groupIndex, className: "py-1" }, /* @__PURE__ */ React7.createElement("div", { className: "py-1.5 px-2 text-xs font-semibold text-muted-foreground" }, group.label), groupOptions.map((option) => {
719
- const globalIndex = filteredOptions.indexOf(option);
812
+ id: dropdownId,
813
+ 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",
814
+ role: "listbox"
815
+ },
816
+ searchable && /* @__PURE__ */ React8.createElement("div", { className: "p-2 border-b border-border" }, /* @__PURE__ */ React8.createElement(
817
+ "input",
818
+ {
819
+ ref: searchInputRef,
820
+ type: "text",
821
+ className: cn(
822
+ "w-full border border-input rounded px-2 py-1 text-sm bg-transparent outline-none focus:ring-1 focus:ring-ring",
823
+ INPUT_AUTOFILL_RESET_CLASSES
824
+ ),
825
+ placeholder: "Search...",
826
+ value: searchQuery,
827
+ onChange: handleSearchChange,
828
+ onClick: (e) => e.stopPropagation(),
829
+ "aria-label": "Search options"
830
+ }
831
+ )),
832
+ /* @__PURE__ */ React8.createElement("div", { className: "max-h-64 overflow-y-auto p-1" }, filteredOptions.length === 0 ? /* @__PURE__ */ React8.createElement("div", { className: "py-2 px-3 text-center text-sm " }, "No options found") : optionGroups.length > 0 ? (
833
+ // Render grouped options
834
+ optionGroups.map((group, groupIndex) => {
835
+ const groupOptions = group.options.filter(
836
+ (opt) => filteredOptions.includes(opt)
837
+ );
838
+ if (groupOptions.length === 0) return null;
839
+ return /* @__PURE__ */ React8.createElement("div", { key: groupIndex, className: "py-1" }, /* @__PURE__ */ React8.createElement("div", { className: "py-1.5 px-2 text-xs font-semibold " }, group.label), groupOptions.map((option) => {
840
+ const globalIndex = filteredOptions.indexOf(option);
841
+ const isSelected = value === option.value;
842
+ const isFocused = globalIndex === focusedIndex;
843
+ const isDisabled = option.disabled;
844
+ return /* @__PURE__ */ React8.createElement(
845
+ "div",
846
+ {
847
+ key: option.value,
848
+ className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-muted ${isFocused ? "bg-muted" : ""} ${isSelected ? "font-medium bg-muted" : ""} ${isDisabled ? "pointer-events-none opacity-50" : ""}`,
849
+ onClick: () => !isDisabled && handleSelect(option.value),
850
+ role: "option",
851
+ "aria-selected": isSelected,
852
+ "aria-disabled": isDisabled
853
+ },
854
+ renderOption ? renderOption(option) : option.label
855
+ );
856
+ }));
857
+ })
858
+ ) : (
859
+ // Render flat options
860
+ filteredOptions.map((option, index) => {
720
861
  const isSelected = value === option.value;
721
- const isFocused = globalIndex === focusedIndex;
862
+ const isFocused = index === focusedIndex;
722
863
  const isDisabled = option.disabled;
723
- return /* @__PURE__ */ React7.createElement(
864
+ return /* @__PURE__ */ React8.createElement(
724
865
  "div",
725
866
  {
726
867
  key: option.value,
727
- className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground ${isFocused ? "bg-accent text-accent-foreground" : ""} ${isSelected ? "font-medium bg-accent" : ""} ${isDisabled ? "pointer-events-none opacity-50" : ""}`,
868
+ className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-muted ${isFocused ? "bg-muted" : ""} ${isSelected ? "font-medium bg-muted" : ""} ${isDisabled ? "pointer-events-none opacity-50" : ""}`,
728
869
  onClick: () => !isDisabled && handleSelect(option.value),
729
870
  role: "option",
730
871
  "aria-selected": isSelected,
@@ -732,28 +873,9 @@ function Select({
732
873
  },
733
874
  renderOption ? renderOption(option) : option.label
734
875
  );
735
- }));
736
- })
737
- ) : (
738
- // Render flat options
739
- filteredOptions.map((option, index) => {
740
- const isSelected = value === option.value;
741
- const isFocused = index === focusedIndex;
742
- const isDisabled = option.disabled;
743
- return /* @__PURE__ */ React7.createElement(
744
- "div",
745
- {
746
- key: option.value,
747
- className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground ${isFocused ? "bg-accent text-accent-foreground" : ""} ${isSelected ? "font-medium bg-accent" : ""} ${isDisabled ? "pointer-events-none opacity-50" : ""}`,
748
- onClick: () => !isDisabled && handleSelect(option.value),
749
- role: "option",
750
- "aria-selected": isSelected,
751
- "aria-disabled": isDisabled
752
- },
753
- renderOption ? renderOption(option) : option.label
754
- );
755
- })
756
- )))
876
+ })
877
+ ))
878
+ )
757
879
  );
758
880
  }
759
881
  Select.displayName = "Select";
@@ -762,7 +884,7 @@ function FileInput({
762
884
  value = [],
763
885
  onChange,
764
886
  onBlur,
765
- placeholder = "Choose file(s)...",
887
+ placeholder = "Choose file...",
766
888
  disabled = false,
767
889
  required = false,
768
890
  error = false,
@@ -782,14 +904,14 @@ function FileInput({
782
904
  onFileRemove,
783
905
  ...props
784
906
  }) {
785
- const inputRef = React7.useRef(null);
786
- const [dragActive, setDragActive] = React7.useState(false);
787
- const [cropperOpen, setCropperOpen] = React7.useState(false);
788
- const [imageToCrop, setImageToCrop] = React7.useState(null);
789
- const [crop, setCrop] = React7.useState({ x: 0, y: 0 });
790
- const [zoom, setZoom] = React7.useState(1);
791
- const [croppedAreaPixels, setCroppedAreaPixels] = React7.useState(null);
792
- const validateFile = React7.useCallback(
907
+ const inputRef = React8.useRef(null);
908
+ const [dragActive, setDragActive] = React8.useState(false);
909
+ const [cropperOpen, setCropperOpen] = React8.useState(false);
910
+ const [imageToCrop, setImageToCrop] = React8.useState(null);
911
+ const [crop, setCrop] = React8.useState({ x: 0, y: 0 });
912
+ const [zoom, setZoom] = React8.useState(1);
913
+ const [croppedAreaPixels, setCroppedAreaPixels] = React8.useState(null);
914
+ const validateFile = React8.useCallback(
793
915
  (file) => {
794
916
  if (accept) {
795
917
  const acceptedTypes = accept.split(",").map((t) => t.trim());
@@ -824,7 +946,7 @@ function FileInput({
824
946
  },
825
947
  [accept, maxSize]
826
948
  );
827
- const handleFiles = React7.useCallback(
949
+ const handleFiles = React8.useCallback(
828
950
  (fileList) => {
829
951
  if (!fileList || fileList.length === 0) return;
830
952
  const newFiles = Array.from(fileList);
@@ -865,9 +987,17 @@ function FileInput({
865
987
  inputRef.current.value = "";
866
988
  }
867
989
  },
868
- [value, onChange, validateFile, maxFiles, multiple, enableCropping, onValidationError]
990
+ [
991
+ value,
992
+ onChange,
993
+ validateFile,
994
+ maxFiles,
995
+ multiple,
996
+ enableCropping,
997
+ onValidationError
998
+ ]
869
999
  );
870
- const createCroppedImage = React7.useCallback(
1000
+ const createCroppedImage = React8.useCallback(
871
1001
  async (imageUrl, cropArea) => {
872
1002
  return new Promise((resolve, reject) => {
873
1003
  const image = new Image();
@@ -891,13 +1021,17 @@ function FileInput({
891
1021
  cropArea.width,
892
1022
  cropArea.height
893
1023
  );
894
- canvas.toBlob((blob) => {
895
- if (blob) {
896
- resolve(blob);
897
- } else {
898
- reject(new Error("Failed to create blob from canvas"));
899
- }
900
- }, "image/jpeg", 0.95);
1024
+ canvas.toBlob(
1025
+ (blob) => {
1026
+ if (blob) {
1027
+ resolve(blob);
1028
+ } else {
1029
+ reject(new Error("Failed to create blob from canvas"));
1030
+ }
1031
+ },
1032
+ "image/jpeg",
1033
+ 0.95
1034
+ );
901
1035
  };
902
1036
  image.onerror = () => {
903
1037
  reject(new Error("Failed to load image"));
@@ -907,7 +1041,7 @@ function FileInput({
907
1041
  },
908
1042
  []
909
1043
  );
910
- const handleCropSave = React7.useCallback(async () => {
1044
+ const handleCropSave = React8.useCallback(async () => {
911
1045
  if (!imageToCrop || !croppedAreaPixels) return;
912
1046
  try {
913
1047
  const croppedBlob = await createCroppedImage(
@@ -917,11 +1051,9 @@ function FileInput({
917
1051
  if (onCropComplete) {
918
1052
  onCropComplete(croppedBlob, imageToCrop.file);
919
1053
  }
920
- const croppedFile = new File(
921
- [croppedBlob],
922
- imageToCrop.file.name,
923
- { type: "image/jpeg" }
924
- );
1054
+ const croppedFile = new File([croppedBlob], imageToCrop.file.name, {
1055
+ type: "image/jpeg"
1056
+ });
925
1057
  const updatedFiles = multiple ? [...value, croppedFile] : [croppedFile];
926
1058
  onChange(updatedFiles);
927
1059
  setCropperOpen(false);
@@ -933,8 +1065,16 @@ function FileInput({
933
1065
  } catch (error2) {
934
1066
  console.error("Failed to crop image:", error2);
935
1067
  }
936
- }, [imageToCrop, croppedAreaPixels, createCroppedImage, onCropComplete, value, onChange, multiple]);
937
- const handleCropCancel = React7.useCallback(() => {
1068
+ }, [
1069
+ imageToCrop,
1070
+ croppedAreaPixels,
1071
+ createCroppedImage,
1072
+ onCropComplete,
1073
+ value,
1074
+ onChange,
1075
+ multiple
1076
+ ]);
1077
+ const handleCropCancel = React8.useCallback(() => {
938
1078
  if (imageToCrop) {
939
1079
  URL.revokeObjectURL(imageToCrop.url);
940
1080
  }
@@ -944,13 +1084,13 @@ function FileInput({
944
1084
  setZoom(1);
945
1085
  setCroppedAreaPixels(null);
946
1086
  }, [imageToCrop]);
947
- const onCropChange = React7.useCallback((crop2) => {
1087
+ const onCropChange = React8.useCallback((crop2) => {
948
1088
  setCrop(crop2);
949
1089
  }, []);
950
- const onZoomChange = React7.useCallback((zoom2) => {
1090
+ const onZoomChange = React8.useCallback((zoom2) => {
951
1091
  setZoom(zoom2);
952
1092
  }, []);
953
- const onCropCompleteInternal = React7.useCallback(
1093
+ const onCropCompleteInternal = React8.useCallback(
954
1094
  (_, croppedAreaPixels2) => {
955
1095
  setCroppedAreaPixels(croppedAreaPixels2);
956
1096
  },
@@ -1011,7 +1151,7 @@ function FileInput({
1011
1151
  }
1012
1152
  return null;
1013
1153
  };
1014
- React7.useEffect(() => {
1154
+ React8.useEffect(() => {
1015
1155
  return () => {
1016
1156
  value.forEach((file) => {
1017
1157
  const previewUrl = getPreviewUrl(file);
@@ -1025,7 +1165,7 @@ function FileInput({
1025
1165
  };
1026
1166
  }, [value, imageToCrop]);
1027
1167
  const combinedClassName = `${className}`.trim();
1028
- return /* @__PURE__ */ React7.createElement("div", { className: combinedClassName }, /* @__PURE__ */ React7.createElement(
1168
+ return /* @__PURE__ */ React8.createElement("div", { className: combinedClassName }, /* @__PURE__ */ React8.createElement(
1029
1169
  "input",
1030
1170
  {
1031
1171
  ref: inputRef,
@@ -1042,10 +1182,10 @@ function FileInput({
1042
1182
  "aria-required": required || props["aria-required"],
1043
1183
  style: { display: "none" }
1044
1184
  }
1045
- ), /* @__PURE__ */ React7.createElement(
1185
+ ), /* @__PURE__ */ React8.createElement(
1046
1186
  "div",
1047
1187
  {
1048
- className: `flex min-h-32 w-full cursor-pointer items-center justify-center rounded-md border-2 border-dashed border-input bg-transparent p-6 transition-colors hover:bg-accent/50 hover:border-ring ${dragActive ? "bg-accent border-ring" : ""} ${disabled ? "cursor-not-allowed opacity-50" : ""} ${error ? "border-red-500" : ""}`,
1188
+ 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" : ""}`,
1049
1189
  onDragEnter: handleDrag,
1050
1190
  onDragLeave: handleDrag,
1051
1191
  onDragOver: handleDrag,
@@ -1057,10 +1197,9 @@ function FileInput({
1057
1197
  "aria-label": placeholder,
1058
1198
  "aria-disabled": disabled
1059
1199
  },
1060
- /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col items-center gap-2 text-center" }, /* @__PURE__ */ React7.createElement(
1200
+ /* @__PURE__ */ React8.createElement("div", { className: "flex flex-col items-center gap-2 text-center" }, /* @__PURE__ */ React8.createElement(
1061
1201
  "svg",
1062
1202
  {
1063
- className: "text-muted-foreground",
1064
1203
  width: "48",
1065
1204
  height: "48",
1066
1205
  viewBox: "0 0 24 24",
@@ -1071,112 +1210,122 @@ function FileInput({
1071
1210
  strokeLinejoin: "round",
1072
1211
  "aria-hidden": "true"
1073
1212
  },
1074
- /* @__PURE__ */ React7.createElement("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
1075
- /* @__PURE__ */ React7.createElement("polyline", { points: "17 8 12 3 7 8" }),
1076
- /* @__PURE__ */ React7.createElement("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
1077
- ), /* @__PURE__ */ React7.createElement("p", { className: "text-sm font-medium" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React7.createElement("p", { className: "text-xs text-muted-foreground" }, "Accepted: ", accept), maxSize && /* @__PURE__ */ React7.createElement("p", { className: "text-xs text-muted-foreground" }, "Max size: ", formatFileSize(maxSize)))
1078
- ), value.length > 0 && /* @__PURE__ */ React7.createElement("ul", { className: "flex flex-col gap-2 mt-4", role: "list" }, value.map((file, index) => {
1213
+ /* @__PURE__ */ React8.createElement("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
1214
+ /* @__PURE__ */ React8.createElement("polyline", { points: "17 8 12 3 7 8" }),
1215
+ /* @__PURE__ */ React8.createElement("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
1216
+ ), /* @__PURE__ */ React8.createElement("p", { className: "text-sm font-medium" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React8.createElement("p", { className: "text-xs" }, "Accepted: ", accept), maxSize && /* @__PURE__ */ React8.createElement("p", { className: "text-xs " }, "Max size: ", formatFileSize(maxSize)))
1217
+ ), value.length > 0 && /* @__PURE__ */ React8.createElement("ul", { className: "flex flex-col gap-2 mt-4", role: "list" }, value.map((file, index) => {
1079
1218
  const previewUrl = showPreview ? getPreviewUrl(file) : null;
1080
- return /* @__PURE__ */ React7.createElement("li", { key: `${file.name}-${index}`, className: "flex items-center gap-3 p-3 rounded-md border border-border bg-card hover:bg-accent/50 transition-colors" }, previewUrl && /* @__PURE__ */ React7.createElement(
1081
- "img",
1082
- {
1083
- src: previewUrl,
1084
- alt: file.name,
1085
- className: "w-12 h-12 rounded object-cover",
1086
- width: "48",
1087
- height: "48"
1088
- }
1089
- ), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React7.createElement("span", { className: "text-sm font-medium truncate" }, file.name), /* @__PURE__ */ React7.createElement("span", { className: "text-xs text-muted-foreground" }, formatFileSize(file.size)), showProgress && uploadProgress[file.name] !== void 0 && /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-2 mt-1" }, /* @__PURE__ */ React7.createElement(
1090
- "div",
1219
+ return /* @__PURE__ */ React8.createElement(
1220
+ "li",
1091
1221
  {
1092
- className: "h-1.5 bg-muted rounded-full overflow-hidden flex-1",
1093
- role: "progressbar",
1094
- "aria-valuenow": uploadProgress[file.name],
1095
- "aria-valuemin": 0,
1096
- "aria-valuemax": 100,
1097
- "aria-label": `Upload progress: ${uploadProgress[file.name]}%`
1222
+ key: `${file.name}-${index}`,
1223
+ className: "flex items-center gap-3 p-3 rounded-md border border-border bg-card text-card-foreground hover:bg-primary/50 transition-colors"
1098
1224
  },
1099
- /* @__PURE__ */ React7.createElement(
1100
- "div",
1225
+ previewUrl && /* @__PURE__ */ React8.createElement(
1226
+ "img",
1101
1227
  {
1102
- className: "h-full bg-primary transition-all",
1103
- style: { width: `${uploadProgress[file.name]}%` }
1228
+ src: previewUrl,
1229
+ alt: file.name,
1230
+ className: "w-12 h-12 rounded object-cover",
1231
+ width: "48",
1232
+ height: "48"
1104
1233
  }
1105
- )
1106
- ), /* @__PURE__ */ React7.createElement("span", { className: "text-xs text-muted-foreground" }, uploadProgress[file.name], "%"))), enableCropping && file.type.startsWith("image/") && /* @__PURE__ */ React7.createElement(
1107
- "button",
1108
- {
1109
- type: "button",
1110
- onClick: (e) => {
1111
- e.stopPropagation();
1112
- handleCrop(file);
1113
- },
1114
- disabled,
1115
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
1116
- "aria-label": `Crop ${file.name}`
1117
- },
1118
- /* @__PURE__ */ React7.createElement(
1119
- "svg",
1234
+ ),
1235
+ /* @__PURE__ */ React8.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React8.createElement("span", { className: "text-sm font-medium truncate" }, file.name), /* @__PURE__ */ React8.createElement("span", { className: "text-xs" }, formatFileSize(file.size)), showProgress && uploadProgress[file.name] !== void 0 && /* @__PURE__ */ React8.createElement("div", { className: "flex items-center gap-2 mt-1" }, /* @__PURE__ */ React8.createElement(
1236
+ "div",
1120
1237
  {
1121
- width: "20",
1122
- height: "20",
1123
- viewBox: "0 0 24 24",
1124
- fill: "none",
1125
- stroke: "currentColor",
1126
- strokeWidth: "2",
1127
- strokeLinecap: "round",
1128
- strokeLinejoin: "round",
1129
- "aria-hidden": "true"
1238
+ className: "h-1.5 bg-muted rounded-full overflow-hidden flex-1",
1239
+ role: "progressbar",
1240
+ "aria-valuenow": uploadProgress[file.name],
1241
+ "aria-valuemin": 0,
1242
+ "aria-valuemax": 100,
1243
+ "aria-label": `Upload progress: ${uploadProgress[file.name]}%`
1130
1244
  },
1131
- /* @__PURE__ */ React7.createElement("path", { d: "M6.13 1L6 16a2 2 0 0 0 2 2h15" }),
1132
- /* @__PURE__ */ React7.createElement("path", { d: "M1 6.13L16 6a2 2 0 0 1 2 2v15" })
1133
- )
1134
- ), /* @__PURE__ */ React7.createElement(
1135
- "button",
1136
- {
1137
- type: "button",
1138
- onClick: (e) => {
1139
- e.stopPropagation();
1140
- handleRemove(index);
1245
+ /* @__PURE__ */ React8.createElement(
1246
+ "div",
1247
+ {
1248
+ className: "h-full bg-primary transition-all",
1249
+ style: { width: `${uploadProgress[file.name]}%` }
1250
+ }
1251
+ )
1252
+ ), /* @__PURE__ */ React8.createElement("span", { className: "text-xs " }, uploadProgress[file.name], "%"))),
1253
+ enableCropping && file.type.startsWith("image/") && /* @__PURE__ */ React8.createElement(
1254
+ "button",
1255
+ {
1256
+ type: "button",
1257
+ onClick: (e) => {
1258
+ e.stopPropagation();
1259
+ handleCrop(file);
1260
+ },
1261
+ disabled,
1262
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
1263
+ "aria-label": `Crop ${file.name}`
1141
1264
  },
1142
- disabled,
1143
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
1144
- "aria-label": `Remove ${file.name}`
1145
- },
1146
- /* @__PURE__ */ React7.createElement(
1147
- "svg",
1265
+ /* @__PURE__ */ React8.createElement(
1266
+ "svg",
1267
+ {
1268
+ width: "20",
1269
+ height: "20",
1270
+ viewBox: "0 0 24 24",
1271
+ fill: "none",
1272
+ stroke: "currentColor",
1273
+ strokeWidth: "2",
1274
+ strokeLinecap: "round",
1275
+ strokeLinejoin: "round",
1276
+ "aria-hidden": "true"
1277
+ },
1278
+ /* @__PURE__ */ React8.createElement("path", { d: "M6.13 1L6 16a2 2 0 0 0 2 2h15" }),
1279
+ /* @__PURE__ */ React8.createElement("path", { d: "M1 6.13L16 6a2 2 0 0 1 2 2v15" })
1280
+ )
1281
+ ),
1282
+ /* @__PURE__ */ React8.createElement(
1283
+ "button",
1148
1284
  {
1149
- width: "20",
1150
- height: "20",
1151
- viewBox: "0 0 24 24",
1152
- fill: "none",
1153
- stroke: "currentColor",
1154
- strokeWidth: "2",
1155
- strokeLinecap: "round",
1156
- strokeLinejoin: "round",
1157
- "aria-hidden": "true"
1285
+ type: "button",
1286
+ onClick: (e) => {
1287
+ e.stopPropagation();
1288
+ handleRemove(index);
1289
+ },
1290
+ disabled,
1291
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
1292
+ "aria-label": `Remove ${file.name}`
1158
1293
  },
1159
- /* @__PURE__ */ React7.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1160
- /* @__PURE__ */ React7.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1294
+ /* @__PURE__ */ React8.createElement(
1295
+ "svg",
1296
+ {
1297
+ width: "20",
1298
+ height: "20",
1299
+ viewBox: "0 0 24 24",
1300
+ fill: "none",
1301
+ stroke: "currentColor",
1302
+ strokeWidth: "2",
1303
+ strokeLinecap: "round",
1304
+ strokeLinejoin: "round",
1305
+ "aria-hidden": "true"
1306
+ },
1307
+ /* @__PURE__ */ React8.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1308
+ /* @__PURE__ */ React8.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1309
+ )
1161
1310
  )
1162
- ));
1163
- })), cropperOpen && imageToCrop && /* @__PURE__ */ React7.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center" }, /* @__PURE__ */ React7.createElement(
1311
+ );
1312
+ })), cropperOpen && imageToCrop && /* @__PURE__ */ React8.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center" }, /* @__PURE__ */ React8.createElement(
1164
1313
  "div",
1165
1314
  {
1166
1315
  className: "absolute inset-0 bg-black/50",
1167
1316
  onClick: handleCropCancel,
1168
1317
  "aria-label": "Close cropper"
1169
1318
  }
1170
- ), /* @__PURE__ */ React7.createElement("div", { className: "relative bg-popover border border-border rounded-lg shadow-lg max-w-3xl w-full mx-4" }, /* @__PURE__ */ React7.createElement("div", { className: "flex items-center justify-between p-4 border-b border-border" }, /* @__PURE__ */ React7.createElement("h3", { className: "text-lg font-semibold" }, "Crop Image"), /* @__PURE__ */ React7.createElement(
1319
+ ), /* @__PURE__ */ React8.createElement("div", { className: "relative bg-popover border border-border rounded-lg shadow-lg max-w-3xl w-full mx-4" }, /* @__PURE__ */ React8.createElement("div", { className: "flex items-center justify-between p-4 border-b border-border" }, /* @__PURE__ */ React8.createElement("h3", { className: "text-lg font-semibold" }, "Crop Image"), /* @__PURE__ */ React8.createElement(
1171
1320
  "button",
1172
1321
  {
1173
1322
  type: "button",
1174
- className: "flex items-center justify-center h-8 w-8 rounded hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
1323
+ className: "flex items-center justify-center h-8 w-8 rounded hover:bg-primary hover:text-primary-foreground transition-colors",
1175
1324
  onClick: handleCropCancel,
1176
1325
  "aria-label": "Close"
1177
1326
  },
1178
1327
  "\u2715"
1179
- )), /* @__PURE__ */ React7.createElement("div", { className: "p-4" }, /* @__PURE__ */ React7.createElement(
1328
+ )), /* @__PURE__ */ React8.createElement("div", { className: "p-4" }, /* @__PURE__ */ React8.createElement(
1180
1329
  "div",
1181
1330
  {
1182
1331
  className: "relative w-full h-96 bg-muted rounded-md overflow-hidden",
@@ -1198,7 +1347,7 @@ function FileInput({
1198
1347
  document.addEventListener("mouseup", handleMouseUp);
1199
1348
  }
1200
1349
  },
1201
- /* @__PURE__ */ React7.createElement(
1350
+ /* @__PURE__ */ React8.createElement(
1202
1351
  "img",
1203
1352
  {
1204
1353
  src: imageToCrop.url,
@@ -1212,7 +1361,10 @@ function FileInput({
1212
1361
  const img = e.currentTarget;
1213
1362
  const containerWidth = 600;
1214
1363
  const containerHeight = 400;
1215
- const cropWidth = cropAspectRatio ? Math.min(containerWidth * 0.8, containerHeight * 0.8 * cropAspectRatio) : containerWidth * 0.8;
1364
+ const cropWidth = cropAspectRatio ? Math.min(
1365
+ containerWidth * 0.8,
1366
+ containerHeight * 0.8 * cropAspectRatio
1367
+ ) : containerWidth * 0.8;
1216
1368
  const cropHeight = cropAspectRatio ? cropWidth / cropAspectRatio : containerHeight * 0.8;
1217
1369
  const scale = zoom;
1218
1370
  const imgWidth = img.naturalWidth;
@@ -1230,7 +1382,7 @@ function FileInput({
1230
1382
  }
1231
1383
  }
1232
1384
  ),
1233
- /* @__PURE__ */ React7.createElement(
1385
+ /* @__PURE__ */ React8.createElement(
1234
1386
  "div",
1235
1387
  {
1236
1388
  className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 border-2 border-primary rounded pointer-events-none",
@@ -1239,9 +1391,18 @@ function FileInput({
1239
1391
  aspectRatio: cropAspectRatio ? String(cropAspectRatio) : void 0
1240
1392
  }
1241
1393
  },
1242
- /* @__PURE__ */ React7.createElement("div", { className: "absolute inset-0 grid grid-cols-3 grid-rows-3" }, /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React7.createElement("div", null))
1394
+ /* @__PURE__ */ React8.createElement("div", { className: "absolute inset-0 grid grid-cols-3 grid-rows-3" }, /* @__PURE__ */ React8.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React8.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React8.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React8.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React8.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React8.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React8.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React8.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React8.createElement("div", null))
1243
1395
  )
1244
- ), /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-3 mt-4" }, /* @__PURE__ */ React7.createElement("label", { htmlFor: "zoom-slider", className: "text-sm font-medium whitespace-nowrap" }, "Zoom: ", zoom.toFixed(1), "x"), /* @__PURE__ */ React7.createElement(
1396
+ ), /* @__PURE__ */ React8.createElement("div", { className: "flex items-center gap-3 mt-4" }, /* @__PURE__ */ React8.createElement(
1397
+ "label",
1398
+ {
1399
+ htmlFor: "zoom-slider",
1400
+ className: "text-sm font-medium whitespace-nowrap"
1401
+ },
1402
+ "Zoom: ",
1403
+ zoom.toFixed(1),
1404
+ "x"
1405
+ ), /* @__PURE__ */ React8.createElement(
1245
1406
  "input",
1246
1407
  {
1247
1408
  id: "zoom-slider",
@@ -1254,15 +1415,15 @@ function FileInput({
1254
1415
  className: "flex-1 h-2 bg-muted rounded-lg appearance-none cursor-pointer",
1255
1416
  "aria-label": "Zoom level"
1256
1417
  }
1257
- ))), /* @__PURE__ */ React7.createElement("div", { className: "flex items-center justify-end gap-2 p-4 border-t border-border" }, /* @__PURE__ */ React7.createElement(
1418
+ ))), /* @__PURE__ */ React8.createElement("div", { className: "flex items-center justify-end gap-2 p-4 border-t border-border" }, /* @__PURE__ */ React8.createElement(
1258
1419
  "button",
1259
1420
  {
1260
1421
  type: "button",
1261
- className: "inline-flex items-center justify-center h-9 rounded-md px-4 text-sm font-medium border border-input bg-transparent hover:bg-accent hover:text-accent-foreground transition-colors",
1422
+ className: "inline-flex items-center justify-center h-9 rounded-md px-4 text-sm font-medium border border-input bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
1262
1423
  onClick: handleCropCancel
1263
1424
  },
1264
1425
  "Cancel"
1265
- ), /* @__PURE__ */ React7.createElement(
1426
+ ), /* @__PURE__ */ React8.createElement(
1266
1427
  "button",
1267
1428
  {
1268
1429
  type: "button",
@@ -1281,27 +1442,6 @@ function formatDate(date, format) {
1281
1442
  const year = d.getFullYear();
1282
1443
  return format.replace("MM", month).replace("dd", day).replace("yyyy", String(year)).replace("yy", String(year).slice(2));
1283
1444
  }
1284
- function parseDate(dateString, format) {
1285
- if (!dateString) return null;
1286
- try {
1287
- if (format === "MM/dd/yyyy" || format === "MM-dd-yyyy") {
1288
- const parts = dateString.split(/[/-]/);
1289
- if (parts.length === 3) {
1290
- const month = parseInt(parts[0], 10) - 1;
1291
- const day = parseInt(parts[1], 10);
1292
- const year = parseInt(parts[2], 10);
1293
- const date2 = new Date(year, month, day);
1294
- if (!isNaN(date2.getTime())) {
1295
- return date2;
1296
- }
1297
- }
1298
- }
1299
- const date = new Date(dateString);
1300
- return isNaN(date.getTime()) ? null : date;
1301
- } catch {
1302
- return null;
1303
- }
1304
- }
1305
1445
  function isDateInArray(date, dates) {
1306
1446
  const dateStr = date.toDateString();
1307
1447
  return dates.some((d) => d.toDateString() === dateStr);
@@ -1325,43 +1465,30 @@ function DatePicker({
1325
1465
  showIcon = true,
1326
1466
  ...props
1327
1467
  }) {
1328
- const [isOpen, setIsOpen] = React7.useState(false);
1329
- const [inputValue, setInputValue] = React7.useState("");
1330
- const [selectedMonth, setSelectedMonth] = React7.useState(
1468
+ const [isOpen, setIsOpen] = React8.useState(false);
1469
+ const [selectedMonth, setSelectedMonth] = React8.useState(
1331
1470
  value || /* @__PURE__ */ new Date()
1332
1471
  );
1333
- const containerRef = React7.useRef(null);
1334
- const inputRef = React7.useRef(null);
1335
- React7.useEffect(() => {
1336
- setInputValue(formatDate(value, format));
1472
+ const containerRef = React8.useRef(null);
1473
+ const inputRef = React8.useRef(null);
1474
+ React8.useEffect(() => {
1337
1475
  if (value) {
1338
1476
  setSelectedMonth(value);
1339
1477
  }
1340
- }, [value, format]);
1478
+ }, [value]);
1341
1479
  const handleDateSelect = (date) => {
1342
1480
  onChange(date);
1343
1481
  setIsOpen(false);
1344
1482
  onBlur?.();
1345
1483
  };
1346
- const handleInputChange = (e) => {
1347
- const newValue = e.target.value;
1348
- setInputValue(newValue);
1349
- const parsedDate = parseDate(newValue, format);
1350
- if (parsedDate && !isNaN(parsedDate.getTime())) {
1351
- onChange(parsedDate);
1352
- } else if (newValue === "") {
1353
- onChange(null);
1354
- }
1355
- };
1356
1484
  const handleClear = (e) => {
1357
1485
  e.stopPropagation();
1358
1486
  onChange(null);
1359
- setInputValue("");
1360
1487
  inputRef.current?.focus();
1361
1488
  };
1362
1489
  const handleToggle = () => {
1363
1490
  if (disabled) return;
1364
- setIsOpen(!isOpen);
1491
+ setIsOpen((prev) => !prev);
1365
1492
  };
1366
1493
  const isDisabled = (date) => {
1367
1494
  if (minDate && date < minDate) return true;
@@ -1370,20 +1497,17 @@ function DatePicker({
1370
1497
  if (isDateDisabled && isDateDisabled(date)) return true;
1371
1498
  return false;
1372
1499
  };
1373
- React7.useEffect(() => {
1374
- const handleClickOutside = (event) => {
1375
- if (containerRef.current && !containerRef.current.contains(event.target)) {
1376
- setIsOpen(false);
1377
- onBlur?.();
1378
- }
1379
- };
1380
- if (isOpen) {
1381
- document.addEventListener("mousedown", handleClickOutside);
1382
- return () => {
1383
- document.removeEventListener("mousedown", handleClickOutside);
1384
- };
1385
- }
1500
+ const closeCalendar = React8.useCallback(() => {
1501
+ if (!isOpen) return;
1502
+ setIsOpen(false);
1503
+ onBlur?.();
1386
1504
  }, [isOpen, onBlur]);
1505
+ useOnClickOutside(containerRef, closeCalendar, "pointerdown", true);
1506
+ const dayGridStyle = {
1507
+ gridTemplateColumns: "repeat(7, minmax(0, 1fr))"
1508
+ };
1509
+ const hasValue = Boolean(value);
1510
+ const displayValue = formatDate(value, format);
1387
1511
  const renderCalendar = () => {
1388
1512
  const year = selectedMonth.getFullYear();
1389
1513
  const month = selectedMonth.getMonth();
@@ -1416,44 +1540,57 @@ function DatePicker({
1416
1540
  const handleNextMonth = () => {
1417
1541
  setSelectedMonth(new Date(year, month + 1, 1));
1418
1542
  };
1419
- return /* @__PURE__ */ React7.createElement("div", { role: "grid", "aria-label": "Calendar" }, /* @__PURE__ */ React7.createElement("div", { className: "flex items-center justify-between pb-2 border-b border-border" }, /* @__PURE__ */ React7.createElement(
1543
+ return /* @__PURE__ */ React8.createElement("div", { role: "grid", "aria-label": "Calendar", className: "w-[248px] max-w-full" }, /* @__PURE__ */ React8.createElement("div", { className: "flex items-center justify-between pb-3" }, /* @__PURE__ */ React8.createElement(
1420
1544
  "button",
1421
1545
  {
1422
1546
  type: "button",
1423
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
1547
+ className: "flex items-center justify-center h-8 w-8 rounded-md border-none bg-transparent hover:bg-muted cursor-pointer transition-colors",
1424
1548
  onClick: handlePrevMonth,
1425
1549
  "aria-label": "Previous month"
1426
1550
  },
1427
- "\u2190"
1428
- ), /* @__PURE__ */ React7.createElement("div", { className: "font-medium text-sm" }, `${monthNames[month]} ${year}`), /* @__PURE__ */ React7.createElement(
1551
+ "\u2039"
1552
+ ), /* @__PURE__ */ React8.createElement("div", { className: "font-medium text-sm" }, `${monthNames[month]} ${year}`), /* @__PURE__ */ React8.createElement(
1429
1553
  "button",
1430
1554
  {
1431
1555
  type: "button",
1432
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
1556
+ className: "flex items-center justify-center h-8 w-8 rounded-md border-none bg-transparent hover:bg-muted cursor-pointer transition-colors",
1433
1557
  onClick: handleNextMonth,
1434
1558
  "aria-label": "Next month"
1435
1559
  },
1436
- "\u2192"
1437
- )), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7.createElement(
1560
+ "\u203A"
1561
+ )), /* @__PURE__ */ React8.createElement(
1438
1562
  "div",
1439
1563
  {
1440
- key: day,
1441
- className: "flex items-center justify-center h-8 w-full text-xs font-medium"
1564
+ className: "grid gap-1 text-xs text-muted-foreground",
1565
+ style: dayGridStyle
1442
1566
  },
1443
- day
1444
- ))), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
1567
+ ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React8.createElement(
1568
+ "div",
1569
+ {
1570
+ key: day,
1571
+ className: "flex items-center justify-center h-8 w-8 font-medium"
1572
+ },
1573
+ day
1574
+ ))
1575
+ ), /* @__PURE__ */ React8.createElement("div", { className: "grid gap-1", style: dayGridStyle }, days.map((date, index) => {
1445
1576
  if (!date) {
1446
- return /* @__PURE__ */ React7.createElement("div", { key: `empty-${index}` });
1577
+ return /* @__PURE__ */ React8.createElement("div", { key: `empty-${index}`, className: "h-8 w-8" });
1447
1578
  }
1448
1579
  const isSelected = value && date.toDateString() === value.toDateString();
1449
1580
  const isToday = date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
1450
1581
  const disabled2 = isDisabled(date);
1451
- return /* @__PURE__ */ React7.createElement(
1582
+ return /* @__PURE__ */ React8.createElement(
1452
1583
  "button",
1453
1584
  {
1454
1585
  key: date.toISOString(),
1455
1586
  type: "button",
1456
- 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" : ""}`,
1587
+ className: cn(
1588
+ "flex items-center justify-center h-8 w-8 rounded-md border-none bg-transparent cursor-pointer text-sm transition-colors",
1589
+ "hover:bg-muted",
1590
+ isSelected && "bg-primary text-primary-foreground font-semibold",
1591
+ !isSelected && isToday && "border border-primary",
1592
+ disabled2 && "cursor-not-allowed opacity-50 pointer-events-none"
1593
+ ),
1457
1594
  onClick: () => !disabled2 && handleDateSelect(date),
1458
1595
  disabled: disabled2,
1459
1596
  "aria-label": formatDate(date, format)
@@ -1462,21 +1599,21 @@ function DatePicker({
1462
1599
  );
1463
1600
  })));
1464
1601
  };
1465
- const combinedClassName = `relative ${className}`.trim();
1466
- return /* @__PURE__ */ React7.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7.createElement(
1602
+ const combinedClassName = cn("relative", className);
1603
+ return /* @__PURE__ */ React8.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React8.createElement(
1467
1604
  "input",
1468
1605
  {
1469
1606
  type: "hidden",
1470
1607
  name,
1471
1608
  value: value ? value.toISOString() : ""
1472
1609
  }
1473
- ), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement(
1610
+ ), /* @__PURE__ */ React8.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React8.createElement(
1474
1611
  "span",
1475
1612
  {
1476
1613
  className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
1477
1614
  "aria-hidden": "true"
1478
1615
  },
1479
- /* @__PURE__ */ React7.createElement(
1616
+ /* @__PURE__ */ React8.createElement(
1480
1617
  "svg",
1481
1618
  {
1482
1619
  xmlns: "http://www.w3.org/2000/svg",
@@ -1489,16 +1626,24 @@ function DatePicker({
1489
1626
  strokeLinejoin: "round",
1490
1627
  strokeWidth: "2"
1491
1628
  },
1492
- /* @__PURE__ */ React7.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
1629
+ /* @__PURE__ */ React8.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" })
1493
1630
  )
1494
- ), /* @__PURE__ */ React7.createElement(
1631
+ ), /* @__PURE__ */ React8.createElement(
1495
1632
  "input",
1496
1633
  {
1497
1634
  ref: inputRef,
1498
1635
  type: "text",
1499
- 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" : ""}`,
1500
- value: inputValue,
1501
- onChange: handleInputChange,
1636
+ className: cn(
1637
+ "flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
1638
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
1639
+ "disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1640
+ INPUT_AUTOFILL_RESET_CLASSES,
1641
+ showIcon ? "pl-10" : "pl-3",
1642
+ clearable && value ? "pr-10" : "pr-3",
1643
+ !error && hasValue && "ring-2 ring-ring",
1644
+ error && "border-destructive ring-1 ring-destructive"
1645
+ ),
1646
+ value: displayValue,
1502
1647
  onClick: handleToggle,
1503
1648
  onBlur,
1504
1649
  disabled,
@@ -1509,7 +1654,7 @@ function DatePicker({
1509
1654
  "aria-required": required || props["aria-required"],
1510
1655
  readOnly: true
1511
1656
  }
1512
- ), clearable && value && !disabled && /* @__PURE__ */ React7.createElement(
1657
+ ), clearable && value && !disabled && /* @__PURE__ */ React8.createElement(
1513
1658
  "button",
1514
1659
  {
1515
1660
  type: "button",
@@ -1519,49 +1664,49 @@ function DatePicker({
1519
1664
  tabIndex: -1
1520
1665
  },
1521
1666
  "\u2715"
1522
- )), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, renderCalendar()));
1667
+ )), isOpen && !disabled && /* @__PURE__ */ React8.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()));
1523
1668
  }
1524
1669
  DatePicker.displayName = "DatePicker";
1525
- function parseTimeString(timeStr, use24Hour) {
1526
- if (!timeStr) return null;
1527
- try {
1528
- if (use24Hour) {
1529
- const [hourStr, minuteStr] = timeStr.split(":");
1530
- const hour24 = parseInt(hourStr, 10);
1531
- const minute = parseInt(minuteStr, 10);
1532
- if (isNaN(hour24) || isNaN(minute)) return null;
1533
- if (hour24 < 0 || hour24 > 23) return null;
1534
- if (minute < 0 || minute > 59) return null;
1535
- const period = hour24 >= 12 ? "PM" : "AM";
1536
- const hour = hour24 === 0 ? 12 : hour24 > 12 ? hour24 - 12 : hour24;
1537
- return { hour, minute, period };
1538
- } else {
1539
- const match = timeStr.match(/^(\d{1,2}):(\d{2})\s*(AM|PM)$/i);
1540
- if (!match) return null;
1541
- const hour = parseInt(match[1], 10);
1542
- const minute = parseInt(match[2], 10);
1543
- const period = match[3].toUpperCase();
1544
- if (hour < 1 || hour > 12) return null;
1545
- if (minute < 0 || minute > 59) return null;
1546
- return { hour, minute, period };
1670
+ function normalizeToNativeTime(value) {
1671
+ if (!value) return "";
1672
+ const twelveHourMatch = value.match(
1673
+ /^(\d{1,2}):(\d{2})(?::(\d{2}))?\s*(AM|PM)$/i
1674
+ );
1675
+ if (twelveHourMatch) {
1676
+ const rawHour = parseInt(twelveHourMatch[1], 10);
1677
+ const minute = parseInt(twelveHourMatch[2], 10);
1678
+ const period = twelveHourMatch[4].toUpperCase();
1679
+ if (Number.isNaN(rawHour) || Number.isNaN(minute) || rawHour < 1 || rawHour > 12 || minute < 0 || minute > 59) {
1680
+ return "";
1547
1681
  }
1548
- } catch {
1549
- return null;
1682
+ const normalizedHour = period === "PM" ? rawHour === 12 ? 12 : rawHour + 12 : rawHour === 12 ? 0 : rawHour;
1683
+ return `${String(normalizedHour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
1684
+ }
1685
+ const twentyFourHourMatch = value.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/);
1686
+ if (twentyFourHourMatch) {
1687
+ const hour = parseInt(twentyFourHourMatch[1], 10);
1688
+ const minute = parseInt(twentyFourHourMatch[2], 10);
1689
+ if (Number.isNaN(hour) || Number.isNaN(minute) || hour < 0 || hour > 23 || minute < 0 || minute > 59) {
1690
+ return "";
1691
+ }
1692
+ return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
1550
1693
  }
1694
+ return "";
1551
1695
  }
1552
- function formatTimeValue(time, use24Hour) {
1553
- if (!time) return "";
1696
+ function formatFromNativeTime(nativeValue, use24Hour) {
1697
+ if (!nativeValue) return "";
1698
+ const [hourValue, minuteValue] = nativeValue.split(":");
1699
+ const hour = parseInt(hourValue, 10);
1700
+ const minute = parseInt(minuteValue, 10);
1701
+ if (Number.isNaN(hour) || Number.isNaN(minute)) {
1702
+ return "";
1703
+ }
1554
1704
  if (use24Hour) {
1555
- let hour24 = time.hour;
1556
- if (time.period === "PM" && time.hour !== 12) {
1557
- hour24 = time.hour + 12;
1558
- } else if (time.period === "AM" && time.hour === 12) {
1559
- hour24 = 0;
1560
- }
1561
- return `${String(hour24).padStart(2, "0")}:${String(time.minute).padStart(2, "0")}`;
1562
- } else {
1563
- return `${time.hour}:${String(time.minute).padStart(2, "0")} ${time.period}`;
1705
+ return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
1564
1706
  }
1707
+ const period = hour >= 12 ? "PM" : "AM";
1708
+ const hour12 = hour % 12 || 12;
1709
+ return `${hour12}:${String(minute).padStart(2, "0")} ${period}`;
1565
1710
  }
1566
1711
  function TimePicker({
1567
1712
  name,
@@ -1579,188 +1724,87 @@ function TimePicker({
1579
1724
  showIcon = true,
1580
1725
  ...props
1581
1726
  }) {
1582
- const [isOpen, setIsOpen] = React7.useState(false);
1583
- const [timeValue, setTimeValue] = React7.useState(null);
1584
- const containerRef = React7.useRef(null);
1585
- const inputRef = React7.useRef(null);
1586
- React7.useEffect(() => {
1587
- const parsed = parseTimeString(value, use24Hour);
1588
- setTimeValue(parsed);
1589
- }, [value, use24Hour]);
1590
- const handleHourChange = (hour) => {
1591
- const newTime = {
1592
- hour,
1593
- minute: timeValue?.minute || 0,
1594
- period: timeValue?.period || "AM"
1595
- };
1596
- setTimeValue(newTime);
1597
- onChange(formatTimeValue(newTime, use24Hour));
1598
- };
1599
- const handleMinuteChange = (minute) => {
1600
- const newTime = {
1601
- hour: timeValue?.hour || 12,
1602
- minute,
1603
- period: timeValue?.period || "AM"
1604
- };
1605
- setTimeValue(newTime);
1606
- onChange(formatTimeValue(newTime, use24Hour));
1607
- };
1608
- const handlePeriodChange = (period) => {
1609
- const newTime = {
1610
- hour: timeValue?.hour || 12,
1611
- minute: timeValue?.minute || 0,
1612
- period
1613
- };
1614
- setTimeValue(newTime);
1615
- onChange(formatTimeValue(newTime, use24Hour));
1727
+ const inputRef = React8.useRef(null);
1728
+ const [nativeValue, setNativeValue] = React8.useState(
1729
+ normalizeToNativeTime(value)
1730
+ );
1731
+ React8.useEffect(() => {
1732
+ setNativeValue(normalizeToNativeTime(value));
1733
+ }, [value]);
1734
+ const handleChange = (e) => {
1735
+ const nextNativeValue = e.target.value;
1736
+ setNativeValue(nextNativeValue);
1737
+ onChange(formatFromNativeTime(nextNativeValue, use24Hour));
1616
1738
  };
1617
1739
  const handleClear = (e) => {
1618
1740
  e.stopPropagation();
1741
+ setNativeValue("");
1619
1742
  onChange("");
1620
- setTimeValue(null);
1621
1743
  inputRef.current?.focus();
1622
1744
  };
1623
- const handleToggle = () => {
1624
- if (disabled) return;
1625
- setIsOpen(!isOpen);
1626
- };
1627
- React7.useEffect(() => {
1628
- const handleClickOutside = (event) => {
1629
- if (containerRef.current && !containerRef.current.contains(event.target)) {
1630
- setIsOpen(false);
1631
- onBlur?.();
1632
- }
1633
- };
1634
- if (isOpen) {
1635
- document.addEventListener("mousedown", handleClickOutside);
1636
- return () => {
1637
- document.removeEventListener("mousedown", handleClickOutside);
1638
- };
1639
- }
1640
- }, [isOpen, onBlur]);
1641
- const hours = React7.useMemo(() => {
1642
- if (use24Hour) {
1643
- return Array.from({ length: 24 }, (_, i) => i);
1644
- } else {
1645
- return Array.from({ length: 12 }, (_, i) => i + 1);
1646
- }
1647
- }, [use24Hour]);
1648
- const minutes = React7.useMemo(() => {
1649
- const mins = [];
1650
- for (let i = 0; i < 60; i += minuteStep) {
1651
- mins.push(i);
1652
- }
1653
- return mins;
1654
- }, [minuteStep]);
1655
- const combinedClassName = `relative ${className}`.trim();
1656
- const displayValue = formatTimeValue(timeValue, use24Hour);
1657
- return /* @__PURE__ */ React7.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7.createElement(
1658
- "input",
1659
- {
1660
- type: "hidden",
1661
- name,
1662
- value
1663
- }
1664
- ), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement("span", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none", "aria-hidden": "true" }, /* @__PURE__ */ React7.createElement(
1665
- "svg",
1745
+ const hasValue = Boolean(value);
1746
+ const stepInSeconds = Math.max(1, minuteStep * 60);
1747
+ return /* @__PURE__ */ React8.createElement("div", { className: cn("relative", className) }, /* @__PURE__ */ React8.createElement("input", { type: "hidden", name, value }), /* @__PURE__ */ React8.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React8.createElement(
1748
+ "span",
1666
1749
  {
1667
- xmlns: "http://www.w3.org/2000/svg",
1668
- width: "18",
1669
- height: "18",
1670
- viewBox: "0 0 24 24",
1671
- fill: "none",
1672
- stroke: "currentColor",
1673
- strokeLinecap: "round",
1674
- strokeLinejoin: "round",
1675
- strokeWidth: "2"
1750
+ className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
1751
+ "aria-hidden": "true"
1676
1752
  },
1677
- /* @__PURE__ */ React7.createElement("circle", { cx: "12", cy: "12", r: "10" }),
1678
- /* @__PURE__ */ React7.createElement("path", { d: "M12 6v6l4 2" })
1679
- )), /* @__PURE__ */ React7.createElement(
1753
+ /* @__PURE__ */ React8.createElement(
1754
+ "svg",
1755
+ {
1756
+ xmlns: "http://www.w3.org/2000/svg",
1757
+ width: "18",
1758
+ height: "18",
1759
+ viewBox: "0 0 24 24",
1760
+ fill: "none",
1761
+ stroke: "currentColor",
1762
+ strokeLinecap: "round",
1763
+ strokeLinejoin: "round",
1764
+ strokeWidth: "2"
1765
+ },
1766
+ /* @__PURE__ */ React8.createElement("circle", { cx: "12", cy: "12", r: "10" }),
1767
+ /* @__PURE__ */ React8.createElement("path", { d: "M12 6v6l4 2" })
1768
+ )
1769
+ ), /* @__PURE__ */ React8.createElement(
1680
1770
  "input",
1681
1771
  {
1682
1772
  ref: inputRef,
1683
- type: "text",
1684
- className: `flex h-9 w-full rounded-md border border-input bg-transparent ${showIcon ? "pl-10" : "pl-3"} ${clearable && value ? "pr-10" : "pr-3"} py-1 text-base shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm ${error ? "border-red-500 ring-1 ring-red-500" : ""}`,
1685
- value: displayValue,
1686
- onClick: handleToggle,
1773
+ type: "time",
1774
+ className: cn(
1775
+ "flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
1776
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
1777
+ "disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1778
+ "appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none",
1779
+ INPUT_AUTOFILL_RESET_CLASSES,
1780
+ showIcon ? "pl-10" : "pl-3",
1781
+ clearable && value ? "pr-10" : "pr-3",
1782
+ !error && hasValue && "ring-2 ring-ring",
1783
+ error && "border-destructive ring-1 ring-destructive"
1784
+ ),
1785
+ value: nativeValue,
1786
+ onChange: handleChange,
1687
1787
  onBlur,
1688
1788
  disabled,
1689
1789
  required,
1790
+ step: stepInSeconds,
1690
1791
  placeholder,
1691
1792
  "aria-invalid": error || props["aria-invalid"] ? "true" : "false",
1692
1793
  "aria-describedby": props["aria-describedby"],
1693
1794
  "aria-required": required || props["aria-required"],
1694
- readOnly: true
1795
+ ...props
1695
1796
  }
1696
- ), clearable && value && !disabled && /* @__PURE__ */ React7.createElement(
1797
+ ), clearable && value && !disabled && /* @__PURE__ */ React8.createElement(
1697
1798
  "button",
1698
1799
  {
1699
1800
  type: "button",
1700
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors",
1801
+ className: "absolute right-3 top-1/2 -translate-y-1/2 transition-colors",
1701
1802
  onClick: handleClear,
1702
1803
  "aria-label": "Clear time",
1703
1804
  tabIndex: -1
1704
1805
  },
1705
1806
  "\u2715"
1706
- )), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, /* @__PURE__ */ React7.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium text-muted-foreground mb-2 text-center" }, use24Hour ? "Hour" : "Hour"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, hours.map((hour) => {
1707
- const displayHour = use24Hour ? hour : hour;
1708
- const isSelected = use24Hour ? timeValue?.hour === (hour === 0 ? 12 : hour > 12 ? hour - 12 : hour) && timeValue?.period === (hour >= 12 ? "PM" : "AM") : timeValue?.hour === hour;
1709
- return /* @__PURE__ */ React7.createElement(
1710
- "button",
1711
- {
1712
- key: hour,
1713
- type: "button",
1714
- className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-accent hover:text-accent-foreground ${isSelected ? "bg-primary text-primary-foreground font-semibold" : ""}`,
1715
- onClick: () => {
1716
- if (use24Hour) {
1717
- const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
1718
- const period = hour >= 12 ? "PM" : "AM";
1719
- const newTime = {
1720
- hour: hour12,
1721
- minute: timeValue?.minute || 0,
1722
- period
1723
- };
1724
- setTimeValue(newTime);
1725
- onChange(formatTimeValue(newTime, use24Hour));
1726
- } else {
1727
- handleHourChange(hour);
1728
- }
1729
- },
1730
- "aria-label": `${String(displayHour).padStart(2, "0")} hours`
1731
- },
1732
- String(displayHour).padStart(2, "0")
1733
- );
1734
- }))), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium text-muted-foreground mb-2 text-center" }, "Minute"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, minutes.map((minute) => {
1735
- const isSelected = timeValue?.minute === minute;
1736
- return /* @__PURE__ */ React7.createElement(
1737
- "button",
1738
- {
1739
- key: minute,
1740
- type: "button",
1741
- className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-accent hover:text-accent-foreground ${isSelected ? "bg-primary text-primary-foreground font-semibold" : ""}`,
1742
- onClick: () => handleMinuteChange(minute),
1743
- "aria-label": `${String(minute).padStart(2, "0")} minutes`
1744
- },
1745
- String(minute).padStart(2, "0")
1746
- );
1747
- }))), !use24Hour && /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col w-20" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium text-muted-foreground mb-2 text-center" }, "Period"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React7.createElement(
1748
- "button",
1749
- {
1750
- type: "button",
1751
- className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-accent hover:text-accent-foreground ${timeValue?.period === "AM" ? "bg-primary text-primary-foreground font-semibold" : ""}`,
1752
- onClick: () => handlePeriodChange("AM")
1753
- },
1754
- "AM"
1755
- ), /* @__PURE__ */ React7.createElement(
1756
- "button",
1757
- {
1758
- type: "button",
1759
- className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-accent hover:text-accent-foreground ${timeValue?.period === "PM" ? "bg-primary text-primary-foreground font-semibold" : ""}`,
1760
- onClick: () => handlePeriodChange("PM")
1761
- },
1762
- "PM"
1763
- ))))));
1807
+ )));
1764
1808
  }
1765
1809
  TimePicker.displayName = "TimePicker";
1766
1810
  function formatDate2(date, format) {
@@ -1780,6 +1824,9 @@ function isDateInRange(date, start, end) {
1780
1824
  const time = date.getTime();
1781
1825
  return time >= start.getTime() && time <= end.getTime();
1782
1826
  }
1827
+ function addMonths(date, delta) {
1828
+ return new Date(date.getFullYear(), date.getMonth() + delta, 1);
1829
+ }
1783
1830
  function DateRangePicker({
1784
1831
  name,
1785
1832
  value = { start: null, end: null },
@@ -1800,13 +1847,15 @@ function DateRangePicker({
1800
1847
  separator = " - ",
1801
1848
  ...props
1802
1849
  }) {
1803
- const [isOpen, setIsOpen] = React7.useState(false);
1804
- const [selectedMonth, setSelectedMonth] = React7.useState(value.start || /* @__PURE__ */ new Date());
1805
- const [rangeStart, setRangeStart] = React7.useState(value.start);
1806
- const [rangeEnd, setRangeEnd] = React7.useState(value.end);
1807
- const [hoverDate, setHoverDate] = React7.useState(null);
1808
- const containerRef = React7.useRef(null);
1809
- React7.useEffect(() => {
1850
+ const [isOpen, setIsOpen] = React8.useState(false);
1851
+ const [selectedMonth, setSelectedMonth] = React8.useState(
1852
+ value.start || /* @__PURE__ */ new Date()
1853
+ );
1854
+ const [rangeStart, setRangeStart] = React8.useState(value.start);
1855
+ const [rangeEnd, setRangeEnd] = React8.useState(value.end);
1856
+ const [hoverDate, setHoverDate] = React8.useState(null);
1857
+ const containerRef = React8.useRef(null);
1858
+ React8.useEffect(() => {
1810
1859
  setRangeStart(value.start);
1811
1860
  setRangeEnd(value.end);
1812
1861
  if (value.start) {
@@ -1840,7 +1889,7 @@ function DateRangePicker({
1840
1889
  };
1841
1890
  const handleToggle = () => {
1842
1891
  if (disabled) return;
1843
- setIsOpen(!isOpen);
1892
+ setIsOpen((prev) => !prev);
1844
1893
  };
1845
1894
  const isDisabled = (date) => {
1846
1895
  if (minDate && date < minDate) return true;
@@ -1849,23 +1898,36 @@ function DateRangePicker({
1849
1898
  if (isDateDisabled && isDateDisabled(date)) return true;
1850
1899
  return false;
1851
1900
  };
1852
- React7.useEffect(() => {
1853
- const handleClickOutside = (event) => {
1854
- if (containerRef.current && !containerRef.current.contains(event.target)) {
1855
- setIsOpen(false);
1856
- onBlur?.();
1857
- }
1858
- };
1859
- if (isOpen) {
1860
- document.addEventListener("mousedown", handleClickOutside);
1861
- return () => {
1862
- document.removeEventListener("mousedown", handleClickOutside);
1863
- };
1864
- }
1901
+ const closeCalendar = React8.useCallback(() => {
1902
+ if (!isOpen) return;
1903
+ setIsOpen(false);
1904
+ onBlur?.();
1865
1905
  }, [isOpen, onBlur]);
1866
- const renderCalendar = () => {
1867
- const year = selectedMonth.getFullYear();
1868
- const month = selectedMonth.getMonth();
1906
+ useOnClickOutside(containerRef, closeCalendar, "pointerdown", true);
1907
+ const dayGridStyle = {
1908
+ gridTemplateColumns: "repeat(7, minmax(0, 1fr))"
1909
+ };
1910
+ const monthsGridStyle = {
1911
+ gridTemplateColumns: "repeat(auto-fit, minmax(240px, 1fr))"
1912
+ };
1913
+ const monthNames = [
1914
+ "January",
1915
+ "February",
1916
+ "March",
1917
+ "April",
1918
+ "May",
1919
+ "June",
1920
+ "July",
1921
+ "August",
1922
+ "September",
1923
+ "October",
1924
+ "November",
1925
+ "December"
1926
+ ];
1927
+ const hasValue = Boolean(rangeStart || rangeEnd);
1928
+ const renderMonth = (monthDate, controls) => {
1929
+ const year = monthDate.getFullYear();
1930
+ const month = monthDate.getMonth();
1869
1931
  const daysInMonth = new Date(year, month + 1, 0).getDate();
1870
1932
  const firstDayOfMonth = new Date(year, month, 1).getDay();
1871
1933
  const days = [];
@@ -1875,60 +1937,65 @@ function DateRangePicker({
1875
1937
  for (let day = 1; day <= daysInMonth; day++) {
1876
1938
  days.push(new Date(year, month, day));
1877
1939
  }
1878
- const monthNames = [
1879
- "January",
1880
- "February",
1881
- "March",
1882
- "April",
1883
- "May",
1884
- "June",
1885
- "July",
1886
- "August",
1887
- "September",
1888
- "October",
1889
- "November",
1890
- "December"
1891
- ];
1892
- const handlePrevMonth = () => {
1893
- setSelectedMonth(new Date(year, month - 1, 1));
1894
- };
1895
- const handleNextMonth = () => {
1896
- setSelectedMonth(new Date(year, month + 1, 1));
1897
- };
1898
- return /* @__PURE__ */ React7.createElement("div", { role: "grid", "aria-label": "Calendar" }, /* @__PURE__ */ React7.createElement("div", { className: "flex items-center justify-between pb-2 border-b border-border" }, /* @__PURE__ */ React7.createElement(
1940
+ return /* @__PURE__ */ React8.createElement("div", { className: "w-[240px] max-w-full" }, /* @__PURE__ */ React8.createElement("div", { className: "flex items-center justify-between pb-3" }, controls?.prev ? /* @__PURE__ */ React8.createElement(
1899
1941
  "button",
1900
1942
  {
1901
1943
  type: "button",
1902
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent cursor-pointer",
1903
- onClick: handlePrevMonth,
1944
+ className: "flex items-center justify-center h-8 w-8 rounded-md border-none bg-transparent hover:bg-muted cursor-pointer transition-colors",
1945
+ onClick: () => setSelectedMonth((prev) => addMonths(prev, -1)),
1904
1946
  "aria-label": "Previous month"
1905
1947
  },
1906
- "\u2190"
1907
- ), /* @__PURE__ */ React7.createElement("div", { className: "font-medium text-sm" }, `${monthNames[month]} ${year}`), /* @__PURE__ */ React7.createElement(
1948
+ "\u2039"
1949
+ ) : /* @__PURE__ */ React8.createElement("div", { className: "h-8 w-8", "aria-hidden": "true" }), /* @__PURE__ */ React8.createElement("div", { className: "font-medium text-sm" }, `${monthNames[month]} ${year}`), controls?.next ? /* @__PURE__ */ React8.createElement(
1908
1950
  "button",
1909
1951
  {
1910
1952
  type: "button",
1911
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent cursor-pointer",
1912
- onClick: handleNextMonth,
1953
+ className: "flex items-center justify-center h-8 w-8 rounded-md border-none bg-transparent hover:bg-muted cursor-pointer transition-colors",
1954
+ onClick: () => setSelectedMonth((prev) => addMonths(prev, 1)),
1913
1955
  "aria-label": "Next month"
1914
1956
  },
1915
- "\u2192"
1916
- )), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7.createElement("div", { key: day, className: "flex items-center justify-center h-8 w-full text-xs text-muted-foreground font-medium" }, day))), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
1957
+ "\u203A"
1958
+ ) : /* @__PURE__ */ React8.createElement("div", { className: "h-8 w-8", "aria-hidden": "true" })), /* @__PURE__ */ React8.createElement(
1959
+ "div",
1960
+ {
1961
+ className: "grid gap-1 text-xs text-muted-foreground",
1962
+ style: dayGridStyle
1963
+ },
1964
+ ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React8.createElement(
1965
+ "div",
1966
+ {
1967
+ key: `${month}-${day}`,
1968
+ className: "flex items-center justify-center h-8 w-8 font-medium"
1969
+ },
1970
+ day
1971
+ ))
1972
+ ), /* @__PURE__ */ React8.createElement("div", { className: "grid gap-1", style: dayGridStyle }, days.map((date, index) => {
1917
1973
  if (!date) {
1918
- return /* @__PURE__ */ React7.createElement("div", { key: `empty-${index}` });
1974
+ return /* @__PURE__ */ React8.createElement("div", { key: `empty-${month}-${index}`, className: "h-8 w-8" });
1919
1975
  }
1920
1976
  const isStart = rangeStart && date.toDateString() === rangeStart.toDateString();
1921
1977
  const isEnd = rangeEnd && date.toDateString() === rangeEnd.toDateString();
1978
+ const isRangeEndpoint = Boolean(isStart || isEnd);
1922
1979
  const isInRange = rangeStart && rangeEnd && isDateInRange(date, rangeStart, rangeEnd);
1923
1980
  const isInHoverRange = rangeStart && !rangeEnd && hoverDate && (date >= rangeStart && date <= hoverDate || date <= rangeStart && date >= hoverDate);
1981
+ const isRangeHighlight = Boolean(
1982
+ (isInRange || isInHoverRange) && !isRangeEndpoint
1983
+ );
1924
1984
  const isToday = date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
1925
1985
  const disabled2 = isDisabled(date);
1926
- return /* @__PURE__ */ React7.createElement(
1986
+ return /* @__PURE__ */ React8.createElement(
1927
1987
  "button",
1928
1988
  {
1929
1989
  key: date.toISOString(),
1930
1990
  type: "button",
1931
- className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-accent hover:text-accent-foreground ${isStart || isEnd ? "bg-primary text-primary-foreground font-semibold" : ""} ${isInRange || isInHoverRange ? "bg-accent/50" : ""} ${isToday ? "border border-primary" : ""} ${disabled2 ? "cursor-not-allowed opacity-50 pointer-events-none" : ""}`,
1991
+ className: cn(
1992
+ "flex items-center justify-center h-8 w-8 rounded-md border-none bg-transparent cursor-pointer text-sm transition-colors",
1993
+ "hover:bg-muted",
1994
+ isRangeEndpoint && "bg-primary text-primary-foreground font-semibold",
1995
+ isRangeHighlight && "bg-muted",
1996
+ !isRangeEndpoint && !isRangeHighlight && isToday && "border border-primary",
1997
+ disabled2 && "cursor-not-allowed opacity-50 pointer-events-none"
1998
+ ),
1932
1999
  onClick: () => !disabled2 && handleDateSelect(date),
1933
2000
  onMouseEnter: () => setHoverDate(date),
1934
2001
  onMouseLeave: () => setHoverDate(null),
@@ -1939,41 +2006,57 @@ function DateRangePicker({
1939
2006
  );
1940
2007
  })));
1941
2008
  };
1942
- const combinedClassName = `relative ${className}`.trim();
2009
+ const combinedClassName = cn("relative", className);
1943
2010
  const displayValue = rangeStart && rangeEnd ? `${formatDate2(rangeStart, format)}${separator}${formatDate2(rangeEnd, format)}` : rangeStart ? formatDate2(rangeStart, format) : "";
1944
- return /* @__PURE__ */ React7.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7.createElement(
2011
+ return /* @__PURE__ */ React8.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React8.createElement(
1945
2012
  "input",
1946
2013
  {
1947
2014
  type: "hidden",
1948
2015
  name: `${name}[start]`,
1949
2016
  value: rangeStart ? rangeStart.toISOString() : ""
1950
2017
  }
1951
- ), /* @__PURE__ */ React7.createElement(
2018
+ ), /* @__PURE__ */ React8.createElement(
1952
2019
  "input",
1953
2020
  {
1954
2021
  type: "hidden",
1955
2022
  name: `${name}[end]`,
1956
2023
  value: rangeEnd ? rangeEnd.toISOString() : ""
1957
2024
  }
1958
- ), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement("span", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none", "aria-hidden": "true" }, /* @__PURE__ */ React7.createElement(
1959
- "svg",
2025
+ ), /* @__PURE__ */ React8.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React8.createElement(
2026
+ "span",
1960
2027
  {
1961
- xmlns: "http://www.w3.org/2000/svg",
1962
- width: "18",
1963
- height: "18",
1964
- viewBox: "0 0 24 24",
1965
- fill: "none",
1966
- stroke: "currentColor",
1967
- strokeLinecap: "round",
1968
- strokeLinejoin: "round",
1969
- strokeWidth: "2"
2028
+ className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
2029
+ "aria-hidden": "true"
1970
2030
  },
1971
- /* @__PURE__ */ React7.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
1972
- )), /* @__PURE__ */ React7.createElement(
2031
+ /* @__PURE__ */ React8.createElement(
2032
+ "svg",
2033
+ {
2034
+ xmlns: "http://www.w3.org/2000/svg",
2035
+ width: "18",
2036
+ height: "18",
2037
+ viewBox: "0 0 24 24",
2038
+ fill: "none",
2039
+ stroke: "currentColor",
2040
+ strokeLinecap: "round",
2041
+ strokeLinejoin: "round",
2042
+ strokeWidth: "2"
2043
+ },
2044
+ /* @__PURE__ */ React8.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" })
2045
+ )
2046
+ ), /* @__PURE__ */ React8.createElement(
1973
2047
  "input",
1974
2048
  {
1975
2049
  type: "text",
1976
- className: `flex h-9 w-full rounded-md border border-input bg-transparent ${showIcon ? "pl-10" : "pl-3"} ${clearable && (rangeStart || rangeEnd) ? "pr-10" : "pr-3"} py-1 text-base shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm ${error ? "border-red-500 ring-1 ring-red-500" : ""}`,
2050
+ className: cn(
2051
+ "flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
2052
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
2053
+ "disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
2054
+ INPUT_AUTOFILL_RESET_CLASSES,
2055
+ showIcon ? "pl-10" : "pl-3",
2056
+ clearable && (rangeStart || rangeEnd) ? "pr-10" : "pr-3",
2057
+ !error && hasValue && "ring-2 ring-ring",
2058
+ error && "border-destructive ring-1 ring-destructive"
2059
+ ),
1977
2060
  value: displayValue,
1978
2061
  onClick: handleToggle,
1979
2062
  onBlur,
@@ -1985,17 +2068,17 @@ function DateRangePicker({
1985
2068
  "aria-required": required || props["aria-required"],
1986
2069
  readOnly: true
1987
2070
  }
1988
- ), clearable && (rangeStart || rangeEnd) && !disabled && /* @__PURE__ */ React7.createElement(
2071
+ ), clearable && (rangeStart || rangeEnd) && !disabled && /* @__PURE__ */ React8.createElement(
1989
2072
  "button",
1990
2073
  {
1991
2074
  type: "button",
1992
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors",
2075
+ className: "absolute right-3 top-1/2 -translate-y-1/2 transition-colors",
1993
2076
  onClick: handleClear,
1994
2077
  "aria-label": "Clear date range",
1995
2078
  tabIndex: -1
1996
2079
  },
1997
2080
  "\u2715"
1998
- )), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, renderCalendar(), rangeStart && !rangeEnd && /* @__PURE__ */ React7.createElement("div", { className: "text-xs text-muted-foreground text-center pt-2 border-t border-border mt-2" }, "Select end date")));
2081
+ )), isOpen && !disabled && /* @__PURE__ */ React8.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.createElement("div", { role: "grid", "aria-label": "Calendar" }, /* @__PURE__ */ React8.createElement("div", { className: "grid gap-4", style: monthsGridStyle }, renderMonth(selectedMonth, { prev: true }), renderMonth(addMonths(selectedMonth, 1), { next: true }))), rangeStart && !rangeEnd && /* @__PURE__ */ React8.createElement("div", { className: "text-xs text-center pt-2 border-t border-border mt-2" }, "Select end date")));
1999
2082
  }
2000
2083
  DateRangePicker.displayName = "DateRangePicker";
2001
2084
  function htmlToMarkdown(html) {
@@ -2051,18 +2134,26 @@ function RichTextEditor({
2051
2134
  className = "",
2052
2135
  mode = "wysiwyg",
2053
2136
  allowModeSwitch = false,
2054
- placeholder = "Start typing...",
2137
+ placeholder = "Your message...",
2055
2138
  minHeight = "200px",
2056
2139
  maxHeight,
2057
2140
  showToolbar = true,
2058
- toolbarButtons = ["bold", "italic", "underline", "heading", "bulletList", "orderedList", "link"],
2141
+ toolbarButtons = [
2142
+ "bold",
2143
+ "italic",
2144
+ "underline",
2145
+ "heading",
2146
+ "bulletList",
2147
+ "orderedList",
2148
+ "link"
2149
+ ],
2059
2150
  ...props
2060
2151
  }) {
2061
- const [currentMode, setCurrentMode] = React7.useState(mode);
2062
- const [content, setContent] = React7.useState(value);
2063
- const editorRef = React7.useRef(null);
2064
- const textareaRef = React7.useRef(null);
2065
- React7.useEffect(() => {
2152
+ const [currentMode, setCurrentMode] = React8.useState(mode);
2153
+ const [content, setContent] = React8.useState(value);
2154
+ const editorRef = React8.useRef(null);
2155
+ const textareaRef = React8.useRef(null);
2156
+ React8.useEffect(() => {
2066
2157
  setContent(value);
2067
2158
  if (currentMode === "wysiwyg" && editorRef.current) {
2068
2159
  editorRef.current.innerHTML = value;
@@ -2150,21 +2241,32 @@ function RichTextEditor({
2150
2241
  }
2151
2242
  }
2152
2243
  };
2153
- const combinedClassName = `rounded-md border border-input ${error ? "border-red-500 ring-1 ring-red-500" : ""} ${disabled ? "opacity-50 cursor-not-allowed" : ""} ${className}`.trim();
2244
+ const hasValue = React8.useMemo(() => {
2245
+ if (!content) return false;
2246
+ const stripped = content.replace(/<[^>]+>/g, "").trim();
2247
+ return stripped.length > 0;
2248
+ }, [content]);
2249
+ const combinedClassName = cn(
2250
+ "rounded-md border border-input",
2251
+ !error && hasValue && "ring-2 ring-ring",
2252
+ error && "border-destructive ring-1 ring-destructive",
2253
+ disabled && "opacity-50 cursor-not-allowed",
2254
+ className
2255
+ );
2154
2256
  const editorStyle = {
2155
2257
  minHeight,
2156
2258
  maxHeight,
2157
2259
  overflowY: maxHeight ? "auto" : void 0
2158
2260
  };
2159
- return /* @__PURE__ */ React7.createElement("div", { className: combinedClassName }, /* @__PURE__ */ React7.createElement("input", { type: "hidden", name, value: content }), showToolbar && /* @__PURE__ */ React7.createElement("div", { className: "flex items-center justify-between p-2 border-b border-border bg-muted/50" }, /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-1" }, toolbarButtons.map((buttonName) => {
2261
+ return /* @__PURE__ */ React8.createElement("div", { className: combinedClassName }, /* @__PURE__ */ React8.createElement("input", { type: "hidden", name, value: content }), showToolbar && /* @__PURE__ */ React8.createElement("div", { className: "flex items-center justify-between p-2 border-b border-border bg-muted/50" }, /* @__PURE__ */ React8.createElement("div", { className: "flex items-center gap-1" }, toolbarButtons.map((buttonName) => {
2160
2262
  const button = toolbarConfig[buttonName];
2161
2263
  if (!button) return null;
2162
- return /* @__PURE__ */ React7.createElement(
2264
+ return /* @__PURE__ */ React8.createElement(
2163
2265
  "button",
2164
2266
  {
2165
2267
  key: buttonName,
2166
2268
  type: "button",
2167
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent text-muted-foreground hover:text-foreground cursor-pointer transition-colors disabled:cursor-not-allowed disabled:opacity-50",
2269
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-muted cursor-pointer transition-colors disabled:cursor-not-allowed disabled:opacity-50",
2168
2270
  onClick: () => editorRef.current && button.action(editorRef.current),
2169
2271
  title: button.title,
2170
2272
  disabled: disabled || currentMode === "markdown",
@@ -2172,22 +2274,22 @@ function RichTextEditor({
2172
2274
  },
2173
2275
  button.icon
2174
2276
  );
2175
- })), allowModeSwitch && /* @__PURE__ */ React7.createElement(
2277
+ })), allowModeSwitch && /* @__PURE__ */ React8.createElement(
2176
2278
  "button",
2177
2279
  {
2178
2280
  type: "button",
2179
- className: "flex items-center justify-center h-8 px-3 rounded border-none bg-transparent hover:bg-accent text-xs font-medium text-muted-foreground hover:text-foreground cursor-pointer transition-colors disabled:cursor-not-allowed disabled:opacity-50",
2281
+ className: "flex items-center justify-center h-8 px-3 rounded border-none bg-transparent hover:bg-muted text-xs font-medium cursor-pointer transition-colors disabled:cursor-not-allowed disabled:opacity-50",
2180
2282
  onClick: handleModeToggle,
2181
2283
  disabled,
2182
2284
  title: `Switch to ${currentMode === "wysiwyg" ? "Markdown" : "WYSIWYG"}`,
2183
2285
  "aria-label": `Switch to ${currentMode === "wysiwyg" ? "Markdown" : "WYSIWYG"}`
2184
2286
  },
2185
2287
  currentMode === "wysiwyg" ? "MD" : "WYSIWYG"
2186
- )), /* @__PURE__ */ React7.createElement("div", { style: editorStyle }, currentMode === "wysiwyg" ? /* @__PURE__ */ React7.createElement(
2288
+ )), /* @__PURE__ */ React8.createElement("div", { style: editorStyle }, currentMode === "wysiwyg" ? /* @__PURE__ */ React8.createElement(
2187
2289
  "div",
2188
2290
  {
2189
2291
  ref: editorRef,
2190
- className: "w-full p-3 text-base md:text-sm outline-none bg-transparent focus-visible:outline-none [&:empty:before]:content-[attr(data-placeholder)] [&:empty:before]:text-muted-foreground",
2292
+ className: "w-full p-3 text-base md:text-sm outline-none bg-transparent focus-visible:outline-none [&:empty:before]:content-[attr(data-placeholder)]",
2191
2293
  role: "textbox",
2192
2294
  contentEditable: !disabled,
2193
2295
  onInput: handleWysiwygChange,
@@ -2198,11 +2300,14 @@ function RichTextEditor({
2198
2300
  "aria-required": required || props["aria-required"],
2199
2301
  suppressContentEditableWarning: true
2200
2302
  }
2201
- ) : /* @__PURE__ */ React7.createElement(
2303
+ ) : /* @__PURE__ */ React8.createElement(
2202
2304
  "textarea",
2203
2305
  {
2204
2306
  ref: textareaRef,
2205
- className: "w-full p-3 text-base md:text-sm outline-none bg-transparent resize-none focus-visible:outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
2307
+ className: cn(
2308
+ "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",
2309
+ INPUT_AUTOFILL_RESET_CLASSES
2310
+ ),
2206
2311
  value: content,
2207
2312
  onChange: handleMarkdownChange,
2208
2313
  onBlur,