@skybin-tech/nebula-ui 0.0.28 → 0.0.30

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 (273) hide show
  1. package/README.md +422 -356
  2. package/dist/cjs/_virtual/_rolldown/runtime.cjs +1 -1
  3. package/dist/cjs/components/Accordion/Accordion.cjs.map +1 -1
  4. package/dist/cjs/components/Alert/Alert.cjs.map +1 -1
  5. package/dist/cjs/components/Avatar/Avatar.cjs.map +1 -1
  6. package/dist/cjs/components/Badge/Badge.cjs.map +1 -1
  7. package/dist/cjs/components/Button/Button.cjs +1 -1
  8. package/dist/cjs/components/Button/Button.cjs.map +1 -1
  9. package/dist/cjs/components/Card/Card.cjs.map +1 -1
  10. package/dist/cjs/components/Checkbox/Checkbox.cjs.map +1 -1
  11. package/dist/cjs/components/DropdownMenu/DropdownMenu.cjs.map +1 -1
  12. package/dist/cjs/components/Form/Checkbox.cjs.map +1 -1
  13. package/dist/cjs/components/Form/Combobox.cjs +124 -0
  14. package/dist/cjs/components/Form/Combobox.cjs.map +1 -0
  15. package/dist/cjs/components/Form/CountryPicker.cjs +101 -0
  16. package/dist/cjs/components/Form/CountryPicker.cjs.map +1 -0
  17. package/dist/cjs/components/Form/CountrySelect.cjs +111 -0
  18. package/dist/cjs/components/Form/CountrySelect.cjs.map +1 -0
  19. package/dist/cjs/components/Form/DatePicker.cjs +122 -0
  20. package/dist/cjs/components/Form/DatePicker.cjs.map +1 -0
  21. package/dist/cjs/components/Form/FieldLayout.cjs +65 -0
  22. package/dist/cjs/components/Form/FieldLayout.cjs.map +1 -0
  23. package/dist/cjs/components/Form/Form.cjs +12 -9
  24. package/dist/cjs/components/Form/Form.cjs.map +1 -1
  25. package/dist/cjs/components/Form/FormSwitch.cjs.map +1 -1
  26. package/dist/cjs/components/Form/PhoneInput.cjs +170 -0
  27. package/dist/cjs/components/Form/PhoneInput.cjs.map +1 -0
  28. package/dist/cjs/components/Form/Radio.cjs.map +1 -1
  29. package/dist/cjs/components/Form/Select.cjs +35 -47
  30. package/dist/cjs/components/Form/Select.cjs.map +1 -1
  31. package/dist/cjs/components/Form/TextArea.cjs +1 -1
  32. package/dist/cjs/components/Form/TextArea.cjs.map +1 -1
  33. package/dist/cjs/components/Form/TextBox.cjs +50 -61
  34. package/dist/cjs/components/Form/TextBox.cjs.map +1 -1
  35. package/dist/cjs/components/Form/context.cjs +25 -11
  36. package/dist/cjs/components/Form/context.cjs.map +1 -1
  37. package/dist/cjs/components/Form/hooks.cjs.map +1 -1
  38. package/dist/cjs/components/Form/index.cjs +16 -0
  39. package/dist/cjs/components/Form/variants.cjs.map +1 -1
  40. package/dist/cjs/components/Input/Input.cjs +2 -2
  41. package/dist/cjs/components/Input/Input.cjs.map +1 -1
  42. package/dist/cjs/components/Label/Label.cjs.map +1 -1
  43. package/dist/cjs/components/Pagination/Pagination.cjs +4 -4
  44. package/dist/cjs/components/Pagination/Pagination.cjs.map +1 -1
  45. package/dist/cjs/components/Separator/Separator.cjs.map +1 -1
  46. package/dist/cjs/components/Switch/Switch.cjs.map +1 -1
  47. package/dist/cjs/components/Tabs/Tabs.cjs.map +1 -1
  48. package/dist/cjs/components/Textarea/Textarea.cjs.map +1 -1
  49. package/dist/cjs/components/Tooltip/Tooltip.cjs.map +1 -1
  50. package/dist/cjs/data/countries.cjs +1062 -0
  51. package/dist/cjs/data/countries.cjs.map +1 -0
  52. package/dist/cjs/hooks/useDebounce.cjs.map +1 -1
  53. package/dist/cjs/hooks/useToast.cjs.map +1 -1
  54. package/dist/cjs/hooks/useToggle.cjs.map +1 -1
  55. package/dist/cjs/index.cjs +64 -4
  56. package/dist/cjs/primitives/accordion.cjs.map +1 -1
  57. package/dist/cjs/primitives/alert-dialog.cjs +73 -0
  58. package/dist/cjs/primitives/alert-dialog.cjs.map +1 -0
  59. package/dist/cjs/primitives/alert.cjs.map +1 -1
  60. package/dist/cjs/primitives/avatar.cjs.map +1 -1
  61. package/dist/cjs/primitives/badge.cjs.map +1 -1
  62. package/dist/cjs/primitives/breadcrumb.cjs +73 -0
  63. package/dist/cjs/primitives/breadcrumb.cjs.map +1 -0
  64. package/dist/cjs/primitives/button.cjs +8 -7
  65. package/dist/cjs/primitives/button.cjs.map +1 -1
  66. package/dist/cjs/primitives/calendar.cjs.map +1 -1
  67. package/dist/cjs/primitives/card.cjs.map +1 -1
  68. package/dist/cjs/primitives/checkbox.cjs.map +1 -1
  69. package/dist/cjs/primitives/command.cjs.map +1 -1
  70. package/dist/cjs/primitives/dialog.cjs.map +1 -1
  71. package/dist/cjs/primitives/dropdown-menu.cjs.map +1 -1
  72. package/dist/cjs/primitives/input-otp.cjs +49 -0
  73. package/dist/cjs/primitives/input-otp.cjs.map +1 -0
  74. package/dist/cjs/primitives/label.cjs.map +1 -1
  75. package/dist/cjs/primitives/popover.cjs.map +1 -1
  76. package/dist/cjs/primitives/progress.cjs +24 -0
  77. package/dist/cjs/primitives/progress.cjs.map +1 -0
  78. package/dist/cjs/primitives/radio-group.cjs.map +1 -1
  79. package/dist/cjs/primitives/scroll-area.cjs.map +1 -1
  80. package/dist/cjs/primitives/select.cjs.map +1 -1
  81. package/dist/cjs/primitives/separator.cjs.map +1 -1
  82. package/dist/cjs/primitives/sheet.cjs +78 -0
  83. package/dist/cjs/primitives/sheet.cjs.map +1 -0
  84. package/dist/cjs/primitives/slider.cjs +23 -0
  85. package/dist/cjs/primitives/slider.cjs.map +1 -0
  86. package/dist/cjs/primitives/sonner.cjs.map +1 -1
  87. package/dist/cjs/primitives/switch.cjs.map +1 -1
  88. package/dist/cjs/primitives/table.cjs.map +1 -1
  89. package/dist/cjs/primitives/tabs.cjs.map +1 -1
  90. package/dist/cjs/primitives/textarea.cjs +1 -1
  91. package/dist/cjs/primitives/textarea.cjs.map +1 -1
  92. package/dist/cjs/primitives/textbox.cjs +1 -1
  93. package/dist/cjs/primitives/textbox.cjs.map +1 -1
  94. package/dist/cjs/primitives/toast.cjs.map +1 -1
  95. package/dist/cjs/primitives/toggle.cjs.map +1 -1
  96. package/dist/cjs/utils/cn.cjs.map +1 -1
  97. package/dist/components/Alert/Alert.js.map +1 -1
  98. package/dist/components/AlertDialog/AlertDialog.d.ts +2 -0
  99. package/dist/components/AlertDialog/AlertDialog.d.ts.map +1 -0
  100. package/dist/components/AlertDialog/index.d.ts +2 -0
  101. package/dist/components/AlertDialog/index.d.ts.map +1 -0
  102. package/dist/components/Avatar/Avatar.js.map +1 -1
  103. package/dist/components/Badge/Badge.js.map +1 -1
  104. package/dist/components/Breadcrumb/Breadcrumb.d.ts +2 -0
  105. package/dist/components/Breadcrumb/Breadcrumb.d.ts.map +1 -0
  106. package/dist/components/Breadcrumb/index.d.ts +2 -0
  107. package/dist/components/Breadcrumb/index.d.ts.map +1 -0
  108. package/dist/components/Button/Button.d.ts.map +1 -1
  109. package/dist/components/Button/Button.js +2 -2
  110. package/dist/components/Button/Button.js.map +1 -1
  111. package/dist/components/Card/Card.js.map +1 -1
  112. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  113. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
  114. package/dist/components/Form/Checkbox.js.map +1 -1
  115. package/dist/components/Form/Combobox.d.ts +31 -0
  116. package/dist/components/Form/Combobox.d.ts.map +1 -0
  117. package/dist/components/Form/Combobox.js +124 -0
  118. package/dist/components/Form/Combobox.js.map +1 -0
  119. package/dist/components/Form/CountryPicker.d.ts +17 -0
  120. package/dist/components/Form/CountryPicker.d.ts.map +1 -0
  121. package/dist/components/Form/CountryPicker.js +101 -0
  122. package/dist/components/Form/CountryPicker.js.map +1 -0
  123. package/dist/components/Form/CountrySelect.d.ts +32 -0
  124. package/dist/components/Form/CountrySelect.d.ts.map +1 -0
  125. package/dist/components/Form/CountrySelect.js +111 -0
  126. package/dist/components/Form/CountrySelect.js.map +1 -0
  127. package/dist/components/Form/DatePicker.d.ts +27 -0
  128. package/dist/components/Form/DatePicker.d.ts.map +1 -0
  129. package/dist/components/Form/DatePicker.js +122 -0
  130. package/dist/components/Form/DatePicker.js.map +1 -0
  131. package/dist/components/Form/FieldLayout.d.ts +15 -0
  132. package/dist/components/Form/FieldLayout.d.ts.map +1 -0
  133. package/dist/components/Form/FieldLayout.js +65 -0
  134. package/dist/components/Form/FieldLayout.js.map +1 -0
  135. package/dist/components/Form/Form.d.ts +1 -1
  136. package/dist/components/Form/Form.d.ts.map +1 -1
  137. package/dist/components/Form/Form.js +12 -9
  138. package/dist/components/Form/Form.js.map +1 -1
  139. package/dist/components/Form/FormSwitch.js.map +1 -1
  140. package/dist/components/Form/PhoneInput.d.ts +38 -0
  141. package/dist/components/Form/PhoneInput.d.ts.map +1 -0
  142. package/dist/components/Form/PhoneInput.js +170 -0
  143. package/dist/components/Form/PhoneInput.js.map +1 -0
  144. package/dist/components/Form/Radio.js.map +1 -1
  145. package/dist/components/Form/Select.d.ts.map +1 -1
  146. package/dist/components/Form/Select.js +35 -47
  147. package/dist/components/Form/Select.js.map +1 -1
  148. package/dist/components/Form/TextArea.js +1 -1
  149. package/dist/components/Form/TextArea.js.map +1 -1
  150. package/dist/components/Form/TextBox.d.ts.map +1 -1
  151. package/dist/components/Form/TextBox.js +50 -61
  152. package/dist/components/Form/TextBox.js.map +1 -1
  153. package/dist/components/Form/context.d.ts.map +1 -1
  154. package/dist/components/Form/context.js +25 -11
  155. package/dist/components/Form/context.js.map +1 -1
  156. package/dist/components/Form/context.test.d.ts +2 -0
  157. package/dist/components/Form/context.test.d.ts.map +1 -0
  158. package/dist/components/Form/hooks.js.map +1 -1
  159. package/dist/components/Form/index.d.ts +12 -0
  160. package/dist/components/Form/index.d.ts.map +1 -1
  161. package/dist/components/Form/index.js +7 -1
  162. package/dist/components/Input/Input.js +2 -2
  163. package/dist/components/Input/Input.js.map +1 -1
  164. package/dist/components/InputOTP/InputOTP.d.ts +2 -0
  165. package/dist/components/InputOTP/InputOTP.d.ts.map +1 -0
  166. package/dist/components/InputOTP/index.d.ts +2 -0
  167. package/dist/components/InputOTP/index.d.ts.map +1 -0
  168. package/dist/components/Label/Label.js.map +1 -1
  169. package/dist/components/Pagination/Pagination.d.ts +2 -2
  170. package/dist/components/Pagination/Pagination.d.ts.map +1 -1
  171. package/dist/components/Pagination/Pagination.js +4 -4
  172. package/dist/components/Pagination/Pagination.js.map +1 -1
  173. package/dist/components/Progress/Progress.d.ts +2 -0
  174. package/dist/components/Progress/Progress.d.ts.map +1 -0
  175. package/dist/components/Progress/index.d.ts +2 -0
  176. package/dist/components/Progress/index.d.ts.map +1 -0
  177. package/dist/components/Separator/Separator.js.map +1 -1
  178. package/dist/components/Sheet/Sheet.d.ts +2 -0
  179. package/dist/components/Sheet/Sheet.d.ts.map +1 -0
  180. package/dist/components/Sheet/index.d.ts +2 -0
  181. package/dist/components/Sheet/index.d.ts.map +1 -0
  182. package/dist/components/Slider/Slider.d.ts +2 -0
  183. package/dist/components/Slider/Slider.d.ts.map +1 -0
  184. package/dist/components/Slider/index.d.ts +2 -0
  185. package/dist/components/Slider/index.d.ts.map +1 -0
  186. package/dist/components/Switch/Switch.js.map +1 -1
  187. package/dist/components/Tabs/Tabs.js.map +1 -1
  188. package/dist/components/Textarea/Textarea.js.map +1 -1
  189. package/dist/data/countries.d.ts +18 -0
  190. package/dist/data/countries.d.ts.map +1 -0
  191. package/dist/data/countries.js +1054 -0
  192. package/dist/data/countries.js.map +1 -0
  193. package/dist/hooks/useDebounce.js.map +1 -1
  194. package/dist/hooks/useToast.js.map +1 -1
  195. package/dist/hooks/useToggle.js.map +1 -1
  196. package/dist/index.d.ts +10 -2
  197. package/dist/index.d.ts.map +1 -1
  198. package/dist/index.js +16 -5
  199. package/dist/primitives/accordion.js.map +1 -1
  200. package/dist/primitives/alert-dialog.d.ts +21 -0
  201. package/dist/primitives/alert-dialog.d.ts.map +1 -0
  202. package/dist/primitives/alert-dialog.js +60 -0
  203. package/dist/primitives/alert-dialog.js.map +1 -0
  204. package/dist/primitives/alert.js.map +1 -1
  205. package/dist/primitives/avatar.js.map +1 -1
  206. package/dist/primitives/breadcrumb.d.ts +20 -0
  207. package/dist/primitives/breadcrumb.d.ts.map +1 -0
  208. package/dist/primitives/breadcrumb.js +65 -0
  209. package/dist/primitives/breadcrumb.js.map +1 -0
  210. package/dist/primitives/button.d.ts +4 -3
  211. package/dist/primitives/button.d.ts.map +1 -1
  212. package/dist/primitives/button.js +7 -7
  213. package/dist/primitives/button.js.map +1 -1
  214. package/dist/primitives/calendar.js.map +1 -1
  215. package/dist/primitives/card.js.map +1 -1
  216. package/dist/primitives/checkbox.js.map +1 -1
  217. package/dist/primitives/command.js.map +1 -1
  218. package/dist/primitives/dialog.js.map +1 -1
  219. package/dist/primitives/dropdown-menu.js.map +1 -1
  220. package/dist/primitives/index.d.ts +6 -0
  221. package/dist/primitives/index.d.ts.map +1 -1
  222. package/dist/primitives/input-otp.d.ts +35 -0
  223. package/dist/primitives/input-otp.d.ts.map +1 -0
  224. package/dist/primitives/input-otp.js +44 -0
  225. package/dist/primitives/input-otp.js.map +1 -0
  226. package/dist/primitives/input.d.ts +1 -3
  227. package/dist/primitives/input.d.ts.map +1 -1
  228. package/dist/primitives/label.js.map +1 -1
  229. package/dist/primitives/popover.js.map +1 -1
  230. package/dist/primitives/progress.d.ts +5 -0
  231. package/dist/primitives/progress.d.ts.map +1 -0
  232. package/dist/primitives/progress.js +21 -0
  233. package/dist/primitives/progress.js.map +1 -0
  234. package/dist/primitives/radio-group.js.map +1 -1
  235. package/dist/primitives/scroll-area.js.map +1 -1
  236. package/dist/primitives/select.js.map +1 -1
  237. package/dist/primitives/separator.js.map +1 -1
  238. package/dist/primitives/sheet.d.ts +26 -0
  239. package/dist/primitives/sheet.d.ts.map +1 -0
  240. package/dist/primitives/sheet.js +66 -0
  241. package/dist/primitives/sheet.js.map +1 -0
  242. package/dist/primitives/slider.d.ts +5 -0
  243. package/dist/primitives/slider.d.ts.map +1 -0
  244. package/dist/primitives/slider.js +20 -0
  245. package/dist/primitives/slider.js.map +1 -0
  246. package/dist/primitives/sonner.js.map +1 -1
  247. package/dist/primitives/switch.js.map +1 -1
  248. package/dist/primitives/table.js.map +1 -1
  249. package/dist/primitives/tabs.js.map +1 -1
  250. package/dist/primitives/textarea.js +1 -1
  251. package/dist/primitives/textarea.js.map +1 -1
  252. package/dist/primitives/textbox.js +1 -1
  253. package/dist/primitives/textbox.js.map +1 -1
  254. package/dist/primitives/toast.js.map +1 -1
  255. package/dist/primitives/toggle.js.map +1 -1
  256. package/package.json +168 -60
  257. package/src/styles/index.css +107 -0
  258. package/dist/cjs/primitives/input.cjs +0 -20
  259. package/dist/cjs/primitives/input.cjs.map +0 -1
  260. package/dist/primitives/input.js +0 -18
  261. package/dist/primitives/input.js.map +0 -1
  262. package/dist/stories/Button.d.ts +0 -15
  263. package/dist/stories/Button.d.ts.map +0 -1
  264. package/dist/stories/Button.stories.d.ts +0 -24
  265. package/dist/stories/Button.stories.d.ts.map +0 -1
  266. package/dist/stories/Header.d.ts +0 -12
  267. package/dist/stories/Header.d.ts.map +0 -1
  268. package/dist/stories/Header.stories.d.ts +0 -19
  269. package/dist/stories/Header.stories.d.ts.map +0 -1
  270. package/dist/stories/Page.d.ts +0 -3
  271. package/dist/stories/Page.d.ts.map +0 -1
  272. package/dist/stories/Page.stories.d.ts +0 -13
  273. package/dist/stories/Page.stories.d.ts.map +0 -1
@@ -0,0 +1,101 @@
1
+ "use client";
2
+ "use client";
3
+ import { cn } from "../../utils/cn.js";
4
+ import { Button } from "../../primitives/button.js";
5
+ import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "../../primitives/command.js";
6
+ import { Popover, PopoverContent, PopoverTrigger } from "../../primitives/popover.js";
7
+ import { COUNTRIES, filterCountries, getCountryByCode, getCountryFlag, sortCountriesWithPriority } from "../../data/countries.js";
8
+ import { useMemo, useState } from "react";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ import { Check, ChevronsUpDown } from "lucide-react";
11
+ //#region src/components/Form/CountryPicker.tsx
12
+ function resolveCountries(include, exclude, priorityCountries) {
13
+ let countries = COUNTRIES;
14
+ if (include?.length) {
15
+ const includeSet = new Set(include.map((code) => code.toUpperCase()));
16
+ countries = countries.filter((country) => includeSet.has(country.code));
17
+ }
18
+ if (exclude?.length) {
19
+ const excludeSet = new Set(exclude.map((code) => code.toUpperCase()));
20
+ countries = countries.filter((country) => !excludeSet.has(country.code));
21
+ }
22
+ return sortCountriesWithPriority(countries, priorityCountries);
23
+ }
24
+ function CountryPicker({ value, onValueChange, placeholder = "Select country", disabled, compact = false, include, exclude, priorityCountries, className, id, required, "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedBy }) {
25
+ const [open, setOpen] = useState(false);
26
+ const countries = useMemo(() => resolveCountries(include, exclude, priorityCountries), [
27
+ include,
28
+ exclude,
29
+ priorityCountries
30
+ ]);
31
+ const selectedCountry = value ? getCountryByCode(value) : void 0;
32
+ return /* @__PURE__ */ jsxs(Popover, {
33
+ open,
34
+ onOpenChange: setOpen,
35
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
36
+ asChild: true,
37
+ children: /* @__PURE__ */ jsxs(Button, {
38
+ id,
39
+ type: "button",
40
+ variant: "outline",
41
+ role: "combobox",
42
+ "aria-expanded": open,
43
+ "aria-required": required,
44
+ "aria-invalid": ariaInvalid,
45
+ "aria-describedby": ariaDescribedBy,
46
+ disabled,
47
+ className: cn("justify-between font-normal", compact ? "h-full w-auto shrink-0 border-0 bg-transparent px-2 shadow-none hover:bg-transparent" : "w-full", !value && "text-muted-foreground", className),
48
+ children: [selectedCountry ? /* @__PURE__ */ jsxs("span", {
49
+ className: "flex min-w-0 items-center gap-2 truncate",
50
+ children: [/* @__PURE__ */ jsx("span", {
51
+ "aria-hidden": "true",
52
+ children: getCountryFlag(selectedCountry.code)
53
+ }), !compact && /* @__PURE__ */ jsx("span", {
54
+ className: "truncate",
55
+ children: selectedCountry.name
56
+ })]
57
+ }) : /* @__PURE__ */ jsx("span", {
58
+ className: "truncate",
59
+ children: compact ? "…" : placeholder
60
+ }), !compact && /* @__PURE__ */ jsx(ChevronsUpDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })]
61
+ })
62
+ }), /* @__PURE__ */ jsx(PopoverContent, {
63
+ className: "w-[320px] p-0",
64
+ align: "start",
65
+ children: /* @__PURE__ */ jsxs(Command, {
66
+ filter: (itemValue, search) => {
67
+ const country = countries.find((entry) => entry.code.toLowerCase() === itemValue.toLowerCase());
68
+ if (!country) return 0;
69
+ return filterCountries([country], search).length > 0 ? 1 : 0;
70
+ },
71
+ children: [/* @__PURE__ */ jsx(CommandInput, { placeholder: "Search country..." }), /* @__PURE__ */ jsxs(CommandList, { children: [/* @__PURE__ */ jsx(CommandEmpty, { children: "No country found." }), /* @__PURE__ */ jsx(CommandGroup, { children: countries.map((country) => /* @__PURE__ */ jsxs(CommandItem, {
72
+ value: country.code,
73
+ onSelect: (currentValue) => {
74
+ onValueChange(currentValue.toUpperCase());
75
+ setOpen(false);
76
+ },
77
+ children: [
78
+ /* @__PURE__ */ jsx(Check, { className: cn("mr-2 h-4 w-4", value === country.code ? "opacity-100" : "opacity-0") }),
79
+ /* @__PURE__ */ jsx("span", {
80
+ "aria-hidden": "true",
81
+ className: "mr-2",
82
+ children: getCountryFlag(country.code)
83
+ }),
84
+ /* @__PURE__ */ jsx("span", {
85
+ className: "truncate",
86
+ children: country.name
87
+ }),
88
+ /* @__PURE__ */ jsx("span", {
89
+ className: "ml-auto text-xs text-muted-foreground",
90
+ children: country.dialCode
91
+ })
92
+ ]
93
+ }, country.code)) })] })]
94
+ })
95
+ })]
96
+ });
97
+ }
98
+ //#endregion
99
+ export { CountryPicker };
100
+
101
+ //# sourceMappingURL=CountryPicker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CountryPicker.js","names":[],"sources":["../../../src/components/Form/CountryPicker.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useMemo, useState } from \"react\";\r\nimport { Check, ChevronsUpDown } from \"lucide-react\";\r\nimport { cn } from \"../../utils/cn\";\r\nimport { Button } from \"../../primitives/button\";\r\nimport {\r\n Command,\r\n CommandEmpty,\r\n CommandGroup,\r\n CommandInput,\r\n CommandItem,\r\n CommandList,\r\n} from \"../../primitives/command\";\r\nimport { Popover, PopoverContent, PopoverTrigger } from \"../../primitives/popover\";\r\nimport {\r\n COUNTRIES,\r\n filterCountries,\r\n getCountryByCode,\r\n getCountryFlag,\r\n sortCountriesWithPriority,\r\n type Country,\r\n} from \"../../data/countries\";\r\n\r\nexport interface CountryPickerProps {\r\n value?: string;\r\n onValueChange: (value: string) => void;\r\n placeholder?: string;\r\n disabled?: boolean;\r\n compact?: boolean;\r\n include?: string[];\r\n exclude?: string[];\r\n priorityCountries?: string[];\r\n className?: string;\r\n id?: string;\r\n required?: boolean;\r\n \"aria-invalid\"?: boolean;\r\n \"aria-describedby\"?: string;\r\n}\r\n\r\nfunction resolveCountries(\r\n include?: string[],\r\n exclude?: string[],\r\n priorityCountries?: string[]\r\n): Country[] {\r\n let countries = COUNTRIES;\r\n\r\n if (include?.length) {\r\n const includeSet = new Set(include.map((code) => code.toUpperCase()));\r\n countries = countries.filter((country) => includeSet.has(country.code));\r\n }\r\n\r\n if (exclude?.length) {\r\n const excludeSet = new Set(exclude.map((code) => code.toUpperCase()));\r\n countries = countries.filter((country) => !excludeSet.has(country.code));\r\n }\r\n\r\n return sortCountriesWithPriority(countries, priorityCountries);\r\n}\r\n\r\nexport function CountryPicker({\r\n value,\r\n onValueChange,\r\n placeholder = \"Select country\",\r\n disabled,\r\n compact = false,\r\n include,\r\n exclude,\r\n priorityCountries,\r\n className,\r\n id,\r\n required,\r\n \"aria-invalid\": ariaInvalid,\r\n \"aria-describedby\": ariaDescribedBy,\r\n}: CountryPickerProps) {\r\n const [open, setOpen] = useState(false);\r\n const countries = useMemo(\r\n () => resolveCountries(include, exclude, priorityCountries),\r\n [include, exclude, priorityCountries]\r\n );\r\n const selectedCountry = value ? getCountryByCode(value) : undefined;\r\n\r\n return (\r\n <Popover open={open} onOpenChange={setOpen}>\r\n <PopoverTrigger asChild>\r\n <Button\r\n id={id}\r\n type=\"button\"\r\n variant=\"outline\"\r\n role=\"combobox\"\r\n aria-expanded={open}\r\n aria-required={required}\r\n aria-invalid={ariaInvalid}\r\n aria-describedby={ariaDescribedBy}\r\n disabled={disabled}\r\n className={cn(\r\n \"justify-between font-normal\",\r\n compact ? \"h-full w-auto shrink-0 border-0 bg-transparent px-2 shadow-none hover:bg-transparent\" : \"w-full\",\r\n !value && \"text-muted-foreground\",\r\n className\r\n )}\r\n >\r\n {selectedCountry ? (\r\n <span className=\"flex min-w-0 items-center gap-2 truncate\">\r\n <span aria-hidden=\"true\">{getCountryFlag(selectedCountry.code)}</span>\r\n {!compact && <span className=\"truncate\">{selectedCountry.name}</span>}\r\n </span>\r\n ) : (\r\n <span className=\"truncate\">{compact ? \"…\" : placeholder}</span>\r\n )}\r\n {!compact && <ChevronsUpDown className=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />}\r\n </Button>\r\n </PopoverTrigger>\r\n <PopoverContent className=\"w-[320px] p-0\" align=\"start\">\r\n <Command\r\n filter={(itemValue, search) => {\r\n const country = countries.find(\r\n (entry) => entry.code.toLowerCase() === itemValue.toLowerCase()\r\n );\r\n if (!country) {\r\n return 0;\r\n }\r\n\r\n return filterCountries([country], search).length > 0 ? 1 : 0;\r\n }}\r\n >\r\n <CommandInput placeholder=\"Search country...\" />\r\n <CommandList>\r\n <CommandEmpty>No country found.</CommandEmpty>\r\n <CommandGroup>\r\n {countries.map((country) => (\r\n <CommandItem\r\n key={country.code}\r\n value={country.code}\r\n onSelect={(currentValue) => {\r\n onValueChange(currentValue.toUpperCase());\r\n setOpen(false);\r\n }}\r\n >\r\n <Check\r\n className={cn(\r\n \"mr-2 h-4 w-4\",\r\n value === country.code ? \"opacity-100\" : \"opacity-0\"\r\n )}\r\n />\r\n <span aria-hidden=\"true\" className=\"mr-2\">\r\n {getCountryFlag(country.code)}\r\n </span>\r\n <span className=\"truncate\">{country.name}</span>\r\n <span className=\"ml-auto text-xs text-muted-foreground\">\r\n {country.dialCode}\r\n </span>\r\n </CommandItem>\r\n ))}\r\n </CommandGroup>\r\n </CommandList>\r\n </Command>\r\n </PopoverContent>\r\n </Popover>\r\n );\r\n}\r\n\r\n"],"mappings":";;;;;;;;;;;AAwCA,SAAS,iBACP,SACA,SACA,mBACW;CACX,IAAI,YAAY;CAEhB,IAAI,SAAS,QAAQ;EACnB,MAAM,aAAa,IAAI,IAAI,QAAQ,KAAK,SAAS,KAAK,YAAY,CAAC,CAAC;EACpE,YAAY,UAAU,QAAQ,YAAY,WAAW,IAAI,QAAQ,IAAI,CAAC;CACxE;CAEA,IAAI,SAAS,QAAQ;EACnB,MAAM,aAAa,IAAI,IAAI,QAAQ,KAAK,SAAS,KAAK,YAAY,CAAC,CAAC;EACpE,YAAY,UAAU,QAAQ,YAAY,CAAC,WAAW,IAAI,QAAQ,IAAI,CAAC;CACzE;CAEA,OAAO,0BAA0B,WAAW,iBAAiB;AAC/D;AAEA,SAAgB,cAAc,EAC5B,OACA,eACA,cAAc,kBACd,UACA,UAAU,OACV,SACA,SACA,mBACA,WACA,IACA,UACA,gBAAgB,aAChB,oBAAoB,mBACC;CACrB,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,YAAY,cACV,iBAAiB,SAAS,SAAS,iBAAiB,GAC1D;EAAC;EAAS;EAAS;CAAiB,CACtC;CACA,MAAM,kBAAkB,QAAQ,iBAAiB,KAAK,IAAI,KAAA;CAE1D,OACE,qBAAC,SAAD;EAAe;EAAM,cAAc;EAAnC,UAAA,CACE,oBAAC,gBAAD;GAAgB,SAAA;GACd,UAAA,qBAAC,QAAD;IACM;IACJ,MAAK;IACL,SAAQ;IACR,MAAK;IACL,iBAAe;IACf,iBAAe;IACf,gBAAc;IACd,oBAAkB;IACR;IACV,WAAW,GACT,+BACA,UAAU,yFAAyF,UACnG,CAAC,SAAS,yBACV,SACF;IAfF,UAAA,CAiBG,kBACC,qBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA,CACE,oBAAC,QAAD;MAAM,eAAY;MAAQ,UAAA,eAAe,gBAAgB,IAAI;KAAQ,CAAA,GACpE,CAAC,WAAW,oBAAC,QAAD;MAAM,WAAU;MAAY,UAAA,gBAAgB;KAAW,CAAA,CAChE;IAEN,CAAA,IAAA,oBAAC,QAAD;KAAM,WAAU;KAAY,UAAA,UAAU,MAAM;IAAkB,CAAA,GAE/D,CAAC,WAAW,oBAAC,gBAAD,EAAgB,WAAU,mCAAoC,CAAA,CACrE;;EACM,CAAA,GAChB,oBAAC,gBAAD;GAAgB,WAAU;GAAgB,OAAM;GAC9C,UAAA,qBAAC,SAAD;IACE,SAAS,WAAW,WAAW;KAC7B,MAAM,UAAU,UAAU,MACvB,UAAU,MAAM,KAAK,YAAY,MAAM,UAAU,YAAY,CAChE;KACA,IAAI,CAAC,SACH,OAAO;KAGT,OAAO,gBAAgB,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC,SAAS,IAAI,IAAI;IAC7D;IAVF,UAAA,CAYE,oBAAC,cAAD,EAAc,aAAY,oBAAqB,CAAA,GAC/C,qBAAC,aAAD,EAAA,UAAA,CACE,oBAAC,cAAD,EAAA,UAAc,oBAA+B,CAAA,GAC7C,oBAAC,cAAD,EAAA,UACG,UAAU,KAAK,YACd,qBAAC,aAAD;KAEE,OAAO,QAAQ;KACf,WAAW,iBAAiB;MAC1B,cAAc,aAAa,YAAY,CAAC;MACxC,QAAQ,KAAK;KACf;KANF,UAAA;MAQE,oBAAC,OAAD,EACE,WAAW,GACT,gBACA,UAAU,QAAQ,OAAO,gBAAgB,WAC3C,EACD,CAAA;MACD,oBAAC,QAAD;OAAM,eAAY;OAAO,WAAU;OAChC,UAAA,eAAe,QAAQ,IAAI;MACxB,CAAA;MACN,oBAAC,QAAD;OAAM,WAAU;OAAY,UAAA,QAAQ;MAAW,CAAA;MAC/C,oBAAC,QAAD;OAAM,WAAU;OACb,UAAA,QAAQ;MACL,CAAA;KACK;IApBN,GAAA,QAAQ,IAoBF,CACd,EACW,CAAA,CACH,EAAA,CAAA,CACN;;EACK,CAAA,CACT;;AAEb"}
@@ -0,0 +1,32 @@
1
+ import { Control, FieldPath, FieldValues } from 'react-hook-form';
2
+ import { VariantProps } from 'class-variance-authority';
3
+ declare const countrySelectVariants: (props?: ({
4
+ size?: "sm" | "lg" | "md" | null | undefined;
5
+ variant?: "default" | "error" | "success" | null | undefined;
6
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
7
+ export interface CountrySelectProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> extends VariantProps<typeof countrySelectVariants> {
8
+ name: TName;
9
+ label?: string;
10
+ helperText?: string;
11
+ showError?: boolean;
12
+ error?: string;
13
+ fullWidth?: boolean;
14
+ placeholder?: string;
15
+ allowClear?: boolean;
16
+ disabled?: boolean;
17
+ className?: string;
18
+ id?: string;
19
+ control?: Control<TFieldValues>;
20
+ include?: string[];
21
+ exclude?: string[];
22
+ priorityCountries?: string[];
23
+ /** Field is required (`true` or custom error message string) */
24
+ required?: boolean | string;
25
+ validate?: (value: unknown) => boolean | string | Promise<boolean | string>;
26
+ }
27
+ export declare function CountrySelect<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ name, label, helperText, showError, error: customError, size, variant, fullWidth, placeholder, allowClear, disabled, className, id: providedId, control: externalControl, include, exclude, priorityCountries, required, validate, }: CountrySelectProps<TFieldValues, TName>): import("react").JSX.Element;
28
+ export declare namespace CountrySelect {
29
+ var displayName: string;
30
+ }
31
+ export {};
32
+ //# sourceMappingURL=CountrySelect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CountrySelect.d.ts","sourceRoot":"","sources":["../../../src/components/Form/CountrySelect.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAsD,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACrI,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAMlE,QAAA,MAAM,qBAAqB;;;8EAiBzB,CAAC;AAEH,MAAM,WAAW,kBAAkB,CACjC,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,KAAK,SAAS,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC,CAC/D,SAAQ,YAAY,CAAC,OAAO,qBAAqB,CAAC;IAClD,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,gEAAgE;IAChE,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC;CAC7E;AAED,wBAAgB,aAAa,CAC3B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,KAAK,SAAS,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC,EAC/D,EACA,IAAI,EACJ,KAAK,EACL,UAAU,EACV,SAAgB,EAChB,KAAK,EAAE,WAAW,EAClB,IAAI,EACJ,OAAO,EACP,SAAgB,EAChB,WAAgC,EAChC,UAAU,EACV,QAAQ,EACR,SAAS,EACT,EAAE,EAAE,UAAU,EACd,OAAO,EAAE,eAAe,EACxB,OAAO,EACP,OAAO,EACP,iBAAiB,EACjB,QAAQ,EACR,QAAQ,GACT,EAAE,kBAAkB,CAAC,YAAY,EAAE,KAAK,CAAC,+BA+FzC;yBAtHe,aAAa"}
@@ -0,0 +1,111 @@
1
+ "use client";
2
+ "use client";
3
+ import { cn } from "../../utils/cn.js";
4
+ import { FormConfigContext } from "./context.js";
5
+ import { FieldLayout } from "./FieldLayout.js";
6
+ import { CountryPicker } from "./CountryPicker.js";
7
+ import { useContext, useEffect, useId } from "react";
8
+ import { cva } from "class-variance-authority";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ import { useController, useFormContext } from "react-hook-form";
11
+ //#region src/components/Form/CountrySelect.tsx
12
+ var countrySelectVariants = cva("", {
13
+ variants: {
14
+ size: {
15
+ sm: "h-8 text-xs",
16
+ md: "h-10 text-sm",
17
+ lg: "h-12 text-base"
18
+ },
19
+ variant: {
20
+ default: "border-input focus-visible:ring-ring",
21
+ error: "border-destructive focus-visible:ring-destructive",
22
+ success: "border-green-500 focus-visible:ring-green-500"
23
+ }
24
+ },
25
+ defaultVariants: {
26
+ size: "md",
27
+ variant: "default"
28
+ }
29
+ });
30
+ function CountrySelect({ name, label, helperText, showError = true, error: customError, size, variant, fullWidth = true, placeholder = "Select a country", allowClear, disabled, className, id: providedId, control: externalControl, include, exclude, priorityCountries, required, validate }) {
31
+ const generatedId = useId();
32
+ const inputId = providedId ?? generatedId;
33
+ const formConfigContext = useContext(FormConfigContext);
34
+ const formConfig = formConfigContext ?? {};
35
+ const rhfContext = useFormContext();
36
+ const control = externalControl ?? rhfContext?.control;
37
+ const registerFieldValidation = formConfigContext?.registerFieldValidation;
38
+ const unregisterFieldValidation = formConfigContext?.unregisterFieldValidation;
39
+ useEffect(() => {
40
+ if (registerFieldValidation) {
41
+ const rules = {};
42
+ if (required !== void 0) rules.required = required;
43
+ if (validate !== void 0) rules.validate = validate;
44
+ registerFieldValidation({
45
+ name,
46
+ type: "string",
47
+ rules
48
+ });
49
+ return () => {
50
+ unregisterFieldValidation?.(name);
51
+ };
52
+ }
53
+ }, [
54
+ registerFieldValidation,
55
+ unregisterFieldValidation,
56
+ name,
57
+ required,
58
+ validate
59
+ ]);
60
+ const { field, fieldState } = useController({
61
+ name,
62
+ control
63
+ });
64
+ const fieldError = fieldState.error?.message;
65
+ const errorMessage = customError ?? fieldError;
66
+ const hasError = !!errorMessage;
67
+ const effectiveSize = size ?? formConfig.size ?? "md";
68
+ const effectiveDisabled = disabled ?? formConfig.disabled;
69
+ const effectiveVariant = hasError ? "error" : variant;
70
+ return /* @__PURE__ */ jsx(FieldLayout, {
71
+ inputId,
72
+ label,
73
+ required: !!required,
74
+ helperText,
75
+ errorMessage: showError ? errorMessage : void 0,
76
+ showError,
77
+ fullWidth,
78
+ formConfig,
79
+ children: /* @__PURE__ */ jsxs("div", {
80
+ className: "flex gap-2",
81
+ children: [/* @__PURE__ */ jsx(CountryPicker, {
82
+ id: inputId,
83
+ value: field.value ?? "",
84
+ onValueChange: (value) => field.onChange(value),
85
+ placeholder,
86
+ disabled: effectiveDisabled,
87
+ include,
88
+ exclude,
89
+ priorityCountries,
90
+ required: !!required,
91
+ "aria-invalid": hasError,
92
+ "aria-describedby": hasError ? `${inputId}-error` : helperText ? `${inputId}-helper` : void 0,
93
+ className: cn(countrySelectVariants({
94
+ size: effectiveSize,
95
+ variant: effectiveVariant
96
+ }), className)
97
+ }), allowClear && field.value && /* @__PURE__ */ jsx("button", {
98
+ type: "button",
99
+ className: "text-sm text-muted-foreground hover:text-foreground",
100
+ onClick: () => field.onChange(""),
101
+ disabled: effectiveDisabled,
102
+ children: "Clear"
103
+ })]
104
+ })
105
+ });
106
+ }
107
+ CountrySelect.displayName = "CountrySelect";
108
+ //#endregion
109
+ export { CountrySelect };
110
+
111
+ //# sourceMappingURL=CountrySelect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CountrySelect.js","names":[],"sources":["../../../src/components/Form/CountrySelect.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useContext, useEffect, useId } from \"react\";\r\nimport { useController, useFormContext as useRHFFormContext, type Control, type FieldPath, type FieldValues } from \"react-hook-form\";\r\nimport { cva, type VariantProps } from \"class-variance-authority\";\r\nimport { cn } from \"../../utils/cn\";\r\nimport { FormConfigContext, type FieldValidationRules, type FormConfig } from \"./context\";\r\nimport { FieldLayout } from \"./FieldLayout\";\r\nimport { CountryPicker } from \"./CountryPicker\";\r\n\r\nconst countrySelectVariants = cva(\"\", {\r\n variants: {\r\n size: {\r\n sm: \"h-8 text-xs\",\r\n md: \"h-10 text-sm\",\r\n lg: \"h-12 text-base\",\r\n },\r\n variant: {\r\n default: \"border-input focus-visible:ring-ring\",\r\n error: \"border-destructive focus-visible:ring-destructive\",\r\n success: \"border-green-500 focus-visible:ring-green-500\",\r\n },\r\n },\r\n defaultVariants: {\r\n size: \"md\",\r\n variant: \"default\",\r\n },\r\n});\r\n\r\nexport interface CountrySelectProps<\r\n TFieldValues extends FieldValues = FieldValues,\r\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\r\n> extends VariantProps<typeof countrySelectVariants> {\r\n name: TName;\r\n label?: string;\r\n helperText?: string;\r\n showError?: boolean;\r\n error?: string;\r\n fullWidth?: boolean;\r\n placeholder?: string;\r\n allowClear?: boolean;\r\n disabled?: boolean;\r\n className?: string;\r\n id?: string;\r\n control?: Control<TFieldValues>;\r\n include?: string[];\r\n exclude?: string[];\r\n priorityCountries?: string[];\r\n /** Field is required (`true` or custom error message string) */\r\n required?: boolean | string;\r\n validate?: (value: unknown) => boolean | string | Promise<boolean | string>;\r\n}\r\n\r\nexport function CountrySelect<\r\n TFieldValues extends FieldValues = FieldValues,\r\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\r\n>({\r\n name,\r\n label,\r\n helperText,\r\n showError = true,\r\n error: customError,\r\n size,\r\n variant,\r\n fullWidth = true,\r\n placeholder = \"Select a country\",\r\n allowClear,\r\n disabled,\r\n className,\r\n id: providedId,\r\n control: externalControl,\r\n include,\r\n exclude,\r\n priorityCountries,\r\n required,\r\n validate,\r\n}: CountrySelectProps<TFieldValues, TName>) {\r\n const generatedId = useId();\r\n const inputId = providedId ?? generatedId;\r\n const formConfigContext = useContext(FormConfigContext);\r\n const formConfig: FormConfig = formConfigContext ?? {};\r\n const rhfContext = useRHFFormContext<TFieldValues>();\r\n const control = externalControl ?? rhfContext?.control;\r\n\r\n const registerFieldValidation = formConfigContext?.registerFieldValidation;\r\n const unregisterFieldValidation = formConfigContext?.unregisterFieldValidation;\r\n\r\n useEffect(() => {\r\n if (registerFieldValidation) {\r\n const rules: FieldValidationRules = {};\r\n if (required !== undefined) rules.required = required;\r\n if (validate !== undefined) rules.validate = validate;\r\n\r\n registerFieldValidation({\r\n name: name as string,\r\n type: \"string\",\r\n rules,\r\n });\r\n\r\n return () => {\r\n unregisterFieldValidation?.(name as string);\r\n };\r\n }\r\n }, [\r\n registerFieldValidation,\r\n unregisterFieldValidation,\r\n name,\r\n required,\r\n validate,\r\n ]);\r\n\r\n const { field, fieldState } = useController<TFieldValues, TName>({\r\n name,\r\n control,\r\n });\r\n\r\n const fieldError = fieldState.error?.message;\r\n const errorMessage = customError ?? fieldError;\r\n const hasError = !!errorMessage;\r\n const effectiveSize = size ?? formConfig.size ?? \"md\";\r\n const effectiveDisabled = disabled ?? formConfig.disabled;\r\n const effectiveVariant = hasError ? \"error\" : variant;\r\n\r\n return (\r\n <FieldLayout\r\n inputId={inputId}\r\n label={label}\r\n required={!!required}\r\n helperText={helperText}\r\n errorMessage={showError ? errorMessage : undefined}\r\n showError={showError}\r\n fullWidth={fullWidth}\r\n formConfig={formConfig}\r\n >\r\n <div className=\"flex gap-2\">\r\n <CountryPicker\r\n id={inputId}\r\n value={field.value ?? \"\"}\r\n onValueChange={(value) => field.onChange(value)}\r\n placeholder={placeholder}\r\n disabled={effectiveDisabled}\r\n include={include}\r\n exclude={exclude}\r\n priorityCountries={priorityCountries}\r\n required={!!required}\r\n aria-invalid={hasError}\r\n aria-describedby={\r\n hasError\r\n ? `${inputId}-error`\r\n : helperText\r\n ? `${inputId}-helper`\r\n : undefined\r\n }\r\n className={cn(\r\n countrySelectVariants({ size: effectiveSize, variant: effectiveVariant }),\r\n className\r\n )}\r\n />\r\n {allowClear && field.value && (\r\n <button\r\n type=\"button\"\r\n className=\"text-sm text-muted-foreground hover:text-foreground\"\r\n onClick={() => field.onChange(\"\")}\r\n disabled={effectiveDisabled}\r\n >\r\n Clear\r\n </button>\r\n )}\r\n </div>\r\n </FieldLayout>\r\n );\r\n}\r\n\r\nCountrySelect.displayName = \"CountrySelect\";\r\n"],"mappings":";;;;;;;;;;;AAUA,IAAM,wBAAwB,IAAI,IAAI;CACpC,UAAU;EACR,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EACA,SAAS;GACP,SAAS;GACT,OAAO;GACP,SAAS;EACX;CACF;CACA,iBAAiB;EACf,MAAM;EACN,SAAS;CACX;AACF,CAAC;AA0BD,SAAgB,cAGd,EACA,MACA,OACA,YACA,YAAY,MACZ,OAAO,aACP,MACA,SACA,YAAY,MACZ,cAAc,oBACd,YACA,UACA,WACA,IAAI,YACJ,SAAS,iBACT,SACA,SACA,mBACA,UACA,YAC0C;CAC1C,MAAM,cAAc,MAAM;CAC1B,MAAM,UAAU,cAAc;CAC9B,MAAM,oBAAoB,WAAW,iBAAiB;CACtD,MAAM,aAAyB,qBAAqB,CAAC;CACrD,MAAM,aAAa,eAAgC;CACnD,MAAM,UAAU,mBAAmB,YAAY;CAE/C,MAAM,0BAA0B,mBAAmB;CACnD,MAAM,4BAA4B,mBAAmB;CAErD,gBAAgB;EACd,IAAI,yBAAyB;GAC3B,MAAM,QAA8B,CAAC;GACrC,IAAI,aAAa,KAAA,GAAW,MAAM,WAAW;GAC7C,IAAI,aAAa,KAAA,GAAW,MAAM,WAAW;GAE7C,wBAAwB;IAChB;IACN,MAAM;IACN;GACF,CAAC;GAED,aAAa;IACX,4BAA4B,IAAc;GAC5C;EACF;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,MAAM,EAAE,OAAO,eAAe,cAAmC;EAC/D;EACA;CACF,CAAC;CAED,MAAM,aAAa,WAAW,OAAO;CACrC,MAAM,eAAe,eAAe;CACpC,MAAM,WAAW,CAAC,CAAC;CACnB,MAAM,gBAAgB,QAAQ,WAAW,QAAQ;CACjD,MAAM,oBAAoB,YAAY,WAAW;CACjD,MAAM,mBAAmB,WAAW,UAAU;CAE9C,OACE,oBAAC,aAAD;EACW;EACF;EACP,UAAU,CAAC,CAAC;EACA;EACZ,cAAc,YAAY,eAAe,KAAA;EAC9B;EACA;EACC;EAEZ,UAAA,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,oBAAC,eAAD;IACE,IAAI;IACJ,OAAO,MAAM,SAAS;IACtB,gBAAgB,UAAU,MAAM,SAAS,KAAK;IACjC;IACb,UAAU;IACD;IACA;IACU;IACnB,UAAU,CAAC,CAAC;IACZ,gBAAc;IACd,oBACE,WACI,GAAG,QAAQ,UACX,aACE,GAAG,QAAQ,WACX,KAAA;IAER,WAAW,GACT,sBAAsB;KAAE,MAAM;KAAe,SAAS;IAAiB,CAAC,GACxE,SACF;GACD,CAAA,GACA,cAAc,MAAM,SACnB,oBAAC,UAAD;IACE,MAAK;IACL,WAAU;IACV,eAAe,MAAM,SAAS,EAAE;IAChC,UAAU;IACX,UAAA;GAEO,CAAA,CAEP;;CACM,CAAA;AAEjB;AAEA,cAAc,cAAc"}
@@ -0,0 +1,27 @@
1
+ import { Control, FieldPath, FieldValues } from 'react-hook-form';
2
+ import { VariantProps } from 'class-variance-authority';
3
+ declare const datePickerVariants: (props?: ({
4
+ size?: "sm" | "lg" | "md" | null | undefined;
5
+ variant?: "default" | "error" | "success" | null | undefined;
6
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
7
+ export interface DatePickerProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> extends VariantProps<typeof datePickerVariants> {
8
+ name: TName;
9
+ label?: string;
10
+ helperText?: string;
11
+ showError?: boolean;
12
+ error?: string;
13
+ fullWidth?: boolean;
14
+ placeholder?: string;
15
+ disabled?: boolean;
16
+ className?: string;
17
+ id?: string;
18
+ control?: Control<TFieldValues>;
19
+ required?: boolean | string;
20
+ validate?: (value: unknown) => boolean | string | Promise<boolean | string>;
21
+ }
22
+ export declare function DatePicker<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ name, label, helperText, showError, error: customError, size, variant, fullWidth, placeholder, disabled, className, id: providedId, control: externalControl, required, validate, }: DatePickerProps<TFieldValues, TName>): import("react").JSX.Element;
23
+ export declare namespace DatePicker {
24
+ var displayName: string;
25
+ }
26
+ export {};
27
+ //# sourceMappingURL=DatePicker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatePicker.d.ts","sourceRoot":"","sources":["../../../src/components/Form/DatePicker.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAsD,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACrI,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAQlE,QAAA,MAAM,kBAAkB;;;8EAiBtB,CAAC;AAEH,MAAM,WAAW,eAAe,CAC9B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,KAAK,SAAS,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC,CAC/D,SAAQ,YAAY,CAAC,OAAO,kBAAkB,CAAC;IAC/C,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC;CAC7E;AAED,wBAAgB,UAAU,CACxB,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,KAAK,SAAS,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC,EAC/D,EACA,IAAI,EACJ,KAAK,EACL,UAAU,EACV,SAAgB,EAChB,KAAK,EAAE,WAAW,EAClB,IAAI,EACJ,OAAO,EACP,SAAgB,EAChB,WAA2B,EAC3B,QAAQ,EACR,SAAS,EACT,EAAE,EAAE,UAAU,EACd,OAAO,EAAE,eAAe,EACxB,QAAQ,EACR,QAAQ,GACT,EAAE,eAAe,CAAC,YAAY,EAAE,KAAK,CAAC,+BAkGtC;yBArHe,UAAU"}
@@ -0,0 +1,122 @@
1
+ "use client";
2
+ "use client";
3
+ import { cn } from "../../utils/cn.js";
4
+ import { Button } from "../../primitives/button.js";
5
+ import { FormConfigContext } from "./context.js";
6
+ import { FieldLayout } from "./FieldLayout.js";
7
+ import { Popover, PopoverContent, PopoverTrigger } from "../../primitives/popover.js";
8
+ import { Calendar } from "../../primitives/calendar.js";
9
+ import { useContext, useEffect, useId, useState } from "react";
10
+ import { cva } from "class-variance-authority";
11
+ import { jsx, jsxs } from "react/jsx-runtime";
12
+ import { useController, useFormContext } from "react-hook-form";
13
+ import { CalendarIcon } from "lucide-react";
14
+ import { format } from "date-fns";
15
+ //#region src/components/Form/DatePicker.tsx
16
+ var datePickerVariants = cva("w-full justify-start text-left font-normal", {
17
+ variants: {
18
+ size: {
19
+ sm: "h-8 text-xs",
20
+ md: "h-10 text-sm",
21
+ lg: "h-12 text-base"
22
+ },
23
+ variant: {
24
+ default: "border-input",
25
+ error: "border-destructive",
26
+ success: "border-green-500"
27
+ }
28
+ },
29
+ defaultVariants: {
30
+ size: "md",
31
+ variant: "default"
32
+ }
33
+ });
34
+ function DatePicker({ name, label, helperText, showError = true, error: customError, size, variant, fullWidth = true, placeholder = "Pick a date", disabled, className, id: providedId, control: externalControl, required, validate }) {
35
+ const generatedId = useId();
36
+ const inputId = providedId ?? generatedId;
37
+ const [open, setOpen] = useState(false);
38
+ const formConfigContext = useContext(FormConfigContext);
39
+ const formConfig = formConfigContext ?? {};
40
+ const rhfContext = useFormContext();
41
+ const control = externalControl ?? rhfContext?.control;
42
+ const registerFieldValidation = formConfigContext?.registerFieldValidation;
43
+ const unregisterFieldValidation = formConfigContext?.unregisterFieldValidation;
44
+ useEffect(() => {
45
+ if (registerFieldValidation) {
46
+ const rules = {};
47
+ if (required !== void 0) rules.required = required;
48
+ if (validate !== void 0) rules.validate = validate;
49
+ registerFieldValidation({
50
+ name,
51
+ type: "date",
52
+ rules
53
+ });
54
+ return () => {
55
+ unregisterFieldValidation?.(name);
56
+ };
57
+ }
58
+ }, [
59
+ registerFieldValidation,
60
+ unregisterFieldValidation,
61
+ name,
62
+ required,
63
+ validate
64
+ ]);
65
+ const { field, fieldState } = useController({
66
+ name,
67
+ control
68
+ });
69
+ const selectedDate = field.value ? new Date(field.value) : void 0;
70
+ const fieldError = fieldState.error?.message;
71
+ const errorMessage = customError ?? fieldError;
72
+ const hasError = !!errorMessage;
73
+ const effectiveSize = size ?? formConfig.size ?? "md";
74
+ const effectiveDisabled = disabled ?? formConfig.disabled;
75
+ const effectiveVariant = hasError ? "error" : variant;
76
+ return /* @__PURE__ */ jsx(FieldLayout, {
77
+ inputId,
78
+ label,
79
+ required: !!required,
80
+ helperText,
81
+ errorMessage: showError ? errorMessage : void 0,
82
+ showError,
83
+ fullWidth,
84
+ formConfig,
85
+ children: /* @__PURE__ */ jsxs(Popover, {
86
+ open,
87
+ onOpenChange: setOpen,
88
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
89
+ asChild: true,
90
+ children: /* @__PURE__ */ jsxs(Button, {
91
+ id: inputId,
92
+ type: "button",
93
+ variant: "outline",
94
+ disabled: effectiveDisabled,
95
+ "aria-invalid": hasError,
96
+ "aria-describedby": hasError ? `${inputId}-error` : helperText ? `${inputId}-helper` : void 0,
97
+ className: cn(datePickerVariants({
98
+ size: effectiveSize,
99
+ variant: effectiveVariant
100
+ }), !selectedDate && "text-muted-foreground", className),
101
+ children: [/* @__PURE__ */ jsx(CalendarIcon, { className: "mr-2 h-4 w-4" }), selectedDate ? format(selectedDate, "PPP") : placeholder]
102
+ })
103
+ }), /* @__PURE__ */ jsx(PopoverContent, {
104
+ className: "w-auto p-0",
105
+ align: "start",
106
+ children: /* @__PURE__ */ jsx(Calendar, {
107
+ mode: "single",
108
+ selected: selectedDate,
109
+ onSelect: (date) => {
110
+ field.onChange(date ?? "");
111
+ setOpen(false);
112
+ }
113
+ })
114
+ })]
115
+ })
116
+ });
117
+ }
118
+ DatePicker.displayName = "DatePicker";
119
+ //#endregion
120
+ export { DatePicker };
121
+
122
+ //# sourceMappingURL=DatePicker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatePicker.js","names":[],"sources":["../../../src/components/Form/DatePicker.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useContext, useEffect, useId, useState } from \"react\";\r\nimport { format } from \"date-fns\";\r\nimport { CalendarIcon } from \"lucide-react\";\r\nimport { useController, useFormContext as useRHFFormContext, type Control, type FieldPath, type FieldValues } from \"react-hook-form\";\r\nimport { cva, type VariantProps } from \"class-variance-authority\";\r\nimport { cn } from \"../../utils/cn\";\r\nimport { Button } from \"../../primitives/button\";\r\nimport { Calendar } from \"../../primitives/calendar\";\r\nimport { Popover, PopoverContent, PopoverTrigger } from \"../../primitives/popover\";\r\nimport { FormConfigContext, type FieldValidationRules, type FormConfig } from \"./context\";\r\nimport { FieldLayout } from \"./FieldLayout\";\r\n\r\nconst datePickerVariants = cva(\"w-full justify-start text-left font-normal\", {\r\n variants: {\r\n size: {\r\n sm: \"h-8 text-xs\",\r\n md: \"h-10 text-sm\",\r\n lg: \"h-12 text-base\",\r\n },\r\n variant: {\r\n default: \"border-input\",\r\n error: \"border-destructive\",\r\n success: \"border-green-500\",\r\n },\r\n },\r\n defaultVariants: {\r\n size: \"md\",\r\n variant: \"default\",\r\n },\r\n});\r\n\r\nexport interface DatePickerProps<\r\n TFieldValues extends FieldValues = FieldValues,\r\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\r\n> extends VariantProps<typeof datePickerVariants> {\r\n name: TName;\r\n label?: string;\r\n helperText?: string;\r\n showError?: boolean;\r\n error?: string;\r\n fullWidth?: boolean;\r\n placeholder?: string;\r\n disabled?: boolean;\r\n className?: string;\r\n id?: string;\r\n control?: Control<TFieldValues>;\r\n required?: boolean | string;\r\n validate?: (value: unknown) => boolean | string | Promise<boolean | string>;\r\n}\r\n\r\nexport function DatePicker<\r\n TFieldValues extends FieldValues = FieldValues,\r\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\r\n>({\r\n name,\r\n label,\r\n helperText,\r\n showError = true,\r\n error: customError,\r\n size,\r\n variant,\r\n fullWidth = true,\r\n placeholder = \"Pick a date\",\r\n disabled,\r\n className,\r\n id: providedId,\r\n control: externalControl,\r\n required,\r\n validate,\r\n}: DatePickerProps<TFieldValues, TName>) {\r\n const generatedId = useId();\r\n const inputId = providedId ?? generatedId;\r\n const [open, setOpen] = useState(false);\r\n const formConfigContext = useContext(FormConfigContext);\r\n const formConfig: FormConfig = formConfigContext ?? {};\r\n const rhfContext = useRHFFormContext<TFieldValues>();\r\n const control = externalControl ?? rhfContext?.control;\r\n\r\n const registerFieldValidation = formConfigContext?.registerFieldValidation;\r\n const unregisterFieldValidation = formConfigContext?.unregisterFieldValidation;\r\n\r\n useEffect(() => {\r\n if (registerFieldValidation) {\r\n const rules: FieldValidationRules = {};\r\n if (required !== undefined) rules.required = required;\r\n if (validate !== undefined) rules.validate = validate;\r\n\r\n registerFieldValidation({\r\n name: name as string,\r\n type: \"date\",\r\n rules,\r\n });\r\n\r\n return () => {\r\n unregisterFieldValidation?.(name as string);\r\n };\r\n }\r\n }, [\r\n registerFieldValidation,\r\n unregisterFieldValidation,\r\n name,\r\n required,\r\n validate,\r\n ]);\r\n\r\n const { field, fieldState } = useController<TFieldValues, TName>({\r\n name,\r\n control,\r\n });\r\n\r\n const selectedDate = field.value ? new Date(field.value) : undefined;\r\n const fieldError = fieldState.error?.message;\r\n const errorMessage = customError ?? fieldError;\r\n const hasError = !!errorMessage;\r\n const effectiveSize = size ?? formConfig.size ?? \"md\";\r\n const effectiveDisabled = disabled ?? formConfig.disabled;\r\n const effectiveVariant = hasError ? \"error\" : variant;\r\n\r\n return (\r\n <FieldLayout\r\n inputId={inputId}\r\n label={label}\r\n required={!!required}\r\n helperText={helperText}\r\n errorMessage={showError ? errorMessage : undefined}\r\n showError={showError}\r\n fullWidth={fullWidth}\r\n formConfig={formConfig}\r\n >\r\n <Popover open={open} onOpenChange={setOpen}>\r\n <PopoverTrigger asChild>\r\n <Button\r\n id={inputId}\r\n type=\"button\"\r\n variant=\"outline\"\r\n disabled={effectiveDisabled}\r\n aria-invalid={hasError}\r\n aria-describedby={\r\n hasError\r\n ? `${inputId}-error`\r\n : helperText\r\n ? `${inputId}-helper`\r\n : undefined\r\n }\r\n className={cn(\r\n datePickerVariants({ size: effectiveSize, variant: effectiveVariant }),\r\n !selectedDate && \"text-muted-foreground\",\r\n className\r\n )}\r\n >\r\n <CalendarIcon className=\"mr-2 h-4 w-4\" />\r\n {selectedDate ? format(selectedDate, \"PPP\") : placeholder}\r\n </Button>\r\n </PopoverTrigger>\r\n <PopoverContent className=\"w-auto p-0\" align=\"start\">\r\n <Calendar\r\n mode=\"single\"\r\n selected={selectedDate}\r\n onSelect={(date) => {\r\n field.onChange(date ?? \"\");\r\n setOpen(false);\r\n }}\r\n />\r\n </PopoverContent>\r\n </Popover>\r\n </FieldLayout>\r\n );\r\n}\r\n\r\nDatePicker.displayName = \"DatePicker\";\r\n"],"mappings":";;;;;;;;;;;;;;;AAcA,IAAM,qBAAqB,IAAI,8CAA8C;CAC3E,UAAU;EACR,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EACA,SAAS;GACP,SAAS;GACT,OAAO;GACP,SAAS;EACX;CACF;CACA,iBAAiB;EACf,MAAM;EACN,SAAS;CACX;AACF,CAAC;AAqBD,SAAgB,WAGd,EACA,MACA,OACA,YACA,YAAY,MACZ,OAAO,aACP,MACA,SACA,YAAY,MACZ,cAAc,eACd,UACA,WACA,IAAI,YACJ,SAAS,iBACT,UACA,YACuC;CACvC,MAAM,cAAc,MAAM;CAC1B,MAAM,UAAU,cAAc;CAC9B,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,oBAAoB,WAAW,iBAAiB;CACtD,MAAM,aAAyB,qBAAqB,CAAC;CACrD,MAAM,aAAa,eAAgC;CACnD,MAAM,UAAU,mBAAmB,YAAY;CAE/C,MAAM,0BAA0B,mBAAmB;CACnD,MAAM,4BAA4B,mBAAmB;CAErD,gBAAgB;EACd,IAAI,yBAAyB;GAC3B,MAAM,QAA8B,CAAC;GACrC,IAAI,aAAa,KAAA,GAAW,MAAM,WAAW;GAC7C,IAAI,aAAa,KAAA,GAAW,MAAM,WAAW;GAE7C,wBAAwB;IAChB;IACN,MAAM;IACN;GACF,CAAC;GAED,aAAa;IACX,4BAA4B,IAAc;GAC5C;EACF;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,MAAM,EAAE,OAAO,eAAe,cAAmC;EAC/D;EACA;CACF,CAAC;CAED,MAAM,eAAe,MAAM,QAAQ,IAAI,KAAK,MAAM,KAAK,IAAI,KAAA;CAC3D,MAAM,aAAa,WAAW,OAAO;CACrC,MAAM,eAAe,eAAe;CACpC,MAAM,WAAW,CAAC,CAAC;CACnB,MAAM,gBAAgB,QAAQ,WAAW,QAAQ;CACjD,MAAM,oBAAoB,YAAY,WAAW;CACjD,MAAM,mBAAmB,WAAW,UAAU;CAE9C,OACE,oBAAC,aAAD;EACW;EACF;EACP,UAAU,CAAC,CAAC;EACA;EACZ,cAAc,YAAY,eAAe,KAAA;EAC9B;EACA;EACC;EAEZ,UAAA,qBAAC,SAAD;GAAe;GAAM,cAAc;GAAnC,UAAA,CACE,oBAAC,gBAAD;IAAgB,SAAA;IACd,UAAA,qBAAC,QAAD;KACE,IAAI;KACJ,MAAK;KACL,SAAQ;KACR,UAAU;KACV,gBAAc;KACd,oBACE,WACI,GAAG,QAAQ,UACX,aACE,GAAG,QAAQ,WACX,KAAA;KAER,WAAW,GACT,mBAAmB;MAAE,MAAM;MAAe,SAAS;KAAiB,CAAC,GACrE,CAAC,gBAAgB,yBACjB,SACF;KAjBF,UAAA,CAmBE,oBAAC,cAAD,EAAc,WAAU,eAAgB,CAAA,GACvC,eAAe,OAAO,cAAc,KAAK,IAAI,WACxC;;GACM,CAAA,GAChB,oBAAC,gBAAD;IAAgB,WAAU;IAAa,OAAM;IAC3C,UAAA,oBAAC,UAAD;KACE,MAAK;KACL,UAAU;KACV,WAAW,SAAS;MAClB,MAAM,SAAS,QAAQ,EAAE;MACzB,QAAQ,KAAK;KACf;IACD,CAAA;GACa,CAAA,CACT;;CACE,CAAA;AAEjB;AAEA,WAAW,cAAc"}
@@ -0,0 +1,15 @@
1
+ import { ReactNode } from 'react';
2
+ import { FormConfig } from './context';
3
+ export interface FieldLayoutProps {
4
+ inputId: string;
5
+ label?: string;
6
+ required?: boolean;
7
+ helperText?: string;
8
+ errorMessage?: string;
9
+ showError?: boolean;
10
+ fullWidth?: boolean;
11
+ formConfig?: FormConfig;
12
+ children: ReactNode;
13
+ }
14
+ export declare function FieldLayout({ inputId, label, required, helperText, errorMessage, showError, fullWidth, formConfig, children, }: FieldLayoutProps): import("react").JSX.Element;
15
+ //# sourceMappingURL=FieldLayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FieldLayout.d.ts","sourceRoot":"","sources":["../../../src/components/Form/FieldLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAUD,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,KAAK,EACL,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,SAAgB,EAChB,SAAgB,EAChB,UAAe,EACf,QAAQ,GACT,EAAE,gBAAgB,+BA6ElB"}
@@ -0,0 +1,65 @@
1
+ "use client";
2
+ "use client";
3
+ import { cn } from "../../utils/cn.js";
4
+ import { Label } from "../../primitives/label.js";
5
+ import { labelVariants } from "./variants.js";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/components/Form/FieldLayout.tsx
8
+ function resolveLabelWidth(labelWidth) {
9
+ if (labelWidth === void 0) return;
10
+ return typeof labelWidth === "number" ? `${labelWidth}px` : labelWidth;
11
+ }
12
+ function FieldLayout({ inputId, label, required, helperText, errorMessage, showError = true, fullWidth = true, formConfig = {}, children }) {
13
+ const layout = formConfig.layout ?? "vertical";
14
+ const labelWidth = resolveLabelWidth(formConfig.labelWidth);
15
+ const hasError = !!errorMessage;
16
+ const showHelper = !!helperText && !hasError;
17
+ const labelNode = label ? /* @__PURE__ */ jsxs(Label, {
18
+ htmlFor: inputId,
19
+ className: cn(labelVariants({ required: !!required }), layout === "horizontal" && "mb-0 shrink-0 pt-2", layout === "inline" && "mb-0 shrink-0"),
20
+ style: layout === "horizontal" && labelWidth ? { width: labelWidth } : void 0,
21
+ children: [label, formConfig.colon && ":"]
22
+ }) : null;
23
+ const messages = /* @__PURE__ */ jsxs(Fragment, { children: [showError && hasError && /* @__PURE__ */ jsx("p", {
24
+ id: `${inputId}-error`,
25
+ className: "text-sm text-destructive",
26
+ role: "alert",
27
+ children: errorMessage
28
+ }), showHelper && /* @__PURE__ */ jsx("p", {
29
+ id: `${inputId}-helper`,
30
+ className: "text-sm text-muted-foreground",
31
+ children: helperText
32
+ })] });
33
+ if (layout === "horizontal") return /* @__PURE__ */ jsx("div", {
34
+ className: cn("space-y-1.5", fullWidth && "w-full"),
35
+ children: /* @__PURE__ */ jsxs("div", {
36
+ className: "flex items-start gap-4",
37
+ children: [labelNode, /* @__PURE__ */ jsxs("div", {
38
+ className: "min-w-0 flex-1 space-y-1.5",
39
+ children: [children, messages]
40
+ })]
41
+ })
42
+ });
43
+ if (layout === "inline") return /* @__PURE__ */ jsxs("div", {
44
+ className: cn("space-y-1.5", fullWidth && "w-full"),
45
+ children: [/* @__PURE__ */ jsxs("div", {
46
+ className: "flex flex-wrap items-center gap-3",
47
+ children: [labelNode, /* @__PURE__ */ jsx("div", {
48
+ className: "min-w-0 flex-1",
49
+ children
50
+ })]
51
+ }), messages]
52
+ });
53
+ return /* @__PURE__ */ jsxs("div", {
54
+ className: cn("space-y-1.5", fullWidth && "w-full"),
55
+ children: [
56
+ labelNode,
57
+ children,
58
+ messages
59
+ ]
60
+ });
61
+ }
62
+ //#endregion
63
+ export { FieldLayout };
64
+
65
+ //# sourceMappingURL=FieldLayout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FieldLayout.js","names":[],"sources":["../../../src/components/Form/FieldLayout.tsx"],"sourcesContent":["'use client';\r\n\r\nimport type { ReactNode } from \"react\";\r\nimport { cn } from \"../../utils/cn\";\r\nimport { Label } from \"../../primitives/label\";\r\nimport { labelVariants } from \"./variants\";\r\nimport type { FormConfig } from \"./context\";\r\n\r\nexport interface FieldLayoutProps {\r\n inputId: string;\r\n label?: string;\r\n required?: boolean;\r\n helperText?: string;\r\n errorMessage?: string;\r\n showError?: boolean;\r\n fullWidth?: boolean;\r\n formConfig?: FormConfig;\r\n children: ReactNode;\r\n}\r\n\r\nfunction resolveLabelWidth(labelWidth?: string | number): string | undefined {\r\n if (labelWidth === undefined) {\r\n return undefined;\r\n }\r\n\r\n return typeof labelWidth === \"number\" ? `${labelWidth}px` : labelWidth;\r\n}\r\n\r\nexport function FieldLayout({\r\n inputId,\r\n label,\r\n required,\r\n helperText,\r\n errorMessage,\r\n showError = true,\r\n fullWidth = true,\r\n formConfig = {},\r\n children,\r\n}: FieldLayoutProps) {\r\n const layout = formConfig.layout ?? \"vertical\";\r\n const labelWidth = resolveLabelWidth(formConfig.labelWidth);\r\n const hasError = !!errorMessage;\r\n const showHelper = !!helperText && !hasError;\r\n\r\n const labelNode = label ? (\r\n <Label\r\n htmlFor={inputId}\r\n className={cn(\r\n labelVariants({ required: !!required }),\r\n layout === \"horizontal\" && \"mb-0 shrink-0 pt-2\",\r\n layout === \"inline\" && \"mb-0 shrink-0\"\r\n )}\r\n style={layout === \"horizontal\" && labelWidth ? { width: labelWidth } : undefined}\r\n >\r\n {label}\r\n {formConfig.colon && \":\"}\r\n </Label>\r\n ) : null;\r\n\r\n const messages = (\r\n <>\r\n {showError && hasError && (\r\n <p\r\n id={`${inputId}-error`}\r\n className=\"text-sm text-destructive\"\r\n role=\"alert\"\r\n >\r\n {errorMessage}\r\n </p>\r\n )}\r\n\r\n {showHelper && (\r\n <p\r\n id={`${inputId}-helper`}\r\n className=\"text-sm text-muted-foreground\"\r\n >\r\n {helperText}\r\n </p>\r\n )}\r\n </>\r\n );\r\n\r\n if (layout === \"horizontal\") {\r\n return (\r\n <div className={cn(\"space-y-1.5\", fullWidth && \"w-full\")}>\r\n <div className=\"flex items-start gap-4\">\r\n {labelNode}\r\n <div className=\"min-w-0 flex-1 space-y-1.5\">\r\n {children}\r\n {messages}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (layout === \"inline\") {\r\n return (\r\n <div className={cn(\"space-y-1.5\", fullWidth && \"w-full\")}>\r\n <div className=\"flex flex-wrap items-center gap-3\">\r\n {labelNode}\r\n <div className=\"min-w-0 flex-1\">{children}</div>\r\n </div>\r\n {messages}\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className={cn(\"space-y-1.5\", fullWidth && \"w-full\")}>\r\n {labelNode}\r\n {children}\r\n {messages}\r\n </div>\r\n );\r\n}\r\n"],"mappings":";;;;;;;AAoBA,SAAS,kBAAkB,YAAkD;CAC3E,IAAI,eAAe,KAAA,GACjB;CAGF,OAAO,OAAO,eAAe,WAAW,GAAG,WAAW,MAAM;AAC9D;AAEA,SAAgB,YAAY,EAC1B,SACA,OACA,UACA,YACA,cACA,YAAY,MACZ,YAAY,MACZ,aAAa,CAAC,GACd,YACmB;CACnB,MAAM,SAAS,WAAW,UAAU;CACpC,MAAM,aAAa,kBAAkB,WAAW,UAAU;CAC1D,MAAM,WAAW,CAAC,CAAC;CACnB,MAAM,aAAa,CAAC,CAAC,cAAc,CAAC;CAEpC,MAAM,YAAY,QAChB,qBAAC,OAAD;EACE,SAAS;EACT,WAAW,GACT,cAAc,EAAE,UAAU,CAAC,CAAC,SAAS,CAAC,GACtC,WAAW,gBAAgB,sBAC3B,WAAW,YAAY,eACzB;EACA,OAAO,WAAW,gBAAgB,aAAa,EAAE,OAAO,WAAW,IAAI,KAAA;EAPzE,UAAA,CASG,OACA,WAAW,SAAS,GAChB;CACL,CAAA,IAAA;CAEJ,MAAM,WACJ,qBAAA,UAAA,EAAA,UAAA,CACG,aAAa,YACZ,oBAAC,KAAD;EACE,IAAI,GAAG,QAAQ;EACf,WAAU;EACV,MAAK;EAEJ,UAAA;CACA,CAAA,GAGJ,cACC,oBAAC,KAAD;EACE,IAAI,GAAG,QAAQ;EACf,WAAU;EAET,UAAA;CACA,CAAA,CAEL,EAAA,CAAA;CAGJ,IAAI,WAAW,cACb,OACE,oBAAC,OAAD;EAAK,WAAW,GAAG,eAAe,aAAa,QAAQ;EACrD,UAAA,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACG,WACD,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACG,UACA,QACE;GACF,CAAA,CAAA;;CACF,CAAA;CAIT,IAAI,WAAW,UACb,OACE,qBAAC,OAAD;EAAK,WAAW,GAAG,eAAe,aAAa,QAAQ;EAAvD,UAAA,CACE,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACG,WACD,oBAAC,OAAD;IAAK,WAAU;IAAkB;GAAc,CAAA,CAC5C;EACJ,CAAA,GAAA,QACE;;CAIT,OACE,qBAAC,OAAD;EAAK,WAAW,GAAG,eAAe,aAAa,QAAQ;EAAvD,UAAA;GACG;GACA;GACA;EACE;;AAET"}
@@ -55,7 +55,7 @@ export interface FormProps<TFieldValues extends FieldValues = FieldValues, TCont
55
55
  * </Form>
56
56
  * ```
57
57
  */
58
- export declare function Form<TFieldValues extends FieldValues = FieldValues, TContext = unknown>({ schema: baseSchema, defaultValues, values, onSubmit, onError, config, children, form: externalForm, mode, reValidateMode, resolver: customResolver, ...formProps }: FormProps<TFieldValues, TContext>): import("react").JSX.Element;
58
+ export declare function Form<TFieldValues extends FieldValues = FieldValues, TContext = unknown>({ schema: baseSchema, defaultValues, values, onSubmit, onError, config, children, form: externalForm, mode: modeProp, reValidateMode: reValidateModeProp, resolver: customResolver, ...formProps }: FormProps<TFieldValues, TContext>): import("react").JSX.Element;
59
59
  export declare namespace Form {
60
60
  var displayName: string;
61
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Form.d.ts","sourceRoot":"","sources":["../../../src/components/Form/Form.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC7D,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,QAAQ,EAEd,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAIL,KAAK,UAAU,EAEhB,MAAM,WAAW,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,SAAS,CACxB,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,QAAQ,GAAG,OAAO,CAClB,SAAQ,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,eAAe,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAC/E,uEAAuE;IAEvE,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC3C,kCAAkC;IAClC,aAAa,CAAC,EAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,eAAe,CAAC,CAAC;IACtE,kCAAkC;IAClC,MAAM,CAAC,EAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC;IACxD,qBAAqB;IACrB,QAAQ,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACvC,oBAAoB;IACpB,OAAO,CAAC,EAAE,kBAAkB,CAAC,YAAY,CAAC,CAAC;IAC3C,yBAAyB;IACzB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,eAAe;IACf,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,oDAAoD;IACpD,IAAI,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACnC,sBAAsB;IACtB,IAAI,CAAC,EAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;IACpD,wBAAwB;IACxB,cAAc,CAAC,EAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,gBAAgB,CAAC,CAAC;IACxE,yCAAyC;IACzC,QAAQ,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,IAAI,CAClB,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,QAAQ,GAAG,OAAO,EAClB,EACA,MAAM,EAAE,UAAU,EAClB,aAAa,EACb,MAAM,EACN,QAAQ,EACR,OAAO,EACP,MAAM,EACN,QAAQ,EACR,IAAI,EAAE,YAAY,EAClB,IAAe,EACf,cAA2B,EAC3B,QAAQ,EAAE,cAAc,EACxB,GAAG,SAAS,EACb,EAAE,SAAS,CAAC,YAAY,EAAE,QAAQ,CAAC,+BAmGnC;yBAnHe,IAAI"}
1
+ {"version":3,"file":"Form.d.ts","sourceRoot":"","sources":["../../../src/components/Form/Form.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC7D,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,QAAQ,EAEd,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAIL,KAAK,UAAU,EAEhB,MAAM,WAAW,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,SAAS,CACxB,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,QAAQ,GAAG,OAAO,CAClB,SAAQ,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,eAAe,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAC/E,uEAAuE;IAEvE,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC3C,kCAAkC;IAClC,aAAa,CAAC,EAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,eAAe,CAAC,CAAC;IACtE,kCAAkC;IAClC,MAAM,CAAC,EAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC;IACxD,qBAAqB;IACrB,QAAQ,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACvC,oBAAoB;IACpB,OAAO,CAAC,EAAE,kBAAkB,CAAC,YAAY,CAAC,CAAC;IAC3C,yBAAyB;IACzB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,eAAe;IACf,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,oDAAoD;IACpD,IAAI,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACnC,sBAAsB;IACtB,IAAI,CAAC,EAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;IACpD,wBAAwB;IACxB,cAAc,CAAC,EAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,gBAAgB,CAAC,CAAC;IACxE,yCAAyC;IACzC,QAAQ,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,IAAI,CAClB,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,QAAQ,GAAG,OAAO,EAClB,EACA,MAAM,EAAE,UAAU,EAClB,aAAa,EACb,MAAM,EACN,QAAQ,EACR,OAAO,EACP,MAAM,EACN,QAAQ,EACR,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,QAAQ,EACd,cAAc,EAAE,kBAAkB,EAClC,QAAQ,EAAE,cAAc,EACxB,GAAG,SAAS,EACb,EAAE,SAAS,CAAC,YAAY,EAAE,QAAQ,CAAC,+BA+GnC;yBA/He,IAAI"}
@@ -33,21 +33,24 @@ import { z } from "zod";
33
33
  * </Form>
34
34
  * ```
35
35
  */
36
- function Form({ schema: baseSchema, defaultValues, values, onSubmit, onError, config, children, form: externalForm, mode = "onBlur", reValidateMode = "onChange", resolver: customResolver, ...formProps }) {
36
+ function Form({ schema: baseSchema, defaultValues, values, onSubmit, onError, config, children, form: externalForm, mode: modeProp, reValidateMode: reValidateModeProp, resolver: customResolver, ...formProps }) {
37
37
  const mergedConfig = {
38
38
  ...defaultFormConfig,
39
39
  ...config
40
40
  };
41
+ const mode = modeProp ?? (mergedConfig.validateOnChange ? "onChange" : mergedConfig.validateOnBlur !== false ? "onBlur" : "onSubmit");
42
+ const reValidateMode = reValidateModeProp ?? (mergedConfig.validateOnChange ? "onChange" : "onBlur");
41
43
  const { registerFieldValidation, unregisterFieldValidation, getValidationSchema } = useFieldValidationRegistry();
44
+ const dynamicResolver = useCallback(async (vals, context, options) => {
45
+ if (customResolver) return customResolver(vals, context, options);
46
+ const fieldSchema = getValidationSchema();
47
+ let finalSchema;
48
+ if (baseSchema instanceof z.ZodObject) finalSchema = baseSchema.merge(fieldSchema);
49
+ else finalSchema = baseSchema ?? fieldSchema;
50
+ return zodResolver(finalSchema)(vals, context, options);
51
+ }, [baseSchema, customResolver]);
42
52
  const internalForm = useForm({
43
- resolver: useCallback(async (vals, context, options) => {
44
- if (customResolver) return customResolver(vals, context, options);
45
- const fieldSchema = getValidationSchema();
46
- let finalSchema;
47
- if (baseSchema instanceof z.ZodObject) finalSchema = baseSchema.merge(fieldSchema);
48
- else finalSchema = baseSchema ?? fieldSchema;
49
- return zodResolver(finalSchema)(vals, context, options);
50
- }, [baseSchema, customResolver]),
53
+ resolver: dynamicResolver,
51
54
  defaultValues,
52
55
  values,
53
56
  mode,