@codapet/design-system 0.4.4 → 0.4.6

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/index.d.mts CHANGED
@@ -251,9 +251,9 @@ interface InputProps extends Omit<React$1.ComponentProps<'input'>, 'size'>, Vari
251
251
  declare const Input: React$1.ForwardRefExoticComponent<Omit<InputProps, "ref"> & React$1.RefAttributes<HTMLInputElement>>;
252
252
 
253
253
  type DateFormat = 'MM/DD/YYYY' | 'DD/MM/YYYY' | 'YYYY-MM-DD' | 'DD-MM-YYYY' | 'MM-DD-YYYY' | 'DD.MM.YYYY' | 'MMMM D, YYYY' | 'D MMMM YYYY';
254
- type NativeInputProps$2 = Omit<React$1.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'min' | 'max' | 'size' | 'disabled' | 'onSelect'>;
255
- type FlattenedCalendarProps$1 = Omit<React$1.ComponentProps<typeof Calendar>, keyof React$1.InputHTMLAttributes<HTMLInputElement> | 'className' | 'mode' | 'selected' | 'onSelect' | 'month' | 'onMonthChange' | 'disabled' | 'captionLayout' | 'showOutsideDays' | 'classNames'>;
256
- interface DateInputProps extends NativeInputProps$2, FlattenedCalendarProps$1 {
254
+ type NativeInputProps = Omit<React$1.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'min' | 'max' | 'size' | 'disabled' | 'onSelect'>;
255
+ type FlattenedCalendarProps$1 = Omit<React$1.ComponentProps<typeof Calendar>, keyof React$1.InputHTMLAttributes<HTMLInputElement> | 'className' | 'mode' | 'selected' | 'onSelect' | 'month' | 'onMonthChange' | 'disabled' | 'captionLayout' | 'showOutsideDays' | 'classNames' | 'components' | 'formatters' | 'buttonVariant'>;
256
+ interface DateInputProps extends NativeInputProps, FlattenedCalendarProps$1 {
257
257
  date: Date | null;
258
258
  setDate: (date: Date | null) => void;
259
259
  maxDate?: Date | null;
@@ -273,12 +273,14 @@ interface DateInputProps extends NativeInputProps$2, FlattenedCalendarProps$1 {
273
273
  captionLayout?: React$1.ComponentProps<typeof Calendar>['captionLayout'];
274
274
  showOutsideDays?: React$1.ComponentProps<typeof Calendar>['showOutsideDays'];
275
275
  classNames?: React$1.ComponentProps<typeof Calendar>['classNames'];
276
+ components?: React$1.ComponentProps<typeof Calendar>['components'];
277
+ formatters?: React$1.ComponentProps<typeof Calendar>['formatters'];
278
+ buttonVariant?: React$1.ComponentProps<typeof Calendar>['buttonVariant'];
276
279
  }
277
- declare function DateInput({ date, setDate, maxDate, minDate, disableFuture, className, inputClassName, calendarClassName, inputDisabled, dateFormat, mode, selected, onSelect, month, onMonthChange, disabled: calendarDisabled, captionLayout, showOutsideDays, classNames, placeholder, onBlur, ...restProps }: DateInputProps): react_jsx_runtime.JSX.Element;
280
+ declare function DateInput({ date, setDate, maxDate, minDate, disableFuture, className, inputClassName, calendarClassName, inputDisabled, dateFormat, mode, selected, onSelect, month, onMonthChange, disabled: calendarDisabled, captionLayout, showOutsideDays, classNames, components, formatters, buttonVariant, placeholder, onBlur, ...restProps }: DateInputProps): react_jsx_runtime.JSX.Element;
278
281
 
279
- type NativeInputProps$1 = Omit<React$1.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'min' | 'max' | 'size' | 'disabled' | 'onSelect'>;
280
- type FlattenedCalendarProps = Omit<React$1.ComponentProps<typeof Calendar>, keyof React$1.InputHTMLAttributes<HTMLInputElement> | 'className' | 'mode' | 'selected' | 'onSelect' | 'month' | 'onMonthChange' | 'disabled' | 'captionLayout' | 'showOutsideDays' | 'classNames'>;
281
- interface DateRangeInputProps extends NativeInputProps$1, FlattenedCalendarProps {
282
+ type FlattenedCalendarProps = Omit<React$1.ComponentProps<typeof Calendar>, keyof React$1.InputHTMLAttributes<HTMLInputElement> | 'className' | 'mode' | 'selected' | 'onSelect' | 'month' | 'onMonthChange' | 'disabled' | 'captionLayout' | 'showOutsideDays' | 'classNames' | 'components' | 'formatters' | 'buttonVariant'>;
283
+ interface DateRangeInputProps extends FlattenedCalendarProps {
282
284
  dateRange: DateRange | undefined;
283
285
  setDateRange: (range: DateRange | undefined) => void;
284
286
  maxDate?: Date | null;
@@ -286,9 +288,11 @@ interface DateRangeInputProps extends NativeInputProps$1, FlattenedCalendarProps
286
288
  disableFuture?: boolean;
287
289
  inputDisabled?: boolean;
288
290
  size?: VariantProps<typeof inputVariants>['size'];
291
+ className?: string;
289
292
  inputClassName?: string;
290
293
  calendarClassName?: string;
291
294
  dateFormat?: DateFormat;
295
+ placeholder?: string;
292
296
  selected?: DateRange;
293
297
  onSelect?: (range: DateRange | undefined) => void;
294
298
  month?: React$1.ComponentProps<typeof Calendar>['month'];
@@ -297,8 +301,11 @@ interface DateRangeInputProps extends NativeInputProps$1, FlattenedCalendarProps
297
301
  captionLayout?: React$1.ComponentProps<typeof Calendar>['captionLayout'];
298
302
  showOutsideDays?: React$1.ComponentProps<typeof Calendar>['showOutsideDays'];
299
303
  classNames?: React$1.ComponentProps<typeof Calendar>['classNames'];
304
+ components?: React$1.ComponentProps<typeof Calendar>['components'];
305
+ formatters?: React$1.ComponentProps<typeof Calendar>['formatters'];
306
+ buttonVariant?: React$1.ComponentProps<typeof Calendar>['buttonVariant'];
300
307
  }
301
- declare function DateRangeInput({ dateRange, setDateRange, maxDate, minDate, disableFuture, className, inputClassName, calendarClassName, inputDisabled, dateFormat, selected, onSelect, month, onMonthChange, disabled: calendarDisabled, captionLayout, showOutsideDays, classNames, placeholder, onBlur, ...restProps }: DateRangeInputProps): react_jsx_runtime.JSX.Element;
308
+ declare function DateRangeInput({ dateRange, setDateRange, maxDate, minDate, disableFuture, className, inputClassName, calendarClassName, inputDisabled, dateFormat, selected, onSelect, month, onMonthChange, disabled: calendarDisabled, captionLayout, showOutsideDays, classNames, components, formatters, buttonVariant, placeholder, size, ...restProps }: DateRangeInputProps): react_jsx_runtime.JSX.Element;
302
309
 
303
310
  declare function Drawer({ ...props }: React$1.ComponentProps<typeof Drawer$1.Root>): react_jsx_runtime.JSX.Element;
304
311
  declare function DrawerTrigger({ ...props }: React$1.ComponentProps<typeof Drawer$1.Trigger>): react_jsx_runtime.JSX.Element;
@@ -576,13 +583,13 @@ declare function TabsList({ className, ...props }: React$1.ComponentProps<typeof
576
583
  declare function TabsTrigger({ className, ...props }: React$1.ComponentProps<typeof TabsPrimitive.Trigger>): react_jsx_runtime.JSX.Element;
577
584
  declare function TabsContent({ className, ...props }: React$1.ComponentProps<typeof TabsPrimitive.Content>): react_jsx_runtime.JSX.Element;
578
585
 
579
- type TimeFormat = '12h' | '24h';
586
+ type TimeFormat = '12h' | '24h' | 'h:mm a' | 'h:mm A';
580
587
  interface TimeValue {
581
588
  hours: number;
582
589
  minutes: number;
583
590
  }
584
- type NativeInputProps = Omit<React$1.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'min' | 'max' | 'size' | 'disabled' | 'onSelect'>;
585
- interface TimeInputProps extends NativeInputProps {
591
+ type BaseInputProps = Omit<React$1.ComponentProps<typeof Input>, 'value' | 'onChange' | 'min' | 'max' | 'size' | 'disabled' | 'onSelect' | 'rightIcon' | 'ref'>;
592
+ interface TimeInputProps extends BaseInputProps {
586
593
  time: TimeValue | null;
587
594
  setTime: (time: TimeValue | null) => void;
588
595
  timeFormat?: TimeFormat;
@@ -590,8 +597,10 @@ interface TimeInputProps extends NativeInputProps {
590
597
  inputDisabled?: boolean;
591
598
  size?: VariantProps<typeof inputVariants>['size'];
592
599
  inputClassName?: string;
600
+ icon?: React$1.ReactNode;
601
+ formatDisplay?: (time: TimeValue) => string;
593
602
  }
594
- declare function TimeInput({ time, setTime, timeFormat, minuteStep, inputDisabled, className, inputClassName, size, placeholder, onBlur, ...restProps }: TimeInputProps): react_jsx_runtime.JSX.Element;
603
+ declare function TimeInput({ time, setTime, timeFormat, minuteStep, inputDisabled, className, inputClassName, size, placeholder, onBlur, icon, formatDisplay, ...restProps }: TimeInputProps): react_jsx_runtime.JSX.Element;
595
604
 
596
605
  declare const toggleVariants: (props?: ({
597
606
  variant?: "default" | "outline" | null | undefined;
package/dist/index.mjs CHANGED
@@ -2174,6 +2174,9 @@ function DateInput({
2174
2174
  captionLayout = "dropdown",
2175
2175
  showOutsideDays = false,
2176
2176
  classNames,
2177
+ components,
2178
+ formatters,
2179
+ buttonVariant,
2177
2180
  placeholder,
2178
2181
  onBlur,
2179
2182
  ...restProps
@@ -2269,6 +2272,9 @@ function DateInput({
2269
2272
  calendarClassName
2270
2273
  ),
2271
2274
  classNames,
2275
+ components,
2276
+ formatters,
2277
+ buttonVariant,
2272
2278
  onSelect: onSelect ?? defaultCalendarOnSelect,
2273
2279
  disabled: calendarDisabled ?? defaultCalendarDisabled
2274
2280
  };
@@ -2351,11 +2357,7 @@ function DateInput({
2351
2357
 
2352
2358
  // src/components/ui/date-range-input.tsx
2353
2359
  import "class-variance-authority";
2354
- import {
2355
- format as dateFnsFormat2,
2356
- parse as dateFnsParse2,
2357
- isValid as isValid2
2358
- } from "date-fns";
2360
+ import { format as dateFnsFormat2, isValid as isValid2 } from "date-fns";
2359
2361
  import { CalendarDays as CalendarDays2 } from "lucide-react";
2360
2362
  import * as React21 from "react";
2361
2363
  import { jsx as jsx23, jsxs as jsxs11 } from "react/jsx-runtime";
@@ -2379,65 +2381,6 @@ var DATE_FORMAT_PLACEHOLDER2 = {
2379
2381
  "MMMM D, YYYY": "Month d, yyyy",
2380
2382
  "D MMMM YYYY": "d Month yyyy"
2381
2383
  };
2382
- var INPUT_PROP_KEYS2 = /* @__PURE__ */ new Set([
2383
- "accept",
2384
- "alt",
2385
- "autoComplete",
2386
- "autoFocus",
2387
- "capture",
2388
- "checked",
2389
- "dirName",
2390
- "form",
2391
- "formAction",
2392
- "formEncType",
2393
- "formMethod",
2394
- "formNoValidate",
2395
- "formTarget",
2396
- "height",
2397
- "list",
2398
- "maxLength",
2399
- "minLength",
2400
- "multiple",
2401
- "name",
2402
- "pattern",
2403
- "readOnly",
2404
- "required",
2405
- "size",
2406
- "src",
2407
- "step",
2408
- "type",
2409
- "width",
2410
- "id",
2411
- "inputMode",
2412
- "lang",
2413
- "tabIndex",
2414
- "title",
2415
- "role",
2416
- "style",
2417
- "onFocus",
2418
- "onFocusCapture",
2419
- "onBlurCapture",
2420
- "onInput",
2421
- "onInvalid",
2422
- "onKeyDownCapture",
2423
- "onKeyPress",
2424
- "onKeyPressCapture",
2425
- "onKeyUp",
2426
- "onKeyUpCapture",
2427
- "onPaste",
2428
- "onPasteCapture",
2429
- "onPointerDown",
2430
- "onPointerDownCapture",
2431
- "onPointerUp",
2432
- "onPointerUpCapture",
2433
- "onMouseDown",
2434
- "onMouseDownCapture",
2435
- "onMouseUp",
2436
- "onMouseUpCapture",
2437
- "onCompositionEnd",
2438
- "onCompositionStart",
2439
- "onCompositionUpdate"
2440
- ]);
2441
2384
  function formatDate2(date, dateFormat = "MM/DD/YYYY") {
2442
2385
  if (!date || !isValid2(date)) {
2443
2386
  return "";
@@ -2452,27 +2395,6 @@ function formatRange(range, dateFormat = "MM/DD/YYYY") {
2452
2395
  if (from) return from;
2453
2396
  return "";
2454
2397
  }
2455
- function parseRange(value, dateFormat = "MM/DD/YYYY") {
2456
- if (!value) return null;
2457
- const parts = value.split(/\s*[\u2013\-]\s*/);
2458
- const fromStr = parts[0]?.trim();
2459
- if (!fromStr) return null;
2460
- const fromParsed = dateFnsParse2(
2461
- fromStr,
2462
- DATE_FORMAT_TOKENS2[dateFormat],
2463
- /* @__PURE__ */ new Date()
2464
- );
2465
- if (!isValid2(fromParsed)) return null;
2466
- const toStr = parts[1]?.trim();
2467
- if (!toStr) return { from: fromParsed, to: void 0 };
2468
- const toParsed = dateFnsParse2(
2469
- toStr,
2470
- DATE_FORMAT_TOKENS2[dateFormat],
2471
- /* @__PURE__ */ new Date()
2472
- );
2473
- if (!isValid2(toParsed)) return { from: fromParsed, to: void 0 };
2474
- return { from: fromParsed, to: toParsed };
2475
- }
2476
2398
  function rangePlaceholder(dateFormat) {
2477
2399
  const p = DATE_FORMAT_PLACEHOLDER2[dateFormat];
2478
2400
  return `${p} \u2013 ${p}`;
@@ -2496,8 +2418,11 @@ function DateRangeInput({
2496
2418
  captionLayout = "dropdown",
2497
2419
  showOutsideDays = false,
2498
2420
  classNames,
2421
+ components,
2422
+ formatters,
2423
+ buttonVariant,
2499
2424
  placeholder,
2500
- onBlur,
2425
+ size,
2501
2426
  ...restProps
2502
2427
  }) {
2503
2428
  const resolvedPlaceholder = placeholder ?? rangePlaceholder(dateFormat);
@@ -2505,23 +2430,12 @@ function DateRangeInput({
2505
2430
  const [monthState, setMonthState] = React21.useState(
2506
2431
  dateRange?.from ?? null
2507
2432
  );
2508
- const [value, setValue] = React21.useState(formatRange(dateRange, dateFormat));
2509
- const [inputProps, calendarProps] = React21.useMemo(() => {
2510
- const nextInputProps = {};
2511
- const nextCalendarProps = {};
2512
- for (const [key, val] of Object.entries(restProps)) {
2513
- const isInputProp = INPUT_PROP_KEYS2.has(key) || key.startsWith("aria-") || key.startsWith("data-");
2514
- if (isInputProp) {
2515
- nextInputProps[key] = val;
2516
- } else {
2517
- nextCalendarProps[key] = val;
2518
- }
2433
+ const displayValue = formatRange(dateRange, dateFormat);
2434
+ React21.useEffect(() => {
2435
+ if (dateRange?.from) {
2436
+ setMonthState(dateRange.from);
2519
2437
  }
2520
- return [
2521
- nextInputProps,
2522
- nextCalendarProps
2523
- ];
2524
- }, [restProps]);
2438
+ }, [dateRange]);
2525
2439
  const today = React21.useMemo(() => {
2526
2440
  const d = /* @__PURE__ */ new Date();
2527
2441
  d.setHours(0, 0, 0, 0);
@@ -2551,12 +2465,6 @@ function DateRangeInput({
2551
2465
  }
2552
2466
  return null;
2553
2467
  }, [minDate]);
2554
- React21.useEffect(() => {
2555
- setValue(formatRange(dateRange, dateFormat));
2556
- if (dateRange?.from) {
2557
- setMonthState(dateRange.from);
2558
- }
2559
- }, [dateRange, dateFormat]);
2560
2468
  const effectiveMonth = month ?? monthState ?? void 0;
2561
2469
  const effectiveSelected = selected ?? dateRange;
2562
2470
  const isInputDisabled = inputDisabled ?? (typeof calendarDisabled === "boolean" ? calendarDisabled : false);
@@ -2584,7 +2492,7 @@ function DateRangeInput({
2584
2492
  setOpen(false);
2585
2493
  };
2586
2494
  const resolvedCalendarProps = {
2587
- ...calendarProps,
2495
+ ...restProps,
2588
2496
  mode: "range",
2589
2497
  selected: effectiveSelected,
2590
2498
  captionLayout,
@@ -2596,117 +2504,56 @@ function DateRangeInput({
2596
2504
  calendarClassName
2597
2505
  ),
2598
2506
  classNames,
2507
+ components,
2508
+ formatters,
2509
+ buttonVariant,
2599
2510
  onSelect: handleCalendarSelect,
2600
2511
  disabled: calendarDisabled ?? defaultCalendarDisabled
2601
2512
  };
2602
- const handleInputChange = (e) => {
2603
- const inputValue = e.target.value;
2604
- setValue(inputValue);
2605
- if (inputValue === "") {
2606
- setDateRange(void 0);
2607
- return;
2608
- }
2609
- const parsed = parseRange(inputValue, dateFormat);
2610
- if (!parsed || !parsed.from) return;
2611
- const from = new Date(parsed.from);
2612
- from.setHours(0, 0, 0, 0);
2613
- if (!isWithinBounds(from)) return;
2614
- if (parsed.to) {
2615
- const to = new Date(parsed.to);
2616
- to.setHours(0, 0, 0, 0);
2617
- if (isWithinBounds(to) && from <= to) {
2618
- setDateRange(parsed);
2619
- setMonthState(from);
2620
- }
2621
- } else {
2622
- setDateRange({ from: parsed.from, to: void 0 });
2623
- setMonthState(from);
2624
- }
2625
- };
2626
- const handleBlur = (e) => {
2627
- onBlur?.(e);
2628
- if (value === "") {
2629
- if (dateRange !== void 0) {
2630
- setDateRange(void 0);
2631
- }
2632
- return;
2633
- }
2634
- const parsed = parseRange(value, dateFormat);
2635
- if (!parsed || !parsed.from) {
2636
- setValue(formatRange(dateRange, dateFormat));
2637
- return;
2638
- }
2639
- const from = new Date(parsed.from);
2640
- from.setHours(0, 0, 0, 0);
2641
- if (!isWithinBounds(from)) {
2642
- setValue(formatRange(dateRange, dateFormat));
2643
- return;
2644
- }
2645
- if (parsed.to) {
2646
- const to = new Date(parsed.to);
2647
- to.setHours(0, 0, 0, 0);
2648
- if (!isWithinBounds(to) || from > to) {
2649
- setValue(formatRange(dateRange, dateFormat));
2650
- }
2651
- }
2652
- };
2653
2513
  return /* @__PURE__ */ jsx23("div", { className: cn("relative flex gap-2", className), children: /* @__PURE__ */ jsxs11(Popover, { open, onOpenChange: setOpen, children: [
2654
- /* @__PURE__ */ jsx23(PopoverTrigger, { asChild: true, disabled: isInputDisabled, children: /* @__PURE__ */ jsx23("div", { className: "w-full relative", children: /* @__PURE__ */ jsx23(
2655
- Input,
2514
+ /* @__PURE__ */ jsx23(PopoverTrigger, { asChild: true, disabled: isInputDisabled, children: /* @__PURE__ */ jsxs11(
2515
+ Button,
2656
2516
  {
2657
- value,
2658
- placeholder: resolvedPlaceholder,
2659
- className: cn("bg-background cursor-pointer", inputClassName),
2660
- onChange: handleInputChange,
2661
- onBlur: handleBlur,
2517
+ type: "button",
2518
+ variant: "outline",
2519
+ className: cn(
2520
+ inputVariants({ size }),
2521
+ "bg-background cursor-pointer w-full text-left flex items-center justify-between gap-2 font-normal",
2522
+ isInputDisabled && "pointer-events-none cursor-not-allowed opacity-50",
2523
+ inputClassName
2524
+ ),
2662
2525
  disabled: isInputDisabled,
2663
- onKeyDown: (e) => {
2664
- if (e.key === "ArrowDown" && !isInputDisabled) {
2665
- e.preventDefault();
2666
- setOpen(true);
2667
- }
2668
- },
2669
- rightIcon: /* @__PURE__ */ jsx23(CalendarDays2, { className: "h-4 w-4 text-muted-foreground" }),
2670
- rightIconOnClick: isInputDisabled ? void 0 : () => setOpen(!open),
2671
- rightIconButtonProps: { disabled: isInputDisabled },
2672
- ...inputProps
2673
- }
2674
- ) }) }),
2675
- /* @__PURE__ */ jsxs11(
2676
- PopoverContent,
2677
- {
2678
- className: "w-auto p-0 flex flex-col overflow-y-auto max-h-[min(90dvh,520px)]",
2679
- align: "end",
2680
- alignOffset: -8,
2681
- sideOffset: 10,
2682
- side: "top",
2683
2526
  children: [
2684
- /* @__PURE__ */ jsx23(Calendar, { ...resolvedCalendarProps }),
2685
- /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-2 px-2 py-2", children: [
2686
- /* @__PURE__ */ jsx23(
2687
- Button,
2688
- {
2689
- variant: "ghost-secondary",
2690
- size: "sm",
2691
- onClick: handleClear,
2692
- type: "button",
2693
- children: "Clear"
2694
- }
2695
- ),
2696
- /* @__PURE__ */ jsx23(
2697
- Button,
2698
- {
2699
- variant: "primary",
2700
- size: "sm",
2701
- onClick: handleAdd,
2702
- type: "button",
2703
- children: "Add"
2704
- }
2705
- )
2706
- ] })
2527
+ displayValue || resolvedPlaceholder,
2528
+ /* @__PURE__ */ jsx23(CalendarDays2, { className: "h-4 w-4 text-muted-foreground shrink-0" })
2707
2529
  ]
2708
2530
  }
2709
- )
2531
+ ) }),
2532
+ /* @__PURE__ */ jsxs11(PopoverContent, { className: "p-0 flex flex-col overflow-y-auto max-h-[min(90dvh,520px)] md:w-[350px] w-[var(--radix-popover-trigger-width)] ", children: [
2533
+ /* @__PURE__ */ jsx23(Calendar, { ...resolvedCalendarProps }),
2534
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-2 px-2 py-2", children: [
2535
+ /* @__PURE__ */ jsx23(
2536
+ Button,
2537
+ {
2538
+ variant: "ghost-secondary",
2539
+ size: "sm",
2540
+ onClick: handleClear,
2541
+ type: "button",
2542
+ children: "Clear"
2543
+ }
2544
+ ),
2545
+ /* @__PURE__ */ jsx23(
2546
+ Button,
2547
+ {
2548
+ variant: "primary",
2549
+ size: "sm",
2550
+ onClick: handleAdd,
2551
+ type: "button",
2552
+ children: "Add"
2553
+ }
2554
+ )
2555
+ ] })
2556
+ ] })
2710
2557
  ] }) });
2711
2558
  }
2712
2559
 
@@ -5309,7 +5156,7 @@ function TabsList({
5309
5156
  {
5310
5157
  "data-slot": "tabs-list",
5311
5158
  className: cn(
5312
- " text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
5159
+ "text-muted-foreground flex h-9 items-center rounded-lg p-[3px] overflow-x-auto",
5313
5160
  className
5314
5161
  ),
5315
5162
  ...props
@@ -5325,7 +5172,7 @@ function TabsTrigger({
5325
5172
  {
5326
5173
  "data-slot": "tabs-trigger",
5327
5174
  className: cn(
5328
- "cursor-pointer data-[state=active]:border-b-2 data-[state=active]:border-brand-normal border-0 border-t-0 rounded-none data-[state=active]:text-black data-[state=active]:font-semibold data-[state=active]:bg-background dark:data-[state=active]:text-white focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 px-2 py-[6px] font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 text-zinc-500 font-sans border-b-1 border-b-gray-stroke-light text-sm",
5175
+ "cursor-pointer data-[state=active]:border-b-2 data-[state=active]:border-brand-normal border-0 border-t-0 rounded-none data-[state=active]:text-black data-[state=active]:font-semibold data-[state=active]:bg-background dark:data-[state=active]:text-white focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 dark:text-muted-foreground inline-flex h-[calc(100%-1px)] shrink-0 items-center justify-center gap-1.5 px-2 py-[6px] font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 text-zinc-500 font-sans border-b-1 border-b-gray-stroke-light text-sm",
5329
5176
  className
5330
5177
  ),
5331
5178
  ...props
@@ -5351,26 +5198,47 @@ import "class-variance-authority";
5351
5198
  import { Clock } from "lucide-react";
5352
5199
  import * as React46 from "react";
5353
5200
  import { jsx as jsx49, jsxs as jsxs24 } from "react/jsx-runtime";
5201
+ var TIME_FORMAT_PLACEHOLDER = {
5202
+ "12h": "hh:mm AM/PM",
5203
+ "24h": "HH:mm",
5204
+ "h:mm a": "h:mm am/pm",
5205
+ "h:mm A": "h:mm AM/PM"
5206
+ };
5207
+ function is24HourFormat(tf) {
5208
+ return tf === "24h";
5209
+ }
5354
5210
  function formatTime(time, timeFormat = "12h") {
5355
5211
  if (!time) return "";
5356
- if (timeFormat === "24h") {
5357
- return `${String(time.hours).padStart(2, "0")}:${String(time.minutes).padStart(2, "0")}`;
5212
+ const { hours, minutes } = time;
5213
+ const h24 = String(hours).padStart(2, "0");
5214
+ const m = String(minutes).padStart(2, "0");
5215
+ const h12 = hours % 12 || 12;
5216
+ const h12p = String(h12).padStart(2, "0");
5217
+ const period = hours >= 12 ? "PM" : "AM";
5218
+ switch (timeFormat) {
5219
+ case "24h":
5220
+ return `${h24}:${m}`;
5221
+ case "h:mm a":
5222
+ return `${h12}:${m} ${period.toLowerCase()}`;
5223
+ case "h:mm A":
5224
+ return `${h12}:${m} ${period}`;
5225
+ case "12h":
5226
+ default:
5227
+ return `${h12p}:${m} ${period}`;
5358
5228
  }
5359
- const period = time.hours >= 12 ? "PM" : "AM";
5360
- const h12 = time.hours % 12 || 12;
5361
- return `${String(h12).padStart(2, "0")}:${String(time.minutes).padStart(2, "0")} ${period}`;
5362
5229
  }
5363
5230
  function parseTime(value, timeFormat = "12h") {
5364
5231
  if (!value.trim()) return null;
5365
- if (timeFormat === "24h") {
5366
- const match2 = value.trim().match(/^(\d{1,2}):(\d{2})$/);
5232
+ const v = value.trim();
5233
+ if (is24HourFormat(timeFormat)) {
5234
+ const match2 = v.match(/^(\d{1,2}):(\d{2})$/);
5367
5235
  if (!match2) return null;
5368
5236
  const hours2 = parseInt(match2[1], 10);
5369
5237
  const minutes2 = parseInt(match2[2], 10);
5370
5238
  if (hours2 < 0 || hours2 > 23 || minutes2 < 0 || minutes2 > 59) return null;
5371
5239
  return { hours: hours2, minutes: minutes2 };
5372
5240
  }
5373
- const match = value.trim().match(/^(\d{1,2}):(\d{2})\s*(AM|PM|am|pm)$/i);
5241
+ const match = v.match(/^(\d{1,2}):(\d{2})\s*(AM|PM|am|pm)$/i);
5374
5242
  if (!match) return null;
5375
5243
  let hours = parseInt(match[1], 10);
5376
5244
  const minutes = parseInt(match[2], 10);
@@ -5381,7 +5249,7 @@ function parseTime(value, timeFormat = "12h") {
5381
5249
  return { hours, minutes };
5382
5250
  }
5383
5251
  function getDisplayHour(hours, timeFormat) {
5384
- if (timeFormat === "24h") return hours;
5252
+ if (is24HourFormat(timeFormat)) return hours;
5385
5253
  return hours % 12 || 12;
5386
5254
  }
5387
5255
  function getPeriod(hours) {
@@ -5398,17 +5266,27 @@ function TimeInput({
5398
5266
  size,
5399
5267
  placeholder,
5400
5268
  onBlur,
5269
+ icon,
5270
+ formatDisplay,
5401
5271
  ...restProps
5402
5272
  }) {
5403
- const resolvedPlaceholder = placeholder ?? (timeFormat === "12h" ? "hh:mm AM/PM" : "HH:mm");
5273
+ const resolvedPlaceholder = placeholder ?? TIME_FORMAT_PLACEHOLDER[timeFormat];
5274
+ const displayFormat = React46.useCallback(
5275
+ (t) => {
5276
+ if (!t) return "";
5277
+ if (formatDisplay) return formatDisplay(t);
5278
+ return formatTime(t, timeFormat);
5279
+ },
5280
+ [formatDisplay, timeFormat]
5281
+ );
5404
5282
  const [open, setOpen] = React46.useState(false);
5405
- const [value, setValue] = React46.useState(formatTime(time, timeFormat));
5283
+ const [value, setValue] = React46.useState(displayFormat(time));
5406
5284
  const hoursRef = React46.useRef(null);
5407
5285
  const minutesRef = React46.useRef(null);
5408
5286
  const periodRef = React46.useRef(null);
5409
5287
  React46.useEffect(() => {
5410
- setValue(formatTime(time, timeFormat));
5411
- }, [time, timeFormat]);
5288
+ setValue(displayFormat(time));
5289
+ }, [time, displayFormat]);
5412
5290
  const scrollToSelected = React46.useCallback(() => {
5413
5291
  requestAnimationFrame(() => {
5414
5292
  for (const ref of [hoursRef, minutesRef, periodRef]) {
@@ -5446,12 +5324,12 @@ function TimeInput({
5446
5324
  }
5447
5325
  const parsed = parseTime(value, timeFormat);
5448
5326
  if (!parsed) {
5449
- setValue(formatTime(time, timeFormat));
5327
+ setValue(displayFormat(time));
5450
5328
  }
5451
5329
  };
5452
5330
  const handleHourSelect = (hour) => {
5453
5331
  let h24;
5454
- if (timeFormat === "24h") {
5332
+ if (is24HourFormat(timeFormat)) {
5455
5333
  h24 = hour;
5456
5334
  } else {
5457
5335
  const currentPeriod = time ? getPeriod(time.hours) : "AM";
@@ -5472,7 +5350,7 @@ function TimeInput({
5472
5350
  const newHours = period === "AM" ? currentH12 : currentH12 + 12;
5473
5351
  setTime({ hours: newHours, minutes: time?.minutes ?? 0 });
5474
5352
  };
5475
- const hoursList = timeFormat === "12h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 24 }, (_, i) => i);
5353
+ const hoursList = is24HourFormat(timeFormat) ? Array.from({ length: 24 }, (_, i) => i) : Array.from({ length: 12 }, (_, i) => i + 1);
5476
5354
  const minutesList = Array.from(
5477
5355
  { length: Math.ceil(60 / minuteStep) },
5478
5356
  (_, i) => i * minuteStep
@@ -5500,7 +5378,7 @@ function TimeInput({
5500
5378
  setOpen(true);
5501
5379
  }
5502
5380
  },
5503
- rightIcon: /* @__PURE__ */ jsx49(Clock, { className: "h-4 w-4 text-muted-foreground" }),
5381
+ rightIcon: icon !== void 0 ? icon : /* @__PURE__ */ jsx49(Clock, { className: "h-4 w-4 text-muted-foreground" }),
5504
5382
  ...restProps
5505
5383
  }
5506
5384
  ) }) }),
@@ -5508,10 +5386,6 @@ function TimeInput({
5508
5386
  PopoverContent,
5509
5387
  {
5510
5388
  className: "w-auto p-0 ",
5511
- align: "end",
5512
- alignOffset: -8,
5513
- sideOffset: 10,
5514
- side: "top",
5515
5389
  onOpenAutoFocus: (e) => e.preventDefault(),
5516
5390
  children: /* @__PURE__ */ jsxs24("div", { className: "flex divide-x", children: [
5517
5391
  /* @__PURE__ */ jsx49("div", { className: "h-56 w-16 overflow-y-auto overscroll-y-contain [-webkit-overflow-scrolling:touch]", children: /* @__PURE__ */ jsx49("div", { ref: hoursRef, className: "flex flex-col p-1 ", children: hoursList.map((h) => /* @__PURE__ */ jsx49(
@@ -5529,7 +5403,7 @@ function TimeInput({
5529
5403
  },
5530
5404
  h
5531
5405
  )) }) }),
5532
- /* @__PURE__ */ jsx49("div", { className: "h-56 w-16 overflow-y-auto overscroll-y-contain [-webkit-overflow-scrolling:touch]", children: /* @__PURE__ */ jsx49("div", { ref: minutesRef, className: "flex flex-col p-1", children: minutesList.map((m) => /* @__PURE__ */ jsx49(
5406
+ /* @__PURE__ */ jsx49("div", { className: "h-56 w-16 overflow-y-auto overscroll-y-contain [-webkit-overflow-scrolling:touch]", children: /* @__PURE__ */ jsx49("div", { ref: minutesRef, className: "flex flex-col p-1 ", children: minutesList.map((m) => /* @__PURE__ */ jsx49(
5533
5407
  Button,
5534
5408
  {
5535
5409
  variant: "ghost",
@@ -5544,7 +5418,7 @@ function TimeInput({
5544
5418
  },
5545
5419
  m
5546
5420
  )) }) }),
5547
- timeFormat === "12h" && /* @__PURE__ */ jsx49("div", { className: "flex flex-col p-1 justify-center gap-1", children: ["AM", "PM"].map((p) => /* @__PURE__ */ jsx49(
5421
+ !is24HourFormat(timeFormat) && /* @__PURE__ */ jsx49("div", { className: "flex flex-col p-1 justify-center gap-1", children: ["AM", "PM"].map((p) => /* @__PURE__ */ jsx49(
5548
5422
  Button,
5549
5423
  {
5550
5424
  variant: "ghost",