@firecms/formex 3.0.0-canary.186 → 3.0.0-canary.188
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.es.js +54 -44
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +54 -44
- package/dist/index.umd.js.map +1 -1
- package/dist/useCreateFormex.d.ts +2 -1
- package/package.json +2 -2
- package/src/useCreateFormex.tsx +188 -118
package/dist/index.es.js
CHANGED
|
@@ -276,8 +276,9 @@ function useCreateFormex({
|
|
|
276
276
|
initialDirty,
|
|
277
277
|
validation,
|
|
278
278
|
validateOnChange = false,
|
|
279
|
-
onSubmit,
|
|
280
279
|
validateOnInitialRender = false,
|
|
280
|
+
onSubmit,
|
|
281
|
+
onReset,
|
|
281
282
|
debugId
|
|
282
283
|
}) {
|
|
283
284
|
const initialValuesRef = React__default.useRef(initialValues);
|
|
@@ -296,19 +297,19 @@ function useCreateFormex({
|
|
|
296
297
|
validate();
|
|
297
298
|
}
|
|
298
299
|
}, []);
|
|
299
|
-
const setValues = (newValues) => {
|
|
300
|
+
const setValues = React__default.useCallback((newValues) => {
|
|
300
301
|
valuesRef.current = newValues;
|
|
301
302
|
setValuesInner(newValues);
|
|
302
|
-
setDirty(equal(initialValuesRef.current, newValues));
|
|
303
|
-
};
|
|
304
|
-
const validate = async () => {
|
|
303
|
+
setDirty(!equal(initialValuesRef.current, newValues));
|
|
304
|
+
}, []);
|
|
305
|
+
const validate = React__default.useCallback(async () => {
|
|
305
306
|
setIsValidating(true);
|
|
306
307
|
const validationErrors = await validation?.(valuesRef.current);
|
|
307
308
|
setErrors(validationErrors ?? {});
|
|
308
309
|
setIsValidating(false);
|
|
309
310
|
return validationErrors;
|
|
310
|
-
};
|
|
311
|
-
const setFieldValue = (key, value, shouldValidate) => {
|
|
311
|
+
}, [validation]);
|
|
312
|
+
const setFieldValue = React__default.useCallback((key, value, shouldValidate) => {
|
|
312
313
|
const newValues_0 = setIn(valuesRef.current, key, value);
|
|
313
314
|
valuesRef.current = newValues_0;
|
|
314
315
|
setValuesInner(newValues_0);
|
|
@@ -318,29 +319,33 @@ function useCreateFormex({
|
|
|
318
319
|
if (shouldValidate) {
|
|
319
320
|
validate();
|
|
320
321
|
}
|
|
321
|
-
};
|
|
322
|
-
const setFieldError = (key_0, error) => {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
322
|
+
}, [validate]);
|
|
323
|
+
const setFieldError = React__default.useCallback((key_0, error) => {
|
|
324
|
+
setErrors((prevErrors) => {
|
|
325
|
+
const newErrors = {
|
|
326
|
+
...prevErrors
|
|
327
|
+
};
|
|
328
|
+
if (error) {
|
|
329
|
+
newErrors[key_0] = error;
|
|
330
|
+
} else {
|
|
331
|
+
delete newErrors[key_0];
|
|
332
|
+
}
|
|
333
|
+
return newErrors;
|
|
334
|
+
});
|
|
335
|
+
}, []);
|
|
336
|
+
const setFieldTouched = React__default.useCallback((key_1, touched, shouldValidate_0) => {
|
|
337
|
+
setTouchedState((prev) => {
|
|
338
|
+
const newTouched = {
|
|
339
|
+
...prev,
|
|
340
|
+
[key_1]: touched
|
|
341
|
+
};
|
|
342
|
+
return newTouched;
|
|
343
|
+
});
|
|
339
344
|
if (shouldValidate_0) {
|
|
340
345
|
validate();
|
|
341
346
|
}
|
|
342
|
-
};
|
|
343
|
-
const handleChange = (event) => {
|
|
347
|
+
}, [validate]);
|
|
348
|
+
const handleChange = React__default.useCallback((event) => {
|
|
344
349
|
const target = event.target;
|
|
345
350
|
let value_0;
|
|
346
351
|
if (target.type === "checkbox") {
|
|
@@ -353,17 +358,17 @@ function useCreateFormex({
|
|
|
353
358
|
const name = target.name;
|
|
354
359
|
setFieldValue(name, value_0, validateOnChange);
|
|
355
360
|
setFieldTouched(name, true);
|
|
356
|
-
};
|
|
357
|
-
const handleBlur = (event_0) => {
|
|
361
|
+
}, [setFieldValue, setFieldTouched, validateOnChange]);
|
|
362
|
+
const handleBlur = React__default.useCallback((event_0) => {
|
|
358
363
|
const target_0 = event_0.target;
|
|
359
364
|
const name_0 = target_0.name;
|
|
360
365
|
setFieldTouched(name_0, true);
|
|
361
|
-
};
|
|
362
|
-
const submit = async (e) => {
|
|
366
|
+
}, [setFieldTouched]);
|
|
367
|
+
const submit = React__default.useCallback(async (e) => {
|
|
363
368
|
e?.preventDefault();
|
|
364
369
|
e?.stopPropagation();
|
|
365
370
|
setIsSubmitting(true);
|
|
366
|
-
setSubmitCount(
|
|
371
|
+
setSubmitCount((prev_0) => prev_0 + 1);
|
|
367
372
|
const validationErrors_0 = await validation?.(valuesRef.current);
|
|
368
373
|
if (validationErrors_0 && Object.keys(validationErrors_0).length > 0) {
|
|
369
374
|
setErrors(validationErrors_0);
|
|
@@ -372,25 +377,27 @@ function useCreateFormex({
|
|
|
372
377
|
await onSubmit?.(valuesRef.current, controllerRef.current);
|
|
373
378
|
}
|
|
374
379
|
setIsSubmitting(false);
|
|
375
|
-
setVersion(
|
|
376
|
-
};
|
|
377
|
-
const resetForm = (props) => {
|
|
380
|
+
setVersion((prev_1) => prev_1 + 1);
|
|
381
|
+
}, [onSubmit, validation]);
|
|
382
|
+
const resetForm = React__default.useCallback((props) => {
|
|
378
383
|
const {
|
|
379
384
|
submitCount: submitCountProp,
|
|
380
385
|
values: valuesProp,
|
|
381
386
|
errors: errorsProp,
|
|
382
387
|
touched: touchedProp
|
|
383
388
|
} = props ?? {};
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
setValuesInner(valuesProp ??
|
|
389
|
+
valuesRef.current = valuesProp ?? initialValuesRef.current;
|
|
390
|
+
initialValuesRef.current = valuesProp ?? initialValuesRef.current;
|
|
391
|
+
setValuesInner(valuesProp ?? initialValuesRef.current);
|
|
387
392
|
setErrors(errorsProp ?? {});
|
|
388
393
|
setTouchedState(touchedProp ?? {});
|
|
389
394
|
setDirty(false);
|
|
390
395
|
setSubmitCount(submitCountProp ?? 0);
|
|
391
|
-
setVersion(
|
|
392
|
-
|
|
393
|
-
|
|
396
|
+
setVersion((prev_2) => prev_2 + 1);
|
|
397
|
+
onReset?.(controllerRef.current);
|
|
398
|
+
}, [onReset]);
|
|
399
|
+
const controllerRef = React__default.useRef({});
|
|
400
|
+
const controller = React__default.useMemo(() => ({
|
|
394
401
|
values,
|
|
395
402
|
initialValues: initialValuesRef.current,
|
|
396
403
|
handleChange,
|
|
@@ -404,18 +411,21 @@ function useCreateFormex({
|
|
|
404
411
|
setFieldTouched,
|
|
405
412
|
dirty,
|
|
406
413
|
setDirty,
|
|
414
|
+
// setter from useState is stable
|
|
407
415
|
handleSubmit: submit,
|
|
408
416
|
submitCount,
|
|
409
417
|
setSubmitCount,
|
|
418
|
+
// setter from useState is stable
|
|
410
419
|
handleBlur,
|
|
411
420
|
validate,
|
|
412
421
|
isValidating,
|
|
413
422
|
resetForm,
|
|
414
423
|
version,
|
|
415
424
|
debugId: debugIdRef.current
|
|
416
|
-
};
|
|
417
|
-
|
|
418
|
-
|
|
425
|
+
}), [values, errors, touchedState, dirty, isSubmitting, submitCount, isValidating, version, handleChange, handleBlur, setValues, setFieldValue, setFieldTouched, setFieldError, validate, submit, resetForm]);
|
|
426
|
+
React__default.useEffect(() => {
|
|
427
|
+
controllerRef.current = controller;
|
|
428
|
+
}, [controller]);
|
|
419
429
|
return controller;
|
|
420
430
|
}
|
|
421
431
|
export {
|
package/dist/index.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","sources":["../src/Formex.tsx","../src/utils.ts","../src/Field.tsx","../src/useCreateFormex.tsx"],"sourcesContent":["import React, { useContext } from \"react\";\nimport { FormexController } from \"./types\";\n\nconst FormexContext = React.createContext<FormexController<any>>({} as any);\n\nexport const useFormex = <T extends object>() => useContext<FormexController<T>>(FormexContext);\n\nexport const Formex = FormexContext.Provider;\n","import * as React from \"react\";\n\n/** @private is the value an empty array? */\nexport const isEmptyArray = (value?: any) =>\n Array.isArray(value) && value.length === 0;\n\n/** @private is the given object a Function? */\nexport const isFunction = (obj: any): obj is Function =>\n typeof obj === \"function\";\n\n/** @private is the given object an Object? */\nexport const isObject = (obj: any): obj is Object =>\n obj !== null && typeof obj === \"object\";\n\n/** @private is the given object an integer? */\nexport const isInteger = (obj: any): boolean =>\n String(Math.floor(Number(obj))) === obj;\n\n/** @private is the given object a string? */\nexport const isString = (obj: any): obj is string =>\n Object.prototype.toString.call(obj) === \"[object String]\";\n\n/** @private is the given object a NaN? */\n// eslint-disable-next-line no-self-compare\nexport const isNaN = (obj: any): boolean => obj !== obj;\n\n/** @private Does a React component have exactly 0 children? */\nexport const isEmptyChildren = (children: any): boolean =>\n React.Children.count(children) === 0;\n\n/** @private is the given object/value a promise? */\nexport const isPromise = (value: any): value is PromiseLike<any> =>\n isObject(value) && isFunction(value.then);\n\n/** @private is the given object/value a type of synthetic event? */\nexport const isInputEvent = (value: any): value is React.SyntheticEvent<any> =>\n value && isObject(value) && isObject(value.target);\n\n/**\n * Same as document.activeElement but wraps in a try-catch block. In IE it is\n * not safe to call document.activeElement if there is nothing focused.\n *\n * The activeElement will be null only if the document or document body is not\n * yet defined.\n *\n * @param {?Document} doc Defaults to current document.\n * @return {Element | null}\n * @see https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/dom/getActiveElement.js\n */\nexport function getActiveElement(doc?: Document): Element | null {\n doc = doc || (typeof document !== \"undefined\" ? document : undefined);\n if (typeof doc === \"undefined\") {\n return null;\n }\n try {\n return doc.activeElement || doc.body;\n } catch (e) {\n return doc.body;\n }\n}\n\n/**\n * Deeply get a value from an object via its path.\n */\nexport function getIn(\n obj: any,\n key: string | string[],\n def?: any,\n p = 0\n) {\n const path = toPath(key);\n while (obj && p < path.length) {\n obj = obj[path[p++]];\n }\n\n // check if path is not in the end\n if (p !== path.length && !obj) {\n return def;\n }\n\n return obj === undefined ? def : obj;\n}\n\nexport function setIn(obj: any, path: string, value: any): any {\n const res: any = clone(obj); // this keeps inheritance when obj is a class\n let resVal: any = res;\n let i = 0;\n const pathArray = toPath(path);\n\n for (; i < pathArray.length - 1; i++) {\n const currentPath: string = pathArray[i];\n const currentObj: any = getIn(obj, pathArray.slice(0, i + 1));\n\n if (currentObj && (isObject(currentObj) || Array.isArray(currentObj))) {\n resVal = resVal[currentPath] = clone(currentObj);\n } else {\n const nextPath: string = pathArray[i + 1];\n resVal = resVal[currentPath] =\n isInteger(nextPath) && Number(nextPath) >= 0 ? [] : {};\n }\n }\n\n // Return original object if new value is the same as current\n if ((i === 0 ? obj : resVal)[pathArray[i]] === value) {\n return obj;\n }\n\n if (value === undefined) {\n delete resVal[pathArray[i]];\n } else {\n resVal[pathArray[i]] = value;\n }\n\n // If the path array has a single element, the loop did not run.\n // Deleting on `resVal` had no effect in this scenario, so we delete on the result instead.\n if (i === 0 && value === undefined) {\n delete res[pathArray[i]];\n }\n\n return res;\n}\n\n/**\n * Recursively a set the same value for all keys and arrays nested object, cloning\n * @param object\n * @param value\n * @param visited\n * @param response\n */\nexport function setNestedObjectValues<T>(\n object: any,\n value: any,\n visited: any = new WeakMap(),\n response: any = {}\n): T {\n for (const k of Object.keys(object)) {\n const val = object[k];\n if (isObject(val)) {\n if (!visited.get(val)) {\n visited.set(val, true);\n // In order to keep array values consistent for both dot path and\n // bracket syntax, we need to check if this is an array so that\n // this will output { friends: [true] } and not { friends: { \"0\": true } }\n response[k] = Array.isArray(val) ? [] : {};\n setNestedObjectValues(val, value, visited, response[k]);\n }\n } else {\n response[k] = value;\n }\n }\n\n return response;\n}\n\nexport function clone(value: any) {\n if (Array.isArray(value)) {\n return [...value];\n } else if (typeof value === \"object\" && value !== null) {\n return { ...value };\n } else {\n return value; // This is for primitive types which do not need cloning.\n }\n}\n\nfunction toPath(value: string | string[]) {\n if (Array.isArray(value)) return value; // Already in path array form.\n // Replace brackets with dots, remove leading/trailing dots, then split by dot.\n return value.replace(/\\[(\\d+)]/g, \".$1\").replace(/^\\./, \"\").replace(/\\.$/, \"\").split(\".\");\n}\n","import * as React from \"react\";\nimport { useFormex } from \"./Formex\";\nimport { getIn, isFunction, isObject } from \"./utils\";\nimport { FormexController } from \"./types\";\n\nexport interface FieldInputProps<Value> {\n /** Value of the field */\n value: Value;\n /** Name of the field */\n name: string;\n /** Multiple select? */\n multiple?: boolean;\n /** Is the field checked? */\n checked?: boolean;\n /** Change event handler */\n onChange: (event: React.SyntheticEvent) => void,\n /** Blur event handler */\n onBlur: (event: React.FocusEvent) => void,\n}\n\nexport interface FormexFieldProps<Value = any, FormValues extends object = any> {\n field: FieldInputProps<Value>;\n form: FormexController<FormValues>;\n}\n\nexport interface FieldConfig<Value, C extends React.ElementType | undefined = undefined> {\n\n /**\n * Component to render. Can either be a string e.g. 'select', 'input', or 'textarea', or a component.\n */\n as?:\n | C\n | string\n | React.ForwardRefExoticComponent<any>;\n\n /**\n * Children render function <Field name>{props => ...}</Field>)\n */\n children?: ((props: FormexFieldProps<Value>) => React.ReactNode) | React.ReactNode;\n\n /**\n * Validate a single field value independently\n */\n // validate?: FieldValidator;\n\n /**\n * Used for 'select' and related input types.\n */\n multiple?: boolean;\n\n /**\n * Field name\n */\n name: string;\n\n /** HTML input type */\n type?: string;\n\n /** Field value */\n value?: any;\n\n /** Inner ref */\n innerRef?: (instance: any) => void;\n\n}\n\nexport type FieldProps<T, C extends React.ElementType | undefined> = {\n as?: C;\n} & (C extends React.ElementType ? (React.ComponentProps<C> & FieldConfig<T, C>) : FieldConfig<T, C>);\n\nexport function Field<T, C extends React.ElementType | undefined = undefined>({\n validate,\n name,\n children,\n as: is, // `as` is reserved in typescript lol\n // component,\n className,\n ...props\n }: FieldProps<T, C>) {\n const formex = useFormex();\n\n const field = getFieldProps({ name, ...props }, formex);\n\n if (isFunction(children)) {\n return children({ field, form: formex });\n }\n\n // if (component) {\n // if (typeof component === \"string\") {\n // const { innerRef, ...rest } = props;\n // return React.createElement(\n // component,\n // { ref: innerRef, ...field, ...rest, className },\n // children\n // );\n // }\n // return React.createElement(\n // component,\n // { field, form: formex, ...props, className },\n // children\n // );\n // }\n\n // default to input here so we can check for both `as` and `children` above\n const asElement = is || \"input\";\n\n if (typeof asElement === \"string\") {\n const { innerRef, ...rest } = props;\n return React.createElement(\n asElement,\n { ref: innerRef, ...field, ...rest, className },\n children\n );\n }\n\n return React.createElement(asElement, { ...field, ...props, className }, children);\n}\n\nconst getFieldProps = (nameOrOptions: string | FieldConfig<any>, formex: FormexController<any>): FieldInputProps<any> => {\n const isAnObject = isObject(nameOrOptions);\n const name = isAnObject\n ? (nameOrOptions as FieldConfig<any>).name\n : nameOrOptions;\n const valueState = getIn(formex.values, name);\n\n const field: FieldInputProps<any> = {\n name,\n value: valueState,\n onChange: formex.handleChange,\n onBlur: formex.handleBlur,\n };\n if (isAnObject) {\n const {\n type,\n value: valueProp, // value is special for checkboxes\n as: is,\n multiple,\n } = nameOrOptions as FieldConfig<any>;\n\n if (type === \"checkbox\") {\n if (valueProp === undefined) {\n field.checked = !!valueState;\n } else {\n field.checked = !!(\n Array.isArray(valueState) && ~valueState.indexOf(valueProp)\n );\n field.value = valueProp;\n }\n } else if (type === \"radio\") {\n field.checked = valueState === valueProp;\n field.value = valueProp;\n } else if (is === \"select\" && multiple) {\n field.value = field.value || [];\n field.multiple = true;\n }\n }\n return field;\n};\n","import React, { FormEvent, useEffect, useState } from \"react\";\nimport { getIn, setIn } from \"./utils\";\nimport equal from \"react-fast-compare\"\n\nimport { FormexController, FormexResetProps } from \"./types\";\n\nexport function useCreateFormex<T extends object>({\n initialValues,\n initialErrors,\n initialDirty,\n validation,\n validateOnChange = false,\n onSubmit,\n validateOnInitialRender = false,\n debugId\n }: {\n initialValues: T,\n initialErrors?: Record<string, string>,\n initialDirty?: boolean,\n validateOnChange?: boolean,\n validateOnInitialRender?: boolean,\n validation?: (values: T) => Record<string, string> | Promise<Record<string, string>> | undefined | void,\n onSubmit?: (values: T, controller: FormexController<T>) => void | Promise<void>,\n debugId?: string\n}): FormexController<T> {\n\n const initialValuesRef = React.useRef<T>(initialValues);\n const valuesRef = React.useRef<T>(initialValues);\n const debugIdRef = React.useRef<string | undefined>(debugId);\n\n const [values, setValuesInner] = useState<T>(initialValues);\n const [touchedState, setTouchedState] = useState<Record<string, boolean>>({});\n const [errors, setErrors] = useState<Record<string, string>>(initialErrors ?? {});\n const [dirty, setDirty] = useState(initialDirty ?? false);\n const [submitCount, setSubmitCount] = useState(0);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isValidating, setIsValidating] = useState(false);\n const [version, setVersion] = useState(0);\n\n useEffect(() => {\n if (validateOnInitialRender) {\n validate();\n }\n }, []);\n\n const setValues = (newValues: T) => {\n valuesRef.current = newValues;\n setValuesInner(newValues);\n setDirty(equal(initialValuesRef.current, newValues));\n }\n\n const validate = async () => {\n setIsValidating(true);\n const validationErrors = await validation?.(valuesRef.current);\n setErrors(validationErrors ?? {});\n setIsValidating(false);\n return validationErrors;\n }\n\n const setFieldValue = (key: string, value: any, shouldValidate?: boolean) => {\n const newValues = setIn(valuesRef.current, key, value);\n valuesRef.current = newValues;\n setValuesInner(newValues);\n if (!equal(getIn(initialValuesRef.current, key), value)) {\n setDirty(true);\n }\n if (shouldValidate) {\n validate();\n }\n }\n\n const setFieldError = (key: string, error: string | undefined) => {\n const newErrors = { ...errors };\n if (error) {\n newErrors[key] = error;\n } else {\n delete newErrors[key];\n }\n setErrors(newErrors);\n }\n\n const setFieldTouched = (key: string, touched: boolean, shouldValidate?: boolean | undefined) => {\n const newTouched = { ...touchedState };\n newTouched[key] = touched;\n setTouchedState(newTouched);\n if (shouldValidate) {\n validate();\n }\n }\n\n const handleChange = (event: React.SyntheticEvent) => {\n const target = event.target as HTMLInputElement;\n let value;\n if (target.type === \"checkbox\") {\n value = target.checked;\n } else if (target.type === \"number\") {\n value = target.valueAsNumber;\n } else {\n value = target.value;\n }\n const name = target.name;\n setFieldValue(name, value, validateOnChange);\n setFieldTouched(name, true);\n }\n\n const handleBlur = (event: React.FocusEvent) => {\n const target = event.target as HTMLInputElement;\n const name = target.name;\n setFieldTouched(name, true);\n }\n\n const submit = async (e?: FormEvent<HTMLFormElement>) => {\n e?.preventDefault();\n e?.stopPropagation();\n setIsSubmitting(true);\n setSubmitCount(submitCount + 1);\n const validationErrors = await validation?.(valuesRef.current);\n if (validationErrors && Object.keys(validationErrors).length > 0) {\n setErrors(validationErrors);\n } else {\n setErrors({});\n await onSubmit?.(valuesRef.current, controllerRef.current);\n }\n setIsSubmitting(false);\n setVersion(version + 1);\n }\n\n const resetForm = (props?: FormexResetProps<T>) => {\n const {\n submitCount: submitCountProp,\n values: valuesProp,\n errors: errorsProp,\n touched: touchedProp\n } = props ?? {};\n initialValuesRef.current = valuesProp ?? initialValues;\n valuesRef.current = valuesProp ?? initialValues;\n setValuesInner(valuesProp ?? initialValues);\n setErrors(errorsProp ?? {});\n setTouchedState(touchedProp ?? {});\n setDirty(false);\n setSubmitCount(submitCountProp ?? 0);\n setVersion(version + 1);\n }\n\n const controller: FormexController<T> = {\n values,\n initialValues: initialValuesRef.current,\n handleChange,\n isSubmitting,\n setSubmitting: setIsSubmitting,\n setValues,\n setFieldValue,\n errors,\n setFieldError,\n touched: touchedState,\n setFieldTouched,\n dirty,\n setDirty,\n handleSubmit: submit,\n submitCount,\n setSubmitCount,\n handleBlur,\n validate,\n isValidating,\n resetForm,\n version,\n debugId: debugIdRef.current\n };\n\n const controllerRef = React.useRef<FormexController<T>>(controller);\n controllerRef.current = controller;\n return controller\n}\n"],"names":["FormexContext","React","createContext","useFormex","useContext","Formex","Provider","isEmptyArray","value","Array","isArray","length","isFunction","obj","isObject","isInteger","String","Math","floor","Number","isString","Object","prototype","toString","call","isNaN","isEmptyChildren","children","Children","count","isPromise","then","isInputEvent","target","getActiveElement","doc","document","undefined","activeElement","body","e","getIn","key","def","p","path","toPath","setIn","res","clone","resVal","i","pathArray","currentPath","currentObj","slice","nextPath","setNestedObjectValues","object","visited","WeakMap","response","k","keys","val","get","set","replace","split","Field","t0","$","_c","className","is","name","props","validate","t1","t2","as","t3","t4","t5","formex","field","Symbol","for","getFieldProps","form","bb0","asElement","innerRef","rest","ref","createElement","nameOrOptions","isAnObject","valueState","values","onChange","handleChange","onBlur","handleBlur","type","valueProp","multiple","checked","indexOf","useCreateFormex","initialValues","initialErrors","initialDirty","validation","validateOnChange","onSubmit","validateOnInitialRender","debugId","initialValuesRef","useRef","valuesRef","debugIdRef","setValuesInner","useState","touchedState","setTouchedState","errors","setErrors","dirty","setDirty","submitCount","setSubmitCount","isSubmitting","setIsSubmitting","isValidating","setIsValidating","version","setVersion","useEffect","setValues","newValues","current","equal","validationErrors","setFieldValue","shouldValidate","setFieldError","error","newErrors","setFieldTouched","touched","newTouched","event","valueAsNumber","submit","preventDefault","stopPropagation","controllerRef","resetForm","submitCountProp","valuesProp","errorsProp","touchedProp","controller","setSubmitting","handleSubmit"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../src/Formex.tsx","../src/utils.ts","../src/Field.tsx","../src/useCreateFormex.tsx"],"sourcesContent":["import React, { useContext } from \"react\";\nimport { FormexController } from \"./types\";\n\nconst FormexContext = React.createContext<FormexController<any>>({} as any);\n\nexport const useFormex = <T extends object>() => useContext<FormexController<T>>(FormexContext);\n\nexport const Formex = FormexContext.Provider;\n","import * as React from \"react\";\n\n/** @private is the value an empty array? */\nexport const isEmptyArray = (value?: any) =>\n Array.isArray(value) && value.length === 0;\n\n/** @private is the given object a Function? */\nexport const isFunction = (obj: any): obj is Function =>\n typeof obj === \"function\";\n\n/** @private is the given object an Object? */\nexport const isObject = (obj: any): obj is Object =>\n obj !== null && typeof obj === \"object\";\n\n/** @private is the given object an integer? */\nexport const isInteger = (obj: any): boolean =>\n String(Math.floor(Number(obj))) === obj;\n\n/** @private is the given object a string? */\nexport const isString = (obj: any): obj is string =>\n Object.prototype.toString.call(obj) === \"[object String]\";\n\n/** @private is the given object a NaN? */\n// eslint-disable-next-line no-self-compare\nexport const isNaN = (obj: any): boolean => obj !== obj;\n\n/** @private Does a React component have exactly 0 children? */\nexport const isEmptyChildren = (children: any): boolean =>\n React.Children.count(children) === 0;\n\n/** @private is the given object/value a promise? */\nexport const isPromise = (value: any): value is PromiseLike<any> =>\n isObject(value) && isFunction(value.then);\n\n/** @private is the given object/value a type of synthetic event? */\nexport const isInputEvent = (value: any): value is React.SyntheticEvent<any> =>\n value && isObject(value) && isObject(value.target);\n\n/**\n * Same as document.activeElement but wraps in a try-catch block. In IE it is\n * not safe to call document.activeElement if there is nothing focused.\n *\n * The activeElement will be null only if the document or document body is not\n * yet defined.\n *\n * @param {?Document} doc Defaults to current document.\n * @return {Element | null}\n * @see https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/dom/getActiveElement.js\n */\nexport function getActiveElement(doc?: Document): Element | null {\n doc = doc || (typeof document !== \"undefined\" ? document : undefined);\n if (typeof doc === \"undefined\") {\n return null;\n }\n try {\n return doc.activeElement || doc.body;\n } catch (e) {\n return doc.body;\n }\n}\n\n/**\n * Deeply get a value from an object via its path.\n */\nexport function getIn(\n obj: any,\n key: string | string[],\n def?: any,\n p = 0\n) {\n const path = toPath(key);\n while (obj && p < path.length) {\n obj = obj[path[p++]];\n }\n\n // check if path is not in the end\n if (p !== path.length && !obj) {\n return def;\n }\n\n return obj === undefined ? def : obj;\n}\n\nexport function setIn(obj: any, path: string, value: any): any {\n const res: any = clone(obj); // this keeps inheritance when obj is a class\n let resVal: any = res;\n let i = 0;\n const pathArray = toPath(path);\n\n for (; i < pathArray.length - 1; i++) {\n const currentPath: string = pathArray[i];\n const currentObj: any = getIn(obj, pathArray.slice(0, i + 1));\n\n if (currentObj && (isObject(currentObj) || Array.isArray(currentObj))) {\n resVal = resVal[currentPath] = clone(currentObj);\n } else {\n const nextPath: string = pathArray[i + 1];\n resVal = resVal[currentPath] =\n isInteger(nextPath) && Number(nextPath) >= 0 ? [] : {};\n }\n }\n\n // Return original object if new value is the same as current\n if ((i === 0 ? obj : resVal)[pathArray[i]] === value) {\n return obj;\n }\n\n if (value === undefined) {\n delete resVal[pathArray[i]];\n } else {\n resVal[pathArray[i]] = value;\n }\n\n // If the path array has a single element, the loop did not run.\n // Deleting on `resVal` had no effect in this scenario, so we delete on the result instead.\n if (i === 0 && value === undefined) {\n delete res[pathArray[i]];\n }\n\n return res;\n}\n\n/**\n * Recursively a set the same value for all keys and arrays nested object, cloning\n * @param object\n * @param value\n * @param visited\n * @param response\n */\nexport function setNestedObjectValues<T>(\n object: any,\n value: any,\n visited: any = new WeakMap(),\n response: any = {}\n): T {\n for (const k of Object.keys(object)) {\n const val = object[k];\n if (isObject(val)) {\n if (!visited.get(val)) {\n visited.set(val, true);\n // In order to keep array values consistent for both dot path and\n // bracket syntax, we need to check if this is an array so that\n // this will output { friends: [true] } and not { friends: { \"0\": true } }\n response[k] = Array.isArray(val) ? [] : {};\n setNestedObjectValues(val, value, visited, response[k]);\n }\n } else {\n response[k] = value;\n }\n }\n\n return response;\n}\n\nexport function clone(value: any) {\n if (Array.isArray(value)) {\n return [...value];\n } else if (typeof value === \"object\" && value !== null) {\n return { ...value };\n } else {\n return value; // This is for primitive types which do not need cloning.\n }\n}\n\nfunction toPath(value: string | string[]) {\n if (Array.isArray(value)) return value; // Already in path array form.\n // Replace brackets with dots, remove leading/trailing dots, then split by dot.\n return value.replace(/\\[(\\d+)]/g, \".$1\").replace(/^\\./, \"\").replace(/\\.$/, \"\").split(\".\");\n}\n","import * as React from \"react\";\nimport { useFormex } from \"./Formex\";\nimport { getIn, isFunction, isObject } from \"./utils\";\nimport { FormexController } from \"./types\";\n\nexport interface FieldInputProps<Value> {\n /** Value of the field */\n value: Value;\n /** Name of the field */\n name: string;\n /** Multiple select? */\n multiple?: boolean;\n /** Is the field checked? */\n checked?: boolean;\n /** Change event handler */\n onChange: (event: React.SyntheticEvent) => void,\n /** Blur event handler */\n onBlur: (event: React.FocusEvent) => void,\n}\n\nexport interface FormexFieldProps<Value = any, FormValues extends object = any> {\n field: FieldInputProps<Value>;\n form: FormexController<FormValues>;\n}\n\nexport interface FieldConfig<Value, C extends React.ElementType | undefined = undefined> {\n\n /**\n * Component to render. Can either be a string e.g. 'select', 'input', or 'textarea', or a component.\n */\n as?:\n | C\n | string\n | React.ForwardRefExoticComponent<any>;\n\n /**\n * Children render function <Field name>{props => ...}</Field>)\n */\n children?: ((props: FormexFieldProps<Value>) => React.ReactNode) | React.ReactNode;\n\n /**\n * Validate a single field value independently\n */\n // validate?: FieldValidator;\n\n /**\n * Used for 'select' and related input types.\n */\n multiple?: boolean;\n\n /**\n * Field name\n */\n name: string;\n\n /** HTML input type */\n type?: string;\n\n /** Field value */\n value?: any;\n\n /** Inner ref */\n innerRef?: (instance: any) => void;\n\n}\n\nexport type FieldProps<T, C extends React.ElementType | undefined> = {\n as?: C;\n} & (C extends React.ElementType ? (React.ComponentProps<C> & FieldConfig<T, C>) : FieldConfig<T, C>);\n\nexport function Field<T, C extends React.ElementType | undefined = undefined>({\n validate,\n name,\n children,\n as: is, // `as` is reserved in typescript lol\n // component,\n className,\n ...props\n }: FieldProps<T, C>) {\n const formex = useFormex();\n\n const field = getFieldProps({ name, ...props }, formex);\n\n if (isFunction(children)) {\n return children({ field, form: formex });\n }\n\n // if (component) {\n // if (typeof component === \"string\") {\n // const { innerRef, ...rest } = props;\n // return React.createElement(\n // component,\n // { ref: innerRef, ...field, ...rest, className },\n // children\n // );\n // }\n // return React.createElement(\n // component,\n // { field, form: formex, ...props, className },\n // children\n // );\n // }\n\n // default to input here so we can check for both `as` and `children` above\n const asElement = is || \"input\";\n\n if (typeof asElement === \"string\") {\n const { innerRef, ...rest } = props;\n return React.createElement(\n asElement,\n { ref: innerRef, ...field, ...rest, className },\n children\n );\n }\n\n return React.createElement(asElement, { ...field, ...props, className }, children);\n}\n\nconst getFieldProps = (nameOrOptions: string | FieldConfig<any>, formex: FormexController<any>): FieldInputProps<any> => {\n const isAnObject = isObject(nameOrOptions);\n const name = isAnObject\n ? (nameOrOptions as FieldConfig<any>).name\n : nameOrOptions;\n const valueState = getIn(formex.values, name);\n\n const field: FieldInputProps<any> = {\n name,\n value: valueState,\n onChange: formex.handleChange,\n onBlur: formex.handleBlur,\n };\n if (isAnObject) {\n const {\n type,\n value: valueProp, // value is special for checkboxes\n as: is,\n multiple,\n } = nameOrOptions as FieldConfig<any>;\n\n if (type === \"checkbox\") {\n if (valueProp === undefined) {\n field.checked = !!valueState;\n } else {\n field.checked = !!(\n Array.isArray(valueState) && ~valueState.indexOf(valueProp)\n );\n field.value = valueProp;\n }\n } else if (type === \"radio\") {\n field.checked = valueState === valueProp;\n field.value = valueProp;\n } else if (is === \"select\" && multiple) {\n field.value = field.value || [];\n field.multiple = true;\n }\n }\n return field;\n};\n","import React, { useEffect, useState } from \"react\";\nimport { getIn, setIn } from \"./utils\";\nimport equal from \"react-fast-compare\"\n\nimport { FormexController, FormexResetProps } from \"./types\";\n\nexport function useCreateFormex<T extends object>({\n initialValues,\n initialErrors,\n initialDirty,\n validation,\n validateOnChange = false,\n validateOnInitialRender = false,\n onSubmit,\n onReset,\n debugId,\n }: {\n initialValues: T;\n initialErrors?: Record<string, string>;\n initialDirty?: boolean;\n validateOnChange?: boolean;\n validateOnInitialRender?: boolean;\n validation?: (\n values: T\n ) =>\n | Record<string, string>\n | Promise<Record<string, string>>\n | undefined\n | void;\n onSubmit?: (values: T, controller: FormexController<T>) => void | Promise<void>;\n onReset?: (controller: FormexController<T>) => void | Promise<void>;\n debugId?: string;\n}): FormexController<T> {\n // Refs (for current state which shouldn’t trigger re – renders)\n const initialValuesRef = React.useRef<T>(initialValues);\n const valuesRef = React.useRef<T>(initialValues);\n const debugIdRef = React.useRef<string | undefined>(debugId);\n\n // State\n const [values, setValuesInner] = useState<T>(initialValues);\n const [touchedState, setTouchedState] = useState<Record<string, boolean>>({});\n const [errors, setErrors] = useState<Record<string, string>>(initialErrors ?? {});\n const [dirty, setDirty] = useState(initialDirty ?? false);\n const [submitCount, setSubmitCount] = useState(0);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isValidating, setIsValidating] = useState(false);\n const [version, setVersion] = useState(0);\n\n // Run initial validation if required\n useEffect(() => {\n if (validateOnInitialRender) {\n validate();\n }\n }, []);\n\n // Memoize setValues so that it doesn’t change unless nothing inside changes.\n const setValues = React.useCallback((newValues: T) => {\n valuesRef.current = newValues;\n setValuesInner(newValues);\n // Adjust dirty flag by comparing with the initial values\n setDirty(!equal(initialValuesRef.current, newValues));\n }, []);\n\n // Memoized validate function\n const validate = React.useCallback(async () => {\n setIsValidating(true);\n const validationErrors = await validation?.(valuesRef.current);\n setErrors(validationErrors ?? {});\n setIsValidating(false);\n return validationErrors;\n }, [validation]);\n\n // setFieldValue updates a single field and optionally triggers validation\n const setFieldValue = React.useCallback(\n (key: string, value: any, shouldValidate?: boolean) => {\n const newValues = setIn(valuesRef.current, key, value);\n valuesRef.current = newValues;\n setValuesInner(newValues);\n // Compare with initial value using getIn\n if (!equal(getIn(initialValuesRef.current, key), value)) {\n setDirty(true);\n }\n if (shouldValidate) {\n validate();\n }\n },\n [validate]\n );\n\n // setFieldError uses functional updates to ensure we’re working off the current error state.\n const setFieldError = React.useCallback((key: string, error: string | undefined) => {\n setErrors((prevErrors) => {\n const newErrors = { ...prevErrors };\n if (error) {\n newErrors[key] = error;\n } else {\n delete newErrors[key];\n }\n return newErrors;\n });\n }, []);\n\n // setFieldTouched updates touched state and can optionally trigger validation.\n const setFieldTouched = React.useCallback(\n (key: string, touched: boolean, shouldValidate?: boolean) => {\n setTouchedState((prev) => {\n const newTouched = {\n ...prev,\n [key]: touched\n };\n return newTouched;\n });\n if (shouldValidate) {\n validate();\n }\n },\n [validate]\n );\n\n // handleChange reads the event, determines the proper value,\n // and then delegates to setFieldValue and setFieldTouched.\n const handleChange = React.useCallback(\n (event: React.SyntheticEvent) => {\n const target = event.target as HTMLInputElement;\n let value;\n if (target.type === \"checkbox\") {\n value = target.checked;\n } else if (target.type === \"number\") {\n value = target.valueAsNumber;\n } else {\n value = target.value;\n }\n const name = target.name;\n setFieldValue(name, value, validateOnChange);\n setFieldTouched(name, true);\n },\n [setFieldValue, setFieldTouched, validateOnChange]\n );\n\n // handleBlur simply marks the field as touched.\n const handleBlur = React.useCallback((event: React.FocusEvent) => {\n const target = event.target as HTMLInputElement;\n const name = target.name;\n setFieldTouched(name, true);\n }, [setFieldTouched]);\n\n // submit uses functional updates on submitCount and version.\n const submit = React.useCallback(\n async (e?: React.FormEvent<HTMLFormElement>) => {\n e?.preventDefault();\n e?.stopPropagation();\n setIsSubmitting(true);\n setSubmitCount((prev) => prev + 1);\n const validationErrors = await validation?.(valuesRef.current);\n if (validationErrors && Object.keys(validationErrors).length > 0) {\n setErrors(validationErrors);\n } else {\n setErrors({});\n await onSubmit?.(valuesRef.current, controllerRef.current);\n }\n setIsSubmitting(false);\n setVersion((prev) => prev + 1);\n },\n [onSubmit, validation]\n );\n\n // resetForm resets to the passed props (or initial configuration).\n const resetForm = React.useCallback((props?: FormexResetProps<T>) => {\n const {\n submitCount: submitCountProp,\n values: valuesProp,\n errors: errorsProp,\n touched: touchedProp\n } =\n props ?? {};\n valuesRef.current = valuesProp ?? initialValuesRef.current;\n initialValuesRef.current = valuesProp ?? initialValuesRef.current;\n setValuesInner(valuesProp ?? initialValuesRef.current);\n setErrors(errorsProp ?? {});\n setTouchedState(touchedProp ?? {});\n setDirty(false);\n setSubmitCount(submitCountProp ?? 0);\n setVersion((prev) => prev + 1);\n onReset?.(controllerRef.current);\n }, [onReset]);\n\n // Create a ref for the controller so that it remains stable over time.\n const controllerRef = React.useRef<FormexController<T>>({} as FormexController<T>);\n\n // Memoize the controller object so that consumers don’t see new references on every render.\n const controller = React.useMemo<FormexController<T>>(\n () => ({\n values,\n initialValues: initialValuesRef.current,\n handleChange,\n isSubmitting,\n setSubmitting: setIsSubmitting,\n setValues,\n setFieldValue,\n errors,\n setFieldError,\n touched: touchedState,\n setFieldTouched,\n dirty,\n setDirty, // setter from useState is stable\n handleSubmit: submit,\n submitCount,\n setSubmitCount, // setter from useState is stable\n handleBlur,\n validate,\n isValidating,\n resetForm,\n version,\n debugId: debugIdRef.current,\n }),\n [\n values,\n errors,\n touchedState,\n dirty,\n isSubmitting,\n submitCount,\n isValidating,\n version,\n handleChange,\n handleBlur,\n setValues,\n setFieldValue,\n setFieldTouched,\n setFieldError,\n validate,\n submit,\n resetForm,\n ]\n );\n\n // Keep the ref updated with the latest controller\n React.useEffect(() => {\n controllerRef.current = controller;\n }, [controller]);\n\n return controller;\n}\n"],"names":["FormexContext","React","createContext","useFormex","useContext","Formex","Provider","isEmptyArray","value","Array","isArray","length","isFunction","obj","isObject","isInteger","String","Math","floor","Number","isString","Object","prototype","toString","call","isNaN","isEmptyChildren","children","Children","count","isPromise","then","isInputEvent","target","getActiveElement","doc","document","undefined","activeElement","body","e","getIn","key","def","p","path","toPath","setIn","res","clone","resVal","i","pathArray","currentPath","currentObj","slice","nextPath","setNestedObjectValues","object","visited","WeakMap","response","k","keys","val","get","set","replace","split","Field","t0","$","_c","className","is","name","props","validate","t1","t2","as","t3","t4","t5","formex","field","Symbol","for","getFieldProps","form","bb0","asElement","innerRef","rest","ref","createElement","nameOrOptions","isAnObject","valueState","values","onChange","handleChange","onBlur","handleBlur","type","valueProp","multiple","checked","indexOf","useCreateFormex","initialValues","initialErrors","initialDirty","validation","validateOnChange","validateOnInitialRender","onSubmit","onReset","debugId","initialValuesRef","useRef","valuesRef","debugIdRef","setValuesInner","useState","touchedState","setTouchedState","errors","setErrors","dirty","setDirty","submitCount","setSubmitCount","isSubmitting","setIsSubmitting","isValidating","setIsValidating","version","setVersion","useEffect","setValues","useCallback","newValues","current","equal","validationErrors","setFieldValue","shouldValidate","setFieldError","error","prevErrors","newErrors","setFieldTouched","touched","prev","newTouched","event","valueAsNumber","submit","preventDefault","stopPropagation","controllerRef","resetForm","submitCountProp","valuesProp","errorsProp","touchedProp","controller","useMemo","setSubmitting","handleSubmit"],"mappings":"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"}
|
package/dist/index.umd.js
CHANGED
|
@@ -293,8 +293,9 @@
|
|
|
293
293
|
initialDirty,
|
|
294
294
|
validation,
|
|
295
295
|
validateOnChange = false,
|
|
296
|
-
onSubmit,
|
|
297
296
|
validateOnInitialRender = false,
|
|
297
|
+
onSubmit,
|
|
298
|
+
onReset,
|
|
298
299
|
debugId
|
|
299
300
|
}) {
|
|
300
301
|
const initialValuesRef = React.useRef(initialValues);
|
|
@@ -313,19 +314,19 @@
|
|
|
313
314
|
validate();
|
|
314
315
|
}
|
|
315
316
|
}, []);
|
|
316
|
-
const setValues = (newValues) => {
|
|
317
|
+
const setValues = React.useCallback((newValues) => {
|
|
317
318
|
valuesRef.current = newValues;
|
|
318
319
|
setValuesInner(newValues);
|
|
319
|
-
setDirty(equal(initialValuesRef.current, newValues));
|
|
320
|
-
};
|
|
321
|
-
const validate = async () => {
|
|
320
|
+
setDirty(!equal(initialValuesRef.current, newValues));
|
|
321
|
+
}, []);
|
|
322
|
+
const validate = React.useCallback(async () => {
|
|
322
323
|
setIsValidating(true);
|
|
323
324
|
const validationErrors = await validation?.(valuesRef.current);
|
|
324
325
|
setErrors(validationErrors ?? {});
|
|
325
326
|
setIsValidating(false);
|
|
326
327
|
return validationErrors;
|
|
327
|
-
};
|
|
328
|
-
const setFieldValue = (key, value, shouldValidate) => {
|
|
328
|
+
}, [validation]);
|
|
329
|
+
const setFieldValue = React.useCallback((key, value, shouldValidate) => {
|
|
329
330
|
const newValues_0 = setIn(valuesRef.current, key, value);
|
|
330
331
|
valuesRef.current = newValues_0;
|
|
331
332
|
setValuesInner(newValues_0);
|
|
@@ -335,29 +336,33 @@
|
|
|
335
336
|
if (shouldValidate) {
|
|
336
337
|
validate();
|
|
337
338
|
}
|
|
338
|
-
};
|
|
339
|
-
const setFieldError = (key_0, error) => {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
339
|
+
}, [validate]);
|
|
340
|
+
const setFieldError = React.useCallback((key_0, error) => {
|
|
341
|
+
setErrors((prevErrors) => {
|
|
342
|
+
const newErrors = {
|
|
343
|
+
...prevErrors
|
|
344
|
+
};
|
|
345
|
+
if (error) {
|
|
346
|
+
newErrors[key_0] = error;
|
|
347
|
+
} else {
|
|
348
|
+
delete newErrors[key_0];
|
|
349
|
+
}
|
|
350
|
+
return newErrors;
|
|
351
|
+
});
|
|
352
|
+
}, []);
|
|
353
|
+
const setFieldTouched = React.useCallback((key_1, touched, shouldValidate_0) => {
|
|
354
|
+
setTouchedState((prev) => {
|
|
355
|
+
const newTouched = {
|
|
356
|
+
...prev,
|
|
357
|
+
[key_1]: touched
|
|
358
|
+
};
|
|
359
|
+
return newTouched;
|
|
360
|
+
});
|
|
356
361
|
if (shouldValidate_0) {
|
|
357
362
|
validate();
|
|
358
363
|
}
|
|
359
|
-
};
|
|
360
|
-
const handleChange = (event) => {
|
|
364
|
+
}, [validate]);
|
|
365
|
+
const handleChange = React.useCallback((event) => {
|
|
361
366
|
const target = event.target;
|
|
362
367
|
let value_0;
|
|
363
368
|
if (target.type === "checkbox") {
|
|
@@ -370,17 +375,17 @@
|
|
|
370
375
|
const name = target.name;
|
|
371
376
|
setFieldValue(name, value_0, validateOnChange);
|
|
372
377
|
setFieldTouched(name, true);
|
|
373
|
-
};
|
|
374
|
-
const handleBlur = (event_0) => {
|
|
378
|
+
}, [setFieldValue, setFieldTouched, validateOnChange]);
|
|
379
|
+
const handleBlur = React.useCallback((event_0) => {
|
|
375
380
|
const target_0 = event_0.target;
|
|
376
381
|
const name_0 = target_0.name;
|
|
377
382
|
setFieldTouched(name_0, true);
|
|
378
|
-
};
|
|
379
|
-
const submit = async (e) => {
|
|
383
|
+
}, [setFieldTouched]);
|
|
384
|
+
const submit = React.useCallback(async (e) => {
|
|
380
385
|
e?.preventDefault();
|
|
381
386
|
e?.stopPropagation();
|
|
382
387
|
setIsSubmitting(true);
|
|
383
|
-
setSubmitCount(
|
|
388
|
+
setSubmitCount((prev_0) => prev_0 + 1);
|
|
384
389
|
const validationErrors_0 = await validation?.(valuesRef.current);
|
|
385
390
|
if (validationErrors_0 && Object.keys(validationErrors_0).length > 0) {
|
|
386
391
|
setErrors(validationErrors_0);
|
|
@@ -389,25 +394,27 @@
|
|
|
389
394
|
await onSubmit?.(valuesRef.current, controllerRef.current);
|
|
390
395
|
}
|
|
391
396
|
setIsSubmitting(false);
|
|
392
|
-
setVersion(
|
|
393
|
-
};
|
|
394
|
-
const resetForm = (props) => {
|
|
397
|
+
setVersion((prev_1) => prev_1 + 1);
|
|
398
|
+
}, [onSubmit, validation]);
|
|
399
|
+
const resetForm = React.useCallback((props) => {
|
|
395
400
|
const {
|
|
396
401
|
submitCount: submitCountProp,
|
|
397
402
|
values: valuesProp,
|
|
398
403
|
errors: errorsProp,
|
|
399
404
|
touched: touchedProp
|
|
400
405
|
} = props ?? {};
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
setValuesInner(valuesProp ??
|
|
406
|
+
valuesRef.current = valuesProp ?? initialValuesRef.current;
|
|
407
|
+
initialValuesRef.current = valuesProp ?? initialValuesRef.current;
|
|
408
|
+
setValuesInner(valuesProp ?? initialValuesRef.current);
|
|
404
409
|
setErrors(errorsProp ?? {});
|
|
405
410
|
setTouchedState(touchedProp ?? {});
|
|
406
411
|
setDirty(false);
|
|
407
412
|
setSubmitCount(submitCountProp ?? 0);
|
|
408
|
-
setVersion(
|
|
409
|
-
|
|
410
|
-
|
|
413
|
+
setVersion((prev_2) => prev_2 + 1);
|
|
414
|
+
onReset?.(controllerRef.current);
|
|
415
|
+
}, [onReset]);
|
|
416
|
+
const controllerRef = React.useRef({});
|
|
417
|
+
const controller = React.useMemo(() => ({
|
|
411
418
|
values,
|
|
412
419
|
initialValues: initialValuesRef.current,
|
|
413
420
|
handleChange,
|
|
@@ -421,18 +428,21 @@
|
|
|
421
428
|
setFieldTouched,
|
|
422
429
|
dirty,
|
|
423
430
|
setDirty,
|
|
431
|
+
// setter from useState is stable
|
|
424
432
|
handleSubmit: submit,
|
|
425
433
|
submitCount,
|
|
426
434
|
setSubmitCount,
|
|
435
|
+
// setter from useState is stable
|
|
427
436
|
handleBlur,
|
|
428
437
|
validate,
|
|
429
438
|
isValidating,
|
|
430
439
|
resetForm,
|
|
431
440
|
version,
|
|
432
441
|
debugId: debugIdRef.current
|
|
433
|
-
};
|
|
434
|
-
|
|
435
|
-
|
|
442
|
+
}), [values, errors, touchedState, dirty, isSubmitting, submitCount, isValidating, version, handleChange, handleBlur, setValues, setFieldValue, setFieldTouched, setFieldError, validate, submit, resetForm]);
|
|
443
|
+
React.useEffect(() => {
|
|
444
|
+
controllerRef.current = controller;
|
|
445
|
+
}, [controller]);
|
|
436
446
|
return controller;
|
|
437
447
|
}
|
|
438
448
|
exports2.Field = Field;
|
package/dist/index.umd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.umd.js","sources":["../src/Formex.tsx","../src/utils.ts","../src/Field.tsx","../src/useCreateFormex.tsx"],"sourcesContent":["import React, { useContext } from \"react\";\nimport { FormexController } from \"./types\";\n\nconst FormexContext = React.createContext<FormexController<any>>({} as any);\n\nexport const useFormex = <T extends object>() => useContext<FormexController<T>>(FormexContext);\n\nexport const Formex = FormexContext.Provider;\n","import * as React from \"react\";\n\n/** @private is the value an empty array? */\nexport const isEmptyArray = (value?: any) =>\n Array.isArray(value) && value.length === 0;\n\n/** @private is the given object a Function? */\nexport const isFunction = (obj: any): obj is Function =>\n typeof obj === \"function\";\n\n/** @private is the given object an Object? */\nexport const isObject = (obj: any): obj is Object =>\n obj !== null && typeof obj === \"object\";\n\n/** @private is the given object an integer? */\nexport const isInteger = (obj: any): boolean =>\n String(Math.floor(Number(obj))) === obj;\n\n/** @private is the given object a string? */\nexport const isString = (obj: any): obj is string =>\n Object.prototype.toString.call(obj) === \"[object String]\";\n\n/** @private is the given object a NaN? */\n// eslint-disable-next-line no-self-compare\nexport const isNaN = (obj: any): boolean => obj !== obj;\n\n/** @private Does a React component have exactly 0 children? */\nexport const isEmptyChildren = (children: any): boolean =>\n React.Children.count(children) === 0;\n\n/** @private is the given object/value a promise? */\nexport const isPromise = (value: any): value is PromiseLike<any> =>\n isObject(value) && isFunction(value.then);\n\n/** @private is the given object/value a type of synthetic event? */\nexport const isInputEvent = (value: any): value is React.SyntheticEvent<any> =>\n value && isObject(value) && isObject(value.target);\n\n/**\n * Same as document.activeElement but wraps in a try-catch block. In IE it is\n * not safe to call document.activeElement if there is nothing focused.\n *\n * The activeElement will be null only if the document or document body is not\n * yet defined.\n *\n * @param {?Document} doc Defaults to current document.\n * @return {Element | null}\n * @see https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/dom/getActiveElement.js\n */\nexport function getActiveElement(doc?: Document): Element | null {\n doc = doc || (typeof document !== \"undefined\" ? document : undefined);\n if (typeof doc === \"undefined\") {\n return null;\n }\n try {\n return doc.activeElement || doc.body;\n } catch (e) {\n return doc.body;\n }\n}\n\n/**\n * Deeply get a value from an object via its path.\n */\nexport function getIn(\n obj: any,\n key: string | string[],\n def?: any,\n p = 0\n) {\n const path = toPath(key);\n while (obj && p < path.length) {\n obj = obj[path[p++]];\n }\n\n // check if path is not in the end\n if (p !== path.length && !obj) {\n return def;\n }\n\n return obj === undefined ? def : obj;\n}\n\nexport function setIn(obj: any, path: string, value: any): any {\n const res: any = clone(obj); // this keeps inheritance when obj is a class\n let resVal: any = res;\n let i = 0;\n const pathArray = toPath(path);\n\n for (; i < pathArray.length - 1; i++) {\n const currentPath: string = pathArray[i];\n const currentObj: any = getIn(obj, pathArray.slice(0, i + 1));\n\n if (currentObj && (isObject(currentObj) || Array.isArray(currentObj))) {\n resVal = resVal[currentPath] = clone(currentObj);\n } else {\n const nextPath: string = pathArray[i + 1];\n resVal = resVal[currentPath] =\n isInteger(nextPath) && Number(nextPath) >= 0 ? [] : {};\n }\n }\n\n // Return original object if new value is the same as current\n if ((i === 0 ? obj : resVal)[pathArray[i]] === value) {\n return obj;\n }\n\n if (value === undefined) {\n delete resVal[pathArray[i]];\n } else {\n resVal[pathArray[i]] = value;\n }\n\n // If the path array has a single element, the loop did not run.\n // Deleting on `resVal` had no effect in this scenario, so we delete on the result instead.\n if (i === 0 && value === undefined) {\n delete res[pathArray[i]];\n }\n\n return res;\n}\n\n/**\n * Recursively a set the same value for all keys and arrays nested object, cloning\n * @param object\n * @param value\n * @param visited\n * @param response\n */\nexport function setNestedObjectValues<T>(\n object: any,\n value: any,\n visited: any = new WeakMap(),\n response: any = {}\n): T {\n for (const k of Object.keys(object)) {\n const val = object[k];\n if (isObject(val)) {\n if (!visited.get(val)) {\n visited.set(val, true);\n // In order to keep array values consistent for both dot path and\n // bracket syntax, we need to check if this is an array so that\n // this will output { friends: [true] } and not { friends: { \"0\": true } }\n response[k] = Array.isArray(val) ? [] : {};\n setNestedObjectValues(val, value, visited, response[k]);\n }\n } else {\n response[k] = value;\n }\n }\n\n return response;\n}\n\nexport function clone(value: any) {\n if (Array.isArray(value)) {\n return [...value];\n } else if (typeof value === \"object\" && value !== null) {\n return { ...value };\n } else {\n return value; // This is for primitive types which do not need cloning.\n }\n}\n\nfunction toPath(value: string | string[]) {\n if (Array.isArray(value)) return value; // Already in path array form.\n // Replace brackets with dots, remove leading/trailing dots, then split by dot.\n return value.replace(/\\[(\\d+)]/g, \".$1\").replace(/^\\./, \"\").replace(/\\.$/, \"\").split(\".\");\n}\n","import * as React from \"react\";\nimport { useFormex } from \"./Formex\";\nimport { getIn, isFunction, isObject } from \"./utils\";\nimport { FormexController } from \"./types\";\n\nexport interface FieldInputProps<Value> {\n /** Value of the field */\n value: Value;\n /** Name of the field */\n name: string;\n /** Multiple select? */\n multiple?: boolean;\n /** Is the field checked? */\n checked?: boolean;\n /** Change event handler */\n onChange: (event: React.SyntheticEvent) => void,\n /** Blur event handler */\n onBlur: (event: React.FocusEvent) => void,\n}\n\nexport interface FormexFieldProps<Value = any, FormValues extends object = any> {\n field: FieldInputProps<Value>;\n form: FormexController<FormValues>;\n}\n\nexport interface FieldConfig<Value, C extends React.ElementType | undefined = undefined> {\n\n /**\n * Component to render. Can either be a string e.g. 'select', 'input', or 'textarea', or a component.\n */\n as?:\n | C\n | string\n | React.ForwardRefExoticComponent<any>;\n\n /**\n * Children render function <Field name>{props => ...}</Field>)\n */\n children?: ((props: FormexFieldProps<Value>) => React.ReactNode) | React.ReactNode;\n\n /**\n * Validate a single field value independently\n */\n // validate?: FieldValidator;\n\n /**\n * Used for 'select' and related input types.\n */\n multiple?: boolean;\n\n /**\n * Field name\n */\n name: string;\n\n /** HTML input type */\n type?: string;\n\n /** Field value */\n value?: any;\n\n /** Inner ref */\n innerRef?: (instance: any) => void;\n\n}\n\nexport type FieldProps<T, C extends React.ElementType | undefined> = {\n as?: C;\n} & (C extends React.ElementType ? (React.ComponentProps<C> & FieldConfig<T, C>) : FieldConfig<T, C>);\n\nexport function Field<T, C extends React.ElementType | undefined = undefined>({\n validate,\n name,\n children,\n as: is, // `as` is reserved in typescript lol\n // component,\n className,\n ...props\n }: FieldProps<T, C>) {\n const formex = useFormex();\n\n const field = getFieldProps({ name, ...props }, formex);\n\n if (isFunction(children)) {\n return children({ field, form: formex });\n }\n\n // if (component) {\n // if (typeof component === \"string\") {\n // const { innerRef, ...rest } = props;\n // return React.createElement(\n // component,\n // { ref: innerRef, ...field, ...rest, className },\n // children\n // );\n // }\n // return React.createElement(\n // component,\n // { field, form: formex, ...props, className },\n // children\n // );\n // }\n\n // default to input here so we can check for both `as` and `children` above\n const asElement = is || \"input\";\n\n if (typeof asElement === \"string\") {\n const { innerRef, ...rest } = props;\n return React.createElement(\n asElement,\n { ref: innerRef, ...field, ...rest, className },\n children\n );\n }\n\n return React.createElement(asElement, { ...field, ...props, className }, children);\n}\n\nconst getFieldProps = (nameOrOptions: string | FieldConfig<any>, formex: FormexController<any>): FieldInputProps<any> => {\n const isAnObject = isObject(nameOrOptions);\n const name = isAnObject\n ? (nameOrOptions as FieldConfig<any>).name\n : nameOrOptions;\n const valueState = getIn(formex.values, name);\n\n const field: FieldInputProps<any> = {\n name,\n value: valueState,\n onChange: formex.handleChange,\n onBlur: formex.handleBlur,\n };\n if (isAnObject) {\n const {\n type,\n value: valueProp, // value is special for checkboxes\n as: is,\n multiple,\n } = nameOrOptions as FieldConfig<any>;\n\n if (type === \"checkbox\") {\n if (valueProp === undefined) {\n field.checked = !!valueState;\n } else {\n field.checked = !!(\n Array.isArray(valueState) && ~valueState.indexOf(valueProp)\n );\n field.value = valueProp;\n }\n } else if (type === \"radio\") {\n field.checked = valueState === valueProp;\n field.value = valueProp;\n } else if (is === \"select\" && multiple) {\n field.value = field.value || [];\n field.multiple = true;\n }\n }\n return field;\n};\n","import React, { FormEvent, useEffect, useState } from \"react\";\nimport { getIn, setIn } from \"./utils\";\nimport equal from \"react-fast-compare\"\n\nimport { FormexController, FormexResetProps } from \"./types\";\n\nexport function useCreateFormex<T extends object>({\n initialValues,\n initialErrors,\n initialDirty,\n validation,\n validateOnChange = false,\n onSubmit,\n validateOnInitialRender = false,\n debugId\n }: {\n initialValues: T,\n initialErrors?: Record<string, string>,\n initialDirty?: boolean,\n validateOnChange?: boolean,\n validateOnInitialRender?: boolean,\n validation?: (values: T) => Record<string, string> | Promise<Record<string, string>> | undefined | void,\n onSubmit?: (values: T, controller: FormexController<T>) => void | Promise<void>,\n debugId?: string\n}): FormexController<T> {\n\n const initialValuesRef = React.useRef<T>(initialValues);\n const valuesRef = React.useRef<T>(initialValues);\n const debugIdRef = React.useRef<string | undefined>(debugId);\n\n const [values, setValuesInner] = useState<T>(initialValues);\n const [touchedState, setTouchedState] = useState<Record<string, boolean>>({});\n const [errors, setErrors] = useState<Record<string, string>>(initialErrors ?? {});\n const [dirty, setDirty] = useState(initialDirty ?? false);\n const [submitCount, setSubmitCount] = useState(0);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isValidating, setIsValidating] = useState(false);\n const [version, setVersion] = useState(0);\n\n useEffect(() => {\n if (validateOnInitialRender) {\n validate();\n }\n }, []);\n\n const setValues = (newValues: T) => {\n valuesRef.current = newValues;\n setValuesInner(newValues);\n setDirty(equal(initialValuesRef.current, newValues));\n }\n\n const validate = async () => {\n setIsValidating(true);\n const validationErrors = await validation?.(valuesRef.current);\n setErrors(validationErrors ?? {});\n setIsValidating(false);\n return validationErrors;\n }\n\n const setFieldValue = (key: string, value: any, shouldValidate?: boolean) => {\n const newValues = setIn(valuesRef.current, key, value);\n valuesRef.current = newValues;\n setValuesInner(newValues);\n if (!equal(getIn(initialValuesRef.current, key), value)) {\n setDirty(true);\n }\n if (shouldValidate) {\n validate();\n }\n }\n\n const setFieldError = (key: string, error: string | undefined) => {\n const newErrors = { ...errors };\n if (error) {\n newErrors[key] = error;\n } else {\n delete newErrors[key];\n }\n setErrors(newErrors);\n }\n\n const setFieldTouched = (key: string, touched: boolean, shouldValidate?: boolean | undefined) => {\n const newTouched = { ...touchedState };\n newTouched[key] = touched;\n setTouchedState(newTouched);\n if (shouldValidate) {\n validate();\n }\n }\n\n const handleChange = (event: React.SyntheticEvent) => {\n const target = event.target as HTMLInputElement;\n let value;\n if (target.type === \"checkbox\") {\n value = target.checked;\n } else if (target.type === \"number\") {\n value = target.valueAsNumber;\n } else {\n value = target.value;\n }\n const name = target.name;\n setFieldValue(name, value, validateOnChange);\n setFieldTouched(name, true);\n }\n\n const handleBlur = (event: React.FocusEvent) => {\n const target = event.target as HTMLInputElement;\n const name = target.name;\n setFieldTouched(name, true);\n }\n\n const submit = async (e?: FormEvent<HTMLFormElement>) => {\n e?.preventDefault();\n e?.stopPropagation();\n setIsSubmitting(true);\n setSubmitCount(submitCount + 1);\n const validationErrors = await validation?.(valuesRef.current);\n if (validationErrors && Object.keys(validationErrors).length > 0) {\n setErrors(validationErrors);\n } else {\n setErrors({});\n await onSubmit?.(valuesRef.current, controllerRef.current);\n }\n setIsSubmitting(false);\n setVersion(version + 1);\n }\n\n const resetForm = (props?: FormexResetProps<T>) => {\n const {\n submitCount: submitCountProp,\n values: valuesProp,\n errors: errorsProp,\n touched: touchedProp\n } = props ?? {};\n initialValuesRef.current = valuesProp ?? initialValues;\n valuesRef.current = valuesProp ?? initialValues;\n setValuesInner(valuesProp ?? initialValues);\n setErrors(errorsProp ?? {});\n setTouchedState(touchedProp ?? {});\n setDirty(false);\n setSubmitCount(submitCountProp ?? 0);\n setVersion(version + 1);\n }\n\n const controller: FormexController<T> = {\n values,\n initialValues: initialValuesRef.current,\n handleChange,\n isSubmitting,\n setSubmitting: setIsSubmitting,\n setValues,\n setFieldValue,\n errors,\n setFieldError,\n touched: touchedState,\n setFieldTouched,\n dirty,\n setDirty,\n handleSubmit: submit,\n submitCount,\n setSubmitCount,\n handleBlur,\n validate,\n isValidating,\n resetForm,\n version,\n debugId: debugIdRef.current\n };\n\n const controllerRef = React.useRef<FormexController<T>>(controller);\n controllerRef.current = controller;\n return controller\n}\n"],"names":["FormexContext","React","createContext","useFormex","useContext","Formex","Provider","isEmptyArray","value","Array","isArray","length","isFunction","obj","isObject","isInteger","String","Math","floor","Number","isString","Object","prototype","toString","call","isNaN","isEmptyChildren","children","Children","count","isPromise","then","isInputEvent","target","getActiveElement","doc","document","undefined","activeElement","body","e","getIn","key","def","p","path","toPath","setIn","res","clone","resVal","i","pathArray","currentPath","currentObj","slice","nextPath","setNestedObjectValues","object","visited","WeakMap","response","k","keys","val","get","set","replace","split","Field","t0","$","_c","className","is","name","props","validate","t1","t2","as","t3","t4","t5","formex","field","Symbol","for","getFieldProps","form","bb0","asElement","innerRef","rest","ref","createElement","nameOrOptions","isAnObject","valueState","values","onChange","handleChange","onBlur","handleBlur","type","valueProp","multiple","checked","indexOf","useCreateFormex","initialValues","initialErrors","initialDirty","validation","validateOnChange","onSubmit","validateOnInitialRender","debugId","initialValuesRef","useRef","valuesRef","debugIdRef","setValuesInner","useState","touchedState","setTouchedState","errors","setErrors","dirty","setDirty","submitCount","setSubmitCount","isSubmitting","setIsSubmitting","isValidating","setIsValidating","version","setVersion","useEffect","setValues","newValues","current","equal","validationErrors","setFieldValue","shouldValidate","setFieldError","error","newErrors","setFieldTouched","touched","newTouched","event","valueAsNumber","submit","preventDefault","stopPropagation","controllerRef","resetForm","submitCountProp","valuesProp","errorsProp","touchedProp","controller","setSubmitting","handleSubmit"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/Formex.tsx","../src/utils.ts","../src/Field.tsx","../src/useCreateFormex.tsx"],"sourcesContent":["import React, { useContext } from \"react\";\nimport { FormexController } from \"./types\";\n\nconst FormexContext = React.createContext<FormexController<any>>({} as any);\n\nexport const useFormex = <T extends object>() => useContext<FormexController<T>>(FormexContext);\n\nexport const Formex = FormexContext.Provider;\n","import * as React from \"react\";\n\n/** @private is the value an empty array? */\nexport const isEmptyArray = (value?: any) =>\n Array.isArray(value) && value.length === 0;\n\n/** @private is the given object a Function? */\nexport const isFunction = (obj: any): obj is Function =>\n typeof obj === \"function\";\n\n/** @private is the given object an Object? */\nexport const isObject = (obj: any): obj is Object =>\n obj !== null && typeof obj === \"object\";\n\n/** @private is the given object an integer? */\nexport const isInteger = (obj: any): boolean =>\n String(Math.floor(Number(obj))) === obj;\n\n/** @private is the given object a string? */\nexport const isString = (obj: any): obj is string =>\n Object.prototype.toString.call(obj) === \"[object String]\";\n\n/** @private is the given object a NaN? */\n// eslint-disable-next-line no-self-compare\nexport const isNaN = (obj: any): boolean => obj !== obj;\n\n/** @private Does a React component have exactly 0 children? */\nexport const isEmptyChildren = (children: any): boolean =>\n React.Children.count(children) === 0;\n\n/** @private is the given object/value a promise? */\nexport const isPromise = (value: any): value is PromiseLike<any> =>\n isObject(value) && isFunction(value.then);\n\n/** @private is the given object/value a type of synthetic event? */\nexport const isInputEvent = (value: any): value is React.SyntheticEvent<any> =>\n value && isObject(value) && isObject(value.target);\n\n/**\n * Same as document.activeElement but wraps in a try-catch block. In IE it is\n * not safe to call document.activeElement if there is nothing focused.\n *\n * The activeElement will be null only if the document or document body is not\n * yet defined.\n *\n * @param {?Document} doc Defaults to current document.\n * @return {Element | null}\n * @see https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/dom/getActiveElement.js\n */\nexport function getActiveElement(doc?: Document): Element | null {\n doc = doc || (typeof document !== \"undefined\" ? document : undefined);\n if (typeof doc === \"undefined\") {\n return null;\n }\n try {\n return doc.activeElement || doc.body;\n } catch (e) {\n return doc.body;\n }\n}\n\n/**\n * Deeply get a value from an object via its path.\n */\nexport function getIn(\n obj: any,\n key: string | string[],\n def?: any,\n p = 0\n) {\n const path = toPath(key);\n while (obj && p < path.length) {\n obj = obj[path[p++]];\n }\n\n // check if path is not in the end\n if (p !== path.length && !obj) {\n return def;\n }\n\n return obj === undefined ? def : obj;\n}\n\nexport function setIn(obj: any, path: string, value: any): any {\n const res: any = clone(obj); // this keeps inheritance when obj is a class\n let resVal: any = res;\n let i = 0;\n const pathArray = toPath(path);\n\n for (; i < pathArray.length - 1; i++) {\n const currentPath: string = pathArray[i];\n const currentObj: any = getIn(obj, pathArray.slice(0, i + 1));\n\n if (currentObj && (isObject(currentObj) || Array.isArray(currentObj))) {\n resVal = resVal[currentPath] = clone(currentObj);\n } else {\n const nextPath: string = pathArray[i + 1];\n resVal = resVal[currentPath] =\n isInteger(nextPath) && Number(nextPath) >= 0 ? [] : {};\n }\n }\n\n // Return original object if new value is the same as current\n if ((i === 0 ? obj : resVal)[pathArray[i]] === value) {\n return obj;\n }\n\n if (value === undefined) {\n delete resVal[pathArray[i]];\n } else {\n resVal[pathArray[i]] = value;\n }\n\n // If the path array has a single element, the loop did not run.\n // Deleting on `resVal` had no effect in this scenario, so we delete on the result instead.\n if (i === 0 && value === undefined) {\n delete res[pathArray[i]];\n }\n\n return res;\n}\n\n/**\n * Recursively a set the same value for all keys and arrays nested object, cloning\n * @param object\n * @param value\n * @param visited\n * @param response\n */\nexport function setNestedObjectValues<T>(\n object: any,\n value: any,\n visited: any = new WeakMap(),\n response: any = {}\n): T {\n for (const k of Object.keys(object)) {\n const val = object[k];\n if (isObject(val)) {\n if (!visited.get(val)) {\n visited.set(val, true);\n // In order to keep array values consistent for both dot path and\n // bracket syntax, we need to check if this is an array so that\n // this will output { friends: [true] } and not { friends: { \"0\": true } }\n response[k] = Array.isArray(val) ? [] : {};\n setNestedObjectValues(val, value, visited, response[k]);\n }\n } else {\n response[k] = value;\n }\n }\n\n return response;\n}\n\nexport function clone(value: any) {\n if (Array.isArray(value)) {\n return [...value];\n } else if (typeof value === \"object\" && value !== null) {\n return { ...value };\n } else {\n return value; // This is for primitive types which do not need cloning.\n }\n}\n\nfunction toPath(value: string | string[]) {\n if (Array.isArray(value)) return value; // Already in path array form.\n // Replace brackets with dots, remove leading/trailing dots, then split by dot.\n return value.replace(/\\[(\\d+)]/g, \".$1\").replace(/^\\./, \"\").replace(/\\.$/, \"\").split(\".\");\n}\n","import * as React from \"react\";\nimport { useFormex } from \"./Formex\";\nimport { getIn, isFunction, isObject } from \"./utils\";\nimport { FormexController } from \"./types\";\n\nexport interface FieldInputProps<Value> {\n /** Value of the field */\n value: Value;\n /** Name of the field */\n name: string;\n /** Multiple select? */\n multiple?: boolean;\n /** Is the field checked? */\n checked?: boolean;\n /** Change event handler */\n onChange: (event: React.SyntheticEvent) => void,\n /** Blur event handler */\n onBlur: (event: React.FocusEvent) => void,\n}\n\nexport interface FormexFieldProps<Value = any, FormValues extends object = any> {\n field: FieldInputProps<Value>;\n form: FormexController<FormValues>;\n}\n\nexport interface FieldConfig<Value, C extends React.ElementType | undefined = undefined> {\n\n /**\n * Component to render. Can either be a string e.g. 'select', 'input', or 'textarea', or a component.\n */\n as?:\n | C\n | string\n | React.ForwardRefExoticComponent<any>;\n\n /**\n * Children render function <Field name>{props => ...}</Field>)\n */\n children?: ((props: FormexFieldProps<Value>) => React.ReactNode) | React.ReactNode;\n\n /**\n * Validate a single field value independently\n */\n // validate?: FieldValidator;\n\n /**\n * Used for 'select' and related input types.\n */\n multiple?: boolean;\n\n /**\n * Field name\n */\n name: string;\n\n /** HTML input type */\n type?: string;\n\n /** Field value */\n value?: any;\n\n /** Inner ref */\n innerRef?: (instance: any) => void;\n\n}\n\nexport type FieldProps<T, C extends React.ElementType | undefined> = {\n as?: C;\n} & (C extends React.ElementType ? (React.ComponentProps<C> & FieldConfig<T, C>) : FieldConfig<T, C>);\n\nexport function Field<T, C extends React.ElementType | undefined = undefined>({\n validate,\n name,\n children,\n as: is, // `as` is reserved in typescript lol\n // component,\n className,\n ...props\n }: FieldProps<T, C>) {\n const formex = useFormex();\n\n const field = getFieldProps({ name, ...props }, formex);\n\n if (isFunction(children)) {\n return children({ field, form: formex });\n }\n\n // if (component) {\n // if (typeof component === \"string\") {\n // const { innerRef, ...rest } = props;\n // return React.createElement(\n // component,\n // { ref: innerRef, ...field, ...rest, className },\n // children\n // );\n // }\n // return React.createElement(\n // component,\n // { field, form: formex, ...props, className },\n // children\n // );\n // }\n\n // default to input here so we can check for both `as` and `children` above\n const asElement = is || \"input\";\n\n if (typeof asElement === \"string\") {\n const { innerRef, ...rest } = props;\n return React.createElement(\n asElement,\n { ref: innerRef, ...field, ...rest, className },\n children\n );\n }\n\n return React.createElement(asElement, { ...field, ...props, className }, children);\n}\n\nconst getFieldProps = (nameOrOptions: string | FieldConfig<any>, formex: FormexController<any>): FieldInputProps<any> => {\n const isAnObject = isObject(nameOrOptions);\n const name = isAnObject\n ? (nameOrOptions as FieldConfig<any>).name\n : nameOrOptions;\n const valueState = getIn(formex.values, name);\n\n const field: FieldInputProps<any> = {\n name,\n value: valueState,\n onChange: formex.handleChange,\n onBlur: formex.handleBlur,\n };\n if (isAnObject) {\n const {\n type,\n value: valueProp, // value is special for checkboxes\n as: is,\n multiple,\n } = nameOrOptions as FieldConfig<any>;\n\n if (type === \"checkbox\") {\n if (valueProp === undefined) {\n field.checked = !!valueState;\n } else {\n field.checked = !!(\n Array.isArray(valueState) && ~valueState.indexOf(valueProp)\n );\n field.value = valueProp;\n }\n } else if (type === \"radio\") {\n field.checked = valueState === valueProp;\n field.value = valueProp;\n } else if (is === \"select\" && multiple) {\n field.value = field.value || [];\n field.multiple = true;\n }\n }\n return field;\n};\n","import React, { useEffect, useState } from \"react\";\nimport { getIn, setIn } from \"./utils\";\nimport equal from \"react-fast-compare\"\n\nimport { FormexController, FormexResetProps } from \"./types\";\n\nexport function useCreateFormex<T extends object>({\n initialValues,\n initialErrors,\n initialDirty,\n validation,\n validateOnChange = false,\n validateOnInitialRender = false,\n onSubmit,\n onReset,\n debugId,\n }: {\n initialValues: T;\n initialErrors?: Record<string, string>;\n initialDirty?: boolean;\n validateOnChange?: boolean;\n validateOnInitialRender?: boolean;\n validation?: (\n values: T\n ) =>\n | Record<string, string>\n | Promise<Record<string, string>>\n | undefined\n | void;\n onSubmit?: (values: T, controller: FormexController<T>) => void | Promise<void>;\n onReset?: (controller: FormexController<T>) => void | Promise<void>;\n debugId?: string;\n}): FormexController<T> {\n // Refs (for current state which shouldn’t trigger re – renders)\n const initialValuesRef = React.useRef<T>(initialValues);\n const valuesRef = React.useRef<T>(initialValues);\n const debugIdRef = React.useRef<string | undefined>(debugId);\n\n // State\n const [values, setValuesInner] = useState<T>(initialValues);\n const [touchedState, setTouchedState] = useState<Record<string, boolean>>({});\n const [errors, setErrors] = useState<Record<string, string>>(initialErrors ?? {});\n const [dirty, setDirty] = useState(initialDirty ?? false);\n const [submitCount, setSubmitCount] = useState(0);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isValidating, setIsValidating] = useState(false);\n const [version, setVersion] = useState(0);\n\n // Run initial validation if required\n useEffect(() => {\n if (validateOnInitialRender) {\n validate();\n }\n }, []);\n\n // Memoize setValues so that it doesn’t change unless nothing inside changes.\n const setValues = React.useCallback((newValues: T) => {\n valuesRef.current = newValues;\n setValuesInner(newValues);\n // Adjust dirty flag by comparing with the initial values\n setDirty(!equal(initialValuesRef.current, newValues));\n }, []);\n\n // Memoized validate function\n const validate = React.useCallback(async () => {\n setIsValidating(true);\n const validationErrors = await validation?.(valuesRef.current);\n setErrors(validationErrors ?? {});\n setIsValidating(false);\n return validationErrors;\n }, [validation]);\n\n // setFieldValue updates a single field and optionally triggers validation\n const setFieldValue = React.useCallback(\n (key: string, value: any, shouldValidate?: boolean) => {\n const newValues = setIn(valuesRef.current, key, value);\n valuesRef.current = newValues;\n setValuesInner(newValues);\n // Compare with initial value using getIn\n if (!equal(getIn(initialValuesRef.current, key), value)) {\n setDirty(true);\n }\n if (shouldValidate) {\n validate();\n }\n },\n [validate]\n );\n\n // setFieldError uses functional updates to ensure we’re working off the current error state.\n const setFieldError = React.useCallback((key: string, error: string | undefined) => {\n setErrors((prevErrors) => {\n const newErrors = { ...prevErrors };\n if (error) {\n newErrors[key] = error;\n } else {\n delete newErrors[key];\n }\n return newErrors;\n });\n }, []);\n\n // setFieldTouched updates touched state and can optionally trigger validation.\n const setFieldTouched = React.useCallback(\n (key: string, touched: boolean, shouldValidate?: boolean) => {\n setTouchedState((prev) => {\n const newTouched = {\n ...prev,\n [key]: touched\n };\n return newTouched;\n });\n if (shouldValidate) {\n validate();\n }\n },\n [validate]\n );\n\n // handleChange reads the event, determines the proper value,\n // and then delegates to setFieldValue and setFieldTouched.\n const handleChange = React.useCallback(\n (event: React.SyntheticEvent) => {\n const target = event.target as HTMLInputElement;\n let value;\n if (target.type === \"checkbox\") {\n value = target.checked;\n } else if (target.type === \"number\") {\n value = target.valueAsNumber;\n } else {\n value = target.value;\n }\n const name = target.name;\n setFieldValue(name, value, validateOnChange);\n setFieldTouched(name, true);\n },\n [setFieldValue, setFieldTouched, validateOnChange]\n );\n\n // handleBlur simply marks the field as touched.\n const handleBlur = React.useCallback((event: React.FocusEvent) => {\n const target = event.target as HTMLInputElement;\n const name = target.name;\n setFieldTouched(name, true);\n }, [setFieldTouched]);\n\n // submit uses functional updates on submitCount and version.\n const submit = React.useCallback(\n async (e?: React.FormEvent<HTMLFormElement>) => {\n e?.preventDefault();\n e?.stopPropagation();\n setIsSubmitting(true);\n setSubmitCount((prev) => prev + 1);\n const validationErrors = await validation?.(valuesRef.current);\n if (validationErrors && Object.keys(validationErrors).length > 0) {\n setErrors(validationErrors);\n } else {\n setErrors({});\n await onSubmit?.(valuesRef.current, controllerRef.current);\n }\n setIsSubmitting(false);\n setVersion((prev) => prev + 1);\n },\n [onSubmit, validation]\n );\n\n // resetForm resets to the passed props (or initial configuration).\n const resetForm = React.useCallback((props?: FormexResetProps<T>) => {\n const {\n submitCount: submitCountProp,\n values: valuesProp,\n errors: errorsProp,\n touched: touchedProp\n } =\n props ?? {};\n valuesRef.current = valuesProp ?? initialValuesRef.current;\n initialValuesRef.current = valuesProp ?? initialValuesRef.current;\n setValuesInner(valuesProp ?? initialValuesRef.current);\n setErrors(errorsProp ?? {});\n setTouchedState(touchedProp ?? {});\n setDirty(false);\n setSubmitCount(submitCountProp ?? 0);\n setVersion((prev) => prev + 1);\n onReset?.(controllerRef.current);\n }, [onReset]);\n\n // Create a ref for the controller so that it remains stable over time.\n const controllerRef = React.useRef<FormexController<T>>({} as FormexController<T>);\n\n // Memoize the controller object so that consumers don’t see new references on every render.\n const controller = React.useMemo<FormexController<T>>(\n () => ({\n values,\n initialValues: initialValuesRef.current,\n handleChange,\n isSubmitting,\n setSubmitting: setIsSubmitting,\n setValues,\n setFieldValue,\n errors,\n setFieldError,\n touched: touchedState,\n setFieldTouched,\n dirty,\n setDirty, // setter from useState is stable\n handleSubmit: submit,\n submitCount,\n setSubmitCount, // setter from useState is stable\n handleBlur,\n validate,\n isValidating,\n resetForm,\n version,\n debugId: debugIdRef.current,\n }),\n [\n values,\n errors,\n touchedState,\n dirty,\n isSubmitting,\n submitCount,\n isValidating,\n version,\n handleChange,\n handleBlur,\n setValues,\n setFieldValue,\n setFieldTouched,\n setFieldError,\n validate,\n submit,\n resetForm,\n ]\n );\n\n // Keep the ref updated with the latest controller\n React.useEffect(() => {\n controllerRef.current = controller;\n }, [controller]);\n\n return controller;\n}\n"],"names":["FormexContext","React","createContext","useFormex","useContext","Formex","Provider","isEmptyArray","value","Array","isArray","length","isFunction","obj","isObject","isInteger","String","Math","floor","Number","isString","Object","prototype","toString","call","isNaN","isEmptyChildren","children","Children","count","isPromise","then","isInputEvent","target","getActiveElement","doc","document","undefined","activeElement","body","e","getIn","key","def","p","path","toPath","setIn","res","clone","resVal","i","pathArray","currentPath","currentObj","slice","nextPath","setNestedObjectValues","object","visited","WeakMap","response","k","keys","val","get","set","replace","split","Field","t0","$","_c","className","is","name","props","validate","t1","t2","as","t3","t4","t5","formex","field","Symbol","for","getFieldProps","form","bb0","asElement","innerRef","rest","ref","createElement","nameOrOptions","isAnObject","valueState","values","onChange","handleChange","onBlur","handleBlur","type","valueProp","multiple","checked","indexOf","useCreateFormex","initialValues","initialErrors","initialDirty","validation","validateOnChange","validateOnInitialRender","onSubmit","onReset","debugId","initialValuesRef","useRef","valuesRef","debugIdRef","setValuesInner","useState","touchedState","setTouchedState","errors","setErrors","dirty","setDirty","submitCount","setSubmitCount","isSubmitting","setIsSubmitting","isValidating","setIsValidating","version","setVersion","useEffect","setValues","useCallback","newValues","current","equal","validationErrors","setFieldValue","shouldValidate","setFieldError","error","prevErrors","newErrors","setFieldTouched","touched","prev","newTouched","event","valueAsNumber","submit","preventDefault","stopPropagation","controllerRef","resetForm","submitCountProp","valuesProp","errorsProp","touchedProp","controller","useMemo","setSubmitting","handleSubmit"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FormexController } from "./types";
|
|
2
|
-
export declare function useCreateFormex<T extends object>({ initialValues, initialErrors, initialDirty, validation, validateOnChange, onSubmit,
|
|
2
|
+
export declare function useCreateFormex<T extends object>({ initialValues, initialErrors, initialDirty, validation, validateOnChange, validateOnInitialRender, onSubmit, onReset, debugId, }: {
|
|
3
3
|
initialValues: T;
|
|
4
4
|
initialErrors?: Record<string, string>;
|
|
5
5
|
initialDirty?: boolean;
|
|
@@ -7,5 +7,6 @@ export declare function useCreateFormex<T extends object>({ initialValues, initi
|
|
|
7
7
|
validateOnInitialRender?: boolean;
|
|
8
8
|
validation?: (values: T) => Record<string, string> | Promise<Record<string, string>> | undefined | void;
|
|
9
9
|
onSubmit?: (values: T, controller: FormexController<T>) => void | Promise<void>;
|
|
10
|
+
onReset?: (controller: FormexController<T>) => void | Promise<void>;
|
|
10
11
|
debugId?: string;
|
|
11
12
|
}): FormexController<T>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firecms/formex",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.0.0-canary.
|
|
4
|
+
"version": "3.0.0-canary.188",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -74,5 +74,5 @@
|
|
|
74
74
|
"node"
|
|
75
75
|
]
|
|
76
76
|
},
|
|
77
|
-
"gitHead": "
|
|
77
|
+
"gitHead": "12b6a7c4cb3e88d900d169f4903cc8fbfb7c08ba"
|
|
78
78
|
}
|
package/src/useCreateFormex.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
2
|
import { getIn, setIn } from "./utils";
|
|
3
3
|
import equal from "react-fast-compare"
|
|
4
4
|
|
|
@@ -10,24 +10,33 @@ export function useCreateFormex<T extends object>({
|
|
|
10
10
|
initialDirty,
|
|
11
11
|
validation,
|
|
12
12
|
validateOnChange = false,
|
|
13
|
-
onSubmit,
|
|
14
13
|
validateOnInitialRender = false,
|
|
15
|
-
|
|
14
|
+
onSubmit,
|
|
15
|
+
onReset,
|
|
16
|
+
debugId,
|
|
16
17
|
}: {
|
|
17
|
-
initialValues: T
|
|
18
|
-
initialErrors?: Record<string, string
|
|
19
|
-
initialDirty?: boolean
|
|
20
|
-
validateOnChange?: boolean
|
|
21
|
-
validateOnInitialRender?: boolean
|
|
22
|
-
validation?: (
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
initialValues: T;
|
|
19
|
+
initialErrors?: Record<string, string>;
|
|
20
|
+
initialDirty?: boolean;
|
|
21
|
+
validateOnChange?: boolean;
|
|
22
|
+
validateOnInitialRender?: boolean;
|
|
23
|
+
validation?: (
|
|
24
|
+
values: T
|
|
25
|
+
) =>
|
|
26
|
+
| Record<string, string>
|
|
27
|
+
| Promise<Record<string, string>>
|
|
28
|
+
| undefined
|
|
29
|
+
| void;
|
|
30
|
+
onSubmit?: (values: T, controller: FormexController<T>) => void | Promise<void>;
|
|
31
|
+
onReset?: (controller: FormexController<T>) => void | Promise<void>;
|
|
32
|
+
debugId?: string;
|
|
25
33
|
}): FormexController<T> {
|
|
26
|
-
|
|
34
|
+
// Refs (for current state which shouldn’t trigger re – renders)
|
|
27
35
|
const initialValuesRef = React.useRef<T>(initialValues);
|
|
28
36
|
const valuesRef = React.useRef<T>(initialValues);
|
|
29
37
|
const debugIdRef = React.useRef<string | undefined>(debugId);
|
|
30
38
|
|
|
39
|
+
// State
|
|
31
40
|
const [values, setValuesInner] = useState<T>(initialValues);
|
|
32
41
|
const [touchedState, setTouchedState] = useState<Record<string, boolean>>({});
|
|
33
42
|
const [errors, setErrors] = useState<Record<string, string>>(initialErrors ?? {});
|
|
@@ -37,137 +46,198 @@ export function useCreateFormex<T extends object>({
|
|
|
37
46
|
const [isValidating, setIsValidating] = useState(false);
|
|
38
47
|
const [version, setVersion] = useState(0);
|
|
39
48
|
|
|
49
|
+
// Run initial validation if required
|
|
40
50
|
useEffect(() => {
|
|
41
51
|
if (validateOnInitialRender) {
|
|
42
52
|
validate();
|
|
43
53
|
}
|
|
44
54
|
}, []);
|
|
45
55
|
|
|
46
|
-
|
|
56
|
+
// Memoize setValues so that it doesn’t change unless nothing inside changes.
|
|
57
|
+
const setValues = React.useCallback((newValues: T) => {
|
|
47
58
|
valuesRef.current = newValues;
|
|
48
59
|
setValuesInner(newValues);
|
|
49
|
-
|
|
50
|
-
|
|
60
|
+
// Adjust dirty flag by comparing with the initial values
|
|
61
|
+
setDirty(!equal(initialValuesRef.current, newValues));
|
|
62
|
+
}, []);
|
|
51
63
|
|
|
52
|
-
|
|
64
|
+
// Memoized validate function
|
|
65
|
+
const validate = React.useCallback(async () => {
|
|
53
66
|
setIsValidating(true);
|
|
54
67
|
const validationErrors = await validation?.(valuesRef.current);
|
|
55
68
|
setErrors(validationErrors ?? {});
|
|
56
69
|
setIsValidating(false);
|
|
57
70
|
return validationErrors;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
setErrors(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const handleChange = (event: React.SyntheticEvent) => {
|
|
92
|
-
const target = event.target as HTMLInputElement;
|
|
93
|
-
let value;
|
|
94
|
-
if (target.type === "checkbox") {
|
|
95
|
-
value = target.checked;
|
|
96
|
-
} else if (target.type === "number") {
|
|
97
|
-
value = target.valueAsNumber;
|
|
98
|
-
} else {
|
|
99
|
-
value = target.value;
|
|
100
|
-
}
|
|
101
|
-
const name = target.name;
|
|
102
|
-
setFieldValue(name, value, validateOnChange);
|
|
103
|
-
setFieldTouched(name, true);
|
|
104
|
-
}
|
|
71
|
+
}, [validation]);
|
|
72
|
+
|
|
73
|
+
// setFieldValue updates a single field and optionally triggers validation
|
|
74
|
+
const setFieldValue = React.useCallback(
|
|
75
|
+
(key: string, value: any, shouldValidate?: boolean) => {
|
|
76
|
+
const newValues = setIn(valuesRef.current, key, value);
|
|
77
|
+
valuesRef.current = newValues;
|
|
78
|
+
setValuesInner(newValues);
|
|
79
|
+
// Compare with initial value using getIn
|
|
80
|
+
if (!equal(getIn(initialValuesRef.current, key), value)) {
|
|
81
|
+
setDirty(true);
|
|
82
|
+
}
|
|
83
|
+
if (shouldValidate) {
|
|
84
|
+
validate();
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
[validate]
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// setFieldError uses functional updates to ensure we’re working off the current error state.
|
|
91
|
+
const setFieldError = React.useCallback((key: string, error: string | undefined) => {
|
|
92
|
+
setErrors((prevErrors) => {
|
|
93
|
+
const newErrors = { ...prevErrors };
|
|
94
|
+
if (error) {
|
|
95
|
+
newErrors[key] = error;
|
|
96
|
+
} else {
|
|
97
|
+
delete newErrors[key];
|
|
98
|
+
}
|
|
99
|
+
return newErrors;
|
|
100
|
+
});
|
|
101
|
+
}, []);
|
|
105
102
|
|
|
106
|
-
|
|
103
|
+
// setFieldTouched updates touched state and can optionally trigger validation.
|
|
104
|
+
const setFieldTouched = React.useCallback(
|
|
105
|
+
(key: string, touched: boolean, shouldValidate?: boolean) => {
|
|
106
|
+
setTouchedState((prev) => {
|
|
107
|
+
const newTouched = {
|
|
108
|
+
...prev,
|
|
109
|
+
[key]: touched
|
|
110
|
+
};
|
|
111
|
+
return newTouched;
|
|
112
|
+
});
|
|
113
|
+
if (shouldValidate) {
|
|
114
|
+
validate();
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
[validate]
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
// handleChange reads the event, determines the proper value,
|
|
121
|
+
// and then delegates to setFieldValue and setFieldTouched.
|
|
122
|
+
const handleChange = React.useCallback(
|
|
123
|
+
(event: React.SyntheticEvent) => {
|
|
124
|
+
const target = event.target as HTMLInputElement;
|
|
125
|
+
let value;
|
|
126
|
+
if (target.type === "checkbox") {
|
|
127
|
+
value = target.checked;
|
|
128
|
+
} else if (target.type === "number") {
|
|
129
|
+
value = target.valueAsNumber;
|
|
130
|
+
} else {
|
|
131
|
+
value = target.value;
|
|
132
|
+
}
|
|
133
|
+
const name = target.name;
|
|
134
|
+
setFieldValue(name, value, validateOnChange);
|
|
135
|
+
setFieldTouched(name, true);
|
|
136
|
+
},
|
|
137
|
+
[setFieldValue, setFieldTouched, validateOnChange]
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
// handleBlur simply marks the field as touched.
|
|
141
|
+
const handleBlur = React.useCallback((event: React.FocusEvent) => {
|
|
107
142
|
const target = event.target as HTMLInputElement;
|
|
108
143
|
const name = target.name;
|
|
109
144
|
setFieldTouched(name, true);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
e
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
145
|
+
}, [setFieldTouched]);
|
|
146
|
+
|
|
147
|
+
// submit uses functional updates on submitCount and version.
|
|
148
|
+
const submit = React.useCallback(
|
|
149
|
+
async (e?: React.FormEvent<HTMLFormElement>) => {
|
|
150
|
+
e?.preventDefault();
|
|
151
|
+
e?.stopPropagation();
|
|
152
|
+
setIsSubmitting(true);
|
|
153
|
+
setSubmitCount((prev) => prev + 1);
|
|
154
|
+
const validationErrors = await validation?.(valuesRef.current);
|
|
155
|
+
if (validationErrors && Object.keys(validationErrors).length > 0) {
|
|
156
|
+
setErrors(validationErrors);
|
|
157
|
+
} else {
|
|
158
|
+
setErrors({});
|
|
159
|
+
await onSubmit?.(valuesRef.current, controllerRef.current);
|
|
160
|
+
}
|
|
161
|
+
setIsSubmitting(false);
|
|
162
|
+
setVersion((prev) => prev + 1);
|
|
163
|
+
},
|
|
164
|
+
[onSubmit, validation]
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
// resetForm resets to the passed props (or initial configuration).
|
|
168
|
+
const resetForm = React.useCallback((props?: FormexResetProps<T>) => {
|
|
129
169
|
const {
|
|
130
170
|
submitCount: submitCountProp,
|
|
131
171
|
values: valuesProp,
|
|
132
172
|
errors: errorsProp,
|
|
133
173
|
touched: touchedProp
|
|
134
|
-
} =
|
|
135
|
-
|
|
136
|
-
valuesRef.current = valuesProp ??
|
|
137
|
-
|
|
174
|
+
} =
|
|
175
|
+
props ?? {};
|
|
176
|
+
valuesRef.current = valuesProp ?? initialValuesRef.current;
|
|
177
|
+
initialValuesRef.current = valuesProp ?? initialValuesRef.current;
|
|
178
|
+
setValuesInner(valuesProp ?? initialValuesRef.current);
|
|
138
179
|
setErrors(errorsProp ?? {});
|
|
139
180
|
setTouchedState(touchedProp ?? {});
|
|
140
181
|
setDirty(false);
|
|
141
182
|
setSubmitCount(submitCountProp ?? 0);
|
|
142
|
-
setVersion(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
183
|
+
setVersion((prev) => prev + 1);
|
|
184
|
+
onReset?.(controllerRef.current);
|
|
185
|
+
}, [onReset]);
|
|
186
|
+
|
|
187
|
+
// Create a ref for the controller so that it remains stable over time.
|
|
188
|
+
const controllerRef = React.useRef<FormexController<T>>({} as FormexController<T>);
|
|
189
|
+
|
|
190
|
+
// Memoize the controller object so that consumers don’t see new references on every render.
|
|
191
|
+
const controller = React.useMemo<FormexController<T>>(
|
|
192
|
+
() => ({
|
|
193
|
+
values,
|
|
194
|
+
initialValues: initialValuesRef.current,
|
|
195
|
+
handleChange,
|
|
196
|
+
isSubmitting,
|
|
197
|
+
setSubmitting: setIsSubmitting,
|
|
198
|
+
setValues,
|
|
199
|
+
setFieldValue,
|
|
200
|
+
errors,
|
|
201
|
+
setFieldError,
|
|
202
|
+
touched: touchedState,
|
|
203
|
+
setFieldTouched,
|
|
204
|
+
dirty,
|
|
205
|
+
setDirty, // setter from useState is stable
|
|
206
|
+
handleSubmit: submit,
|
|
207
|
+
submitCount,
|
|
208
|
+
setSubmitCount, // setter from useState is stable
|
|
209
|
+
handleBlur,
|
|
210
|
+
validate,
|
|
211
|
+
isValidating,
|
|
212
|
+
resetForm,
|
|
213
|
+
version,
|
|
214
|
+
debugId: debugIdRef.current,
|
|
215
|
+
}),
|
|
216
|
+
[
|
|
217
|
+
values,
|
|
218
|
+
errors,
|
|
219
|
+
touchedState,
|
|
220
|
+
dirty,
|
|
221
|
+
isSubmitting,
|
|
222
|
+
submitCount,
|
|
223
|
+
isValidating,
|
|
224
|
+
version,
|
|
225
|
+
handleChange,
|
|
226
|
+
handleBlur,
|
|
227
|
+
setValues,
|
|
228
|
+
setFieldValue,
|
|
229
|
+
setFieldTouched,
|
|
230
|
+
setFieldError,
|
|
231
|
+
validate,
|
|
232
|
+
submit,
|
|
233
|
+
resetForm,
|
|
234
|
+
]
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
// Keep the ref updated with the latest controller
|
|
238
|
+
React.useEffect(() => {
|
|
239
|
+
controllerRef.current = controller;
|
|
240
|
+
}, [controller]);
|
|
241
|
+
|
|
242
|
+
return controller;
|
|
173
243
|
}
|