"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.useFormElement = exports.useCompositeFormElement = exports.isFormElementForType = exports.getCombinedValidity = void 0; var _fastDeepEqual = _interopRequireDefault(require("fast-deep-equal")); var _react = require("react"); var _useAsync = _interopRequireDefault(require("react-use/lib/useAsync")); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ const unsetValue = Symbol('unset form value'); const useFormElement = ({ initialValue, validate }) => { const [changedValue, setChangedValue] = (0, _react.useState)(unsetValue); const value = changedValue !== unsetValue ? changedValue : initialValue; const updateValue = (0, _react.useCallback)(updater => setChangedValue(previousValue => previousValue === unsetValue ? updater(initialValue) : updater(previousValue)), [initialValue]); const resetValue = (0, _react.useCallback)(() => setChangedValue(unsetValue), []); const isDirty = (0, _react.useMemo)(() => !(0, _fastDeepEqual.default)(value, initialValue), [value, initialValue]); const validity = useValidity(value, validate); return (0, _react.useMemo)(() => ({ initialValue, isDirty, resetValue, updateValue, validity, value }), [initialValue, isDirty, resetValue, updateValue, validity, value]); }; exports.useFormElement = useFormElement; const useCompositeFormElement = ({ childFormElements, validate }) => { const childFormElementEntries = (0, _react.useMemo)(() => Object.entries(childFormElements), // eslint-disable-next-line react-hooks/exhaustive-deps Object.entries(childFormElements).flat()); const value = (0, _react.useMemo)(() => childFormElementEntries.reduce((accumulatedFormValues, [formElementName, formElement]) => ({ ...accumulatedFormValues, [formElementName]: formElement.value }), {}), [childFormElementEntries]); const updateValue = (0, _react.useCallback)(updater => { const newValues = updater(value); childFormElementEntries.forEach(([formElementName, formElement]) => formElement.updateValue(() => newValues[formElementName])); }, [childFormElementEntries, value]); const isDirty = (0, _react.useMemo)(() => childFormElementEntries.some(([, formElement]) => formElement.isDirty), [childFormElementEntries]); const formValidity = useValidity(value, validate); const childFormElementsValidity = (0, _react.useMemo)(() => { if (childFormElementEntries.some(([, formElement]) => formElement.validity.validity === 'invalid')) { return { validity: 'invalid', reasons: [{ type: 'child' }] }; } else if (childFormElementEntries.some(([, formElement]) => formElement.validity.validity === 'pending')) { return { validity: 'pending' }; } else { return { validity: 'valid' }; } }, [childFormElementEntries]); const validity = (0, _react.useMemo)(() => getCombinedValidity(formValidity, childFormElementsValidity), [formValidity, childFormElementsValidity]); const resetValue = (0, _react.useCallback)(() => { childFormElementEntries.forEach(([, formElement]) => formElement.resetValue()); }, [childFormElementEntries]); const initialValue = (0, _react.useMemo)(() => childFormElementEntries.reduce((accumulatedFormValues, [formElementName, formElement]) => ({ ...accumulatedFormValues, [formElementName]: formElement.initialValue }), {}), [childFormElementEntries]); return (0, _react.useMemo)(() => ({ childFormElements, initialValue, isDirty, resetValue, updateValue, validity, value }), [childFormElements, initialValue, isDirty, resetValue, updateValue, validity, value]); }; exports.useCompositeFormElement = useCompositeFormElement; const useValidity = (value, validate) => { const validationState = (0, _useAsync.default)(() => { var _validate; return (_validate = validate === null || validate === void 0 ? void 0 : validate(value)) !== null && _validate !== void 0 ? _validate : Promise.resolve([]); }, [validate, value]); const validity = (0, _react.useMemo)(() => { if (validationState.loading) { return { validity: 'pending' }; } else if (validationState.error != null) { return { validity: 'invalid', reasons: [{ type: 'generic', message: `${validationState.error}` }] }; } else if (validationState.value && validationState.value.length > 0) { return { validity: 'invalid', reasons: validationState.value }; } else { return { validity: 'valid' }; } }, [validationState.error, validationState.loading, validationState.value]); return validity; }; const getCombinedValidity = (first, second) => { if (first.validity === 'invalid' || second.validity === 'invalid') { return { validity: 'invalid', reasons: [...(first.validity === 'invalid' ? first.reasons : []), ...(second.validity === 'invalid' ? second.reasons : [])] }; } else if (first.validity === 'pending' || second.validity === 'pending') { return { validity: 'pending' }; } else { return { validity: 'valid' }; } }; exports.getCombinedValidity = getCombinedValidity; const isFormElementForType = isValue => formElement => isValue(formElement.value); exports.isFormElementForType = isFormElementForType;