@page-speed/forms 0.4.1 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/inputs.cjs CHANGED
@@ -1,6 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var React7 = require('react');
4
+ var clsx = require('clsx');
5
+ var tailwindMerge = require('tailwind-merge');
4
6
 
5
7
  function _interopNamespace(e) {
6
8
  if (e && e.__esModule) return e;
@@ -43,7 +45,7 @@ function TextInput({
43
45
  const handleBlur = () => {
44
46
  onBlur?.();
45
47
  };
46
- 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";
48
+ const baseClassName = "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm";
47
49
  const errorClassName = error ? "border-red-500 ring-1 ring-red-500" : "";
48
50
  const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
49
51
  return /* @__PURE__ */ React7__namespace.createElement(
@@ -90,7 +92,7 @@ function TextArea({
90
92
  const handleBlur = () => {
91
93
  onBlur?.();
92
94
  };
93
- 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";
95
+ const baseClassName = "flex min-h-20 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm";
94
96
  const errorClassName = error ? "border-red-500 ring-1 ring-red-500" : "";
95
97
  const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
96
98
  return /* @__PURE__ */ React7__namespace.createElement(
@@ -117,6 +119,11 @@ function TextArea({
117
119
  );
118
120
  }
119
121
  TextArea.displayName = "TextArea";
122
+ function cn(...inputs) {
123
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
124
+ }
125
+
126
+ // src/inputs/Checkbox.tsx
120
127
  function Checkbox({
121
128
  name,
122
129
  value,
@@ -129,6 +136,7 @@ function Checkbox({
129
136
  indeterminate = false,
130
137
  label,
131
138
  description,
139
+ checkboxVariant = "boxed",
132
140
  ...props
133
141
  }) {
134
142
  const inputRef = React7__namespace.useRef(null);
@@ -144,36 +152,92 @@ function Checkbox({
144
152
  const handleBlur = () => {
145
153
  onBlur?.();
146
154
  };
147
- const checkbox = /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative inline-flex" }, /* @__PURE__ */ React7__namespace.createElement(
148
- "input",
155
+ const isActive = value || indeterminate && !value;
156
+ const checkbox = /* @__PURE__ */ React7__namespace.createElement(
157
+ "div",
149
158
  {
150
- ref: inputRef,
151
- type: "checkbox",
152
- id: checkboxId,
153
- name,
154
- checked: value,
155
- onChange: handleChange,
156
- onBlur: handleBlur,
157
- disabled,
158
- required,
159
- className: `peer relative flex size-4 shrink-0 appearance-none items-center justify-center rounded-lg border border-input bg-transparent outline-none transition-colors focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 ${error ? "border-destructive ring-3 ring-destructive/20" : ""} ${value ? "bg-primary border-primary" : ""} ${className}`,
160
- "aria-invalid": error || props["aria-invalid"],
161
- "aria-describedby": description ? `${checkboxId}-description` : props["aria-describedby"],
162
- "aria-required": required || props["aria-required"],
163
- ...props
164
- }
165
- ), value && /* @__PURE__ */ React7__namespace.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary-foreground" }, /* @__PURE__ */ React7__namespace.createElement("svg", { className: "size-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3" }, /* @__PURE__ */ React7__namespace.createElement("polyline", { points: "20 6 9 17 4 12" }))), indeterminate && !value && /* @__PURE__ */ React7__namespace.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary" }, /* @__PURE__ */ React7__namespace.createElement("svg", { className: "size-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3" }, /* @__PURE__ */ React7__namespace.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" }))));
159
+ className: cn(
160
+ "relative inline-flex items-center justify-center",
161
+ !label && className
162
+ )
163
+ },
164
+ /* @__PURE__ */ React7__namespace.createElement(
165
+ "input",
166
+ {
167
+ ref: inputRef,
168
+ type: "checkbox",
169
+ id: checkboxId,
170
+ name,
171
+ checked: value,
172
+ onChange: handleChange,
173
+ onBlur: handleBlur,
174
+ disabled,
175
+ required,
176
+ className: "peer sr-only",
177
+ "aria-invalid": error || props["aria-invalid"],
178
+ "aria-describedby": description ? `${checkboxId}-description` : props["aria-describedby"],
179
+ "aria-required": required || props["aria-required"],
180
+ ...props
181
+ }
182
+ ),
183
+ /* @__PURE__ */ React7__namespace.createElement(
184
+ "div",
185
+ {
186
+ className: cn(
187
+ "flex shrink-0 items-center justify-center rounded-full border-2 transition-colors size-6",
188
+ !error && isActive && "border-primary bg-primary text-primary-foreground",
189
+ !error && !isActive && "border-input bg-transparent",
190
+ error && isActive && "border-destructive bg-destructive text-destructive-foreground",
191
+ error && !isActive && "border-destructive bg-transparent",
192
+ disabled && "opacity-50",
193
+ "peer-focus-visible:ring-2 peer-focus-visible:ring-ring/50 peer-focus-visible:ring-offset-1"
194
+ )
195
+ },
196
+ value && /* @__PURE__ */ React7__namespace.createElement(
197
+ "svg",
198
+ {
199
+ className: "size-3.5",
200
+ viewBox: "0 0 24 24",
201
+ fill: "none",
202
+ stroke: "currentColor",
203
+ strokeWidth: "3",
204
+ strokeLinecap: "round",
205
+ strokeLinejoin: "round"
206
+ },
207
+ /* @__PURE__ */ React7__namespace.createElement("polyline", { points: "20 6 9 17 4 12" })
208
+ ),
209
+ indeterminate && !value && /* @__PURE__ */ React7__namespace.createElement(
210
+ "svg",
211
+ {
212
+ className: "size-3.5",
213
+ viewBox: "0 0 24 24",
214
+ fill: "none",
215
+ stroke: "currentColor",
216
+ strokeWidth: "3",
217
+ strokeLinecap: "round",
218
+ strokeLinejoin: "round"
219
+ },
220
+ /* @__PURE__ */ React7__namespace.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
221
+ )
222
+ )
223
+ );
166
224
  if (label) {
167
225
  return /* @__PURE__ */ React7__namespace.createElement(
168
226
  "label",
169
227
  {
170
- className: `flex w-fit gap-2 items-center ${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}`,
228
+ className: cn(
229
+ "w-full h-full flex gap-3 p-3 duration-200",
230
+ checkboxVariant === "boxed" && "border rounded-lg hover:ring-2",
231
+ checkboxVariant === "boxed" && value && "ring-2",
232
+ disabled ? "opacity-50 cursor-not-allowed hover:ring-0" : "cursor-pointer",
233
+ className
234
+ ),
171
235
  htmlFor: checkboxId
172
236
  },
173
- /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, checkbox, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center gap-2 text-sm font-medium" }, label), description && /* @__PURE__ */ React7__namespace.createElement(
237
+ /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex w-full flex-row gap-2" }, checkbox, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-sm font-medium" }, label), description && /* @__PURE__ */ React7__namespace.createElement(
174
238
  "p",
175
239
  {
176
- className: "text-muted-foreground text-sm",
240
+ className: "text-xs opacity-75",
177
241
  id: `${checkboxId}-description`
178
242
  },
179
243
  description
@@ -211,6 +275,18 @@ function CheckboxGroup({
211
275
  ).length;
212
276
  const allSelected = selectedEnabledCount === enabledOptions.length;
213
277
  const someSelected = selectedEnabledCount > 0 && !allSelected;
278
+ const checkboxVariant = React7__namespace.useMemo(() => {
279
+ if (options.some((opt) => opt.description)) {
280
+ return "boxed";
281
+ }
282
+ return "inline";
283
+ }, [options]);
284
+ const countableValue = React7__namespace.useMemo(() => {
285
+ if (value?.length > 0) {
286
+ return value.length;
287
+ }
288
+ return 0;
289
+ }, [value]);
214
290
  const handleChange = (optionValue, checked) => {
215
291
  const newValues = checked ? [...value, optionValue] : value.filter((v) => v !== optionValue);
216
292
  if (maxSelections && checked && newValues.length > maxSelections) {
@@ -229,9 +305,14 @@ function CheckboxGroup({
229
305
  const handleBlur = () => {
230
306
  onBlur?.();
231
307
  };
232
- const layoutClass = layout === "inline" ? "flex flex-row flex-wrap gap-4" : layout === "grid" ? `grid gap-3` : "flex flex-col gap-3";
233
- const containerClass = `w-full ${layoutClass} ${className}`.trim();
234
- const maxReached = Boolean(maxSelections && value.length >= maxSelections);
308
+ const maxReached = Boolean(maxSelections && countableValue >= maxSelections);
309
+ const containerClass = cn(
310
+ "w-full gap-3",
311
+ layout === "stacked" && "flex flex-col",
312
+ layout === "inline" && "flex flex-row flex-wrap",
313
+ layout === "grid" && "grid",
314
+ className
315
+ );
235
316
  return /* @__PURE__ */ React7__namespace.createElement(
236
317
  "div",
237
318
  {
@@ -245,68 +326,56 @@ function CheckboxGroup({
245
326
  gridTemplateColumns: `repeat(${gridColumns}, 1fr)`
246
327
  } : void 0
247
328
  },
248
- label && /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-sm font-medium" }, label),
249
- description && /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-muted-foreground text-sm" }, description),
329
+ label ? /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-sm font-medium" }, label) : null,
330
+ description ? /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-xs opacity-70" }, description) : null,
250
331
  showSelectAll && enabledOptions.length > 0 && /* @__PURE__ */ React7__namespace.createElement(
251
- "label",
332
+ Checkbox,
252
333
  {
253
- className: `flex w-fit gap-2 items-center ${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}`
254
- },
255
- /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative inline-flex" }, /* @__PURE__ */ React7__namespace.createElement(
256
- "input",
257
- {
258
- type: "checkbox",
259
- checked: allSelected,
260
- ref: (input) => {
261
- if (input) {
262
- input.indeterminate = someSelected;
263
- }
264
- },
265
- onChange: (e) => handleSelectAll(e.target.checked),
266
- onBlur: handleBlur,
267
- disabled,
268
- className: "peer relative flex size-4 shrink-0 appearance-none items-center justify-center rounded-lg border border-input bg-transparent outline-none transition-colors focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50",
269
- "aria-label": selectAllLabel
270
- }
271
- ), allSelected && /* @__PURE__ */ React7__namespace.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary-foreground" }, /* @__PURE__ */ React7__namespace.createElement("svg", { className: "size-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3" }, /* @__PURE__ */ React7__namespace.createElement("polyline", { points: "20 6 9 17 4 12" }))), someSelected && !allSelected && /* @__PURE__ */ React7__namespace.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary" }, /* @__PURE__ */ React7__namespace.createElement("svg", { className: "size-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3" }, /* @__PURE__ */ React7__namespace.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" })))), /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-sm font-medium" }, selectAllLabel))
334
+ name: `${name}-select-all`,
335
+ id: `${name}-select-all`,
336
+ value: allSelected,
337
+ onChange: handleSelectAll,
338
+ onBlur: handleBlur,
339
+ indeterminate: someSelected,
340
+ label: selectAllLabel,
341
+ checkboxVariant: "inline",
342
+ disabled,
343
+ "aria-label": selectAllLabel
344
+ }
272
345
  ),
273
346
  options.map((option) => {
274
347
  const isChecked = value.includes(option.value);
275
348
  const isDisabled = disabled || option.disabled || maxReached && !isChecked;
276
- const checkboxId = `${name}-${option.value}`;
277
349
  return /* @__PURE__ */ React7__namespace.createElement(
278
- "label",
350
+ Checkbox,
279
351
  {
280
352
  key: option.value,
281
- className: `flex w-fit gap-2 items-center ${isDisabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}`,
282
- htmlFor: checkboxId
283
- },
284
- /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative inline-flex" }, /* @__PURE__ */ React7__namespace.createElement(
285
- "input",
286
- {
287
- type: "checkbox",
288
- id: checkboxId,
289
- name,
290
- value: option.value,
291
- checked: isChecked,
292
- onChange: (e) => handleChange(option.value, e.target.checked),
293
- onBlur: handleBlur,
294
- disabled: isDisabled,
295
- required: required && minSelections ? value.length < minSelections : false,
296
- className: `peer relative flex size-4 shrink-0 appearance-none items-center justify-center rounded-lg border border-input bg-transparent outline-none transition-colors focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 ${error ? "border-destructive ring-3 ring-destructive/20" : ""} ${isChecked ? "bg-primary border-primary" : ""}`,
297
- "aria-describedby": option.description ? `${checkboxId}-description` : props["aria-describedby"]
298
- }
299
- ), isChecked && /* @__PURE__ */ React7__namespace.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary-foreground" }, /* @__PURE__ */ React7__namespace.createElement("svg", { className: "size-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3" }, /* @__PURE__ */ React7__namespace.createElement("polyline", { points: "20 6 9 17 4 12" })))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, renderOption ? renderOption(option) : /* @__PURE__ */ React7__namespace.createElement(React7__namespace.Fragment, null, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center gap-2 text-sm font-medium" }, option.label), option.description && /* @__PURE__ */ React7__namespace.createElement(
300
- "p",
301
- {
302
- className: "text-muted-foreground text-sm",
303
- id: `${checkboxId}-description`
304
- },
305
- option.description
306
- ))))
353
+ name,
354
+ id: `${name}-${option.value}`,
355
+ value: isChecked,
356
+ onChange: (checked) => handleChange(option.value, checked),
357
+ onBlur: handleBlur,
358
+ disabled: isDisabled,
359
+ required: required && minSelections ? value.length < minSelections : false,
360
+ error,
361
+ label: renderOption ? renderOption(option) : option.label,
362
+ description: renderOption ? void 0 : option.description,
363
+ checkboxVariant
364
+ }
307
365
  );
308
366
  }),
309
- (minSelections || maxSelections) && /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-sm text-muted-foreground mt-2", "aria-live": "polite" }, minSelections && value.length < minSelections && /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-destructive" }, "Select at least ", minSelections, " option", minSelections !== 1 ? "s" : ""), maxSelections && /* @__PURE__ */ React7__namespace.createElement("span", null, value.length, "/", maxSelections, " selected"))
367
+ (minSelections || maxSelections) && /* @__PURE__ */ React7__namespace.createElement(
368
+ "div",
369
+ {
370
+ className: cn(
371
+ "text-sm p-2 rounded-lg border font-semibold mt-2",
372
+ minSelections && countableValue < minSelections ? "border-destructive bg-destructive/80 text-destructive-foreground" : "border-border bg-card text-card-foreground"
373
+ ),
374
+ "aria-live": "polite"
375
+ },
376
+ minSelections && countableValue < minSelections && /* @__PURE__ */ React7__namespace.createElement("span", null, "Select at least ", minSelections, " option", minSelections !== 1 ? "s" : ""),
377
+ maxSelections && /* @__PURE__ */ React7__namespace.createElement("span", null, countableValue, "/", maxSelections, " selected")
378
+ )
310
379
  );
311
380
  }
312
381
  CheckboxGroup.displayName = "CheckboxGroup";
@@ -355,8 +424,16 @@ function Radio({
355
424
  const handleBlur = () => {
356
425
  onBlur?.();
357
426
  };
358
- const layoutClass = layout === "inline" ? "flex flex-row flex-wrap gap-4" : "grid w-full gap-2";
359
- const containerClass = `${layoutClass} ${className}`.trim();
427
+ const useChoiceCard = React7__namespace.useMemo(() => {
428
+ return options.some((option) => option.description);
429
+ }, [options]);
430
+ const containerClass = React7__namespace.useMemo(() => {
431
+ return cn(
432
+ "w-full gap-3 grid grid-cols-1",
433
+ layout === "inline" && "md:grid-cols-2",
434
+ className
435
+ );
436
+ }, [layout, className]);
360
437
  return /* @__PURE__ */ React7__namespace.createElement(
361
438
  "div",
362
439
  {
@@ -372,38 +449,53 @@ function Radio({
372
449
  const isChecked = value === option.value;
373
450
  const isDisabled = disabled || option.disabled;
374
451
  const radioId = `${name}-${option.value}`;
452
+ const hasDescription = option.description != null && option.description !== "";
453
+ const radioIndicator = /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative inline-flex items-center justify-center" }, /* @__PURE__ */ React7__namespace.createElement(
454
+ "input",
455
+ {
456
+ type: "radio",
457
+ id: radioId,
458
+ name,
459
+ value: option.value,
460
+ checked: isChecked,
461
+ onChange: (e) => handleChange(e.target.value),
462
+ onBlur: handleBlur,
463
+ disabled: isDisabled,
464
+ required,
465
+ className: "peer sr-only",
466
+ "aria-describedby": hasDescription ? `${radioId}-description` : props["aria-describedby"]
467
+ }
468
+ ), /* @__PURE__ */ React7__namespace.createElement(
469
+ "div",
470
+ {
471
+ className: cn(
472
+ "flex shrink-0 items-center justify-center rounded-full border-2 transition-colors size-6",
473
+ !error && isChecked && "border-primary bg-transparent",
474
+ !error && !isChecked && "border-input bg-transparent",
475
+ error && isChecked && "border-destructive bg-transparent",
476
+ error && !isChecked && "border-destructive bg-transparent",
477
+ isDisabled && "opacity-50",
478
+ "peer-focus-visible:ring-2 peer-focus-visible:ring-ring/50 peer-focus-visible:ring-offset-1"
479
+ )
480
+ },
481
+ isChecked && /* @__PURE__ */ React7__namespace.createElement("div", { className: "size-3 rounded-full bg-primary" })
482
+ ));
483
+ const labelContent = /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-sm font-medium" }, option.label), hasDescription && /* @__PURE__ */ React7__namespace.createElement("p", { className: "text-xs opacity-75", id: `${radioId}-description` }, option.description));
375
484
  return /* @__PURE__ */ React7__namespace.createElement(
376
485
  "label",
377
486
  {
378
487
  key: option.value,
379
- className: `flex w-fit gap-2 items-center ${isDisabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}`,
488
+ className: cn(
489
+ "w-full h-full flex gap-3 p-3 duration-200",
490
+ useChoiceCard && "border rounded-lg hover:ring-2",
491
+ useChoiceCard && isChecked && "ring-2",
492
+ isDisabled ? "opacity-50 cursor-not-allowed hover:ring-0" : "cursor-pointer"
493
+ ),
380
494
  htmlFor: radioId,
381
495
  onKeyDown: (e) => handleKeyDown(e, index),
382
496
  tabIndex: isDisabled ? -1 : 0
383
497
  },
384
- /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, option.description ? /* @__PURE__ */ React7__namespace.createElement(React7__namespace.Fragment, null, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center gap-2 text-sm font-medium" }, option.label), /* @__PURE__ */ React7__namespace.createElement(
385
- "p",
386
- {
387
- className: "text-muted-foreground text-sm",
388
- id: `${radioId}-description`
389
- },
390
- option.description
391
- )) : /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-sm font-medium" }, option.label)), /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative" }, /* @__PURE__ */ React7__namespace.createElement(
392
- "input",
393
- {
394
- type: "radio",
395
- id: radioId,
396
- name,
397
- value: option.value,
398
- checked: isChecked,
399
- onChange: (e) => handleChange(e.target.value),
400
- onBlur: handleBlur,
401
- disabled: isDisabled,
402
- required,
403
- className: `peer relative flex aspect-square size-4 shrink-0 appearance-none rounded-full border border-input outline-none transition-colors focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 ${error ? "border-destructive" : ""} ${isChecked ? "border-primary bg-primary" : "bg-transparent"}`,
404
- "aria-describedby": option.description ? `${radioId}-description` : props["aria-describedby"]
405
- }
406
- ), isChecked && /* @__PURE__ */ React7__namespace.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex size-4 -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary-foreground" }, /* @__PURE__ */ React7__namespace.createElement("svg", { className: "size-2 fill-current", viewBox: "0 0 24 24" }, /* @__PURE__ */ React7__namespace.createElement("circle", { cx: "12", cy: "12", r: "10" })))))
498
+ /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, !useChoiceCard && radioIndicator, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, labelContent), useChoiceCard && radioIndicator)
407
499
  );
408
500
  })
409
501
  );
@@ -493,9 +585,7 @@ function Select({
493
585
  if (enabledOptions.length > 0) {
494
586
  const currentIndexInFiltered = focusedIndex;
495
587
  const nextIndex = (currentIndexInFiltered + 1) % enabledOptions.length;
496
- setFocusedIndex(
497
- filteredOptions.indexOf(enabledOptions[nextIndex])
498
- );
588
+ setFocusedIndex(filteredOptions.indexOf(enabledOptions[nextIndex]));
499
589
  }
500
590
  }
501
591
  break;
@@ -506,9 +596,7 @@ function Select({
506
596
  if (enabledOptions.length > 0) {
507
597
  const currentIndexInFiltered = focusedIndex;
508
598
  const prevIndex = (currentIndexInFiltered - 1 + enabledOptions.length) % enabledOptions.length;
509
- setFocusedIndex(
510
- filteredOptions.indexOf(enabledOptions[prevIndex])
511
- );
599
+ setFocusedIndex(filteredOptions.indexOf(enabledOptions[prevIndex]));
512
600
  }
513
601
  }
514
602
  break;
@@ -598,7 +686,7 @@ function Select({
598
686
  /* @__PURE__ */ React7__namespace.createElement(
599
687
  "div",
600
688
  {
601
- 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" : ""}`,
689
+ className: `flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm cursor-pointer transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring ${disabled ? "cursor-not-allowed opacity-50 pointer-events-none" : ""} ${error ? "border-red-500 ring-1 ring-red-500" : ""}`,
602
690
  onClick: handleToggle,
603
691
  role: "combobox",
604
692
  "aria-expanded": isOpen,
@@ -609,48 +697,76 @@ function Select({
609
697
  "aria-disabled": disabled,
610
698
  tabIndex: disabled ? -1 : 0
611
699
  },
612
- /* @__PURE__ */ React7__namespace.createElement("span", { className: "flex items-center flex-1 overflow-hidden text-ellipsis" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-muted-foreground" }, placeholder)),
700
+ /* @__PURE__ */ React7__namespace.createElement("span", { className: "flex items-center flex-1 overflow-hidden text-ellipsis" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React7__namespace.createElement("span", { className: "relative" }, placeholder)),
613
701
  /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center gap-1 ml-2" }, loading && /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-xs" }, "\u23F3"), clearable && value && !disabled && !loading && /* @__PURE__ */ React7__namespace.createElement(
614
702
  "button",
615
703
  {
616
704
  type: "button",
617
- 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",
705
+ 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",
618
706
  onClick: handleClear,
619
707
  "aria-label": "Clear selection",
620
708
  tabIndex: -1
621
709
  },
622
710
  "\u2715"
623
- ), /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-muted-foreground text-xs leading-none", "aria-hidden": "true" }, isOpen ? "\u25B2" : "\u25BC"))
711
+ ), /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-xs leading-none", "aria-hidden": "true" }, isOpen ? "\u25B2" : "\u25BC"))
624
712
  ),
625
- isOpen && /* @__PURE__ */ React7__namespace.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__namespace.createElement("div", { className: "p-2 border-b border-border" }, /* @__PURE__ */ React7__namespace.createElement(
626
- "input",
713
+ isOpen && /* @__PURE__ */ React7__namespace.createElement(
714
+ "div",
627
715
  {
628
- ref: searchInputRef,
629
- type: "text",
630
- className: "w-full border border-input rounded px-2 py-1 text-sm bg-transparent outline-none focus:ring-1 focus:ring-ring",
631
- placeholder: "Search...",
632
- value: searchQuery,
633
- onChange: handleSearchChange,
634
- onClick: (e) => e.stopPropagation(),
635
- "aria-label": "Search options"
636
- }
637
- )), /* @__PURE__ */ React7__namespace.createElement("div", { className: "max-h-64 overflow-y-auto p-1" }, filteredOptions.length === 0 ? /* @__PURE__ */ React7__namespace.createElement("div", { className: "py-2 px-3 text-center text-sm text-muted-foreground" }, "No options found") : optionGroups.length > 0 ? (
638
- // Render grouped options
639
- optionGroups.map((group, groupIndex) => {
640
- const groupOptions = group.options.filter(
641
- (opt) => filteredOptions.includes(opt)
642
- );
643
- if (groupOptions.length === 0) return null;
644
- return /* @__PURE__ */ React7__namespace.createElement("div", { key: groupIndex, className: "py-1" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "py-1.5 px-2 text-xs font-semibold text-muted-foreground" }, group.label), groupOptions.map((option) => {
645
- const globalIndex = filteredOptions.indexOf(option);
716
+ id: dropdownId,
717
+ className: "absolute z-50 top-full mt-1 min-w-full overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md",
718
+ role: "listbox"
719
+ },
720
+ searchable && /* @__PURE__ */ React7__namespace.createElement("div", { className: "p-2 border-b border-border" }, /* @__PURE__ */ React7__namespace.createElement(
721
+ "input",
722
+ {
723
+ ref: searchInputRef,
724
+ type: "text",
725
+ className: "w-full border border-input rounded px-2 py-1 text-sm bg-transparent outline-none focus:ring-1 focus:ring-ring",
726
+ placeholder: "Search...",
727
+ value: searchQuery,
728
+ onChange: handleSearchChange,
729
+ onClick: (e) => e.stopPropagation(),
730
+ "aria-label": "Search options"
731
+ }
732
+ )),
733
+ /* @__PURE__ */ React7__namespace.createElement("div", { className: "max-h-64 overflow-y-auto p-1" }, filteredOptions.length === 0 ? /* @__PURE__ */ React7__namespace.createElement("div", { className: "py-2 px-3 text-center text-sm " }, "No options found") : optionGroups.length > 0 ? (
734
+ // Render grouped options
735
+ optionGroups.map((group, groupIndex) => {
736
+ const groupOptions = group.options.filter(
737
+ (opt) => filteredOptions.includes(opt)
738
+ );
739
+ if (groupOptions.length === 0) return null;
740
+ return /* @__PURE__ */ React7__namespace.createElement("div", { key: groupIndex, className: "py-1" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "py-1.5 px-2 text-xs font-semibold " }, group.label), groupOptions.map((option) => {
741
+ const globalIndex = filteredOptions.indexOf(option);
742
+ const isSelected = value === option.value;
743
+ const isFocused = globalIndex === focusedIndex;
744
+ const isDisabled = option.disabled;
745
+ return /* @__PURE__ */ React7__namespace.createElement(
746
+ "div",
747
+ {
748
+ key: option.value,
749
+ 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" : ""}`,
750
+ onClick: () => !isDisabled && handleSelect(option.value),
751
+ role: "option",
752
+ "aria-selected": isSelected,
753
+ "aria-disabled": isDisabled
754
+ },
755
+ renderOption ? renderOption(option) : option.label
756
+ );
757
+ }));
758
+ })
759
+ ) : (
760
+ // Render flat options
761
+ filteredOptions.map((option, index) => {
646
762
  const isSelected = value === option.value;
647
- const isFocused = globalIndex === focusedIndex;
763
+ const isFocused = index === focusedIndex;
648
764
  const isDisabled = option.disabled;
649
765
  return /* @__PURE__ */ React7__namespace.createElement(
650
766
  "div",
651
767
  {
652
768
  key: option.value,
653
- 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" : ""}`,
769
+ 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" : ""}`,
654
770
  onClick: () => !isDisabled && handleSelect(option.value),
655
771
  role: "option",
656
772
  "aria-selected": isSelected,
@@ -658,28 +774,9 @@ function Select({
658
774
  },
659
775
  renderOption ? renderOption(option) : option.label
660
776
  );
661
- }));
662
- })
663
- ) : (
664
- // Render flat options
665
- filteredOptions.map((option, index) => {
666
- const isSelected = value === option.value;
667
- const isFocused = index === focusedIndex;
668
- const isDisabled = option.disabled;
669
- return /* @__PURE__ */ React7__namespace.createElement(
670
- "div",
671
- {
672
- key: option.value,
673
- 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" : ""}`,
674
- onClick: () => !isDisabled && handleSelect(option.value),
675
- role: "option",
676
- "aria-selected": isSelected,
677
- "aria-disabled": isDisabled
678
- },
679
- renderOption ? renderOption(option) : option.label
680
- );
681
- })
682
- )))
777
+ })
778
+ ))
779
+ )
683
780
  );
684
781
  }
685
782
  Select.displayName = "Select";
@@ -688,7 +785,7 @@ function FileInput({
688
785
  value = [],
689
786
  onChange,
690
787
  onBlur,
691
- placeholder = "Choose file(s)...",
788
+ placeholder = "Choose file...",
692
789
  disabled = false,
693
790
  required = false,
694
791
  error = false,
@@ -791,7 +888,15 @@ function FileInput({
791
888
  inputRef.current.value = "";
792
889
  }
793
890
  },
794
- [value, onChange, validateFile, maxFiles, multiple, enableCropping, onValidationError]
891
+ [
892
+ value,
893
+ onChange,
894
+ validateFile,
895
+ maxFiles,
896
+ multiple,
897
+ enableCropping,
898
+ onValidationError
899
+ ]
795
900
  );
796
901
  const createCroppedImage = React7__namespace.useCallback(
797
902
  async (imageUrl, cropArea) => {
@@ -817,13 +922,17 @@ function FileInput({
817
922
  cropArea.width,
818
923
  cropArea.height
819
924
  );
820
- canvas.toBlob((blob) => {
821
- if (blob) {
822
- resolve(blob);
823
- } else {
824
- reject(new Error("Failed to create blob from canvas"));
825
- }
826
- }, "image/jpeg", 0.95);
925
+ canvas.toBlob(
926
+ (blob) => {
927
+ if (blob) {
928
+ resolve(blob);
929
+ } else {
930
+ reject(new Error("Failed to create blob from canvas"));
931
+ }
932
+ },
933
+ "image/jpeg",
934
+ 0.95
935
+ );
827
936
  };
828
937
  image.onerror = () => {
829
938
  reject(new Error("Failed to load image"));
@@ -843,11 +952,9 @@ function FileInput({
843
952
  if (onCropComplete) {
844
953
  onCropComplete(croppedBlob, imageToCrop.file);
845
954
  }
846
- const croppedFile = new File(
847
- [croppedBlob],
848
- imageToCrop.file.name,
849
- { type: "image/jpeg" }
850
- );
955
+ const croppedFile = new File([croppedBlob], imageToCrop.file.name, {
956
+ type: "image/jpeg"
957
+ });
851
958
  const updatedFiles = multiple ? [...value, croppedFile] : [croppedFile];
852
959
  onChange(updatedFiles);
853
960
  setCropperOpen(false);
@@ -859,7 +966,15 @@ function FileInput({
859
966
  } catch (error2) {
860
967
  console.error("Failed to crop image:", error2);
861
968
  }
862
- }, [imageToCrop, croppedAreaPixels, createCroppedImage, onCropComplete, value, onChange, multiple]);
969
+ }, [
970
+ imageToCrop,
971
+ croppedAreaPixels,
972
+ createCroppedImage,
973
+ onCropComplete,
974
+ value,
975
+ onChange,
976
+ multiple
977
+ ]);
863
978
  const handleCropCancel = React7__namespace.useCallback(() => {
864
979
  if (imageToCrop) {
865
980
  URL.revokeObjectURL(imageToCrop.url);
@@ -971,7 +1086,7 @@ function FileInput({
971
1086
  ), /* @__PURE__ */ React7__namespace.createElement(
972
1087
  "div",
973
1088
  {
974
- 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" : ""}`,
1089
+ className: `flex min-h-32 w-full cursor-pointer items-center justify-center rounded-md border-2 border-dashed border-input bg-transparent p-6 transition-colors hover:bg-primary/50 hover:border-ring ${dragActive ? "bg-primary text-primary-foreground border-ring" : ""} ${disabled ? "cursor-not-allowed opacity-50" : ""} ${error ? "border-red-500" : ""}`,
975
1090
  onDragEnter: handleDrag,
976
1091
  onDragLeave: handleDrag,
977
1092
  onDragOver: handleDrag,
@@ -986,7 +1101,6 @@ function FileInput({
986
1101
  /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col items-center gap-2 text-center" }, /* @__PURE__ */ React7__namespace.createElement(
987
1102
  "svg",
988
1103
  {
989
- className: "text-muted-foreground",
990
1104
  width: "48",
991
1105
  height: "48",
992
1106
  viewBox: "0 0 24 24",
@@ -1000,92 +1114,102 @@ function FileInput({
1000
1114
  /* @__PURE__ */ React7__namespace.createElement("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
1001
1115
  /* @__PURE__ */ React7__namespace.createElement("polyline", { points: "17 8 12 3 7 8" }),
1002
1116
  /* @__PURE__ */ React7__namespace.createElement("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
1003
- ), /* @__PURE__ */ React7__namespace.createElement("p", { className: "text-sm font-medium" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React7__namespace.createElement("p", { className: "text-xs text-muted-foreground" }, "Accepted: ", accept), maxSize && /* @__PURE__ */ React7__namespace.createElement("p", { className: "text-xs text-muted-foreground" }, "Max size: ", formatFileSize(maxSize)))
1117
+ ), /* @__PURE__ */ React7__namespace.createElement("p", { className: "text-sm font-medium" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React7__namespace.createElement("p", { className: "text-xs" }, "Accepted: ", accept), maxSize && /* @__PURE__ */ React7__namespace.createElement("p", { className: "text-xs " }, "Max size: ", formatFileSize(maxSize)))
1004
1118
  ), value.length > 0 && /* @__PURE__ */ React7__namespace.createElement("ul", { className: "flex flex-col gap-2 mt-4", role: "list" }, value.map((file, index) => {
1005
1119
  const previewUrl = showPreview ? getPreviewUrl(file) : null;
1006
- return /* @__PURE__ */ React7__namespace.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__namespace.createElement(
1007
- "img",
1008
- {
1009
- src: previewUrl,
1010
- alt: file.name,
1011
- className: "w-12 h-12 rounded object-cover",
1012
- width: "48",
1013
- height: "48"
1014
- }
1015
- ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-sm font-medium truncate" }, file.name), /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-xs text-muted-foreground" }, formatFileSize(file.size)), showProgress && uploadProgress[file.name] !== void 0 && /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center gap-2 mt-1" }, /* @__PURE__ */ React7__namespace.createElement(
1016
- "div",
1120
+ return /* @__PURE__ */ React7__namespace.createElement(
1121
+ "li",
1017
1122
  {
1018
- className: "h-1.5 bg-muted rounded-full overflow-hidden flex-1",
1019
- role: "progressbar",
1020
- "aria-valuenow": uploadProgress[file.name],
1021
- "aria-valuemin": 0,
1022
- "aria-valuemax": 100,
1023
- "aria-label": `Upload progress: ${uploadProgress[file.name]}%`
1123
+ key: `${file.name}-${index}`,
1124
+ className: "flex items-center gap-3 p-3 rounded-md border border-border bg-card text-card-foreground hover:bg-primary/50 transition-colors"
1024
1125
  },
1025
- /* @__PURE__ */ React7__namespace.createElement(
1026
- "div",
1126
+ previewUrl && /* @__PURE__ */ React7__namespace.createElement(
1127
+ "img",
1027
1128
  {
1028
- className: "h-full bg-primary transition-all",
1029
- style: { width: `${uploadProgress[file.name]}%` }
1129
+ src: previewUrl,
1130
+ alt: file.name,
1131
+ className: "w-12 h-12 rounded object-cover",
1132
+ width: "48",
1133
+ height: "48"
1030
1134
  }
1031
- )
1032
- ), /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-xs text-muted-foreground" }, uploadProgress[file.name], "%"))), enableCropping && file.type.startsWith("image/") && /* @__PURE__ */ React7__namespace.createElement(
1033
- "button",
1034
- {
1035
- type: "button",
1036
- onClick: (e) => {
1037
- e.stopPropagation();
1038
- handleCrop(file);
1039
- },
1040
- disabled,
1041
- 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",
1042
- "aria-label": `Crop ${file.name}`
1043
- },
1044
- /* @__PURE__ */ React7__namespace.createElement(
1045
- "svg",
1135
+ ),
1136
+ /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-sm font-medium truncate" }, file.name), /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-xs" }, formatFileSize(file.size)), showProgress && uploadProgress[file.name] !== void 0 && /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center gap-2 mt-1" }, /* @__PURE__ */ React7__namespace.createElement(
1137
+ "div",
1046
1138
  {
1047
- width: "20",
1048
- height: "20",
1049
- viewBox: "0 0 24 24",
1050
- fill: "none",
1051
- stroke: "currentColor",
1052
- strokeWidth: "2",
1053
- strokeLinecap: "round",
1054
- strokeLinejoin: "round",
1055
- "aria-hidden": "true"
1139
+ className: "h-1.5 bg-muted rounded-full overflow-hidden flex-1",
1140
+ role: "progressbar",
1141
+ "aria-valuenow": uploadProgress[file.name],
1142
+ "aria-valuemin": 0,
1143
+ "aria-valuemax": 100,
1144
+ "aria-label": `Upload progress: ${uploadProgress[file.name]}%`
1056
1145
  },
1057
- /* @__PURE__ */ React7__namespace.createElement("path", { d: "M6.13 1L6 16a2 2 0 0 0 2 2h15" }),
1058
- /* @__PURE__ */ React7__namespace.createElement("path", { d: "M1 6.13L16 6a2 2 0 0 1 2 2v15" })
1059
- )
1060
- ), /* @__PURE__ */ React7__namespace.createElement(
1061
- "button",
1062
- {
1063
- type: "button",
1064
- onClick: (e) => {
1065
- e.stopPropagation();
1066
- handleRemove(index);
1146
+ /* @__PURE__ */ React7__namespace.createElement(
1147
+ "div",
1148
+ {
1149
+ className: "h-full bg-primary transition-all",
1150
+ style: { width: `${uploadProgress[file.name]}%` }
1151
+ }
1152
+ )
1153
+ ), /* @__PURE__ */ React7__namespace.createElement("span", { className: "text-xs " }, uploadProgress[file.name], "%"))),
1154
+ enableCropping && file.type.startsWith("image/") && /* @__PURE__ */ React7__namespace.createElement(
1155
+ "button",
1156
+ {
1157
+ type: "button",
1158
+ onClick: (e) => {
1159
+ e.stopPropagation();
1160
+ handleCrop(file);
1161
+ },
1162
+ disabled,
1163
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
1164
+ "aria-label": `Crop ${file.name}`
1067
1165
  },
1068
- disabled,
1069
- 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",
1070
- "aria-label": `Remove ${file.name}`
1071
- },
1166
+ /* @__PURE__ */ React7__namespace.createElement(
1167
+ "svg",
1168
+ {
1169
+ width: "20",
1170
+ height: "20",
1171
+ viewBox: "0 0 24 24",
1172
+ fill: "none",
1173
+ stroke: "currentColor",
1174
+ strokeWidth: "2",
1175
+ strokeLinecap: "round",
1176
+ strokeLinejoin: "round",
1177
+ "aria-hidden": "true"
1178
+ },
1179
+ /* @__PURE__ */ React7__namespace.createElement("path", { d: "M6.13 1L6 16a2 2 0 0 0 2 2h15" }),
1180
+ /* @__PURE__ */ React7__namespace.createElement("path", { d: "M1 6.13L16 6a2 2 0 0 1 2 2v15" })
1181
+ )
1182
+ ),
1072
1183
  /* @__PURE__ */ React7__namespace.createElement(
1073
- "svg",
1184
+ "button",
1074
1185
  {
1075
- width: "20",
1076
- height: "20",
1077
- viewBox: "0 0 24 24",
1078
- fill: "none",
1079
- stroke: "currentColor",
1080
- strokeWidth: "2",
1081
- strokeLinecap: "round",
1082
- strokeLinejoin: "round",
1083
- "aria-hidden": "true"
1186
+ type: "button",
1187
+ onClick: (e) => {
1188
+ e.stopPropagation();
1189
+ handleRemove(index);
1190
+ },
1191
+ disabled,
1192
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
1193
+ "aria-label": `Remove ${file.name}`
1084
1194
  },
1085
- /* @__PURE__ */ React7__namespace.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1086
- /* @__PURE__ */ React7__namespace.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1195
+ /* @__PURE__ */ React7__namespace.createElement(
1196
+ "svg",
1197
+ {
1198
+ width: "20",
1199
+ height: "20",
1200
+ viewBox: "0 0 24 24",
1201
+ fill: "none",
1202
+ stroke: "currentColor",
1203
+ strokeWidth: "2",
1204
+ strokeLinecap: "round",
1205
+ strokeLinejoin: "round",
1206
+ "aria-hidden": "true"
1207
+ },
1208
+ /* @__PURE__ */ React7__namespace.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1209
+ /* @__PURE__ */ React7__namespace.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1210
+ )
1087
1211
  )
1088
- ));
1212
+ );
1089
1213
  })), cropperOpen && imageToCrop && /* @__PURE__ */ React7__namespace.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center" }, /* @__PURE__ */ React7__namespace.createElement(
1090
1214
  "div",
1091
1215
  {
@@ -1097,7 +1221,7 @@ function FileInput({
1097
1221
  "button",
1098
1222
  {
1099
1223
  type: "button",
1100
- className: "flex items-center justify-center h-8 w-8 rounded hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
1224
+ className: "flex items-center justify-center h-8 w-8 rounded hover:bg-primary hover:text-primary-foreground transition-colors",
1101
1225
  onClick: handleCropCancel,
1102
1226
  "aria-label": "Close"
1103
1227
  },
@@ -1138,7 +1262,10 @@ function FileInput({
1138
1262
  const img = e.currentTarget;
1139
1263
  const containerWidth = 600;
1140
1264
  const containerHeight = 400;
1141
- const cropWidth = cropAspectRatio ? Math.min(containerWidth * 0.8, containerHeight * 0.8 * cropAspectRatio) : containerWidth * 0.8;
1265
+ const cropWidth = cropAspectRatio ? Math.min(
1266
+ containerWidth * 0.8,
1267
+ containerHeight * 0.8 * cropAspectRatio
1268
+ ) : containerWidth * 0.8;
1142
1269
  const cropHeight = cropAspectRatio ? cropWidth / cropAspectRatio : containerHeight * 0.8;
1143
1270
  const scale = zoom;
1144
1271
  const imgWidth = img.naturalWidth;
@@ -1167,7 +1294,16 @@ function FileInput({
1167
1294
  },
1168
1295
  /* @__PURE__ */ React7__namespace.createElement("div", { className: "absolute inset-0 grid grid-cols-3 grid-rows-3" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React7__namespace.createElement("div", null))
1169
1296
  )
1170
- ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center gap-3 mt-4" }, /* @__PURE__ */ React7__namespace.createElement("label", { htmlFor: "zoom-slider", className: "text-sm font-medium whitespace-nowrap" }, "Zoom: ", zoom.toFixed(1), "x"), /* @__PURE__ */ React7__namespace.createElement(
1297
+ ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex items-center gap-3 mt-4" }, /* @__PURE__ */ React7__namespace.createElement(
1298
+ "label",
1299
+ {
1300
+ htmlFor: "zoom-slider",
1301
+ className: "text-sm font-medium whitespace-nowrap"
1302
+ },
1303
+ "Zoom: ",
1304
+ zoom.toFixed(1),
1305
+ "x"
1306
+ ), /* @__PURE__ */ React7__namespace.createElement(
1171
1307
  "input",
1172
1308
  {
1173
1309
  id: "zoom-slider",
@@ -1184,7 +1320,7 @@ function FileInput({
1184
1320
  "button",
1185
1321
  {
1186
1322
  type: "button",
1187
- 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",
1323
+ 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",
1188
1324
  onClick: handleCropCancel
1189
1325
  },
1190
1326
  "Cancel"
@@ -1253,7 +1389,9 @@ function DatePicker({
1253
1389
  }) {
1254
1390
  const [isOpen, setIsOpen] = React7__namespace.useState(false);
1255
1391
  const [inputValue, setInputValue] = React7__namespace.useState("");
1256
- const [selectedMonth, setSelectedMonth] = React7__namespace.useState(value || /* @__PURE__ */ new Date());
1392
+ const [selectedMonth, setSelectedMonth] = React7__namespace.useState(
1393
+ value || /* @__PURE__ */ new Date()
1394
+ );
1257
1395
  const containerRef = React7__namespace.useRef(null);
1258
1396
  const inputRef = React7__namespace.useRef(null);
1259
1397
  React7__namespace.useEffect(() => {
@@ -1344,7 +1482,7 @@ function DatePicker({
1344
1482
  "button",
1345
1483
  {
1346
1484
  type: "button",
1347
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent cursor-pointer",
1485
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
1348
1486
  onClick: handlePrevMonth,
1349
1487
  "aria-label": "Previous month"
1350
1488
  },
@@ -1353,12 +1491,19 @@ function DatePicker({
1353
1491
  "button",
1354
1492
  {
1355
1493
  type: "button",
1356
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent cursor-pointer",
1494
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
1357
1495
  onClick: handleNextMonth,
1358
1496
  "aria-label": "Next month"
1359
1497
  },
1360
1498
  "\u2192"
1361
- )), /* @__PURE__ */ React7__namespace.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7__namespace.createElement("div", { key: day, className: "flex items-center justify-center h-8 w-full text-xs text-muted-foreground font-medium" }, day))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
1499
+ )), /* @__PURE__ */ React7__namespace.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7__namespace.createElement(
1500
+ "div",
1501
+ {
1502
+ key: day,
1503
+ className: "flex items-center justify-center h-8 w-full text-xs font-medium"
1504
+ },
1505
+ day
1506
+ ))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
1362
1507
  if (!date) {
1363
1508
  return /* @__PURE__ */ React7__namespace.createElement("div", { key: `empty-${index}` });
1364
1509
  }
@@ -1370,7 +1515,7 @@ function DatePicker({
1370
1515
  {
1371
1516
  key: date.toISOString(),
1372
1517
  type: "button",
1373
- className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-accent hover:text-accent-foreground ${isSelected ? "bg-primary text-primary-foreground font-semibold" : ""} ${isToday ? "border border-primary" : ""} ${disabled2 ? "cursor-not-allowed opacity-50 pointer-events-none" : ""}`,
1518
+ className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-primary hover:text-primary-foreground ${isSelected ? "bg-primary text-primary-foreground font-semibold" : ""} ${isToday ? "border border-primary" : ""} ${disabled2 ? "cursor-not-allowed opacity-50 pointer-events-none" : ""}`,
1374
1519
  onClick: () => !disabled2 && handleDateSelect(date),
1375
1520
  disabled: disabled2,
1376
1521
  "aria-label": formatDate(date, format)
@@ -1387,26 +1532,33 @@ function DatePicker({
1387
1532
  name,
1388
1533
  value: value ? value.toISOString() : ""
1389
1534
  }
1390
- ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7__namespace.createElement("span", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none", "aria-hidden": "true" }, /* @__PURE__ */ React7__namespace.createElement(
1391
- "svg",
1535
+ ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7__namespace.createElement(
1536
+ "span",
1392
1537
  {
1393
- xmlns: "http://www.w3.org/2000/svg",
1394
- width: "18",
1395
- height: "18",
1396
- viewBox: "0 0 24 24",
1397
- fill: "none",
1398
- stroke: "currentColor",
1399
- strokeLinecap: "round",
1400
- strokeLinejoin: "round",
1401
- strokeWidth: "2"
1538
+ className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
1539
+ "aria-hidden": "true"
1402
1540
  },
1403
- /* @__PURE__ */ React7__namespace.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
1404
- )), /* @__PURE__ */ React7__namespace.createElement(
1541
+ /* @__PURE__ */ React7__namespace.createElement(
1542
+ "svg",
1543
+ {
1544
+ xmlns: "http://www.w3.org/2000/svg",
1545
+ width: "18",
1546
+ height: "18",
1547
+ viewBox: "0 0 24 24",
1548
+ fill: "none",
1549
+ stroke: "currentColor",
1550
+ strokeLinecap: "round",
1551
+ strokeLinejoin: "round",
1552
+ strokeWidth: "2"
1553
+ },
1554
+ /* @__PURE__ */ React7__namespace.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
1555
+ )
1556
+ ), /* @__PURE__ */ React7__namespace.createElement(
1405
1557
  "input",
1406
1558
  {
1407
1559
  ref: inputRef,
1408
1560
  type: "text",
1409
- 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" : ""}`,
1561
+ className: `flex h-9 w-full rounded-md border border-input bg-transparent ${showIcon ? "pl-10" : "pl-3"} ${clearable && value ? "pr-10" : "pr-3"} py-1 text-base shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm ${error ? "border-red-500 ring-1 ring-red-500" : ""}`,
1410
1562
  value: inputValue,
1411
1563
  onChange: handleInputChange,
1412
1564
  onClick: handleToggle,
@@ -1423,7 +1575,7 @@ function DatePicker({
1423
1575
  "button",
1424
1576
  {
1425
1577
  type: "button",
1426
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors",
1578
+ className: "absolute right-3 top-1/2 -translate-y-1/2 transition-colors",
1427
1579
  onClick: handleClear,
1428
1580
  "aria-label": "Clear date",
1429
1581
  tabIndex: -1
@@ -1562,36 +1714,43 @@ function TimePicker({
1562
1714
  }
1563
1715
  return mins;
1564
1716
  }, [minuteStep]);
1565
- const combinedClassName = `relative ${className}`.trim();
1717
+ const combinedClassName = cn("relative", className);
1566
1718
  const displayValue = formatTimeValue(timeValue, use24Hour);
1567
- return /* @__PURE__ */ React7__namespace.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7__namespace.createElement(
1568
- "input",
1719
+ return /* @__PURE__ */ React7__namespace.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7__namespace.createElement("input", { type: "hidden", name, value }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7__namespace.createElement(
1720
+ "span",
1569
1721
  {
1570
- type: "hidden",
1571
- name,
1572
- value
1573
- }
1574
- ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7__namespace.createElement("span", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none", "aria-hidden": "true" }, /* @__PURE__ */ React7__namespace.createElement(
1575
- "svg",
1576
- {
1577
- xmlns: "http://www.w3.org/2000/svg",
1578
- width: "18",
1579
- height: "18",
1580
- viewBox: "0 0 24 24",
1581
- fill: "none",
1582
- stroke: "currentColor",
1583
- strokeLinecap: "round",
1584
- strokeLinejoin: "round",
1585
- strokeWidth: "2"
1722
+ className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
1723
+ "aria-hidden": "true"
1586
1724
  },
1587
- /* @__PURE__ */ React7__namespace.createElement("circle", { cx: "12", cy: "12", r: "10" }),
1588
- /* @__PURE__ */ React7__namespace.createElement("path", { d: "M12 6v6l4 2" })
1589
- )), /* @__PURE__ */ React7__namespace.createElement(
1725
+ /* @__PURE__ */ React7__namespace.createElement(
1726
+ "svg",
1727
+ {
1728
+ xmlns: "http://www.w3.org/2000/svg",
1729
+ width: "18",
1730
+ height: "18",
1731
+ viewBox: "0 0 24 24",
1732
+ fill: "none",
1733
+ stroke: "currentColor",
1734
+ strokeLinecap: "round",
1735
+ strokeLinejoin: "round",
1736
+ strokeWidth: "2"
1737
+ },
1738
+ /* @__PURE__ */ React7__namespace.createElement("circle", { cx: "12", cy: "12", r: "10" }),
1739
+ /* @__PURE__ */ React7__namespace.createElement("path", { d: "M12 6v6l4 2" })
1740
+ )
1741
+ ), /* @__PURE__ */ React7__namespace.createElement(
1590
1742
  "input",
1591
1743
  {
1592
1744
  ref: inputRef,
1593
1745
  type: "text",
1594
- 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" : ""}`,
1746
+ className: cn(
1747
+ "flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
1748
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
1749
+ "disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1750
+ showIcon ? "pl-10" : "pl-3",
1751
+ clearable && value ? "pr-10" : "pr-3",
1752
+ error && "border-red-500 ring-1 ring-red-500"
1753
+ ),
1595
1754
  value: displayValue,
1596
1755
  onClick: handleToggle,
1597
1756
  onBlur,
@@ -1607,13 +1766,13 @@ function TimePicker({
1607
1766
  "button",
1608
1767
  {
1609
1768
  type: "button",
1610
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors",
1769
+ className: "absolute right-3 top-1/2 -translate-y-1/2 transition-colors",
1611
1770
  onClick: handleClear,
1612
1771
  "aria-label": "Clear time",
1613
1772
  tabIndex: -1
1614
1773
  },
1615
1774
  "\u2715"
1616
- )), isOpen && !disabled && /* @__PURE__ */ React7__namespace.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-xs font-medium text-muted-foreground mb-2 text-center" }, use24Hour ? "Hour" : "Hour"), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, hours.map((hour) => {
1775
+ )), isOpen && !disabled && /* @__PURE__ */ React7__namespace.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, use24Hour ? "Hour" : "Hour"), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, hours.map((hour) => {
1617
1776
  const displayHour = use24Hour ? hour : hour;
1618
1777
  const isSelected = use24Hour ? timeValue?.hour === (hour === 0 ? 12 : hour > 12 ? hour - 12 : hour) && timeValue?.period === (hour >= 12 ? "PM" : "AM") : timeValue?.hour === hour;
1619
1778
  return /* @__PURE__ */ React7__namespace.createElement(
@@ -1621,7 +1780,12 @@ function TimePicker({
1621
1780
  {
1622
1781
  key: hour,
1623
1782
  type: "button",
1624
- 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" : ""}`,
1783
+ className: cn(
1784
+ "flex items-center justify-center h-8 w-full rounded",
1785
+ "border-none bg-transparent cursor-pointer text-sm transition-colors",
1786
+ "hover:bg-primary hover:text-primary-foreground",
1787
+ isSelected ? "bg-primary text-primary-foreground font-semibold" : ""
1788
+ ),
1625
1789
  onClick: () => {
1626
1790
  if (use24Hour) {
1627
1791
  const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
@@ -1641,24 +1805,34 @@ function TimePicker({
1641
1805
  },
1642
1806
  String(displayHour).padStart(2, "0")
1643
1807
  );
1644
- }))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-xs font-medium text-muted-foreground mb-2 text-center" }, "Minute"), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, minutes.map((minute) => {
1808
+ }))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, "Minute"), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, minutes.map((minute) => {
1645
1809
  const isSelected = timeValue?.minute === minute;
1646
1810
  return /* @__PURE__ */ React7__namespace.createElement(
1647
1811
  "button",
1648
1812
  {
1649
1813
  key: minute,
1650
1814
  type: "button",
1651
- 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" : ""}`,
1815
+ className: cn(
1816
+ "flex items-center justify-center h-8 w-full",
1817
+ "rounded border-none bg-transparent cursor-pointer text-sm transition-colors",
1818
+ "hover:bg-primary hover:text-primary-foreground",
1819
+ isSelected ? "bg-primary text-primary-foreground font-semibold" : ""
1820
+ ),
1652
1821
  onClick: () => handleMinuteChange(minute),
1653
1822
  "aria-label": `${String(minute).padStart(2, "0")} minutes`
1654
1823
  },
1655
1824
  String(minute).padStart(2, "0")
1656
1825
  );
1657
- }))), !use24Hour && /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col w-20" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-xs font-medium text-muted-foreground mb-2 text-center" }, "Period"), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React7__namespace.createElement(
1826
+ }))), !use24Hour && /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col w-20" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, "Period"), /* @__PURE__ */ React7__namespace.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React7__namespace.createElement(
1658
1827
  "button",
1659
1828
  {
1660
1829
  type: "button",
1661
- 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" : ""}`,
1830
+ className: cn(
1831
+ "flex items-center justify-center h-8 w-full",
1832
+ "rounded border-none bg-transparent cursor-pointer text-sm",
1833
+ "transition-colors hover:bg-primary hover:text-primary-foreground",
1834
+ timeValue?.period === "AM" ? "bg-muted font-semibold" : ""
1835
+ ),
1662
1836
  onClick: () => handlePeriodChange("AM")
1663
1837
  },
1664
1838
  "AM"
@@ -1666,7 +1840,12 @@ function TimePicker({
1666
1840
  "button",
1667
1841
  {
1668
1842
  type: "button",
1669
- 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" : ""}`,
1843
+ className: cn(
1844
+ "flex items-center justify-center h-8 w-full",
1845
+ "rounded border-none bg-transparent cursor-pointer text-sm",
1846
+ "transition-colors hover:bg-primary hover:text-primary-foreground",
1847
+ timeValue?.period === "PM" ? "bg-muted font-semibold" : ""
1848
+ ),
1670
1849
  onClick: () => handlePeriodChange("PM")
1671
1850
  },
1672
1851
  "PM"
@@ -1711,7 +1890,9 @@ function DateRangePicker({
1711
1890
  ...props
1712
1891
  }) {
1713
1892
  const [isOpen, setIsOpen] = React7__namespace.useState(false);
1714
- const [selectedMonth, setSelectedMonth] = React7__namespace.useState(value.start || /* @__PURE__ */ new Date());
1893
+ const [selectedMonth, setSelectedMonth] = React7__namespace.useState(
1894
+ value.start || /* @__PURE__ */ new Date()
1895
+ );
1715
1896
  const [rangeStart, setRangeStart] = React7__namespace.useState(value.start);
1716
1897
  const [rangeEnd, setRangeEnd] = React7__namespace.useState(value.end);
1717
1898
  const [hoverDate, setHoverDate] = React7__namespace.useState(null);
@@ -1809,7 +1990,7 @@ function DateRangePicker({
1809
1990
  "button",
1810
1991
  {
1811
1992
  type: "button",
1812
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent cursor-pointer",
1993
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
1813
1994
  onClick: handlePrevMonth,
1814
1995
  "aria-label": "Previous month"
1815
1996
  },
@@ -1818,19 +1999,30 @@ function DateRangePicker({
1818
1999
  "button",
1819
2000
  {
1820
2001
  type: "button",
1821
- className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent cursor-pointer",
2002
+ className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
1822
2003
  onClick: handleNextMonth,
1823
2004
  "aria-label": "Next month"
1824
2005
  },
1825
2006
  "\u2192"
1826
- )), /* @__PURE__ */ React7__namespace.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7__namespace.createElement("div", { key: day, className: "flex items-center justify-center h-8 w-full text-xs text-muted-foreground font-medium" }, day))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
2007
+ )), /* @__PURE__ */ React7__namespace.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7__namespace.createElement(
2008
+ "div",
2009
+ {
2010
+ key: day,
2011
+ className: "flex items-center justify-center h-8 w-full text-xs font-medium"
2012
+ },
2013
+ day
2014
+ ))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
1827
2015
  if (!date) {
1828
2016
  return /* @__PURE__ */ React7__namespace.createElement("div", { key: `empty-${index}` });
1829
2017
  }
1830
2018
  const isStart = rangeStart && date.toDateString() === rangeStart.toDateString();
1831
2019
  const isEnd = rangeEnd && date.toDateString() === rangeEnd.toDateString();
2020
+ const isRangeEndpoint = Boolean(isStart || isEnd);
1832
2021
  const isInRange = rangeStart && rangeEnd && isDateInRange(date, rangeStart, rangeEnd);
1833
2022
  const isInHoverRange = rangeStart && !rangeEnd && hoverDate && (date >= rangeStart && date <= hoverDate || date <= rangeStart && date >= hoverDate);
2023
+ const isRangeHighlight = Boolean(
2024
+ (isInRange || isInHoverRange) && !isRangeEndpoint
2025
+ );
1834
2026
  const isToday = date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
1835
2027
  const disabled2 = isDisabled(date);
1836
2028
  return /* @__PURE__ */ React7__namespace.createElement(
@@ -1838,7 +2030,14 @@ function DateRangePicker({
1838
2030
  {
1839
2031
  key: date.toISOString(),
1840
2032
  type: "button",
1841
- 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" : ""}`,
2033
+ className: cn(
2034
+ "flex items-center justify-center h-8 w-full rounded border-none bg-transparent",
2035
+ "cursor-pointer text-sm transition-colors hover:bg-muted",
2036
+ isRangeEndpoint && "bg-muted font-semibold",
2037
+ isRangeHighlight && "bg-muted/70",
2038
+ isToday && "border border-primary",
2039
+ disabled2 && "cursor-not-allowed opacity-50 pointer-events-none"
2040
+ ),
1842
2041
  onClick: () => !disabled2 && handleDateSelect(date),
1843
2042
  onMouseEnter: () => setHoverDate(date),
1844
2043
  onMouseLeave: () => setHoverDate(null),
@@ -1849,7 +2048,7 @@ function DateRangePicker({
1849
2048
  );
1850
2049
  })));
1851
2050
  };
1852
- const combinedClassName = `relative ${className}`.trim();
2051
+ const combinedClassName = cn("relative", className);
1853
2052
  const displayValue = rangeStart && rangeEnd ? `${formatDate2(rangeStart, format)}${separator}${formatDate2(rangeEnd, format)}` : rangeStart ? formatDate2(rangeStart, format) : "";
1854
2053
  return /* @__PURE__ */ React7__namespace.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7__namespace.createElement(
1855
2054
  "input",
@@ -1865,25 +2064,39 @@ function DateRangePicker({
1865
2064
  name: `${name}[end]`,
1866
2065
  value: rangeEnd ? rangeEnd.toISOString() : ""
1867
2066
  }
1868
- ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7__namespace.createElement("span", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none", "aria-hidden": "true" }, /* @__PURE__ */ React7__namespace.createElement(
1869
- "svg",
2067
+ ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7__namespace.createElement(
2068
+ "span",
1870
2069
  {
1871
- xmlns: "http://www.w3.org/2000/svg",
1872
- width: "18",
1873
- height: "18",
1874
- viewBox: "0 0 24 24",
1875
- fill: "none",
1876
- stroke: "currentColor",
1877
- strokeLinecap: "round",
1878
- strokeLinejoin: "round",
1879
- strokeWidth: "2"
2070
+ className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
2071
+ "aria-hidden": "true"
1880
2072
  },
1881
- /* @__PURE__ */ React7__namespace.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
1882
- )), /* @__PURE__ */ React7__namespace.createElement(
2073
+ /* @__PURE__ */ React7__namespace.createElement(
2074
+ "svg",
2075
+ {
2076
+ xmlns: "http://www.w3.org/2000/svg",
2077
+ width: "18",
2078
+ height: "18",
2079
+ viewBox: "0 0 24 24",
2080
+ fill: "none",
2081
+ stroke: "currentColor",
2082
+ strokeLinecap: "round",
2083
+ strokeLinejoin: "round",
2084
+ strokeWidth: "2"
2085
+ },
2086
+ /* @__PURE__ */ React7__namespace.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
2087
+ )
2088
+ ), /* @__PURE__ */ React7__namespace.createElement(
1883
2089
  "input",
1884
2090
  {
1885
2091
  type: "text",
1886
- 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" : ""}`,
2092
+ className: cn(
2093
+ "flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
2094
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
2095
+ "disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
2096
+ showIcon ? "pl-10" : "pl-3",
2097
+ clearable && (rangeStart || rangeEnd) ? "pr-10" : "pr-3",
2098
+ error && "border-red-500 ring-1 ring-red-500"
2099
+ ),
1887
2100
  value: displayValue,
1888
2101
  onClick: handleToggle,
1889
2102
  onBlur,
@@ -1899,13 +2112,13 @@ function DateRangePicker({
1899
2112
  "button",
1900
2113
  {
1901
2114
  type: "button",
1902
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors",
2115
+ className: "absolute right-3 top-1/2 -translate-y-1/2 transition-colors",
1903
2116
  onClick: handleClear,
1904
2117
  "aria-label": "Clear date range",
1905
2118
  tabIndex: -1
1906
2119
  },
1907
2120
  "\u2715"
1908
- )), isOpen && !disabled && /* @__PURE__ */ React7__namespace.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, renderCalendar(), rangeStart && !rangeEnd && /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-xs text-muted-foreground text-center pt-2 border-t border-border mt-2" }, "Select end date")));
2121
+ )), isOpen && !disabled && /* @__PURE__ */ React7__namespace.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, renderCalendar(), rangeStart && !rangeEnd && /* @__PURE__ */ React7__namespace.createElement("div", { className: "text-xs text-center pt-2 border-t border-border mt-2" }, "Select end date")));
1909
2122
  }
1910
2123
  DateRangePicker.displayName = "DateRangePicker";
1911
2124
  function htmlToMarkdown(html) {
@@ -1961,11 +2174,19 @@ function RichTextEditor({
1961
2174
  className = "",
1962
2175
  mode = "wysiwyg",
1963
2176
  allowModeSwitch = false,
1964
- placeholder = "Start typing...",
2177
+ placeholder = "Your message...",
1965
2178
  minHeight = "200px",
1966
2179
  maxHeight,
1967
2180
  showToolbar = true,
1968
- toolbarButtons = ["bold", "italic", "underline", "heading", "bulletList", "orderedList", "link"],
2181
+ toolbarButtons = [
2182
+ "bold",
2183
+ "italic",
2184
+ "underline",
2185
+ "heading",
2186
+ "bulletList",
2187
+ "orderedList",
2188
+ "link"
2189
+ ],
1969
2190
  ...props
1970
2191
  }) {
1971
2192
  const [currentMode, setCurrentMode] = React7__namespace.useState(mode);
@@ -2074,7 +2295,7 @@ function RichTextEditor({
2074
2295
  {
2075
2296
  key: buttonName,
2076
2297
  type: "button",
2077
- 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",
2298
+ 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",
2078
2299
  onClick: () => editorRef.current && button.action(editorRef.current),
2079
2300
  title: button.title,
2080
2301
  disabled: disabled || currentMode === "markdown",
@@ -2086,7 +2307,7 @@ function RichTextEditor({
2086
2307
  "button",
2087
2308
  {
2088
2309
  type: "button",
2089
- 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",
2310
+ 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",
2090
2311
  onClick: handleModeToggle,
2091
2312
  disabled,
2092
2313
  title: `Switch to ${currentMode === "wysiwyg" ? "Markdown" : "WYSIWYG"}`,
@@ -2097,7 +2318,7 @@ function RichTextEditor({
2097
2318
  "div",
2098
2319
  {
2099
2320
  ref: editorRef,
2100
- 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",
2321
+ className: "w-full p-3 text-base md:text-sm outline-none bg-transparent focus-visible:outline-none [&:empty:before]:content-[attr(data-placeholder)]",
2101
2322
  role: "textbox",
2102
2323
  contentEditable: !disabled,
2103
2324
  onInput: handleWysiwygChange,
@@ -2112,7 +2333,7 @@ function RichTextEditor({
2112
2333
  "textarea",
2113
2334
  {
2114
2335
  ref: textareaRef,
2115
- 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",
2336
+ className: "w-full p-3 text-base md:text-sm outline-none bg-transparent resize-none focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
2116
2337
  value: content,
2117
2338
  onChange: handleMarkdownChange,
2118
2339
  onBlur,