informed
Version:
A lightweight framework and utility for building powerful forms in React applications
263 lines (230 loc) • 9.85 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var _rollupPluginBabelHelpers = require('../_virtual/_rollupPluginBabelHelpers.js');
var React = require('react');
var utils = require('../utils.js');
var ObjectMap = require('../ObjectMap.js');
var useFormController = require('../hooks/useFormController.js');
var useScope = require('../hooks/useScope.js');
var useConditional = require('../hooks/useConditional.js');
var debug = require('../debug.js');
var FormFields = require('./FormFields.js');
var Relevant = require('./Relevant.js');
var Scope = require('./Scope.js');
var useFieldApi = require('../hooks/useFieldApi.js');
var useUpdateEffect = require('../hooks/useUpdateEffect.js');
var ArrayField = require('./ArrayField.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
var _excluded = ["name", "schema"];
// import { useForceUpdate } from '../hooks/useForceUpdate';
var logger = debug.Debug('informed:FormField' + '\t');
var FormField = function FormField(_ref) {
var _fieldMap$componentTy;
var name = _ref.name,
schema = _ref.schema,
rest = _rollupPluginBabelHelpers.objectWithoutProperties(_ref, _excluded);
// Get the field map off the forms context
var _useFormController = useFormController.useFormController(),
fieldMap = _useFormController.fieldMap,
getOptions = _useFormController.getOptions,
emitter = _useFormController.emitter;
// Name might be scoped
var fullName = useScope.useScope(name);
// Grab the schema
var options = getOptions();
// Grap api
var fieldApi = useFieldApi.useFieldApi(name);
// For conditional props
var _useState = React.useState({}),
_useState2 = _rollupPluginBabelHelpers.slicedToArray(_useState, 2),
condProp = _useState2[0],
setCondProp = _useState2[1];
// IF schema was passed its a sub schema and we lookup via name otherwise we look at whole schema
var lookupName = schema ? name : fullName;
var lookupSchema = schema !== null && schema !== void 0 ? schema : options.schema;
// First find property from the schema via the path to that field
// Examples
// field = "name" ---> properties.name
// field = "brother.name" ---> properties.brother.properties.name
// field = "brother.siblings[1].friend.name" ---> properties.brother.properties.siblings.items.properties.friend.properties.name
var path = utils.getSchemaPathFromJsonPath(lookupName);
var property = ObjectMap.ObjectMap.get(lookupSchema, path);
// console.log(
// 'Lookup Name:',
// lookupName,
// '\nSchema Path:',
// path,
// '\nProperty:',
// lookupSchema
// );
// If property was not found try to find it in conditions
var condition;
if (!property) {
if (lookupSchema.allOf) {
lookupSchema.allOf.forEach(function (item) {
if (item["if"]) {
property = ObjectMap.ObjectMap.get(item.then, path);
condition = item["if"];
}
});
}
// If property was still not found return null
if (!property) {
return null;
}
}
// Next compute the field from property
var schemaField = React.useMemo(function () {
return utils.computeFieldFromProperty(name, property);
}, [name]);
var schemaProps = schemaField.props,
type = schemaField.type,
properties = schemaField.properties,
items = schemaField.items,
componentType = schemaField.componentType,
uiBefore = schemaField.uiBefore,
uiAfter = schemaField.uiAfter;
// Register for events on our field
React.useEffect(function () {
var updater = function updater(target, property) {
// Example
// target="foo"
// property =
// {
// oneOf: [
// { const: '', title: '- Select -' },
// { const: 'modelS', title: 'Model S' },
// { const: 'modelX', title: 'Model X' },
// { const: 'model3', title: 'Model 3' }
// ]
// }
if (target === name) {
logger("Updating field props for ".concat(target), utils.computeFieldFromProperty(name, property));
setCondProp(utils.computeFieldFromProperty(name, property));
}
};
var remover = function remover(target) {
if (target === name) {
setCondProp({});
}
};
emitter.on('update-combine', updater);
emitter.on('update-remove', remover);
return function () {
emitter.removeListener('update-combine', updater);
emitter.removeListener('update-remove', remover);
};
}, [name]);
var hookProps = useConditional.useConditional({
name: schemaProps.name,
evaluate: schemaProps.evaluate,
evaluateWhen: schemaProps.evaluateWhen,
dependsOn: schemaProps.dependsOn
});
// Combine any conditional props with the schema props
var props = React.useMemo(function () {
// Pull new props off of cond property
var condProps = condProp.props;
// Lay those on top of existing ones
var newSchemaProps = utils.sanitize(schemaProps);
var newCondProps = utils.sanitize(condProps);
var newHookProps = utils.sanitize(hookProps);
// Temp fix
if (schemaProps !== null && schemaProps !== void 0 && schemaProps.required || newCondProps !== null && newCondProps !== void 0 && newCondProps.required || newHookProps !== null && newHookProps !== void 0 && newHookProps.required) {
rest.required = (schemaProps === null || schemaProps === void 0 ? void 0 : schemaProps.required) || (newCondProps === null || newCondProps === void 0 ? void 0 : newCondProps.required) || (newHookProps === null || newHookProps === void 0 ? void 0 : newHookProps.required);
}
var newProps = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, newSchemaProps), newCondProps), newHookProps), rest);
logger("Schema Props for ".concat(name), newSchemaProps);
logger("Cond Props for ".concat(name), newCondProps);
logger("Hook Props for ".concat(name), newHookProps);
logger("New Props for ".concat(name), newProps);
return newProps;
}, [condProp, hookProps]);
useUpdateEffect.useUpdateEffect(function () {
if (props.options) {
logger('options changed', props.options);
fieldApi.reset();
}
}, [props.options]);
// Component is either on field map or components list passed in
var Component = (_fieldMap$componentTy = fieldMap[componentType]) !== null && _fieldMap$componentTy !== void 0 ? _fieldMap$componentTy : options.components ? options.components[componentType] : null;
// Maybe its with options
// Example adapter:
// withOptions: {
// array: CheckboxGroup,
// },
if (schemaProps.options && fieldMap.withOptions && !items) {
Component = fieldMap.withOptions[componentType] || Component;
// console.log('HERE!!!!!', componentType, fieldMap.withOptions);
}
// console.log('WTF', schemaField);
logger('Rendering Field', name, schemaField);
// Scope for nested
if (!Component && type === 'object' && properties) {
return /*#__PURE__*/React__default["default"].createElement(Scope.Scope, {
scope: name
}, /*#__PURE__*/React__default["default"].createElement(FormFields.FormFields, {
schema: schemaField
}));
}
// Just component
if (Component && type === 'object' && properties) {
return /*#__PURE__*/React__default["default"].createElement(Scope.Scope, {
scope: name
}, /*#__PURE__*/React__default["default"].createElement(Component, props, /*#__PURE__*/React__default["default"].createElement(FormFields.FormFields, {
schema: schemaField
})));
}
// Array field for array ( if none was provided use our default )
if (!Component && type === 'array' && items) {
return /*#__PURE__*/React__default["default"].createElement(ArrayField.ArrayField, _rollupPluginBabelHelpers["extends"]({
name: name,
items: items,
uiBefore: uiBefore,
uiAfter: uiAfter
}, props));
}
// User created custom array field
if (Component && componentType === 'array' && items && type === 'array') {
return /*#__PURE__*/React__default["default"].createElement(Component, _rollupPluginBabelHelpers["extends"]({
name: name,
items: items,
uiBefore: uiBefore,
uiAfter: uiAfter
}, props));
}
// If no component return null ( dont render )
if (!Component) {
return null;
}
if (condition) {
var _condition = condition,
conditions = _condition.properties;
var when = function when(_ref2) {
var formApi = _ref2.formApi,
scope = _ref2.scope;
// Example key "married, Example condition: "{ const: 'yes' }"
return Object.entries(conditions).every(function (_ref3) {
var _ref4 = _rollupPluginBabelHelpers.slicedToArray(_ref3, 2),
propertyName = _ref4[0],
condition = _ref4[1];
return utils.checkCondition(condition, formApi.getValue(scope ? "".concat(scope, ".").concat(propertyName) : propertyName));
});
};
var Comp = function Comp() {
return /*#__PURE__*/React__default["default"].createElement(Relevant.Relevant, {
when: when
}, /*#__PURE__*/React__default["default"].createElement(Component, _rollupPluginBabelHelpers["extends"]({
name: name
}, props)));
};
// console.log('WTF', Component);
return /*#__PURE__*/React__default["default"].createElement(Comp, null);
}
// Note we DONT pass in scoped name here because useField is already scoped
return /*#__PURE__*/React__default["default"].createElement(Component, _rollupPluginBabelHelpers["extends"]({
name: name
}, props));
};
exports.FormField = FormField;