@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 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
- const newErrors = {
324
- ...errors
325
- };
326
- if (error) {
327
- newErrors[key_0] = error;
328
- } else {
329
- delete newErrors[key_0];
330
- }
331
- setErrors(newErrors);
332
- };
333
- const setFieldTouched = (key_1, touched, shouldValidate_0) => {
334
- const newTouched = {
335
- ...touchedState
336
- };
337
- newTouched[key_1] = touched;
338
- setTouchedState(newTouched);
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(submitCount + 1);
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(version + 1);
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
- initialValuesRef.current = valuesProp ?? initialValues;
385
- valuesRef.current = valuesProp ?? initialValues;
386
- setValuesInner(valuesProp ?? initialValues);
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(version + 1);
392
- };
393
- const controller = {
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
- const controllerRef = React__default.useRef(controller);
418
- controllerRef.current = controller;
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 {
@@ -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
- const newErrors = {
341
- ...errors
342
- };
343
- if (error) {
344
- newErrors[key_0] = error;
345
- } else {
346
- delete newErrors[key_0];
347
- }
348
- setErrors(newErrors);
349
- };
350
- const setFieldTouched = (key_1, touched, shouldValidate_0) => {
351
- const newTouched = {
352
- ...touchedState
353
- };
354
- newTouched[key_1] = touched;
355
- setTouchedState(newTouched);
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(submitCount + 1);
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(version + 1);
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
- initialValuesRef.current = valuesProp ?? initialValues;
402
- valuesRef.current = valuesProp ?? initialValues;
403
- setValuesInner(valuesProp ?? initialValues);
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(version + 1);
409
- };
410
- const controller = {
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
- const controllerRef = React.useRef(controller);
435
- controllerRef.current = controller;
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;
@@ -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, validateOnInitialRender, debugId }: {
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.186",
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": "968beff28cddecbacc6740dc5e75288bf423746e"
77
+ "gitHead": "12b6a7c4cb3e88d900d169f4903cc8fbfb7c08ba"
78
78
  }
@@ -1,4 +1,4 @@
1
- import React, { FormEvent, useEffect, useState } from "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
- debugId
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?: (values: T) => Record<string, string> | Promise<Record<string, string>> | undefined | void,
23
- onSubmit?: (values: T, controller: FormexController<T>) => void | Promise<void>,
24
- debugId?: string
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
- const setValues = (newValues: T) => {
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
- setDirty(equal(initialValuesRef.current, newValues));
50
- }
60
+ // Adjust dirty flag by comparing with the initial values
61
+ setDirty(!equal(initialValuesRef.current, newValues));
62
+ }, []);
51
63
 
52
- const validate = async () => {
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
- const setFieldValue = (key: string, value: any, shouldValidate?: boolean) => {
61
- const newValues = setIn(valuesRef.current, key, value);
62
- valuesRef.current = newValues;
63
- setValuesInner(newValues);
64
- if (!equal(getIn(initialValuesRef.current, key), value)) {
65
- setDirty(true);
66
- }
67
- if (shouldValidate) {
68
- validate();
69
- }
70
- }
71
-
72
- const setFieldError = (key: string, error: string | undefined) => {
73
- const newErrors = { ...errors };
74
- if (error) {
75
- newErrors[key] = error;
76
- } else {
77
- delete newErrors[key];
78
- }
79
- setErrors(newErrors);
80
- }
81
-
82
- const setFieldTouched = (key: string, touched: boolean, shouldValidate?: boolean | undefined) => {
83
- const newTouched = { ...touchedState };
84
- newTouched[key] = touched;
85
- setTouchedState(newTouched);
86
- if (shouldValidate) {
87
- validate();
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
- const handleBlur = (event: React.FocusEvent) => {
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
- const submit = async (e?: FormEvent<HTMLFormElement>) => {
113
- e?.preventDefault();
114
- e?.stopPropagation();
115
- setIsSubmitting(true);
116
- setSubmitCount(submitCount + 1);
117
- const validationErrors = await validation?.(valuesRef.current);
118
- if (validationErrors && Object.keys(validationErrors).length > 0) {
119
- setErrors(validationErrors);
120
- } else {
121
- setErrors({});
122
- await onSubmit?.(valuesRef.current, controllerRef.current);
123
- }
124
- setIsSubmitting(false);
125
- setVersion(version + 1);
126
- }
127
-
128
- const resetForm = (props?: FormexResetProps<T>) => {
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
- } = props ?? {};
135
- initialValuesRef.current = valuesProp ?? initialValues;
136
- valuesRef.current = valuesProp ?? initialValues;
137
- setValuesInner(valuesProp ?? initialValues);
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(version + 1);
143
- }
144
-
145
- const controller: FormexController<T> = {
146
- values,
147
- initialValues: initialValuesRef.current,
148
- handleChange,
149
- isSubmitting,
150
- setSubmitting: setIsSubmitting,
151
- setValues,
152
- setFieldValue,
153
- errors,
154
- setFieldError,
155
- touched: touchedState,
156
- setFieldTouched,
157
- dirty,
158
- setDirty,
159
- handleSubmit: submit,
160
- submitCount,
161
- setSubmitCount,
162
- handleBlur,
163
- validate,
164
- isValidating,
165
- resetForm,
166
- version,
167
- debugId: debugIdRef.current
168
- };
169
-
170
- const controllerRef = React.useRef<FormexController<T>>(controller);
171
- controllerRef.current = controller;
172
- return controller
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
  }