@faasjs/react 3.7.0-beta.6 → 3.7.0-beta.7
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/index.d.mts +36 -15
- package/dist/index.d.ts +36 -15
- package/dist/index.js +70 -37
- package/dist/index.mjs +71 -38
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -124,7 +124,7 @@ declare function createSplittingContext<T extends Record<string, any>>(defaultVa
|
|
|
124
124
|
* ```
|
|
125
125
|
*/
|
|
126
126
|
Provider<NewT extends T = T>(props: {
|
|
127
|
-
value?: NewT
|
|
127
|
+
value?: Partial<NewT>;
|
|
128
128
|
children: ReactNode;
|
|
129
129
|
/**
|
|
130
130
|
* Whether to use memoization for the children.
|
|
@@ -135,6 +135,20 @@ declare function createSplittingContext<T extends Record<string, any>>(defaultVa
|
|
|
135
135
|
* `any[]`: memoize the children with specific dependencies.
|
|
136
136
|
*/
|
|
137
137
|
memo?: true | any[];
|
|
138
|
+
/**
|
|
139
|
+
* An object containing initial values that will be automatically converted into state variables using {@link useSplittingState} hook. Each property will create both a state value and its setter following the pattern: value/setValue.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```tsx
|
|
143
|
+
* <Provider
|
|
144
|
+
* initializeStates={{
|
|
145
|
+
* value: 0,
|
|
146
|
+
* }}
|
|
147
|
+
* >
|
|
148
|
+
* // Children will have access to: value, setValue
|
|
149
|
+
* </Provider>
|
|
150
|
+
*/
|
|
151
|
+
initializeStates?: Partial<NewT>;
|
|
138
152
|
}): ReactNode;
|
|
139
153
|
/**
|
|
140
154
|
* The hook to use the splitting context.
|
|
@@ -397,18 +411,22 @@ type FormInputElementProps = {
|
|
|
397
411
|
declare const FormDefaultLang: {
|
|
398
412
|
submit: string;
|
|
399
413
|
required: string;
|
|
414
|
+
string: string;
|
|
400
415
|
number: string;
|
|
401
416
|
};
|
|
402
417
|
type FormLang = typeof FormDefaultLang;
|
|
403
418
|
|
|
404
|
-
type FormRules = {
|
|
405
|
-
type?: 'string' | 'number';
|
|
406
|
-
required?: boolean;
|
|
407
|
-
custom?: (value: any) => Promise<FormError | undefined>;
|
|
408
|
-
};
|
|
409
419
|
type FormError = {
|
|
410
420
|
message: string;
|
|
411
421
|
};
|
|
422
|
+
type FormRule<Options = any> = (value: any, options?: Options, lang?: FormLang) => Promise<FormError | undefined>;
|
|
423
|
+
type InferRuleOption<T> = T extends (value: any, options: infer O, lang?: FormLang) => Promise<FormError | undefined> ? O : never;
|
|
424
|
+
type FormRules = Record<string, FormRule>;
|
|
425
|
+
type InferFormRulesOptions<T> = {
|
|
426
|
+
[K in keyof T]: InferRuleOption<T[K]>;
|
|
427
|
+
};
|
|
428
|
+
declare const FormDefaultRules: FormRules;
|
|
429
|
+
type FormDefaultRulesOptions = InferFormRulesOptions<typeof FormDefaultRules>;
|
|
412
430
|
|
|
413
431
|
type InferFormInputProps<T extends ComponentType<FormInputElementProps> | JSXElementConstructor<any>> = T extends ComponentType<FormInputElementProps> ? Omit<ComponentProps<T>, 'name' | 'value' | 'onChange'> : Omit<ComponentProps<T>, 'name' | 'value'>;
|
|
414
432
|
type FormInputProps<FormElements extends FormElementTypes = FormElementTypes> = {
|
|
@@ -416,9 +434,9 @@ type FormInputProps<FormElements extends FormElementTypes = FormElementTypes> =
|
|
|
416
434
|
props?: InferFormInputProps<FormElements['Input']>;
|
|
417
435
|
};
|
|
418
436
|
|
|
419
|
-
type FormLabelElementProps<FormElements extends FormElementTypes = FormElementTypes> = {
|
|
437
|
+
type FormLabelElementProps<FormElements extends FormElementTypes = FormElementTypes, FormRulesOptions extends Record<string, any> = FormDefaultRulesOptions> = {
|
|
420
438
|
name: string;
|
|
421
|
-
rules?:
|
|
439
|
+
rules?: FormRulesOptions;
|
|
422
440
|
title?: ReactNode;
|
|
423
441
|
description?: ReactNode;
|
|
424
442
|
Label?: FormElements['Label'];
|
|
@@ -432,24 +450,26 @@ type FormElementTypes = {
|
|
|
432
450
|
};
|
|
433
451
|
declare const FormDefaultElements: FormElementTypes;
|
|
434
452
|
|
|
435
|
-
type FormProps<Values extends Record<string, any> = Record<string, any>, FormElements extends FormElementTypes = FormElementTypes> = {
|
|
436
|
-
items: FormLabelElementProps<FormElements
|
|
453
|
+
type FormProps<Values extends Record<string, any> = Record<string, any>, FormElements extends FormElementTypes = FormElementTypes, Rules extends FormRules = typeof FormDefaultRules> = {
|
|
454
|
+
items: FormLabelElementProps<FormElements, InferFormRulesOptions<Rules>>[];
|
|
437
455
|
onSubmit?: (values: Values) => Promise<void>;
|
|
438
456
|
Elements?: Partial<FormElements>;
|
|
439
457
|
lang?: Partial<FormLang>;
|
|
440
458
|
defaultValues?: Values;
|
|
459
|
+
rules?: typeof FormDefaultRules & Rules;
|
|
441
460
|
};
|
|
442
|
-
declare function FormContainer<Values extends Record<string, any> = Record<string, any>, FormElements extends FormElementTypes = FormElementTypes>({ defaultValues, Elements, lang, ...props }: FormProps<Values, FormElements>): react_jsx_runtime.JSX.Element;
|
|
461
|
+
declare function FormContainer<Values extends Record<string, any> = Record<string, any>, FormElements extends FormElementTypes = FormElementTypes, Rules extends FormRules = typeof FormDefaultRules>({ defaultValues, Elements, rules, lang, ...props }: FormProps<Values, FormElements, Rules>): react_jsx_runtime.JSX.Element;
|
|
443
462
|
declare namespace FormContainer {
|
|
444
463
|
var displayName: string;
|
|
445
464
|
var whyDidYouRender: boolean;
|
|
446
465
|
}
|
|
447
466
|
|
|
448
|
-
type FormContextProps<Values extends Record<string, any> = Record<string, any
|
|
467
|
+
type FormContextProps<Values extends Record<string, any> = Record<string, any>, Rules extends FormRules = typeof FormDefaultRules> = {
|
|
449
468
|
items: FormLabelElementProps[];
|
|
450
469
|
onSubmit: (values: Values) => Promise<void>;
|
|
451
470
|
Elements: FormElementTypes;
|
|
452
471
|
lang: FormLang;
|
|
472
|
+
rules: typeof FormDefaultRules & Rules;
|
|
453
473
|
submitting: boolean;
|
|
454
474
|
setSubmitting: Dispatch<SetStateAction<boolean>>;
|
|
455
475
|
values: Values;
|
|
@@ -457,11 +477,12 @@ type FormContextProps<Values extends Record<string, any> = Record<string, any>>
|
|
|
457
477
|
errors: Record<string, FormError>;
|
|
458
478
|
setErrors: Dispatch<SetStateAction<Record<string, FormError>>>;
|
|
459
479
|
};
|
|
460
|
-
declare const FormContextProvider: <NewT extends FormContextProps<Record<string, any
|
|
461
|
-
value?: NewT
|
|
480
|
+
declare const FormContextProvider: <NewT extends FormContextProps<Record<string, any>, FormRules> = FormContextProps<Record<string, any>, FormRules>>(props: {
|
|
481
|
+
value?: Partial<NewT>;
|
|
462
482
|
children: react.ReactNode;
|
|
463
483
|
memo?: true | any[];
|
|
484
|
+
initializeStates?: Partial<NewT>;
|
|
464
485
|
}) => react.ReactNode;
|
|
465
|
-
declare const useFormContext: <NewT extends FormContextProps<Record<string, any
|
|
486
|
+
declare const useFormContext: <NewT extends FormContextProps<Record<string, any>, FormRules> = FormContextProps<Record<string, any>, FormRules>>() => Readonly<NewT>;
|
|
466
487
|
|
|
467
488
|
export { ErrorBoundary, type ErrorBoundaryProps, type ErrorChildrenProps, type FaasDataInjection, FaasDataWrapper, type FaasDataWrapperProps, FaasReactClient, type FaasReactClientInstance, type FaasReactClientOptions, FormContainer as Form, type FormButtonElementProps, type FormContextProps, FormContextProvider, FormDefaultElements, type FormElementTypes, type FormInputElementProps, type FormLabelElementProps, type FormProps, type OnError, OptionalWrapper, type OptionalWrapperProps, createSplittingContext, equal, faas, getClient, useConstant, useEqualCallback, useEqualEffect, useEqualMemo, useEqualMemoize, useFaas, type useFaasOptions, useFormContext, useSplittingState, withFaasData };
|
package/dist/index.d.ts
CHANGED
|
@@ -124,7 +124,7 @@ declare function createSplittingContext<T extends Record<string, any>>(defaultVa
|
|
|
124
124
|
* ```
|
|
125
125
|
*/
|
|
126
126
|
Provider<NewT extends T = T>(props: {
|
|
127
|
-
value?: NewT
|
|
127
|
+
value?: Partial<NewT>;
|
|
128
128
|
children: ReactNode;
|
|
129
129
|
/**
|
|
130
130
|
* Whether to use memoization for the children.
|
|
@@ -135,6 +135,20 @@ declare function createSplittingContext<T extends Record<string, any>>(defaultVa
|
|
|
135
135
|
* `any[]`: memoize the children with specific dependencies.
|
|
136
136
|
*/
|
|
137
137
|
memo?: true | any[];
|
|
138
|
+
/**
|
|
139
|
+
* An object containing initial values that will be automatically converted into state variables using {@link useSplittingState} hook. Each property will create both a state value and its setter following the pattern: value/setValue.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```tsx
|
|
143
|
+
* <Provider
|
|
144
|
+
* initializeStates={{
|
|
145
|
+
* value: 0,
|
|
146
|
+
* }}
|
|
147
|
+
* >
|
|
148
|
+
* // Children will have access to: value, setValue
|
|
149
|
+
* </Provider>
|
|
150
|
+
*/
|
|
151
|
+
initializeStates?: Partial<NewT>;
|
|
138
152
|
}): ReactNode;
|
|
139
153
|
/**
|
|
140
154
|
* The hook to use the splitting context.
|
|
@@ -397,18 +411,22 @@ type FormInputElementProps = {
|
|
|
397
411
|
declare const FormDefaultLang: {
|
|
398
412
|
submit: string;
|
|
399
413
|
required: string;
|
|
414
|
+
string: string;
|
|
400
415
|
number: string;
|
|
401
416
|
};
|
|
402
417
|
type FormLang = typeof FormDefaultLang;
|
|
403
418
|
|
|
404
|
-
type FormRules = {
|
|
405
|
-
type?: 'string' | 'number';
|
|
406
|
-
required?: boolean;
|
|
407
|
-
custom?: (value: any) => Promise<FormError | undefined>;
|
|
408
|
-
};
|
|
409
419
|
type FormError = {
|
|
410
420
|
message: string;
|
|
411
421
|
};
|
|
422
|
+
type FormRule<Options = any> = (value: any, options?: Options, lang?: FormLang) => Promise<FormError | undefined>;
|
|
423
|
+
type InferRuleOption<T> = T extends (value: any, options: infer O, lang?: FormLang) => Promise<FormError | undefined> ? O : never;
|
|
424
|
+
type FormRules = Record<string, FormRule>;
|
|
425
|
+
type InferFormRulesOptions<T> = {
|
|
426
|
+
[K in keyof T]: InferRuleOption<T[K]>;
|
|
427
|
+
};
|
|
428
|
+
declare const FormDefaultRules: FormRules;
|
|
429
|
+
type FormDefaultRulesOptions = InferFormRulesOptions<typeof FormDefaultRules>;
|
|
412
430
|
|
|
413
431
|
type InferFormInputProps<T extends ComponentType<FormInputElementProps> | JSXElementConstructor<any>> = T extends ComponentType<FormInputElementProps> ? Omit<ComponentProps<T>, 'name' | 'value' | 'onChange'> : Omit<ComponentProps<T>, 'name' | 'value'>;
|
|
414
432
|
type FormInputProps<FormElements extends FormElementTypes = FormElementTypes> = {
|
|
@@ -416,9 +434,9 @@ type FormInputProps<FormElements extends FormElementTypes = FormElementTypes> =
|
|
|
416
434
|
props?: InferFormInputProps<FormElements['Input']>;
|
|
417
435
|
};
|
|
418
436
|
|
|
419
|
-
type FormLabelElementProps<FormElements extends FormElementTypes = FormElementTypes> = {
|
|
437
|
+
type FormLabelElementProps<FormElements extends FormElementTypes = FormElementTypes, FormRulesOptions extends Record<string, any> = FormDefaultRulesOptions> = {
|
|
420
438
|
name: string;
|
|
421
|
-
rules?:
|
|
439
|
+
rules?: FormRulesOptions;
|
|
422
440
|
title?: ReactNode;
|
|
423
441
|
description?: ReactNode;
|
|
424
442
|
Label?: FormElements['Label'];
|
|
@@ -432,24 +450,26 @@ type FormElementTypes = {
|
|
|
432
450
|
};
|
|
433
451
|
declare const FormDefaultElements: FormElementTypes;
|
|
434
452
|
|
|
435
|
-
type FormProps<Values extends Record<string, any> = Record<string, any>, FormElements extends FormElementTypes = FormElementTypes> = {
|
|
436
|
-
items: FormLabelElementProps<FormElements
|
|
453
|
+
type FormProps<Values extends Record<string, any> = Record<string, any>, FormElements extends FormElementTypes = FormElementTypes, Rules extends FormRules = typeof FormDefaultRules> = {
|
|
454
|
+
items: FormLabelElementProps<FormElements, InferFormRulesOptions<Rules>>[];
|
|
437
455
|
onSubmit?: (values: Values) => Promise<void>;
|
|
438
456
|
Elements?: Partial<FormElements>;
|
|
439
457
|
lang?: Partial<FormLang>;
|
|
440
458
|
defaultValues?: Values;
|
|
459
|
+
rules?: typeof FormDefaultRules & Rules;
|
|
441
460
|
};
|
|
442
|
-
declare function FormContainer<Values extends Record<string, any> = Record<string, any>, FormElements extends FormElementTypes = FormElementTypes>({ defaultValues, Elements, lang, ...props }: FormProps<Values, FormElements>): react_jsx_runtime.JSX.Element;
|
|
461
|
+
declare function FormContainer<Values extends Record<string, any> = Record<string, any>, FormElements extends FormElementTypes = FormElementTypes, Rules extends FormRules = typeof FormDefaultRules>({ defaultValues, Elements, rules, lang, ...props }: FormProps<Values, FormElements, Rules>): react_jsx_runtime.JSX.Element;
|
|
443
462
|
declare namespace FormContainer {
|
|
444
463
|
var displayName: string;
|
|
445
464
|
var whyDidYouRender: boolean;
|
|
446
465
|
}
|
|
447
466
|
|
|
448
|
-
type FormContextProps<Values extends Record<string, any> = Record<string, any
|
|
467
|
+
type FormContextProps<Values extends Record<string, any> = Record<string, any>, Rules extends FormRules = typeof FormDefaultRules> = {
|
|
449
468
|
items: FormLabelElementProps[];
|
|
450
469
|
onSubmit: (values: Values) => Promise<void>;
|
|
451
470
|
Elements: FormElementTypes;
|
|
452
471
|
lang: FormLang;
|
|
472
|
+
rules: typeof FormDefaultRules & Rules;
|
|
453
473
|
submitting: boolean;
|
|
454
474
|
setSubmitting: Dispatch<SetStateAction<boolean>>;
|
|
455
475
|
values: Values;
|
|
@@ -457,11 +477,12 @@ type FormContextProps<Values extends Record<string, any> = Record<string, any>>
|
|
|
457
477
|
errors: Record<string, FormError>;
|
|
458
478
|
setErrors: Dispatch<SetStateAction<Record<string, FormError>>>;
|
|
459
479
|
};
|
|
460
|
-
declare const FormContextProvider: <NewT extends FormContextProps<Record<string, any
|
|
461
|
-
value?: NewT
|
|
480
|
+
declare const FormContextProvider: <NewT extends FormContextProps<Record<string, any>, FormRules> = FormContextProps<Record<string, any>, FormRules>>(props: {
|
|
481
|
+
value?: Partial<NewT>;
|
|
462
482
|
children: react.ReactNode;
|
|
463
483
|
memo?: true | any[];
|
|
484
|
+
initializeStates?: Partial<NewT>;
|
|
464
485
|
}) => react.ReactNode;
|
|
465
|
-
declare const useFormContext: <NewT extends FormContextProps<Record<string, any
|
|
486
|
+
declare const useFormContext: <NewT extends FormContextProps<Record<string, any>, FormRules> = FormContextProps<Record<string, any>, FormRules>>() => Readonly<NewT>;
|
|
466
487
|
|
|
467
488
|
export { ErrorBoundary, type ErrorBoundaryProps, type ErrorChildrenProps, type FaasDataInjection, FaasDataWrapper, type FaasDataWrapperProps, FaasReactClient, type FaasReactClientInstance, type FaasReactClientOptions, FormContainer as Form, type FormButtonElementProps, type FormContextProps, FormContextProvider, FormDefaultElements, type FormElementTypes, type FormInputElementProps, type FormLabelElementProps, type FormProps, type OnError, OptionalWrapper, type OptionalWrapperProps, createSplittingContext, equal, faas, getClient, useConstant, useEqualCallback, useEqualEffect, useEqualMemo, useEqualMemoize, useFaas, type useFaasOptions, useFormContext, useSplittingState, withFaasData };
|
package/dist/index.js
CHANGED
|
@@ -80,6 +80,17 @@ function useEqualCallback(callback, dependencies) {
|
|
|
80
80
|
useEqualMemoize(dependencies)
|
|
81
81
|
);
|
|
82
82
|
}
|
|
83
|
+
function useSplittingState(initialStates) {
|
|
84
|
+
const states = {};
|
|
85
|
+
for (const key of Object.keys(initialStates)) {
|
|
86
|
+
const state = react.useState(initialStates[key]);
|
|
87
|
+
Object.assign(states, {
|
|
88
|
+
[key]: state[0],
|
|
89
|
+
[`set${String(key).charAt(0).toUpperCase()}${String(key).slice(1)}`]: state[1]
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return states;
|
|
93
|
+
}
|
|
83
94
|
function createSplittingContext(defaultValue) {
|
|
84
95
|
const keys = Array.isArray(defaultValue) ? defaultValue : Object.keys(defaultValue);
|
|
85
96
|
const defaultValues = Array.isArray(defaultValue) ? keys.reduce((prev, cur) => {
|
|
@@ -89,13 +100,14 @@ function createSplittingContext(defaultValue) {
|
|
|
89
100
|
const contexts = {};
|
|
90
101
|
for (const key of keys) contexts[key] = react.createContext(defaultValues[key]);
|
|
91
102
|
function Provider(props) {
|
|
103
|
+
const states = props.initializeStates ? useSplittingState(props.initializeStates) : {};
|
|
92
104
|
let children = props.memo ? useEqualMemo(
|
|
93
105
|
() => props.children,
|
|
94
106
|
props.memo === true ? [] : props.memo
|
|
95
107
|
) : props.children;
|
|
96
108
|
for (const key of keys) {
|
|
97
109
|
const Context = contexts[key];
|
|
98
|
-
const value = props.value?.[key] ?? defaultValues[key];
|
|
110
|
+
const value = props.value?.[key] ?? states[key] ?? defaultValues[key];
|
|
99
111
|
children = /* @__PURE__ */ jsxRuntime.jsx(Context.Provider, { value, children });
|
|
100
112
|
}
|
|
101
113
|
return children;
|
|
@@ -119,17 +131,6 @@ function createSplittingContext(defaultValue) {
|
|
|
119
131
|
use
|
|
120
132
|
};
|
|
121
133
|
}
|
|
122
|
-
function useSplittingState(initialStates) {
|
|
123
|
-
const states = {};
|
|
124
|
-
for (const key of Object.keys(initialStates)) {
|
|
125
|
-
const state = react.useState(initialStates[key]);
|
|
126
|
-
Object.assign(states, {
|
|
127
|
-
[key]: state[0],
|
|
128
|
-
[`set${String(key).charAt(0).toUpperCase()}${String(key).slice(1)}`]: state[1]
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
return states;
|
|
132
|
-
}
|
|
133
134
|
function FaasDataWrapper(props) {
|
|
134
135
|
const request = getClient(props.baseUrl).useFaas(
|
|
135
136
|
props.action,
|
|
@@ -354,7 +355,8 @@ var FormContext = createSplittingContext([
|
|
|
354
355
|
"values",
|
|
355
356
|
"setValues",
|
|
356
357
|
"errors",
|
|
357
|
-
"setErrors"
|
|
358
|
+
"setErrors",
|
|
359
|
+
"rules"
|
|
358
360
|
]);
|
|
359
361
|
var FormContextProvider = FormContext.Provider;
|
|
360
362
|
var useFormContext = FormContext.use;
|
|
@@ -373,21 +375,48 @@ FormBody.displayName = "FormBody";
|
|
|
373
375
|
FormBody.whyDidYouRender = true;
|
|
374
376
|
|
|
375
377
|
// src/Form/rules.ts
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
378
|
+
var FormDefaultRules = {
|
|
379
|
+
required: async (value, _, lang) => {
|
|
380
|
+
if (value === null || value === void 0 || value === "" || Number.isNaN(value)) {
|
|
381
|
+
return { message: lang?.required };
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
type: async (value, options, lang) => {
|
|
385
|
+
switch (options) {
|
|
386
|
+
case "string":
|
|
387
|
+
if (typeof value !== "string") {
|
|
388
|
+
return { message: lang?.string };
|
|
389
|
+
}
|
|
390
|
+
break;
|
|
391
|
+
case "number":
|
|
392
|
+
if (Number.isNaN(Number(value))) {
|
|
393
|
+
return { message: lang?.number };
|
|
394
|
+
}
|
|
395
|
+
break;
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
custom: async (value, options) => {
|
|
399
|
+
return options(value);
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
async function validValues(rules, items, values, lang) {
|
|
384
403
|
const errors = {};
|
|
385
404
|
for (const item of items) {
|
|
386
405
|
const value = values[item.name];
|
|
387
|
-
const
|
|
388
|
-
if (
|
|
389
|
-
const
|
|
390
|
-
|
|
406
|
+
const rulesOptions = item.rules;
|
|
407
|
+
if (rulesOptions) {
|
|
408
|
+
for (const [name, options] of Object.entries(rulesOptions)) {
|
|
409
|
+
const handler = rules[name];
|
|
410
|
+
if (!handler) {
|
|
411
|
+
console.warn(`Rule "${name}" is not defined`);
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
const error = await handler(value, options, lang);
|
|
415
|
+
if (error) {
|
|
416
|
+
errors[item.name] = error;
|
|
417
|
+
break;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
391
420
|
}
|
|
392
421
|
}
|
|
393
422
|
return errors;
|
|
@@ -401,7 +430,8 @@ function FormFooter() {
|
|
|
401
430
|
Elements,
|
|
402
431
|
items,
|
|
403
432
|
setErrors,
|
|
404
|
-
lang
|
|
433
|
+
lang,
|
|
434
|
+
rules
|
|
405
435
|
} = useFormContext();
|
|
406
436
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
407
437
|
Elements.Button,
|
|
@@ -409,7 +439,7 @@ function FormFooter() {
|
|
|
409
439
|
disabled: submitting,
|
|
410
440
|
submit: async () => {
|
|
411
441
|
setSubmitting(true);
|
|
412
|
-
const errors = await validValues(items, values, lang);
|
|
442
|
+
const errors = await validValues(rules, items, values, lang);
|
|
413
443
|
if (Object.keys(errors).length) {
|
|
414
444
|
setErrors(errors);
|
|
415
445
|
setSubmitting(false);
|
|
@@ -498,6 +528,7 @@ var FormDefaultElements = {
|
|
|
498
528
|
var FormDefaultLang = {
|
|
499
529
|
submit: "Submit",
|
|
500
530
|
required: "This field is required",
|
|
531
|
+
string: "This field must be a string",
|
|
501
532
|
number: "This field must be a number"
|
|
502
533
|
};
|
|
503
534
|
function mergeValues(items, defaultValues = {}) {
|
|
@@ -509,23 +540,25 @@ function mergeValues(items, defaultValues = {}) {
|
|
|
509
540
|
function FormContainer({
|
|
510
541
|
defaultValues,
|
|
511
542
|
Elements,
|
|
543
|
+
rules,
|
|
512
544
|
lang,
|
|
513
545
|
...props
|
|
514
546
|
}) {
|
|
515
|
-
const states = useSplittingState({
|
|
516
|
-
values: mergeValues(props.items, defaultValues),
|
|
517
|
-
errors: {},
|
|
518
|
-
submitting: false,
|
|
519
|
-
Elements: Object.assign(FormDefaultElements, Elements),
|
|
520
|
-
lang: Object.assign(FormDefaultLang, lang)
|
|
521
|
-
});
|
|
522
547
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
523
548
|
FormContextProvider,
|
|
524
549
|
{
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
550
|
+
initializeStates: {
|
|
551
|
+
values: mergeValues(props.items, defaultValues),
|
|
552
|
+
errors: {},
|
|
553
|
+
submitting: false,
|
|
554
|
+
Elements: Object.assign(
|
|
555
|
+
FormDefaultElements,
|
|
556
|
+
Elements
|
|
557
|
+
),
|
|
558
|
+
lang: Object.assign(FormDefaultLang, lang),
|
|
559
|
+
rules: Object.assign(FormDefaultRules, rules)
|
|
528
560
|
},
|
|
561
|
+
value: props,
|
|
529
562
|
memo: true,
|
|
530
563
|
children: [
|
|
531
564
|
/* @__PURE__ */ jsxRuntime.jsx(FormBody, {}),
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { forwardRef, useRef, useMemo, useEffect, useCallback,
|
|
1
|
+
import { forwardRef, useRef, useMemo, useEffect, useCallback, useState, createContext, cloneElement, Component, useContext } from 'react';
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import { FaasBrowserClient } from '@faasjs/browser';
|
|
4
4
|
|
|
@@ -78,6 +78,17 @@ function useEqualCallback(callback, dependencies) {
|
|
|
78
78
|
useEqualMemoize(dependencies)
|
|
79
79
|
);
|
|
80
80
|
}
|
|
81
|
+
function useSplittingState(initialStates) {
|
|
82
|
+
const states = {};
|
|
83
|
+
for (const key of Object.keys(initialStates)) {
|
|
84
|
+
const state = useState(initialStates[key]);
|
|
85
|
+
Object.assign(states, {
|
|
86
|
+
[key]: state[0],
|
|
87
|
+
[`set${String(key).charAt(0).toUpperCase()}${String(key).slice(1)}`]: state[1]
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return states;
|
|
91
|
+
}
|
|
81
92
|
function createSplittingContext(defaultValue) {
|
|
82
93
|
const keys = Array.isArray(defaultValue) ? defaultValue : Object.keys(defaultValue);
|
|
83
94
|
const defaultValues = Array.isArray(defaultValue) ? keys.reduce((prev, cur) => {
|
|
@@ -87,13 +98,14 @@ function createSplittingContext(defaultValue) {
|
|
|
87
98
|
const contexts = {};
|
|
88
99
|
for (const key of keys) contexts[key] = createContext(defaultValues[key]);
|
|
89
100
|
function Provider(props) {
|
|
101
|
+
const states = props.initializeStates ? useSplittingState(props.initializeStates) : {};
|
|
90
102
|
let children = props.memo ? useEqualMemo(
|
|
91
103
|
() => props.children,
|
|
92
104
|
props.memo === true ? [] : props.memo
|
|
93
105
|
) : props.children;
|
|
94
106
|
for (const key of keys) {
|
|
95
107
|
const Context = contexts[key];
|
|
96
|
-
const value = props.value?.[key] ?? defaultValues[key];
|
|
108
|
+
const value = props.value?.[key] ?? states[key] ?? defaultValues[key];
|
|
97
109
|
children = /* @__PURE__ */ jsx(Context.Provider, { value, children });
|
|
98
110
|
}
|
|
99
111
|
return children;
|
|
@@ -117,17 +129,6 @@ function createSplittingContext(defaultValue) {
|
|
|
117
129
|
use
|
|
118
130
|
};
|
|
119
131
|
}
|
|
120
|
-
function useSplittingState(initialStates) {
|
|
121
|
-
const states = {};
|
|
122
|
-
for (const key of Object.keys(initialStates)) {
|
|
123
|
-
const state = useState(initialStates[key]);
|
|
124
|
-
Object.assign(states, {
|
|
125
|
-
[key]: state[0],
|
|
126
|
-
[`set${String(key).charAt(0).toUpperCase()}${String(key).slice(1)}`]: state[1]
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
return states;
|
|
130
|
-
}
|
|
131
132
|
function FaasDataWrapper(props) {
|
|
132
133
|
const request = getClient(props.baseUrl).useFaas(
|
|
133
134
|
props.action,
|
|
@@ -352,7 +353,8 @@ var FormContext = createSplittingContext([
|
|
|
352
353
|
"values",
|
|
353
354
|
"setValues",
|
|
354
355
|
"errors",
|
|
355
|
-
"setErrors"
|
|
356
|
+
"setErrors",
|
|
357
|
+
"rules"
|
|
356
358
|
]);
|
|
357
359
|
var FormContextProvider = FormContext.Provider;
|
|
358
360
|
var useFormContext = FormContext.use;
|
|
@@ -371,21 +373,48 @@ FormBody.displayName = "FormBody";
|
|
|
371
373
|
FormBody.whyDidYouRender = true;
|
|
372
374
|
|
|
373
375
|
// src/Form/rules.ts
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
376
|
+
var FormDefaultRules = {
|
|
377
|
+
required: async (value, _, lang) => {
|
|
378
|
+
if (value === null || value === void 0 || value === "" || Number.isNaN(value)) {
|
|
379
|
+
return { message: lang?.required };
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
type: async (value, options, lang) => {
|
|
383
|
+
switch (options) {
|
|
384
|
+
case "string":
|
|
385
|
+
if (typeof value !== "string") {
|
|
386
|
+
return { message: lang?.string };
|
|
387
|
+
}
|
|
388
|
+
break;
|
|
389
|
+
case "number":
|
|
390
|
+
if (Number.isNaN(Number(value))) {
|
|
391
|
+
return { message: lang?.number };
|
|
392
|
+
}
|
|
393
|
+
break;
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
custom: async (value, options) => {
|
|
397
|
+
return options(value);
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
async function validValues(rules, items, values, lang) {
|
|
382
401
|
const errors = {};
|
|
383
402
|
for (const item of items) {
|
|
384
403
|
const value = values[item.name];
|
|
385
|
-
const
|
|
386
|
-
if (
|
|
387
|
-
const
|
|
388
|
-
|
|
404
|
+
const rulesOptions = item.rules;
|
|
405
|
+
if (rulesOptions) {
|
|
406
|
+
for (const [name, options] of Object.entries(rulesOptions)) {
|
|
407
|
+
const handler = rules[name];
|
|
408
|
+
if (!handler) {
|
|
409
|
+
console.warn(`Rule "${name}" is not defined`);
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
const error = await handler(value, options, lang);
|
|
413
|
+
if (error) {
|
|
414
|
+
errors[item.name] = error;
|
|
415
|
+
break;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
389
418
|
}
|
|
390
419
|
}
|
|
391
420
|
return errors;
|
|
@@ -399,7 +428,8 @@ function FormFooter() {
|
|
|
399
428
|
Elements,
|
|
400
429
|
items,
|
|
401
430
|
setErrors,
|
|
402
|
-
lang
|
|
431
|
+
lang,
|
|
432
|
+
rules
|
|
403
433
|
} = useFormContext();
|
|
404
434
|
return /* @__PURE__ */ jsx(
|
|
405
435
|
Elements.Button,
|
|
@@ -407,7 +437,7 @@ function FormFooter() {
|
|
|
407
437
|
disabled: submitting,
|
|
408
438
|
submit: async () => {
|
|
409
439
|
setSubmitting(true);
|
|
410
|
-
const errors = await validValues(items, values, lang);
|
|
440
|
+
const errors = await validValues(rules, items, values, lang);
|
|
411
441
|
if (Object.keys(errors).length) {
|
|
412
442
|
setErrors(errors);
|
|
413
443
|
setSubmitting(false);
|
|
@@ -496,6 +526,7 @@ var FormDefaultElements = {
|
|
|
496
526
|
var FormDefaultLang = {
|
|
497
527
|
submit: "Submit",
|
|
498
528
|
required: "This field is required",
|
|
529
|
+
string: "This field must be a string",
|
|
499
530
|
number: "This field must be a number"
|
|
500
531
|
};
|
|
501
532
|
function mergeValues(items, defaultValues = {}) {
|
|
@@ -507,23 +538,25 @@ function mergeValues(items, defaultValues = {}) {
|
|
|
507
538
|
function FormContainer({
|
|
508
539
|
defaultValues,
|
|
509
540
|
Elements,
|
|
541
|
+
rules,
|
|
510
542
|
lang,
|
|
511
543
|
...props
|
|
512
544
|
}) {
|
|
513
|
-
const states = useSplittingState({
|
|
514
|
-
values: mergeValues(props.items, defaultValues),
|
|
515
|
-
errors: {},
|
|
516
|
-
submitting: false,
|
|
517
|
-
Elements: Object.assign(FormDefaultElements, Elements),
|
|
518
|
-
lang: Object.assign(FormDefaultLang, lang)
|
|
519
|
-
});
|
|
520
545
|
return /* @__PURE__ */ jsxs(
|
|
521
546
|
FormContextProvider,
|
|
522
547
|
{
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
548
|
+
initializeStates: {
|
|
549
|
+
values: mergeValues(props.items, defaultValues),
|
|
550
|
+
errors: {},
|
|
551
|
+
submitting: false,
|
|
552
|
+
Elements: Object.assign(
|
|
553
|
+
FormDefaultElements,
|
|
554
|
+
Elements
|
|
555
|
+
),
|
|
556
|
+
lang: Object.assign(FormDefaultLang, lang),
|
|
557
|
+
rules: Object.assign(FormDefaultRules, rules)
|
|
526
558
|
},
|
|
559
|
+
value: props,
|
|
527
560
|
memo: true,
|
|
528
561
|
children: [
|
|
529
562
|
/* @__PURE__ */ jsx(FormBody, {}),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faasjs/react",
|
|
3
|
-
"version": "3.7.0-beta.
|
|
3
|
+
"version": "3.7.0-beta.7",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"dist"
|
|
35
35
|
],
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@faasjs/browser": "3.7.0-beta.
|
|
37
|
+
"@faasjs/browser": "3.7.0-beta.7"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@faasjs/browser": "3.7.0-beta.
|
|
40
|
+
"@faasjs/browser": "3.7.0-beta.7",
|
|
41
41
|
"@types/react": "*",
|
|
42
42
|
"react": "*"
|
|
43
43
|
},
|