@nuxt/ui 3.0.0-alpha.8 → 3.0.0-beta.1

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 (310) hide show
  1. package/.nuxt/ui/accordion.ts +2 -2
  2. package/.nuxt/ui/alert.ts +122 -95
  3. package/.nuxt/ui/avatar-group.ts +14 -2
  4. package/.nuxt/ui/avatar.ts +16 -4
  5. package/.nuxt/ui/badge.ts +139 -93
  6. package/.nuxt/ui/breadcrumb.ts +5 -5
  7. package/.nuxt/ui/button-group.ts +13 -0
  8. package/.nuxt/ui/button.ts +167 -136
  9. package/.nuxt/ui/calendar.ts +103 -0
  10. package/.nuxt/ui/card.ts +27 -1
  11. package/.nuxt/ui/carousel.ts +9 -7
  12. package/.nuxt/ui/checkbox.ts +45 -27
  13. package/.nuxt/ui/chip.ts +44 -15
  14. package/.nuxt/ui/color-picker.ts +47 -0
  15. package/.nuxt/ui/command-palette.ts +28 -18
  16. package/.nuxt/ui/container.ts +1 -1
  17. package/.nuxt/ui/context-menu.ts +64 -46
  18. package/.nuxt/ui/drawer.ts +83 -15
  19. package/.nuxt/ui/dropdown-menu.ts +65 -47
  20. package/.nuxt/ui/form-field.ts +15 -7
  21. package/.nuxt/ui/index.ts +7 -1
  22. package/.nuxt/ui/input-menu.ts +150 -116
  23. package/.nuxt/ui/input-number.ts +235 -0
  24. package/.nuxt/ui/input.ts +111 -76
  25. package/.nuxt/ui/kbd.ts +18 -6
  26. package/.nuxt/ui/link.ts +3 -3
  27. package/.nuxt/ui/modal.ts +8 -7
  28. package/.nuxt/ui/navigation-menu.ts +244 -131
  29. package/.nuxt/ui/pin-input.ts +171 -0
  30. package/.nuxt/ui/popover.ts +2 -2
  31. package/.nuxt/ui/progress.ts +111 -72
  32. package/.nuxt/ui/radio-group.ts +45 -22
  33. package/.nuxt/ui/select-menu.ts +127 -96
  34. package/.nuxt/ui/select.ts +120 -84
  35. package/.nuxt/ui/separator.ts +60 -31
  36. package/.nuxt/ui/skeleton.ts +1 -1
  37. package/.nuxt/ui/slideover.ts +17 -9
  38. package/.nuxt/ui/slider.ts +61 -38
  39. package/.nuxt/ui/stepper.ts +202 -0
  40. package/.nuxt/ui/switch.ts +40 -22
  41. package/.nuxt/ui/table.ts +49 -31
  42. package/.nuxt/ui/tabs.ts +101 -73
  43. package/.nuxt/ui/textarea.ts +111 -76
  44. package/.nuxt/ui/toast.ts +53 -33
  45. package/.nuxt/ui/toaster.ts +31 -15
  46. package/.nuxt/ui/tooltip.ts +2 -2
  47. package/.nuxt/ui/tree.ts +154 -0
  48. package/.nuxt/ui.css +92 -0
  49. package/README.md +69 -18
  50. package/cli/commands/{init.mjs → make/component.mjs} +16 -4
  51. package/cli/commands/make/index.mjs +14 -0
  52. package/cli/commands/make/locale.mjs +64 -0
  53. package/cli/index.mjs +2 -2
  54. package/cli/package.json +2 -2
  55. package/cli/templates.mjs +62 -12
  56. package/cli/utils.mjs +14 -0
  57. package/dist/module.cjs +9 -170
  58. package/dist/module.d.cts +5 -15
  59. package/dist/module.d.mts +5 -15
  60. package/dist/module.d.ts +5 -15
  61. package/dist/module.json +2 -2
  62. package/dist/module.mjs +12 -167
  63. package/dist/runtime/components/Accordion.vue +8 -39
  64. package/dist/runtime/components/Alert.vue +25 -21
  65. package/dist/runtime/components/App.vue +15 -15
  66. package/dist/runtime/components/Avatar.vue +33 -21
  67. package/dist/runtime/components/AvatarGroup.vue +5 -7
  68. package/dist/runtime/components/Badge.vue +10 -8
  69. package/dist/runtime/components/Breadcrumb.vue +13 -34
  70. package/dist/runtime/components/Button.vue +5 -8
  71. package/dist/runtime/components/ButtonGroup.vue +5 -7
  72. package/dist/runtime/components/Calendar.vue +194 -0
  73. package/dist/runtime/components/Card.vue +10 -9
  74. package/dist/runtime/components/Carousel.vue +26 -17
  75. package/dist/runtime/components/Checkbox.vue +32 -38
  76. package/dist/runtime/components/Chip.vue +6 -8
  77. package/dist/runtime/components/Collapsible.vue +10 -11
  78. package/dist/runtime/components/ColorPicker.vue +297 -0
  79. package/dist/runtime/components/CommandPalette.vue +114 -98
  80. package/dist/runtime/components/Container.vue +4 -7
  81. package/dist/runtime/components/ContextMenu.vue +16 -69
  82. package/dist/runtime/components/ContextMenuContent.vue +14 -10
  83. package/dist/runtime/components/Drawer.vue +23 -12
  84. package/dist/runtime/components/DropdownMenu.vue +18 -59
  85. package/dist/runtime/components/DropdownMenuContent.vue +14 -10
  86. package/dist/runtime/components/Form.vue +78 -49
  87. package/dist/runtime/components/FormField.vue +28 -15
  88. package/dist/runtime/components/Icon.vue +1 -1
  89. package/dist/runtime/components/Input.vue +15 -7
  90. package/dist/runtime/components/InputMenu.vue +133 -66
  91. package/dist/runtime/components/InputNumber.vue +197 -0
  92. package/dist/runtime/components/Kbd.vue +5 -6
  93. package/dist/runtime/components/Link.vue +24 -13
  94. package/dist/runtime/components/LinkBase.vue +1 -1
  95. package/dist/runtime/components/Modal.vue +56 -34
  96. package/dist/runtime/components/NavigationMenu.vue +129 -112
  97. package/dist/runtime/components/OverlayProvider.vue +28 -0
  98. package/dist/runtime/components/Pagination.vue +18 -14
  99. package/dist/runtime/components/PinInput.vue +95 -0
  100. package/dist/runtime/components/Popover.vue +28 -14
  101. package/dist/runtime/components/Progress.vue +28 -12
  102. package/dist/runtime/components/RadioGroup.vue +9 -12
  103. package/dist/runtime/components/Select.vue +61 -35
  104. package/dist/runtime/components/SelectMenu.vue +201 -130
  105. package/dist/runtime/components/Separator.vue +6 -5
  106. package/dist/runtime/components/Skeleton.vue +4 -7
  107. package/dist/runtime/components/Slideover.vue +56 -33
  108. package/dist/runtime/components/Slider.vue +8 -7
  109. package/dist/runtime/components/Stepper.vue +170 -0
  110. package/dist/runtime/components/Switch.vue +19 -23
  111. package/dist/runtime/components/Table.vue +157 -32
  112. package/dist/runtime/components/Tabs.vue +12 -31
  113. package/dist/runtime/components/Textarea.vue +18 -9
  114. package/dist/runtime/components/Toast.vue +39 -25
  115. package/dist/runtime/components/Toaster.vue +31 -24
  116. package/dist/runtime/components/Tooltip.vue +9 -12
  117. package/dist/runtime/components/Tree.vue +196 -0
  118. package/dist/runtime/composables/defineLocale.d.ts +9 -0
  119. package/dist/runtime/composables/defineLocale.js +4 -0
  120. package/dist/runtime/composables/defineShortcuts.d.ts +1 -1
  121. package/dist/runtime/composables/defineShortcuts.js +2 -2
  122. package/dist/runtime/composables/useFormField.d.ts +11 -4
  123. package/dist/runtime/composables/useFormField.js +19 -9
  124. package/dist/runtime/composables/useLocale.d.ts +4 -0
  125. package/dist/runtime/composables/useLocale.js +10 -0
  126. package/dist/runtime/composables/useOverlay.d.ts +30 -0
  127. package/dist/runtime/composables/useOverlay.js +70 -0
  128. package/dist/runtime/composables/useToast.d.ts +4 -3
  129. package/dist/runtime/composables/useToast.js +20 -6
  130. package/dist/runtime/index.css +1 -1
  131. package/dist/runtime/keyframes.css +1 -1
  132. package/dist/runtime/locale/ar.d.ts +2 -0
  133. package/dist/runtime/locale/ar.js +55 -0
  134. package/dist/runtime/locale/az.d.ts +2 -0
  135. package/dist/runtime/locale/az.js +54 -0
  136. package/dist/runtime/locale/bn.d.ts +2 -0
  137. package/dist/runtime/locale/bn.js +54 -0
  138. package/dist/runtime/locale/cs.d.ts +2 -0
  139. package/dist/runtime/locale/cs.js +54 -0
  140. package/dist/runtime/locale/da.d.ts +2 -0
  141. package/dist/runtime/locale/da.js +54 -0
  142. package/dist/runtime/locale/de.d.ts +2 -0
  143. package/dist/runtime/locale/de.js +54 -0
  144. package/dist/runtime/locale/el.d.ts +2 -0
  145. package/dist/runtime/locale/el.js +54 -0
  146. package/dist/runtime/locale/en.d.ts +2 -0
  147. package/dist/runtime/locale/en.js +54 -0
  148. package/dist/runtime/locale/es.d.ts +2 -0
  149. package/dist/runtime/locale/es.js +54 -0
  150. package/dist/runtime/locale/et.d.ts +2 -0
  151. package/dist/runtime/locale/et.js +54 -0
  152. package/dist/runtime/locale/fa_ir.d.ts +2 -0
  153. package/dist/runtime/locale/fa_ir.js +55 -0
  154. package/dist/runtime/locale/fi.d.ts +2 -0
  155. package/dist/runtime/locale/fi.js +54 -0
  156. package/dist/runtime/locale/fr.d.ts +2 -0
  157. package/dist/runtime/locale/fr.js +54 -0
  158. package/dist/runtime/locale/he.d.ts +2 -0
  159. package/dist/runtime/locale/he.js +53 -0
  160. package/dist/runtime/locale/hi.d.ts +2 -0
  161. package/dist/runtime/locale/hi.js +54 -0
  162. package/dist/runtime/locale/hu.d.ts +2 -0
  163. package/dist/runtime/locale/hu.js +54 -0
  164. package/dist/runtime/locale/id.d.ts +2 -0
  165. package/dist/runtime/locale/id.js +54 -0
  166. package/dist/runtime/locale/index.d.ts +34 -0
  167. package/dist/runtime/locale/index.js +34 -0
  168. package/dist/runtime/locale/it.d.ts +2 -0
  169. package/dist/runtime/locale/it.js +54 -0
  170. package/dist/runtime/locale/ja.d.ts +2 -0
  171. package/dist/runtime/locale/ja.js +54 -0
  172. package/dist/runtime/locale/km.d.ts +2 -0
  173. package/dist/runtime/locale/km.js +54 -0
  174. package/dist/runtime/locale/ko.d.ts +2 -0
  175. package/dist/runtime/locale/ko.js +54 -0
  176. package/dist/runtime/locale/nb_no.d.ts +2 -0
  177. package/dist/runtime/locale/nb_no.js +54 -0
  178. package/dist/runtime/locale/nl.d.ts +2 -0
  179. package/dist/runtime/locale/nl.js +54 -0
  180. package/dist/runtime/locale/pl.d.ts +2 -0
  181. package/dist/runtime/locale/pl.js +54 -0
  182. package/dist/runtime/locale/pt.d.ts +2 -0
  183. package/dist/runtime/locale/pt.js +54 -0
  184. package/dist/runtime/locale/pt_br.d.ts +2 -0
  185. package/dist/runtime/locale/pt_br.js +54 -0
  186. package/dist/runtime/locale/ru.d.ts +2 -0
  187. package/dist/runtime/locale/ru.js +54 -0
  188. package/dist/runtime/locale/sk.d.ts +2 -0
  189. package/dist/runtime/locale/sk.js +54 -0
  190. package/dist/runtime/locale/sv.d.ts +2 -0
  191. package/dist/runtime/locale/sv.js +54 -0
  192. package/dist/runtime/locale/th.d.ts +2 -0
  193. package/dist/runtime/locale/th.js +54 -0
  194. package/dist/runtime/locale/tr.d.ts +2 -0
  195. package/dist/runtime/locale/tr.js +54 -0
  196. package/dist/runtime/locale/uk.d.ts +2 -0
  197. package/dist/runtime/locale/uk.js +54 -0
  198. package/dist/runtime/locale/vi.d.ts +2 -0
  199. package/dist/runtime/locale/vi.js +54 -0
  200. package/dist/runtime/locale/zh_cn.d.ts +2 -0
  201. package/dist/runtime/locale/zh_cn.js +54 -0
  202. package/dist/runtime/locale/zh_tw.d.ts +2 -0
  203. package/dist/runtime/locale/zh_tw.js +54 -0
  204. package/dist/runtime/plugins/colors.js +8 -5
  205. package/dist/runtime/types/form.d.ts +29 -15
  206. package/dist/runtime/types/form.js +2 -2
  207. package/dist/runtime/types/index.d.ts +8 -0
  208. package/dist/runtime/types/index.js +8 -0
  209. package/dist/runtime/types/locale.d.ts +56 -0
  210. package/dist/runtime/types/locale.js +0 -0
  211. package/dist/runtime/types/utils.d.ts +7 -3
  212. package/dist/runtime/utils/form.d.ts +5 -9
  213. package/dist/runtime/utils/form.js +113 -50
  214. package/dist/runtime/utils/index.d.ts +1 -1
  215. package/dist/runtime/utils/index.js +15 -2
  216. package/dist/runtime/utils/link.d.ts +1 -1
  217. package/dist/runtime/utils/locale.d.ts +15 -0
  218. package/dist/runtime/utils/locale.js +25 -0
  219. package/dist/runtime/utils/tv.d.ts +1 -0
  220. package/dist/runtime/utils/tv.js +4 -0
  221. package/dist/runtime/vue/components/Icon.vue +2 -2
  222. package/dist/runtime/vue/components/Link.vue +87 -23
  223. package/dist/runtime/vue/composables/useAppConfig.d.ts +1 -0
  224. package/dist/runtime/vue/composables/useAppConfig.js +2 -0
  225. package/dist/runtime/vue/plugins/head.d.ts +1 -1
  226. package/dist/runtime/vue/plugins/head.js +3 -3
  227. package/dist/runtime/vue/stubs.d.ts +19 -0
  228. package/dist/runtime/vue/stubs.js +37 -0
  229. package/dist/shared/{ui.BufKhDiD.mjs → ui.DSPu6Y8j.mjs} +1071 -409
  230. package/dist/shared/{ui.BU7wzH0D.cjs → ui.DfK2RX6G.cjs} +1074 -409
  231. package/dist/unplugin.cjs +62 -26
  232. package/dist/unplugin.d.cts +17 -3
  233. package/dist/unplugin.d.mts +17 -3
  234. package/dist/unplugin.d.ts +17 -3
  235. package/dist/unplugin.mjs +61 -25
  236. package/dist/vite.cjs +3 -2
  237. package/dist/vite.d.cts +2 -0
  238. package/dist/vite.d.mts +2 -0
  239. package/dist/vite.d.ts +2 -0
  240. package/dist/vite.mjs +3 -2
  241. package/package.json +110 -67
  242. package/dist/chunks/component-meta.cjs +0 -73264
  243. package/dist/chunks/component-meta.mjs +0 -73262
  244. package/dist/client/devtools/200.html +0 -1
  245. package/dist/client/devtools/404.html +0 -1
  246. package/dist/client/devtools/_fonts/rP2Wp2ywxg089UriCZaSExd86J3t9jz86MvyyKK58UfivUw4aw-SK92LTmKP0.woff2 +0 -0
  247. package/dist/client/devtools/_fonts/rP2Wp2ywxg089UriCZaSExd86J3t9jz86MvyyKy58UfivUw-9uYm8d48E4.woff2 +0 -0
  248. package/dist/client/devtools/_fonts/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu0-K6z9mXg-VNw7NHvqnp.woff2 +0 -0
  249. package/dist/client/devtools/_fonts/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu6-K6z9mXgjU0-EkYdMs3MAX.woff2 +0 -0
  250. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-7DW3w-R7n06NbhGy.woff +0 -0
  251. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-JDG3w-leGNfkTmsj.woff +0 -0
  252. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-JDW3w-ciElMF03ku.woff +0 -0
  253. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8JCm3w-sB722Uoa0f.woff +0 -0
  254. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8JDW3w-PBDI1JDjwV.woff +0 -0
  255. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8gCm3w-0q1hqVn09O.woff +0 -0
  256. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat9XCm3w-ByvzuLy2fa.woff +0 -0
  257. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat9uCm3w-5TKCIs6EEw.woff +0 -0
  258. package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat_XDW3w-r2swRDGfn2.woff +0 -0
  259. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAC5thTQ-ldB60l5U8r.woff +0 -0
  260. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAIpthTQ-wbFKGFDrgo.woff +0 -0
  261. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAIpxhTQ-LLUBv5jskj.woff +0 -0
  262. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwARZthTQ-F71RdTRbNg.woff +0 -0
  263. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwA_JxhTQ-6nh65gZkc0.woff +0 -0
  264. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAfJthTQ-aMoWEJLmTt.woff +0 -0
  265. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAkJxhTQ-WMBvmLOgKm.woff +0 -0
  266. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAop1hTQ-utGC2hnWq2.woff +0 -0
  267. package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAopxhTQ-YpyTieVa5B.woff +0 -0
  268. package/dist/client/devtools/_nuxt/Bj9hdafK.js +0 -1
  269. package/dist/client/devtools/_nuxt/DM3_wAgz.js +0 -62
  270. package/dist/client/devtools/_nuxt/builds/latest.json +0 -1
  271. package/dist/client/devtools/_nuxt/builds/meta/e6b425f7-b919-4014-915b-0ea07c316790.json +0 -1
  272. package/dist/client/devtools/_nuxt/entry.DaJP-ZMB.css +0 -24
  273. package/dist/client/devtools/_nuxt/error-404.B0Nmv3fV.css +0 -1
  274. package/dist/client/devtools/_nuxt/error-500.C8fgTxVz.css +0 -1
  275. package/dist/client/devtools/_nuxt/hKiujHsR.js +0 -1
  276. package/dist/client/devtools/favicon.svg +0 -1
  277. package/dist/client/devtools/index.html +0 -1
  278. package/dist/devtools/runtime/DevtoolsRenderer.vue +0 -53
  279. package/dist/devtools/runtime/examples/AvatarGroupExample.vue +0 -7
  280. package/dist/devtools/runtime/examples/ButtonGroupExample.vue +0 -8
  281. package/dist/devtools/runtime/examples/CardExample.vue +0 -13
  282. package/dist/devtools/runtime/examples/CarouselExample.vue +0 -13
  283. package/dist/devtools/runtime/examples/ChipExample.vue +0 -5
  284. package/dist/devtools/runtime/examples/CollapsibleExample.vue +0 -8
  285. package/dist/devtools/runtime/examples/CommandPaletteExample.vue +0 -29
  286. package/dist/devtools/runtime/examples/ContainerExample.vue +0 -5
  287. package/dist/devtools/runtime/examples/ContextMenuExample.vue +0 -5
  288. package/dist/devtools/runtime/examples/DrawerExample.vue +0 -8
  289. package/dist/devtools/runtime/examples/DropdownMenuExample.vue +0 -5
  290. package/dist/devtools/runtime/examples/FormExample.vue +0 -30
  291. package/dist/devtools/runtime/examples/FormFieldExample.vue +0 -5
  292. package/dist/devtools/runtime/examples/LinkExample.vue +0 -5
  293. package/dist/devtools/runtime/examples/ModalExample.vue +0 -8
  294. package/dist/devtools/runtime/examples/PopoverExample.vue +0 -8
  295. package/dist/devtools/runtime/examples/SkeletonExample.vue +0 -3
  296. package/dist/devtools/runtime/examples/SlideoverExample.vue +0 -8
  297. package/dist/devtools/runtime/examples/ToasterExample.vue +0 -11
  298. package/dist/devtools/runtime/examples/TooltipExample.vue +0 -5
  299. package/dist/runtime/components/ModalProvider.vue +0 -12
  300. package/dist/runtime/components/SlideoverProvider.vue +0 -12
  301. package/dist/runtime/composables/extendDevtoolsMeta.d.ts +0 -7
  302. package/dist/runtime/composables/extendDevtoolsMeta.js +0 -2
  303. package/dist/runtime/composables/useModal.d.ts +0 -17
  304. package/dist/runtime/composables/useModal.js +0 -46
  305. package/dist/runtime/composables/useSlideover.d.ts +0 -17
  306. package/dist/runtime/composables/useSlideover.js +0 -46
  307. package/dist/runtime/plugins/modal.d.ts +0 -2
  308. package/dist/runtime/plugins/modal.js +0 -10
  309. package/dist/runtime/plugins/slideover.d.ts +0 -2
  310. package/dist/runtime/plugins/slideover.js +0 -10
@@ -1,17 +1,16 @@
1
1
  <script lang="ts">
2
- import { tv } from 'tailwind-variants'
3
2
  import type { DrawerRootProps, DrawerRootEmits } from 'vaul-vue'
4
- import type { DialogContentProps } from 'radix-vue'
3
+ import type { DialogContentProps } from 'reka-ui'
5
4
  import type { AppConfig } from '@nuxt/schema'
6
5
  import _appConfig from '#build/app.config'
7
6
  import theme from '#build/ui/drawer'
8
- import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
7
+ import { tv } from '../utils/tv'
9
8
 
10
- const appConfig = _appConfig as AppConfig & { ui: { drawer: Partial<typeof theme> } }
9
+ const appConfigDrawer = _appConfig as AppConfig & { ui: { drawer: Partial<typeof theme> } }
11
10
 
12
- const drawer = tv({ extend: tv(theme), ...(appConfig.ui?.drawer || {}) })
11
+ const drawer = tv({ extend: tv(theme), ...(appConfigDrawer.ui?.drawer || {}) })
13
12
 
14
- export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | 'closeThreshold' | 'defaultOpen' | 'direction' | 'dismissible' | 'fadeFromIndex' | 'fixed' | 'modal' | 'nested' | 'direction' | 'open' | 'scrollLockTimeout' | 'shouldScaleBackground' | 'snapPoints'> {
13
+ export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | 'closeThreshold' | 'defaultOpen' | 'direction' | 'fadeFromIndex' | 'fixed' | 'modal' | 'nested' | 'direction' | 'open' | 'scrollLockTimeout' | 'shouldScaleBackground' | 'snapPoints'> {
15
14
  /**
16
15
  * The element or component this component should render as.
17
16
  * @defaultValue 'div'
@@ -19,6 +18,11 @@ export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | '
19
18
  as?: any
20
19
  title?: string
21
20
  description?: string
21
+ /**
22
+ * Whether to inset the drawer from the edges.
23
+ * @defaultValue false
24
+ */
25
+ inset?: boolean
22
26
  /** The content of the drawer. */
23
27
  content?: Omit<DialogContentProps, 'as' | 'asChild' | 'forceMount'>
24
28
  /**
@@ -36,6 +40,11 @@ export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | '
36
40
  * @defaultValue true
37
41
  */
38
42
  portal?: boolean
43
+ /**
44
+ * When `false`, the drawer will not close when clicking outside or pressing escape.
45
+ * @defaultValue true
46
+ */
47
+ dismissible?: boolean
39
48
  class?: any
40
49
  ui?: Partial<typeof drawer.slots>
41
50
  }
@@ -52,13 +61,11 @@ export interface DrawerSlots {
52
61
  body(props?: {}): any
53
62
  footer(props?: {}): any
54
63
  }
55
-
56
- extendDevtoolsMeta({ example: 'DrawerExample' })
57
64
  </script>
58
65
 
59
66
  <script setup lang="ts">
60
67
  import { computed, toRef } from 'vue'
61
- import { useForwardPropsEmits } from 'radix-vue'
68
+ import { useForwardPropsEmits } from 'reka-ui'
62
69
  import { DrawerRoot, DrawerTrigger, DrawerPortal, DrawerOverlay, DrawerContent, DrawerTitle, DrawerDescription } from 'vaul-vue'
63
70
  import { reactivePick } from '@vueuse/core'
64
71
 
@@ -73,22 +80,26 @@ const slots = defineSlots<DrawerSlots>()
73
80
 
74
81
  const rootProps = useForwardPropsEmits(reactivePick(props, 'activeSnapPoint', 'closeThreshold', 'defaultOpen', 'dismissible', 'fadeFromIndex', 'fixed', 'modal', 'nested', 'direction', 'open', 'scrollLockTimeout', 'shouldScaleBackground', 'snapPoints'), emits)
75
82
  const contentProps = toRef(() => props.content)
83
+ const contentEvents = {
84
+ closeAutoFocus: (e: Event) => e.preventDefault()
85
+ }
76
86
 
77
87
  const ui = computed(() => drawer({
78
- direction: props.direction
88
+ direction: props.direction,
89
+ inset: props.inset
79
90
  }))
80
91
  </script>
81
92
 
82
93
  <template>
83
94
  <DrawerRoot v-bind="rootProps">
84
- <DrawerTrigger v-if="!!slots.default" as-child>
95
+ <DrawerTrigger v-if="!!slots.default" as-child :class="props.class">
85
96
  <slot />
86
97
  </DrawerTrigger>
87
98
 
88
99
  <DrawerPortal :disabled="!portal">
89
100
  <DrawerOverlay v-if="overlay" :class="ui.overlay({ class: props.ui?.overlay })" />
90
101
 
91
- <DrawerContent :class="ui.content({ class: [props.class, props.ui?.content] })" v-bind="contentProps">
102
+ <DrawerContent :class="ui.content({ class: [!slots.default && props.class, props.ui?.content] })" v-bind="contentProps" v-on="contentEvents">
92
103
  <slot name="handle">
93
104
  <div v-if="handle" :class="ui.handle({ class: props.ui?.handle })" />
94
105
  </slot>
@@ -1,16 +1,16 @@
1
1
  <script lang="ts">
2
- import { tv, type VariantProps } from 'tailwind-variants'
3
- import type { DropdownMenuRootProps, DropdownMenuRootEmits, DropdownMenuContentProps, DropdownMenuArrowProps } from 'radix-vue'
2
+ import type { VariantProps } from 'tailwind-variants'
3
+ import type { DropdownMenuRootProps, DropdownMenuRootEmits, DropdownMenuContentProps, DropdownMenuArrowProps } from 'reka-ui'
4
4
  import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/dropdown-menu'
7
- import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
7
+ import { tv } from '../utils/tv'
8
8
  import type { AvatarProps, KbdProps, LinkProps } from '../types'
9
9
  import type { DynamicSlots, PartialString } from '../types/utils'
10
10
 
11
- const appConfig = _appConfig as AppConfig & { ui: { dropdownMenu: Partial<typeof theme> } }
11
+ const appConfigDropdownMenu = _appConfig as AppConfig & { ui: { dropdownMenu: Partial<typeof theme> } }
12
12
 
13
- const dropdownMenu = tv({ extend: tv(theme), ...(appConfig.ui?.dropdownMenu || {}) })
13
+ const dropdownMenu = tv({ extend: tv(theme), ...(appConfigDropdownMenu.ui?.dropdownMenu || {}) })
14
14
 
15
15
  type DropdownMenuVariants = VariantProps<typeof dropdownMenu>
16
16
 
@@ -50,9 +50,15 @@ export interface DropdownMenuProps<T> extends Omit<DropdownMenuRootProps, 'dir'>
50
50
  * @defaultValue appConfig.ui.icons.loading
51
51
  */
52
52
  loadingIcon?: string
53
+ /**
54
+ * The icon displayed when the item is an external link.
55
+ * Set to `false` to hide the external icon.
56
+ * @defaultValue appConfig.ui.icons.external
57
+ */
58
+ externalIcon?: boolean | string
53
59
  /**
54
60
  * The content of the menu.
55
- * @defaultValue { side: 'bottom', sideOffset: 8 }
61
+ * @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8 }
56
62
  */
57
63
  content?: Omit<DropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'>
58
64
  /**
@@ -86,61 +92,12 @@ export type DropdownMenuSlots<T extends { slot?: string }> = {
86
92
  'item-label': SlotProps<T>
87
93
  'item-trailing': SlotProps<T>
88
94
  } & DynamicSlots<T, SlotProps<T>>
89
-
90
- extendDevtoolsMeta({
91
- example: 'DropdownMenuExample',
92
- ignoreProps: ['items'],
93
- defaultProps: {
94
- items: [
95
- [{
96
- label: 'My account',
97
- avatar: {
98
- src: 'https://avatars.githubusercontent.com/u/739984?v=4'
99
- },
100
- type: 'label'
101
- }], [{
102
- label: 'Profile',
103
- icon: 'i-lucide-user',
104
- slot: 'custom'
105
- }, {
106
- label: 'Billing',
107
- icon: 'i-lucide-credit-card',
108
- kbds: ['meta', 'b']
109
- }, {
110
- label: 'Settings',
111
- icon: 'i-lucide-cog',
112
- kbds: ['?']
113
- }], [{
114
- label: 'Invite users',
115
- icon: 'i-lucide-user-plus',
116
- children: [[{
117
- label: 'Invite by email',
118
- icon: 'i-lucide-send-horizontal'
119
- }, {
120
- label: 'Invite by link',
121
- icon: 'i-lucide-link',
122
- kbds: ['meta', 'i']
123
- }]]
124
- }],
125
- [{
126
- label: 'GitHub',
127
- icon: 'i-simple-icons-github',
128
- to: 'https://github.com/nuxt/ui',
129
- target: '_blank'
130
- }, {
131
- label: 'Support',
132
- icon: 'i-lucide-life-buoy',
133
- to: '/components/dropdown-menu'
134
- }]
135
- ]
136
- }
137
- })
138
95
  </script>
139
96
 
140
97
  <script setup lang="ts" generic="T extends DropdownMenuItem">
141
98
  import { computed, toRef } from 'vue'
142
99
  import { defu } from 'defu'
143
- import { DropdownMenuRoot, DropdownMenuTrigger, DropdownMenuArrow, useForwardPropsEmits } from 'radix-vue'
100
+ import { DropdownMenuRoot, DropdownMenuTrigger, DropdownMenuArrow, useForwardPropsEmits } from 'reka-ui'
144
101
  import { reactivePick } from '@vueuse/core'
145
102
  import { omit } from '../utils'
146
103
  import UDropdownMenuContent from './DropdownMenuContent.vue'
@@ -148,13 +105,14 @@ import UDropdownMenuContent from './DropdownMenuContent.vue'
148
105
  const props = withDefaults(defineProps<DropdownMenuProps<T>>(), {
149
106
  portal: true,
150
107
  modal: true,
108
+ externalIcon: true,
151
109
  labelKey: 'label'
152
110
  })
153
111
  const emits = defineEmits<DropdownMenuEmits>()
154
112
  const slots = defineSlots<DropdownMenuSlots<T>>()
155
113
 
156
114
  const rootProps = useForwardPropsEmits(reactivePick(props, 'defaultOpen', 'open', 'modal'), emits)
157
- const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8 }) as DropdownMenuContentProps)
115
+ const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8 }) as DropdownMenuContentProps)
158
116
  const arrowProps = toRef(() => props.arrow as DropdownMenuArrowProps)
159
117
  const proxySlots = omit(slots, ['default']) as Record<string, DropdownMenuSlots<T>[string]>
160
118
 
@@ -165,12 +123,12 @@ const ui = computed(() => dropdownMenu({
165
123
 
166
124
  <template>
167
125
  <DropdownMenuRoot v-slot="{ open }" v-bind="rootProps">
168
- <DropdownMenuTrigger v-if="!!slots.default" as-child :disabled="disabled">
126
+ <DropdownMenuTrigger v-if="!!slots.default" as-child :class="props.class" :disabled="disabled">
169
127
  <slot :open="open" />
170
128
  </DropdownMenuTrigger>
171
129
 
172
130
  <UDropdownMenuContent
173
- :class="ui.content({ class: [props.class, props.ui?.content] })"
131
+ :class="ui.content({ class: [!slots.default && props.class, props.ui?.content] })"
174
132
  :ui="ui"
175
133
  :ui-override="props.ui"
176
134
  v-bind="contentProps"
@@ -179,6 +137,7 @@ const ui = computed(() => dropdownMenu({
179
137
  :label-key="labelKey"
180
138
  :checked-icon="checkedIcon"
181
139
  :loading-icon="loadingIcon"
140
+ :external-icon="externalIcon"
182
141
  >
183
142
  <template v-for="(_, name) in proxySlots" #[name]="slotData: any">
184
143
  <slot :name="name" v-bind="slotData" />
@@ -1,25 +1,26 @@
1
1
  <!-- eslint-disable vue/block-tag-newline -->
2
2
  <script lang="ts">
3
- import { tv } from 'tailwind-variants'
4
- import type { DropdownMenuContentProps as RadixDropdownMenuContentProps, DropdownMenuContentEmits as RadixDropdownMenuContentEmits } from 'radix-vue'
3
+ import type { DropdownMenuContentProps as RekaDropdownMenuContentProps, DropdownMenuContentEmits as RekaDropdownMenuContentEmits } from 'reka-ui'
5
4
  import theme from '#build/ui/dropdown-menu'
5
+ import { tv } from '../utils/tv'
6
6
  import type { KbdProps, AvatarProps, DropdownMenuItem, DropdownMenuSlots } from '../types'
7
7
 
8
8
  const _dropdownMenu = tv(theme)()
9
9
 
10
- interface DropdownMenuContentProps<T> extends Omit<RadixDropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'> {
10
+ interface DropdownMenuContentProps<T> extends Omit<RekaDropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'> {
11
11
  items?: T[] | T[][]
12
12
  portal?: boolean
13
13
  sub?: boolean
14
14
  labelKey: string
15
15
  checkedIcon?: string
16
16
  loadingIcon?: string
17
+ externalIcon?: boolean | string
17
18
  class?: any
18
19
  ui: typeof _dropdownMenu
19
20
  uiOverride?: any
20
21
  }
21
22
 
22
- interface DropdownMenuContentEmits extends RadixDropdownMenuContentEmits {}
23
+ interface DropdownMenuContentEmits extends RekaDropdownMenuContentEmits {}
23
24
 
24
25
  type DropdownMenuContentSlots<T extends { slot?: string }> = Omit<DropdownMenuSlots<T>, 'default'> & {
25
26
  default(props?: {}): any
@@ -29,8 +30,8 @@ type DropdownMenuContentSlots<T extends { slot?: string }> = Omit<DropdownMenuSl
29
30
 
30
31
  <script setup lang="ts" generic="T extends DropdownMenuItem">
31
32
  import { computed } from 'vue'
32
- import { DropdownMenu } from 'radix-vue/namespaced'
33
- import { useForwardPropsEmits } from 'radix-vue'
33
+ import { DropdownMenu } from 'reka-ui/namespaced'
34
+ import { useForwardPropsEmits } from 'reka-ui'
34
35
  import { reactiveOmit, createReusableTemplate } from '@vueuse/core'
35
36
  import { useAppConfig } from '#imports'
36
37
  import { omit, get } from '../utils'
@@ -40,13 +41,15 @@ import ULink from './Link.vue'
40
41
  import UAvatar from './Avatar.vue'
41
42
  import UIcon from './Icon.vue'
42
43
  import UKbd from './Kbd.vue'
44
+ // eslint-disable-next-line import/no-self-import
45
+ import UDropdownMenuContent from './DropdownMenuContent.vue'
43
46
 
44
47
  const props = defineProps<DropdownMenuContentProps<T>>()
45
48
  const emits = defineEmits<DropdownMenuContentEmits>()
46
49
  const slots = defineSlots<DropdownMenuContentSlots<T>>()
47
50
 
48
51
  const appConfig = useAppConfig()
49
- const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'class', 'ui'), emits)
52
+ const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'labelKey', 'checkedIcon', 'loadingIcon', 'externalIcon', 'class', 'ui', 'uiOverride'), emits)
50
53
  const proxySlots = omit(slots, ['default']) as Record<string, DropdownMenuContentSlots<T>[string]>
51
54
 
52
55
  const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: DropdownMenuItem, active?: boolean, index: number }>()
@@ -68,7 +71,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
68
71
  {{ get(item, props.labelKey as string) }}
69
72
  </slot>
70
73
 
71
- <UIcon v-if="item.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
74
+ <UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
72
75
  </span>
73
76
 
74
77
  <span :class="ui.itemTrailing({ class: uiOverride?.itemTrailing })">
@@ -119,6 +122,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
119
122
  :label-key="labelKey"
120
123
  :checked-icon="checkedIcon"
121
124
  :loading-icon="loadingIcon"
125
+ :external-icon="externalIcon"
122
126
  v-bind="item.content"
123
127
  >
124
128
  <template v-for="(_, name) in proxySlots" #[name]="slotData: any">
@@ -128,11 +132,11 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
128
132
  </DropdownMenu.Sub>
129
133
  <DropdownMenu.CheckboxItem
130
134
  v-else-if="item.type === 'checkbox'"
131
- :checked="item.checked"
135
+ :model-value="item.checked"
132
136
  :disabled="item.disabled"
133
137
  :text-value="get(item, props.labelKey as string)"
134
138
  :class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color })"
135
- @update:checked="item.onUpdateChecked"
139
+ @update:model-value="item.onUpdateChecked"
136
140
  @select="item.onSelect"
137
141
  >
138
142
  <ReuseItemTemplate :item="item" :index="index" />
@@ -1,14 +1,14 @@
1
1
  <script lang="ts">
2
- import { tv } from 'tailwind-variants'
3
2
  import type { AppConfig } from '@nuxt/schema'
4
3
  import _appConfig from '#build/app.config'
5
4
  import theme from '#build/ui/form'
6
- import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
5
+ import { tv } from '../utils/tv'
7
6
  import type { FormSchema, FormError, FormInputEvents, FormErrorEvent, FormSubmitEvent, FormEvent, Form, FormErrorWithId } from '../types/form'
7
+ import type { DeepReadonly } from 'vue'
8
8
 
9
- const appConfig = _appConfig as AppConfig & { ui: { form: Partial<typeof theme> } }
9
+ const appConfigForm = _appConfig as AppConfig & { ui: { form: Partial<typeof theme> } }
10
10
 
11
- const form = tv({ extend: tv(theme), ...(appConfig.ui?.form || {}) })
11
+ const form = tv({ extend: tv(theme), ...(appConfigForm.ui?.form || {}) })
12
12
 
13
13
  export interface FormProps<T extends object> {
14
14
  id?: string | number
@@ -19,6 +19,7 @@ export interface FormProps<T extends object> {
19
19
  disabled?: boolean
20
20
  validateOnInputDelay?: number
21
21
  class?: any
22
+ transform?: boolean
22
23
  onSubmit?: ((event: FormSubmitEvent<T>) => void | Promise<void>) | (() => void | Promise<void>)
23
24
  }
24
25
 
@@ -30,29 +31,29 @@ export interface FormEmits<T extends object> {
30
31
  export interface FormSlots {
31
32
  default(props?: {}): any
32
33
  }
33
-
34
- extendDevtoolsMeta({ example: 'FormExample' })
35
34
  </script>
36
35
 
37
36
  <script lang="ts" setup generic="T extends object">
38
37
  import { provide, inject, nextTick, ref, onUnmounted, onMounted, computed, useId, readonly } from 'vue'
39
38
  import { useEventBus } from '@vueuse/core'
40
39
  import { formOptionsInjectionKey, formInputsInjectionKey, formBusInjectionKey, formLoadingInjectionKey } from '../composables/useFormField'
41
- import { getYupErrors, isYupSchema, getValibotErrors, isValibotSchema, getZodErrors, isZodSchema, getJoiErrors, isJoiSchema, getStandardErrors, isStandardSchema, getSuperStructErrors, isSuperStructSchema } from '../utils/form'
40
+ import { validateSchema } from '../utils/form'
42
41
  import { FormValidationException } from '../types/form'
43
42
 
44
43
  const props = withDefaults(defineProps<FormProps<T>>(), {
45
44
  validateOn() {
46
45
  return ['input', 'blur', 'change'] as FormInputEvents[]
47
46
  },
48
- validateOnInputDelay: 300
47
+ validateOnInputDelay: 300,
48
+ transform: true
49
49
  })
50
+
50
51
  const emits = defineEmits<FormEmits<T>>()
51
52
  defineSlots<FormSlots>()
52
53
 
53
54
  const formId = props.id ?? useId() as string
54
55
 
55
- const bus = useEventBus<FormEvent>(`form-${formId}`)
56
+ const bus = useEventBus<FormEvent<T>>(`form-${formId}`)
56
57
  const parentBus = inject(
57
58
  formBusInjectionKey,
58
59
  undefined
@@ -60,7 +61,7 @@ const parentBus = inject(
60
61
 
61
62
  provide(formBusInjectionKey, bus)
62
63
 
63
- const nestedForms = ref<Map<string | number, { validate: () => any }>>(new Map())
64
+ const nestedForms = ref<Map<string | number, { validate: typeof _validate }>>(new Map())
64
65
 
65
66
  onMounted(async () => {
66
67
  bus.on(async (event) => {
@@ -68,8 +69,24 @@ onMounted(async () => {
68
69
  nestedForms.value.set(event.formId, { validate: event.validate })
69
70
  } else if (event.type === 'detach') {
70
71
  nestedForms.value.delete(event.formId)
71
- } else if (props.validateOn?.includes(event.type as FormInputEvents)) {
72
- await _validate({ name: event.name, silent: true, nested: false })
72
+ } else if (props.validateOn?.includes(event.type)) {
73
+ if (event.type !== 'input') {
74
+ await _validate({ name: event.name, silent: true, nested: false })
75
+ } else if (event.eager || blurredFields.has(event.name)) {
76
+ await _validate({ name: event.name, silent: true, nested: false })
77
+ }
78
+ }
79
+
80
+ if (event.type === 'blur') {
81
+ blurredFields.add(event.name)
82
+ }
83
+
84
+ if (event.type === 'change' || event.type === 'input' || event.type === 'blur' || event.type === 'focus') {
85
+ touchedFields.add(event.name)
86
+ }
87
+
88
+ if (event.type === 'change' || event.type === 'input') {
89
+ dirtyFields.add(event.name)
73
90
  }
74
91
  })
75
92
  })
@@ -94,70 +111,78 @@ onUnmounted(() => {
94
111
  const errors = ref<FormErrorWithId[]>([])
95
112
  provide('form-errors', errors)
96
113
 
97
- const inputs = ref<Record<string, string>>({})
98
- provide(formInputsInjectionKey, inputs)
114
+ const inputs = ref<{ [P in keyof T]?: { id?: string, pattern?: RegExp } }>({})
115
+ provide(formInputsInjectionKey, inputs as any)
116
+
117
+ const dirtyFields = new Set<keyof T>()
118
+ const touchedFields = new Set<keyof T>()
119
+ const blurredFields = new Set<keyof T>()
99
120
 
100
121
  function resolveErrorIds(errs: FormError[]): FormErrorWithId[] {
101
122
  return errs.map(err => ({
102
123
  ...err,
103
- id: inputs.value[err.name]
124
+ id: inputs.value[err.name]?.id
104
125
  }))
105
126
  }
106
127
 
128
+ const transformedState = ref<T | null>(null)
129
+
107
130
  async function getErrors(): Promise<FormErrorWithId[]> {
108
131
  let errs = props.validate ? (await props.validate(props.state)) ?? [] : []
109
132
 
110
133
  if (props.schema) {
111
- if (isZodSchema(props.schema)) {
112
- errs = errs.concat(await getZodErrors(props.state, props.schema))
113
- } else if (isYupSchema(props.schema)) {
114
- errs = errs.concat(await getYupErrors(props.state, props.schema))
115
- } else if (isJoiSchema(props.schema)) {
116
- errs = errs.concat(await getJoiErrors(props.state, props.schema))
117
- } else if (isValibotSchema(props.schema)) {
118
- errs = errs.concat(await getValibotErrors(props.state, props.schema))
119
- } else if (isSuperStructSchema(props.schema)) {
120
- errs = errs.concat(await getSuperStructErrors(props.state, props.schema))
121
- } else if (isStandardSchema(props.schema)) {
122
- errs = errs.concat(await getStandardErrors(props.state, props.schema))
134
+ const { errors, result } = await validateSchema(props.state, props.schema as FormSchema<typeof props.state>)
135
+ if (errors) {
136
+ errs = errs.concat(errors)
123
137
  } else {
124
- throw new Error('Form validation failed: Unsupported form schema')
138
+ transformedState.value = result
125
139
  }
126
140
  }
127
141
 
128
142
  return resolveErrorIds(errs)
129
143
  }
130
144
 
131
- async function _validate(opts: { name?: string | string[], silent?: boolean, nested?: boolean } = { silent: false, nested: true }): Promise<T | false> {
132
- const names = opts.name && !Array.isArray(opts.name) ? [opts.name] : opts.name
145
+ async function _validate(opts: { name?: keyof T | (keyof T)[], silent?: boolean, nested?: boolean, transform?: boolean } = { silent: false, nested: true, transform: false }): Promise<T | false> {
146
+ const names = opts.name && !Array.isArray(opts.name) ? [opts.name] : opts.name as (keyof T)[]
133
147
 
134
148
  const nestedValidatePromises = !names && opts.nested
135
149
  ? Array.from(nestedForms.value.values()).map(
136
- ({ validate }) => validate().then(() => undefined).catch((error: Error) => {
137
- if (!(error instanceof FormValidationException)) {
138
- throw error
139
- }
140
- return error
141
- })
142
- )
150
+ ({ validate }) => validate(opts).then(() => undefined).catch((error: Error) => {
151
+ if (!(error instanceof FormValidationException)) {
152
+ throw error
153
+ }
154
+ return error
155
+ })
156
+ )
143
157
  : []
144
158
 
145
159
  if (names) {
146
- const otherErrors = errors.value.filter(error => !names!.includes(error.name))
147
- const pathErrors = (await getErrors()).filter(error => names!.includes(error.name)
148
- )
160
+ const otherErrors = errors.value.filter(error => !names.some((name) => {
161
+ const pattern = inputs.value?.[name]?.pattern
162
+ return name === error.name || (pattern && error.name.match(pattern))
163
+ }))
164
+
165
+ const pathErrors = (await getErrors()).filter(error => names.some((name) => {
166
+ const pattern = inputs.value?.[name]?.pattern
167
+ return name === error.name || (pattern && error.name.match(pattern))
168
+ }))
169
+
149
170
  errors.value = otherErrors.concat(pathErrors)
150
171
  } else {
151
172
  errors.value = await getErrors()
152
173
  }
153
174
 
154
- const childErrors = (await Promise.all(nestedValidatePromises)).filter(val => val)
175
+ const childErrors = (await Promise.all(nestedValidatePromises)).filter(val => val !== undefined)
155
176
 
156
177
  if (errors.value.length + childErrors.length > 0) {
157
178
  if (opts.silent) return false
158
179
  throw new FormValidationException(formId, errors.value, childErrors)
159
180
  }
160
181
 
182
+ if (opts.transform) {
183
+ Object.assign(props.state, transformedState.value)
184
+ }
185
+
161
186
  return props.state as T
162
187
  }
163
188
 
@@ -170,8 +195,7 @@ async function onSubmitWrapper(payload: Event) {
170
195
  const event = payload as FormSubmitEvent<any>
171
196
 
172
197
  try {
173
- await _validate({ nested: true })
174
- event.data = props.state
198
+ event.data = await _validate({ nested: true, transform: props.transform })
175
199
  await props.onSubmit?.(event)
176
200
  } catch (error) {
177
201
  if (!(error instanceof FormValidationException)) {
@@ -181,12 +205,12 @@ async function onSubmitWrapper(payload: Event) {
181
205
  const errorEvent: FormErrorEvent = {
182
206
  ...event,
183
207
  errors: error.errors,
184
- childrens: error.childrens
208
+ children: error.children
185
209
  }
186
210
  emits('error', errorEvent)
211
+ } finally {
212
+ loading.value = false
187
213
  }
188
-
189
- loading.value = false
190
214
  }
191
215
 
192
216
  const disabled = computed(() => props.disabled || loading.value)
@@ -200,7 +224,7 @@ defineExpose<Form<T>>({
200
224
  validate: _validate,
201
225
  errors,
202
226
 
203
- setErrors(errs: FormError[], name?: string) {
227
+ setErrors(errs: FormError[], name?: keyof T) {
204
228
  if (name) {
205
229
  errors.value = errors.value
206
230
  .filter(error => error.name !== name)
@@ -214,7 +238,7 @@ defineExpose<Form<T>>({
214
238
  await onSubmitWrapper(new Event('submit'))
215
239
  },
216
240
 
217
- getErrors(name?: string) {
241
+ getErrors(name?: keyof T) {
218
242
  if (name) {
219
243
  return errors.value.filter(err => err.name === name)
220
244
  }
@@ -229,7 +253,12 @@ defineExpose<Form<T>>({
229
253
  }
230
254
  },
231
255
 
232
- disabled
256
+ disabled,
257
+ dirty: computed(() => !!dirtyFields.size),
258
+
259
+ dirtyFields: readonly(dirtyFields) as DeepReadonly<Set<keyof T>>,
260
+ blurredFields: readonly(blurredFields) as DeepReadonly<Set<keyof T>>,
261
+ touchedFields: readonly(touchedFields) as DeepReadonly<Set<keyof T>>
233
262
  })
234
263
  </script>
235
264