@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
203 lines (202 loc) • 6.49 kB
JavaScript
;
"use client";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = useFieldAsync;
var _react = require("react");
var _isAsync = require("../../../shared/helpers/isAsync.js");
function useFieldAsync({
onChange,
onChangeContext,
valueRef,
forceUpdate,
persistErrorState,
revealError,
setFieldState,
hasError,
warningRef,
infoRef,
fieldStateRef,
removeErrorRef,
hasPath,
identifier,
executeOnChangeRegardlessOfError,
handlePathChangeDataContext
}) {
const asyncBehaviorIsEnabled = (0, _react.useMemo)(() => {
return (0, _isAsync.isAsync)(onChange) || (0, _isAsync.isAsync)(onChangeContext);
}, [onChangeContext, onChange]);
const validatedValueRef = (0, _react.useRef)(undefined);
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 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, fieldStateRef]);
const handleChangeEventResult = (0, _react.useCallback)(async () => {
const result = changeEventResultRef.current || {};
if ('error' in result) {
if (!result.error) {
removeErrorRef.current();
} 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, removeErrorRef, persistErrorState, revealError, yieldAsyncProcess, setFieldState, warningRef, infoRef, forceUpdate]);
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, onChangeContext, defineAsyncProcess, hasError, setEventResult, handlePathChangeDataContext, identifier, forceUpdate, valueRef]);
return {
asyncBehaviorIsEnabled,
defineAsyncProcess,
addToPool,
runPool,
yieldAsyncProcess,
handleChangeEventResult,
setEventResult,
callOnChangeContext,
asyncProcessRef,
validatedValueRef,
changeEventResultRef
};
}
//# sourceMappingURL=useFieldAsync.js.map