@faasjs/react 3.7.0-beta.4 → 3.7.0-beta.5

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 CHANGED
@@ -376,8 +376,8 @@ declare const OptionalWrapper: React.FC<OptionalWrapperProps> & {
376
376
 
377
377
  type FormButtonElementProps = {
378
378
  children?: React.ReactNode;
379
- disabled?: boolean;
380
- submit?: () => void;
379
+ disabled: boolean;
380
+ submit: () => Promise<void>;
381
381
  };
382
382
 
383
383
  type FormInputElementProps = {
@@ -389,6 +389,10 @@ type FormInputElementProps = {
389
389
  type FormRules = {
390
390
  type?: 'string' | 'number';
391
391
  required?: boolean;
392
+ custom?: (value: any) => Promise<FormError | undefined>;
393
+ };
394
+ type FormError = {
395
+ message: string;
392
396
  };
393
397
 
394
398
  type InferFormInputProps<T extends ComponentType<FormInputElementProps> | JSXElementConstructor<any>> = T extends ComponentType<FormInputElementProps> ? Omit<ComponentProps<T>, 'name' | 'value' | 'onChange'> : Omit<ComponentProps<T>, 'name' | 'value'>;
@@ -430,9 +434,11 @@ type FormContextProps<Values extends Record<string, any> = Record<string, any>>
430
434
  onSubmit: (values: Values) => Promise<void>;
431
435
  Elements: FormElementTypes;
432
436
  submitting: boolean;
433
- setSubmitting: React.Dispatch<React.SetStateAction<boolean>>;
437
+ setSubmitting: Dispatch<SetStateAction<boolean>>;
434
438
  values: Values;
435
- setValues: React.Dispatch<React.SetStateAction<Values>>;
439
+ setValues: Dispatch<SetStateAction<Values>>;
440
+ errors: Record<string, FormError>;
441
+ setErrors: Dispatch<SetStateAction<Record<string, FormError>>>;
436
442
  };
437
443
  declare const FormContextProvider: <NewT extends FormContextProps<Record<string, any>> = FormContextProps<Record<string, any>>>(props: {
438
444
  value?: NewT;
package/dist/index.d.ts CHANGED
@@ -376,8 +376,8 @@ declare const OptionalWrapper: React.FC<OptionalWrapperProps> & {
376
376
 
377
377
  type FormButtonElementProps = {
378
378
  children?: React.ReactNode;
379
- disabled?: boolean;
380
- submit?: () => void;
379
+ disabled: boolean;
380
+ submit: () => Promise<void>;
381
381
  };
382
382
 
383
383
  type FormInputElementProps = {
@@ -389,6 +389,10 @@ type FormInputElementProps = {
389
389
  type FormRules = {
390
390
  type?: 'string' | 'number';
391
391
  required?: boolean;
392
+ custom?: (value: any) => Promise<FormError | undefined>;
393
+ };
394
+ type FormError = {
395
+ message: string;
392
396
  };
393
397
 
394
398
  type InferFormInputProps<T extends ComponentType<FormInputElementProps> | JSXElementConstructor<any>> = T extends ComponentType<FormInputElementProps> ? Omit<ComponentProps<T>, 'name' | 'value' | 'onChange'> : Omit<ComponentProps<T>, 'name' | 'value'>;
@@ -430,9 +434,11 @@ type FormContextProps<Values extends Record<string, any> = Record<string, any>>
430
434
  onSubmit: (values: Values) => Promise<void>;
431
435
  Elements: FormElementTypes;
432
436
  submitting: boolean;
433
- setSubmitting: React.Dispatch<React.SetStateAction<boolean>>;
437
+ setSubmitting: Dispatch<SetStateAction<boolean>>;
434
438
  values: Values;
435
- setValues: React.Dispatch<React.SetStateAction<Values>>;
439
+ setValues: Dispatch<SetStateAction<Values>>;
440
+ errors: Record<string, FormError>;
441
+ setErrors: Dispatch<SetStateAction<Record<string, FormError>>>;
436
442
  };
437
443
  declare const FormContextProvider: <NewT extends FormContextProps<Record<string, any>> = FormContextProps<Record<string, any>>>(props: {
438
444
  value?: NewT;
package/dist/index.js CHANGED
@@ -350,7 +350,9 @@ var FormContext = createSplittingContext([
350
350
  "submitting",
351
351
  "setSubmitting",
352
352
  "values",
353
- "setValues"
353
+ "setValues",
354
+ "errors",
355
+ "setErrors"
354
356
  ]);
355
357
  var FormContextProvider = FormContext.Provider;
356
358
  var useFormContext = FormContext.use;
@@ -367,14 +369,49 @@ function FormBody() {
367
369
  }
368
370
  FormBody.displayName = "FormBody";
369
371
  FormBody.whyDidYouRender = true;
372
+
373
+ // src/Form/rules.ts
374
+ async function validValue(rules, value) {
375
+ if (rules.required && (value === null || value === void 0 || value === "" || Number.isNaN(value)))
376
+ return { message: "This field is required" };
377
+ if (rules.type === "number" && Number.isNaN(Number(value)))
378
+ return { message: "This field must be a number" };
379
+ return rules.custom?.(value);
380
+ }
381
+ async function validValues(items, values) {
382
+ const errors = {};
383
+ for (const item of items) {
384
+ const value = values[item.name];
385
+ const rules = item.rules;
386
+ if (rules) {
387
+ const error = await validValue(rules, value);
388
+ if (error) errors[item.name] = error;
389
+ }
390
+ }
391
+ return errors;
392
+ }
370
393
  function FormFooter() {
371
- const { submitting, setSubmitting, onSubmit, values, Elements } = useFormContext();
394
+ const {
395
+ submitting,
396
+ setSubmitting,
397
+ onSubmit,
398
+ values,
399
+ Elements,
400
+ items,
401
+ setErrors
402
+ } = useFormContext();
372
403
  return /* @__PURE__ */ jsxRuntime.jsx(
373
404
  Elements.Button,
374
405
  {
375
406
  disabled: submitting,
376
- submit: () => {
407
+ submit: async () => {
377
408
  setSubmitting(true);
409
+ const errors = await validValues(items, values);
410
+ if (Object.keys(errors).length) {
411
+ setErrors(errors);
412
+ setSubmitting(false);
413
+ return;
414
+ }
378
415
  onSubmit(values).finally(() => setSubmitting(false));
379
416
  },
380
417
  children: "Submit"
@@ -406,7 +443,7 @@ var FormLabelElement = ({
406
443
  Label,
407
444
  input
408
445
  }) => {
409
- const { values, setValues } = useFormContext();
446
+ const { values, setValues, errors } = useFormContext();
410
447
  if (Label)
411
448
  return /* @__PURE__ */ jsxRuntime.jsx(
412
449
  Label,
@@ -440,7 +477,8 @@ var FormLabelElement = ({
440
477
  }))
441
478
  }
442
479
  ),
443
- description
480
+ description,
481
+ errors[name]?.message
444
482
  ] });
445
483
  };
446
484
  FormLabelElement.displayName = "FormLabelElement";
@@ -461,6 +499,7 @@ function mergeValues(items, defaultValues = {}) {
461
499
  function FormContainer({ defaultValues, elements, ...props }) {
462
500
  const states = useSplittingState({
463
501
  values: mergeValues(props.items, defaultValues),
502
+ errors: {},
464
503
  submitting: false,
465
504
  Elements: Object.assign(FormDefaultElements, elements)
466
505
  });
package/dist/index.mjs CHANGED
@@ -348,7 +348,9 @@ var FormContext = createSplittingContext([
348
348
  "submitting",
349
349
  "setSubmitting",
350
350
  "values",
351
- "setValues"
351
+ "setValues",
352
+ "errors",
353
+ "setErrors"
352
354
  ]);
353
355
  var FormContextProvider = FormContext.Provider;
354
356
  var useFormContext = FormContext.use;
@@ -365,14 +367,49 @@ function FormBody() {
365
367
  }
366
368
  FormBody.displayName = "FormBody";
367
369
  FormBody.whyDidYouRender = true;
370
+
371
+ // src/Form/rules.ts
372
+ async function validValue(rules, value) {
373
+ if (rules.required && (value === null || value === void 0 || value === "" || Number.isNaN(value)))
374
+ return { message: "This field is required" };
375
+ if (rules.type === "number" && Number.isNaN(Number(value)))
376
+ return { message: "This field must be a number" };
377
+ return rules.custom?.(value);
378
+ }
379
+ async function validValues(items, values) {
380
+ const errors = {};
381
+ for (const item of items) {
382
+ const value = values[item.name];
383
+ const rules = item.rules;
384
+ if (rules) {
385
+ const error = await validValue(rules, value);
386
+ if (error) errors[item.name] = error;
387
+ }
388
+ }
389
+ return errors;
390
+ }
368
391
  function FormFooter() {
369
- const { submitting, setSubmitting, onSubmit, values, Elements } = useFormContext();
392
+ const {
393
+ submitting,
394
+ setSubmitting,
395
+ onSubmit,
396
+ values,
397
+ Elements,
398
+ items,
399
+ setErrors
400
+ } = useFormContext();
370
401
  return /* @__PURE__ */ jsx(
371
402
  Elements.Button,
372
403
  {
373
404
  disabled: submitting,
374
- submit: () => {
405
+ submit: async () => {
375
406
  setSubmitting(true);
407
+ const errors = await validValues(items, values);
408
+ if (Object.keys(errors).length) {
409
+ setErrors(errors);
410
+ setSubmitting(false);
411
+ return;
412
+ }
376
413
  onSubmit(values).finally(() => setSubmitting(false));
377
414
  },
378
415
  children: "Submit"
@@ -404,7 +441,7 @@ var FormLabelElement = ({
404
441
  Label,
405
442
  input
406
443
  }) => {
407
- const { values, setValues } = useFormContext();
444
+ const { values, setValues, errors } = useFormContext();
408
445
  if (Label)
409
446
  return /* @__PURE__ */ jsx(
410
447
  Label,
@@ -438,7 +475,8 @@ var FormLabelElement = ({
438
475
  }))
439
476
  }
440
477
  ),
441
- description
478
+ description,
479
+ errors[name]?.message
442
480
  ] });
443
481
  };
444
482
  FormLabelElement.displayName = "FormLabelElement";
@@ -459,6 +497,7 @@ function mergeValues(items, defaultValues = {}) {
459
497
  function FormContainer({ defaultValues, elements, ...props }) {
460
498
  const states = useSplittingState({
461
499
  values: mergeValues(props.items, defaultValues),
500
+ errors: {},
462
501
  submitting: false,
463
502
  Elements: Object.assign(FormDefaultElements, elements)
464
503
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faasjs/react",
3
- "version": "3.7.0-beta.4",
3
+ "version": "3.7.0-beta.5",
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.4"
37
+ "@faasjs/browser": "3.7.0-beta.5"
38
38
  },
39
39
  "devDependencies": {
40
- "@faasjs/browser": "3.7.0-beta.4",
40
+ "@faasjs/browser": "3.7.0-beta.5",
41
41
  "@types/react": "*",
42
42
  "react": "*"
43
43
  },