UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

1,022 lines (1,021 loc) 38.4 kB
"use client"; import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties"; const _excluded = ["id", "globalStatusId", "defaultData", "emptyData", "data", "schema", "onChange", "onPathChange", "onSubmit", "onSubmitRequest", "onSubmitComplete", "onCommit", "onClear", "onUpdateDataValue", "scrollTopOnSubmit", "minimumAsyncBehaviorTime", "asyncSubmitTimeout", "sessionStorageId", "ajvInstance", "transformIn", "transformOut", "filterSubmitData", "countryCode", "locale", "translations", "required", "errorMessages", "isolate", "children"]; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } import "core-js/modules/web.dom-collections.iterator.js"; import React, { useRef, useMemo, useCallback, useReducer, useEffect, useContext } from 'react'; import pointer from '../../utils/json-pointer'; import { makeAjvInstance, ajvErrorsToFormErrors } from '../../utils'; import { debounce } from '../../../../shared/helpers'; import FieldPropsProvider from '../../Field/Provider'; import useUpdateEffect from '../../../../shared/helpers/useUpdateEffect'; import { isAsync } from '../../../../shared/helpers/isAsync'; import { createReferenceKey, useSharedState } from '../../../../shared/helpers/useSharedState'; import SharedContext from '../../../../shared/Context'; import useTranslation from '../../hooks/useTranslation'; import DataContext from '../Context'; import structuredClone from '@ungap/structured-clone'; const useLayoutEffect = typeof window === 'undefined' ? React.useEffect : React.useLayoutEffect; const isArrayJsonPointer = /^\/\d+(\/|$)/; export default function Provider(props) { var _sharedAttachments$da; const [, forceUpdate] = useReducer(() => ({}), {}); const { id, globalStatusId = 'main', defaultData, emptyData, data, schema, onChange, onPathChange, onSubmit, onSubmitRequest, onSubmitComplete, onCommit, onClear, onUpdateDataValue, scrollTopOnSubmit, minimumAsyncBehaviorTime, asyncSubmitTimeout, sessionStorageId, ajvInstance, transformIn, transformOut, filterSubmitData, countryCode, locale, translations, required, errorMessages, isolate, children } = props, rest = _objectWithoutProperties(props, _excluded); if (data !== undefined && sessionStorageId !== undefined) { throw new Error('Use "defaultData" instead of "data" when using sessionStorageId'); } const { hasContext } = useContext(DataContext) || {}; if (hasContext && !isolate) { throw new Error('DataContext (Form.Handler) cannot be nested'); } const formElementRef = useRef(null); const { locale: sharedLocale } = useContext(SharedContext) || {}; const translation = useTranslation().Field; const ajvRef = useRef(makeAjvInstance(ajvInstance)); const mountedFieldsRef = useRef(new Map()); const snapshotsRef = useRef(new Map()); const existingFieldsRef = useRef(new Map()); const hasVisibleErrorRef = useRef(new Map()); const errorsRef = useRef(); const addSetShowAllErrorsRef = useRef([]); const showAllErrorsRef = useRef(false); const setShowAllErrors = useCallback(showAllErrors => { showAllErrorsRef.current = showAllErrors ? Date.now() : showAllErrors; forceUpdate(); addSetShowAllErrorsRef.current.forEach(fn => fn === null || fn === void 0 ? void 0 : fn(showAllErrors)); }, []); const revealError = useCallback((path, hasError) => { if (hasError) { hasVisibleErrorRef.current.set(path, hasError); } else { hasVisibleErrorRef.current.delete(path); } forceUpdate(); }, []); const submitStateRef = useRef({}); const setSubmitState = useCallback(state => { submitStateRef.current = _objectSpread(_objectSpread({}, submitStateRef.current), state); forceUpdate(); }, []); const formStateRef = useRef(); const keepPending = useRef(false); const setFormState = useCallback(function (formState) { let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (typeof (options === null || options === void 0 ? void 0 : options.keepPending) === 'boolean') { keepPending.current = options === null || options === void 0 ? void 0 : options.keepPending; } formStateRef.current = formState; forceUpdate(); }, []); const fieldErrorRef = useRef({}); const fieldStateRef = useRef({}); const initialData = useMemo(() => { if (sessionStorageId && typeof window !== 'undefined') { var _window$sessionStorag; const sessionDataJSON = (_window$sessionStorag = window.sessionStorage) === null || _window$sessionStorag === void 0 ? void 0 : _window$sessionStorag.getItem(sessionStorageId); if (sessionDataJSON) { return JSON.parse(sessionDataJSON); } } return data !== null && data !== void 0 ? data : defaultData; }, []); const internalDataRef = useRef(initialData); const isEmptyDataRef = useRef(false); const ajvValidatorRef = useRef(); const executeAjvValidator = useCallback(() => { var _ajvValidatorRef$curr; if (!ajvValidatorRef.current) { return; } if (!((_ajvValidatorRef$curr = ajvValidatorRef.current) !== null && _ajvValidatorRef$curr !== void 0 && _ajvValidatorRef$curr.call(ajvValidatorRef, internalDataRef.current))) { errorsRef.current = ajvErrorsToFormErrors(ajvValidatorRef.current.errors, internalDataRef.current); } else { errorsRef.current = undefined; } }, []); const validateData = useCallback(() => { if (!ajvValidatorRef.current) { return; } executeAjvValidator(); forceUpdate(); }, [executeAjvValidator]); const checkFieldStateFor = useCallback((path, state) => { var _errorsRef$current; return Boolean(state === 'error' ? ((_errorsRef$current = errorsRef.current) === null || _errorsRef$current === void 0 ? void 0 : _errorsRef$current[path]) instanceof Error || fieldErrorRef.current[path] instanceof Error : fieldStateRef.current[path] === state); }, []); const hasFieldState = useCallback(state => { return Array.from(mountedFieldsRef.current.entries()).some(_ref => { let [path, item] = _ref; return item.isMounted && checkFieldStateFor(path, state); }); }, [checkFieldStateFor]); const hasFieldError = useCallback(path => { return Array.from(mountedFieldsRef.current.entries()).some(_ref2 => { let [p, item] = _ref2; return item.isMounted && p === path && checkFieldStateFor(path, 'error'); }); }, [checkFieldStateFor]); const hasErrors = useCallback(() => { return hasFieldState('error'); }, [hasFieldState]); const setFieldError = useCallback((path, error) => { if (error) { fieldErrorRef.current[path] = error; } else { delete fieldErrorRef.current[path]; } for (const item of fieldEventListenersRef.current) { const { type, callback } = item; if (type === 'onSetFieldError') { callback(); } } }, []); const setFieldState = useCallback((path, fieldState) => { if (fieldState !== fieldStateRef.current[path]) { fieldStateRef.current[path] = fieldState; forceUpdate(); } }, []); const getDataPathHandlerParameters = useCallback(function (path) { var _fieldInternalsRef$cu; let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : internalDataRef.current; const value = pointer.has(data, path) ? pointer.get(data, path) : undefined; const { value: displayValue } = fieldDisplayValueRef.current[path] || {}; const props = ((_fieldInternalsRef$cu = fieldInternalsRef.current[path]) === null || _fieldInternalsRef$cu === void 0 ? void 0 : _fieldInternalsRef$cu.props) || {}; const label = props === null || props === void 0 ? void 0 : props['label']; const error = fieldErrorRef.current[path]; return { path, value, displayValue, label, props, data: internalDataRef.current, error, internal: { error } }; }, []); const mutateDataHandler = useCallback(function (data, handler) { let { remove = false, mutate = true, fireHandlerWhen = null } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; const freshData = {}; const mutateEntry = (path, result) => { if (remove) { if (result === false) { data = structuredClone(data); pointer.remove(data, path); } } else { if (typeof result !== 'undefined') { if (mutate) { data = structuredClone(data); pointer.set(data, path, result); } else { pointer.set(freshData, path, result); } } } }; if (typeof handler === 'function') { const run = path => { const { type } = fieldDisplayValueRef.current[path] || {}; if ((fireHandlerWhen === null || fireHandlerWhen === void 0 ? void 0 : fireHandlerWhen({ type })) !== false) { const result = handler(getDataPathHandlerParameters(path, data)); mutateEntry(path, result); } }; for (const path in fieldInternalsRef.current) { const exists = pointer.has(data, path); if (exists) { run(path); } } pointer.walk(internalDataRef.current, (value, path) => { if (fieldInternalsRef.current[path] === undefined) { run(path); } }); if (!mutate) { return freshData; } return data; } else if (handler) { const runFilter = _ref3 => { let { path, condition } = _ref3; const exists = pointer.has(data, path); if (exists) { const result = typeof condition === 'function' ? condition(getDataPathHandlerParameters(path, data)) : condition; mutateEntry(path, result); } }; const wildcardPaths = []; Object.entries(handler).forEach(_ref4 => { let [path, condition] = _ref4; if (path.includes('*')) { const parts = path.split(/\/\*/g); const exists = pointer.has(data, parts[0]); if (exists) { const traverse = (subData, subPath, idx) => { if (idx === parts.length - 1) { wildcardPaths.push({ path: subPath, condition }); return; } const list = pointer.get(subData, subPath); if (Array.isArray(list)) { list.forEach((_, i) => { traverse(list[i], `${subPath}/${i}${parts[idx + 1]}`, idx + 1); }); } }; traverse(data, parts[0], 0); } } else { runFilter({ path, condition }); } }); wildcardPaths.forEach(runFilter); return data; } return data; }, [getDataPathHandlerParameters]); const visibleDataHandler = useCallback(function () { let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : internalDataRef.current; let { keepPaths, removePaths } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; const visibleData = {}; mountedFieldsRef.current.forEach((item, path) => { if (item && item.isVisible !== false && (item.isPreMounted !== false || item.wasStepChange === true) && (removePaths ? !removePaths.includes(path) : true) && pointer.has(data, path)) { pointer.set(visibleData, path, pointer.get(data, path)); } }); if (keepPaths) { keepPaths.forEach(path => { if (pointer.has(data, path)) { pointer.set(visibleData, path, pointer.get(data, path)); } }); } return visibleData; }, []); const filterDataHandler = useCallback((data, filter) => { if (filter) { return mutateDataHandler(data, filter, { remove: true }); } return data; }, [mutateDataHandler]); const filterData = useCallback(function (filter) { let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : internalDataRef.current; return filterDataHandler(data, filter); }, [filterDataHandler]); const fieldDisplayValueRef = useRef({}); const fieldConnectionsRef = useRef({}); const setFieldConnection = useCallback((path, connections) => { fieldConnectionsRef.current[path] = connections; }, []); const fieldInternalsRef = useRef({}); const setFieldInternals = useCallback((path, internals) => { fieldInternalsRef.current[path] = Object.assign(fieldInternalsRef.current[path] || {}, internals); }, []); const valueInternalsRef = useRef({}); const setValueInternals = useCallback((path, props) => { valueInternalsRef.current[path] = Object.assign(valueInternalsRef.current[path] || {}, { props }); }, []); const hasFieldWithAsyncValidator = useCallback(() => { for (const path in fieldInternalsRef.current) { var _mountedFieldsRef$cur; if ((_mountedFieldsRef$cur = mountedFieldsRef.current.get(path)) !== null && _mountedFieldsRef$cur !== void 0 && _mountedFieldsRef$cur.isMounted) { var _fieldInternalsRef$cu2; const props = (_fieldInternalsRef$cu2 = fieldInternalsRef.current[path]) === null || _fieldInternalsRef$cu2 === void 0 ? void 0 : _fieldInternalsRef$cu2.props; if (isAsync(props === null || props === void 0 ? void 0 : props.onChangeValidator) || isAsync(props === null || props === void 0 ? void 0 : props.onBlurValidator)) { return true; } } } return false; }, []); const sharedData = useSharedState(id); const sharedAttachments = useSharedState(createReferenceKey(id, 'attachments')); const sharedDataContext = useSharedState(createReferenceKey(id, 'data-context')); const setSharedData = sharedData.set; const extendSharedData = sharedData.extend; const extendAttachment = sharedAttachments.extend; const rerenderUseDataHook = (_sharedAttachments$da = sharedAttachments.data) === null || _sharedAttachments$da === void 0 ? void 0 : _sharedAttachments$da.rerenderUseDataHook; const cacheRef = useRef({ data, schema, shared: sharedData.data, hasUsedInitialData: false }); const internalData = useMemo(() => { if (id && initialData && !sharedData.data) { sharedData.update(initialData); } if (id && initialData && sharedData.data && cacheRef.current.shared === sharedData.data && internalDataRef.current === initialData && typeof internalDataRef.current === 'object') { return _objectSpread(_objectSpread({}, internalDataRef.current), sharedData.data || {}); } if (id && !initialData && !internalDataRef.current && sharedData.data && cacheRef.current.shared === sharedData.data) { return sharedData.data; } if (id && sharedData.data && cacheRef.current.shared !== sharedData.data && sharedData.data !== internalDataRef.current && typeof internalDataRef.current === 'object') { cacheRef.current.shared = sharedData.data; if (isEmptyDataRef.current) { return Array.isArray(internalDataRef.current) ? [] : clearedData; } return _objectSpread(_objectSpread({}, internalDataRef.current), sharedData.data || {}); } if (data !== cacheRef.current.data) { cacheRef.current.data = data; return data; } return internalDataRef.current; }, [id, initialData, sharedData, data]); internalDataRef.current = props.path && pointer.has(internalData, props.path) ? pointer.get(internalData, props.path) : internalData; const clearData = useCallback(() => { var _ref5, _requestAnimationFram; isEmptyDataRef.current = true; internalDataRef.current = (_ref5 = typeof emptyData === 'function' ? emptyData(internalDataRef.current) : emptyData) !== null && _ref5 !== void 0 ? _ref5 : Array.isArray(internalDataRef.current) ? [] : clearedData; if (id) { setSharedData(internalDataRef.current); } forceUpdate(); onClear === null || onClear === void 0 ? void 0 : onClear(); (_requestAnimationFram = requestAnimationFrame) === null || _requestAnimationFram === void 0 ? void 0 : _requestAnimationFram(() => { isEmptyDataRef.current = false; }); }, [emptyData, id, onClear, setSharedData]); useMemo(() => { executeAjvValidator(); }, [internalDataRef.current]); const storeInSession = useMemo(() => { return debounce(() => { var _window$sessionStorag2; (_window$sessionStorag2 = window.sessionStorage) === null || _window$sessionStorag2 === void 0 ? void 0 : _window$sessionStorag2.setItem(sessionStorageId, JSON.stringify(internalDataRef.current)); }, process.env.NODE_ENV === 'test' ? 1 : 800); }, [sessionStorageId]); const setData = useCallback(function (newData) { let { preventUpdate = false } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (transformIn) { newData = mutateDataHandler(newData, transformIn); } internalDataRef.current = newData; if (id) { extendSharedData(newData, { preventSyncOfSameInstance: true }); if (filterSubmitData) { rerenderUseDataHook === null || rerenderUseDataHook === void 0 ? void 0 : rerenderUseDataHook(); } } if (sessionStorageId && typeof window !== 'undefined') { storeInSession(); } if (!preventUpdate) { forceUpdate(); } }, [extendSharedData, filterSubmitData, id, mutateDataHandler, rerenderUseDataHook, sessionStorageId, storeInSession, transformIn]); const updateDataValue = useCallback(function (path, value) { var _internalDataRef$curr; let { preventUpdate } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; if (!path) { return; } const givenData = path === '/' ? value : (_internalDataRef$curr = internalDataRef.current) !== null && _internalDataRef$curr !== void 0 ? _internalDataRef$curr : path.match(isArrayJsonPointer) ? [] : {}; let newData = null; try { newData = structuredClone(givenData); } catch (e) { newData = givenData; } if (path !== '/') { pointer.set(newData, path, value); } setData(newData, { preventUpdate }); onUpdateDataValue === null || onUpdateDataValue === void 0 ? void 0 : onUpdateDataValue(path, value, { preventUpdate }); }, [onUpdateDataValue, setData]); const handlePathChangeUnvalidated = useCallback(async (path, value) => { if (!path) { return null; } updateDataValue(path, value); if (isAsync(onPathChange)) { await (onPathChange === null || onPathChange === void 0 ? void 0 : onPathChange(path, value)); } else { onPathChange === null || onPathChange === void 0 ? void 0 : onPathChange(path, value); } for (const itm of fieldEventListenersRef.current) { if (itm.type === 'onPathChange' && itm.path === path) { const { callback } = itm; if (isAsync(callback)) { await callback({ value }); } else { callback({ value }); } } } }, [onPathChange, updateDataValue]); const handlePathChange = useCallback(async function (path) { let value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '_undefined_'; if (!path) { return null; } if (value !== '_undefined_') { handlePathChangeUnvalidated(path, value); } showAllErrorsRef.current = false; validateData(); const data = internalDataRef.current; const options = { filterData }; const transformedData = transformOut ? mutateDataHandler(data, transformOut) : data; for (const cb of changeHandlerStackRef.current) { if (isAsync(onChange)) { await cb(transformedData, options); } else { cb(transformedData, options); } } if (isAsync(onChange)) { return await onChange(transformedData, options); } return onChange === null || onChange === void 0 ? void 0 : onChange(transformedData, options); }, [filterData, handlePathChangeUnvalidated, mutateDataHandler, onChange, transformOut, validateData]); const changeHandlerStackRef = useRef([]); const addOnChangeHandler = useCallback(callback => { const exists = changeHandlerStackRef.current.some(cb => { return callback === cb; }); if (!exists) { changeHandlerStackRef.current.push(callback); } }, []); const setMountedFieldState = useCallback((path, state) => { mountedFieldsRef.current.set(path, _objectSpread(_objectSpread({}, mountedFieldsRef.current.get(path)), state)); for (const itm of fieldEventListenersRef.current) { if (itm.type === 'onMount' && itm.path === path) { const { callback } = itm; callback(); } } }, []); const scrollToTop = useCallback(() => { if (typeof window !== 'undefined') { var _window, _window$scrollTo; (_window = window) === null || _window === void 0 ? void 0 : (_window$scrollTo = _window.scrollTo) === null || _window$scrollTo === void 0 ? void 0 : _window$scrollTo.call(_window, { top: 0, behavior: 'smooth' }); } }, []); const handleSubmitCall = useCallback(async args => { const { onSubmit, enableAsyncBehavior, skipFieldValidation, skipErrorCheck } = args; setSubmitState({ error: undefined, customStatus: undefined }); const asyncBehaviorIsEnabled = (skipErrorCheck ? true : !hasErrors() || hasFieldState('pending')) && (enableAsyncBehavior || hasFieldWithAsyncValidator()); if (asyncBehaviorIsEnabled) { setFormState('pending'); } if (!skipFieldValidation) { for (const item of fieldEventListenersRef.current) { var _mountedFieldsRef$cur2; const { path, type, callback } = item; if (type === 'onSubmitCall' && (_mountedFieldsRef$cur2 = mountedFieldsRef.current.get(path)) !== null && _mountedFieldsRef$cur2 !== void 0 && _mountedFieldsRef$cur2.isMounted) { if (asyncBehaviorIsEnabled) { await callback(); } else { callback(); } } } } let result; if (!(skipErrorCheck ? false : hasErrors()) && !hasFieldState('pending') && (skipFieldValidation ? true : !hasFieldState('error'))) { var _result2, _result4, _result5, _result6, _result7; let submitResult; try { if (isolate) { for (const item of fieldEventListenersRef.current) { const { type, callback } = item; if (type === 'onBeforeCommit') { callback(); } } submitResult = await (onCommit === null || onCommit === void 0 ? void 0 : onCommit(internalDataRef.current, { clearData })); } else { submitResult = await onSubmit(); } if (submitResult instanceof Error) { throw submitResult; } } catch (error) { submitResult = { error }; } result = submitResult; if (asyncBehaviorIsEnabled) { var _result; if ((_result = result) !== null && _result !== void 0 && _result.error) { setFormState('abort'); } else if (keepPending.current !== true) { setFormState('complete'); } } if ((_result2 = result) !== null && _result2 !== void 0 && _result2['status']) { var _result3; setFormState((_result3 = result) === null || _result3 === void 0 ? void 0 : _result3['status']); } if ((_result4 = result) !== null && _result4 !== void 0 && _result4.error || (_result5 = result) !== null && _result5 !== void 0 && _result5.warning || (_result6 = result) !== null && _result6 !== void 0 && _result6.info || (_result7 = result) !== null && _result7 !== void 0 && _result7.customStatus) { setSubmitState(result); } } else { if (asyncBehaviorIsEnabled) { await new Promise(resolve => window.requestAnimationFrame(resolve)); setFormState(undefined); if (!skipFieldValidation) { onSubmitContinueRef.current = () => { window.requestAnimationFrame(() => { handleSubmitCall(_objectSpread(_objectSpread({}, args), {}, { skipFieldValidation: true })); }); }; } } setShowAllErrors(true); onSubmitRequest === null || onSubmitRequest === void 0 ? void 0 : onSubmitRequest({ getErrors: () => Object.keys(fieldErrorRef.current).map(path => { return getDataPathHandlerParameters(path); }).filter(_ref6 => { let { error } = _ref6; return error; }) }); for (const itm of fieldEventListenersRef.current) { if (itm.type === 'onSubmitRequest') { itm.callback(); } } } return result; }, [clearData, getDataPathHandlerParameters, hasErrors, hasFieldState, hasFieldWithAsyncValidator, isolate, onCommit, onSubmitRequest, setFormState, setShowAllErrors, setSubmitState]); const getSubmitData = useCallback(() => { const data = internalDataRef.current; const mutatedData = transformOut ? mutateDataHandler(data, transformOut) : data; const filteredData = filterSubmitData ? filterDataHandler(mutatedData, filterSubmitData) : mutatedData; return filteredData; }, [filterDataHandler, filterSubmitData, mutateDataHandler, transformOut]); const getSubmitParams = useCallback(() => { const reduceToVisibleFields = (data, options) => { return visibleDataHandler(transformOut ? mutateDataHandler(data, transformOut) : data, options); }; const transformData = (data, handler) => { return mutateDataHandler(data, handler, { mutate: false, fireHandlerWhen: _ref7 => { let { type } = _ref7; return type === 'field'; } }); }; const formElement = formElementRef.current; const params = { filterData, reduceToVisibleFields, transformData, resetForm: () => { var _formElement$reset; formElement === null || formElement === void 0 ? void 0 : (_formElement$reset = formElement.reset) === null || _formElement$reset === void 0 ? void 0 : _formElement$reset.call(formElement); if (typeof window !== 'undefined') { if (sessionStorageId) { window.sessionStorage.removeItem(sessionStorageId); } } forceUpdate(); }, clearData }; return params; }, [clearData, filterData, mutateDataHandler, sessionStorageId, transformOut, visibleDataHandler]); const handleSubmit = useCallback(async () => { for (const item of fieldEventListenersRef.current) { const { type, callback } = item; if (type === 'onBeforeSubmit') { callback(); } } return await handleSubmitCall({ enableAsyncBehavior: isAsync(onSubmit), onSubmit: async () => { let stop = false; const preventSubmit = () => stop = true; for (const item of fieldEventListenersRef.current) { const { type, callback } = item; if (type === 'onSubmit') { if (isAsync(callback)) { await callback({ preventSubmit }); } else { callback({ preventSubmit }); } } } if (stop) { return; } const data = getSubmitData(); const options = getSubmitParams(); let result = undefined; if (isAsync(onSubmit)) { result = await onSubmit(data, options); } else { result = onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit(data, options); } const completeResult = await (onSubmitComplete === null || onSubmitComplete === void 0 ? void 0 : onSubmitComplete(data, result)); if (completeResult) { result = Object.keys(result).length > 0 ? _objectSpread(_objectSpread({}, result), completeResult) : completeResult; } if (scrollTopOnSubmit) { scrollToTop(); } return result; } }); }, [getSubmitData, getSubmitParams, handleSubmitCall, onSubmit, onSubmitComplete, scrollToTop, scrollTopOnSubmit]); const fieldEventListenersRef = useRef([]); const setFieldEventListener = useCallback(function (path, type, callback) { let { remove = false } = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; fieldEventListenersRef.current = fieldEventListenersRef.current.filter(_ref8 => { let { path: p, type: t, callback: c } = _ref8; return !(p === path && t === type && c === callback); }); if (!remove) { fieldEventListenersRef.current.push({ path, type, callback }); } }, []); const onSubmitContinueRef = useRef(null); if (!hasFieldState('pending')) { var _onSubmitContinueRef$; (_onSubmitContinueRef$ = onSubmitContinueRef.current) === null || _onSubmitContinueRef$ === void 0 ? void 0 : _onSubmitContinueRef$.call(onSubmitContinueRef); onSubmitContinueRef.current = null; } useLayoutEffect(() => { if (schema) { var _ajvRef$current; ajvValidatorRef.current = (_ajvRef$current = ajvRef.current) === null || _ajvRef$current === void 0 ? void 0 : _ajvRef$current.compile(schema); } validateData(); }, [schema, validateData]); useUpdateEffect(() => { if (schema && schema !== cacheRef.current.schema) { var _ajvRef$current2; cacheRef.current.schema = schema; ajvValidatorRef.current = (_ajvRef$current2 = ajvRef.current) === null || _ajvRef$current2 === void 0 ? void 0 : _ajvRef$current2.compile(schema); validateData(); forceUpdate(); } }, [schema, validateData, forceUpdate]); const onTimeout = useCallback(() => { setFormState(undefined); setSubmitState({ info: undefined, warning: undefined, error: undefined, customStatus: undefined }); }, [setFormState, setSubmitState]); useLayoutEffect(() => { if (id) { if (initialData && !sharedData.data) { extendSharedData(initialData, { preventSyncOfSameInstance: true }); } } }, [id, initialData, extendSharedData, sharedData.data]); useLayoutEffect(() => { if (id) { extendAttachment({ visibleDataHandler, filterDataHandler, hasErrors, hasFieldError, setShowAllErrors, setSubmitState, clearData, setData, updateDataValue, fieldConnectionsRef, internalDataRef }, { preventSyncOfSameInstance: true }); if (filterSubmitData) { rerenderUseDataHook === null || rerenderUseDataHook === void 0 ? void 0 : rerenderUseDataHook(); } } }, [clearData, extendAttachment, filterDataHandler, filterSubmitData, hasErrors, hasFieldError, id, rerenderUseDataHook, setData, setShowAllErrors, setSubmitState, updateDataValue, visibleDataHandler]); const { bufferedFormState: formState } = useFormStatusBuffer({ formState: formStateRef.current, waitFor: hasFieldState('pending'), minimumAsyncBehaviorTime, asyncSubmitTimeout, onTimeout }); const submitState = submitStateRef.current; const disabled = typeof (rest === null || rest === void 0 ? void 0 : rest['disabled']) === 'boolean' ? rest === null || rest === void 0 ? void 0 : rest['disabled'] : formState === 'pending' === true ? true : undefined; const contextErrorMessages = (errorMessages === null || errorMessages === void 0 ? void 0 : errorMessages[locale !== null && locale !== void 0 ? locale : sharedLocale]) || errorMessages; const getSourceValue = useCallback(value => { const data = internalDataRef.current; if (String(value).startsWith('/') && pointer.has(data, String(value))) { return pointer.get(data, String(value)); } return value; }, []); const contextValue = _objectSpread({ handlePathChange, handlePathChangeUnvalidated, handleSubmit, setMountedFieldState, handleSubmitCall, setFormState, setSubmitState, setShowAllErrors, revealError, setFieldEventListener, setFieldState, setFieldError, setFieldConnection, setFieldInternals, setValueInternals, hasErrors, hasFieldError, hasFieldState, validateData, updateDataValue, setData, clearData, visibleDataHandler, filterDataHandler, getSubmitData, getSubmitParams, addOnChangeHandler, scrollToTop, schema, disabled, required, formState, submitState, contextErrorMessages, hasContext: true, errors: errorsRef.current, showAllErrors: showAllErrorsRef.current, hasVisibleError: hasVisibleErrorRef.current.size > 0, addSetShowAllErrorsRef, fieldConnectionsRef, fieldDisplayValueRef, fieldInternalsRef, valueInternalsRef, mountedFieldsRef, snapshotsRef, existingFieldsRef, formElementRef, isEmptyDataRef, fieldErrorRef, errorsRef, ajvInstance: ajvRef.current, countryCode: countryCode ? getSourceValue(countryCode) : undefined, id, data: internalDataRef.current, internalDataRef, props }, rest); if (id) { sharedDataContext.set(contextValue); } return React.createElement(DataContext.Provider, { value: contextValue }, React.createElement(FieldPropsProvider, { FormStatus: globalStatusId ? { globalStatus: { id: globalStatusId, title: translation.errorSummaryTitle, show: Boolean(showAllErrorsRef.current) } } : undefined, formElement: disabled ? { disabled: true } : undefined, locale: locale ? locale : undefined, translations: translations ? translations : undefined }, children)); } function useFormStatusBuffer(props) { const { formState, waitFor, minimumAsyncBehaviorTime, asyncSubmitTimeout, onTimeout } = props || {}; const [, forceUpdate] = useReducer(() => ({}), {}); const stateRef = useRef(); const nowRef = useRef(null); const timeoutRef = useRef({}); const setState = useCallback(state => { stateRef.current = state; forceUpdate(); }, [forceUpdate]); const clear = useCallback(() => { for (const key in timeoutRef.current) { clearTimeout(timeoutRef.current[key]); } }, []); const hadCompleteRef = useRef(false); const activeElementRef = useRef(null); useEffect(() => { const isTest = process.env.NODE_ENV === 'test'; const minimum = minimumAsyncBehaviorTime !== null && minimumAsyncBehaviorTime !== void 0 ? minimumAsyncBehaviorTime : isTest ? 1 : 1000; if (stateRef.current && formState === 'error') { clear(); setState(undefined); return; } if (formState === 'abort') { clear(); setState('abort'); timeoutRef.current.reset = setTimeout(() => { nowRef.current = 0; setState(undefined); }, minimum); return; } if (formState === 'complete') { hadCompleteRef.current = true; } if (formState === 'pending' && stateRef.current !== 'pending') { activeElementRef.current = document.activeElement; clear(); nowRef.current = Date.now(); hadCompleteRef.current = false; setState('pending'); } else if (stateRef.current === 'pending') { const offset = Math.max(Date.now() - nowRef.current); const delay = isTest ? minimum : Math.max(minimum - offset, 0); if (!waitFor) { timeoutRef.current.complete = setTimeout(() => { if (hadCompleteRef.current) { setState('complete'); } window.requestAnimationFrame(() => { var _activeElementRef$cur, _activeElementRef$cur2; (_activeElementRef$cur = activeElementRef.current) === null || _activeElementRef$cur === void 0 ? void 0 : (_activeElementRef$cur2 = _activeElementRef$cur.focus) === null || _activeElementRef$cur2 === void 0 ? void 0 : _activeElementRef$cur2.call(_activeElementRef$cur); }); }, delay); timeoutRef.current.reset = setTimeout(() => { nowRef.current = 0; setState(undefined); clear(); }, delay + minimum); } } if (stateRef.current === 'pending') { timeoutRef.current.timeout = setTimeout(() => { clear(); setState(undefined); onTimeout === null || onTimeout === void 0 ? void 0 : onTimeout(); }, asyncSubmitTimeout !== null && asyncSubmitTimeout !== void 0 ? asyncSubmitTimeout : 30000); } return clear; }, [clear, minimumAsyncBehaviorTime, formState, setState, waitFor, asyncSubmitTimeout, onTimeout]); return { bufferedFormState: stateRef.current }; } export const clearedData = Object.freeze({}); //# sourceMappingURL=Provider.js.map