UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

1,174 lines (1,173 loc) 77.5 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.checkForError = checkForError; exports.clearedArray = void 0; exports.default = useFieldProps; var _push = _interopRequireDefault(require("core-js-pure/stable/instance/push.js")); var _react = _interopRequireWildcard(require("react")); var _index = _interopRequireDefault(require("../utils/json-pointer/index.js")); var _index2 = require("../utils/index.js"); var _index3 = require("../DataContext/index.js"); var _Provider = require("../DataContext/Provider/Provider.js"); var _FieldProviderContext = _interopRequireDefault(require("../Field/Provider/FieldProviderContext.js")); var _componentHelper = require("../../../shared/component-helper.js"); var _useId = _interopRequireDefault(require("../../../shared/helpers/useId.js")); var _useUpdateEffect = _interopRequireDefault(require("../../../shared/helpers/useUpdateEffect.js")); var _FieldBlockContext = _interopRequireDefault(require("../FieldBlock/FieldBlockContext.js")); var _IterateItemContext = _interopRequireDefault(require("../Iterate/IterateItemContext.js")); var _SectionContext = _interopRequireDefault(require("../Form/Section/SectionContext.js")); var _FieldBoundaryContext = _interopRequireDefault(require("../DataContext/FieldBoundary/FieldBoundaryContext.js")); var _VisibilityContext = _interopRequireDefault(require("../Form/Visibility/VisibilityContext.js")); var _index4 = _interopRequireDefault(require("../Wizard/Context/index.js")); var _StepContext = _interopRequireDefault(require("../Wizard/Step/StepContext.js")); var _SnapshotContext = _interopRequireDefault(require("../Form/Snapshot/SnapshotContext.js")); var _useProcessManager = _interopRequireDefault(require("./useProcessManager.js")); var _usePath = _interopRequireDefault(require("./usePath.js")); var _Context = _interopRequireDefault(require("../../../shared/Context.js")); var _useSharedState = require("../../../shared/helpers/useSharedState.js"); var _isAsync = require("../../../shared/helpers/isAsync.js"); var _useTranslation = _interopRequireDefault(require("./useTranslation.js")); var _useExternalValue = _interopRequireDefault(require("./useExternalValue.js")); var _useDataValue = _interopRequireDefault(require("./useDataValue.js")); var _useIsomorphicLayoutEffect = require("../../../shared/helpers/useIsomorphicLayoutEffect.js"); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function useFieldProps(localProps, { executeOnChangeRegardlessOfError = false, executeOnChangeRegardlessOfUnchangedValue = false, updateContextDataInSync = false, omitMultiplePathWarning = false, forceUpdateWhenContextDataIsSet = false, omitSectionPath = false } = {}) { var _dataContext$props, _dataContext$props$lo, _dataContext$props2, _dataContext$props4, _localErrorRef$curren, _contextErrorRef$curr, _dataContext$internal, _dataContext$props6, _props$path, _props$autoComplete; const { extend } = (0, _react.useContext)(_FieldProviderContext.default); const props = extend(localProps); const { path: pathProp, value: valueProp, defaultValue, itemPath, emptyValue, required: requiredProp, disabled: disabledProp, info: infoProp, warning: warningProp, error: initialErrorProp = 'initial', errorMessages, onStatusChange, onFocus, onBlur, onChange, onBlurValidator, validator, onChangeValidator: onChangeValidatorProp = validator, exportValidators, schema, validateInitially, validateUnchanged, continuousValidation, validateContinuously = continuousValidation, transformIn = external => external, transformOut = internal => internal, toInput = value => value, fromInput = value => value, toEvent = value => value, transformValue = value => value, provideAdditionalArgs = (value, additionalArgs) => additionalArgs, fromExternal = value => value, validateRequired = (value, { emptyValue, required, error }) => { if (required && (value === emptyValue || typeof emptyValue === 'undefined' && value === '')) { return error; } } } = props; const [salt, forceUpdate] = (0, _react.useReducer)(() => ({}), {}); const isInternalRerenderRef = (0, _react.useRef)(undefined); (0, _react.useMemo)(() => { isInternalRerenderRef.current = salt; }, [salt]); const { startProcess } = (0, _useProcessManager.default)(); const id = (0, _useId.default)(props.id); const dataContext = (0, _react.useContext)(_index3.Context); const { locale: sharedLocale } = (0, _react.useContext)(_Context.default) || {}; const fieldBlockContext = (0, _react.useContext)(_FieldBlockContext.default); const iterateItemContext = (0, _react.useContext)(_IterateItemContext.default); const sectionContext = (0, _react.useContext)(_SectionContext.default); const fieldBoundaryContext = (0, _react.useContext)(_FieldBoundaryContext.default); const wizardContext = (0, _react.useContext)(_index4.default); const wizardStepContext = (0, _react.useContext)(_StepContext.default); const { setMountedField: setMountedFieldSnapshot } = (0, _react.useContext)(_SnapshotContext.default) || {}; const { isVisible, keepInDOM } = (0, _react.useContext)(_VisibilityContext.default) || {}; const handleFieldAsVisible = isVisible || keepInDOM; const { getValueByPath, getSourceValue } = (0, _useDataValue.default)(); const translation = (0, _useTranslation.default)(); const { formatMessage } = translation; const translationRef = (0, _react.useRef)(translation); translationRef.current = translation; const transformers = (0, _react.useRef)({ transformIn, transformOut, provideAdditionalArgs, toInput, fromInput, toEvent, fromExternal, transformValue, validateRequired }); const { handlePathChangeUnvalidated: handlePathChangeUnvalidatedDataContext, handlePathChange: handlePathChangeDataContext, updateDataValue: updateDataValueDataContext, validateData: validateDataDataContext, setFieldState: setFieldStateDataContext, setFieldError: setFieldErrorDataContext, setFieldInternals: setFieldInternalsDataContext, setFieldConnection: setFieldConnectionDataContext, revealError: revealErrorDataContext, setMountedFieldState: setMountedFieldStateDataContext, getAjvInstance: getAjvInstanceDataContext, setFieldEventListener, errors: dataContextErrors, showAllErrors, contextErrorMessages, fieldDisplayValueRef, existingFieldsRef, fieldInternalsRef, mountedFieldsRef, sectionSchemaPathsRef, prerenderFieldProps, hasContext: hasDataContext } = dataContext || {}; const onChangeContext = dataContext === null || dataContext === void 0 || (_dataContext$props = dataContext.props) === null || _dataContext$props === void 0 ? void 0 : _dataContext$props.onChange; const locale = (_dataContext$props$lo = dataContext === null || dataContext === void 0 || (_dataContext$props2 = dataContext.props) === null || _dataContext$props2 === void 0 ? void 0 : _dataContext$props2.locale) !== null && _dataContext$props$lo !== void 0 ? _dataContext$props$lo : sharedLocale; const disabled = disabledProp !== null && disabledProp !== void 0 ? disabledProp : props.readOnly; const inFieldBlock = Boolean(fieldBlockContext && fieldBlockContext.disableStatusSummary !== true); const resolvedSchema = (0, _react.useMemo)(() => { const s = schema; if (typeof s === 'function') { try { return s(props); } catch (_) { return undefined; } } return s; }, [schema]); const finalSchema = (0, _react.useMemo)(() => { const s = resolvedSchema; if (typeof s === 'function') { try { return s(props); } catch (_) { return undefined; } } return s; }, [resolvedSchema]); const hasZodSchema = (0, _index2.isZodSchema)(finalSchema); const { setBlockRecord, setFieldState: setFieldStateFieldBlock, showFieldError: showFieldErrorFieldBlock, mountedFieldsRef: mountedFieldsRefFieldBlock } = inFieldBlock ? fieldBlockContext : {}; const { activeIndex, activeIndexRef, setFieldError: setFieldErrorWizard } = wizardContext || {}; const { index: wizardIndex } = wizardStepContext || {}; const { handleChange: handleChangeIterateContext, index: iterateIndex, arrayValue: iterateArrayValue, nestedIteratePath } = iterateItemContext || {}; const { path: sectionPath, errorPrioritization } = sectionContext || {}; const { setFieldError: setFieldErrorBoundary, revealError: revealErrorBoundary, showBoundaryErrors } = fieldBoundaryContext || {}; const hasPath = Boolean(pathProp); const isParentRelativePath = typeof pathProp === 'string' && pathProp.startsWith('../'); const hasItemPath = Boolean(itemPath); const { path, identifier, makeIteratePath, joinPath, cleanPath } = (0, _usePath.default)({ id, path: pathProp, itemPath, omitSectionPath }); const sectionSchemaPaths = sectionSchemaPathsRef === null || sectionSchemaPathsRef === void 0 ? void 0 : sectionSchemaPathsRef.current; const hasSectionSchema = Boolean((sectionSchemaPaths === null || sectionSchemaPaths === void 0 ? void 0 : sectionSchemaPaths.size) && identifier && Array.from(sectionSchemaPaths).some(sectionSchemaPath => { if (sectionSchemaPath === '/') { return true; } return identifier === sectionSchemaPath || identifier.startsWith(`${sectionSchemaPath}/`); })); const defaultValueRef = (0, _react.useRef)(defaultValue); (0, _useIsomorphicLayoutEffect.useIsomorphicLayoutEffect)(() => { defaultValueRef.current = defaultValue; }, []); const tmpValue = (0, _useExternalValue.default)({ path: identifier, itemPath, value: valueProp, transformers, emptyValue: defaultValue ? undefined : emptyValue }); const externalValueDeps = tmpValue; const externalValue = transformers.current.transformIn(tmpValue !== null && tmpValue !== void 0 ? tmpValue : defaultValueRef.current); (0, _react.useEffect)(() => { var _dataContext$props3; if (finalSchema && !hasZodSchema && !omitMultiplePathWarning && hasDataContext && !(dataContext !== null && dataContext !== void 0 && (_dataContext$props3 = dataContext.props) !== null && _dataContext$props3 !== void 0 && _dataContext$props3.ajvInstance)) { (0, _componentHelper.warn)(`Field${identifier ? ` (${identifier})` : ''} received a JSON Schema but no ajvInstance was provided to Form.Handler. Provide "ajvInstance" on Form.Handler.`); } }, [finalSchema, hasZodSchema, identifier, hasDataContext, dataContext === null || dataContext === void 0 || (_dataContext$props4 = dataContext.props) === null || _dataContext$props4 === void 0 ? void 0 : _dataContext$props4.ajvInstance, omitMultiplePathWarning]); const valueRef = (0, _react.useRef)(externalValue); const changedRef = (0, _react.useRef)(); const hasFocusRef = (0, _react.useRef)(); const revealErrorRef = (0, _react.useRef)(null); const required = (0, _react.useMemo)(() => { if (typeof requiredProp !== 'undefined') { return requiredProp; } if (schema || dataContext !== null && dataContext !== void 0 && dataContext.schema) { const paths = identifier.split('/'); if (paths.length > 0) { const requiredInSchema = [schema === null || schema === void 0 ? void 0 : schema['required']]; if (paths.length > 1) { const schema = dataContext.schema; const pathWithoutLast = paths.slice(0, -1).join('/properties/'); const schemaPart = _index.default.has(schema, pathWithoutLast) ? _index.default.get(schema, pathWithoutLast) : schema; const requiredSchemaList = schemaPart === null || schemaPart === void 0 ? void 0 : schemaPart['required']; if (Array.isArray(requiredSchemaList)) { const rootPath = pathWithoutLast.replace(/properties\//g, ''); const requiredList = requiredSchemaList.map(path => { path = cleanPath('/' + path); return sectionPath && path.startsWith(sectionPath) ? path : joinPath([sectionPath || rootPath, path]); }); (0, _push.default)(requiredInSchema).call(requiredInSchema, requiredList); } } const collected = requiredInSchema.flatMap(value => value).filter(Boolean); if (collected.filter(Boolean).some(path => { path = cleanPath('/' + path); return identifier === path || sectionPath === path; })) { return true; } } } }, [cleanPath, dataContext.schema, identifier, joinPath, requiredProp, schema, sectionPath]); const getFieldByPath = (0, _react.useCallback)(path => { var _fieldInternalsRef$cu; return ((_fieldInternalsRef$cu = fieldInternalsRef.current) === null || _fieldInternalsRef$cu === void 0 ? void 0 : _fieldInternalsRef$cu[path]) || { props: undefined, id: undefined }; }, [fieldInternalsRef]); const errorMessageCacheRef = (0, _react.useRef)(new Map()); const ensureErrorMessageObject = (0, _react.useCallback)(error => { let key = null; let returnValue = error; if (typeof error === 'string') { key = error; returnValue = new Error(error); } else if (error && _react.default.isValidElement(error)) { key = error.key || (0, _componentHelper.convertJsxToString)(error); returnValue = new _index2.FormError('Error', { formattedMessage: error }); } if (key) { if (errorMessageCacheRef.current.has(key)) { return errorMessageCacheRef.current.get(key); } else { errorMessageCacheRef.current.set(key, returnValue); } } return returnValue; }, []); const messageCacheRef = (0, _react.useRef)({ isSet: false, message: undefined }); const executeMessage = (0, _react.useCallback)((message, forceReturnErrorMessageObject) => { if (typeof message === 'function') { const ALWAYS = 4; const INITIALLY = 8; let currentMode = ALWAYS; const msg = message(valueRef.current, { conditionally: (callback, options) => { currentMode &= ~ALWAYS; if (options !== null && options !== void 0 && options.showInitially) { currentMode |= INITIALLY; } return executeMessage(callback()); }, getValueByPath, getFieldByPath }); if (msg === undefined) { messageCacheRef.current.message = undefined; return null; } const isError = msg instanceof Error || msg instanceof _index2.FormError || Array.isArray(msg) && checkForError(msg); if (!messageCacheRef.current.isSet && currentMode & INITIALLY || currentMode & ALWAYS || hasFocusRef.current === false || messageCacheRef.current.message) { if (isInternalRerenderRef.current || currentMode & ALWAYS || !messageCacheRef.current.isSet && currentMode & INITIALLY) { if (msg) { messageCacheRef.current.isSet = true; } if (msg || !hasFocusRef.current || currentMode & ALWAYS) { messageCacheRef.current.message = msg; } } message = messageCacheRef.current.message; if (isError && message) { revealErrorRef.current = true; } if (!isError && !message) { return null; } } else { return undefined; } } return forceReturnErrorMessageObject ? ensureErrorMessageObject(message) : message; }, [getFieldByPath, getValueByPath, ensureErrorMessageObject]); const errorProp = initialErrorProp === 'initial' ? undefined : initialErrorProp; const error = executeMessage(errorProp, true); const warning = executeMessage(warningProp); const info = executeMessage(infoProp); if (revealErrorRef.current === null) { revealErrorRef.current = validateInitially !== null && validateInitially !== void 0 ? validateInitially : Boolean(errorProp); } const errorMethodRef = (0, _react.useRef)({}); const localErrorRef = (0, _react.useRef)(); const localErrorInitiatorRef = (0, _react.useRef)(); const contextErrorRef = (0, _react.useRef)(); const onChangeValidator = (0, _react.useMemo)(() => { if (onChangeValidatorProp) { return onChangeValidatorProp; } if (validateContinuously && onBlurValidator) { return onBlurValidator; } return undefined; }, [onChangeValidatorProp, validateContinuously, onBlurValidator]); const onChangeValidatorRef = (0, _react.useRef)(onChangeValidator); (0, _useUpdateEffect.default)(() => { onChangeValidatorRef.current = onChangeValidator; }, [onChangeValidator]); const onBlurValidatorRef = (0, _react.useRef)(onBlurValidator); (0, _useUpdateEffect.default)(() => { onBlurValidatorRef.current = onBlurValidator; }, [onBlurValidator]); const getAjvInstance = (0, _react.useCallback)(() => { return hasDataContext ? getAjvInstanceDataContext === null || getAjvInstanceDataContext === void 0 ? void 0 : getAjvInstanceDataContext() : (0, _index2.makeAjvInstance)(); }, [hasDataContext, getAjvInstanceDataContext]); const schemaValidatorRef = (0, _react.useRef)(); if (!schemaValidatorRef.current && finalSchema) { if (hasZodSchema) { schemaValidatorRef.current = (0, _index2.createZodValidator)(finalSchema); } else { var _getAjvInstance, _getAjvInstance$compi; schemaValidatorRef.current = (_getAjvInstance = getAjvInstance()) === null || _getAjvInstance === void 0 || (_getAjvInstance$compi = _getAjvInstance.compile) === null || _getAjvInstance$compi === void 0 ? void 0 : _getAjvInstance$compi.call(_getAjvInstance, finalSchema); } } const asyncBehaviorIsEnabled = (0, _react.useMemo)(() => { return (0, _isAsync.isAsync)(onChange) || (0, _isAsync.isAsync)(onChangeContext); }, [onChangeContext, onChange]); const validatedValueRef = (0, _react.useRef)(); const changeEventResultRef = (0, _react.useRef)(null); const asyncProcessRef = (0, _react.useRef)(null); const defineAsyncProcess = (0, _react.useCallback)(name => { asyncProcessRef.current = name; }, []); const asyncBufferRef = (0, _react.useRef)({}); for (const key in asyncBufferRef.current) { const { resolve, validateProcesses } = asyncBufferRef.current[key] || {}; if ((validateProcesses === null || validateProcesses === void 0 ? void 0 : validateProcesses()) === false) { delete asyncBufferRef.current[key]; if (typeof resolve === 'function') { window.requestAnimationFrame(resolve); } } } const eventPool = (0, _react.useRef)({ onChangeValidator: null, onBlurValidator: null, onChangeContext: null, onChangeLocal: null }); const addToPool = (0, _react.useCallback)((name, fn, runAsync) => { if (!eventPool.current[name]) { eventPool.current[name] = { fn, runAsync }; } }, []); const runPool = (0, _react.useCallback)(async (cb = null) => { for (const key in eventPool.current) { if (!eventPool.current[key]) { continue; } const { fn, runAsync } = eventPool.current[key] || {}; if (fn) { eventPool.current[key] = null; if (runAsync) { await fn(); } else { fn(); } } } cb === null || cb === void 0 || cb(); }, []); const fieldStateRef = (0, _react.useRef)(); const setFieldState = (0, _react.useCallback)(state => { fieldStateRef.current = state; setFieldStateDataContext === null || setFieldStateDataContext === void 0 || setFieldStateDataContext(identifier, resolveValidatingState(state)); setFieldStateFieldBlock === null || setFieldStateFieldBlock === void 0 || setFieldStateFieldBlock(identifier, resolveValidatingState(state)); if (!validateInitially) { forceUpdate(); } }, [setFieldStateDataContext, identifier, setFieldStateFieldBlock, validateInitially]); const setErrorState = (0, _react.useCallback)(hasError => { setFieldErrorWizard === null || setFieldErrorWizard === void 0 || setFieldErrorWizard(wizardIndex, identifier, handleFieldAsVisible !== false ? hasError : undefined); showFieldErrorFieldBlock === null || showFieldErrorFieldBlock === void 0 || showFieldErrorFieldBlock(identifier, hasError); revealErrorBoundary === null || revealErrorBoundary === void 0 || revealErrorBoundary(identifier, hasError); revealErrorDataContext === null || revealErrorDataContext === void 0 || revealErrorDataContext(identifier, hasError); }, [identifier, handleFieldAsVisible, revealErrorBoundary, revealErrorDataContext, setFieldErrorWizard, showFieldErrorFieldBlock, wizardIndex]); const revealError = (0, _react.useCallback)(() => { if (validateInitially === false && revealErrorRef.current === false) { revealErrorRef.current = undefined; return; } const hasError = Boolean(localErrorRef.current); revealErrorRef.current = true; setErrorState(hasError); }, [validateInitially, setErrorState]); const hideError = (0, _react.useCallback)(() => { if (revealErrorRef.current) { revealErrorRef.current = undefined; setErrorState(false); } }, [setErrorState]); const errorMessagesCacheRef = (0, _react.useRef)({ locale: null, errorMessages: null, extendedErrorMessages: null }); const combinedErrorMessages = (0, _react.useMemo)(() => { const cache = errorMessagesCacheRef.current; if (cache.locale === locale && errorMessages && cache.extendedErrorMessages && Object.values(cache.errorMessages || {}).join('') === Object.values(errorMessages || {}).join('')) { return cache.extendedErrorMessages; } const messages = { ...contextErrorMessages, ...(contextErrorMessages === null || contextErrorMessages === void 0 ? void 0 : contextErrorMessages[identifier]), ...errorMessages }; const extendedErrorMessages = (0, _index2.extendErrorMessagesWithTranslationMessages)((0, _index2.overwriteErrorMessagesWithGivenAjvKeys)(messages), translationRef.current); errorMessagesCacheRef.current = { locale, errorMessages, extendedErrorMessages }; return extendedErrorMessages; }, [contextErrorMessages, errorMessages, identifier, locale]); const prepareError = (0, _react.useCallback)(error => { const prepare = error => { if (error instanceof _index2.FormError) { let message = error.message; const { ajvKeyword } = error; if (typeof ajvKeyword === 'string') { const ajvMessage = combinedErrorMessages === null || combinedErrorMessages === void 0 ? void 0 : combinedErrorMessages[ajvKeyword]; if (ajvMessage) { message = ajvMessage; } } const { validationRule } = error; if (typeof validationRule === 'string') { const ajvMessage = combinedErrorMessages === null || combinedErrorMessages === void 0 ? void 0 : combinedErrorMessages[validationRule]; if (ajvMessage) { message = ajvMessage; } } if (combinedErrorMessages !== null && combinedErrorMessages !== void 0 && combinedErrorMessages[message]) { message = combinedErrorMessages === null || combinedErrorMessages === void 0 ? void 0 : combinedErrorMessages[message]; if (error.messageValues) { message = Object.entries(error.messageValues || {}).reduce((msg, [key, value]) => { return msg.replace(`{${key}}`, value); }, message); } } else if (message.includes('.')) { message = formatMessage(message, error.messageValues); } if (_react.default.isValidElement(message)) { error.formattedMessage = message; } else { error.message = message; } } return ensureErrorMessageObject(error); }; if (Array.isArray(error)) { return new _index2.FormError('Error', { errors: error.map(prepare) }); } if (error instanceof _index2.FormError) { if (Array.isArray(error.errors)) { error.errors = error.errors.map(prepare); return error; } return prepare(error); } return error; }, [combinedErrorMessages, ensureErrorMessageObject, formatMessage]); contextErrorRef.current = (0, _react.useMemo)(() => { const dataContextError = dataContextErrors === null || dataContextErrors === void 0 ? void 0 : dataContextErrors[identifier]; if (!dataContextError) { return undefined; } const error = prepareError(dataContextError); if ((0, _index2.errorChanged)(error, contextErrorRef.current)) { return error; } return contextErrorRef.current; }, [dataContextErrors, identifier, prepareError]); if (((_localErrorRef$curren = localErrorRef.current) === null || _localErrorRef$curren === void 0 ? void 0 : _localErrorRef$curren['ajvKeyword']) === 'type' || ((_contextErrorRef$curr = contextErrorRef.current) === null || _contextErrorRef$curr === void 0 ? void 0 : _contextErrorRef$curr['ajvKeyword']) === 'type') { revealErrorRef.current = true; } const getBufferedError = (0, _react.useCallback)(() => { if (initialErrorProp !== 'initial' && typeof errorProp !== 'function') { return prepareError(errorProp); } else if (revealErrorRef.current) { var _contextErrorRef$curr2, _ref, _prepareError; if (((_contextErrorRef$curr2 = contextErrorRef.current) === null || _contextErrorRef$curr2 === void 0 ? void 0 : _contextErrorRef$curr2['ajvKeyword']) === 'type') { return contextErrorRef.current; } return (_ref = (_prepareError = prepareError(error)) !== null && _prepareError !== void 0 ? _prepareError : localErrorRef.current) !== null && _ref !== void 0 ? _ref : contextErrorRef.current; } else if (error === null) { return null; } }, [error, errorProp, initialErrorProp, prepareError]); const bufferedError = getBufferedError(); const bufferedErrorRef = (0, _react.useRef)(bufferedError); bufferedErrorRef.current = bufferedError; const errorIsVisible = Boolean(bufferedError) || inFieldBlock && fieldBlockContext.hasErrorProp; const hasError = (0, _react.useCallback)(() => { var _ref2; return Boolean((_ref2 = error !== null && error !== void 0 ? error : localErrorRef.current) !== null && _ref2 !== void 0 ? _ref2 : contextErrorRef.current); }, [error]); const connectWithPathListenerRef = (0, _react.useRef)(() => { runOnChangeValidator(); runOnBlurValidator(); }); const handleConnectWithPath = (0, _react.useCallback)(path => { setFieldEventListener === null || setFieldEventListener === void 0 || setFieldEventListener(path, 'onPathChange', connectWithPathListenerRef.current); return { getValue: () => getValueByPath(path) }; }, [getValueByPath, setFieldEventListener]); const additionalArgsRef = (0, _react.useRef)({ validators: exportValidators, props, dataContext, getValueByPath, getSourceValue, setFieldEventListener }); additionalArgsRef.current.validators = exportValidators; additionalArgsRef.current.props = props; const additionalArgs = (0, _react.useMemo)(() => { const args = { ...combinedErrorMessages, errorMessages: combinedErrorMessages, ...additionalArgsRef.current, connectWithPath: path => { return handleConnectWithPath(path); }, connectWithItemPath: itemPath => { return handleConnectWithPath(makeIteratePath(itemPath)); } }; return args; }, [combinedErrorMessages, handleConnectWithPath, makeIteratePath]); const callStackRef = (0, _react.useRef)([]); const hasBeenCalledRef = (0, _react.useCallback)(validator => { var _context; const result = callStackRef.current.includes(validator); (0, _push.default)(_context = callStackRef.current).call(_context, validator); return result; }, []); const callValidatorFnAsync = (0, _react.useCallback)(async (validator, value = valueRef.current) => { if (typeof validator !== 'function') { return; } const result = await validator(value, additionalArgs); if (Array.isArray(result)) { const errors = []; for (const validatorOrError of result) { if (validatorOrError instanceof Error) { (0, _push.default)(errors).call(errors, validatorOrError); } else if (!hasBeenCalledRef(validatorOrError)) { const result = await callValidatorFnAsync(validatorOrError, value); if (result instanceof Error) { callStackRef.current = []; return result; } } } if (errors.length > 0) { return new _index2.FormError('Error', { errors }); } callStackRef.current = []; } else { return ensureErrorMessageObject(result); } }, [additionalArgs, hasBeenCalledRef, ensureErrorMessageObject]); const callValidatorFnSync = (0, _react.useCallback)((validator, value = valueRef.current) => { if (typeof validator !== 'function') { return; } const result = validator(value, additionalArgs); if (Array.isArray(result)) { const hasAsyncValidator = result.some(validator => (0, _isAsync.isAsync)(validator)); if (hasAsyncValidator) { return new Promise(resolve => { callValidatorFnAsync(validator, value).then(result => { resolve(result); }); }); } const errors = []; for (const validatorOrError of result) { if (validatorOrError instanceof Error) { (0, _push.default)(errors).call(errors, validatorOrError); } else if (!hasBeenCalledRef(validatorOrError)) { const result = callValidatorFnSync(validatorOrError, value); if (result instanceof Error) { callStackRef.current = []; return result; } } } if (errors.length > 0) { return new _index2.FormError('Error', { errors }); } callStackRef.current = []; } else { return ensureErrorMessageObject(result); } }, [additionalArgs, callValidatorFnAsync, hasBeenCalledRef, ensureErrorMessageObject]); const stateId = (0, _useId.default)(); const persistErrorState = (0, _react.useCallback)((method, initiator, errorArg = undefined) => { var _errorMethodRef$curre, _errorMethodRef$curre2; const error = prepareError(errorArg); if (!(0, _index2.errorChanged)(error, localErrorRef.current)) { return; } if (initiator !== 'dataContextError') { localErrorInitiatorRef.current = initiator; } if (method === 'wipe') { errorMethodRef.current = {}; } else { errorMethodRef.current[method] = error; } if (!error && method === 'gracefully' && ((_errorMethodRef$curre = errorMethodRef.current) !== null && _errorMethodRef$curre !== void 0 && _errorMethodRef$curre.weak || (_errorMethodRef$curre2 = errorMethodRef.current) !== null && _errorMethodRef$curre2 !== void 0 && _errorMethodRef$curre2.gracefully)) { return; } const currentError = handleFieldAsVisible !== false ? error : undefined; localErrorRef.current = currentError; setFieldErrorDataContext === null || setFieldErrorDataContext === void 0 || setFieldErrorDataContext(identifier, currentError); setFieldErrorBoundary === null || setFieldErrorBoundary === void 0 || setFieldErrorBoundary(identifier, currentError); setBlockRecord === null || setBlockRecord === void 0 || setBlockRecord({ stateId, identifier, type: 'error', content: currentError, showInitially: Boolean(inFieldBlock && validateInitially) }); setFieldStateDataContext === null || setFieldStateDataContext === void 0 || setFieldStateDataContext(identifier, error ? 'error' : undefined); if (updateContextDataInSync && !prerenderFieldProps) { setFieldErrorWizard === null || setFieldErrorWizard === void 0 || setFieldErrorWizard(wizardIndex, identifier, Boolean(currentError)); } forceUpdate(); }, [handleFieldAsVisible, identifier, inFieldBlock, prepareError, prerenderFieldProps, setBlockRecord, setFieldErrorBoundary, setFieldErrorDataContext, setFieldErrorWizard, setFieldStateDataContext, stateId, updateContextDataInSync, validateInitially, wizardIndex]); const clearErrorState = (0, _react.useCallback)(() => { persistErrorState('wipe', undefined); localErrorInitiatorRef.current = undefined; const schemaValidator = schemaValidatorRef.current; if (schemaValidator && !hasZodSchema && Array.isArray(schemaValidator === null || schemaValidator === void 0 ? void 0 : schemaValidator.errors)) { schemaValidator.errors = []; } }, [persistErrorState, hasZodSchema]); const setChanged = (0, _react.useCallback)(state => { changedRef.current = state; }, []); const validatorCacheRef = (0, _react.useRef)({ onChangeValidator: null, onBlurValidator: null }); const revealOnChangeValidatorResult = (0, _react.useCallback)(({ result, unchangedValue }) => { const runAsync = (0, _isAsync.isAsync)(onChangeValidatorRef.current); if (unchangedValue) { persistErrorState(runAsync ? 'gracefully' : 'weak', 'onChangeValidator', result); if (validateInitially && !changedRef.current || validateUnchanged || validateContinuously || runAsync) { window.requestAnimationFrame(() => { if (localErrorInitiatorRef.current === 'onChangeValidator') { revealError(); forceUpdate(); } }); } } if (runAsync) { defineAsyncProcess(undefined); if (unchangedValue) { setFieldState(result instanceof Error ? 'error' : 'complete'); } else { setFieldState('pending'); } } }, [validateContinuously, defineAsyncProcess, persistErrorState, revealError, setFieldState, validateInitially, validateUnchanged]); const callOnChangeValidator = (0, _react.useCallback)(async () => { if (typeof onChangeValidatorRef.current !== 'function') { return {}; } const tmpValue = valueRef.current; let result = (0, _isAsync.isAsync)(onChangeValidatorRef.current) ? await callValidatorFnAsync(onChangeValidatorRef.current) : callValidatorFnSync(onChangeValidatorRef.current); if (result instanceof Promise) { result = await result; } const unchangedValue = tmpValue === valueRef.current; return { result, unchangedValue }; }, [callValidatorFnAsync, callValidatorFnSync]); const startOnChangeValidatorValidation = (0, _react.useCallback)(async () => { if (typeof onChangeValidatorRef.current !== 'function') { return; } if ((0, _isAsync.isAsync)(onChangeValidatorRef.current)) { defineAsyncProcess('onChangeValidator'); setFieldState('validating'); hideError(); } const tmpValue = valueRef.current; let result = (0, _isAsync.isAsync)(onChangeValidatorRef.current) ? await callValidatorFnAsync(onChangeValidatorRef.current) : callValidatorFnSync(onChangeValidatorRef.current); if (result instanceof Promise) { result = await result; } const unchangedValue = tmpValue === valueRef.current; revealOnChangeValidatorResult({ result, unchangedValue }); return { result }; }, [callValidatorFnAsync, callValidatorFnSync, defineAsyncProcess, hideError, revealOnChangeValidatorResult, setFieldState]); const runOnChangeValidator = (0, _react.useCallback)(async () => { if (!onChangeValidatorRef.current) { return; } const { result, unchangedValue } = await callOnChangeValidator(); if (String(result) !== String(validatorCacheRef.current.onChangeValidator)) { if (result) { revealOnChangeValidatorResult({ result, unchangedValue }); } else { hideError(); clearErrorState(); } } validatorCacheRef.current.onChangeValidator = result || null; }, [callOnChangeValidator, clearErrorState, hideError, revealOnChangeValidatorResult]); const callOnBlurValidator = (0, _react.useCallback)(async ({ overrideValue = null } = {}) => { if (typeof onBlurValidatorRef.current !== 'function') { return {}; } const value = transformers.current.toEvent(overrideValue !== null && overrideValue !== void 0 ? overrideValue : valueRef.current, 'onBlurValidator'); let result = (0, _isAsync.isAsync)(onBlurValidatorRef.current) ? await callValidatorFnAsync(onBlurValidatorRef.current, value) : callValidatorFnSync(onBlurValidatorRef.current, value); if (result instanceof Promise) { result = await result; } return { result }; }, [callValidatorFnAsync, callValidatorFnSync]); const revealOnBlurValidatorResult = (0, _react.useCallback)(({ result }) => { persistErrorState('gracefully', 'onBlurValidator', result); if ((0, _isAsync.isAsync)(onBlurValidatorRef.current)) { defineAsyncProcess(undefined); setFieldState(result instanceof Error ? 'error' : 'complete'); } revealError(); }, [defineAsyncProcess, persistErrorState, revealError, setFieldState]); const startOnBlurValidatorProcess = (0, _react.useCallback)(async ({ overrideValue = null } = {}) => { if (typeof onBlurValidatorRef.current !== 'function') { return; } if ((localErrorInitiatorRef.current === 'required' || localErrorInitiatorRef.current === 'schema') && !asyncBehaviorIsEnabled && !(0, _isAsync.isAsync)(onChangeValidatorRef.current)) { return; } if ((0, _isAsync.isAsync)(onBlurValidatorRef.current)) { defineAsyncProcess('onBlurValidator'); setFieldState('validating'); } const value = transformers.current.toEvent(overrideValue !== null && overrideValue !== void 0 ? overrideValue : valueRef.current, 'onBlurValidator'); let result = (0, _isAsync.isAsync)(onBlurValidatorRef.current) ? await callValidatorFnAsync(onBlurValidatorRef.current, value) : callValidatorFnSync(onBlurValidatorRef.current, value); if (result instanceof Promise) { result = await result; } revealOnBlurValidatorResult({ result }); return { result }; }, [asyncBehaviorIsEnabled, callValidatorFnAsync, callValidatorFnSync, defineAsyncProcess, revealOnBlurValidatorResult, setFieldState]); const runOnBlurValidator = (0, _react.useCallback)(async () => { if (!onBlurValidatorRef.current) { return; } const { result } = await callOnBlurValidator(); if (String(result) !== String(validatorCacheRef.current.onBlurValidator) && revealErrorRef.current) { if (result) { revealOnBlurValidatorResult({ result }); } else { hideError(); clearErrorState(); } } validatorCacheRef.current.onBlurValidator = result || null; }, [callOnBlurValidator, clearErrorState, hideError, revealOnBlurValidatorResult]); const prioritizeContextSchema = (0, _react.useMemo)(() => { if (errorPrioritization) { const contextSchema = dataContext === null || dataContext === void 0 ? void 0 : dataContext.schema; if ((0, _index2.isZodSchema)(contextSchema)) { return (errorPrioritization === null || errorPrioritization === void 0 ? void 0 : errorPrioritization.indexOf('contextSchema')) === 0; } const schemaPath = identifier.split('/').join('/properties/'); const hasContextSchema = _index.default.has(contextSchema || {}, schemaPath); return hasContextSchema && (errorPrioritization === null || errorPrioritization === void 0 ? void 0 : errorPrioritization.indexOf('contextSchema')) === 0; } }, [dataContext === null || dataContext === void 0 ? void 0 : dataContext.schema, errorPrioritization, identifier]); const prioritizeSectionSchema = (0, _react.useMemo)(() => { return (errorPrioritization === null || errorPrioritization === void 0 ? void 0 : errorPrioritization.indexOf('sectionSchema')) === 0 && hasSectionSchema; }, [errorPrioritization, hasSectionSchema]); const validateValue = (0, _react.useCallback)(async () => { const isProcessActive = startProcess(); if (disabled) { if (isProcessActive()) { clearErrorState(); } hideError(); setFieldState(undefined); return; } const value = valueRef.current; changeEventResultRef.current = null; validatedValueRef.current = null; let initiator = null; try { const requiredError = transformers.current.validateRequired(value, { emptyValue, required, isChanged: changedRef.current, error: new _index2.FormError('Field.errorRequired') }); if (requiredError instanceof Error) { initiator = 'required'; throw requiredError; } if (error instanceof Error) { initiator = 'errorProp'; throw error; } const skipLocalSchema = prioritizeContextSchema || prioritizeSectionSchema; if (value !== undefined && !skipLocalSchema && typeof schemaValidatorRef.current === 'function') { const validationResult = schemaValidatorRef.current(value); if (validationResult !== true) { let error; if (hasZodSchema) { const zodError = validationResult; error = (0, _index2.zodErrorsToOneFormError)(zodError.issues); } else { error = (0, _index2.ajvErrorsToOneFormError)(schemaValidatorRef.current.errors, value); } initiator = 'schema'; throw error; } } if (onChangeValidatorRef.current && (changedRef.current || validateInitially || validateUnchanged)) { const { result } = await startOnChangeValidatorValidation(); if (result instanceof Error) { initiator = 'onChangeValidator'; throw result; } } if (onBlurValidatorRef.current && validateInitially && !changedRef.current) { const { result } = await startOnBlurValidatorProcess(); if (result instanceof Error) { initiator = 'onBlurValidator'; throw result; } } if (isProcessActive()) { clearErrorState(); } validatedValueRef.current = value; } catch (error) { if (isProcessActive()) { persistErrorState('weak', initiator, error); if (validateContinuously && changedRef.current) { revealError(); } } } }, [clearErrorState, disabled, emptyValue, error, hasZodSchema, hideError, persistErrorState, prioritizeContextSchema, prioritizeSectionSchema, required, revealError, setFieldState, startOnBlurValidatorProcess, startOnChangeValidatorValidation, startProcess, validateInitially, validateContinuously, validateUnchanged]); const removeError = (0, _react.useCallback)(() => { setChanged(false); hideError(); clearErrorState(); validateValue(); }, [clearErrorState, hideError, setChanged, validateValue]); const handleError = (0, _react.useCallback)(() => { if (validateContinuously || validateContinuously !== false && !hasFocusRef.current) { revealError(); } else { hideError(); } }, [validateContinuously, hideError, revealError]); const getEventArgs = (0, _react.useCallback)(({ eventName, additionalArgs, overrideValue = undefined }) => { const value = transformers.current.toEvent(overrideValue !== null && overrideValue !== void 0 ? overrideValue : valueRef.current, eventName); const args = transformers.current.provideAdditionalArgs(value, additionalArgs); const transformedValue = transformers.current.transformOut(value, args); if (typeof args !== 'undefined') { return [transformedValue, args]; } return [transformedValue]; }, []); const setHasFocus = (0, _react.useCallback)(async (hasFocus, overrideValue, localAdditionalArgs) => { const args = getEventArgs({ eventName: hasFocus ? 'onFocus' : 'onBlur', overrideValue, additionalArgs: localAdditionalArgs ? { ...additionalArgs, ...localAdditionalArgs } : additionalArgs }); if (hasFocus) { hasFocusRef.current = true; onFocus === null || onFocus === void 0 || onFocus.apply(this, args); setMountedFieldStateDataContext(identifier, { isFocused: true }); } else { hasFocusRef.current = false; onBlur === null || onBlur === void 0 || onBlur.apply(this, args); setMountedFieldStateDataContext(identifier, { isFocused: false }); if (!changedRef.current && !validateUnchanged) { return; } addToPool('onBlurValidator', async () => await startOnBlurValidatorProcess({ overrideValue }), (0, _isAsync.isAsync)(onBlurValidatorRef.current)); await runPool(() => { revealError(); forceUpdate(); }); } }, [getEventArgs, additionalArgs, onFocus, setMountedFieldStateDataContext, identifier, onBlur, validateUnchanged, addToPool, runPool, startOnBlurValidatorProcess, revealError]); const yieldAsyncProcess = (0, _react.useCallback)(async ({ name, waitFor }) => { return new Promise(resolve => { const validateProcesses = () => { const result = waitFor.some(({ processName, withStates, hasValue }) => { const hasMatchingValue = hasValue === validatedValueRef.current; const result = (typeof hasValue === 'undefined' ? false : !hasMatchingValue) || (processName ? processName === asyncProcessRef.current : true) && (withStates === null || withStates === void 0 ? void 0 : withStates.some(state => { return state === fieldStateRef.current; })); return result; }); return result; }; if (validateProcesses() === true) { asyncBufferRef.current[name] = { resolve, validateProcesses }; } else { resolve(); setFieldState('pending'); } }); }, [setFieldState]); const handleChangeEventResult = (0, _react.useCallback)(async () => { const result = changeEventResultRef.current || {}; if ('error' in result) { if (!result.error) { removeError(); } else { persistErrorState('gracefully', 'onChangeValidator', result.error); revealError(); } } if ('warning' in result) { warningRef.current = result.warning; } if ('info' in result) { infoRef.current = result.info; } if (asyncBehaviorIsEnabled) { await yieldAsyncProcess({ name: 'onSubmitContext', waitFor: [{ withStates: ['validating'] }] }); } defineAsyncProcess(undefined); if ((result === null || result === void 0 ? void 0 : result.success) === 'saved') { setFieldState('success'); } else if (result !== null && result !== void 0 && result.error) { setFieldState('error'); } else if (asyncBehaviorIsEnabled) { setFieldState('complete'); } forceUpdate(); }, [asyncBehaviorIsEnabled, defineAsyncProcess, removeError, persistErrorState, revealError, yieldAsyncProcess, setFieldState]); const setEventResult = (0, _react.useCallback)(async result => { if (result instanceof Error) { result = { error: result }; } changeEventResultRef.current = { ...changeEventResultRef.current, ...result }; await handleChangeEventResult(); }, [handleChangeEventResult]); const callOnChangeContext = (0, _react.useCallback)(async () => { if (asyncBehaviorIsEnabled && !executeOnChangeRegardlessOfError) { await yieldAsyncProcess({ name: 'onChangeContext', waitFor: [{ processName: 'onChangeValidator', withStates: ['validating', 'error'], hasValue: valueRef.current }, { processName: 'onBlurValidator', withStates: ['validating', 'error'], hasValue: valueRef.current }] }); } if (hasPath) { if ((0, _isAsync.isAsync)(onChangeContext)) { defineAsyncProcess('onChangeContext'); if (!hasError() || executeOnChangeRegardlessOfError) { await setEventResult(await (handlePathChangeDataContext === null || handlePathChangeDataContext === void 0 ? void 0 : handlePathChangeDataContext(identifier))); } else { await setEventResult(null); } } else if (onChangeContext || !asyncBehaviorIsEnabled) { setEventResult(handlePathChangeDataContext === null || handlePathChangeDataContext === void 0 ? void 0 : handlePathChangeDataContext(identifier)); } } forceUpdate(); }, [asyncBehaviorIsEnabled, executeOnChangeRegardlessOfError, hasPath, yieldAsyncProcess, onChan