@data-driven-forms/react-form-renderer
Version:
React Form Renderer. Data Driven Forms converts JSON form definitions into fully functional React forms.
249 lines (224 loc) • 11.1 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _typeof from "@babel/runtime/helpers/typeof";
var _excluded = ["actionMapper", "children", "clearedValue", "clearOnUnmount", "componentMapper", "conditionMapper", "decorators", "FormTemplate", "FormTemplateProps", "mutators", "onCancel", "onError", "onReset", "onSubmit", "schema", "schemaValidatorMapper", "subscription", "validatorMapper", "initialValues"],
_excluded2 = ["reset", "mutators", "getState", "submit"];
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
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) { _defineProperty(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; }
import arrayMutators from 'final-form-arrays';
import createFocusDecorator from 'final-form-focus';
import React, { useCallback, useMemo, useRef, useState, cloneElement } from 'react';
import defaultSchemaValidator from '../default-schema-validator';
import defaultValidatorMapper from '../validator-mapper';
import Form from '../form';
import RendererContext from '../renderer-context';
import renderForm from './render-form';
import SchemaErrorComponent from './schema-error-component';
var isFunc = function isFunc(fn) {
return typeof fn === 'function';
};
var renderChildren = function renderChildren(children, props) {
if (isFunc(children)) {
return children(props);
}
var childElement = children;
if (Array.isArray(children)) {
/**
* Only permit one child element
*/
if (children.length !== 1) {
throw new Error('FormRenderer expects only one child element!');
}
childElement = children[0];
}
if (_typeof(childElement) === 'object') {
/**
* Clone react element, pass form fields and schema as props, but override them with child props if present
*/
return /*#__PURE__*/cloneElement(children, _objectSpread(_objectSpread({}, props), childElement.props));
}
throw new Error("Invalid children prop! Expected one of [null, Function, object], got ".concat(_typeof(children)));
};
var FormRenderer = function FormRenderer(_ref) {
var actionMapper = _ref.actionMapper,
children = _ref.children,
clearedValue = _ref.clearedValue,
_ref$clearOnUnmount = _ref.clearOnUnmount,
clearOnUnmount = _ref$clearOnUnmount === void 0 ? false : _ref$clearOnUnmount,
componentMapper = _ref.componentMapper,
_ref$conditionMapper = _ref.conditionMapper,
conditionMapper = _ref$conditionMapper === void 0 ? {} : _ref$conditionMapper,
decorators = _ref.decorators,
FormTemplate = _ref.FormTemplate,
FormTemplateProps = _ref.FormTemplateProps,
mutators = _ref.mutators,
onCancel = _ref.onCancel,
onError = _ref.onError,
onReset = _ref.onReset,
onSubmit = _ref.onSubmit,
schema = _ref.schema,
schemaValidatorMapper = _ref.schemaValidatorMapper,
subscription = _ref.subscription,
validatorMapper = _ref.validatorMapper,
_ref$initialValues = _ref.initialValues,
initialValues = _ref$initialValues === void 0 ? {} : _ref$initialValues,
props = _objectWithoutProperties(_ref, _excluded);
var _useState = useState([]),
_useState2 = _slicedToArray(_useState, 2),
fileInputs = _useState2[0],
setFileInputs = _useState2[1];
var formFields = useMemo(function () {
return renderForm(schema.fields);
}, [schema]);
var registeredFields = useRef({});
var focusDecorator = useRef(createFocusDecorator());
var validatorMapperMerged = useMemo(function () {
return _objectSpread(_objectSpread({}, defaultValidatorMapper), validatorMapper);
}, [validatorMapper]);
var mutatorsMerged = useMemo(function () {
return _objectSpread(_objectSpread({}, arrayMutators), mutators);
}, [mutators]);
var decoratorsMerged = useMemo(function () {
return [focusDecorator.current].concat(_toConsumableArray(Array.isArray(decorators) ? decorators : []));
}, [decorators]);
var handleSubmitCallback = useCallback(function (values, formApi) {
for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
args[_key - 2] = arguments[_key];
}
return !isFunc(onSubmit) ? undefined : onSubmit.apply(void 0, [values, _objectSpread(_objectSpread({}, formApi), {}, {
fileInputs: fileInputs
})].concat(args));
}, [onSubmit, fileInputs]);
var handleCancelCallback = useCallback(function (getState) {
return function () {
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
return onCancel.apply(void 0, [getState().values].concat(args));
};
}, [onCancel]);
var handleResetCallback = useCallback(function (reset) {
return function () {
reset();
return !isFunc(onReset) ? void 0 : onReset.apply(void 0, arguments);
};
}, [onReset]);
var handleErrorCallback = useCallback(function () {
var _console;
// eslint-disable-next-line no-console
(_console = console).error.apply(_console, arguments);
return !isFunc(onError) ? void 0 : onError.apply(void 0, arguments);
}, [onError]);
var registerInputFile = useCallback(function (name) {
setFileInputs(function (prevFiles) {
return [].concat(_toConsumableArray(prevFiles), [name]);
});
}, []);
var unRegisterInputFile = useCallback(function (name) {
setFileInputs(function (prevFiles) {
return _toConsumableArray(prevFiles.splice(prevFiles.indexOf(name)));
});
}, []);
var setRegisteredFields = useCallback(function (fn) {
return registeredFields.current = fn(_objectSpread({}, registeredFields.current));
}, []);
var internalRegisterField = useCallback(function (name) {
setRegisteredFields(function (prev) {
return prev[name] ? _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, name, prev[name] + 1)) : _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, name, 1));
});
}, []);
var internalUnRegisterField = useCallback(function (name) {
setRegisteredFields(function (_ref2) {
var currentField = _ref2[name],
prev = _objectWithoutProperties(_ref2, [name].map(_toPropertyKey));
return currentField && currentField > 1 ? _objectSpread(_defineProperty({}, name, currentField - 1), prev) : prev;
});
}, []);
var internalGetRegisteredFields = useCallback(function () {
var fields = registeredFields.current;
return Object.entries(fields).reduce(function (acc, _ref3) {
var _ref4 = _slicedToArray(_ref3, 2),
name = _ref4[0],
value = _ref4[1];
return value > 0 ? [].concat(_toConsumableArray(acc), [name]) : acc;
}, []);
}, []);
try {
var validatorTypes = Object.keys(validatorMapperMerged);
var actionTypes = actionMapper ? Object.keys(actionMapper) : [];
defaultSchemaValidator(schema, componentMapper, validatorTypes, actionTypes, schemaValidatorMapper);
} catch (error) {
handleErrorCallback('schema-error', error);
return /*#__PURE__*/React.createElement(SchemaErrorComponent, {
name: error.name,
message: error.message
});
}
return /*#__PURE__*/React.createElement(Form, _extends({
onSubmit: handleSubmitCallback,
mutators: mutatorsMerged,
decorators: decoratorsMerged,
subscription: _objectSpread({
pristine: true,
submitting: true,
valid: true
}, subscription),
render: function render(_ref5) {
var handleSubmit = _ref5.handleSubmit,
pristine = _ref5.pristine,
valid = _ref5.valid,
_ref5$form = _ref5.form,
reset = _ref5$form.reset,
mutators = _ref5$form.mutators,
getState = _ref5$form.getState,
submit = _ref5$form.submit,
form = _objectWithoutProperties(_ref5$form, _excluded2);
return /*#__PURE__*/React.createElement(RendererContext.Provider, {
value: {
componentMapper: componentMapper,
validatorMapper: validatorMapperMerged,
actionMapper: actionMapper,
conditionMapper: conditionMapper,
formOptions: _objectSpread(_objectSpread(_objectSpread({
registerInputFile: registerInputFile,
unRegisterInputFile: unRegisterInputFile,
pristine: pristine,
onSubmit: onSubmit,
onCancel: isFunc(onCancel) ? handleCancelCallback(getState) : undefined,
onReset: handleResetCallback(reset),
onError: handleErrorCallback,
getState: getState,
valid: valid,
clearedValue: clearedValue,
submit: submit,
handleSubmit: handleSubmit,
reset: reset,
clearOnUnmount: clearOnUnmount,
renderForm: renderForm,
internalRegisterField: internalRegisterField,
internalUnRegisterField: internalUnRegisterField
}, mutators), form), {}, {
ffGetRegisteredFields: form.getRegisteredFields,
getRegisteredFields: internalGetRegisteredFields,
initialValues: initialValues,
schema: schema
})
}
}, FormTemplate && /*#__PURE__*/React.createElement(FormTemplate, _extends({
formFields: formFields,
schema: schema
}, FormTemplateProps)), children && renderChildren(children, {
formFields: formFields,
schema: schema
}));
}
}, props, {
initialValues: initialValues
}));
};
export default FormRenderer;