@inertiajs/svelte 2.3.17 → 3.0.0-beta.2
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/dist/components/App.svelte +120 -44
- package/dist/components/App.svelte.d.ts +10 -19
- package/dist/components/Deferred.svelte +68 -9
- package/dist/components/Deferred.svelte.d.ts +9 -20
- package/dist/components/Form.svelte +358 -242
- package/dist/components/Form.svelte.d.ts +51 -96
- package/dist/components/InfiniteScroll.svelte +227 -167
- package/dist/components/InfiniteScroll.svelte.d.ts +29 -116
- package/dist/components/Link.svelte +96 -48
- package/dist/components/Link.svelte.d.ts +49 -56
- package/dist/components/Render.svelte +62 -21
- package/dist/components/Render.svelte.d.ts +9 -25
- package/dist/components/WhenVisible.svelte +83 -66
- package/dist/components/WhenVisible.svelte.d.ts +11 -26
- package/dist/components/createForm.d.ts +8 -0
- package/dist/components/createForm.js +4 -0
- package/dist/components/formContext.d.ts +3 -3
- package/dist/components/formContext.js +9 -3
- package/dist/createInertiaApp.d.ts +12 -7
- package/dist/createInertiaApp.js +63 -24
- package/dist/index.d.ts +8 -5
- package/dist/index.js +8 -5
- package/dist/layoutProps.svelte.d.ts +6 -0
- package/dist/layoutProps.svelte.js +25 -0
- package/dist/link.js +13 -2
- package/dist/page.svelte.d.ts +10 -0
- package/dist/page.svelte.js +14 -0
- package/dist/types.d.ts +11 -4
- package/dist/types.js +1 -1
- package/dist/{useForm.d.ts → useForm.svelte.d.ts} +4 -4
- package/dist/useForm.svelte.js +116 -0
- package/dist/useFormState.svelte.d.ts +84 -0
- package/dist/useFormState.svelte.js +290 -0
- package/dist/useHttp.svelte.d.ts +61 -0
- package/dist/useHttp.svelte.js +154 -0
- package/dist/usePrefetch.svelte.d.ts +7 -0
- package/dist/{usePrefetch.js → usePrefetch.svelte.js} +18 -13
- package/dist/useRemember.svelte.d.ts +1 -0
- package/dist/useRemember.svelte.js +10 -0
- package/package.json +11 -11
- package/resources/boost/skills/inertia-svelte-development/SKILL.blade.php +241 -107
- package/dist/page.d.ts +0 -13
- package/dist/page.js +0 -8
- package/dist/useForm.js +0 -356
- package/dist/usePrefetch.d.ts +0 -7
- package/dist/useRemember.d.ts +0 -1
- package/dist/useRemember.js +0 -11
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { router, UseFormUtils } from '@inertiajs/core';
|
|
2
|
+
import { cloneDeep } from 'lodash-es';
|
|
3
|
+
import useFormState, {} from './useFormState.svelte';
|
|
4
|
+
let reservedFormKeys = null;
|
|
5
|
+
let bootstrapping = false;
|
|
6
|
+
function validateFormDataKeys(data) {
|
|
7
|
+
if (bootstrapping) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (reservedFormKeys === null) {
|
|
11
|
+
bootstrapping = true;
|
|
12
|
+
const store = useForm({});
|
|
13
|
+
reservedFormKeys = new Set(Object.keys(store));
|
|
14
|
+
bootstrapping = false;
|
|
15
|
+
}
|
|
16
|
+
const conflicts = Object.keys(data).filter((key) => reservedFormKeys.has(key));
|
|
17
|
+
if (conflicts.length > 0) {
|
|
18
|
+
console.error(`[Inertia] useForm() data contains field(s) that conflict with form properties: ${conflicts.map((k) => `"${k}"`).join(', ')}. ` +
|
|
19
|
+
`These fields will be overwritten by form methods/properties. Please rename these fields.`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export default function useForm(...args) {
|
|
23
|
+
const { rememberKey, data, precognitionEndpoint } = UseFormUtils.parseUseFormArguments(...args);
|
|
24
|
+
const resolvedData = typeof data === 'function' ? data() : data;
|
|
25
|
+
validateFormDataKeys(resolvedData);
|
|
26
|
+
let cancelToken = null;
|
|
27
|
+
let pendingOptimisticCallback = null;
|
|
28
|
+
const { form: baseForm, setDefaults, getTransform, getPrecognitionEndpoint, setFormState, markAsSuccessful, wasDefaultsCalledInOnSuccess, resetDefaultsCalledInOnSuccess, setRememberExcludeKeys, resetBeforeSubmit, finishProcessing, } = useFormState({
|
|
29
|
+
data,
|
|
30
|
+
rememberKey,
|
|
31
|
+
precognitionEndpoint,
|
|
32
|
+
});
|
|
33
|
+
const formWithPrecognition = () => baseForm;
|
|
34
|
+
const submit = (...args) => {
|
|
35
|
+
const { method, url, options } = UseFormUtils.parseSubmitArguments(args, getPrecognitionEndpoint());
|
|
36
|
+
resetDefaultsCalledInOnSuccess();
|
|
37
|
+
const transformedData = getTransform()(form.data());
|
|
38
|
+
const _options = {
|
|
39
|
+
...options,
|
|
40
|
+
onCancelToken: (token) => {
|
|
41
|
+
cancelToken = token;
|
|
42
|
+
return options.onCancelToken?.(token);
|
|
43
|
+
},
|
|
44
|
+
onBefore: (visit) => {
|
|
45
|
+
resetBeforeSubmit();
|
|
46
|
+
return options.onBefore?.(visit);
|
|
47
|
+
},
|
|
48
|
+
onStart: (visit) => {
|
|
49
|
+
setFormState('processing', true);
|
|
50
|
+
return options.onStart?.(visit);
|
|
51
|
+
},
|
|
52
|
+
onProgress: (event) => {
|
|
53
|
+
setFormState('progress', event || null);
|
|
54
|
+
return options.onProgress?.(event);
|
|
55
|
+
},
|
|
56
|
+
onSuccess: async (page) => {
|
|
57
|
+
markAsSuccessful();
|
|
58
|
+
const onSuccess = options.onSuccess ? await options.onSuccess(page) : null;
|
|
59
|
+
if (!wasDefaultsCalledInOnSuccess()) {
|
|
60
|
+
setDefaults(cloneDeep(form.data()));
|
|
61
|
+
}
|
|
62
|
+
return onSuccess;
|
|
63
|
+
},
|
|
64
|
+
onError: (errors) => {
|
|
65
|
+
form.clearErrors().setError(errors);
|
|
66
|
+
return options.onError?.(errors);
|
|
67
|
+
},
|
|
68
|
+
onCancel: () => {
|
|
69
|
+
return options.onCancel?.();
|
|
70
|
+
},
|
|
71
|
+
onFinish: (visit) => {
|
|
72
|
+
finishProcessing();
|
|
73
|
+
cancelToken = null;
|
|
74
|
+
return options.onFinish?.(visit);
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
_options.optimistic = _options.optimistic ?? pendingOptimisticCallback ?? undefined;
|
|
78
|
+
pendingOptimisticCallback = null;
|
|
79
|
+
if (method === 'delete') {
|
|
80
|
+
router.delete(url, { ..._options, data: transformedData });
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
router[method](url, transformedData, _options);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const cancel = () => {
|
|
87
|
+
cancelToken?.cancel();
|
|
88
|
+
};
|
|
89
|
+
const createSubmitMethod = (method) => (url, options = {}) => {
|
|
90
|
+
submit(method, url, options);
|
|
91
|
+
};
|
|
92
|
+
Object.assign(baseForm, {
|
|
93
|
+
submit,
|
|
94
|
+
get: createSubmitMethod('get'),
|
|
95
|
+
post: createSubmitMethod('post'),
|
|
96
|
+
put: createSubmitMethod('put'),
|
|
97
|
+
patch: createSubmitMethod('patch'),
|
|
98
|
+
delete: createSubmitMethod('delete'),
|
|
99
|
+
cancel,
|
|
100
|
+
dontRemember(...keys) {
|
|
101
|
+
setRememberExcludeKeys(keys);
|
|
102
|
+
return form;
|
|
103
|
+
},
|
|
104
|
+
optimistic(callback) {
|
|
105
|
+
pendingOptimisticCallback = callback;
|
|
106
|
+
return form;
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
const form = baseForm;
|
|
110
|
+
const originalWithPrecognition = formWithPrecognition().withPrecognition;
|
|
111
|
+
form.withPrecognition = (...args) => {
|
|
112
|
+
originalWithPrecognition(...args);
|
|
113
|
+
return form;
|
|
114
|
+
};
|
|
115
|
+
return getPrecognitionEndpoint() ? form : form;
|
|
116
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { ErrorValue, FormDataErrors, FormDataKeys, FormDataValues, Progress, UrlMethodPair, UseFormTransformCallback, UseFormWithPrecognitionArguments } from '@inertiajs/core';
|
|
2
|
+
import type { NamedInputEvent, ValidationConfig, Validator } from 'laravel-precognition';
|
|
3
|
+
type TransformCallback<TForm> = (data: TForm) => object;
|
|
4
|
+
type PrecognitionValidationConfig<TKeys> = ValidationConfig & {
|
|
5
|
+
only?: TKeys[] | Iterable<TKeys> | ArrayLike<TKeys>;
|
|
6
|
+
};
|
|
7
|
+
export interface FormStateProps<TForm extends object> {
|
|
8
|
+
isDirty: boolean;
|
|
9
|
+
errors: FormDataErrors<TForm>;
|
|
10
|
+
hasErrors: boolean;
|
|
11
|
+
progress: Progress | null;
|
|
12
|
+
wasSuccessful: boolean;
|
|
13
|
+
recentlySuccessful: boolean;
|
|
14
|
+
processing: boolean;
|
|
15
|
+
setStore(data: TForm): void;
|
|
16
|
+
setStore<T extends FormDataKeys<TForm>>(key: T, value: FormDataValues<TForm, T>): void;
|
|
17
|
+
data(): TForm;
|
|
18
|
+
transform(callback: UseFormTransformCallback<TForm>): this;
|
|
19
|
+
defaults(): this;
|
|
20
|
+
defaults(fields: Partial<TForm>): this;
|
|
21
|
+
defaults<T extends FormDataKeys<TForm>>(field: T, value: FormDataValues<TForm, T>): this;
|
|
22
|
+
reset<K extends FormDataKeys<TForm>>(...fields: K[]): this;
|
|
23
|
+
clearErrors<K extends FormDataKeys<TForm>>(...fields: K[]): this;
|
|
24
|
+
resetAndClearErrors<K extends FormDataKeys<TForm>>(...fields: K[]): this;
|
|
25
|
+
setError<K extends FormDataKeys<TForm>>(field: K, value: ErrorValue): this;
|
|
26
|
+
setError(errors: FormDataErrors<TForm>): this;
|
|
27
|
+
withPrecognition: (...args: UseFormWithPrecognitionArguments) => FormStateWithPrecognition<TForm>;
|
|
28
|
+
}
|
|
29
|
+
export interface FormStateValidationProps<TForm extends object> {
|
|
30
|
+
invalid<K extends FormDataKeys<TForm>>(field: K): boolean;
|
|
31
|
+
setValidationTimeout(duration: number): this;
|
|
32
|
+
touch<K extends FormDataKeys<TForm>>(field: K | NamedInputEvent | Array<K>, ...fields: K[]): this;
|
|
33
|
+
touched<K extends FormDataKeys<TForm>>(field?: K): boolean;
|
|
34
|
+
valid<K extends FormDataKeys<TForm>>(field: K): boolean;
|
|
35
|
+
validate<K extends FormDataKeys<TForm>>(field?: K | NamedInputEvent | PrecognitionValidationConfig<K>, config?: PrecognitionValidationConfig<K>): this;
|
|
36
|
+
validateFiles(): this;
|
|
37
|
+
validating: boolean;
|
|
38
|
+
validator: () => Validator;
|
|
39
|
+
withAllErrors(): this;
|
|
40
|
+
withoutFileValidation(): this;
|
|
41
|
+
setErrors(errors: FormDataErrors<TForm> | Record<string, string | string[]>): this;
|
|
42
|
+
forgetError<K extends FormDataKeys<TForm> | NamedInputEvent>(field: K): this;
|
|
43
|
+
}
|
|
44
|
+
export interface InternalPrecognitionState {
|
|
45
|
+
__touched: string[];
|
|
46
|
+
__valid: string[];
|
|
47
|
+
}
|
|
48
|
+
export interface InternalRememberState<TForm extends object> {
|
|
49
|
+
__rememberable: boolean;
|
|
50
|
+
__remember: () => {
|
|
51
|
+
data: TForm;
|
|
52
|
+
errors: FormDataErrors<TForm>;
|
|
53
|
+
};
|
|
54
|
+
__restore: (restored: {
|
|
55
|
+
data: TForm;
|
|
56
|
+
errors: FormDataErrors<TForm>;
|
|
57
|
+
}) => void;
|
|
58
|
+
}
|
|
59
|
+
export type FormState<TForm extends object> = FormStateProps<TForm> & TForm;
|
|
60
|
+
export type FormStateWithPrecognition<TForm extends object> = FormState<TForm> & FormStateValidationProps<TForm> & InternalPrecognitionState;
|
|
61
|
+
export interface UseFormStateOptions<TForm extends object> {
|
|
62
|
+
data: TForm | (() => TForm);
|
|
63
|
+
rememberKey?: string | null;
|
|
64
|
+
precognitionEndpoint?: (() => UrlMethodPair) | null;
|
|
65
|
+
}
|
|
66
|
+
export interface UseFormStateReturn<TForm extends object> {
|
|
67
|
+
form: FormState<TForm> & InternalRememberState<TForm>;
|
|
68
|
+
setDefaults: (newDefaults: TForm) => void;
|
|
69
|
+
getTransform: () => TransformCallback<TForm>;
|
|
70
|
+
getPrecognitionEndpoint: () => (() => UrlMethodPair) | null;
|
|
71
|
+
setFormState: <K extends string>(key: K, value: any) => void;
|
|
72
|
+
markAsSuccessful: () => void;
|
|
73
|
+
wasDefaultsCalledInOnSuccess: () => boolean;
|
|
74
|
+
resetDefaultsCalledInOnSuccess: () => void;
|
|
75
|
+
setRememberExcludeKeys: (keys: FormDataKeys<TForm>[]) => void;
|
|
76
|
+
resetBeforeSubmit: () => void;
|
|
77
|
+
finishProcessing: () => void;
|
|
78
|
+
withAllErrors: {
|
|
79
|
+
enabled: () => boolean;
|
|
80
|
+
enable: () => void;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export default function useFormState<TForm extends object>(options: UseFormStateOptions<TForm>): UseFormStateReturn<TForm>;
|
|
84
|
+
export {};
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { router, UseFormUtils } from '@inertiajs/core';
|
|
2
|
+
import { createValidator, resolveName, toSimpleValidationErrors } from 'laravel-precognition';
|
|
3
|
+
import { cloneDeep, get, has, isEqual, set } from 'lodash-es';
|
|
4
|
+
import { config } from '.';
|
|
5
|
+
export default function useFormState(options) {
|
|
6
|
+
const { data: dataOption, rememberKey, precognitionEndpoint: initialPrecognitionEndpoint } = options;
|
|
7
|
+
const isDataFunction = typeof dataOption === 'function';
|
|
8
|
+
const resolveData = () => (isDataFunction ? dataOption() : dataOption);
|
|
9
|
+
const restored = rememberKey
|
|
10
|
+
? router.restore(rememberKey)
|
|
11
|
+
: null;
|
|
12
|
+
const initialData = restored?.data ?? cloneDeep(resolveData());
|
|
13
|
+
let defaults = cloneDeep(initialData);
|
|
14
|
+
let transform = (data) => data;
|
|
15
|
+
let validatorRef = null;
|
|
16
|
+
let withAllErrors = null;
|
|
17
|
+
const withAllErrorsEnabled = () => withAllErrors ?? config.get('form.withAllErrors');
|
|
18
|
+
let precognitionEndpoint = initialPrecognitionEndpoint ?? null;
|
|
19
|
+
let recentlySuccessfulTimeoutId = null;
|
|
20
|
+
let defaultsCalledInOnSuccess = false;
|
|
21
|
+
let rememberExcludeKeys = [];
|
|
22
|
+
let setFormStateInternal;
|
|
23
|
+
const tap = (value, callback) => {
|
|
24
|
+
callback(value);
|
|
25
|
+
return value;
|
|
26
|
+
};
|
|
27
|
+
const withPrecognition = (...args) => {
|
|
28
|
+
precognitionEndpoint = UseFormUtils.createWayfinderCallback(...args);
|
|
29
|
+
const formWithPrecognition = () => form;
|
|
30
|
+
if (!validatorRef) {
|
|
31
|
+
const validator = createValidator((client) => {
|
|
32
|
+
const { method, url } = precognitionEndpoint();
|
|
33
|
+
const f = formWithPrecognition();
|
|
34
|
+
const transformedData = cloneDeep(transform(f.data()));
|
|
35
|
+
return client[method](url, transformedData);
|
|
36
|
+
}, cloneDeep(defaults));
|
|
37
|
+
validatorRef = validator;
|
|
38
|
+
validator
|
|
39
|
+
.on('validatingChanged', () => {
|
|
40
|
+
setFormStateInternal('validating', validator.validating());
|
|
41
|
+
})
|
|
42
|
+
.on('validatedChanged', () => {
|
|
43
|
+
setFormStateInternal('__valid', validator.valid());
|
|
44
|
+
})
|
|
45
|
+
.on('touchedChanged', () => {
|
|
46
|
+
setFormStateInternal('__touched', validator.touched());
|
|
47
|
+
})
|
|
48
|
+
.on('errorsChanged', () => {
|
|
49
|
+
const validationErrors = withAllErrorsEnabled()
|
|
50
|
+
? validator.errors()
|
|
51
|
+
: toSimpleValidationErrors(validator.errors());
|
|
52
|
+
setFormStateInternal('errors', {});
|
|
53
|
+
formWithPrecognition().setError(validationErrors);
|
|
54
|
+
setFormStateInternal('__valid', validator.valid());
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
Object.assign(form, {
|
|
58
|
+
...form,
|
|
59
|
+
__touched: [],
|
|
60
|
+
__valid: [],
|
|
61
|
+
validating: false,
|
|
62
|
+
validator: () => validatorRef,
|
|
63
|
+
validate: (field, config) => {
|
|
64
|
+
const f = formWithPrecognition();
|
|
65
|
+
if (typeof field === 'object' && !('target' in field)) {
|
|
66
|
+
config = field;
|
|
67
|
+
field = undefined;
|
|
68
|
+
}
|
|
69
|
+
if (field === undefined) {
|
|
70
|
+
validatorRef.validate(config);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
field = resolveName(field);
|
|
74
|
+
const transformedData = transform(f.data());
|
|
75
|
+
validatorRef.validate(field, get(transformedData, field), config);
|
|
76
|
+
}
|
|
77
|
+
return f;
|
|
78
|
+
},
|
|
79
|
+
touch: (field, ...fields) => {
|
|
80
|
+
const f = formWithPrecognition();
|
|
81
|
+
if (Array.isArray(field)) {
|
|
82
|
+
validatorRef?.touch(field);
|
|
83
|
+
}
|
|
84
|
+
else if (typeof field === 'string') {
|
|
85
|
+
validatorRef?.touch([field, ...fields]);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
validatorRef?.touch(field);
|
|
89
|
+
}
|
|
90
|
+
return f;
|
|
91
|
+
},
|
|
92
|
+
validateFiles: () => tap(formWithPrecognition(), () => validatorRef?.validateFiles()),
|
|
93
|
+
setValidationTimeout: (duration) => tap(formWithPrecognition(), () => validatorRef.setTimeout(duration)),
|
|
94
|
+
withAllErrors: () => tap(formWithPrecognition(), () => (withAllErrors = true)),
|
|
95
|
+
withoutFileValidation: () => tap(formWithPrecognition(), () => validatorRef?.withoutFileValidation()),
|
|
96
|
+
valid: (field) => formWithPrecognition().__valid.includes(field),
|
|
97
|
+
invalid: (field) => field in formWithPrecognition().errors,
|
|
98
|
+
touched: (field) => {
|
|
99
|
+
const touched = formWithPrecognition().__touched;
|
|
100
|
+
return typeof field === 'string' ? touched.includes(field) : touched.length > 0;
|
|
101
|
+
},
|
|
102
|
+
setErrors: (errors) => tap(formWithPrecognition(), () => {
|
|
103
|
+
const f = formWithPrecognition();
|
|
104
|
+
f.setError(errors);
|
|
105
|
+
}),
|
|
106
|
+
forgetError: (field) => tap(formWithPrecognition(), () => {
|
|
107
|
+
const f = formWithPrecognition();
|
|
108
|
+
f.clearErrors(resolveName(field));
|
|
109
|
+
}),
|
|
110
|
+
});
|
|
111
|
+
return form;
|
|
112
|
+
};
|
|
113
|
+
let form = $state({
|
|
114
|
+
...initialData,
|
|
115
|
+
isDirty: false,
|
|
116
|
+
errors: (restored?.errors ?? {}),
|
|
117
|
+
hasErrors: false,
|
|
118
|
+
progress: null,
|
|
119
|
+
wasSuccessful: false,
|
|
120
|
+
recentlySuccessful: false,
|
|
121
|
+
processing: false,
|
|
122
|
+
setStore(keyOrData, maybeValue = undefined) {
|
|
123
|
+
if (typeof keyOrData === 'string') {
|
|
124
|
+
set(form, keyOrData, maybeValue);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
Object.assign(form, keyOrData);
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
data() {
|
|
131
|
+
return Object.keys(defaults).reduce((carry, key) => {
|
|
132
|
+
return set(carry, key, get(this, key));
|
|
133
|
+
}, {});
|
|
134
|
+
},
|
|
135
|
+
transform(callback) {
|
|
136
|
+
transform = callback;
|
|
137
|
+
return this;
|
|
138
|
+
},
|
|
139
|
+
defaults(fieldOrFields, maybeValue) {
|
|
140
|
+
if (isDataFunction) {
|
|
141
|
+
throw new Error('You cannot call `defaults()` when using a function to define your form data.');
|
|
142
|
+
}
|
|
143
|
+
defaultsCalledInOnSuccess = true;
|
|
144
|
+
if (typeof fieldOrFields === 'undefined') {
|
|
145
|
+
defaults = cloneDeep(this.data());
|
|
146
|
+
this.isDirty = false;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
defaults =
|
|
150
|
+
typeof fieldOrFields === 'string'
|
|
151
|
+
? set(cloneDeep(defaults), fieldOrFields, maybeValue)
|
|
152
|
+
: Object.assign(cloneDeep(defaults), fieldOrFields);
|
|
153
|
+
}
|
|
154
|
+
validatorRef?.defaults(defaults);
|
|
155
|
+
return this;
|
|
156
|
+
},
|
|
157
|
+
reset(...fields) {
|
|
158
|
+
const resolvedData = isDataFunction ? cloneDeep(resolveData()) : defaults;
|
|
159
|
+
const clonedData = cloneDeep(resolvedData);
|
|
160
|
+
if (fields.length === 0) {
|
|
161
|
+
if (isDataFunction) {
|
|
162
|
+
defaults = clonedData;
|
|
163
|
+
}
|
|
164
|
+
this.setStore(clonedData);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
;
|
|
168
|
+
fields
|
|
169
|
+
.filter((key) => has(clonedData, key))
|
|
170
|
+
.forEach((key) => {
|
|
171
|
+
if (isDataFunction) {
|
|
172
|
+
set(defaults, key, get(clonedData, key));
|
|
173
|
+
}
|
|
174
|
+
set(this, key, get(clonedData, key));
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
validatorRef?.reset(...fields);
|
|
178
|
+
return this;
|
|
179
|
+
},
|
|
180
|
+
setError(fieldOrFields, maybeValue) {
|
|
181
|
+
const errors = typeof fieldOrFields === 'string' ? { [fieldOrFields]: maybeValue } : fieldOrFields;
|
|
182
|
+
setFormStateInternal('errors', {
|
|
183
|
+
...this.errors,
|
|
184
|
+
...errors,
|
|
185
|
+
});
|
|
186
|
+
validatorRef?.setErrors(errors);
|
|
187
|
+
return this;
|
|
188
|
+
},
|
|
189
|
+
clearErrors(...fields) {
|
|
190
|
+
setFormStateInternal('errors', Object.keys(this.errors).reduce((carry, field) => ({
|
|
191
|
+
...carry,
|
|
192
|
+
...(fields.length > 0 && !fields.includes(field) ? { [field]: this.errors[field] } : {}),
|
|
193
|
+
}), {}));
|
|
194
|
+
if (validatorRef) {
|
|
195
|
+
if (fields.length === 0) {
|
|
196
|
+
validatorRef.setErrors({});
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
fields.forEach(validatorRef.forgetError);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return this;
|
|
203
|
+
},
|
|
204
|
+
resetAndClearErrors(...fields) {
|
|
205
|
+
this.reset(...fields);
|
|
206
|
+
this.clearErrors(...fields);
|
|
207
|
+
return this;
|
|
208
|
+
},
|
|
209
|
+
withPrecognition,
|
|
210
|
+
__rememberable: rememberKey === null,
|
|
211
|
+
__remember() {
|
|
212
|
+
const formData = this.data();
|
|
213
|
+
if (rememberExcludeKeys.length > 0) {
|
|
214
|
+
const filtered = { ...formData };
|
|
215
|
+
rememberExcludeKeys.forEach((k) => delete filtered[k]);
|
|
216
|
+
return { data: filtered, errors: $state.snapshot(this.errors) };
|
|
217
|
+
}
|
|
218
|
+
return { data: formData, errors: $state.snapshot(this.errors) };
|
|
219
|
+
},
|
|
220
|
+
__restore(restored) {
|
|
221
|
+
Object.assign(this, restored.data);
|
|
222
|
+
this.setError(restored.errors);
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
setFormStateInternal = (key, value) => {
|
|
226
|
+
form[key] = value;
|
|
227
|
+
};
|
|
228
|
+
$effect(() => {
|
|
229
|
+
const newIsDirty = !isEqual(form.data(), defaults);
|
|
230
|
+
if (form.isDirty !== newIsDirty) {
|
|
231
|
+
setFormStateInternal('isDirty', newIsDirty);
|
|
232
|
+
}
|
|
233
|
+
const hasErrors = Object.keys(form.errors).length > 0;
|
|
234
|
+
if (form.hasErrors !== hasErrors) {
|
|
235
|
+
setFormStateInternal('hasErrors', hasErrors);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
$effect(() => {
|
|
239
|
+
if (!rememberKey) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
const storedData = router.restore(rememberKey);
|
|
243
|
+
const newData = form.__remember();
|
|
244
|
+
if (!isEqual(storedData, newData)) {
|
|
245
|
+
router.remember(newData, rememberKey);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
if (precognitionEndpoint) {
|
|
249
|
+
form.withPrecognition(precognitionEndpoint);
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
form: form,
|
|
253
|
+
setDefaults: (newDefaults) => {
|
|
254
|
+
defaults = newDefaults;
|
|
255
|
+
},
|
|
256
|
+
getTransform: () => transform,
|
|
257
|
+
getPrecognitionEndpoint: () => precognitionEndpoint,
|
|
258
|
+
setFormState: setFormStateInternal,
|
|
259
|
+
markAsSuccessful: () => {
|
|
260
|
+
form.clearErrors();
|
|
261
|
+
setFormStateInternal('wasSuccessful', true);
|
|
262
|
+
setFormStateInternal('recentlySuccessful', true);
|
|
263
|
+
recentlySuccessfulTimeoutId = setTimeout(() => setFormStateInternal('recentlySuccessful', false), config.get('form.recentlySuccessfulDuration'));
|
|
264
|
+
},
|
|
265
|
+
wasDefaultsCalledInOnSuccess: () => defaultsCalledInOnSuccess,
|
|
266
|
+
resetDefaultsCalledInOnSuccess: () => {
|
|
267
|
+
defaultsCalledInOnSuccess = false;
|
|
268
|
+
},
|
|
269
|
+
setRememberExcludeKeys: (keys) => {
|
|
270
|
+
rememberExcludeKeys = keys;
|
|
271
|
+
},
|
|
272
|
+
resetBeforeSubmit: () => {
|
|
273
|
+
setFormStateInternal('wasSuccessful', false);
|
|
274
|
+
setFormStateInternal('recentlySuccessful', false);
|
|
275
|
+
if (recentlySuccessfulTimeoutId) {
|
|
276
|
+
clearTimeout(recentlySuccessfulTimeoutId);
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
finishProcessing: () => {
|
|
280
|
+
setFormStateInternal('processing', false);
|
|
281
|
+
setFormStateInternal('progress', null);
|
|
282
|
+
},
|
|
283
|
+
withAllErrors: {
|
|
284
|
+
enabled: withAllErrorsEnabled,
|
|
285
|
+
enable: () => {
|
|
286
|
+
withAllErrors = true;
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { ErrorValue, FormDataErrors, FormDataKeys, FormDataType, FormDataValues, Method, Progress, UrlMethodPair, UseFormTransformCallback, UseFormWithPrecognitionArguments, UseHttpSubmitArguments, UseHttpSubmitOptions } from '@inertiajs/core';
|
|
2
|
+
import type { NamedInputEvent, ValidationConfig, Validator } from 'laravel-precognition';
|
|
3
|
+
export interface UseHttpProps<TForm extends object, TResponse = unknown> {
|
|
4
|
+
isDirty: boolean;
|
|
5
|
+
errors: FormDataErrors<TForm>;
|
|
6
|
+
hasErrors: boolean;
|
|
7
|
+
progress: Progress | null;
|
|
8
|
+
wasSuccessful: boolean;
|
|
9
|
+
recentlySuccessful: boolean;
|
|
10
|
+
processing: boolean;
|
|
11
|
+
response: TResponse | null;
|
|
12
|
+
setStore(data: TForm): void;
|
|
13
|
+
setStore<T extends FormDataKeys<TForm>>(key: T, value: FormDataValues<TForm, T>): void;
|
|
14
|
+
data(): TForm;
|
|
15
|
+
transform(callback: UseFormTransformCallback<TForm>): this;
|
|
16
|
+
defaults(): this;
|
|
17
|
+
defaults(fields: Partial<TForm>): this;
|
|
18
|
+
defaults<T extends FormDataKeys<TForm>>(field: T, value: FormDataValues<TForm, T>): this;
|
|
19
|
+
reset<K extends FormDataKeys<TForm>>(...fields: K[]): this;
|
|
20
|
+
clearErrors<K extends FormDataKeys<TForm>>(...fields: K[]): this;
|
|
21
|
+
resetAndClearErrors<K extends FormDataKeys<TForm>>(...fields: K[]): this;
|
|
22
|
+
setError<K extends FormDataKeys<TForm>>(field: K, value: ErrorValue): this;
|
|
23
|
+
setError(errors: FormDataErrors<TForm>): this;
|
|
24
|
+
submit(...args: UseHttpSubmitArguments<TResponse, TForm>): Promise<TResponse>;
|
|
25
|
+
get(url: string, options?: UseHttpSubmitOptions<TResponse, TForm>): Promise<TResponse>;
|
|
26
|
+
post(url: string, options?: UseHttpSubmitOptions<TResponse, TForm>): Promise<TResponse>;
|
|
27
|
+
put(url: string, options?: UseHttpSubmitOptions<TResponse, TForm>): Promise<TResponse>;
|
|
28
|
+
patch(url: string, options?: UseHttpSubmitOptions<TResponse, TForm>): Promise<TResponse>;
|
|
29
|
+
delete(url: string, options?: UseHttpSubmitOptions<TResponse, TForm>): Promise<TResponse>;
|
|
30
|
+
cancel(): void;
|
|
31
|
+
dontRemember<K extends FormDataKeys<TForm>>(...fields: K[]): this;
|
|
32
|
+
optimistic(callback: (currentData: TForm) => Partial<TForm>): this;
|
|
33
|
+
withAllErrors(): this;
|
|
34
|
+
withPrecognition: (...args: UseFormWithPrecognitionArguments) => UseHttpPrecognitiveProps<TForm, TResponse>;
|
|
35
|
+
}
|
|
36
|
+
type PrecognitionValidationConfig<TKeys> = ValidationConfig & {
|
|
37
|
+
only?: TKeys[] | Iterable<TKeys> | ArrayLike<TKeys>;
|
|
38
|
+
};
|
|
39
|
+
export interface UseHttpValidationProps<TForm extends object> {
|
|
40
|
+
invalid<K extends FormDataKeys<TForm>>(field: K): boolean;
|
|
41
|
+
setValidationTimeout(duration: number): this;
|
|
42
|
+
touch<K extends FormDataKeys<TForm>>(field: K | NamedInputEvent | Array<K>, ...fields: K[]): this;
|
|
43
|
+
touched<K extends FormDataKeys<TForm>>(field?: K): boolean;
|
|
44
|
+
valid<K extends FormDataKeys<TForm>>(field: K): boolean;
|
|
45
|
+
validate<K extends FormDataKeys<TForm>>(field?: K | NamedInputEvent | PrecognitionValidationConfig<K>, config?: PrecognitionValidationConfig<K>): this;
|
|
46
|
+
validateFiles(): this;
|
|
47
|
+
validating: boolean;
|
|
48
|
+
validator: () => Validator;
|
|
49
|
+
withAllErrors(): this;
|
|
50
|
+
withoutFileValidation(): this;
|
|
51
|
+
setErrors(errors: FormDataErrors<TForm> | Record<string, string | string[]>): this;
|
|
52
|
+
forgetError<K extends FormDataKeys<TForm> | NamedInputEvent>(field: K): this;
|
|
53
|
+
}
|
|
54
|
+
export type UseHttp<TForm extends object, TResponse = unknown> = UseHttpProps<TForm, TResponse> & TForm;
|
|
55
|
+
export type UseHttpPrecognitiveProps<TForm extends object, TResponse = unknown> = UseHttp<TForm, TResponse> & UseHttpValidationProps<TForm>;
|
|
56
|
+
export default function useHttp<TForm extends FormDataType<TForm>, TResponse = unknown>(method: Method | (() => Method), url: string | (() => string), data: TForm | (() => TForm)): UseHttpPrecognitiveProps<TForm, TResponse>;
|
|
57
|
+
export default function useHttp<TForm extends FormDataType<TForm>, TResponse = unknown>(urlMethodPair: UrlMethodPair | (() => UrlMethodPair), data: TForm | (() => TForm)): UseHttpPrecognitiveProps<TForm, TResponse>;
|
|
58
|
+
export default function useHttp<TForm extends FormDataType<TForm>, TResponse = unknown>(rememberKey: string, data: TForm | (() => TForm)): UseHttp<TForm, TResponse>;
|
|
59
|
+
export default function useHttp<TForm extends FormDataType<TForm>, TResponse = unknown>(data: TForm | (() => TForm)): UseHttp<TForm, TResponse>;
|
|
60
|
+
export default function useHttp<TForm extends FormDataType<TForm>, TResponse = unknown>(): UseHttp<TForm, TResponse>;
|
|
61
|
+
export {};
|