@base-ui-components/react
Version:
Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.
134 lines (133 loc) • 5.28 kB
JavaScript
;
'use client';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useFieldControlValidation = useFieldControlValidation;
var React = _interopRequireWildcard(require("react"));
var _useEventCallback = require("../../utils/useEventCallback");
var _FieldRootContext = require("../root/FieldRootContext");
var _mergeReactProps = require("../../utils/mergeReactProps");
var _constants = require("../utils/constants");
var _FormContext = require("../../form/FormContext");
var _getCombinedFieldValidityData = require("../utils/getCombinedFieldValidityData");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const validityKeys = Object.keys(_constants.DEFAULT_VALIDITY_STATE);
function useFieldControlValidation() {
const {
setValidityData,
validate,
messageIds,
validityData,
validationMode,
validationDebounceTime,
invalid,
markedDirtyRef,
controlId,
state
} = (0, _FieldRootContext.useFieldRootContext)();
const {
formRef
} = (0, _FormContext.useFormContext)();
const timeoutRef = React.useRef(-1);
const inputRef = React.useRef(null);
React.useEffect(() => {
return () => {
window.clearTimeout(timeoutRef.current);
};
}, []);
const commitValidation = (0, _useEventCallback.useEventCallback)(async value => {
const element = inputRef.current;
if (!element) {
return;
}
function getState(el) {
return validityKeys.reduce((acc, key) => {
acc[key] = el.validity[key];
if (!el.validity.customError && !markedDirtyRef.current) {
acc[key] = key === 'valid';
}
return acc;
}, {});
}
window.clearTimeout(timeoutRef.current);
const resultOrPromise = validate(value);
let result = null;
if (typeof resultOrPromise === 'object' && resultOrPromise !== null && 'then' in resultOrPromise) {
result = await resultOrPromise;
} else {
result = resultOrPromise;
}
let errorMessage = '';
if (result !== null) {
errorMessage = Array.isArray(result) ? result.join('\n') : result;
}
element.setCustomValidity(errorMessage);
const nextState = getState(element);
let validationErrors = [];
if (Array.isArray(result)) {
validationErrors = result;
} else if (result) {
validationErrors = [result];
} else if (element.validationMessage) {
validationErrors = [element.validationMessage];
}
const nextValidityData = {
value,
state: nextState,
error: Array.isArray(result) ? result[0] : result ?? element.validationMessage,
errors: validationErrors,
initialValue: validityData.initialValue
};
if (controlId) {
const currentFieldData = formRef.current.fields.get(controlId);
if (currentFieldData) {
formRef.current.fields.set(controlId, {
...currentFieldData,
...(0, _getCombinedFieldValidityData.getCombinedFieldValidityData)(nextValidityData, invalid)
});
}
}
setValidityData(nextValidityData);
});
const getValidationProps = React.useCallback((externalProps = {}) => (0, _mergeReactProps.mergeReactProps)(externalProps, {
...(messageIds.length && {
'aria-describedby': messageIds.join(' ')
}),
...(state.valid === false && {
'aria-invalid': true
})
}), [messageIds, state.valid]);
const getInputValidationProps = React.useCallback((externalProps = {}) => (0, _mergeReactProps.mergeReactProps)(getValidationProps(externalProps), {
onChange(event) {
// Workaround for https://github.com/facebook/react/issues/9023
if (event.nativeEvent.defaultPrevented) {
return;
}
if (invalid || validationMode !== 'onChange') {
return;
}
const element = event.currentTarget;
if (element.value === '') {
// Ignore the debounce time for empty values.
commitValidation(element.value);
return;
}
window.clearTimeout(timeoutRef.current);
if (validationDebounceTime) {
timeoutRef.current = window.setTimeout(() => {
commitValidation(element.value);
}, validationDebounceTime);
} else {
commitValidation(element.value);
}
}
}), [getValidationProps, invalid, validationMode, validationDebounceTime, commitValidation]);
return React.useMemo(() => ({
getValidationProps,
getInputValidationProps,
inputRef,
commitValidation
}), [getValidationProps, getInputValidationProps, commitValidation]);
}