@timeax/form-palette 0.0.2 → 0.0.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 (503) hide show
  1. package/dist/adapters/axios.d.ts +21 -0
  2. package/dist/adapters/axios.d.ts.map +1 -0
  3. package/dist/adapters/axios.js +74 -0
  4. package/dist/adapters/axios.js.map +1 -0
  5. package/dist/adapters/index.d.ts +35 -0
  6. package/dist/adapters/index.d.ts.map +1 -0
  7. package/dist/adapters/index.js +74 -0
  8. package/dist/adapters/index.js.map +1 -0
  9. package/dist/adapters/inertia.d.ts +24 -0
  10. package/dist/adapters/inertia.d.ts.map +1 -0
  11. package/dist/adapters/inertia.js +126 -0
  12. package/dist/adapters/inertia.js.map +1 -0
  13. package/dist/core/adapter-registry.d.ts +30 -0
  14. package/dist/core/adapter-registry.d.ts.map +1 -0
  15. package/{src/core/adapter-registry.ts → dist/core/adapter-registry.js} +10 -28
  16. package/dist/core/adapter-registry.js.map +1 -0
  17. package/{src/core/bound/bind-host.ts → dist/core/bound/bind-host.d.ts} +2 -3
  18. package/dist/core/bound/bind-host.d.ts.map +1 -0
  19. package/dist/core/bound/bind-host.js +2 -0
  20. package/dist/core/bound/bind-host.js.map +1 -0
  21. package/dist/core/bound/observe-bound-field.d.ts +21 -0
  22. package/dist/core/bound/observe-bound-field.d.ts.map +1 -0
  23. package/dist/core/bound/observe-bound-field.js +116 -0
  24. package/dist/core/bound/observe-bound-field.js.map +1 -0
  25. package/dist/core/bound/wait-for-bound-field.d.ts +5 -0
  26. package/dist/core/bound/wait-for-bound-field.d.ts.map +1 -0
  27. package/dist/core/bound/wait-for-bound-field.js +35 -0
  28. package/dist/core/bound/wait-for-bound-field.js.map +1 -0
  29. package/{src/core/context.ts → dist/core/context.d.ts} +2 -6
  30. package/dist/core/context.d.ts.map +1 -0
  31. package/dist/core/context.js +11 -0
  32. package/dist/core/context.js.map +1 -0
  33. package/dist/core/core-provider.d.ts +22 -0
  34. package/dist/core/core-provider.d.ts.map +1 -0
  35. package/{src/core/core-provider.tsx → dist/core/core-provider.js} +209 -364
  36. package/dist/core/core-provider.js.map +1 -0
  37. package/dist/core/core-root.d.ts +26 -0
  38. package/dist/core/core-root.d.ts.map +1 -0
  39. package/dist/core/core-root.js +38 -0
  40. package/dist/core/core-root.js.map +1 -0
  41. package/dist/core/core-shell.d.ts +22 -0
  42. package/dist/core/core-shell.d.ts.map +1 -0
  43. package/dist/core/core-shell.js +8 -0
  44. package/dist/core/core-shell.js.map +1 -0
  45. package/{src/core/errors/error-strip.tsx → dist/core/errors/error-strip.d.ts} +2 -39
  46. package/dist/core/errors/error-strip.d.ts.map +1 -0
  47. package/dist/core/errors/error-strip.js +18 -0
  48. package/dist/core/errors/error-strip.js.map +1 -0
  49. package/dist/core/errors/index.d.ts +4 -0
  50. package/dist/core/errors/index.d.ts.map +1 -0
  51. package/dist/core/errors/index.js +4 -0
  52. package/dist/core/errors/index.js.map +1 -0
  53. package/dist/core/errors/map-error-bag.d.ts +24 -0
  54. package/dist/core/errors/map-error-bag.d.ts.map +1 -0
  55. package/{src/core/errors/map-error-bag.ts → dist/core/errors/map-error-bag.js} +10 -22
  56. package/dist/core/errors/map-error-bag.js.map +1 -0
  57. package/dist/core/errors/map-zod.d.ts +18 -0
  58. package/dist/core/errors/map-zod.d.ts.map +1 -0
  59. package/{src/core/errors/map-zod.ts → dist/core/errors/map-zod.js} +7 -19
  60. package/dist/core/errors/map-zod.js.map +1 -0
  61. package/dist/core/hooks/use-button.d.ts +73 -0
  62. package/dist/core/hooks/use-button.d.ts.map +1 -0
  63. package/dist/core/hooks/use-button.js +116 -0
  64. package/dist/core/hooks/use-button.js.map +1 -0
  65. package/dist/core/hooks/use-core-context.d.ts +9 -0
  66. package/dist/core/hooks/use-core-context.d.ts.map +1 -0
  67. package/{src/core/hooks/use-core-context.ts → dist/core/hooks/use-core-context.js} +3 -6
  68. package/dist/core/hooks/use-core-context.js.map +1 -0
  69. package/dist/core/hooks/use-core-utility.d.ts +1 -0
  70. package/dist/core/hooks/use-core-utility.d.ts.map +1 -0
  71. package/dist/core/hooks/use-core-utility.js +2 -0
  72. package/dist/core/hooks/use-core-utility.js.map +1 -0
  73. package/{src/core/hooks/use-core.ts → dist/core/hooks/use-core.d.ts} +9 -13
  74. package/dist/core/hooks/use-core.d.ts.map +1 -0
  75. package/dist/core/hooks/use-core.js +11 -0
  76. package/dist/core/hooks/use-core.js.map +1 -0
  77. package/dist/core/hooks/use-field.d.ts +141 -0
  78. package/dist/core/hooks/use-field.d.ts.map +1 -0
  79. package/dist/core/hooks/use-field.js +256 -0
  80. package/dist/core/hooks/use-field.js.map +1 -0
  81. package/dist/core/hooks/use-optional-field.d.ts +9 -0
  82. package/dist/core/hooks/use-optional-field.d.ts.map +1 -0
  83. package/dist/core/hooks/use-optional-field.js +146 -0
  84. package/dist/core/hooks/use-optional-field.js.map +1 -0
  85. package/dist/core/index.d.ts +11 -0
  86. package/dist/core/index.d.ts.map +1 -0
  87. package/dist/core/index.js +11 -0
  88. package/dist/core/index.js.map +1 -0
  89. package/dist/core/registry/binder-registry.d.ts +38 -0
  90. package/dist/core/registry/binder-registry.d.ts.map +1 -0
  91. package/dist/core/registry/binder-registry.js +52 -0
  92. package/dist/core/registry/binder-registry.js.map +1 -0
  93. package/dist/core/registry/field-registry.d.ts +86 -0
  94. package/dist/core/registry/field-registry.d.ts.map +1 -0
  95. package/{src/core/registry/field-registry.ts → dist/core/registry/field-registry.js} +56 -70
  96. package/dist/core/registry/field-registry.js.map +1 -0
  97. package/dist/core/test.d.ts +2 -0
  98. package/dist/core/test.d.ts.map +1 -0
  99. package/dist/core/test.js +9 -0
  100. package/dist/core/test.js.map +1 -0
  101. package/dist/index.d.ts +15 -0
  102. package/dist/index.d.ts.map +1 -0
  103. package/{src/index.ts → dist/index.js} +5 -47
  104. package/dist/index.js.map +1 -0
  105. package/{src/input/index.ts → dist/input/index.d.ts} +1 -2
  106. package/dist/input/index.d.ts.map +1 -0
  107. package/dist/input/index.js +3 -0
  108. package/dist/input/index.js.map +1 -0
  109. package/dist/input/input-field.d.ts +15 -0
  110. package/dist/input/input-field.d.ts.map +1 -0
  111. package/dist/input/input-field.js +413 -0
  112. package/dist/input/input-field.js.map +1 -0
  113. package/dist/input/input-layout-graph.d.ts +77 -0
  114. package/dist/input/input-layout-graph.d.ts.map +1 -0
  115. package/dist/input/input-layout-graph.js +108 -0
  116. package/dist/input/input-layout-graph.js.map +1 -0
  117. package/{src/input/input-props.ts → dist/input/input-props.d.ts} +22 -84
  118. package/dist/input/input-props.d.ts.map +1 -0
  119. package/dist/input/input-props.js +4 -0
  120. package/dist/input/input-props.js.map +1 -0
  121. package/dist/lib/get-global-countries.d.ts +3 -0
  122. package/dist/lib/get-global-countries.d.ts.map +1 -0
  123. package/dist/lib/get-global-countries.js +70 -0
  124. package/dist/lib/get-global-countries.js.map +1 -0
  125. package/dist/lib/utils.d.ts +3 -0
  126. package/dist/lib/utils.d.ts.map +1 -0
  127. package/dist/lib/utils.js +6 -0
  128. package/dist/lib/utils.js.map +1 -0
  129. package/dist/presets/index.d.ts +1 -0
  130. package/dist/presets/index.d.ts.map +1 -0
  131. package/dist/presets/index.js +2 -0
  132. package/dist/presets/index.js.map +1 -0
  133. package/dist/presets/shadcn-preset.d.ts +1 -0
  134. package/dist/presets/shadcn-preset.d.ts.map +1 -0
  135. package/dist/presets/shadcn-preset.js +2 -0
  136. package/dist/presets/shadcn-preset.js.map +1 -0
  137. package/dist/presets/shadcn-variants/checkbox.d.ts +212 -0
  138. package/dist/presets/shadcn-variants/checkbox.d.ts.map +1 -0
  139. package/dist/presets/shadcn-variants/checkbox.js +315 -0
  140. package/dist/presets/shadcn-variants/checkbox.js.map +1 -0
  141. package/dist/presets/shadcn-variants/chips.d.ts +154 -0
  142. package/dist/presets/shadcn-variants/chips.d.ts.map +1 -0
  143. package/dist/presets/shadcn-variants/chips.js +266 -0
  144. package/dist/presets/shadcn-variants/chips.js.map +1 -0
  145. package/dist/presets/shadcn-variants/color.d.ts +63 -0
  146. package/dist/presets/shadcn-variants/color.d.ts.map +1 -0
  147. package/dist/presets/shadcn-variants/color.js +96 -0
  148. package/dist/presets/shadcn-variants/color.js.map +1 -0
  149. package/dist/presets/shadcn-variants/custom.d.ts +94 -0
  150. package/dist/presets/shadcn-variants/custom.d.ts.map +1 -0
  151. package/dist/presets/shadcn-variants/custom.js +80 -0
  152. package/dist/presets/shadcn-variants/custom.js.map +1 -0
  153. package/dist/presets/shadcn-variants/date.d.ts +114 -0
  154. package/dist/presets/shadcn-variants/date.d.ts.map +1 -0
  155. package/dist/presets/shadcn-variants/date.js +414 -0
  156. package/dist/presets/shadcn-variants/date.js.map +1 -0
  157. package/dist/presets/shadcn-variants/file.d.ts +79 -0
  158. package/dist/presets/shadcn-variants/file.d.ts.map +1 -0
  159. package/dist/presets/shadcn-variants/file.js +289 -0
  160. package/dist/presets/shadcn-variants/file.js.map +1 -0
  161. package/dist/presets/shadcn-variants/keyvalue.d.ts +35 -0
  162. package/dist/presets/shadcn-variants/keyvalue.d.ts.map +1 -0
  163. package/dist/presets/shadcn-variants/keyvalue.js +215 -0
  164. package/dist/presets/shadcn-variants/keyvalue.js.map +1 -0
  165. package/dist/presets/shadcn-variants/multiselect.d.ts +210 -0
  166. package/dist/presets/shadcn-variants/multiselect.d.ts.map +1 -0
  167. package/dist/presets/shadcn-variants/multiselect.js +352 -0
  168. package/dist/presets/shadcn-variants/multiselect.js.map +1 -0
  169. package/dist/presets/shadcn-variants/number.d.ts +31 -0
  170. package/dist/presets/shadcn-variants/number.d.ts.map +1 -0
  171. package/dist/presets/shadcn-variants/number.js +64 -0
  172. package/dist/presets/shadcn-variants/number.js.map +1 -0
  173. package/dist/presets/shadcn-variants/password.d.ts +195 -0
  174. package/dist/presets/shadcn-variants/password.d.ts.map +1 -0
  175. package/dist/presets/shadcn-variants/password.js +296 -0
  176. package/dist/presets/shadcn-variants/password.js.map +1 -0
  177. package/dist/presets/shadcn-variants/phone.d.ts +69 -0
  178. package/dist/presets/shadcn-variants/phone.d.ts.map +1 -0
  179. package/dist/presets/shadcn-variants/phone.js +308 -0
  180. package/dist/presets/shadcn-variants/phone.js.map +1 -0
  181. package/dist/presets/shadcn-variants/radio.d.ts +172 -0
  182. package/dist/presets/shadcn-variants/radio.d.ts.map +1 -0
  183. package/dist/presets/shadcn-variants/radio.js +192 -0
  184. package/dist/presets/shadcn-variants/radio.js.map +1 -0
  185. package/dist/presets/shadcn-variants/select.d.ts +203 -0
  186. package/dist/presets/shadcn-variants/select.d.ts.map +1 -0
  187. package/dist/presets/shadcn-variants/select.js +285 -0
  188. package/dist/presets/shadcn-variants/select.js.map +1 -0
  189. package/dist/presets/shadcn-variants/slider.d.ts +131 -0
  190. package/dist/presets/shadcn-variants/slider.d.ts.map +1 -0
  191. package/dist/presets/shadcn-variants/slider.js +151 -0
  192. package/dist/presets/shadcn-variants/slider.js.map +1 -0
  193. package/dist/presets/shadcn-variants/text.d.ts +155 -0
  194. package/dist/presets/shadcn-variants/text.d.ts.map +1 -0
  195. package/dist/presets/shadcn-variants/text.js +98 -0
  196. package/dist/presets/shadcn-variants/text.js.map +1 -0
  197. package/dist/presets/shadcn-variants/textarea.d.ts +18 -0
  198. package/dist/presets/shadcn-variants/textarea.d.ts.map +1 -0
  199. package/dist/presets/shadcn-variants/textarea.js +24 -0
  200. package/dist/presets/shadcn-variants/textarea.js.map +1 -0
  201. package/dist/presets/shadcn-variants/toggle.d.ts +61 -0
  202. package/dist/presets/shadcn-variants/toggle.d.ts.map +1 -0
  203. package/dist/presets/shadcn-variants/toggle.js +67 -0
  204. package/dist/presets/shadcn-variants/toggle.js.map +1 -0
  205. package/dist/presets/shadcn-variants/treeselect.d.ts +81 -0
  206. package/dist/presets/shadcn-variants/treeselect.d.ts.map +1 -0
  207. package/dist/presets/shadcn-variants/treeselect.js +317 -0
  208. package/dist/presets/shadcn-variants/treeselect.js.map +1 -0
  209. package/dist/presets/ui/badge.d.ts +10 -0
  210. package/dist/presets/ui/badge.d.ts.map +1 -0
  211. package/dist/presets/ui/badge.js +23 -0
  212. package/dist/presets/ui/badge.js.map +1 -0
  213. package/dist/presets/ui/button.d.ts +11 -0
  214. package/dist/presets/ui/button.d.ts.map +1 -0
  215. package/dist/presets/ui/button.js +34 -0
  216. package/dist/presets/ui/button.js.map +1 -0
  217. package/dist/presets/ui/calendar.d.ts +9 -0
  218. package/dist/presets/ui/calendar.d.ts.map +1 -0
  219. package/dist/presets/ui/calendar.js +76 -0
  220. package/dist/presets/ui/calendar.js.map +1 -0
  221. package/dist/presets/ui/checkbox.d.ts +18 -0
  222. package/dist/presets/ui/checkbox.d.ts.map +1 -0
  223. package/dist/presets/ui/checkbox.js +61 -0
  224. package/dist/presets/ui/checkbox.js.map +1 -0
  225. package/dist/presets/ui/custom.d.ts +1 -0
  226. package/dist/presets/ui/custom.d.ts.map +1 -0
  227. package/dist/presets/ui/custom.js +2 -0
  228. package/dist/presets/ui/custom.js.map +1 -0
  229. package/dist/presets/ui/dialog.d.ts +16 -0
  230. package/dist/presets/ui/dialog.d.ts.map +1 -0
  231. package/dist/presets/ui/dialog.js +36 -0
  232. package/dist/presets/ui/dialog.js.map +1 -0
  233. package/dist/presets/ui/field.d.ts +25 -0
  234. package/dist/presets/ui/field.d.ts.map +1 -0
  235. package/dist/presets/ui/field.js +76 -0
  236. package/dist/presets/ui/field.js.map +1 -0
  237. package/dist/presets/ui/input-mask.d.ts +34 -0
  238. package/dist/presets/ui/input-mask.d.ts.map +1 -0
  239. package/dist/presets/ui/input-mask.js +561 -0
  240. package/dist/presets/ui/input-mask.js.map +1 -0
  241. package/dist/presets/ui/input-otp.d.ts +12 -0
  242. package/dist/presets/ui/input-otp.d.ts.map +1 -0
  243. package/dist/presets/ui/input-otp.js +22 -0
  244. package/dist/presets/ui/input-otp.js.map +1 -0
  245. package/dist/presets/ui/input.d.ts +83 -0
  246. package/dist/presets/ui/input.d.ts.map +1 -0
  247. package/dist/presets/ui/input.js +436 -0
  248. package/dist/presets/ui/input.js.map +1 -0
  249. package/dist/presets/ui/label.d.ts +5 -0
  250. package/dist/presets/ui/label.d.ts.map +1 -0
  251. package/dist/presets/ui/label.js +8 -0
  252. package/dist/presets/ui/label.js.map +1 -0
  253. package/dist/presets/ui/number.d.ts +60 -0
  254. package/dist/presets/ui/number.d.ts.map +1 -0
  255. package/dist/presets/ui/number.js +1078 -0
  256. package/dist/presets/ui/number.js.map +1 -0
  257. package/dist/presets/ui/popover.d.ts +8 -0
  258. package/dist/presets/ui/popover.d.ts.map +1 -0
  259. package/dist/presets/ui/popover.js +17 -0
  260. package/dist/presets/ui/popover.js.map +1 -0
  261. package/dist/presets/ui/radio-group.d.ts +6 -0
  262. package/dist/presets/ui/radio-group.d.ts.map +1 -0
  263. package/dist/presets/ui/radio-group.js +12 -0
  264. package/dist/presets/ui/radio-group.js.map +1 -0
  265. package/dist/presets/ui/scroll-area.d.ts +6 -0
  266. package/dist/presets/ui/scroll-area.d.ts.map +1 -0
  267. package/dist/presets/ui/scroll-area.js +13 -0
  268. package/dist/presets/ui/scroll-area.js.map +1 -0
  269. package/dist/presets/ui/select.d.ts +21 -0
  270. package/dist/presets/ui/select.d.ts.map +1 -0
  271. package/dist/presets/ui/select.js +38 -0
  272. package/dist/presets/ui/select.js.map +1 -0
  273. package/dist/presets/ui/separator.d.ts +5 -0
  274. package/dist/presets/ui/separator.d.ts.map +1 -0
  275. package/dist/presets/ui/separator.js +9 -0
  276. package/dist/presets/ui/separator.js.map +1 -0
  277. package/dist/presets/ui/slider.d.ts +5 -0
  278. package/dist/presets/ui/slider.d.ts.map +1 -0
  279. package/dist/presets/ui/slider.js +14 -0
  280. package/dist/presets/ui/slider.js.map +1 -0
  281. package/dist/presets/ui/switch.d.ts +7 -0
  282. package/dist/presets/ui/switch.d.ts.map +1 -0
  283. package/dist/presets/ui/switch.js +9 -0
  284. package/dist/presets/ui/switch.js.map +1 -0
  285. package/dist/presets/ui/textarea.d.ts +76 -0
  286. package/dist/presets/ui/textarea.d.ts.map +1 -0
  287. package/dist/presets/ui/textarea.js +291 -0
  288. package/dist/presets/ui/textarea.js.map +1 -0
  289. package/dist/presets/ui/time-dropdowns.d.ts +58 -0
  290. package/dist/presets/ui/time-dropdowns.d.ts.map +1 -0
  291. package/dist/presets/ui/time-dropdowns.js +133 -0
  292. package/dist/presets/ui/time-dropdowns.js.map +1 -0
  293. package/{src/schema/adapter.ts → dist/schema/adapter.d.ts} +7 -35
  294. package/dist/schema/adapter.d.ts.map +1 -0
  295. package/dist/schema/adapter.js +3 -0
  296. package/dist/schema/adapter.js.map +1 -0
  297. package/{src/schema/core.ts → dist/schema/core.d.ts} +17 -117
  298. package/dist/schema/core.d.ts.map +1 -0
  299. package/dist/schema/core.js +4 -0
  300. package/dist/schema/core.js.map +1 -0
  301. package/dist/schema/field-map.d.ts +1 -0
  302. package/dist/schema/field-map.d.ts.map +1 -0
  303. package/dist/schema/field-map.js +2 -0
  304. package/dist/schema/field-map.js.map +1 -0
  305. package/{src/schema/field.ts → dist/schema/field.d.ts} +1 -34
  306. package/dist/schema/field.d.ts.map +1 -0
  307. package/dist/schema/field.js +4 -0
  308. package/dist/schema/field.js.map +1 -0
  309. package/dist/schema/index.d.ts +1 -0
  310. package/dist/schema/index.d.ts.map +1 -0
  311. package/dist/schema/index.js +2 -0
  312. package/dist/schema/index.js.map +1 -0
  313. package/{src/schema/input-field.ts → dist/schema/input-field.d.ts} +6 -43
  314. package/dist/schema/input-field.d.ts.map +1 -0
  315. package/dist/schema/input-field.js +3 -0
  316. package/dist/schema/input-field.js.map +1 -0
  317. package/dist/schema/presets.d.ts +1 -0
  318. package/dist/schema/presets.d.ts.map +1 -0
  319. package/dist/schema/presets.js +2 -0
  320. package/dist/schema/presets.js.map +1 -0
  321. package/{src/schema/variant.ts → dist/schema/variant.d.ts} +24 -64
  322. package/dist/schema/variant.d.ts.map +1 -0
  323. package/dist/schema/variant.js +3 -0
  324. package/dist/schema/variant.js.map +1 -0
  325. package/dist/variants/core/checkbox.d.ts +15 -0
  326. package/dist/variants/core/checkbox.d.ts.map +1 -0
  327. package/dist/variants/core/checkbox.js +27 -0
  328. package/dist/variants/core/checkbox.js.map +1 -0
  329. package/dist/variants/core/chips.d.ts +3 -0
  330. package/dist/variants/core/chips.d.ts.map +1 -0
  331. package/dist/variants/core/chips.js +20 -0
  332. package/dist/variants/core/chips.js.map +1 -0
  333. package/dist/variants/core/color.d.ts +3 -0
  334. package/dist/variants/core/color.d.ts.map +1 -0
  335. package/dist/variants/core/color.js +14 -0
  336. package/dist/variants/core/color.js.map +1 -0
  337. package/dist/variants/core/custom.d.ts +11 -0
  338. package/dist/variants/core/custom.d.ts.map +1 -0
  339. package/{src/variants/core/custom.tsx → dist/variants/core/custom.js} +15 -18
  340. package/dist/variants/core/custom.js.map +1 -0
  341. package/dist/variants/core/date.d.ts +3 -0
  342. package/dist/variants/core/date.d.ts.map +1 -0
  343. package/dist/variants/core/date.js +20 -0
  344. package/dist/variants/core/date.js.map +1 -0
  345. package/dist/variants/core/file.d.ts +3 -0
  346. package/dist/variants/core/file.d.ts.map +1 -0
  347. package/dist/variants/core/file.js +6 -0
  348. package/dist/variants/core/file.js.map +1 -0
  349. package/dist/variants/core/keyvalue.d.ts +3 -0
  350. package/dist/variants/core/keyvalue.d.ts.map +1 -0
  351. package/dist/variants/core/keyvalue.js +9 -0
  352. package/dist/variants/core/keyvalue.js.map +1 -0
  353. package/dist/variants/core/multiselect.d.ts +11 -0
  354. package/dist/variants/core/multiselect.d.ts.map +1 -0
  355. package/dist/variants/core/multiselect.js +15 -0
  356. package/dist/variants/core/multiselect.js.map +1 -0
  357. package/dist/variants/core/number.d.ts +38 -0
  358. package/dist/variants/core/number.d.ts.map +1 -0
  359. package/dist/variants/core/number.js +62 -0
  360. package/dist/variants/core/number.js.map +1 -0
  361. package/dist/variants/core/password.d.ts +11 -0
  362. package/dist/variants/core/password.d.ts.map +1 -0
  363. package/dist/variants/core/password.js +29 -0
  364. package/dist/variants/core/password.js.map +1 -0
  365. package/dist/variants/core/phone.d.ts +3 -0
  366. package/dist/variants/core/phone.d.ts.map +1 -0
  367. package/dist/variants/core/phone.js +14 -0
  368. package/dist/variants/core/phone.js.map +1 -0
  369. package/dist/variants/core/radio.d.ts +8 -0
  370. package/dist/variants/core/radio.d.ts.map +1 -0
  371. package/dist/variants/core/radio.js +34 -0
  372. package/dist/variants/core/radio.js.map +1 -0
  373. package/dist/variants/core/select.d.ts +5 -0
  374. package/dist/variants/core/select.d.ts.map +1 -0
  375. package/dist/variants/core/select.js +11 -0
  376. package/dist/variants/core/select.js.map +1 -0
  377. package/dist/variants/core/slider.d.ts +19 -0
  378. package/dist/variants/core/slider.d.ts.map +1 -0
  379. package/dist/variants/core/slider.js +36 -0
  380. package/dist/variants/core/slider.js.map +1 -0
  381. package/dist/variants/core/text.d.ts +38 -0
  382. package/dist/variants/core/text.d.ts.map +1 -0
  383. package/{src/variants/core/text.tsx → dist/variants/core/text.js} +4 -56
  384. package/dist/variants/core/text.js.map +1 -0
  385. package/dist/variants/core/textarea.d.ts +3 -0
  386. package/dist/variants/core/textarea.d.ts.map +1 -0
  387. package/dist/variants/core/textarea.js +20 -0
  388. package/dist/variants/core/textarea.js.map +1 -0
  389. package/dist/variants/core/toggle.d.ts +6 -0
  390. package/dist/variants/core/toggle.d.ts.map +1 -0
  391. package/dist/variants/core/toggle.js +41 -0
  392. package/dist/variants/core/toggle.js.map +1 -0
  393. package/dist/variants/core/treeselect.d.ts +4 -0
  394. package/dist/variants/core/treeselect.d.ts.map +1 -0
  395. package/dist/variants/core/treeselect.js +7 -0
  396. package/dist/variants/core/treeselect.js.map +1 -0
  397. package/dist/variants/helpers/selection-summary.d.ts +24 -0
  398. package/dist/variants/helpers/selection-summary.d.ts.map +1 -0
  399. package/dist/variants/helpers/selection-summary.js +105 -0
  400. package/dist/variants/helpers/selection-summary.js.map +1 -0
  401. package/dist/variants/index.d.ts +16 -0
  402. package/dist/variants/index.d.ts.map +1 -0
  403. package/{src/variants/index.ts → dist/variants/index.js} +7 -27
  404. package/dist/variants/index.js.map +1 -0
  405. package/dist/variants/registry.d.ts +19 -0
  406. package/dist/variants/registry.d.ts.map +1 -0
  407. package/dist/variants/registry.js +29 -0
  408. package/dist/variants/registry.js.map +1 -0
  409. package/dist/variants/select-shared.d.ts +1 -0
  410. package/dist/variants/select-shared.d.ts.map +1 -0
  411. package/dist/variants/select-shared.js +2 -0
  412. package/dist/variants/select-shared.js.map +1 -0
  413. package/{src/variants/shared.ts → dist/variants/shared.d.ts} +3 -22
  414. package/dist/variants/shared.d.ts.map +1 -0
  415. package/dist/variants/shared.js +3 -0
  416. package/dist/variants/shared.js.map +1 -0
  417. package/package.json +5 -5
  418. package/.scaffold-cache.json +0 -537
  419. package/src/.scaffold-cache.json +0 -544
  420. package/src/adapters/axios.ts +0 -117
  421. package/src/adapters/index.ts +0 -91
  422. package/src/adapters/inertia.ts +0 -187
  423. package/src/core/bound/observe-bound-field.ts +0 -172
  424. package/src/core/bound/wait-for-bound-field.ts +0 -57
  425. package/src/core/core-root.tsx +0 -72
  426. package/src/core/core-shell.tsx +0 -44
  427. package/src/core/errors/index.ts +0 -2
  428. package/src/core/hooks/use-button.ts +0 -220
  429. package/src/core/hooks/use-core-utility.ts +0 -0
  430. package/src/core/hooks/use-field.ts +0 -497
  431. package/src/core/hooks/use-optional-field.ts +0 -28
  432. package/src/core/index.ts +0 -0
  433. package/src/core/registry/binder-registry.ts +0 -82
  434. package/src/core/test.tsx +0 -17
  435. package/src/global.d.ts +0 -14
  436. package/src/input/input-field.tsx +0 -854
  437. package/src/input/input-layout-graph.ts +0 -230
  438. package/src/lib/get-global-countries.ts +0 -87
  439. package/src/lib/utils.ts +0 -6
  440. package/src/presets/index.ts +0 -0
  441. package/src/presets/shadcn-preset.ts +0 -0
  442. package/src/presets/shadcn-variants/checkbox.tsx +0 -849
  443. package/src/presets/shadcn-variants/chips.tsx +0 -756
  444. package/src/presets/shadcn-variants/color.tsx +0 -284
  445. package/src/presets/shadcn-variants/custom.tsx +0 -227
  446. package/src/presets/shadcn-variants/date.tsx +0 -796
  447. package/src/presets/shadcn-variants/file.tsx +0 -764
  448. package/src/presets/shadcn-variants/keyvalue.tsx +0 -556
  449. package/src/presets/shadcn-variants/multiselect.tsx +0 -1132
  450. package/src/presets/shadcn-variants/number.tsx +0 -176
  451. package/src/presets/shadcn-variants/password.tsx +0 -737
  452. package/src/presets/shadcn-variants/phone.tsx +0 -628
  453. package/src/presets/shadcn-variants/radio.tsx +0 -578
  454. package/src/presets/shadcn-variants/select.tsx +0 -956
  455. package/src/presets/shadcn-variants/slider.tsx +0 -622
  456. package/src/presets/shadcn-variants/text.tsx +0 -343
  457. package/src/presets/shadcn-variants/textarea.tsx +0 -66
  458. package/src/presets/shadcn-variants/toggle.tsx +0 -218
  459. package/src/presets/shadcn-variants/treeselect.tsx +0 -784
  460. package/src/presets/ui/badge.tsx +0 -46
  461. package/src/presets/ui/button.tsx +0 -60
  462. package/src/presets/ui/calendar.tsx +0 -214
  463. package/src/presets/ui/checkbox.tsx +0 -115
  464. package/src/presets/ui/custom.tsx +0 -0
  465. package/src/presets/ui/dialog.tsx +0 -141
  466. package/src/presets/ui/field.tsx +0 -246
  467. package/src/presets/ui/input-mask.tsx +0 -739
  468. package/src/presets/ui/input-otp.tsx +0 -77
  469. package/src/presets/ui/input.tsx +0 -1011
  470. package/src/presets/ui/label.tsx +0 -22
  471. package/src/presets/ui/number.tsx +0 -1370
  472. package/src/presets/ui/popover.tsx +0 -46
  473. package/src/presets/ui/radio-group.tsx +0 -43
  474. package/src/presets/ui/scroll-area.tsx +0 -56
  475. package/src/presets/ui/select.tsx +0 -190
  476. package/src/presets/ui/separator.tsx +0 -28
  477. package/src/presets/ui/slider.tsx +0 -61
  478. package/src/presets/ui/switch.tsx +0 -32
  479. package/src/presets/ui/textarea.tsx +0 -634
  480. package/src/presets/ui/time-dropdowns.tsx +0 -350
  481. package/src/schema/field-map.ts +0 -0
  482. package/src/schema/index.ts +0 -0
  483. package/src/schema/presets.ts +0 -0
  484. package/src/variants/core/checkbox.tsx +0 -54
  485. package/src/variants/core/chips.tsx +0 -22
  486. package/src/variants/core/color.tsx +0 -16
  487. package/src/variants/core/date.tsx +0 -25
  488. package/src/variants/core/file.tsx +0 -9
  489. package/src/variants/core/keyvalue.tsx +0 -12
  490. package/src/variants/core/multiselect.tsx +0 -28
  491. package/src/variants/core/number.tsx +0 -115
  492. package/src/variants/core/password.tsx +0 -35
  493. package/src/variants/core/phone.tsx +0 -16
  494. package/src/variants/core/radio.tsx +0 -38
  495. package/src/variants/core/select.tsx +0 -15
  496. package/src/variants/core/slider.tsx +0 -55
  497. package/src/variants/core/textarea.tsx +0 -22
  498. package/src/variants/core/toggle.tsx +0 -50
  499. package/src/variants/core/treeselect.tsx +0 -11
  500. package/src/variants/helpers/selection-summary.tsx +0 -236
  501. package/src/variants/registry.ts +0 -38
  502. package/src/variants/select-shared.ts +0 -0
  503. package/tsconfig.json +0 -14
@@ -1,1132 +0,0 @@
1
- // src/presets/shadcn-variants/multi-select.tsx
2
-
3
- import * as React from "react";
4
- import type { VariantBaseProps, ChangeDetail } from "@/variants/shared";
5
- import { cn } from "@/lib/utils";
6
- import { Input } from "@/presets/ui/input";
7
- import { Checkbox } from "@/presets/ui/checkbox";
8
- import {
9
- Popover,
10
- PopoverTrigger,
11
- PopoverContent,
12
- } from "@/presets/ui/popover";
13
- import { ChevronDown, Search, X } from "lucide-react";
14
- import { removeSelectValue, SelectionSummary } from "@/variants/helpers/selection-summary";
15
-
16
- type SelectPrimitive = string | number;
17
-
18
- type Size = "sm" | "md" | "lg";
19
- type Density = "compact" | "comfortable" | "loose";
20
-
21
- export type MultiSelectOption =
22
- | SelectPrimitive
23
- | {
24
- label?: React.ReactNode;
25
- value?: SelectPrimitive;
26
- description?: React.ReactNode;
27
- disabled?: boolean;
28
- icon?: React.ReactNode;
29
- [key: string]: any;
30
- };
31
-
32
- type NormalizedMultiItem = {
33
- key: string;
34
- value: SelectPrimitive;
35
- labelNode: React.ReactNode;
36
- labelText: string;
37
- description?: React.ReactNode;
38
- disabled?: boolean;
39
- icon?: React.ReactNode;
40
- raw: MultiSelectOption;
41
- };
42
-
43
- export interface ShadcnMultiSelectVariantProps
44
- extends Pick<
45
- VariantBaseProps<SelectPrimitive[] | undefined>,
46
- | "value"
47
- | "onValue"
48
- | "error"
49
- | "disabled"
50
- | "readOnly"
51
- | "size"
52
- | "density"
53
- > {
54
- /**
55
- * Options for the multi-select.
56
- *
57
- * You can pass:
58
- * - primitives: ["ng", "gh", "ke"]
59
- * - objects: [{ label, value, ...extra }]
60
- */
61
- options?: MultiSelectOption[];
62
-
63
- /**
64
- * Automatically capitalise the first letter of the label
65
- * (when the resolved label is a string).
66
- */
67
- autoCap?: boolean;
68
-
69
- /**
70
- * How to read the label from each option.
71
- *
72
- * - string → key on the option object
73
- * - function → custom mapper
74
- * - omitted → tries `label`, else String(value)
75
- */
76
- optionLabel?: string | ((item: MultiSelectOption) => React.ReactNode);
77
-
78
- /**
79
- * How to read the value from each option.
80
- *
81
- * - string → key on the option object
82
- * - function → custom mapper
83
- * - omitted → uses `value`, or `id`, or `key`, or index
84
- */
85
- optionValue?: string | ((item: MultiSelectOption) => SelectPrimitive);
86
-
87
- /**
88
- * Optional description line under the label.
89
- */
90
- optionDescription?: string | ((item: MultiSelectOption) => React.ReactNode);
91
-
92
- /**
93
- * How to determine if an option is disabled.
94
- */
95
- optionDisabled?: string | ((item: MultiSelectOption) => boolean);
96
-
97
- /**
98
- * How to extract an icon for each option.
99
- *
100
- * - string → key on the option object (default "icon")
101
- * - function → custom mapper
102
- */
103
- optionIcon?: string | ((item: MultiSelectOption) => React.ReactNode);
104
-
105
- /**
106
- * How to compute the React key for each option.
107
- */
108
- optionKey?: string | ((item: MultiSelectOption, index: number) => React.Key);
109
-
110
- /**
111
- * Enable inline search inside the dropdown.
112
- */
113
- searchable?: boolean;
114
-
115
- /**
116
- * Placeholder for the search input.
117
- */
118
- searchPlaceholder?: string;
119
-
120
- /**
121
- * Text to show when search yields no results.
122
- */
123
- emptySearchText?: React.ReactNode;
124
-
125
- /**
126
- * Placeholder when nothing is selected.
127
- */
128
- placeholder?: React.ReactNode;
129
-
130
- /**
131
- * Show a small clear button in the trigger when any value is selected.
132
- */
133
- clearable?: boolean;
134
-
135
- /**
136
- * Whether to show a "Select all" row.
137
- */
138
- showSelectAll?: boolean;
139
-
140
- /**
141
- * Label for the "Select all" row.
142
- * Default: "Select all".
143
- */
144
- selectAllLabel?: React.ReactNode;
145
-
146
- /**
147
- * Where to place the "Select all" row.
148
- * Default: "top".
149
- */
150
- selectAllPosition?: "top" | "bottom";
151
-
152
- /**
153
- * Custom renderer for each option row (checkbox + label).
154
- */
155
- renderOption?: (ctx: {
156
- item: NormalizedMultiItem;
157
- selected: boolean;
158
- index: number;
159
- option: React.ReactNode; // prebuilt row you can wrap
160
- }) => React.ReactNode;
161
-
162
- /**
163
- * Custom renderer for the trigger summary.
164
- */
165
- renderValue?: (ctx: {
166
- selectedItems: NormalizedMultiItem[];
167
- placeholder?: React.ReactNode;
168
- }) => React.ReactNode;
169
-
170
- /**
171
- * Custom renderer for the checkbox.
172
- *
173
- * - item: the option item (or null for "select all")
174
- * - selected: whether this row is currently fully selected
175
- * - indeterminate: partially selected (used for "select all")
176
- * - isSelectAll: true for the "select all" row
177
- */
178
- renderCheckbox?: (ctx: {
179
- item: NormalizedMultiItem | null;
180
- selected: boolean;
181
- indeterminate: boolean;
182
- isSelectAll: boolean;
183
- }) => React.ReactNode;
184
-
185
- /**
186
- * Max height (in px) for the dropdown list before scrolling.
187
- * Default: 260.
188
- */
189
- maxListHeight?: number;
190
-
191
- /**
192
- * Wrapper class for the whole variant.
193
- */
194
- className?: string;
195
-
196
- /**
197
- * Extra classes for the trigger button.
198
- */
199
- triggerClassName?: string;
200
-
201
- /**
202
- * Extra classes for the popover content.
203
- */
204
- contentClassName?: string;
205
-
206
- // ─────────────────────────────────────────────
207
- // Icons & controls (parity with single select)
208
- // ─────────────────────────────────────────────
209
-
210
- /**
211
- * One or more icons displayed inside the trigger, on the left.
212
- *
213
- * If not provided and `icon` is set, that single icon
214
- * is treated as `leadingIcons[0]`.
215
- */
216
- leadingIcons?: React.ReactNode[];
217
-
218
- /**
219
- * Icons displayed on the right side of the trigger,
220
- * near the clear button / chevron area.
221
- */
222
- trailingIcons?: React.ReactNode[];
223
-
224
- /**
225
- * Convenience single-icon prop for the left side.
226
- */
227
- icon?: React.ReactNode;
228
-
229
- /**
230
- * Base gap between icons and text.
231
- * Defaults to 4px-ish via `gap-1`.
232
- */
233
- iconGap?: number;
234
-
235
- /**
236
- * Extra spacing to apply between leading icons and the text.
237
- */
238
- leadingIconSpacing?: number;
239
-
240
- /**
241
- * Extra spacing to apply between trailing icons and the clear button.
242
- */
243
- trailingIconSpacing?: number;
244
-
245
- /**
246
- * Arbitrary React node rendered before the select (e.g. a button).
247
- */
248
- leadingControl?: React.ReactNode;
249
-
250
- /**
251
- * Arbitrary React node rendered after the select (e.g. a button).
252
- */
253
- trailingControl?: React.ReactNode;
254
-
255
- /**
256
- * Extra classes for the leading control wrapper.
257
- */
258
- leadingControlClassName?: string;
259
-
260
- /**
261
- * Extra classes for the trailing control wrapper.
262
- */
263
- trailingControlClassName?: string;
264
-
265
- /**
266
- * If true and there are controls, the select trigger + controls share
267
- * a single visual box (borders, radius, focus states).
268
- */
269
- joinControls?: boolean;
270
-
271
- /**
272
- * When joinControls is true, whether the box styling extends over controls
273
- * (true) or controls are visually separate (false).
274
- */
275
- extendBoxToControls?: boolean;
276
- }
277
-
278
- // ─────────────────────────────────────────────
279
- // Helpers
280
- // ─────────────────────────────────────────────
281
-
282
- function capitalizeFirst(label: string): string {
283
- if (!label) return label;
284
- return label.charAt(0).toUpperCase() + label.slice(1);
285
- }
286
-
287
- function normalizeOptions(
288
- opts: readonly MultiSelectOption[] | undefined,
289
- config: Pick<
290
- ShadcnMultiSelectVariantProps,
291
- | "autoCap"
292
- | "optionLabel"
293
- | "optionValue"
294
- | "optionDescription"
295
- | "optionDisabled"
296
- | "optionKey"
297
- | "optionIcon"
298
- >
299
- ): NormalizedMultiItem[] {
300
- if (!opts || !opts.length) return [];
301
-
302
- return opts.map((raw, index) => {
303
- const asObj: any =
304
- typeof raw === "string" || typeof raw === "number"
305
- ? { label: String(raw), value: raw }
306
- : raw;
307
-
308
- const value: SelectPrimitive =
309
- typeof config.optionValue === "function"
310
- ? config.optionValue(raw)
311
- : typeof config.optionValue === "string"
312
- ? (asObj[config.optionValue] as SelectPrimitive)
313
- : (asObj.value ??
314
- asObj.id ??
315
- asObj.key ??
316
- String(index));
317
-
318
- let labelNode: React.ReactNode =
319
- typeof config.optionLabel === "function"
320
- ? config.optionLabel(raw)
321
- : typeof config.optionLabel === "string"
322
- ? asObj[config.optionLabel] ?? asObj.label ?? String(value)
323
- : asObj.label ?? String(value);
324
-
325
- if (config.autoCap && typeof labelNode === "string") {
326
- labelNode = capitalizeFirst(labelNode);
327
- }
328
-
329
- const labelText =
330
- typeof labelNode === "string"
331
- ? labelNode
332
- : typeof labelNode === "number"
333
- ? String(labelNode)
334
- : asObj.labelText ?? String(value);
335
-
336
- const description: React.ReactNode =
337
- typeof config.optionDescription === "function"
338
- ? config.optionDescription(raw)
339
- : typeof config.optionDescription === "string"
340
- ? asObj[config.optionDescription]
341
- : asObj.description;
342
-
343
- const disabled: boolean =
344
- typeof config.optionDisabled === "function"
345
- ? config.optionDisabled(raw)
346
- : typeof config.optionDisabled === "string"
347
- ? !!asObj[config.optionDisabled]
348
- : !!asObj.disabled;
349
-
350
- const icon: React.ReactNode =
351
- typeof config.optionIcon === "function"
352
- ? config.optionIcon(raw)
353
- : typeof config.optionIcon === "string"
354
- ? asObj[config.optionIcon]
355
- : asObj.icon;
356
-
357
- const key: React.Key =
358
- typeof config.optionKey === "function"
359
- ? config.optionKey(raw, index)
360
- : typeof config.optionKey === "string"
361
- ? asObj[config.optionKey] ?? value ?? index
362
- : asObj.key ?? value ?? index;
363
-
364
- return {
365
- key: String(key),
366
- value,
367
- labelNode,
368
- labelText,
369
- description,
370
- disabled,
371
- icon,
372
- raw,
373
- };
374
- });
375
- }
376
-
377
- function triggerHeight(size?: Size) {
378
- switch (size) {
379
- case "sm":
380
- return "h-8 text-xs";
381
- case "lg":
382
- return "h-11 text-base";
383
- default:
384
- return "h-9 text-sm";
385
- }
386
- }
387
-
388
- function triggerPadding(density?: Density) {
389
- switch (density) {
390
- case "compact":
391
- return "py-1";
392
- case "loose":
393
- return "py-2";
394
- case "comfortable":
395
- default:
396
- return "py-1.5";
397
- }
398
- }
399
-
400
- function summarizeSelection(
401
- selectedItems: NormalizedMultiItem[],
402
- placeholder?: React.ReactNode
403
- ): React.ReactNode {
404
- if (!selectedItems.length) {
405
- return (
406
- <span className="truncate text-muted-foreground">
407
- {placeholder ?? "Select options…"}
408
- </span>
409
- );
410
- }
411
-
412
- if (selectedItems.length === 1) {
413
- return (
414
- <span className="truncate">
415
- {selectedItems[0].labelNode}
416
- </span>
417
- );
418
- }
419
-
420
- if (selectedItems.length === 2) {
421
- return (
422
- <span className="truncate">
423
- {selectedItems[0].labelNode}
424
- {", "}
425
- {selectedItems[1].labelNode}
426
- </span>
427
- );
428
- }
429
-
430
- const first = selectedItems[0];
431
- const restCount = selectedItems.length - 1;
432
-
433
- return (
434
- <span className="truncate">
435
- {first.labelNode}
436
- {", "}
437
- <span className="text-muted-foreground">
438
- +{restCount} more
439
- </span>
440
- </span>
441
- );
442
- }
443
-
444
- // ─────────────────────────────────────────────
445
- // Component
446
- // ─────────────────────────────────────────────
447
-
448
- export const ShadcnMultiSelectVariant = React.forwardRef<
449
- HTMLButtonElement,
450
- ShadcnMultiSelectVariantProps
451
- >(function ShadcnMultiSelectVariant(props, _ref) {
452
- const {
453
- value,
454
- onValue,
455
- error,
456
- disabled,
457
- readOnly,
458
- size,
459
- density,
460
-
461
- options,
462
-
463
- autoCap,
464
- optionLabel,
465
- optionValue,
466
- optionDescription,
467
- optionDisabled,
468
- optionIcon,
469
- optionKey,
470
-
471
- searchable,
472
- searchPlaceholder,
473
- emptySearchText,
474
-
475
- placeholder,
476
- clearable,
477
-
478
- showSelectAll,
479
- selectAllLabel,
480
- selectAllPosition = "top",
481
-
482
- renderOption,
483
- renderValue,
484
- renderCheckbox,
485
-
486
- maxListHeight = 260,
487
-
488
- className,
489
- triggerClassName,
490
- contentClassName,
491
-
492
- // Icons & controls
493
- leadingIcons,
494
- trailingIcons,
495
- icon,
496
- iconGap,
497
- leadingIconSpacing,
498
- trailingIconSpacing,
499
- leadingControl,
500
- trailingControl,
501
- leadingControlClassName,
502
- trailingControlClassName,
503
- joinControls = true,
504
- extendBoxToControls = true,
505
- } = props;
506
-
507
- const [open, setOpen] = React.useState(false);
508
- const [query, setQuery] = React.useState("");
509
-
510
- const items = React.useMemo(
511
- () =>
512
- normalizeOptions(options ?? [], {
513
- autoCap,
514
- optionLabel,
515
- optionValue,
516
- optionDescription,
517
- optionDisabled,
518
- optionKey,
519
- optionIcon,
520
- }),
521
- [
522
- options,
523
- autoCap,
524
- optionLabel,
525
- optionValue,
526
- optionDescription,
527
- optionDisabled,
528
- optionKey,
529
- optionIcon,
530
- ]
531
- );
532
-
533
- const selectedValues = React.useMemo(
534
- () => new Set<SelectPrimitive>((value ?? []) as SelectPrimitive[]),
535
- [value]
536
- );
537
-
538
- const selectedItems = React.useMemo(
539
- () => items.filter((it) => selectedValues.has(it.value)),
540
- [items, selectedValues]
541
- );
542
-
543
- const filteredItems = React.useMemo(() => {
544
- if (!query) return items;
545
- const q = query.toLowerCase();
546
- return items.filter((it) =>
547
- it.labelText.toLowerCase().includes(q)
548
- );
549
- }, [items, query]);
550
-
551
- const selectableItems = React.useMemo(
552
- () => items.filter((it) => !it.disabled),
553
- [items]
554
- );
555
-
556
- const allSelectableValues = React.useMemo(
557
- () => new Set<SelectPrimitive>(selectableItems.map((it) => it.value)),
558
- [selectableItems]
559
- );
560
-
561
- const allSelected =
562
- selectableItems.length > 0 &&
563
- selectableItems.every((it) => selectedValues.has(it.value));
564
-
565
- const someSelected =
566
- selectableItems.length > 0 &&
567
- !allSelected &&
568
- selectableItems.some((it) => selectedValues.has(it.value));
569
-
570
- const heightCls = triggerHeight(size as Size | undefined);
571
- const padCls = triggerPadding(density as Density | undefined);
572
-
573
- const showClear = clearable && (value?.length ?? 0) > 0;
574
-
575
- const disabledTrigger = disabled || readOnly;
576
-
577
- const handleToggleValue = React.useCallback(
578
- (primitive: SelectPrimitive) => {
579
- if (!onValue || disabled || readOnly) return;
580
-
581
- const current = (value ?? []) as SelectPrimitive[];
582
- const isSelected = current.some((v) => v === primitive);
583
-
584
- let next: SelectPrimitive[];
585
- if (isSelected) {
586
- next = current.filter((v) => v !== primitive);
587
- } else {
588
- next = [...current, primitive];
589
- }
590
-
591
- const final = next.length ? next : undefined;
592
-
593
- const detail: ChangeDetail = {
594
- source: "variant",
595
- raw: {
596
- type: "toggle",
597
- value: primitive,
598
- next: final,
599
- },
600
- nativeEvent: undefined,
601
- meta: undefined,
602
- };
603
-
604
- onValue(final as any, detail);
605
- },
606
- [onValue, value, disabled, readOnly]
607
- );
608
-
609
- const handleSelectAll = React.useCallback(() => {
610
- if (!onValue || disabled || readOnly) return;
611
-
612
- const current = (value ?? []) as SelectPrimitive[];
613
-
614
- const allSelectableArr = Array.from(allSelectableValues);
615
-
616
- const currentlyAllSelected =
617
- allSelectableArr.length > 0 &&
618
- allSelectableArr.every((v) => selectedValues.has(v));
619
-
620
- let next: SelectPrimitive[];
621
-
622
- if (currentlyAllSelected) {
623
- // unselect all selectable ones, keep others (if any)
624
- next = current.filter((v) => !allSelectableValues.has(v));
625
- } else {
626
- // union of existing + all selectable
627
- const merged = new Set<SelectPrimitive>(current);
628
- for (const v of allSelectableArr) merged.add(v);
629
- next = Array.from(merged);
630
- }
631
-
632
- const final = next.length ? next : undefined;
633
-
634
- const detail: ChangeDetail = {
635
- source: "variant",
636
- raw: {
637
- type: "select-all",
638
- next: final,
639
- },
640
- nativeEvent: undefined,
641
- meta: {
642
- allSelected: !currentlyAllSelected,
643
- },
644
- };
645
-
646
- onValue(final as any, detail);
647
- }, [
648
- onValue,
649
- value,
650
- disabled,
651
- readOnly,
652
- allSelectableValues,
653
- selectedValues,
654
- ]);
655
-
656
- const handleClearAll = React.useCallback(() => {
657
- if (!onValue || disabled || readOnly) return;
658
-
659
- const detail: ChangeDetail = {
660
- source: "variant",
661
- raw: {
662
- type: "clear",
663
- },
664
- nativeEvent: undefined,
665
- meta: undefined,
666
- };
667
-
668
- onValue(undefined as any, detail);
669
- }, [onValue, disabled, readOnly]);
670
-
671
- const triggerSummary = renderValue
672
- ? renderValue({ selectedItems, placeholder })
673
- : (
674
- <SelectionSummary
675
- selectedItems={selectedItems}
676
- placeholder={placeholder}
677
- onRemoveValue={(item) => {
678
- // whatever you already do to unselect a single value
679
- // e.g. toggleValue(value) if it adds/removes from the set
680
- // toggleValue(value);
681
-
682
-
683
- const updated = removeSelectValue(
684
- selectedValues as unknown as SelectPrimitive[],
685
- item.value
686
- );
687
-
688
- const detail: ChangeDetail = {
689
- source: "variant",
690
- raw: item,
691
- nativeEvent: undefined,
692
- meta: { action: "remove", removed: value },
693
- };
694
-
695
- onValue?.(updated, detail);
696
- }}
697
- />
698
- );
699
-
700
- // ─────────────────────────────────────────────
701
- // Icons setup (same semantics as select variant)
702
- // ─────────────────────────────────────────────
703
-
704
- const resolvedLeadingIcons: React.ReactNode[] = (() => {
705
- if (leadingIcons && leadingIcons.length) return leadingIcons;
706
- if (icon) return [icon];
707
- return [];
708
- })();
709
-
710
- const resolvedTrailingIcons: React.ReactNode[] = trailingIcons ?? [];
711
-
712
- const baseIconGap = iconGap ?? 4;
713
- const leadingGap = leadingIconSpacing ?? baseIconGap;
714
- const trailingGap = trailingIconSpacing ?? baseIconGap;
715
-
716
- const hasLeadingIcons = resolvedLeadingIcons.length > 0;
717
- const hasTrailingIcons = resolvedTrailingIcons.length > 0;
718
-
719
- const hasLeadingControl = !!leadingControl;
720
- const hasTrailingControl = !!trailingControl;
721
- const hasControls = hasLeadingControl || hasTrailingControl;
722
-
723
- const makeCheckboxNode = React.useCallback(
724
- (opts: {
725
- item: NormalizedMultiItem | null;
726
- selected: boolean;
727
- indeterminate: boolean;
728
- isSelectAll: boolean;
729
- }) => {
730
- if (renderCheckbox) {
731
- return renderCheckbox(opts);
732
- }
733
-
734
- return (
735
- <Checkbox
736
- className="mr-2 mt-0.5"
737
- checked={
738
- opts.indeterminate
739
- ? "none"
740
- : opts.selected
741
- }
742
- aria-hidden="true"
743
- // purely visual; click handled on row button
744
- onCheckedChange={() => { }}
745
- />
746
- );
747
- },
748
- [renderCheckbox]
749
- );
750
-
751
- const baseBoxClasses = cn(
752
- "border-input w-full min-w-0 rounded-md border bg-transparent shadow-xs",
753
- "transition-[color,box-shadow] outline-none",
754
- "focus-within:border-ring focus-within:ring-ring/50 focus-within:ring-[3px]",
755
- "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
756
- );
757
-
758
- // Trigger button body (icons + summary + clear + trailing icons + chevron)
759
- const triggerButton = (
760
- <button
761
- ref={_ref}
762
- type="button"
763
- disabled={disabledTrigger}
764
- className={cn(
765
- "flex w-full items-center justify-between rounded-md border border-input bg-background px-3 text-left shadow-xs",
766
- "focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:border-ring",
767
- "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
768
- heightCls,
769
- padCls,
770
- hasControls &&
771
- joinControls &&
772
- extendBoxToControls &&
773
- "border-none shadow-none focus-visible:ring-0 focus-visible:outline-none",
774
- triggerClassName
775
- )}
776
- >
777
- <div className="flex w-full items-center justify-between gap-2">
778
- {/* Left side: leading icons + summary */}
779
- <div className="flex min-w-0 items-center grow gap-2">
780
- {hasLeadingIcons && (
781
- <span
782
- className="flex items-center gap-1 shrink-0"
783
- style={{ columnGap: leadingGap }}
784
- data-slot="leading-icons"
785
- >
786
- {resolvedLeadingIcons.map((node, idx) => (
787
- <span
788
- key={idx}
789
- className="flex items-center justify-center"
790
- >
791
- {node}
792
- </span>
793
- ))}
794
- </span>
795
- )}
796
-
797
- <div className="min-w-0 flex-1">
798
- {triggerSummary}
799
- </div>
800
- </div>
801
-
802
- {/* Right side: clear + trailing icons + chevron */}
803
- <div className="flex items-center gap-1 shrink-0">
804
- {showClear && (
805
- <button
806
- type="button"
807
- aria-label="Clear selection"
808
- onClick={(e) => {
809
- e.stopPropagation();
810
- e.preventDefault();
811
- handleClearAll();
812
- }}
813
- className="flex h-4 w-4 items-center justify-center rounded hover:bg-muted"
814
- data-slot="clear"
815
- >
816
- <X className="h-3 w-3 pointer-events-none" />
817
- </button>
818
- )}
819
-
820
- {hasTrailingIcons && (
821
- <span
822
- className="flex items-center gap-1"
823
- style={{ columnGap: trailingGap }}
824
- data-slot="trailing-icons"
825
- >
826
- {resolvedTrailingIcons.map((node, idx) => (
827
- <span
828
- key={idx}
829
- className="flex items-center justify-center"
830
- >
831
- {node}
832
- </span>
833
- ))}
834
- </span>
835
- )}
836
-
837
- <ChevronDown className="h-4 w-4 text-muted-foreground" />
838
- </div>
839
- </div>
840
- </button>
841
- );
842
-
843
- // Core multi-select element (Popover + list)
844
- const MultiSelectCore = (
845
- <Popover
846
- open={open && !disabledTrigger}
847
- onOpenChange={(next) => {
848
- if (disabledTrigger) return;
849
- setOpen(next);
850
- if (!next) setQuery("");
851
- }}
852
- >
853
- <PopoverTrigger asChild>
854
- {triggerButton}
855
- </PopoverTrigger>
856
-
857
- <PopoverContent
858
- className={cn(
859
- "w-(--radix-popover-trigger-width) p-0",
860
- contentClassName
861
- )}
862
- align="start"
863
- >
864
- {/* Search bar */}
865
- {searchable && (
866
- <div className="p-2 border-b border-border">
867
- <Input
868
- autoFocus
869
- icon={<Search className="size-4" />}
870
- value={query}
871
- onChange={(e) => setQuery(e.target.value)}
872
- placeholder={
873
- searchPlaceholder ?? "Search options…"
874
- }
875
- size={size}
876
- density={density}
877
- />
878
- </div>
879
- )}
880
-
881
- <div
882
- className="py-1 overflow-auto"
883
- style={{ maxHeight: maxListHeight }}
884
- >
885
- {/* Optional "Select all" at top */}
886
- {showSelectAll &&
887
- selectAllPosition === "top" && (
888
- <button
889
- type="button"
890
- className={cn(
891
- "flex w-full items-center px-2 py-1.5 text-sm",
892
- "hover:bg-muted/70",
893
- "disabled:cursor-not-allowed disabled:opacity-50"
894
- )}
895
- onClick={handleSelectAll}
896
- >
897
- {makeCheckboxNode({
898
- item: null,
899
- selected: allSelected,
900
- indeterminate: someSelected,
901
- isSelectAll: true,
902
- })}
903
- <span className="truncate">
904
- {selectAllLabel ?? "Select all"}
905
- </span>
906
- </button>
907
- )}
908
-
909
- {/* Options */}
910
- {filteredItems.length === 0 ? (
911
- <div className="px-2 py-1.5 text-xs text-muted-foreground">
912
- {emptySearchText ?? "No results found"}
913
- </div>
914
- ) : (
915
- filteredItems.map((item, index) => {
916
- const selected = selectedValues.has(
917
- item.value
918
- );
919
-
920
- const row = (
921
- <button
922
- key={item.key}
923
- type="button"
924
- className={cn(
925
- "flex w-full items-start gap-2 px-2 py-1.5 text-sm",
926
- "hover:bg-muted/70",
927
- item.disabled &&
928
- "opacity-50 cursor-not-allowed"
929
- )}
930
- onClick={() => {
931
- if (item.disabled) return;
932
- handleToggleValue(item.value);
933
- }}
934
- >
935
- {makeCheckboxNode({
936
- item,
937
- selected,
938
- indeterminate: false,
939
- isSelectAll: false,
940
- })}
941
-
942
- <div className="flex flex-1 items-start gap-2">
943
- {item.icon && (
944
- <span className="mt-0.5 shrink-0">
945
- {item.icon}
946
- </span>
947
- )}
948
- <div className="flex flex-col">
949
- <span>{item.labelNode}</span>
950
- {item.description && (
951
- <span className="text-xs text-muted-foreground">
952
- {item.description}
953
- </span>
954
- )}
955
- </div>
956
- </div>
957
- </button>
958
- );
959
-
960
- if (!renderOption) return row;
961
-
962
- return renderOption({
963
- item,
964
- selected,
965
- index,
966
- option: row,
967
- });
968
- })
969
- )}
970
-
971
- {/* Optional "Select all" at bottom */}
972
- {showSelectAll &&
973
- selectAllPosition === "bottom" && (
974
- <button
975
- type="button"
976
- className={cn(
977
- "mt-1 flex w-full items-center px-2 py-1.5 text-sm border-t border-border",
978
- "hover:bg-muted/70",
979
- "disabled:cursor-not-allowed disabled:opacity-50"
980
- )}
981
- onClick={handleSelectAll}
982
- >
983
- {makeCheckboxNode({
984
- item: null,
985
- selected: allSelected,
986
- indeterminate: someSelected,
987
- isSelectAll: true,
988
- })}
989
- <span className="truncate">
990
- {selectAllLabel ?? "Select all"}
991
- </span>
992
- </button>
993
- )}
994
- </div>
995
- </PopoverContent>
996
- </Popover>
997
- );
998
-
999
- // ─────────────────────────────────────────────
1000
- // Layout modes (mirroring select variant)
1001
- // ─────────────────────────────────────────────
1002
-
1003
- // CASE 1: no controls → just the multi-select
1004
- if (!hasControls) {
1005
- return (
1006
- <div
1007
- data-slot="select-field"
1008
- data-multi="true"
1009
- className={cn(
1010
- "w-full",
1011
- disabled && "opacity-50 cursor-not-allowed",
1012
- className
1013
- )}
1014
- aria-disabled={disabled || undefined}
1015
- aria-invalid={error ? "true" : undefined}
1016
- >
1017
- {MultiSelectCore}
1018
- </div>
1019
- );
1020
- }
1021
-
1022
- // CASE 2: controls + joinControls → shared single box
1023
- if (joinControls) {
1024
- const groupClassName = cn(
1025
- "flex items-stretch w-full",
1026
- extendBoxToControls &&
1027
- cn(
1028
- "relative",
1029
- baseBoxClasses // ring via :focus-within
1030
- ),
1031
- !extendBoxToControls &&
1032
- "relative border-none shadow-none bg-transparent",
1033
- className
1034
- );
1035
-
1036
- return (
1037
- <div
1038
- data-slot="select-field"
1039
- data-multi="true"
1040
- className="w-full"
1041
- aria-disabled={disabled || undefined}
1042
- aria-invalid={error ? "true" : undefined}
1043
- >
1044
- <div
1045
- className={groupClassName}
1046
- data-slot="select-group"
1047
- data-disabled={disabled ? "true" : "false"}
1048
- >
1049
- {hasLeadingControl && (
1050
- <div
1051
- className={cn(
1052
- "flex items-center px-2",
1053
- leadingControlClassName
1054
- )}
1055
- data-slot="leading-control"
1056
- >
1057
- {leadingControl}
1058
- </div>
1059
- )}
1060
-
1061
- <div
1062
- className={cn(
1063
- "flex-1 min-w-0 flex items-stretch"
1064
- )}
1065
- data-slot="select-region"
1066
- >
1067
- {MultiSelectCore}
1068
- </div>
1069
-
1070
- {hasTrailingControl && (
1071
- <div
1072
- className={cn(
1073
- "flex items-center px-2",
1074
- trailingControlClassName
1075
- )}
1076
- data-slot="trailing-control"
1077
- >
1078
- {trailingControl}
1079
- </div>
1080
- )}
1081
- </div>
1082
- </div>
1083
- );
1084
- }
1085
-
1086
- // CASE 3: controls present, but separate (no joined box)
1087
- return (
1088
- <div
1089
- data-slot="select-field"
1090
- data-multi="true"
1091
- className={cn(
1092
- "flex items-stretch w-full",
1093
- disabled && "opacity-50 cursor-not-allowed",
1094
- className
1095
- )}
1096
- aria-disabled={disabled || undefined}
1097
- aria-invalid={error ? "true" : undefined}
1098
- >
1099
- {hasLeadingControl && (
1100
- <div
1101
- className={cn(
1102
- "flex items-center mr-1",
1103
- leadingControlClassName
1104
- )}
1105
- data-slot="leading-control"
1106
- >
1107
- {leadingControl}
1108
- </div>
1109
- )}
1110
-
1111
- <div className="flex-1 min-w-0" data-slot="select-region">
1112
- {MultiSelectCore}
1113
- </div>
1114
-
1115
- {hasTrailingControl && (
1116
- <div
1117
- className={cn(
1118
- "flex items-center ml-1",
1119
- trailingControlClassName
1120
- )}
1121
- data-slot="trailing-control"
1122
- >
1123
- {trailingControl}
1124
- </div>
1125
- )}
1126
- </div>
1127
- );
1128
- });
1129
-
1130
- ShadcnMultiSelectVariant.displayName = "ShadcnMultiSelectVariant";
1131
-
1132
- export default ShadcnMultiSelectVariant;