UNPKG

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