@tomino/dynamic-form-semantic-ui
Version:
Semantic UI form renderer based on dynamic form generation
151 lines • 7.55 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const styles = tslib_1.__importStar(require("./properties_common"));
const properties_common_1 = require("./properties_common");
const classnames_1 = tslib_1.__importDefault(require("classnames"));
const mobx_react_1 = require("mobx-react");
const common_1 = require("../common");
const mobx_1 = require("mobx");
const dynamic_form_1 = require("@tomino/dynamic-form");
const group_1 = require("./group");
const semantic_ui_react_1 = require("semantic-ui-react");
const editor_context_1 = require("../editor/editor_context");
const helpers_1 = require("../helpers");
function renderControl(options, value, type, placeholder, error, onValueChange, mappingKey, className = '') {
return options ? (React.createElement(semantic_ui_react_1.Dropdown, { value: value, "data-value": value, "data-key": mappingKey, search: true, selection: true, fluid: true, name: "type", onChange: onValueChange, className: classnames_1.default('property-search', className, common_1.select, {
invalid: error
}), options: options })) : (React.createElement("input", { type: type, placeholder: placeholder, onChange: onValueChange, className: classnames_1.default({
invalid: error
}), value: value, "data-key": mappingKey, "data-value": value }));
}
const MapRow = (props) => {
const { mappingKey, map, owner, formElement, handlers, source, controlMap } = props;
const [currentKey, setKey] = React.useState(mappingKey);
const [value, setValue] = React.useState(map.get(mappingKey));
const [error, setError] = React.useState('');
const context = React.useContext(editor_context_1.EditorContext);
let keyOptions = helpers_1.getValue({ formElement, owner, handlers, catalogue: null }, context, 'options');
let valueOptions;
const editorState = React.useContext(editor_context_1.EditorContext);
const editorItem = editorState.editorCatalogue.components[owner.getValue('control')];
let schema;
if (editorItem && editorItem.props) {
schema = new dynamic_form_1.Schema(editorItem.props);
keyOptions = Object.getOwnPropertyNames(schema.properties).map(key => ({
label: schema.properties[key].title,
value: key,
description: schema.properties[key].description
}));
if (currentKey) {
valueOptions = editorItem.props[currentKey].schema.$enum;
if (valueOptions) {
valueOptions.forEach(o => (o.key = mappingKey));
}
}
}
const selected = currentKey && keyOptions && keyOptions.find(o => o.value === currentKey);
const onKeyChange = mobx_1.action((e, control) => {
const originalKey = e.currentTarget.getAttribute('data-key') || '';
const newKey = control.value;
const value = e.currentTarget.getAttribute('data-value');
setKey(newKey);
if (map.has(newKey)) {
owner.setError(source, 'Key exists: ' + newKey);
setError(originalKey);
return;
}
owner.mapRemove(source, originalKey);
owner.setMapValue(source, newKey, value == null ? '' : value);
let mapping = controlMap.find(o => o.key === originalKey);
if (mapping) {
mapping.key = newKey;
}
else {
controlMap.push({ key: newKey });
}
});
const onValueChange = (e) => {
const key = e.currentTarget.getAttribute('data-key');
let value = e.currentTarget.value;
setValue(value);
const source = common_1.prop(formElement);
if (schema) {
value = schema.properties[key].tryParse(value);
owner.setMapValue(source, e.key, value);
const mapSource = owner.getValue(source);
const mapObject = JSON.parse(JSON.stringify(mapSource));
let result = schema.validate(mapObject);
if (result && result.length) {
let errorKey = result[0].dataPath.replace(/\//g, '');
owner.setError(source, `${errorKey}: ${result[0].message}`);
setError(errorKey);
}
else {
owner.setError(source, '');
setError('');
}
}
else {
owner.setMapValue(source, key, value);
}
};
const deleteValue = (e) => {
const originalKey = e.currentTarget.getAttribute('data-key');
owner.mapRemove(source, originalKey);
};
return (React.createElement("div", { className: classnames_1.default(properties_common_1.styledTableRow(editorState.theme), { invalid: error }), onClick: e => {
if (selected && selected.description) {
owner.setValue('_help', selected.description);
e.preventDefault();
e.stopPropagation();
}
} },
React.createElement("div", { className: styles.tableRowFull }, renderControl(keyOptions, currentKey, 'text', 'Key', error === currentKey, onKeyChange, mappingKey, 'first gray')),
React.createElement("div", { className: styles.tableRowFull }, renderControl(valueOptions, value, (selected && selected.type) || 'text', 'Value', error === currentKey, onValueChange, mappingKey, 'second')),
React.createElement("div", { className: styles.tableRowAuto },
React.createElement("button", { className: properties_common_1.addButton(editorState.theme), onClick: deleteValue, "data-key": mappingKey }, "x"))));
};
let Map = class Map extends React.Component {
constructor() {
super(...arguments);
this.onClear = () => {
this.props.owner.setValue(common_1.prop(this.props.formElement), '');
};
this.addRow = () => {
const source = common_1.prop(this.props.formElement);
const current = this.props.owner.getValue(source);
if (!current || typeof current !== 'object') {
this.props.owner.setValue(source, {});
}
this.props.owner.setMapValue(source, '', '');
};
}
render() {
const { formElement, owner, handlers } = this.props;
const source = common_1.prop(formElement);
const controlMap = [];
const map = owner.getValue(source);
const lines = [];
if (map && typeof map === 'object') {
map.forEach((_value, key) => {
if (controlMap.every(c => c.key !== key)) {
controlMap.push({ key });
}
});
for (let i = 0; i < controlMap.length; i++) {
const mapping = controlMap[i];
lines.push(React.createElement(MapRow, { key: i, mappingKey: mapping.key, map: map, owner: owner, formElement: formElement, source: source, handlers: handlers, controlMap: controlMap }));
}
}
return (React.createElement(group_1.PropertyHeader, { label: formElement.props && formElement.props.text, buttons: React.createElement("button", { className: "headerButton", onClick: this.addRow }, "+") },
React.createElement("div", { className: properties_common_1.celled(this.context.theme) }, lines.length > 0 ? lines : undefined)));
}
};
Map.contextType = editor_context_1.EditorContext;
Map = tslib_1.__decorate([
mobx_react_1.observer
], Map);
exports.Map = Map;
//# sourceMappingURL=map.js.map