mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-14 12:14:41 +01:00
feat(Form): support for valibot@33 (#132)
This commit is contained in:
@@ -72,7 +72,7 @@
|
||||
"joi": "^17.13.3",
|
||||
"nuxt": "^3.12.2",
|
||||
"release-it": "^17.4.0",
|
||||
"valibot": "^0.30.0",
|
||||
"valibot": "^0.33.0",
|
||||
"vitest": "^1.6.0",
|
||||
"vitest-environment-nuxt": "^1.0.0",
|
||||
"vue-tsc": "^2.0.22",
|
||||
|
||||
9
pnpm-lock.yaml
generated
9
pnpm-lock.yaml
generated
@@ -90,8 +90,8 @@ importers:
|
||||
specifier: ^17.4.0
|
||||
version: 17.4.0(typescript@5.5.2)
|
||||
valibot:
|
||||
specifier: ^0.30.0
|
||||
version: 0.30.0
|
||||
specifier: ^0.33.0
|
||||
version: 0.33.3
|
||||
vitest:
|
||||
specifier: ^1.6.0
|
||||
version: 1.6.0(@types/node@20.14.9)(happy-dom@14.12.3)(lightningcss@1.25.1)(sass@1.77.6)(terser@5.31.1)
|
||||
@@ -7010,6 +7010,9 @@ packages:
|
||||
valibot@0.30.0:
|
||||
resolution: {integrity: sha512-5POBdbSkM+3nvJ6ZlyQHsggisfRtyT4tVTo1EIIShs6qCdXJnyWU5TJ68vr8iTg5zpOLjXLRiBqNx+9zwZz/rA==}
|
||||
|
||||
valibot@0.33.3:
|
||||
resolution: {integrity: sha512-/fuY1DlX8uiQ7aphlzrrI2DbG0YJk84JMgvz2qKpUIdXRNsS53varfo4voPjSrjUr5BSV2K0miSEJUOlA5fQFg==}
|
||||
|
||||
validate-npm-package-license@3.0.4:
|
||||
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
|
||||
|
||||
@@ -16316,6 +16319,8 @@ snapshots:
|
||||
|
||||
valibot@0.30.0: {}
|
||||
|
||||
valibot@0.33.3: {}
|
||||
|
||||
validate-npm-package-license@3.0.4:
|
||||
dependencies:
|
||||
spdx-correct: 3.2.0
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { ComputedRef, Ref } from 'vue'
|
||||
import type { ZodSchema } from 'zod'
|
||||
import type { Schema as JoiSchema } from 'joi'
|
||||
import type { ObjectSchema as YupObjectSchema } from 'yup'
|
||||
import type { ObjectSchemaAsync as ValibotObjectSchema } from 'valibot'
|
||||
import type { GenericSchema as ValibotSchema, GenericSchemaAsync as ValibotSchemaAsync, SafeParser as ValibotSafeParser, SafeParserAsync as ValibotSafeParserAsync } from 'valibot'
|
||||
import type { GetObjectField } from './utils'
|
||||
|
||||
export interface Form<T> {
|
||||
@@ -18,7 +18,8 @@ export interface Form<T> {
|
||||
export type FormSchema<T extends Record<string, any>> =
|
||||
| ZodSchema
|
||||
| YupObjectSchema<T>
|
||||
| ValibotObjectSchema<T>
|
||||
| ValibotSchema | ValibotSchemaAsync
|
||||
| ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>
|
||||
| JoiSchema<T>
|
||||
|
||||
export type FormInputEvents = 'input' | 'blur' | 'change'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { ZodSchema } from 'zod'
|
||||
import type { ValidationError as JoiError, Schema as JoiSchema } from 'joi'
|
||||
import type { ObjectSchema as YupObjectSchema, ValidationError as YupError } from 'yup'
|
||||
import type { ObjectSchemaAsync as ValibotObjectSchema } from 'valibot'
|
||||
import type { GenericSchema as ValibotSchema, GenericSchemaAsync as ValibotSchemaAsync, SafeParser as ValibotSafeParser, SafeParserAsync as ValibotSafeParserAsync } from 'valibot'
|
||||
import type { FormError } from '../types/form'
|
||||
|
||||
export function isYupSchema(schema: any): schema is YupObjectSchema<any> {
|
||||
@@ -67,17 +67,18 @@ export async function getJoiErrors(state: any, schema: JoiSchema): Promise<FormE
|
||||
}
|
||||
}
|
||||
|
||||
export function isValibotSchema(schema: any): schema is ValibotObjectSchema<any> {
|
||||
return schema._parse !== undefined
|
||||
export function isValibotSchema(schema: any): schema is ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any> {
|
||||
return '_run' in schema || (typeof schema === 'function' && 'schema' in schema)
|
||||
}
|
||||
|
||||
export async function getValibotError(state: any, schema: ValibotObjectSchema<any>): Promise<FormError[]> {
|
||||
const result = await schema._parse(state)
|
||||
if (result.issues) {
|
||||
return result.issues.map(issue => ({
|
||||
name: issue.path?.map(p => p.key).join('.') || '',
|
||||
message: issue.message
|
||||
}))
|
||||
}
|
||||
return []
|
||||
export async function getValibotError(
|
||||
state: any,
|
||||
schema: ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>
|
||||
): Promise<FormError[]> {
|
||||
const result = await ('_run' in schema ? schema._run({ typed: false, value: state }, {}) : schema(state))
|
||||
return result.issues?.map(issue => ({
|
||||
// We know that the key for a form schema is always a string or a number
|
||||
name: issue.path?.map((item: any) => item.key).join('.') || '',
|
||||
message: issue.message
|
||||
})) || []
|
||||
}
|
||||
|
||||
@@ -106,14 +106,19 @@ describe('Form', () => {
|
||||
}
|
||||
],
|
||||
['valibot', {
|
||||
schema: valibot.objectAsync({
|
||||
schema: valibot.object({
|
||||
email: valibot.string(),
|
||||
password: valibot.string([
|
||||
valibot.minLength(8, 'Must be at least 8 characters')
|
||||
])
|
||||
password: valibot.pipe(valibot.string(), valibot.minLength(8, 'Must be at least 8 characters'))
|
||||
})
|
||||
}
|
||||
],
|
||||
['valibot safeParser', {
|
||||
schema: valibot.safeParser(valibot.object({
|
||||
email: valibot.string(),
|
||||
password: valibot.pipe(valibot.string(), valibot.minLength(8, 'Must be at least 8 characters'))
|
||||
}))
|
||||
}
|
||||
],
|
||||
['custom', {
|
||||
async validate(state: any) {
|
||||
const errs = []
|
||||
|
||||
@@ -128,6 +128,68 @@ exports[`Form > renders with default slot correctly 1`] = `"<form id="1" class="
|
||||
|
||||
exports[`Form > renders with state correctly 1`] = `"<form id="0" class=""></form>"`;
|
||||
|
||||
exports[`Form > valibot safeParser validation works > with error 1`] = `
|
||||
"<form id="42" class="">
|
||||
<div class="text-sm">
|
||||
<div class="">
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<div class="">
|
||||
<div class="relative inline-flex items-center"><input id="email" type="text" name="email" class="w-full rounded-md border-0 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 px-2.5 py-1.5 text-sm gap-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400" value="bob@dylan.com">
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<!--v-if-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm">
|
||||
<div class="">
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<div class="">
|
||||
<div class="relative inline-flex items-center"><input id="password" type="text" name="password" class="w-full rounded-md border-0 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 px-2.5 py-1.5 text-sm gap-1.5 shadow-sm bg-transparent text-gray-900 dark:text-white ring ring-inset ring-red-500 dark:ring-red-400 focus-visible:ring-2 focus-visible:ring-red-500 dark:focus-visible:ring-red-400" value="short">
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<p class="mt-2 text-red-500 dark:text-red-400">Must be at least 8 characters</p>
|
||||
</div>
|
||||
</div>
|
||||
</form>"
|
||||
`;
|
||||
|
||||
exports[`Form > valibot safeParser validation works > without error 1`] = `
|
||||
"<form id="42" class="">
|
||||
<div class="text-sm">
|
||||
<div class="">
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<div class="">
|
||||
<div class="relative inline-flex items-center"><input id="email" type="text" name="email" class="w-full rounded-md border-0 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 px-2.5 py-1.5 text-sm gap-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400" value="bob@dylan.com">
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<!--v-if-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm">
|
||||
<div class="">
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<div class="">
|
||||
<div class="relative inline-flex items-center"><input id="password" type="text" name="password" class="w-full rounded-md border-0 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 px-2.5 py-1.5 text-sm gap-1.5 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring ring-inset ring-gray-300 dark:ring-gray-700 focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400" value="validpassword">
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<!--v-if-->
|
||||
</div>
|
||||
</div>
|
||||
</form>"
|
||||
`;
|
||||
|
||||
exports[`Form > valibot validation works > with error 1`] = `
|
||||
"<form id="42" class="">
|
||||
<div class="text-sm">
|
||||
|
||||
Reference in New Issue
Block a user