@nuxt/ui 3.0.2 → 3.1.0

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 (220) hide show
  1. package/.nuxt/ui/accordion.ts +25 -4
  2. package/.nuxt/ui/alert.ts +52 -31
  3. package/.nuxt/ui/avatar-group.ts +24 -3
  4. package/.nuxt/ui/avatar.ts +26 -5
  5. package/.nuxt/ui/badge.ts +56 -35
  6. package/.nuxt/ui/breadcrumb.ts +28 -7
  7. package/.nuxt/ui/button-group.ts +23 -2
  8. package/.nuxt/ui/button.ts +66 -45
  9. package/.nuxt/ui/calendar.ts +39 -18
  10. package/.nuxt/ui/card.ts +28 -7
  11. package/.nuxt/ui/carousel.ts +29 -8
  12. package/.nuxt/ui/checkbox-group.ts +82 -0
  13. package/.nuxt/ui/checkbox.ts +163 -29
  14. package/.nuxt/ui/chip.ts +31 -10
  15. package/.nuxt/ui/collapsible.ts +23 -2
  16. package/.nuxt/ui/color-picker.ts +26 -5
  17. package/.nuxt/ui/command-palette.ts +37 -16
  18. package/.nuxt/ui/container.ts +23 -2
  19. package/.nuxt/ui/context-menu.ts +56 -35
  20. package/.nuxt/ui/drawer.ts +33 -12
  21. package/.nuxt/ui/dropdown-menu.ts +57 -36
  22. package/.nuxt/ui/form-field.ts +29 -8
  23. package/.nuxt/ui/form.ts +23 -2
  24. package/.nuxt/ui/index.ts +1 -0
  25. package/.nuxt/ui/input-menu.ts +65 -44
  26. package/.nuxt/ui/input-number.ts +43 -22
  27. package/.nuxt/ui/input.ts +46 -25
  28. package/.nuxt/ui/kbd.ts +27 -6
  29. package/.nuxt/ui/link.ts +26 -5
  30. package/.nuxt/ui/modal.ts +28 -7
  31. package/.nuxt/ui/navigation-menu.ts +102 -83
  32. package/.nuxt/ui/pagination.ts +23 -2
  33. package/.nuxt/ui/pin-input.ts +43 -22
  34. package/.nuxt/ui/popover.ts +25 -4
  35. package/.nuxt/ui/progress.ts +40 -19
  36. package/.nuxt/ui/radio-group.ts +273 -37
  37. package/.nuxt/ui/select-menu.ts +59 -35
  38. package/.nuxt/ui/select.ts +55 -34
  39. package/.nuxt/ui/separator.ts +31 -10
  40. package/.nuxt/ui/skeleton.ts +24 -3
  41. package/.nuxt/ui/slideover.ts +27 -6
  42. package/.nuxt/ui/slider.ts +39 -18
  43. package/.nuxt/ui/stepper.ts +41 -20
  44. package/.nuxt/ui/switch.ts +43 -22
  45. package/.nuxt/ui/table.ts +38 -17
  46. package/.nuxt/ui/tabs.ts +55 -34
  47. package/.nuxt/ui/textarea.ts +63 -37
  48. package/.nuxt/ui/toast.ts +47 -26
  49. package/.nuxt/ui/toaster.ts +23 -2
  50. package/.nuxt/ui/tooltip.ts +25 -4
  51. package/.nuxt/ui/tree.ts +41 -20
  52. package/.nuxt/ui.css +56 -12
  53. package/README.md +11 -0
  54. package/cli/templates.mjs +18 -17
  55. package/dist/module.json +5 -5
  56. package/dist/module.mjs +11 -7
  57. package/dist/runtime/components/Accordion.vue +36 -93
  58. package/dist/runtime/components/Accordion.vue.d.ts +91 -0
  59. package/dist/runtime/components/Alert.vue +37 -100
  60. package/dist/runtime/components/Alert.vue.d.ts +96 -0
  61. package/dist/runtime/components/App.vue +28 -34
  62. package/dist/runtime/components/App.vue.d.ts +24 -0
  63. package/dist/runtime/components/Avatar.vue +42 -75
  64. package/dist/runtime/components/Avatar.vue.d.ts +60 -0
  65. package/dist/runtime/components/AvatarGroup.vue +40 -77
  66. package/dist/runtime/components/AvatarGroup.vue.d.ts +40 -0
  67. package/dist/runtime/components/Badge.vue +33 -62
  68. package/dist/runtime/components/Badge.vue.d.ts +62 -0
  69. package/dist/runtime/components/Breadcrumb.vue +37 -90
  70. package/dist/runtime/components/Breadcrumb.vue.d.ts +82 -0
  71. package/dist/runtime/components/Button.vue +95 -104
  72. package/dist/runtime/components/Button.vue.d.ts +73 -0
  73. package/dist/runtime/components/ButtonGroup.vue +20 -46
  74. package/dist/runtime/components/ButtonGroup.vue.d.ts +55 -0
  75. package/dist/runtime/components/Calendar.vue +67 -150
  76. package/dist/runtime/components/Calendar.vue.d.ts +107 -0
  77. package/dist/runtime/components/Card.vue +18 -40
  78. package/dist/runtime/components/Card.vue.d.ts +38 -0
  79. package/dist/runtime/components/Carousel.vue +112 -234
  80. package/dist/runtime/components/Carousel.vue.d.ts +120 -0
  81. package/dist/runtime/components/Checkbox.vue +52 -93
  82. package/dist/runtime/components/Checkbox.vue.d.ts +76 -0
  83. package/dist/runtime/components/CheckboxGroup.vue +121 -0
  84. package/dist/runtime/components/CheckboxGroup.vue.d.ts +75 -0
  85. package/dist/runtime/components/Chip.vue +26 -69
  86. package/dist/runtime/components/Chip.vue.d.ts +71 -0
  87. package/dist/runtime/components/Collapsible.vue +22 -41
  88. package/dist/runtime/components/Collapsible.vue.d.ts +50 -0
  89. package/dist/runtime/components/ColorPicker.vue +111 -197
  90. package/dist/runtime/components/ColorPicker.vue.d.ts +63 -0
  91. package/dist/runtime/components/CommandPalette.vue +96 -237
  92. package/dist/runtime/components/CommandPalette.vue.d.ts +173 -0
  93. package/dist/runtime/components/Container.vue +15 -28
  94. package/dist/runtime/components/Container.vue.d.ts +27 -0
  95. package/dist/runtime/components/ContextMenu.vue +34 -133
  96. package/dist/runtime/components/ContextMenu.vue.d.ts +127 -0
  97. package/dist/runtime/components/ContextMenuContent.vue +73 -81
  98. package/dist/runtime/components/ContextMenuContent.vue.d.ts +105 -0
  99. package/dist/runtime/components/Drawer.vue +49 -83
  100. package/dist/runtime/components/Drawer.vue.d.ts +88 -0
  101. package/dist/runtime/components/DropdownMenu.vue +39 -142
  102. package/dist/runtime/components/DropdownMenu.vue.d.ts +141 -0
  103. package/dist/runtime/components/DropdownMenuContent.vue +78 -88
  104. package/dist/runtime/components/DropdownMenuContent.vue.d.ts +55 -0
  105. package/dist/runtime/components/Form.vue +135 -220
  106. package/dist/runtime/components/Form.vue.d.ts +66 -0
  107. package/dist/runtime/components/FormField.vue +35 -77
  108. package/dist/runtime/components/FormField.vue.d.ts +70 -0
  109. package/dist/runtime/components/Icon.vue +12 -19
  110. package/dist/runtime/components/Icon.vue.d.ts +17 -0
  111. package/dist/runtime/components/Input.vue +82 -140
  112. package/dist/runtime/components/Input.vue.d.ts +91 -0
  113. package/dist/runtime/components/InputMenu.vue +185 -332
  114. package/dist/runtime/components/InputMenu.vue.d.ts +312 -0
  115. package/dist/runtime/components/InputNumber.vue +71 -133
  116. package/dist/runtime/components/InputNumber.vue.d.ts +193 -0
  117. package/dist/runtime/components/Kbd.vue +20 -46
  118. package/dist/runtime/components/Kbd.vue.d.ts +55 -0
  119. package/dist/runtime/components/Link.vue +98 -176
  120. package/dist/runtime/components/Link.vue.d.ts +124 -0
  121. package/dist/runtime/components/LinkBase.vue +33 -42
  122. package/dist/runtime/components/LinkBase.vue.d.ts +48 -0
  123. package/dist/runtime/components/Modal.vue +53 -116
  124. package/dist/runtime/components/Modal.vue.d.ts +109 -0
  125. package/dist/runtime/components/NavigationMenu.vue +77 -209
  126. package/dist/runtime/components/NavigationMenu.vue.d.ts +159 -0
  127. package/dist/runtime/components/OverlayProvider.vue +14 -18
  128. package/dist/runtime/components/OverlayProvider.vue.d.ts +2 -0
  129. package/dist/runtime/components/Pagination.vue +46 -140
  130. package/dist/runtime/components/Pagination.vue.d.ts +143 -0
  131. package/dist/runtime/components/PinInput.vue +61 -78
  132. package/dist/runtime/components/PinInput.vue.d.ts +68 -0
  133. package/dist/runtime/components/Popover.vue +47 -84
  134. package/dist/runtime/components/Popover.vue.d.ts +80 -0
  135. package/dist/runtime/components/Progress.vue +70 -131
  136. package/dist/runtime/components/Progress.vue.d.ts +97 -0
  137. package/dist/runtime/components/RadioGroup.vue +70 -132
  138. package/dist/runtime/components/RadioGroup.vue.d.ts +88 -0
  139. package/dist/runtime/components/Select.vue +110 -224
  140. package/dist/runtime/components/Select.vue.d.ts +139 -0
  141. package/dist/runtime/components/SelectMenu.vue +161 -310
  142. package/dist/runtime/components/SelectMenu.vue.d.ts +184 -0
  143. package/dist/runtime/components/Separator.vue +29 -71
  144. package/dist/runtime/components/Separator.vue.d.ts +75 -0
  145. package/dist/runtime/components/Skeleton.vue +21 -23
  146. package/dist/runtime/components/Skeleton.vue.d.ts +26 -0
  147. package/dist/runtime/components/Slideover.vue +53 -120
  148. package/dist/runtime/components/Slideover.vue.d.ts +111 -0
  149. package/dist/runtime/components/Slider.vue +46 -84
  150. package/dist/runtime/components/Slider.vue.d.ts +71 -0
  151. package/dist/runtime/components/Stepper.vue +45 -115
  152. package/dist/runtime/components/Stepper.vue.d.ts +89 -0
  153. package/dist/runtime/components/Switch.vue +45 -93
  154. package/dist/runtime/components/Switch.vue.d.ts +73 -0
  155. package/dist/runtime/components/Table.vue +163 -267
  156. package/dist/runtime/components/Table.vue.d.ts +183 -0
  157. package/dist/runtime/components/Tabs.vue +41 -107
  158. package/dist/runtime/components/Tabs.vue.d.ts +104 -0
  159. package/dist/runtime/components/Textarea.vue +113 -158
  160. package/dist/runtime/components/Textarea.vue.d.ts +95 -0
  161. package/dist/runtime/components/Toast.vue +49 -110
  162. package/dist/runtime/components/Toast.vue.d.ts +95 -0
  163. package/dist/runtime/components/Toaster.vue +70 -107
  164. package/dist/runtime/components/Toaster.vue.d.ts +63 -0
  165. package/dist/runtime/components/Tooltip.vue +38 -65
  166. package/dist/runtime/components/Tooltip.vue.d.ts +65 -0
  167. package/dist/runtime/components/Tree.vue +59 -166
  168. package/dist/runtime/components/Tree.vue.d.ts +128 -0
  169. package/dist/runtime/composables/defineShortcuts.d.ts +1 -1
  170. package/dist/runtime/composables/useAvatarGroup.d.ts +1 -1
  171. package/dist/runtime/composables/useButtonGroup.d.ts +2 -2
  172. package/dist/runtime/composables/useFormField.d.ts +2 -2
  173. package/dist/runtime/composables/useOverlay.d.ts +14 -7
  174. package/dist/runtime/composables/useOverlay.js +14 -6
  175. package/dist/runtime/composables/usePortal.d.ts +6 -0
  176. package/dist/runtime/composables/usePortal.js +17 -0
  177. package/dist/runtime/index.css +1 -1
  178. package/dist/runtime/inertia/components/Link.vue +146 -0
  179. package/dist/runtime/inertia/components/Link.vue.d.ts +92 -0
  180. package/dist/runtime/inertia/stubs.d.ts +43 -0
  181. package/dist/runtime/inertia/stubs.js +82 -0
  182. package/dist/runtime/locale/bg.d.ts +3 -0
  183. package/dist/runtime/locale/bg.js +54 -0
  184. package/dist/runtime/locale/index.d.ts +5 -1
  185. package/dist/runtime/locale/index.js +5 -1
  186. package/dist/runtime/locale/kk.d.ts +3 -0
  187. package/dist/runtime/locale/kk.js +54 -0
  188. package/dist/runtime/locale/tj.d.ts +3 -0
  189. package/dist/runtime/locale/tj.js +54 -0
  190. package/dist/runtime/locale/ug_cn.d.ts +3 -0
  191. package/dist/runtime/locale/ug_cn.js +55 -0
  192. package/dist/runtime/types/form.d.ts +4 -1
  193. package/dist/runtime/types/index.d.ts +1 -0
  194. package/dist/runtime/types/index.js +1 -0
  195. package/dist/runtime/types/utils.d.ts +47 -7
  196. package/dist/runtime/utils/link.d.ts +3 -3
  197. package/dist/runtime/utils/link.js +1 -0
  198. package/dist/runtime/utils/tv.js +2 -2
  199. package/dist/runtime/vue/components/Icon.vue +7 -8
  200. package/dist/runtime/vue/components/Icon.vue.d.ts +14 -0
  201. package/dist/runtime/vue/components/Link.vue +118 -202
  202. package/dist/runtime/vue/components/Link.vue.d.ts +124 -0
  203. package/dist/runtime/vue/stubs.d.ts +2 -2
  204. package/dist/shared/{ui.BkNUP964.mjs → ui.D7lOOabO.mjs} +621 -362
  205. package/dist/types.d.mts +3 -5
  206. package/dist/unplugin.d.mts +4 -0
  207. package/dist/unplugin.mjs +25 -4
  208. package/dist/vite.mjs +1 -1
  209. package/package.json +94 -53
  210. package/dist/module.cjs +0 -62
  211. package/dist/module.d.cts +0 -45
  212. package/dist/module.d.ts +0 -45
  213. package/dist/shared/ui.BL-XB3u1.cjs +0 -3555
  214. package/dist/types.d.ts +0 -7
  215. package/dist/unplugin.cjs +0 -232
  216. package/dist/unplugin.d.cts +0 -62
  217. package/dist/unplugin.d.ts +0 -62
  218. package/dist/vite.cjs +0 -23
  219. package/dist/vite.d.cts +0 -15
  220. package/dist/vite.d.ts +0 -15
@@ -1,293 +1,208 @@
1
- <script lang="ts">
2
- import type { AppConfig } from '@nuxt/schema'
3
- import _appConfig from '#build/app.config'
4
- import theme from '#build/ui/form'
5
- import { tv } from '../utils/tv'
6
- import type { FormSchema, FormError, FormInputEvents, FormErrorEvent, FormSubmitEvent, FormEvent, Form, FormErrorWithId } from '../types/form'
7
- import type { DeepReadonly } from 'vue'
8
-
9
- const appConfigForm = _appConfig as AppConfig & { ui: { form: Partial<typeof theme> } }
10
-
11
- const form = tv({ extend: tv(theme), ...(appConfigForm.ui?.form || {}) })
12
-
13
- export interface FormProps<T extends object> {
14
- id?: string | number
15
- /** Schema to validate the form state. Supports Standard Schema objects, Yup, Joi, and Superstructs. */
16
- schema?: FormSchema<T>
17
- /** An object representing the current state of the form. */
18
- state: Partial<T>
19
- /**
20
- * Custom validation function to validate the form state.
21
- * @param state - The current state of the form.
22
- * @returns A promise that resolves to an array of FormError objects, or an array of FormError objects directly.
23
- */
24
- validate?: (state: Partial<T>) => Promise<FormError[]> | FormError[]
25
- /**
26
- * The list of input events that trigger the form validation.
27
- * @defaultValue `['blur', 'change', 'input']`
28
- */
29
- validateOn?: FormInputEvents[]
30
- /** Disable all inputs inside the form. */
31
- disabled?: boolean
32
- /**
33
- * Delay in milliseconds before validating the form on input events.
34
- * @defaultValue `300`
35
- */
36
- validateOnInputDelay?: number
37
- /**
38
- * If true, schema transformations will be applied to the state on submit.
39
- * @defaultValue `true`
40
- */
41
- transform?: boolean
42
- class?: any
43
- onSubmit?: ((event: FormSubmitEvent<T>) => void | Promise<void>) | (() => void | Promise<void>)
44
- }
45
-
46
- export interface FormEmits<T extends object> {
47
- (e: 'submit', payload: FormSubmitEvent<T>): void
48
- (e: 'error', payload: FormErrorEvent): void
49
- }
50
-
51
- export interface FormSlots {
52
- default(props?: { errors: FormError[] }): any
53
- }
1
+ <script>
2
+ import theme from "#build/ui/form";
54
3
  </script>
55
4
 
56
- <script lang="ts" setup generic="T extends object">
57
- import { provide, inject, nextTick, ref, onUnmounted, onMounted, computed, useId, readonly } from 'vue'
58
- import { useEventBus } from '@vueuse/core'
59
- import { formOptionsInjectionKey, formInputsInjectionKey, formBusInjectionKey, formLoadingInjectionKey } from '../composables/useFormField'
60
- import { validateSchema } from '../utils/form'
61
- import { FormValidationException } from '../types/form'
62
-
63
- const props = withDefaults(defineProps<FormProps<T>>(), {
64
- validateOn() {
65
- return ['input', 'blur', 'change'] as FormInputEvents[]
66
- },
67
- validateOnInputDelay: 300,
68
- transform: true
69
- })
70
-
71
- const emits = defineEmits<FormEmits<T>>()
72
- defineSlots<FormSlots>()
73
-
74
- const formId = props.id ?? useId() as string
75
-
76
- const bus = useEventBus<FormEvent<T>>(`form-${formId}`)
77
- const parentBus = inject(
5
+ <script setup>
6
+ import { provide, inject, nextTick, ref, onUnmounted, onMounted, computed, useId, readonly } from "vue";
7
+ import { useEventBus } from "@vueuse/core";
8
+ import { useAppConfig } from "#imports";
9
+ import { formOptionsInjectionKey, formInputsInjectionKey, formBusInjectionKey, formLoadingInjectionKey } from "../composables/useFormField";
10
+ import { tv } from "../utils/tv";
11
+ import { validateSchema } from "../utils/form";
12
+ import { FormValidationException } from "../types/form";
13
+ const props = defineProps({
14
+ id: { type: [String, Number], required: false },
15
+ schema: { type: null, required: false },
16
+ state: { type: Object, required: true },
17
+ validate: { type: Function, required: false },
18
+ validateOn: { type: Array, required: false, default() {
19
+ return ["input", "blur", "change"];
20
+ } },
21
+ disabled: { type: Boolean, required: false },
22
+ validateOnInputDelay: { type: Number, required: false, default: 300 },
23
+ transform: { type: Boolean, required: false, default: true },
24
+ attach: { type: Boolean, required: false, default: true },
25
+ loadingAuto: { type: Boolean, required: false, default: true },
26
+ class: { type: null, required: false },
27
+ onSubmit: { type: Function, required: false }
28
+ });
29
+ const emits = defineEmits(["submit", "error"]);
30
+ defineSlots();
31
+ const appConfig = useAppConfig();
32
+ const ui = computed(() => tv({ extend: tv(theme), ...appConfig.ui?.form || {} }));
33
+ const formId = props.id ?? useId();
34
+ const bus = useEventBus(`form-${formId}`);
35
+ const parentBus = props.attach && inject(
78
36
  formBusInjectionKey,
79
- undefined
80
- )
81
-
82
- provide(formBusInjectionKey, bus)
83
-
84
- const nestedForms = ref<Map<string | number, { validate: typeof _validate }>>(new Map())
85
-
37
+ void 0
38
+ );
39
+ provide(formBusInjectionKey, bus);
40
+ const nestedForms = ref(/* @__PURE__ */ new Map());
86
41
  onMounted(async () => {
87
42
  bus.on(async (event) => {
88
- if (event.type === 'attach') {
89
- nestedForms.value.set(event.formId, { validate: event.validate })
90
- } else if (event.type === 'detach') {
91
- nestedForms.value.delete(event.formId)
43
+ if (event.type === "attach") {
44
+ nestedForms.value.set(event.formId, { validate: event.validate });
45
+ } else if (event.type === "detach") {
46
+ nestedForms.value.delete(event.formId);
92
47
  } else if (props.validateOn?.includes(event.type) && !loading.value) {
93
- if (event.type !== 'input') {
94
- await _validate({ name: event.name, silent: true, nested: false })
48
+ if (event.type !== "input") {
49
+ await _validate({ name: event.name, silent: true, nested: false });
95
50
  } else if (event.eager || blurredFields.has(event.name)) {
96
- await _validate({ name: event.name, silent: true, nested: false })
51
+ await _validate({ name: event.name, silent: true, nested: false });
97
52
  }
98
53
  }
99
-
100
- if (event.type === 'blur') {
101
- blurredFields.add(event.name)
54
+ if (event.type === "blur") {
55
+ blurredFields.add(event.name);
102
56
  }
103
-
104
- if (event.type === 'change' || event.type === 'input' || event.type === 'blur' || event.type === 'focus') {
105
- touchedFields.add(event.name)
57
+ if (event.type === "change" || event.type === "input" || event.type === "blur" || event.type === "focus") {
58
+ touchedFields.add(event.name);
106
59
  }
107
-
108
- if (event.type === 'change' || event.type === 'input') {
109
- dirtyFields.add(event.name)
60
+ if (event.type === "change" || event.type === "input") {
61
+ dirtyFields.add(event.name);
110
62
  }
111
- })
112
- })
113
-
63
+ });
64
+ });
114
65
  onUnmounted(() => {
115
- bus.reset()
116
- })
117
-
66
+ bus.reset();
67
+ });
118
68
  onMounted(async () => {
119
69
  if (parentBus) {
120
- await nextTick()
121
- parentBus.emit({ type: 'attach', validate: _validate, formId })
70
+ await nextTick();
71
+ parentBus.emit({ type: "attach", validate: _validate, formId });
122
72
  }
123
- })
124
-
73
+ });
125
74
  onUnmounted(() => {
126
75
  if (parentBus) {
127
- parentBus.emit({ type: 'detach', formId })
76
+ parentBus.emit({ type: "detach", formId });
128
77
  }
129
- })
130
-
131
- const errors = ref<FormErrorWithId[]>([])
132
- provide('form-errors', errors)
133
-
134
- const inputs = ref<{ [P in keyof T]?: { id?: string, pattern?: RegExp } }>({})
135
- provide(formInputsInjectionKey, inputs as any)
136
-
137
- const dirtyFields = new Set<keyof T>()
138
- const touchedFields = new Set<keyof T>()
139
- const blurredFields = new Set<keyof T>()
140
-
141
- function resolveErrorIds(errs: FormError[]): FormErrorWithId[] {
142
- return errs.map(err => ({
78
+ });
79
+ const errors = ref([]);
80
+ provide("form-errors", errors);
81
+ const inputs = ref({});
82
+ provide(formInputsInjectionKey, inputs);
83
+ const dirtyFields = /* @__PURE__ */ new Set();
84
+ const touchedFields = /* @__PURE__ */ new Set();
85
+ const blurredFields = /* @__PURE__ */ new Set();
86
+ function resolveErrorIds(errs) {
87
+ return errs.map((err) => ({
143
88
  ...err,
144
- id: err?.name ? inputs.value[err.name]?.id : undefined
145
- }))
89
+ id: err?.name ? inputs.value[err.name]?.id : void 0
90
+ }));
146
91
  }
147
-
148
- const transformedState = ref<T | null>(null)
149
-
150
- async function getErrors(): Promise<FormErrorWithId[]> {
151
- let errs = props.validate ? (await props.validate(props.state)) ?? [] : []
152
-
92
+ const transformedState = ref(null);
93
+ async function getErrors() {
94
+ let errs = props.validate ? await props.validate(props.state) ?? [] : [];
153
95
  if (props.schema) {
154
- const { errors, result } = await validateSchema(props.state, props.schema as FormSchema<typeof props.state>)
155
- if (errors) {
156
- errs = errs.concat(errors)
96
+ const { errors: errors2, result } = await validateSchema(props.state, props.schema);
97
+ if (errors2) {
98
+ errs = errs.concat(errors2);
157
99
  } else {
158
- transformedState.value = result
100
+ transformedState.value = result;
159
101
  }
160
102
  }
161
-
162
- return resolveErrorIds(errs)
103
+ return resolveErrorIds(errs);
163
104
  }
164
-
165
- async function _validate(opts: { name?: keyof T | (keyof T)[], silent?: boolean, nested?: boolean, transform?: boolean } = { silent: false, nested: true, transform: false }): Promise<T | false> {
166
- const names = opts.name && !Array.isArray(opts.name) ? [opts.name] : opts.name as (keyof T)[]
167
-
168
- const nestedValidatePromises = !names && opts.nested
169
- ? Array.from(nestedForms.value.values()).map(
170
- ({ validate }) => validate(opts).then(() => undefined).catch((error: Error) => {
171
- if (!(error instanceof FormValidationException)) {
172
- throw error
173
- }
174
- return error
175
- })
176
- )
177
- : []
178
-
105
+ async function _validate(opts = { silent: false, nested: true, transform: false }) {
106
+ const names = opts.name && !Array.isArray(opts.name) ? [opts.name] : opts.name;
107
+ const nestedValidatePromises = !names && opts.nested ? Array.from(nestedForms.value.values()).map(
108
+ ({ validate }) => validate(opts).then(() => void 0).catch((error) => {
109
+ if (!(error instanceof FormValidationException)) {
110
+ throw error;
111
+ }
112
+ return error;
113
+ })
114
+ ) : [];
179
115
  if (names) {
180
- const otherErrors = errors.value.filter(error => !names.some((name) => {
181
- const pattern = inputs.value?.[name]?.pattern
182
- return name === error.name || (pattern && error.name?.match(pattern))
183
- }))
184
-
185
- const pathErrors = (await getErrors()).filter(error => names.some((name) => {
186
- const pattern = inputs.value?.[name]?.pattern
187
- return name === error.name || (pattern && error.name?.match(pattern))
188
- }))
189
-
190
- errors.value = otherErrors.concat(pathErrors)
116
+ const otherErrors = errors.value.filter((error) => !names.some((name) => {
117
+ const pattern = inputs.value?.[name]?.pattern;
118
+ return name === error.name || pattern && error.name?.match(pattern);
119
+ }));
120
+ const pathErrors = (await getErrors()).filter((error) => names.some((name) => {
121
+ const pattern = inputs.value?.[name]?.pattern;
122
+ return name === error.name || pattern && error.name?.match(pattern);
123
+ }));
124
+ errors.value = otherErrors.concat(pathErrors);
191
125
  } else {
192
- errors.value = await getErrors()
126
+ errors.value = await getErrors();
193
127
  }
194
-
195
- const childErrors = (await Promise.all(nestedValidatePromises)).filter(val => val !== undefined)
196
-
128
+ const childErrors = (await Promise.all(nestedValidatePromises)).filter((val) => val !== void 0);
197
129
  if (errors.value.length + childErrors.length > 0) {
198
- if (opts.silent) return false
199
- throw new FormValidationException(formId, errors.value, childErrors)
130
+ if (opts.silent) return false;
131
+ throw new FormValidationException(formId, errors.value, childErrors);
200
132
  }
201
-
202
133
  if (opts.transform) {
203
- Object.assign(props.state, transformedState.value)
134
+ Object.assign(props.state, transformedState.value);
204
135
  }
205
-
206
- return props.state as T
136
+ return props.state;
207
137
  }
208
-
209
- const loading = ref(false)
210
- provide(formLoadingInjectionKey, readonly(loading))
211
-
212
- async function onSubmitWrapper(payload: Event) {
213
- loading.value = true
214
-
215
- const event = payload as FormSubmitEvent<any>
216
-
138
+ const loading = ref(false);
139
+ provide(formLoadingInjectionKey, readonly(loading));
140
+ async function onSubmitWrapper(payload) {
141
+ loading.value = props.loadingAuto && true;
142
+ const event = payload;
217
143
  try {
218
- event.data = await _validate({ nested: true, transform: props.transform })
219
- await props.onSubmit?.(event)
220
- dirtyFields.clear()
144
+ event.data = await _validate({ nested: true, transform: props.transform });
145
+ await props.onSubmit?.(event);
146
+ dirtyFields.clear();
221
147
  } catch (error) {
222
148
  if (!(error instanceof FormValidationException)) {
223
- throw error
149
+ throw error;
224
150
  }
225
-
226
- const errorEvent: FormErrorEvent = {
151
+ const errorEvent = {
227
152
  ...event,
228
153
  errors: error.errors,
229
154
  children: error.children
230
- }
231
- emits('error', errorEvent)
155
+ };
156
+ emits("error", errorEvent);
232
157
  } finally {
233
- loading.value = false
158
+ loading.value = false;
234
159
  }
235
160
  }
236
-
237
- const disabled = computed(() => props.disabled || loading.value)
238
-
161
+ const disabled = computed(() => props.disabled || loading.value);
239
162
  provide(formOptionsInjectionKey, computed(() => ({
240
163
  disabled: disabled.value,
241
164
  validateOnInputDelay: props.validateOnInputDelay
242
- })))
243
-
244
- defineExpose<Form<T>>({
165
+ })));
166
+ defineExpose({
245
167
  validate: _validate,
246
168
  errors,
247
-
248
- setErrors(errs: FormError[], name?: keyof T) {
169
+ setErrors(errs, name) {
249
170
  if (name) {
250
- errors.value = errors.value
251
- .filter(error => error.name !== name)
252
- .concat(resolveErrorIds(errs))
171
+ errors.value = errors.value.filter((error) => error.name !== name).concat(resolveErrorIds(errs));
253
172
  } else {
254
- errors.value = resolveErrorIds(errs)
173
+ errors.value = resolveErrorIds(errs);
255
174
  }
256
175
  },
257
-
258
176
  async submit() {
259
- await onSubmitWrapper(new Event('submit'))
177
+ await onSubmitWrapper(new Event("submit"));
260
178
  },
261
-
262
- getErrors(name?: keyof T) {
179
+ getErrors(name) {
263
180
  if (name) {
264
- return errors.value.filter(err => err.name === name)
181
+ return errors.value.filter((err) => err.name === name);
265
182
  }
266
- return errors.value
183
+ return errors.value;
267
184
  },
268
-
269
- clear(name?: string) {
185
+ clear(name) {
270
186
  if (name) {
271
- errors.value = errors.value.filter(err => err.name !== name)
187
+ errors.value = errors.value.filter((err) => err.name !== name);
272
188
  } else {
273
- errors.value = []
189
+ errors.value = [];
274
190
  }
275
191
  },
276
-
277
192
  disabled,
193
+ loading,
278
194
  dirty: computed(() => !!dirtyFields.size),
279
-
280
- dirtyFields: readonly(dirtyFields) as DeepReadonly<Set<keyof T>>,
281
- blurredFields: readonly(blurredFields) as DeepReadonly<Set<keyof T>>,
282
- touchedFields: readonly(touchedFields) as DeepReadonly<Set<keyof T>>
283
- })
195
+ dirtyFields: readonly(dirtyFields),
196
+ blurredFields: readonly(blurredFields),
197
+ touchedFields: readonly(touchedFields)
198
+ });
284
199
  </script>
285
200
 
286
201
  <template>
287
202
  <component
288
203
  :is="parentBus ? 'div' : 'form'"
289
204
  :id="formId"
290
- :class="form({ class: props.class })"
205
+ :class="ui({ class: props.class })"
291
206
  @submit.prevent="onSubmitWrapper"
292
207
  >
293
208
  <slot :errors="errors" />
@@ -0,0 +1,66 @@
1
+ import type { FormSchema, FormError, FormInputEvents, FormErrorEvent, FormSubmitEvent, Form, InferInput, InferOutput } from '../types/form';
2
+ export interface FormProps<S extends FormSchema> {
3
+ id?: string | number;
4
+ /** Schema to validate the form state. Supports Standard Schema objects, Yup, Joi, and Superstructs. */
5
+ schema?: S;
6
+ /** An object representing the current state of the form. */
7
+ state: Partial<InferInput<S>>;
8
+ /**
9
+ * Custom validation function to validate the form state.
10
+ * @param state - The current state of the form.
11
+ * @returns A promise that resolves to an array of FormError objects, or an array of FormError objects directly.
12
+ */
13
+ validate?: (state: Partial<InferInput<S>>) => Promise<FormError[]> | FormError[];
14
+ /**
15
+ * The list of input events that trigger the form validation.
16
+ * @defaultValue `['blur', 'change', 'input']`
17
+ */
18
+ validateOn?: FormInputEvents[];
19
+ /** Disable all inputs inside the form. */
20
+ disabled?: boolean;
21
+ /**
22
+ * Delay in milliseconds before validating the form on input events.
23
+ * @defaultValue `300`
24
+ */
25
+ validateOnInputDelay?: number;
26
+ /**
27
+ * If true, schema transformations will be applied to the state on submit.
28
+ * @defaultValue `true`
29
+ */
30
+ transform?: boolean;
31
+ /**
32
+ * If true, this form will attach to its parent Form (if any) and validate at the same time.
33
+ * @defaultValue `true`
34
+ */
35
+ attach?: boolean;
36
+ /**
37
+ * When `true`, all form elements will be disabled on `@submit` event.
38
+ * This will cause any focused input elements to lose their focus state.
39
+ * @defaultValue `true`
40
+ */
41
+ loadingAuto?: boolean;
42
+ class?: any;
43
+ onSubmit?: ((event: FormSubmitEvent<InferOutput<S>>) => void | Promise<void>) | (() => void | Promise<void>);
44
+ }
45
+ export interface FormEmits<S extends FormSchema> {
46
+ (e: 'submit', payload: FormSubmitEvent<InferOutput<S>>): void;
47
+ (e: 'error', payload: FormErrorEvent): void;
48
+ }
49
+ export interface FormSlots {
50
+ default(props?: {
51
+ errors: FormError[];
52
+ }): any;
53
+ }
54
+ declare const _default: <S extends FormSchema>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
55
+ props: __VLS_PrettifyLocal<any & FormProps<S> & Partial<{}>> & (import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps);
56
+ expose(exposed: import("vue").ShallowUnwrapRef<Form<InferInput<S>>>): void;
57
+ attrs: any;
58
+ slots: Readonly<FormSlots> & FormSlots;
59
+ emit: FormEmits<S>;
60
+ }>) => import("vue").VNode & {
61
+ __ctx?: Awaited<typeof __VLS_setup>;
62
+ };
63
+ export default _default;
64
+ type __VLS_PrettifyLocal<T> = {
65
+ [K in keyof T]: T[K];
66
+ } & {};
@@ -1,82 +1,40 @@
1
- <script lang="ts">
2
- import type { VariantProps } from 'tailwind-variants'
3
- import type { AppConfig } from '@nuxt/schema'
4
- import _appConfig from '#build/app.config'
5
- import theme from '#build/ui/form-field'
6
- import { tv } from '../utils/tv'
7
-
8
- const appConfigFormField = _appConfig as AppConfig & { ui: { formField: Partial<typeof theme> } }
9
-
10
- const formField = tv({ extend: tv(theme), ...(appConfigFormField.ui?.formField || {}) })
11
-
12
- type FormFieldVariants = VariantProps<typeof formField>
13
-
14
- export interface FormFieldProps {
15
- /**
16
- * The element or component this component should render as.
17
- * @defaultValue 'div'
18
- */
19
- as?: any
20
- /** The name of the FormField. Also used to match form errors. */
21
- name?: string
22
- /** A regular expression to match form error names. */
23
- errorPattern?: RegExp
24
- label?: string
25
- description?: string
26
- help?: string
27
- error?: string | boolean
28
- hint?: string
29
- /**
30
- * @defaultValue 'md'
31
- */
32
- size?: FormFieldVariants['size']
33
- required?: boolean
34
- /** If true, validation on input will be active immediately instead of waiting for a blur event. */
35
- eagerValidation?: boolean
36
- /**
37
- * Delay in milliseconds before validating the form on input events.
38
- * @defaultValue `300`
39
- */
40
- validateOnInputDelay?: number
41
- class?: any
42
- ui?: Partial<typeof formField.slots>
43
- }
44
-
45
- export interface FormFieldSlots {
46
- label(props: { label?: string }): any
47
- hint(props: { hint?: string }): any
48
- description(props: { description?: string }): any
49
- help(props: { help?: string }): any
50
- error(props: { error?: string | boolean }): any
51
- default(props: { error?: string | boolean }): any
52
- }
1
+ <script>
2
+ import theme from "#build/ui/form-field";
53
3
  </script>
54
4
 
55
- <script setup lang="ts">
56
- import { computed, ref, inject, provide, type Ref, useId } from 'vue'
57
- import { Primitive, Label } from 'reka-ui'
58
- import { formFieldInjectionKey, inputIdInjectionKey } from '../composables/useFormField'
59
- import type { FormError, FormFieldInjectedOptions } from '../types/form'
60
-
61
- const props = defineProps<FormFieldProps>()
62
- const slots = defineSlots<FormFieldSlots>()
63
-
64
- const ui = computed(() => formField({
5
+ <script setup>
6
+ import { computed, ref, inject, provide, useId } from "vue";
7
+ import { Primitive, Label } from "reka-ui";
8
+ import { useAppConfig } from "#imports";
9
+ import { formFieldInjectionKey, inputIdInjectionKey } from "../composables/useFormField";
10
+ import { tv } from "../utils/tv";
11
+ const props = defineProps({
12
+ as: { type: null, required: false },
13
+ name: { type: String, required: false },
14
+ errorPattern: { type: null, required: false },
15
+ label: { type: String, required: false },
16
+ description: { type: String, required: false },
17
+ help: { type: String, required: false },
18
+ error: { type: [String, Boolean], required: false },
19
+ hint: { type: String, required: false },
20
+ size: { type: null, required: false },
21
+ required: { type: Boolean, required: false },
22
+ eagerValidation: { type: Boolean, required: false },
23
+ validateOnInputDelay: { type: Number, required: false },
24
+ class: { type: null, required: false },
25
+ ui: { type: null, required: false }
26
+ });
27
+ const slots = defineSlots();
28
+ const appConfig = useAppConfig();
29
+ const ui = computed(() => tv({ extend: tv(theme), ...appConfig.ui?.formField || {} })({
65
30
  size: props.size,
66
31
  required: props.required
67
- }))
68
-
69
- const formErrors = inject<Ref<FormError[]> | null>('form-errors', null)
70
-
71
- const error = computed(() => props.error || formErrors?.value?.find(error => error.name && (error.name === props.name || (props.errorPattern && error.name.match(props.errorPattern))))?.message)
72
-
73
- const id = ref(useId())
74
- // Copies id's initial value to bind aria-attributes such as aria-describedby.
75
- // This is required for the RadioGroup component which unsets the id value.
76
- const ariaId = id.value
77
-
78
- provide(inputIdInjectionKey, id)
79
-
32
+ }));
33
+ const formErrors = inject("form-errors", null);
34
+ const error = computed(() => props.error || formErrors?.value?.find((error2) => error2.name && (error2.name === props.name || props.errorPattern && error2.name.match(props.errorPattern)))?.message);
35
+ const id = ref(useId());
36
+ const ariaId = id.value;
37
+ provide(inputIdInjectionKey, id);
80
38
  provide(formFieldInjectionKey, computed(() => ({
81
39
  error: error.value,
82
40
  name: props.name,
@@ -88,7 +46,7 @@ provide(formFieldInjectionKey, computed(() => ({
88
46
  description: props.description,
89
47
  help: props.help,
90
48
  ariaId
91
- }) as FormFieldInjectedOptions<FormFieldProps>))
49
+ })));
92
50
  </script>
93
51
 
94
52
  <template>
@@ -117,7 +75,7 @@ provide(formFieldInjectionKey, computed(() => ({
117
75
  <div :class="[(label || !!slots.label || description || !!slots.description) && ui.container({ class: props.ui?.container })]">
118
76
  <slot :error="error" />
119
77
 
120
- <p v-if="(typeof error === 'string' && error) || !!slots.error" :id="`${ariaId}-error`" :class="ui.error({ class: props.ui?.error })">
78
+ <p v-if="typeof error === 'string' && error || !!slots.error" :id="`${ariaId}-error`" :class="ui.error({ class: props.ui?.error })">
121
79
  <slot name="error" :error="error">
122
80
  {{ error }}
123
81
  </slot>