@algodomain/smart-forms 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/LICENSE +3 -0
  2. package/README.md +243 -0
  3. package/dist/{SmartFormProvider-DyJoDBjQ.d.cts → SmartFormProvider-BdyRQakk.d.cts} +1 -0
  4. package/dist/{SmartFormProvider-DyJoDBjQ.d.ts → SmartFormProvider-BdyRQakk.d.ts} +1 -0
  5. package/dist/{SmartTags-HmvmCJPT.d.cts → SmartTags-DEpmTDF5.d.cts} +42 -18
  6. package/dist/{SmartTags-HmvmCJPT.d.ts → SmartTags-DEpmTDF5.d.ts} +42 -18
  7. package/dist/{chunk-KDPN4CHW.js → chunk-BNQNL7GF.js} +658 -145
  8. package/dist/chunk-BNQNL7GF.js.map +1 -0
  9. package/dist/{chunk-5LRBJEZW.js → chunk-RHECLW3K.js} +80 -7
  10. package/dist/chunk-RHECLW3K.js.map +1 -0
  11. package/dist/{chunk-CJ55WKPC.cjs → chunk-VGP3HY5Y.cjs} +758 -235
  12. package/dist/chunk-VGP3HY5Y.cjs.map +1 -0
  13. package/dist/{chunk-4H5U5IHH.cjs → chunk-WIBCOQPP.cjs} +80 -7
  14. package/dist/chunk-WIBCOQPP.cjs.map +1 -0
  15. package/dist/fields.cjs +212 -481
  16. package/dist/fields.cjs.map +1 -1
  17. package/dist/fields.d.cts +14 -22
  18. package/dist/fields.d.ts +14 -22
  19. package/dist/fields.js +66 -338
  20. package/dist/fields.js.map +1 -1
  21. package/dist/index.cjs +42 -30
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +7 -3
  24. package/dist/index.d.ts +7 -3
  25. package/dist/index.js +17 -9
  26. package/dist/index.js.map +1 -1
  27. package/dist/opinionated.cjs +18 -18
  28. package/dist/opinionated.d.cts +1 -1
  29. package/dist/opinionated.d.ts +1 -1
  30. package/dist/opinionated.js +2 -2
  31. package/package.json +4 -2
  32. package/dist/chunk-4H5U5IHH.cjs.map +0 -1
  33. package/dist/chunk-5LRBJEZW.js.map +0 -1
  34. package/dist/chunk-CJ55WKPC.cjs.map +0 -1
  35. package/dist/chunk-KDPN4CHW.js.map +0 -1
@@ -1,16 +1,19 @@
1
- import { useFormField, useFieldDetection, Label, TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, cn, Input } from './chunk-5LRBJEZW.js';
2
- import * as React4 from 'react';
3
- import { useRef, useEffect, useMemo, useState } from 'react';
1
+ import { useSmartForm, useFormField, useFieldDetection, Label, TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, cn, SmartInput, Input } from './chunk-RHECLW3K.js';
2
+ import * as React6 from 'react';
3
+ import React6__default, { useRef, useEffect, useState } from 'react';
4
4
  import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
5
- import { InfoIcon, Calendar as Calendar$1, X, CheckIcon, CircleIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon } from 'lucide-react';
5
+ import { InfoIcon, SearchIcon, CalendarIcon, ChevronDownIcon, X, CheckIcon, CircleIcon, ChevronsUpDown, Check, Plus, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon } from 'lucide-react';
6
6
  import { jsxs, jsx } from 'react/jsx-runtime';
7
7
  import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
8
8
  import * as SelectPrimitive from '@radix-ui/react-select';
9
- import { format } from 'date-fns';
9
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
10
10
  import { Slot } from '@radix-ui/react-slot';
11
11
  import { cva } from 'class-variance-authority';
12
+ import { Command as Command$1 } from 'cmdk';
13
+ import { eachYearOfInterval, endOfYear, startOfYear, eachMonthOfInterval, isBefore, isAfter, format } from 'date-fns';
12
14
  import { getDefaultClassNames, DayPicker } from 'react-day-picker';
13
- import * as PopoverPrimitive from '@radix-ui/react-popover';
15
+ import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
16
+ import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
14
17
 
15
18
  function Checkbox({
16
19
  className,
@@ -44,12 +47,18 @@ var SmartCheckbox = ({
44
47
  required = false,
45
48
  defaultValue,
46
49
  info,
47
- subLabel
50
+ subLabel,
51
+ disabled,
52
+ hidden
48
53
  }) => {
54
+ const { formData } = useSmartForm();
49
55
  const { value, error, onChange, fieldRef, registerValidation } = useFormField(field);
50
56
  const fieldDetection = useFieldDetection();
51
57
  const hasRegistered = useRef(false);
52
58
  const hasSetDefault = useRef(false);
59
+ const isDisabled = typeof disabled === "function" ? disabled(formData) : disabled || false;
60
+ const isHidden = typeof hidden === "function" ? hidden(formData) : hidden || false;
61
+ if (isHidden) return null;
53
62
  useEffect(() => {
54
63
  if (validation && !hasRegistered.current) {
55
64
  hasRegistered.current = true;
@@ -79,7 +88,8 @@ var SmartCheckbox = ({
79
88
  onCheckedChange: (checked) => onChange(!!checked),
80
89
  className: error ? "border-destructive" : "",
81
90
  "data-field": field,
82
- id: `${field}-checkbox`
91
+ id: `${field}-checkbox`,
92
+ disabled: isDisabled
83
93
  }
84
94
  ),
85
95
  /* @__PURE__ */ jsxs(Label, { htmlFor: `${field}-checkbox`, className: "text-sm font-normal cursor-pointer", children: [
@@ -146,12 +156,18 @@ var SmartRadioGroup = ({
146
156
  required = false,
147
157
  defaultValue,
148
158
  info,
149
- subLabel
159
+ subLabel,
160
+ disabled,
161
+ hidden
150
162
  }) => {
163
+ const { formData } = useSmartForm();
151
164
  const { value, error, onChange, fieldRef, registerValidation } = useFormField(field);
152
165
  const fieldDetection = useFieldDetection();
153
166
  const hasRegistered = useRef(false);
154
167
  const hasSetDefault = useRef(false);
168
+ const isDisabled = typeof disabled === "function" ? disabled(formData) : disabled || false;
169
+ const isHidden = typeof hidden === "function" ? hidden(formData) : hidden || false;
170
+ if (isHidden) return null;
155
171
  useEffect(() => {
156
172
  if (validation && !hasRegistered.current) {
157
173
  hasRegistered.current = true;
@@ -193,6 +209,7 @@ var SmartRadioGroup = ({
193
209
  ref: fieldRef,
194
210
  "data-field": field,
195
211
  name: name || field,
212
+ disabled: isDisabled,
196
213
  children: options.map((option) => /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
197
214
  /* @__PURE__ */ jsx(
198
215
  RadioGroupItem,
@@ -347,12 +364,18 @@ var SmartSelect = ({
347
364
  required = false,
348
365
  defaultValue,
349
366
  info,
350
- subLabel
367
+ subLabel,
368
+ disabled,
369
+ hidden
351
370
  }) => {
371
+ const { formData } = useSmartForm();
352
372
  const { value, error, onChange, fieldRef, registerValidation } = useFormField(field);
353
373
  const fieldDetection = useFieldDetection();
354
374
  const hasRegistered = useRef(false);
355
375
  const hasSetDefault = useRef(false);
376
+ const isDisabled = typeof disabled === "function" ? disabled(formData) : disabled || false;
377
+ const isHidden = typeof hidden === "function" ? hidden(formData) : hidden || false;
378
+ if (isHidden) return null;
356
379
  useEffect(() => {
357
380
  if (validation && !hasRegistered.current) {
358
381
  hasRegistered.current = true;
@@ -397,6 +420,7 @@ var SmartSelect = ({
397
420
  ref: fieldRef,
398
421
  className: `w-full ${error ? "border-destructive" : ""} ${className}`,
399
422
  "data-field": field,
423
+ disabled: isDisabled,
400
424
  children: /* @__PURE__ */ jsx(SelectValue, { placeholder: placeholder || `Select ${label || field}` })
401
425
  }
402
426
  ),
@@ -407,6 +431,36 @@ var SmartSelect = ({
407
431
  error && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm mt-1", children: error })
408
432
  ] });
409
433
  };
434
+ function Popover({
435
+ ...props
436
+ }) {
437
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
438
+ }
439
+ function PopoverTrigger({
440
+ ...props
441
+ }) {
442
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
443
+ }
444
+ function PopoverContent({
445
+ className,
446
+ align = "center",
447
+ sideOffset = 4,
448
+ ...props
449
+ }) {
450
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
451
+ PopoverPrimitive.Content,
452
+ {
453
+ "data-slot": "popover-content",
454
+ align,
455
+ sideOffset,
456
+ className: cn(
457
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
458
+ className
459
+ ),
460
+ ...props
461
+ }
462
+ ) });
463
+ }
410
464
  var buttonVariants = cva(
411
465
  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
412
466
  {
@@ -449,6 +503,323 @@ function Button({
449
503
  }
450
504
  );
451
505
  }
506
+ function Command({
507
+ className,
508
+ ...props
509
+ }) {
510
+ return /* @__PURE__ */ jsx(
511
+ Command$1,
512
+ {
513
+ "data-slot": "command",
514
+ className: cn(
515
+ "bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
516
+ className
517
+ ),
518
+ ...props
519
+ }
520
+ );
521
+ }
522
+ function CommandInput({
523
+ className,
524
+ ...props
525
+ }) {
526
+ return /* @__PURE__ */ jsxs(
527
+ "div",
528
+ {
529
+ "data-slot": "command-input-wrapper",
530
+ className: "flex h-9 items-center gap-2 border-b px-3",
531
+ children: [
532
+ /* @__PURE__ */ jsx(SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
533
+ /* @__PURE__ */ jsx(
534
+ Command$1.Input,
535
+ {
536
+ "data-slot": "command-input",
537
+ className: cn(
538
+ "placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
539
+ className
540
+ ),
541
+ ...props
542
+ }
543
+ )
544
+ ]
545
+ }
546
+ );
547
+ }
548
+ function CommandList({
549
+ className,
550
+ ...props
551
+ }) {
552
+ return /* @__PURE__ */ jsx(
553
+ Command$1.List,
554
+ {
555
+ "data-slot": "command-list",
556
+ className: cn(
557
+ "max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto",
558
+ className
559
+ ),
560
+ ...props
561
+ }
562
+ );
563
+ }
564
+ function CommandEmpty({
565
+ ...props
566
+ }) {
567
+ return /* @__PURE__ */ jsx(
568
+ Command$1.Empty,
569
+ {
570
+ "data-slot": "command-empty",
571
+ className: "py-6 text-center text-sm",
572
+ ...props
573
+ }
574
+ );
575
+ }
576
+ function CommandGroup({
577
+ className,
578
+ ...props
579
+ }) {
580
+ return /* @__PURE__ */ jsx(
581
+ Command$1.Group,
582
+ {
583
+ "data-slot": "command-group",
584
+ className: cn(
585
+ "text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
586
+ className
587
+ ),
588
+ ...props
589
+ }
590
+ );
591
+ }
592
+ function CommandItem({
593
+ className,
594
+ ...props
595
+ }) {
596
+ return /* @__PURE__ */ jsx(
597
+ Command$1.Item,
598
+ {
599
+ "data-slot": "command-item",
600
+ className: cn(
601
+ "data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
602
+ className
603
+ ),
604
+ ...props
605
+ }
606
+ );
607
+ }
608
+ var badgeVariants = cva(
609
+ "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
610
+ {
611
+ variants: {
612
+ variant: {
613
+ default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
614
+ secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
615
+ destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
616
+ outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
617
+ }
618
+ },
619
+ defaultVariants: {
620
+ variant: "default"
621
+ }
622
+ }
623
+ );
624
+ function Badge({
625
+ className,
626
+ variant,
627
+ asChild = false,
628
+ ...props
629
+ }) {
630
+ const Comp = asChild ? Slot : "span";
631
+ return /* @__PURE__ */ jsx(
632
+ Comp,
633
+ {
634
+ "data-slot": "badge",
635
+ className: cn(badgeVariants({ variant }), className),
636
+ ...props
637
+ }
638
+ );
639
+ }
640
+ function Combobox({
641
+ options,
642
+ value = "",
643
+ onChange,
644
+ placeholder = "Select option...",
645
+ searchPlaceholder = "Search...",
646
+ noResultsText = "No results found.",
647
+ width = "100%",
648
+ isDisabled = false,
649
+ allowCustom = false
650
+ }) {
651
+ const [open, setOpen] = React6__default.useState(false);
652
+ const [searchValue, setSearchValue] = useState("");
653
+ const containerStyles = {
654
+ width
655
+ };
656
+ const combinedOptions = allowCustom ? [
657
+ ...options,
658
+ ...searchValue && !options.some(
659
+ (opt) => opt.label.toLowerCase() === searchValue.toLowerCase()
660
+ ) ? [
661
+ {
662
+ value: searchValue.toLowerCase().replace(/\s+/g, "-"),
663
+ label: searchValue
664
+ }
665
+ ] : []
666
+ ] : options;
667
+ const filteredOptions = combinedOptions.filter(
668
+ (option) => option.label.toLowerCase().includes(searchValue.toLowerCase())
669
+ );
670
+ return /* @__PURE__ */ jsx("div", { style: containerStyles, children: /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
671
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
672
+ Button,
673
+ {
674
+ variant: "outline",
675
+ role: "combobox",
676
+ "aria-expanded": open,
677
+ style: containerStyles,
678
+ className: `flex items-center justify-between relative ${isDisabled ? "cursor-not-allowed opacity-50" : ""}`,
679
+ disabled: isDisabled,
680
+ children: [
681
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0 text-left", children: /* @__PURE__ */ jsx("div", { className: "truncate", children: value ? combinedOptions.find((option) => option.value === value)?.label || value : placeholder }) }),
682
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: "ml-2 h-4 w-4 flex-shrink-0 opacity-50" })
683
+ ]
684
+ }
685
+ ) }),
686
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-[var(--radix-popover-trigger-width)] p-0", children: /* @__PURE__ */ jsxs(Command, { className: "w-full", children: [
687
+ /* @__PURE__ */ jsx(
688
+ CommandInput,
689
+ {
690
+ value: searchValue,
691
+ onValueChange: setSearchValue,
692
+ placeholder: searchPlaceholder,
693
+ className: "h-9"
694
+ }
695
+ ),
696
+ /* @__PURE__ */ jsx(CommandList, { children: filteredOptions.length > 0 ? /* @__PURE__ */ jsx(CommandGroup, { className: "max-h-[200px] overflow-y-auto", children: filteredOptions.map((option) => /* @__PURE__ */ jsxs(
697
+ CommandItem,
698
+ {
699
+ value: option.value,
700
+ onSelect: (currentValue) => {
701
+ onChange(currentValue === value ? "" : currentValue);
702
+ setOpen(false);
703
+ setSearchValue("");
704
+ },
705
+ className: "flex items-center",
706
+ style: { width: "100%" },
707
+ children: [
708
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center w-full min-w-0", children: [
709
+ /* @__PURE__ */ jsx(
710
+ Check,
711
+ {
712
+ className: `mr-2 h-4 w-4 flex-shrink-0 ${value === option.value ? "opacity-100" : "opacity-0"}`
713
+ }
714
+ ),
715
+ /* @__PURE__ */ jsx("span", { className: "truncate flex-1", children: option.label })
716
+ ] }),
717
+ option.badge && /* @__PURE__ */ jsx(
718
+ Badge,
719
+ {
720
+ variant: "outline",
721
+ className: "ml-2 text-[10px] px-2 py-0 h-5 font-normal",
722
+ children: option.badge
723
+ }
724
+ )
725
+ ]
726
+ },
727
+ option.value
728
+ )) }) : /* @__PURE__ */ jsxs(CommandEmpty, { children: [
729
+ allowCustom && searchValue && /* @__PURE__ */ jsxs(
730
+ Button,
731
+ {
732
+ variant: "ghost",
733
+ className: "w-full justify-start",
734
+ onClick: () => {
735
+ const newOption = {
736
+ value: searchValue.toLowerCase().replace(/\s+/g, "-")};
737
+ onChange(newOption.value);
738
+ setOpen(false);
739
+ setSearchValue("");
740
+ },
741
+ children: [
742
+ /* @__PURE__ */ jsx(Plus, { className: "mr-2 h-4 w-4" }),
743
+ 'Add "',
744
+ searchValue,
745
+ '" as a new option'
746
+ ]
747
+ }
748
+ ),
749
+ !searchValue && noResultsText
750
+ ] }) })
751
+ ] }) })
752
+ ] }) });
753
+ }
754
+ var SmartCombobox = ({
755
+ field,
756
+ label,
757
+ options,
758
+ className = "",
759
+ placeholder,
760
+ allowCustom = false,
761
+ validation,
762
+ required = false,
763
+ defaultValue,
764
+ info,
765
+ subLabel,
766
+ disabled,
767
+ hidden
768
+ }) => {
769
+ const { formData } = useSmartForm();
770
+ const { value, error, onChange, fieldRef, registerValidation } = useFormField(field);
771
+ const fieldDetection = useFieldDetection();
772
+ const hasRegistered = useRef(false);
773
+ const hasSetDefault = useRef(false);
774
+ const isDisabled = typeof disabled === "function" ? disabled(formData) : disabled || false;
775
+ const isHidden = typeof hidden === "function" ? hidden(formData) : hidden || false;
776
+ if (isHidden) return null;
777
+ useEffect(() => {
778
+ if (validation && !hasRegistered.current) {
779
+ hasRegistered.current = true;
780
+ registerValidation(field, validation);
781
+ }
782
+ }, [validation, field, registerValidation]);
783
+ useEffect(() => {
784
+ if (fieldDetection?.registerField) {
785
+ fieldDetection.registerField(field);
786
+ }
787
+ }, [field, fieldDetection]);
788
+ useEffect(() => {
789
+ if (defaultValue !== void 0 && !hasSetDefault.current && (value === void 0 || value === null || value === "")) {
790
+ onChange(defaultValue);
791
+ hasSetDefault.current = true;
792
+ }
793
+ }, [defaultValue, value, onChange]);
794
+ return /* @__PURE__ */ jsxs("div", { className: `flex-1 min-w-0 ${className}`, children: [
795
+ label && /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
796
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
797
+ /* @__PURE__ */ jsxs(Label, { className: "text-sm font-medium text-foreground", children: [
798
+ label,
799
+ " ",
800
+ required && /* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" })
801
+ ] }),
802
+ info && /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
803
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(InfoIcon, { className: "h-4 w-4 text-muted-foreground cursor-pointer mr-2" }) }),
804
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { className: "max-w-xs", children: info }) })
805
+ ] }) })
806
+ ] }),
807
+ subLabel && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: subLabel })
808
+ ] }),
809
+ /* @__PURE__ */ jsx("div", { ref: fieldRef, "data-field": field, children: /* @__PURE__ */ jsx(
810
+ Combobox,
811
+ {
812
+ options: (options || []).map((o) => ({ value: o.value, label: o.label })),
813
+ value: value || "",
814
+ onChange: (newValue) => onChange(newValue),
815
+ placeholder: placeholder || (label ? `Select ${label.toLowerCase()}` : `Select ${field}`),
816
+ allowCustom,
817
+ isDisabled
818
+ }
819
+ ) }),
820
+ error && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm mt-1", children: error })
821
+ ] });
822
+ };
452
823
  function Calendar({
453
824
  className,
454
825
  classNames,
@@ -601,8 +972,8 @@ function CalendarDayButton({
601
972
  ...props
602
973
  }) {
603
974
  const defaultClassNames = getDefaultClassNames();
604
- const ref = React4.useRef(null);
605
- React4.useEffect(() => {
975
+ const ref = React6.useRef(null);
976
+ React6.useEffect(() => {
606
977
  if (modifiers.focused) ref.current?.focus();
607
978
  }, [modifiers.focused]);
608
979
  return /* @__PURE__ */ jsx(
@@ -625,158 +996,295 @@ function CalendarDayButton({
625
996
  }
626
997
  );
627
998
  }
628
- function Popover({
999
+ function Collapsible({
629
1000
  ...props
630
1001
  }) {
631
- return /* @__PURE__ */ jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
1002
+ return /* @__PURE__ */ jsx(CollapsiblePrimitive.Root, { "data-slot": "collapsible", ...props });
632
1003
  }
633
- function PopoverTrigger({
1004
+ function CollapsibleTrigger2({
634
1005
  ...props
635
1006
  }) {
636
- return /* @__PURE__ */ jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
1007
+ return /* @__PURE__ */ jsx(
1008
+ CollapsiblePrimitive.CollapsibleTrigger,
1009
+ {
1010
+ "data-slot": "collapsible-trigger",
1011
+ ...props
1012
+ }
1013
+ );
637
1014
  }
638
- function PopoverContent({
1015
+ function CollapsibleContent2({
1016
+ ...props
1017
+ }) {
1018
+ return /* @__PURE__ */ jsx(
1019
+ CollapsiblePrimitive.CollapsibleContent,
1020
+ {
1021
+ "data-slot": "collapsible-content",
1022
+ ...props
1023
+ }
1024
+ );
1025
+ }
1026
+ function ScrollArea({
639
1027
  className,
640
- align = "center",
641
- sideOffset = 4,
1028
+ children,
642
1029
  ...props
643
1030
  }) {
644
- return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
645
- PopoverPrimitive.Content,
1031
+ return /* @__PURE__ */ jsxs(
1032
+ ScrollAreaPrimitive.Root,
646
1033
  {
647
- "data-slot": "popover-content",
648
- align,
649
- sideOffset,
1034
+ "data-slot": "scroll-area",
1035
+ className: cn("relative", className),
1036
+ ...props,
1037
+ children: [
1038
+ /* @__PURE__ */ jsx(
1039
+ ScrollAreaPrimitive.Viewport,
1040
+ {
1041
+ "data-slot": "scroll-area-viewport",
1042
+ className: "focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1",
1043
+ children
1044
+ }
1045
+ ),
1046
+ /* @__PURE__ */ jsx(ScrollBar, {}),
1047
+ /* @__PURE__ */ jsx(ScrollAreaPrimitive.Corner, {})
1048
+ ]
1049
+ }
1050
+ );
1051
+ }
1052
+ function ScrollBar({
1053
+ className,
1054
+ orientation = "vertical",
1055
+ ...props
1056
+ }) {
1057
+ return /* @__PURE__ */ jsx(
1058
+ ScrollAreaPrimitive.ScrollAreaScrollbar,
1059
+ {
1060
+ "data-slot": "scroll-area-scrollbar",
1061
+ orientation,
650
1062
  className: cn(
651
- "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
1063
+ "flex touch-none p-px transition-colors select-none",
1064
+ orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent",
1065
+ orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent",
652
1066
  className
653
1067
  ),
654
- ...props
1068
+ ...props,
1069
+ children: /* @__PURE__ */ jsx(
1070
+ ScrollAreaPrimitive.ScrollAreaThumb,
1071
+ {
1072
+ "data-slot": "scroll-area-thumb",
1073
+ className: "bg-border relative flex-1 rounded-full"
1074
+ }
1075
+ )
655
1076
  }
656
- ) });
1077
+ );
657
1078
  }
658
1079
  var SmartDatePicker = ({
659
1080
  field,
660
1081
  label,
661
- className = "",
662
- placeholder,
663
- validation,
664
- required = false,
665
- allowPast = true,
666
- allowFuture = true,
667
- valueAsString = true,
668
- minDate,
669
- maxDate,
670
- defaultValue,
671
- info,
672
- subLabel
1082
+ className,
1083
+ ...props
673
1084
  }) => {
674
- const { value, error, onChange, fieldRef, registerValidation } = useFormField(field);
675
- const fieldDetection = useFieldDetection();
676
- const hasRegistered = useRef(false);
677
- const hasSetDefault = useRef(false);
678
- const parsedValue = useMemo(() => {
679
- if (!value) return void 0;
680
- if (value instanceof Date) return value;
681
- const d = new Date(value);
682
- return isNaN(d.getTime()) ? void 0 : d;
683
- }, [value]);
684
- const [open, setOpen] = useState(false);
685
- useEffect(() => {
686
- if (validation && !hasRegistered.current) {
687
- hasRegistered.current = true;
688
- registerValidation(field, validation);
1085
+ const today = /* @__PURE__ */ new Date();
1086
+ const [month, setMonth] = useState(today);
1087
+ const [date, setDate] = useState(today);
1088
+ const [isYearView, setIsYearView] = useState(false);
1089
+ const [isOpen, setIsOpen] = useState(false);
1090
+ const startDate = new Date(1980, 6);
1091
+ const endDate = new Date(2030, 6);
1092
+ const years = eachYearOfInterval({
1093
+ start: startOfYear(startDate),
1094
+ end: endOfYear(endDate)
1095
+ });
1096
+ const handleDateSelect = (selectedDate) => {
1097
+ setDate(selectedDate);
1098
+ if (selectedDate) {
1099
+ setIsOpen(false);
1100
+ setIsYearView(false);
689
1101
  }
690
- }, [validation, field, registerValidation]);
691
- useEffect(() => {
692
- if (fieldDetection?.registerField) {
693
- fieldDetection.registerField(field);
694
- }
695
- }, [field, fieldDetection]);
696
- useEffect(() => {
697
- if (defaultValue !== void 0 && !hasSetDefault.current && (value === void 0 || value === null || value === "")) {
698
- onChange(defaultValue);
699
- hasSetDefault.current = true;
700
- }
701
- }, [defaultValue, value, onChange]);
702
- const today = useMemo(() => /* @__PURE__ */ new Date(), []);
703
- const disabledMatcher = (date) => {
704
- if (!allowPast) {
705
- const startOfToday = new Date(today.getFullYear(), today.getMonth(), today.getDate());
706
- if (date < startOfToday) return true;
707
- }
708
- if (!allowFuture) {
709
- const startOfTomorrow = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1);
710
- if (date >= startOfTomorrow) return true;
711
- }
712
- if (minDate && date < new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate())) return true;
713
- if (maxDate && date > new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate())) return true;
714
- return false;
715
1102
  };
716
- const handleSelect = (selected) => {
717
- if (!selected) {
718
- onChange(void 0);
719
- return;
720
- }
721
- if (valueAsString) {
722
- const iso = format(selected, "yyyy-MM-dd");
723
- onChange(iso);
724
- } else {
725
- onChange(selected);
726
- }
727
- setOpen(false);
728
- };
729
- const buttonText = useMemo(() => {
730
- if (!parsedValue) return placeholder || `Select ${label || field}`;
731
- return format(parsedValue, "dd/MM/yyyy");
732
- }, [parsedValue, placeholder, label, field]);
733
- return /* @__PURE__ */ jsxs("div", { className: cn("flex-1 min-w-0", className), children: [
734
- label && /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
735
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
736
- /* @__PURE__ */ jsxs(Label, { className: "text-sm font-medium text-foreground", children: [
737
- label,
738
- " ",
739
- required && /* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" })
740
- ] }),
741
- info && /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
742
- /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(InfoIcon, { className: "h-4 w-4 text-muted-foreground cursor-pointer mr-2" }) }),
743
- /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { className: "max-w-xs", children: info }) })
744
- ] }) })
745
- ] }),
746
- subLabel && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: subLabel })
747
- ] }),
748
- /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
749
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
750
- Button,
751
- {
752
- ref: fieldRef,
753
- variant: "outline",
754
- className: cn(
755
- "w-full justify-start text-left font-normal",
756
- !parsedValue && "text-muted-foreground",
757
- error && "border-destructive"
1103
+ return /* @__PURE__ */ jsx("div", { className: "w-[280px]", children: /* @__PURE__ */ jsxs(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
1104
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
1105
+ SmartInput,
1106
+ {
1107
+ field,
1108
+ label,
1109
+ syncValue: date,
1110
+ type: "date",
1111
+ className: `${className ?? ""} cursor-pointer`,
1112
+ icon: /* @__PURE__ */ jsx(CalendarIcon, { className: "size-4" }),
1113
+ iconPosition: "right",
1114
+ ...props
1115
+ }
1116
+ ) }) }),
1117
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-auto p-0", align: "start", children: /* @__PURE__ */ jsx(
1118
+ Calendar,
1119
+ {
1120
+ mode: "single",
1121
+ selected: date,
1122
+ onSelect: handleDateSelect,
1123
+ month,
1124
+ onMonthChange: setMonth,
1125
+ defaultMonth: /* @__PURE__ */ new Date(),
1126
+ startMonth: startDate,
1127
+ endMonth: endDate,
1128
+ className: "overflow-hidden rounded-md p-2",
1129
+ classNames: {
1130
+ month_caption: "ml-2.5 mr-20 justify-start",
1131
+ nav: "flex absolute w-fit right-0 items-center"
1132
+ },
1133
+ components: {
1134
+ CaptionLabel: (props2) => /* @__PURE__ */ jsx(
1135
+ CaptionLabel,
1136
+ {
1137
+ isYearView,
1138
+ setIsYearView,
1139
+ ...props2
1140
+ }
758
1141
  ),
759
- "data-field": field,
760
- children: [
761
- /* @__PURE__ */ jsx(Calendar$1, { className: "mr-2 h-4 w-4" }),
762
- buttonText
763
- ]
1142
+ MonthGrid: (props2) => {
1143
+ return /* @__PURE__ */ jsx(
1144
+ MonthGrid,
1145
+ {
1146
+ className: props2.className,
1147
+ isYearView,
1148
+ setIsYearView,
1149
+ startDate,
1150
+ endDate,
1151
+ years,
1152
+ currentYear: month.getFullYear(),
1153
+ currentMonth: month.getMonth(),
1154
+ onMonthSelect: (selectedMonth) => {
1155
+ setMonth(selectedMonth);
1156
+ setIsYearView(false);
1157
+ },
1158
+ children: props2.children
1159
+ }
1160
+ );
1161
+ }
764
1162
  }
765
- ) }),
766
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-auto p-0", align: "start", children: /* @__PURE__ */ jsx(
767
- Calendar,
1163
+ }
1164
+ ) })
1165
+ ] }) });
1166
+ };
1167
+ function MonthGrid({
1168
+ className,
1169
+ children,
1170
+ isYearView,
1171
+ startDate,
1172
+ endDate,
1173
+ years,
1174
+ currentYear,
1175
+ currentMonth,
1176
+ onMonthSelect
1177
+ }) {
1178
+ const currentYearRef = useRef(null);
1179
+ const currentMonthButtonRef = useRef(null);
1180
+ const scrollAreaRef = useRef(null);
1181
+ useEffect(() => {
1182
+ if (isYearView && currentYearRef.current && scrollAreaRef.current) {
1183
+ const viewport = scrollAreaRef.current.querySelector(
1184
+ "[data-radix-scroll-area-viewport]"
1185
+ );
1186
+ if (viewport) {
1187
+ const yearTop = currentYearRef.current.offsetTop;
1188
+ viewport.scrollTop = yearTop;
1189
+ }
1190
+ setTimeout(() => {
1191
+ currentMonthButtonRef.current?.focus();
1192
+ }, 100);
1193
+ }
1194
+ }, [isYearView]);
1195
+ return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1196
+ /* @__PURE__ */ jsx("table", { className, children }),
1197
+ isYearView && /* @__PURE__ */ jsx("div", { className: "bg-background absolute inset-0 z-20 -mx-2 -mb-2", children: /* @__PURE__ */ jsx(ScrollArea, { ref: scrollAreaRef, className: "h-full", children: years.map((year) => {
1198
+ const months = eachMonthOfInterval({
1199
+ start: startOfYear(year),
1200
+ end: endOfYear(year)
1201
+ });
1202
+ const isCurrentYear = year.getFullYear() === currentYear;
1203
+ return /* @__PURE__ */ jsx(
1204
+ "div",
768
1205
  {
769
- mode: "single",
770
- selected: parsedValue,
771
- onSelect: handleSelect,
772
- disabled: disabledMatcher,
773
- initialFocus: true
774
- }
775
- ) })
776
- ] }),
777
- error && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm mt-1", children: error })
1206
+ ref: isCurrentYear ? currentYearRef : void 0,
1207
+ children: /* @__PURE__ */ jsx(
1208
+ CollapsibleYear,
1209
+ {
1210
+ title: year.getFullYear().toString(),
1211
+ open: isCurrentYear,
1212
+ children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-2", children: months.map((month) => {
1213
+ const isDisabled = isBefore(month, startDate) || isAfter(month, endDate);
1214
+ const isCurrentMonth = month.getMonth() === currentMonth && year.getFullYear() === currentYear;
1215
+ return /* @__PURE__ */ jsx(
1216
+ "button",
1217
+ {
1218
+ ref: isCurrentMonth ? currentMonthButtonRef : void 0,
1219
+ className: `inline-flex h-7 items-center justify-center rounded-md px-3 text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 ${isCurrentMonth ? "bg-primary text-primary-foreground hover:bg-primary/90" : "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground"}`,
1220
+ disabled: isDisabled,
1221
+ onClick: () => onMonthSelect(month),
1222
+ children: format(month, "MMM")
1223
+ },
1224
+ month.getTime()
1225
+ );
1226
+ }) })
1227
+ }
1228
+ )
1229
+ },
1230
+ year.getFullYear()
1231
+ );
1232
+ }) }) })
778
1233
  ] });
779
- };
1234
+ }
1235
+ function CaptionLabel({
1236
+ children,
1237
+ isYearView,
1238
+ setIsYearView
1239
+ }) {
1240
+ return /* @__PURE__ */ jsxs(
1241
+ Button,
1242
+ {
1243
+ className: "data-[state=open]:text-muted-foreground/80 -ms-2 flex items-center gap-2 text-sm font-medium hover:bg-transparent [&[data-state=open]>svg]:rotate-180",
1244
+ variant: "ghost",
1245
+ size: "sm",
1246
+ onClick: () => setIsYearView((prev) => !prev),
1247
+ "data-state": isYearView ? "open" : "closed",
1248
+ children: [
1249
+ children,
1250
+ /* @__PURE__ */ jsx(
1251
+ ChevronDownIcon,
1252
+ {
1253
+ className: "text-muted-foreground/80 shrink-0 transition-transform duration-200",
1254
+ "aria-hidden": "true"
1255
+ }
1256
+ )
1257
+ ]
1258
+ }
1259
+ );
1260
+ }
1261
+ function CollapsibleYear({
1262
+ title,
1263
+ children,
1264
+ open
1265
+ }) {
1266
+ return /* @__PURE__ */ jsxs(Collapsible, { className: "border-t px-2 py-1.5", defaultOpen: open, children: [
1267
+ /* @__PURE__ */ jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs(
1268
+ Button,
1269
+ {
1270
+ className: "flex w-full justify-start gap-2 text-sm font-medium hover:bg-transparent [&[data-state=open]>svg]:rotate-180",
1271
+ variant: "ghost",
1272
+ size: "sm",
1273
+ children: [
1274
+ /* @__PURE__ */ jsx(
1275
+ ChevronDownIcon,
1276
+ {
1277
+ className: "text-muted-foreground/80 shrink-0 transition-transform duration-200",
1278
+ "aria-hidden": "true"
1279
+ }
1280
+ ),
1281
+ title
1282
+ ]
1283
+ }
1284
+ ) }),
1285
+ /* @__PURE__ */ jsx(CollapsibleContent2, { className: "data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down overflow-hidden px-3 py-1 text-sm transition-all", children })
1286
+ ] });
1287
+ }
780
1288
  var SmartTags = ({
781
1289
  field,
782
1290
  label,
@@ -790,15 +1298,20 @@ var SmartTags = ({
790
1298
  minLength,
791
1299
  allowDuplicates = false,
792
1300
  disabled = false,
1301
+ hidden = false,
793
1302
  onTagAdd,
794
1303
  onTagRemove,
795
1304
  info,
796
1305
  subLabel
797
1306
  }) => {
1307
+ const { formData } = useSmartForm();
798
1308
  const { value, error, onChange, fieldRef, registerValidation } = useFormField(field);
799
1309
  const fieldDetection = useFieldDetection();
800
1310
  const hasRegistered = useRef(false);
801
1311
  const hasSetDefault = useRef(false);
1312
+ const isDisabled = typeof disabled === "function" ? disabled(formData) : disabled || false;
1313
+ const isHidden = typeof hidden === "function" ? hidden(formData) : hidden || false;
1314
+ if (isHidden) return null;
802
1315
  const [tags, setTags] = useState([]);
803
1316
  const [inputValue, setInputValue] = useState("");
804
1317
  const inputRef = useRef(null);
@@ -893,7 +1406,7 @@ var SmartTags = ({
893
1406
  "focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
894
1407
  "flex flex-wrap items-center gap-2 cursor-text",
895
1408
  error && "border-destructive focus-within:ring-destructive",
896
- disabled && "cursor-not-allowed opacity-50"
1409
+ isDisabled && "cursor-not-allowed opacity-50"
897
1410
  ),
898
1411
  "data-field": field,
899
1412
  onClick: () => inputRef.current?.focus(),
@@ -915,7 +1428,7 @@ var SmartTags = ({
915
1428
  e.stopPropagation();
916
1429
  removeTag(tagText);
917
1430
  },
918
- disabled,
1431
+ disabled: isDisabled,
919
1432
  children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
920
1433
  }
921
1434
  )
@@ -933,7 +1446,7 @@ var SmartTags = ({
933
1446
  onKeyDown: handleKeyDown,
934
1447
  placeholder: tags.length === 0 ? placeholder : "",
935
1448
  className: "flex-1 min-w-[120px] border-0 shadow-none focus-visible:ring-0 focus-visible:ring-offset-0 p-0 h-auto",
936
- disabled,
1449
+ disabled: isDisabled,
937
1450
  maxLength
938
1451
  }
939
1452
  )
@@ -944,6 +1457,6 @@ var SmartTags = ({
944
1457
  ] });
945
1458
  };
946
1459
 
947
- export { Button, Popover, PopoverContent, PopoverTrigger, SmartCheckbox, SmartDatePicker, SmartRadioGroup, SmartSelect, SmartTags };
948
- //# sourceMappingURL=chunk-KDPN4CHW.js.map
949
- //# sourceMappingURL=chunk-KDPN4CHW.js.map
1460
+ export { Badge, Button, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, Popover, PopoverContent, PopoverTrigger, SmartCheckbox, SmartCombobox, SmartDatePicker, SmartRadioGroup, SmartSelect, SmartTags };
1461
+ //# sourceMappingURL=chunk-BNQNL7GF.js.map
1462
+ //# sourceMappingURL=chunk-BNQNL7GF.js.map