@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
JavaScript
;
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;