Skip to content
This repository was archived by the owner on Apr 9, 2025. It is now read-only.

Commit 973c6fe

Browse files
committed
Improve type clarity and dx
1 parent 2af05a7 commit 973c6fe

File tree

15 files changed

+211
-182
lines changed

15 files changed

+211
-182
lines changed

docs/api/use-form-handler/build.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ Notice how the template looks much cleaner with this approach, and this helps us
7575
## Type Declarations
7676

7777
```ts
78-
export type Build<T> = <TBuild extends Record<keyof T, RegisterOptions>>(
78+
export type Build<T extends Record<string, any> = Record<string, any>> = <
79+
TBuild extends Partial<Record<keyof T, RegisterOptions>>,
80+
>(
7981
configuration: TBuild | Ref<TBuild> | ComputedRef<TBuild>
80-
) => ComputedRef<Record<keyof TBuild, Readonly<RegisterReturn>>>
82+
) => ComputedRef<Record<keyof TBuild, Readonly<RegisterReturn<TBuild>>>>
83+
8184
```

docs/api/use-form-handler/modified-values.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# modifiedValues
22

3-
Returns the current modified fields of the form.
3+
Computed property that holds the current modified values of the form e.g values that are different from initial value if any initial value was indicated or different than the default value for the field if no initial values were given.
44

55
## Demo
66

@@ -15,7 +15,7 @@ Coming soon...
1515
<input type="text" v-bind="register('email')" />
1616
<input type="text" v-bind="register('summary')" />
1717
<pre>
18-
{{ modifiedValues() }} //should be initially
18+
{{ modifiedValues }} //should initially be an empty object
1919
</pre
2020
>
2121
<pre>
@@ -41,5 +41,6 @@ Let's say your form is initialized as above, because you're editing an existing
4141
## Type Declarations
4242

4343
```ts
44-
export type ModifiedValues = <TModified extends T>() => TModified
44+
type ModifiedValues = ComputedRef<Partial<T>>// T being the form interface
45+
4546
```

docs/api/use-form-handler/register.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,31 @@ Custom validations are kept very simple, can be synchronous or asynchronous. We
243243
## Type Declarations
244244

245245
```ts
246+
247+
interface ValidationWithMessage {
248+
value: number | string | RegExp
249+
message: string
250+
}
251+
252+
interface ValidationsConfiguration {
253+
required?: boolean | string
254+
min?: number | ValidationWithMessage<number>
255+
max?: number | ValidationWithMessage<number>
256+
minLength?: number | ValidationWithMessage<number>
257+
maxLength?: number | ValidationWithMessage<number>
258+
pattern?: string | RegExp | ValidationWithMessage<string | RegExp>
259+
}
260+
261+
export interface RegisterOptions extends ValidationsConfiguration {
262+
native?: boolean
263+
defaultValue?: any
264+
validate?: Validations
265+
withDetails?: boolean
266+
disabled?: boolean
267+
useNativeValidation?: boolean
268+
dependentFields?: string[]
269+
}
270+
246271
export type Register = (
247272
name: keyof T,
248273
options?: RegisterOptions

docs/api/use-form-handler/values.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,5 @@ const { register, values } = useFormHandler()
4040
## Type Declarations
4141

4242
```ts
43-
export type Values = T
43+
export type Values = Partial<T>
4444
```

src/logic/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
export { default as getNativeFieldValue } from './getNativeFieldValue'
22
export { default as getDefaultFieldValue } from './getDefaultFieldValue'
3-
export { default as validateField } from './validateField'
4-
export { default as validateForm } from './validateForm'
53
export { default as refFn } from './refFn'
64
export { default as transformValidations } from './transformValidations'

src/logic/refFn.ts

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,52 +6,55 @@ import {
66
isRadioInput,
77
} from '../utils'
88

9-
export default <T>(name: keyof T, _refs: Refs<T>, values: T) => (fieldRef: any) => {
10-
if (!fieldRef) {
11-
delete _refs[name]
12-
return
13-
}
14-
if (fieldRef.$el || !fieldRef.nodeName || !isNativeControl(fieldRef)) {
15-
//TODO: Correctly type this in order to expect a fixed data structure
16-
_refs[name].ref = {
17-
type: 'custom',
9+
export default <T>(name: keyof T, _refs: Refs<T>, values: Partial<T>) =>
10+
(fieldRef: any) => {
11+
if (!fieldRef) {
12+
delete _refs[name]
13+
return
1814
}
19-
return
20-
}
21-
const isFirstRegister =
22-
_refs[name] &&
23-
(!_refs[name].ref ||
24-
(Array.isArray(_refs[name].ref) &&
25-
isRadioInput(fieldRef) &&
26-
!(_refs[name].ref as FieldReference[]).some(
27-
(option: any) => option.value === fieldRef.value
28-
)))
29-
if (isFirstRegister) {
30-
_refs[name].ref = isRadioInput(fieldRef)
31-
? [...((_refs[name].ref as FieldReference[]) || []), fieldRef]
32-
: fieldRef
33-
}
34-
if (isRadioInput(fieldRef)) {
35-
if (isFirstRegister && !!fieldRef.checked) {
36-
values[name] = fieldRef.value
15+
if (fieldRef.$el || !fieldRef.nodeName || !isNativeControl(fieldRef)) {
16+
//TODO: Correctly type this in order to expect a fixed data structure
17+
_refs[name].ref = {
18+
type: 'custom',
19+
}
3720
return
3821
}
39-
fieldRef.checked = values[name] === fieldRef.value
40-
return
41-
}
42-
if (isCheckboxInput(fieldRef)) {
43-
if (isFirstRegister && !!fieldRef.checked) {
44-
values[name] = true as any
22+
const isFirstRegister =
23+
_refs[name] &&
24+
(!_refs[name].ref ||
25+
(Array.isArray(_refs[name].ref) &&
26+
isRadioInput(fieldRef) &&
27+
!(_refs[name].ref as FieldReference[]).some(
28+
(option: any) => option.value === fieldRef.value
29+
)))
30+
if (isFirstRegister) {
31+
_refs[name].ref = isRadioInput(fieldRef)
32+
? [...((_refs[name].ref as FieldReference[]) || []), fieldRef]
33+
: fieldRef
34+
}
35+
if (isRadioInput(fieldRef)) {
36+
if (isFirstRegister && !!fieldRef.checked) {
37+
values[name] = fieldRef.value
38+
return
39+
}
40+
fieldRef.checked = values[name] === fieldRef.value
4541
return
4642
}
47-
fieldRef.checked = !!values[name]
48-
return
49-
}
50-
if (isMultipleSelect(fieldRef)) {
51-
;[...fieldRef.options].forEach((option: any, index) => {
52-
fieldRef[index].selected = !!((values[name] as any)?.includes(option.value))
53-
})
54-
return
43+
if (isCheckboxInput(fieldRef)) {
44+
if (isFirstRegister && !!fieldRef.checked) {
45+
values[name] = true as any
46+
return
47+
}
48+
fieldRef.checked = !!values[name]
49+
return
50+
}
51+
if (isMultipleSelect(fieldRef)) {
52+
;[...fieldRef.options].forEach((option: any, index) => {
53+
fieldRef[index].selected = !!(values[name] as any)?.includes(
54+
option.value
55+
)
56+
})
57+
return
58+
}
59+
fieldRef.value = values[name]
5560
}
56-
fieldRef.value = values[name]
57-
}

src/logic/transformValidations.ts

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@ import {
55
} from '../types'
66
import { max, maxLength, min, minLength, pattern, required } from '../utils'
77

8+
const isValidationWithMessage = (
9+
validation: any
10+
): validation is ValidationWithMessage => {
11+
return (
12+
typeof validation === 'object' &&
13+
validation !== null &&
14+
'value' in validation &&
15+
'message' in validation
16+
)
17+
}
18+
19+
const getValidationForConfiguration = (validation: any, fn: Function) =>
20+
isValidationWithMessage(validation)
21+
? fn(validation.value, validation.message)
22+
: fn(validation)
23+
824
export default (validations: ValidationsConfiguration = {}): Validations => {
925
return {
1026
...(validations.required && {
@@ -14,46 +30,25 @@ export default (validations: ValidationsConfiguration = {}): Validations => {
1430
: required(),
1531
}),
1632
...(validations.min && {
17-
min:
18-
typeof validations.min === 'number'
19-
? min(validations.min)
20-
: min(validations.min.value as number, validations.min.message),
33+
min: getValidationForConfiguration(validations.min, min),
2134
}),
2235
...(validations.max && {
23-
max:
24-
typeof validations.max === 'number'
25-
? max(validations.max)
26-
: max(validations.max.value as number, validations.max.message),
36+
max: getValidationForConfiguration(validations.max, max),
2737
}),
2838
...(validations.minLength && {
29-
minLength:
30-
typeof validations.minLength === 'number'
31-
? minLength(validations.minLength)
32-
: minLength(
33-
validations.minLength.value as number,
34-
validations.minLength.message
35-
),
39+
minLength: getValidationForConfiguration(
40+
validations.minLength,
41+
minLength
42+
),
3643
}),
3744
...(validations.maxLength && {
38-
maxLength:
39-
typeof validations.maxLength === 'number'
40-
? maxLength(validations.maxLength)
41-
: maxLength(
42-
validations.maxLength.value as number,
43-
validations.maxLength.message
44-
),
45+
maxLength: getValidationForConfiguration(
46+
validations.maxLength,
47+
maxLength
48+
),
4549
}),
4650
...(validations.pattern && {
47-
pattern: !(validations.pattern as ValidationWithMessage)?.value
48-
? pattern(
49-
(typeof validations.pattern === 'string'
50-
? new RegExp(validations.pattern)
51-
: validations.pattern) as RegExp
52-
)
53-
: pattern(
54-
(validations.pattern as ValidationWithMessage).value as RegExp,
55-
(validations.pattern as ValidationWithMessage).message as string
56-
),
51+
pattern: getValidationForConfiguration(validations.pattern, pattern),
5752
}),
5853
}
5954
}

src/logic/validateField.ts

Lines changed: 0 additions & 31 deletions
This file was deleted.

src/logic/validateForm.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/types/formHandler.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ export type HandleSubmitErrorFn<T> = (errors: FormState<T>['errors']) => void
1717
export type HandleSubmitSuccessFn<T> = (values: Record<keyof T, any>) => void
1818

1919
export type Build<T extends Record<string, any> = Record<string, any>> = <
20-
TBuild extends Record<keyof T, RegisterOptions>,
20+
TBuild extends Partial<Record<keyof T, RegisterOptions>>,
2121
>(
2222
configuration: TBuild | Ref<TBuild> | ComputedRef<TBuild>
2323
) => ComputedRef<Record<keyof TBuild, Readonly<RegisterReturn<TBuild>>>>
2424

2525
export interface PartialReturn<T> {
2626
/** Current form values */
27-
values: T
27+
values: Partial<T>
2828

2929
/** Current form state */
3030
formState: FormState<T>
@@ -51,7 +51,7 @@ export interface PartialReturn<T> {
5151
clearField: (name: keyof T) => void
5252

5353
/** Function that returns the modified values of the form */
54-
modifiedValues: <TModified extends T>() => TModified
54+
modifiedValues: ComputedRef<Partial<T>>
5555
}
5656

5757
export interface InterceptorParams<T> extends PartialReturn<T> {
@@ -87,18 +87,15 @@ export type SubmitValidation = (
8787

8888
export type InjectionKey = string | Symbol
8989

90-
export interface FormHandlerParams<
91-
TValues extends Record<string, any>,
92-
TInitial extends TValues = TValues,
93-
> {
90+
export interface FormHandlerParams<TForm, TInitial> {
9491
/** Values to initialize the form */
9592
initialValues?: TInitial | Ref<TInitial> | ComputedRef<TInitial>
9693

9794
/** Field change interceptor */
98-
interceptor?: Interceptor<TValues>
95+
interceptor?: Interceptor<TForm>
9996

10097
/** Validation function to execute before submitting (when using this individual validations are invalidated) */
101-
validate?: (values: TValues) => Promise<boolean> | boolean
98+
validate?: (values: Partial<TForm>) => Promise<boolean> | boolean
10299

103100
/** Validation behavior options */
104101
validationMode?: 'onChange' | 'onBlur' | 'onSubmit' | 'always'

0 commit comments

Comments
 (0)