@lyra/form-builder
Version:
Lyra form builder
282 lines (228 loc) • 8.22 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _FormBuilderPropTypes = require('../../FormBuilderPropTypes');
var _FormBuilderPropTypes2 = _interopRequireDefault(_FormBuilderPropTypes);
var _Field = require('./Field');
var _Field2 = _interopRequireDefault(_Field);
var _default = require('part:@lyra/components/fieldsets/default');
var _default2 = _interopRequireDefault(_default);
var _PatchEvent = require('../../PatchEvent');
var _PatchEvent2 = _interopRequireDefault(_PatchEvent);
var _isEmpty = require('../../utils/isEmpty');
var _isEmpty2 = _interopRequireDefault(_isEmpty);
var _UnknownFields = require('./UnknownFields');
var _UnknownFields2 = _interopRequireDefault(_UnknownFields);
var _Field3 = require('./styles/Field.css');
var _Field4 = _interopRequireDefault(_Field3);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function getCollapsedWithDefaults(options = {}, level) {
// todo: warn on "collapsable" and deprecate collapsible in favor of just "collapsed"
// --> relevant: https://github.com/lyra-io/lyra/issues/537
if (options.collapsible === true || options.collapsable === true) {
// collapsible explicit set to true
return {
collapsible: true,
collapsed: options.collapsed !== false
};
} else if (options.collapsible === false || options.collapsable === false) {
// collapsible explicit set to false
return {
// hard limit to avoid infinite recursion
collapsible: level > 9,
collapsed: level > 9
};
}
// default
return {
collapsible: level > 2,
collapsed: level > 2
};
}
class ObjectInput extends _react2.default.PureComponent {
constructor(...args) {
var _temp;
return _temp = super(...args), this.handleFieldChange = (fieldEvent /*: PatchEvent*/, field) => {
var _props = this.props;
const onChange = _props.onChange,
type = _props.type,
value = _props.value,
isRoot = _props.isRoot;
let event = fieldEvent.prefixAll(field.name);
if (!isRoot) {
event = event.prepend((0, _PatchEvent.setIfMissing)(type.name === 'object' ? {} : { _type: type.name }));
if (value) {
const valueTypeName = value && value._type;
const schemaTypeName = type.name;
// eslint-disable-next-line max-depth
if (valueTypeName && schemaTypeName === 'object') {
// The value has a _type key, but the type name from schema is 'object',
// but _type: 'object' is implicit so we should fix it by removing it
event = event.prepend((0, _PatchEvent.unset)(['_type']));
} else if (schemaTypeName !== 'object' && valueTypeName !== schemaTypeName) {
// There's a mismatch between schema type and the value _type
// fix it by setting _type to type name defined in schema
event = event.prepend((0, _PatchEvent.set)(schemaTypeName, ['_type']));
}
}
}
onChange(event);
}, this.setFirstField = el => {
this._firstField = el;
}, _temp;
}
handleBlur() {
var _props2 = this.props;
const onChange = _props2.onChange,
value = _props2.value;
if ((0, _isEmpty2.default)(value)) {
onChange(_PatchEvent2.default.from((0, _PatchEvent.unset)()));
}
}
renderField(field, level, index) {
if (field.type.hidden) {
return null;
}
var _props3 = this.props;
const value = _props3.value,
markers = _props3.markers,
readOnly = _props3.readOnly,
focusPath = _props3.focusPath,
onFocus = _props3.onFocus,
onBlur = _props3.onBlur;
const fieldValue = value && value[field.name];
return _react2.default.createElement(_Field2.default, {
key: field.name,
field: field,
value: fieldValue,
onChange: this.handleFieldChange,
onFocus: onFocus,
onBlur: onBlur,
markers: markers,
focusPath: focusPath,
level: level,
readOnly: readOnly,
ref: index === 0 && this.setFirstField
});
}
renderFieldset(fieldset, fieldsetIndex) {
var _props4 = this.props;
const level = _props4.level,
focusPath = _props4.focusPath;
const columns = fieldset.options && fieldset.options.columns;
const collapsibleOpts = getCollapsedWithDefaults(fieldset.options, level);
const isExpanded = focusPath.length > 0 && fieldset.fields.some(field => focusPath[0] === field.name);
return _react2.default.createElement(
'div',
{ key: fieldset.name, className: _Field4.default.root },
_react2.default.createElement(
_default2.default,
{
legend: fieldset.title,
description: fieldset.description,
level: level + 1,
columns: columns,
isCollapsible: collapsibleOpts.collapsible,
isCollapsed: !isExpanded && collapsibleOpts.collapsed
},
fieldset.fields.map((field, fieldIndex) => {
return this.renderField(field, level + 2, fieldsetIndex + fieldIndex);
})
)
);
}
getRenderedFields() {
var _props5 = this.props;
const type = _props5.type,
level = _props5.level;
if (!type.fieldsets) {
// this is a fallback for schema types that are not parsed to be objects, but still has jsonType == 'object'
return (type.fields || []).map((field, i) => this.renderField(field, level + 1, i));
}
return type.fieldsets.map((fieldset, i) => {
return fieldset.single ? this.renderField(fieldset.field, level + 1, i) : this.renderFieldset(fieldset, i);
});
}
renderUnknownFields() {
var _props6 = this.props;
const value = _props6.value,
type = _props6.type,
onChange = _props6.onChange,
readOnly = _props6.readOnly;
if (!type.fields) {
return null;
}
const knownFieldNames = type.fields.map(field => field.name);
const unknownFields = Object.keys(value || {}).filter(key => !key.startsWith('_') && !knownFieldNames.includes(key));
if (unknownFields.length === 0) {
return null;
}
return _react2.default.createElement(_UnknownFields2.default, {
readOnly: readOnly,
fieldNames: unknownFields,
value: value,
onChange: onChange
});
}
focus() {
if (this._firstField) {
this._firstField.focus();
}
}
render() {
var _props7 = this.props;
const type = _props7.type,
level = _props7.level,
focusPath = _props7.focusPath;
const renderedFields = this.getRenderedFields();
const renderedUnknownFields = this.renderUnknownFields();
if (level === 0) {
return _react2.default.createElement(
'div',
null,
renderedFields,
renderedUnknownFields
);
}
const collapsibleOpts = getCollapsedWithDefaults(type.options, level);
const isExpanded = focusPath.length > 0;
const columns = type.options && type.options.columns;
return _react2.default.createElement(
_default2.default,
{
level: level,
legend: type.title,
description: type.description,
columns: columns,
isCollapsible: collapsibleOpts.collapsible,
isCollapsed: !isExpanded && collapsibleOpts.collapsed
},
renderedFields,
renderedUnknownFields
);
}
}
exports.default = ObjectInput;
ObjectInput.propTypes = {
type: _FormBuilderPropTypes2.default.type,
value: _propTypes2.default.object,
onChange: _propTypes2.default.func,
onFocus: _propTypes2.default.func.isRequired,
focusPath: _propTypes2.default.array,
markers: _propTypes2.default.array,
onBlur: _propTypes2.default.func.isRequired,
level: _propTypes2.default.number,
readOnly: _propTypes2.default.bool,
isRoot: _propTypes2.default.bool
};
ObjectInput.defaultProps = {
onChange() {},
level: 0,
focusPath: [],
isRoot: false
};