@bitrix24/b24ui-nuxt 0.5.11 → 0.6.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.
- package/.nuxt/b24ui/input-menu.ts +2 -2
- package/.nuxt/b24ui/select-menu.ts +4 -4
- package/.nuxt/b24ui/select.ts +2 -2
- package/dist/meta.d.mts +5208 -5061
- package/dist/meta.mjs +5208 -5061
- package/dist/module.json +3 -3
- package/dist/module.mjs +2 -2
- package/dist/runtime/components/Advice.vue +27 -54
- package/dist/runtime/components/Advice.vue.d.ts +170 -0
- package/dist/runtime/components/Alert.vue +35 -96
- package/dist/runtime/components/Alert.vue.d.ts +464 -0
- package/dist/runtime/components/App.vue +24 -34
- package/dist/runtime/components/App.vue.d.ts +23 -0
- package/dist/runtime/components/Avatar.vue +43 -81
- package/dist/runtime/components/Avatar.vue.d.ts +281 -0
- package/dist/runtime/components/AvatarGroup.vue +40 -76
- package/dist/runtime/components/AvatarGroup.vue.d.ts +204 -0
- package/dist/runtime/components/Badge.vue +40 -83
- package/dist/runtime/components/Badge.vue.d.ts +517 -0
- package/dist/runtime/components/Button.vue +96 -155
- package/dist/runtime/components/Button.vue.d.ts +640 -0
- package/dist/runtime/components/ButtonGroup.vue +19 -51
- package/dist/runtime/components/ButtonGroup.vue.d.ts +116 -0
- package/dist/runtime/components/Calendar.vue +73 -152
- package/dist/runtime/components/Calendar.vue.d.ts +437 -0
- package/dist/runtime/components/Checkbox.vue +42 -73
- package/dist/runtime/components/Checkbox.vue.d.ts +354 -0
- package/dist/runtime/components/Chip.vue +26 -74
- package/dist/runtime/components/Chip.vue.d.ts +271 -0
- package/dist/runtime/components/Collapsible.vue +22 -41
- package/dist/runtime/components/Collapsible.vue.d.ts +118 -0
- package/dist/runtime/components/Container.vue +13 -27
- package/dist/runtime/components/Container.vue.d.ts +27 -0
- package/dist/runtime/components/Countdown.vue +153 -378
- package/dist/runtime/components/Countdown.vue.d.ts +356 -0
- package/dist/runtime/components/DescriptionList.vue +78 -149
- package/dist/runtime/components/DescriptionList.vue.d.ts +379 -0
- package/dist/runtime/components/DropdownMenu.vue +38 -139
- package/dist/runtime/components/DropdownMenu.vue.d.ts +533 -0
- package/dist/runtime/components/DropdownMenuContent.vue +68 -80
- package/dist/runtime/components/DropdownMenuContent.vue.d.ts +228 -0
- package/dist/runtime/components/Form.vue +130 -217
- package/dist/runtime/components/Form.vue.d.ts +55 -0
- package/dist/runtime/components/FormField.vue +36 -80
- package/dist/runtime/components/FormField.vue.d.ts +282 -0
- package/dist/runtime/components/Input.vue +79 -179
- package/dist/runtime/components/Input.vue.d.ts +755 -0
- package/dist/runtime/components/InputMenu.vue +185 -381
- package/dist/runtime/components/InputMenu.vue.d.ts +1523 -0
- package/dist/runtime/components/InputNumber.vue +77 -175
- package/dist/runtime/components/InputNumber.vue.d.ts +658 -0
- package/dist/runtime/components/Kbd.vue +18 -45
- package/dist/runtime/components/Kbd.vue.d.ts +109 -0
- package/dist/runtime/components/Link.vue +92 -173
- package/dist/runtime/components/Link.vue.d.ts +129 -0
- package/dist/runtime/components/LinkBase.vue +33 -42
- package/dist/runtime/components/LinkBase.vue.d.ts +48 -0
- package/dist/runtime/components/Modal.vue +48 -127
- package/dist/runtime/components/Modal.vue.d.ts +327 -0
- package/dist/runtime/components/ModalDialogClose.vue +5 -8
- package/dist/runtime/components/ModalDialogClose.vue.d.ts +10 -0
- package/dist/runtime/components/Navbar.vue +15 -33
- package/dist/runtime/components/Navbar.vue.d.ts +101 -0
- package/dist/runtime/components/NavbarDivider.vue +15 -33
- package/dist/runtime/components/NavbarDivider.vue.d.ts +101 -0
- package/dist/runtime/components/NavbarSection.vue +15 -33
- package/dist/runtime/components/NavbarSection.vue.d.ts +101 -0
- package/dist/runtime/components/NavbarSpacer.vue +15 -33
- package/dist/runtime/components/NavbarSpacer.vue.d.ts +101 -0
- package/dist/runtime/components/NavigationMenu.vue +74 -208
- package/dist/runtime/components/NavigationMenu.vue.d.ts +824 -0
- package/dist/runtime/components/OverlayProvider.vue +14 -18
- package/dist/runtime/components/OverlayProvider.vue.d.ts +2 -0
- package/dist/runtime/components/Popover.vue +40 -81
- package/dist/runtime/components/Popover.vue.d.ts +147 -0
- package/dist/runtime/components/Progress.vue +70 -136
- package/dist/runtime/components/Progress.vue.d.ts +592 -0
- package/dist/runtime/components/RadioGroup.vue +59 -134
- package/dist/runtime/components/RadioGroup.vue.d.ts +723 -0
- package/dist/runtime/components/Range.vue +46 -85
- package/dist/runtime/components/Range.vue.d.ts +417 -0
- package/dist/runtime/components/Select.vue +110 -260
- package/dist/runtime/components/Select.vue.d.ts +1201 -0
- package/dist/runtime/components/SelectMenu.vue +161 -347
- package/dist/runtime/components/SelectMenu.vue.d.ts +1298 -0
- package/dist/runtime/components/Separator.vue +28 -71
- package/dist/runtime/components/Separator.vue.d.ts +400 -0
- package/dist/runtime/components/Sidebar.vue +15 -33
- package/dist/runtime/components/Sidebar.vue.d.ts +101 -0
- package/dist/runtime/components/SidebarBody.vue +17 -38
- package/dist/runtime/components/SidebarBody.vue.d.ts +90 -0
- package/dist/runtime/components/SidebarFooter.vue +15 -33
- package/dist/runtime/components/SidebarFooter.vue.d.ts +101 -0
- package/dist/runtime/components/SidebarHeader.vue +15 -33
- package/dist/runtime/components/SidebarHeader.vue.d.ts +101 -0
- package/dist/runtime/components/SidebarHeading.vue +15 -33
- package/dist/runtime/components/SidebarHeading.vue.d.ts +101 -0
- package/dist/runtime/components/SidebarLayout.vue +34 -70
- package/dist/runtime/components/SidebarLayout.vue.d.ts +222 -0
- package/dist/runtime/components/SidebarSection.vue +15 -33
- package/dist/runtime/components/SidebarSection.vue.d.ts +101 -0
- package/dist/runtime/components/SidebarSpacer.vue +15 -33
- package/dist/runtime/components/SidebarSpacer.vue.d.ts +101 -0
- package/dist/runtime/components/Skeleton.vue +12 -22
- package/dist/runtime/components/Skeleton.vue.d.ts +26 -0
- package/dist/runtime/components/Slideover.vue +50 -131
- package/dist/runtime/components/Slideover.vue.d.ts +360 -0
- package/dist/runtime/components/StackedLayout.vue +34 -73
- package/dist/runtime/components/StackedLayout.vue.d.ts +192 -0
- package/dist/runtime/components/Switch.vue +46 -95
- package/dist/runtime/components/Switch.vue.d.ts +587 -0
- package/dist/runtime/components/Tabs.vue +37 -105
- package/dist/runtime/components/Tabs.vue.d.ts +453 -0
- package/dist/runtime/components/Textarea.vue +92 -201
- package/dist/runtime/components/Textarea.vue.d.ts +601 -0
- package/dist/runtime/components/Toast.vue +47 -105
- package/dist/runtime/components/Toast.vue.d.ts +438 -0
- package/dist/runtime/components/Toaster.vue +70 -115
- package/dist/runtime/components/Toaster.vue.d.ts +219 -0
- package/dist/runtime/components/Tooltip.vue +36 -64
- package/dist/runtime/components/Tooltip.vue.d.ts +186 -0
- package/dist/runtime/components/content/TableWrapper.vue +24 -70
- package/dist/runtime/components/content/TableWrapper.vue.d.ts +237 -0
- package/dist/runtime/composables/useAvatarGroup.d.ts +1 -1
- package/dist/runtime/composables/useButtonGroup.d.ts +2 -2
- package/dist/runtime/composables/useComponentIcons.d.ts +3 -3
- package/dist/runtime/composables/useFormField.d.ts +2 -2
- package/dist/runtime/composables/useOverlay.d.ts +14 -7
- package/dist/runtime/composables/useOverlay.js +14 -6
- package/dist/runtime/prose/A.vue +12 -23
- package/dist/runtime/prose/A.vue.d.ts +84 -0
- package/dist/runtime/prose/Blockquote.vue +12 -23
- package/dist/runtime/prose/Blockquote.vue.d.ts +84 -0
- package/dist/runtime/prose/Code.vue +14 -31
- package/dist/runtime/prose/Code.vue.d.ts +97 -0
- package/dist/runtime/prose/Em.vue +12 -23
- package/dist/runtime/prose/Em.vue.d.ts +84 -0
- package/dist/runtime/prose/H1.vue +12 -23
- package/dist/runtime/prose/H1.vue.d.ts +97 -0
- package/dist/runtime/prose/H2.vue +12 -23
- package/dist/runtime/prose/H2.vue.d.ts +123 -0
- package/dist/runtime/prose/H3.vue +12 -23
- package/dist/runtime/prose/H3.vue.d.ts +123 -0
- package/dist/runtime/prose/H4.vue +12 -23
- package/dist/runtime/prose/H4.vue.d.ts +123 -0
- package/dist/runtime/prose/H5.vue +12 -23
- package/dist/runtime/prose/H5.vue.d.ts +123 -0
- package/dist/runtime/prose/H6.vue +12 -23
- package/dist/runtime/prose/H6.vue.d.ts +123 -0
- package/dist/runtime/prose/Hr.vue +12 -19
- package/dist/runtime/prose/Hr.vue.d.ts +74 -0
- package/dist/runtime/prose/Img.vue +12 -23
- package/dist/runtime/prose/Img.vue.d.ts +77 -0
- package/dist/runtime/prose/Li.vue +12 -23
- package/dist/runtime/prose/Li.vue.d.ts +84 -0
- package/dist/runtime/prose/Ol.vue +12 -23
- package/dist/runtime/prose/Ol.vue.d.ts +84 -0
- package/dist/runtime/prose/P.vue +12 -23
- package/dist/runtime/prose/P.vue.d.ts +84 -0
- package/dist/runtime/prose/Pre.vue +16 -33
- package/dist/runtime/prose/Pre.vue.d.ts +117 -0
- package/dist/runtime/prose/Strong.vue +12 -23
- package/dist/runtime/prose/Strong.vue.d.ts +84 -0
- package/dist/runtime/prose/Table.vue +19 -54
- package/dist/runtime/prose/Table.vue.d.ts +144 -0
- package/dist/runtime/prose/Tbody.vue +12 -23
- package/dist/runtime/prose/Tbody.vue.d.ts +84 -0
- package/dist/runtime/prose/Td.vue +12 -23
- package/dist/runtime/prose/Td.vue.d.ts +84 -0
- package/dist/runtime/prose/Th.vue +12 -23
- package/dist/runtime/prose/Th.vue.d.ts +84 -0
- package/dist/runtime/prose/Thead.vue +12 -23
- package/dist/runtime/prose/Thead.vue.d.ts +84 -0
- package/dist/runtime/prose/Tr.vue +12 -23
- package/dist/runtime/prose/Tr.vue.d.ts +84 -0
- package/dist/runtime/prose/Ul.vue +12 -23
- package/dist/runtime/prose/Ul.vue.d.ts +84 -0
- package/dist/runtime/utils/link.d.ts +3 -3
- package/dist/runtime/vue/components/Link.vue +115 -202
- package/dist/runtime/vue/components/Link.vue.d.ts +129 -0
- package/dist/shared/{b24ui-nuxt.CS9Lf0os.mjs → b24ui-nuxt.BA6Y2FnC.mjs} +6 -6
- package/dist/types.d.mts +3 -5
- package/dist/unplugin.mjs +1 -1
- package/dist/vite.mjs +1 -1
- package/package.json +14 -22
- package/dist/meta.cjs +0 -72112
- package/dist/meta.d.cts +0 -72110
- package/dist/meta.d.ts +0 -72110
- package/dist/module.cjs +0 -63
- package/dist/module.d.cts +0 -15
- package/dist/module.d.ts +0 -15
- package/dist/shared/b24ui-nuxt.DrKwIWoc.cjs +0 -7721
- package/dist/types.d.ts +0 -7
- package/dist/unplugin.cjs +0 -236
- package/dist/unplugin.d.cts +0 -33
- package/dist/unplugin.d.ts +0 -33
- package/dist/vite.cjs +0 -21
- package/dist/vite.d.cts +0 -14
- package/dist/vite.d.ts +0 -14
|
@@ -1,285 +1,198 @@
|
|
|
1
|
-
<script
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import type { DeepReadonly } from 'vue'
|
|
8
|
-
|
|
9
|
-
const appConfigForm = _appConfig as AppConfig & { b24ui: { form: Partial<typeof theme> } }
|
|
10
|
-
|
|
11
|
-
const form = tv({ extend: tv(theme), ...(appConfigForm.b24ui?.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 _appConfig from "#build/app.config";
|
|
3
|
+
import theme from "#build/b24ui/form";
|
|
4
|
+
import { tv } from "../utils/tv";
|
|
5
|
+
const appConfigForm = _appConfig;
|
|
6
|
+
const form = tv({ extend: tv(theme), ...appConfigForm.b24ui?.form || {} });
|
|
54
7
|
</script>
|
|
55
8
|
|
|
56
|
-
<script
|
|
57
|
-
import { provide, inject, nextTick, ref, onUnmounted, onMounted, computed, useId, readonly } from
|
|
58
|
-
import { useEventBus } from
|
|
59
|
-
import { formOptionsInjectionKey, formInputsInjectionKey, formBusInjectionKey, formLoadingInjectionKey } from
|
|
60
|
-
import { validateSchema } from
|
|
61
|
-
import { FormValidationException } from
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
9
|
+
<script setup>
|
|
10
|
+
import { provide, inject, nextTick, ref, onUnmounted, onMounted, computed, useId, readonly } from "vue";
|
|
11
|
+
import { useEventBus } from "@vueuse/core";
|
|
12
|
+
import { formOptionsInjectionKey, formInputsInjectionKey, formBusInjectionKey, formLoadingInjectionKey } from "../composables/useFormField";
|
|
13
|
+
import { validateSchema } from "../utils/form";
|
|
14
|
+
import { FormValidationException } from "../types/form";
|
|
15
|
+
const props = defineProps({
|
|
16
|
+
id: { type: [String, Number], required: false },
|
|
17
|
+
schema: { type: null, required: false },
|
|
18
|
+
state: { type: Object, required: true },
|
|
19
|
+
validate: { type: Function, required: false },
|
|
20
|
+
validateOn: { type: Array, required: false, default() {
|
|
21
|
+
return ["input", "blur", "change"];
|
|
22
|
+
} },
|
|
23
|
+
disabled: { type: Boolean, required: false },
|
|
24
|
+
validateOnInputDelay: { type: Number, required: false, default: 300 },
|
|
25
|
+
transform: { 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 formId = props.id ?? useId();
|
|
32
|
+
const bus = useEventBus(`form-${formId}`);
|
|
76
33
|
const parentBus = inject(
|
|
77
34
|
formBusInjectionKey,
|
|
78
|
-
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const nestedForms = ref<Map<string | number, { validate: typeof _validate }>>(new Map())
|
|
84
|
-
|
|
35
|
+
void 0
|
|
36
|
+
);
|
|
37
|
+
provide(formBusInjectionKey, bus);
|
|
38
|
+
const nestedForms = ref(/* @__PURE__ */ new Map());
|
|
85
39
|
onMounted(async () => {
|
|
86
40
|
bus.on(async (event) => {
|
|
87
|
-
if (event.type ===
|
|
88
|
-
nestedForms.value.set(event.formId, { validate: event.validate })
|
|
89
|
-
} else if (event.type ===
|
|
90
|
-
nestedForms.value.delete(event.formId)
|
|
41
|
+
if (event.type === "attach") {
|
|
42
|
+
nestedForms.value.set(event.formId, { validate: event.validate });
|
|
43
|
+
} else if (event.type === "detach") {
|
|
44
|
+
nestedForms.value.delete(event.formId);
|
|
91
45
|
} else if (props.validateOn?.includes(event.type) && !loading.value) {
|
|
92
|
-
if (event.type !==
|
|
93
|
-
await _validate({ name: event.name, silent: true, nested: false })
|
|
46
|
+
if (event.type !== "input") {
|
|
47
|
+
await _validate({ name: event.name, silent: true, nested: false });
|
|
94
48
|
} else if (event.eager || blurredFields.has(event.name)) {
|
|
95
|
-
await _validate({ name: event.name, silent: true, nested: false })
|
|
49
|
+
await _validate({ name: event.name, silent: true, nested: false });
|
|
96
50
|
}
|
|
97
51
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
blurredFields.add(event.name)
|
|
52
|
+
if (event.type === "blur") {
|
|
53
|
+
blurredFields.add(event.name);
|
|
101
54
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
touchedFields.add(event.name)
|
|
55
|
+
if (event.type === "change" || event.type === "input" || event.type === "blur" || event.type === "focus") {
|
|
56
|
+
touchedFields.add(event.name);
|
|
105
57
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
dirtyFields.add(event.name)
|
|
58
|
+
if (event.type === "change" || event.type === "input") {
|
|
59
|
+
dirtyFields.add(event.name);
|
|
109
60
|
}
|
|
110
|
-
})
|
|
111
|
-
})
|
|
112
|
-
|
|
61
|
+
});
|
|
62
|
+
});
|
|
113
63
|
onUnmounted(() => {
|
|
114
|
-
bus.reset()
|
|
115
|
-
})
|
|
116
|
-
|
|
64
|
+
bus.reset();
|
|
65
|
+
});
|
|
117
66
|
onMounted(async () => {
|
|
118
67
|
if (parentBus) {
|
|
119
|
-
await nextTick()
|
|
120
|
-
parentBus.emit({ type:
|
|
68
|
+
await nextTick();
|
|
69
|
+
parentBus.emit({ type: "attach", validate: _validate, formId });
|
|
121
70
|
}
|
|
122
|
-
})
|
|
123
|
-
|
|
71
|
+
});
|
|
124
72
|
onUnmounted(() => {
|
|
125
73
|
if (parentBus) {
|
|
126
|
-
parentBus.emit({ type:
|
|
74
|
+
parentBus.emit({ type: "detach", formId });
|
|
127
75
|
}
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const blurredFields = new Set<keyof T>()
|
|
139
|
-
|
|
140
|
-
function resolveErrorIds(errs: FormError[]): FormErrorWithId[] {
|
|
141
|
-
return errs.map(err => ({
|
|
76
|
+
});
|
|
77
|
+
const errors = ref([]);
|
|
78
|
+
provide("form-errors", errors);
|
|
79
|
+
const inputs = ref({});
|
|
80
|
+
provide(formInputsInjectionKey, inputs);
|
|
81
|
+
const dirtyFields = /* @__PURE__ */ new Set();
|
|
82
|
+
const touchedFields = /* @__PURE__ */ new Set();
|
|
83
|
+
const blurredFields = /* @__PURE__ */ new Set();
|
|
84
|
+
function resolveErrorIds(errs) {
|
|
85
|
+
return errs.map((err) => ({
|
|
142
86
|
...err,
|
|
143
|
-
id: err?.name ? inputs.value[err.name]?.id :
|
|
144
|
-
}))
|
|
87
|
+
id: err?.name ? inputs.value[err.name]?.id : void 0
|
|
88
|
+
}));
|
|
145
89
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
async function getErrors(): Promise<FormErrorWithId[]> {
|
|
150
|
-
let errs = props.validate ? (await props.validate(props.state)) ?? [] : []
|
|
151
|
-
|
|
90
|
+
const transformedState = ref(null);
|
|
91
|
+
async function getErrors() {
|
|
92
|
+
let errs = props.validate ? await props.validate(props.state) ?? [] : [];
|
|
152
93
|
if (props.schema) {
|
|
153
|
-
const { errors, result } = await validateSchema(props.state, props.schema
|
|
154
|
-
if (
|
|
155
|
-
errs = errs.concat(
|
|
94
|
+
const { errors: errors2, result } = await validateSchema(props.state, props.schema);
|
|
95
|
+
if (errors2) {
|
|
96
|
+
errs = errs.concat(errors2);
|
|
156
97
|
} else {
|
|
157
|
-
transformedState.value = result
|
|
98
|
+
transformedState.value = result;
|
|
158
99
|
}
|
|
159
100
|
}
|
|
160
|
-
|
|
161
|
-
return resolveErrorIds(errs)
|
|
101
|
+
return resolveErrorIds(errs);
|
|
162
102
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return error
|
|
174
|
-
})
|
|
175
|
-
)
|
|
176
|
-
: []
|
|
177
|
-
|
|
103
|
+
async function _validate(opts = { silent: false, nested: true, transform: false }) {
|
|
104
|
+
const names = opts.name && !Array.isArray(opts.name) ? [opts.name] : opts.name;
|
|
105
|
+
const nestedValidatePromises = !names && opts.nested ? Array.from(nestedForms.value.values()).map(
|
|
106
|
+
({ validate }) => validate(opts).then(() => void 0).catch((error) => {
|
|
107
|
+
if (!(error instanceof FormValidationException)) {
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
return error;
|
|
111
|
+
})
|
|
112
|
+
) : [];
|
|
178
113
|
if (names) {
|
|
179
|
-
const otherErrors = errors.value.filter(error => !names.some((name) => {
|
|
180
|
-
const pattern = inputs.value?.[name]?.pattern
|
|
181
|
-
return name === error.name ||
|
|
182
|
-
}))
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
errors.value = otherErrors.concat(pathErrors)
|
|
114
|
+
const otherErrors = errors.value.filter((error) => !names.some((name) => {
|
|
115
|
+
const pattern = inputs.value?.[name]?.pattern;
|
|
116
|
+
return name === error.name || pattern && error.name?.match(pattern);
|
|
117
|
+
}));
|
|
118
|
+
const pathErrors = (await getErrors()).filter((error) => names.some((name) => {
|
|
119
|
+
const pattern = inputs.value?.[name]?.pattern;
|
|
120
|
+
return name === error.name || pattern && error.name?.match(pattern);
|
|
121
|
+
}));
|
|
122
|
+
errors.value = otherErrors.concat(pathErrors);
|
|
190
123
|
} else {
|
|
191
|
-
errors.value = await getErrors()
|
|
124
|
+
errors.value = await getErrors();
|
|
192
125
|
}
|
|
193
|
-
|
|
194
|
-
const childErrors = (await Promise.all(nestedValidatePromises)).filter(val => val !== undefined)
|
|
195
|
-
|
|
126
|
+
const childErrors = (await Promise.all(nestedValidatePromises)).filter((val) => val !== void 0);
|
|
196
127
|
if (errors.value.length + childErrors.length > 0) {
|
|
197
|
-
if (opts.silent) return false
|
|
198
|
-
throw new FormValidationException(formId, errors.value, childErrors)
|
|
128
|
+
if (opts.silent) return false;
|
|
129
|
+
throw new FormValidationException(formId, errors.value, childErrors);
|
|
199
130
|
}
|
|
200
|
-
|
|
201
131
|
if (opts.transform) {
|
|
202
|
-
Object.assign(props.state, transformedState.value)
|
|
132
|
+
Object.assign(props.state, transformedState.value);
|
|
203
133
|
}
|
|
204
|
-
|
|
205
|
-
return props.state as T
|
|
134
|
+
return props.state;
|
|
206
135
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
loading.value = true
|
|
213
|
-
|
|
214
|
-
const event = payload as FormSubmitEvent<any>
|
|
215
|
-
|
|
136
|
+
const loading = ref(false);
|
|
137
|
+
provide(formLoadingInjectionKey, readonly(loading));
|
|
138
|
+
async function onSubmitWrapper(payload) {
|
|
139
|
+
loading.value = true;
|
|
140
|
+
const event = payload;
|
|
216
141
|
try {
|
|
217
|
-
event.data = await _validate({ nested: true, transform: props.transform })
|
|
218
|
-
await props.onSubmit?.(event)
|
|
219
|
-
dirtyFields.clear()
|
|
142
|
+
event.data = await _validate({ nested: true, transform: props.transform });
|
|
143
|
+
await props.onSubmit?.(event);
|
|
144
|
+
dirtyFields.clear();
|
|
220
145
|
} catch (error) {
|
|
221
146
|
if (!(error instanceof FormValidationException)) {
|
|
222
|
-
throw error
|
|
147
|
+
throw error;
|
|
223
148
|
}
|
|
224
|
-
|
|
225
|
-
const errorEvent: FormErrorEvent = {
|
|
149
|
+
const errorEvent = {
|
|
226
150
|
...event,
|
|
227
151
|
errors: error.errors,
|
|
228
152
|
children: error.children
|
|
229
|
-
}
|
|
230
|
-
emits(
|
|
153
|
+
};
|
|
154
|
+
emits("error", errorEvent);
|
|
231
155
|
} finally {
|
|
232
|
-
loading.value = false
|
|
156
|
+
loading.value = false;
|
|
233
157
|
}
|
|
234
158
|
}
|
|
235
|
-
|
|
236
|
-
const disabled = computed(() => props.disabled || loading.value)
|
|
237
|
-
|
|
159
|
+
const disabled = computed(() => props.disabled || loading.value);
|
|
238
160
|
provide(formOptionsInjectionKey, computed(() => ({
|
|
239
161
|
disabled: disabled.value,
|
|
240
162
|
validateOnInputDelay: props.validateOnInputDelay
|
|
241
|
-
})))
|
|
242
|
-
|
|
243
|
-
defineExpose<Form<T>>({
|
|
163
|
+
})));
|
|
164
|
+
defineExpose({
|
|
244
165
|
validate: _validate,
|
|
245
166
|
errors,
|
|
246
|
-
|
|
247
|
-
setErrors(errs: FormError[], name?: keyof T) {
|
|
167
|
+
setErrors(errs, name) {
|
|
248
168
|
if (name) {
|
|
249
|
-
errors.value = errors.value
|
|
250
|
-
.filter(error => error.name !== name)
|
|
251
|
-
.concat(resolveErrorIds(errs))
|
|
169
|
+
errors.value = errors.value.filter((error) => error.name !== name).concat(resolveErrorIds(errs));
|
|
252
170
|
} else {
|
|
253
|
-
errors.value = resolveErrorIds(errs)
|
|
171
|
+
errors.value = resolveErrorIds(errs);
|
|
254
172
|
}
|
|
255
173
|
},
|
|
256
|
-
|
|
257
174
|
async submit() {
|
|
258
|
-
await onSubmitWrapper(new Event(
|
|
175
|
+
await onSubmitWrapper(new Event("submit"));
|
|
259
176
|
},
|
|
260
|
-
|
|
261
|
-
getErrors(name?: keyof T) {
|
|
177
|
+
getErrors(name) {
|
|
262
178
|
if (name) {
|
|
263
|
-
return errors.value.filter(err => err.name === name)
|
|
179
|
+
return errors.value.filter((err) => err.name === name);
|
|
264
180
|
}
|
|
265
|
-
return errors.value
|
|
181
|
+
return errors.value;
|
|
266
182
|
},
|
|
267
|
-
|
|
268
|
-
clear(name?: string) {
|
|
183
|
+
clear(name) {
|
|
269
184
|
if (name) {
|
|
270
|
-
errors.value = errors.value.filter(err => err.name !== name)
|
|
185
|
+
errors.value = errors.value.filter((err) => err.name !== name);
|
|
271
186
|
} else {
|
|
272
|
-
errors.value = []
|
|
187
|
+
errors.value = [];
|
|
273
188
|
}
|
|
274
189
|
},
|
|
275
|
-
|
|
276
190
|
disabled,
|
|
277
191
|
dirty: computed(() => !!dirtyFields.size),
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
})
|
|
192
|
+
dirtyFields: readonly(dirtyFields),
|
|
193
|
+
blurredFields: readonly(blurredFields),
|
|
194
|
+
touchedFields: readonly(touchedFields)
|
|
195
|
+
});
|
|
283
196
|
</script>
|
|
284
197
|
|
|
285
198
|
<template>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { FormSchema, FormError, FormInputEvents, FormErrorEvent, FormSubmitEvent, Form } from '../types/form';
|
|
2
|
+
export interface FormProps<T extends object> {
|
|
3
|
+
id?: string | number;
|
|
4
|
+
/** Schema to validate the form state. Supports Standard Schema objects, Yup, Joi, and Superstructs. */
|
|
5
|
+
schema?: FormSchema<T>;
|
|
6
|
+
/** An object representing the current state of the form. */
|
|
7
|
+
state: Partial<T>;
|
|
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<T>) => 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
|
+
class?: any;
|
|
32
|
+
onSubmit?: ((event: FormSubmitEvent<T>) => void | Promise<void>) | (() => void | Promise<void>);
|
|
33
|
+
}
|
|
34
|
+
export interface FormEmits<T extends object> {
|
|
35
|
+
(e: 'submit', payload: FormSubmitEvent<T>): void;
|
|
36
|
+
(e: 'error', payload: FormErrorEvent): void;
|
|
37
|
+
}
|
|
38
|
+
export interface FormSlots {
|
|
39
|
+
default(props?: {
|
|
40
|
+
errors: FormError[];
|
|
41
|
+
}): any;
|
|
42
|
+
}
|
|
43
|
+
declare const _default: <T extends object>(__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<{
|
|
44
|
+
props: __VLS_PrettifyLocal<any & FormProps<T> & Partial<{}>> & (import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps);
|
|
45
|
+
expose(exposed: import("vue").ShallowUnwrapRef<Form<T>>): void;
|
|
46
|
+
attrs: any;
|
|
47
|
+
slots: Readonly<FormSlots> & FormSlots;
|
|
48
|
+
emit: FormEmits<T>;
|
|
49
|
+
}>) => import("vue").VNode & {
|
|
50
|
+
__ctx?: Awaited<typeof __VLS_setup>;
|
|
51
|
+
};
|
|
52
|
+
export default _default;
|
|
53
|
+
type __VLS_PrettifyLocal<T> = {
|
|
54
|
+
[K in keyof T]: T[K];
|
|
55
|
+
} & {};
|
|
@@ -1,87 +1,43 @@
|
|
|
1
|
-
<script
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const appConfigFormField = _appConfig as AppConfig & { b24ui: { formField: Partial<typeof theme> } }
|
|
9
|
-
|
|
10
|
-
const formField = tv({ extend: tv(theme), ...(appConfigFormField.b24ui?.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
|
-
/**
|
|
34
|
-
* @defaultValue false
|
|
35
|
-
*/
|
|
36
|
-
required?: boolean
|
|
37
|
-
/** If true, validation on input will be active immediately instead of waiting for a blur event. */
|
|
38
|
-
eagerValidation?: boolean
|
|
39
|
-
/**
|
|
40
|
-
* Delay in milliseconds before validating the form on input events.
|
|
41
|
-
* @defaultValue `300`
|
|
42
|
-
*/
|
|
43
|
-
validateOnInputDelay?: number
|
|
44
|
-
class?: any
|
|
45
|
-
b24ui?: Partial<typeof formField.slots>
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export interface FormFieldSlots {
|
|
49
|
-
label(props: { label?: string }): any
|
|
50
|
-
hint(props: { hint?: string }): any
|
|
51
|
-
description(props: { description?: string }): any
|
|
52
|
-
help(props: { help?: string }): any
|
|
53
|
-
error(props: { error?: string | boolean }): any
|
|
54
|
-
default(props: { error?: string | boolean }): any
|
|
55
|
-
}
|
|
1
|
+
<script>
|
|
2
|
+
import _appConfig from "#build/app.config";
|
|
3
|
+
import theme from "#build/b24ui/form-field";
|
|
4
|
+
import { tv } from "../utils/tv";
|
|
5
|
+
const appConfigFormField = _appConfig;
|
|
6
|
+
const formField = tv({ extend: tv(theme), ...appConfigFormField.b24ui?.formField || {} });
|
|
56
7
|
</script>
|
|
57
8
|
|
|
58
|
-
<script setup
|
|
59
|
-
import { computed, ref, inject, provide,
|
|
60
|
-
import { Primitive, Label } from
|
|
61
|
-
import { formFieldInjectionKey, inputIdInjectionKey } from
|
|
62
|
-
import
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
9
|
+
<script setup>
|
|
10
|
+
import { computed, ref, inject, provide, useId } from "vue";
|
|
11
|
+
import { Primitive, Label } from "reka-ui";
|
|
12
|
+
import { formFieldInjectionKey, inputIdInjectionKey } from "../composables/useFormField";
|
|
13
|
+
import WarningIcon from "@bitrix24/b24icons-vue/main/WarningIcon";
|
|
14
|
+
const props = defineProps({
|
|
15
|
+
as: { type: null, required: false },
|
|
16
|
+
name: { type: String, required: false },
|
|
17
|
+
errorPattern: { type: null, required: false },
|
|
18
|
+
label: { type: String, required: false },
|
|
19
|
+
description: { type: String, required: false },
|
|
20
|
+
help: { type: String, required: false },
|
|
21
|
+
error: { type: [String, Boolean], required: false },
|
|
22
|
+
hint: { type: String, required: false },
|
|
23
|
+
size: { type: null, required: false },
|
|
24
|
+
required: { type: Boolean, required: false },
|
|
25
|
+
eagerValidation: { type: Boolean, required: false },
|
|
26
|
+
validateOnInputDelay: { type: Number, required: false },
|
|
27
|
+
class: { type: null, required: false },
|
|
28
|
+
b24ui: { type: Object, required: false }
|
|
29
|
+
});
|
|
30
|
+
const slots = defineSlots();
|
|
68
31
|
const b24ui = computed(() => formField({
|
|
69
32
|
size: props.size,
|
|
70
33
|
required: props.required,
|
|
71
34
|
useDescription: Boolean(props.description) || !!slots.description
|
|
72
|
-
}))
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
const id = ref(useId())
|
|
79
|
-
// Copies id's initial value to bind aria-attributes such as aria-describedby.
|
|
80
|
-
// This is required for the RadioGroup component which unsets the id value.
|
|
81
|
-
const ariaId = id.value
|
|
82
|
-
|
|
83
|
-
provide(inputIdInjectionKey, id)
|
|
84
|
-
|
|
35
|
+
}));
|
|
36
|
+
const formErrors = inject("form-errors", null);
|
|
37
|
+
const error = computed(() => props.error || formErrors?.value?.find((error2) => error2.name && (error2.name === props.name || props.errorPattern && error2.name.match(props.errorPattern)))?.message);
|
|
38
|
+
const id = ref(useId());
|
|
39
|
+
const ariaId = id.value;
|
|
40
|
+
provide(inputIdInjectionKey, id);
|
|
85
41
|
provide(formFieldInjectionKey, computed(() => ({
|
|
86
42
|
error: error.value,
|
|
87
43
|
name: props.name,
|
|
@@ -93,7 +49,7 @@ provide(formFieldInjectionKey, computed(() => ({
|
|
|
93
49
|
description: props.description,
|
|
94
50
|
help: props.help,
|
|
95
51
|
ariaId
|
|
96
|
-
})
|
|
52
|
+
})));
|
|
97
53
|
</script>
|
|
98
54
|
|
|
99
55
|
<template>
|
|
@@ -122,7 +78,7 @@ provide(formFieldInjectionKey, computed(() => ({
|
|
|
122
78
|
<div :class="[(label || !!slots.label || description || !!slots.description) && b24ui.container({ class: props.b24ui?.container })]">
|
|
123
79
|
<slot :error="error" />
|
|
124
80
|
|
|
125
|
-
<div v-if="
|
|
81
|
+
<div v-if="typeof error === 'string' && error || !!slots.error" :id="`${ariaId}-error`" :class="b24ui.error({ class: props.b24ui?.error })">
|
|
126
82
|
<slot name="error" :error="error">
|
|
127
83
|
<div class="flex flex-row flex-nowrap gap-0.5">
|
|
128
84
|
<WarningIcon :class="b24ui.errorIcon()" />
|