@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
1,174 lines (1,173 loc) • 77.5 kB
JavaScript
"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