UNPKG

@data-driven-forms/react-form-renderer

Version:

React Form Renderer. Data Driven Forms converts JSON form definitions into fully functional React forms.

362 lines (295 loc) 13.8 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _react = require("react"); var _reactFinalForm = require("react-final-form"); var _enhancedOnChange = _interopRequireDefault(require("./enhanced-on-change")); var _rendererContext = _interopRequireDefault(require("../renderer-context")); var _convertInitialValue = _interopRequireDefault(require("./convert-initial-value")); var _assignSpecialType = _interopRequireDefault(require("./assign-special-type")); var _componentTypes = _interopRequireDefault(require("../component-types")); var _validatorHelpers = require("./validator-helpers"); var _composeValidators = _interopRequireDefault(require("../compose-validators")); var _isEqual = _interopRequireDefault(require("lodash/isEqual")); var _get = _interopRequireDefault(require("lodash/get")); var _excluded = ["value", "blur", "change", "focus"], _excluded2 = ["name", "resolveProps", "skipRegistration"], _excluded3 = ["initializeOnMount", "component", "render", "validate", "useWarnings", "clearOnUnmount", "dataType", "FieldProps"], _excluded4 = ["initialValue", "clearedValue"]; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } var calculateInitialValue = function calculateInitialValue(props) { if (Object.prototype.hasOwnProperty.call(props, 'initialValue') && props.dataType) { return (0, _convertInitialValue["default"])(props.initialValue, props.dataType); } }; var calculateArrayValidator = function calculateArrayValidator(props, validate, component, validatorMapper) { if ((validate || props.dataType) && _componentTypes["default"].FIELD_ARRAY === component) { return (0, _validatorHelpers.prepareArrayValidator)((0, _validatorHelpers.getValidate)(validate, props.dataType, validatorMapper)); } }; var calculateValidate = function calculateValidate(props, validate, component, validatorMapper, setWarning, useWarnings) { if ((validate || props.dataType) && _componentTypes["default"].FIELD_ARRAY !== component) { var validateFn = (0, _composeValidators["default"])((0, _validatorHelpers.getValidate)(validate, props.dataType, validatorMapper)); if (useWarnings) { return /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() { var result, _args = arguments; return _regenerator["default"].wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: setWarning(undefined); _context.next = 3; return validateFn.apply(void 0, _args); case 3: result = _context.sent; if (!((result === null || result === void 0 ? void 0 : result.type) === 'warning')) { _context.next = 7; break; } setWarning(result.error); return _context.abrupt("return"); case 7: return _context.abrupt("return", result); case 8: case "end": return _context.stop(); } } }, _callee); })); } return validateFn; } }; var init = function init(_ref2) { var props = _ref2.props, validate = _ref2.validate, component = _ref2.component, validatorMapper = _ref2.validatorMapper, setWarning = _ref2.setWarning, useWarnings = _ref2.useWarnings; return { initialValue: calculateInitialValue(props), arrayValidator: calculateArrayValidator(props, validate, component, validatorMapper), validate: calculateValidate(props, validate, component, validatorMapper, setWarning, useWarnings), type: (0, _assignSpecialType["default"])(component) }; }; var reducer = function reducer(state, _ref3) { var type = _ref3.type, specialType = _ref3.specialType, validate = _ref3.validate, arrayValidator = _ref3.arrayValidator, initialValue = _ref3.initialValue; switch (type) { case 'setType': return _objectSpread(_objectSpread({}, state), {}, { type: specialType }); case 'setValidators': return _objectSpread(_objectSpread({}, state), {}, { validate: validate, arrayValidator: arrayValidator }); case 'setInitialValue': return _objectSpread(_objectSpread({}, state), {}, { initialValue: initialValue }); default: return state; } }; var createFieldProps = function createFieldProps(name, formOptions) { var _ref4 = formOptions.getFieldState(name) || {}, value = _ref4.value, blur = _ref4.blur, change = _ref4.change, focus = _ref4.focus, meta = (0, _objectWithoutProperties2["default"])(_ref4, _excluded); return { meta: meta, input: { name: name, value: value } }; }; var useFieldApi = function useFieldApi(_ref5) { var name = _ref5.name, resolveProps = _ref5.resolveProps, _ref5$skipRegistratio = _ref5.skipRegistration, skipRegistration = _ref5$skipRegistratio === void 0 ? false : _ref5$skipRegistratio, props = (0, _objectWithoutProperties2["default"])(_ref5, _excluded2); var _useContext = (0, _react.useContext)(_rendererContext["default"]), validatorMapper = _useContext.validatorMapper, formOptions = _useContext.formOptions; var _useState = (0, _react.useState)(), _useState2 = (0, _slicedToArray2["default"])(_useState, 2), warning = _useState2[0], setWarning = _useState2[1]; // if there is field initial value, we have to check form initialValues // initialValues should have higher priority var formInitialValue = Object.prototype.hasOwnProperty.call(props, 'initialValue') ? (0, _get["default"])(formOptions.initialValues, name) : undefined; var resolvedProps = resolveProps ? resolveProps(props, createFieldProps(name, formOptions), formOptions) || {} : {}; var combinedProps = _objectSpread(_objectSpread({}, props), resolvedProps); var initializeOnMount = combinedProps.initializeOnMount, component = combinedProps.component, render = combinedProps.render, validate = combinedProps.validate, useWarnings = combinedProps.useWarnings, clearOnUnmount = combinedProps.clearOnUnmount, dataType = combinedProps.dataType, FieldProps = combinedProps.FieldProps, rest = (0, _objectWithoutProperties2["default"])(combinedProps, _excluded3); var _useReducer = (0, _react.useReducer)(reducer, { props: combinedProps, validate: validate, component: component, validatorMapper: validatorMapper, setWarning: setWarning, useWarnings: useWarnings }, init), _useReducer2 = (0, _slicedToArray2["default"])(_useReducer, 2), _useReducer2$ = _useReducer2[0], type = _useReducer2$.type, initialValue = _useReducer2$.initialValue, stateValidate = _useReducer2$.validate, arrayValidator = _useReducer2$.arrayValidator, dispatch = _useReducer2[1]; var mounted = (0, _react.useRef)(false); var enhancedProps = _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({ dataType: dataType, type: combinedProps.type }, Object.prototype.hasOwnProperty.call(combinedProps, 'initialValue') ? { initialValue: combinedProps.initialValue } : {}), Object.prototype.hasOwnProperty.call(combinedProps, 'value') ? { value: combinedProps.value } : {}), FieldProps), type ? { type: type } : {}), initialValue ? { initialValue: initialValue } : {}), stateValidate ? { validate: stateValidate } : {}); var field = (0, _reactFinalForm.useField)(name, _objectSpread(_objectSpread({}, enhancedProps), typeof formInitialValue !== 'undefined' && { initialValue: formInitialValue })); /** Reinitilize type */ (0, _react.useEffect)(function () { if (mounted.current) { var specialType = (0, _assignSpecialType["default"])(component); if (specialType !== type) { dispatch({ type: 'setType', specialType: specialType }); } } }, [component]); /** Reinitilize array validator/validate */ (0, _react.useEffect)(function () { if (mounted.current) { dispatch({ type: 'setValidators', validate: calculateValidate(enhancedProps, validate, component, validatorMapper, setWarning, useWarnings), arrayValidator: calculateArrayValidator(enhancedProps, validate, component, validatorMapper) }); } /** * We have to stringify the validate array in order to preven infinite looping when validate was passed directly to useFieldApi * const x = useFieldApu({name: 'foo', validate: [{type: 'bar'}]}) will trigger infinite looping witouth the serialize. * Using stringify is acceptable here since the array is usually very small. * If we notice performance hit, we can implement custom hook with a deep equal functionality. */ }, [validate ? JSON.stringify(validate) : false, component, dataType]); /** Re-convert initialValue when changed */ (0, _react.useEffect)(function () { if (mounted.current) { var newInitialValue = calculateInitialValue(enhancedProps); if (!(0, _isEqual["default"])(initialValue, newInitialValue)) { dispatch({ type: 'setInitialValue', initialValue: newInitialValue }); } } }, [enhancedProps.initialValue, dataType]); (0, _react.useEffect)(function () { /** * Re initialize field when mounted to the Form * This affects conditional fields */ if (initializeOnMount) { var value = Object.prototype.hasOwnProperty.call(enhancedProps, 'initialValue') ? enhancedProps.initialValue : formOptions.getFieldState(name).initial; field.input.onChange(value); } }, [initializeOnMount, enhancedProps.initialValue, field.meta.initial, dataType]); /** * Prepare deleted value of field */ var fieldClearedValue = Object.prototype.hasOwnProperty.call(rest, 'clearedValue') ? rest.clearedValue : formOptions.clearedValue; (0, _react.useEffect)(function () { if (!skipRegistration) { formOptions.internalRegisterField(name); } mounted.current = true; if (field.input.type === 'file') { formOptions.registerInputFile(field.input.name); } return function () { mounted.current = false; /** * Delete the value from form state when field is inmounted */ if ((formOptions.clearOnUnmount || clearOnUnmount) && clearOnUnmount !== false) { field.input.onChange(fieldClearedValue); } if (field.input.type === 'file') { formOptions.unRegisterInputFile(field.input.name); } if (!skipRegistration) { formOptions.internalUnRegisterField(name); } }; }, // eslint-disable-next-line react-hooks/exhaustive-deps []); var _initialValue = rest.initialValue, clearedValue = rest.clearedValue, cleanProps = (0, _objectWithoutProperties2["default"])(rest, _excluded4); /** * construct component props necessary that would live in field provider */ return _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, cleanProps), field), arrayValidator && { arrayValidator: arrayValidator }), useWarnings && { meta: _objectSpread(_objectSpread({}, field.meta), {}, { warning: warning }) }), {}, { input: _objectSpread(_objectSpread({}, field.input), {}, { value: field.input.type === 'file' && (0, _typeof2["default"])(field.input.value) === 'object' ? field.input.value.inputValue : field.input.value, onChange: function onChange() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _enhancedOnChange["default"].apply(void 0, [_objectSpread(_objectSpread({}, field.meta), {}, { dataType: dataType, onChange: field.input.onChange, clearedValue: fieldClearedValue })].concat(args)); } }) }); }; var _default = useFieldApi; exports["default"] = _default;