@tomino/dynamic-form-semantic-ui
Version:
Semantic UI form renderer based on dynamic form generation
149 lines • 7.1 kB
JavaScript
import * as tslib_1 from "tslib";
import * as React from 'react';
import * as styles from './properties_common';
import { styledTableRow, addButton, celled } from './properties_common';
import names from 'classnames';
import { observer } from 'mobx-react';
import { select, prop } from '../common';
import { action } from 'mobx';
import { Schema } from '@tomino/dynamic-form';
import { PropertyHeader } from './group';
import { Dropdown } from 'semantic-ui-react';
import { EditorContext } from '../editor/editor_context';
import { getValue } from '../helpers';
function renderControl(options, value, type, placeholder, error, onValueChange, mappingKey, className = '') {
return options ? (React.createElement(Dropdown, { value: value, "data-value": value, "data-key": mappingKey, search: true, selection: true, fluid: true, name: "type", onChange: onValueChange, className: names('property-search', className, select, {
invalid: error
}), options: options })) : (React.createElement("input", { type: type, placeholder: placeholder, onChange: onValueChange, className: names({
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(EditorContext);
let keyOptions = getValue({ formElement, owner, handlers, catalogue: null }, context, 'options');
let valueOptions;
const editorState = React.useContext(EditorContext);
const editorItem = editorState.editorCatalogue.components[owner.getValue('control')];
let schema;
if (editorItem && editorItem.props) {
schema = new 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 = 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 = 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: names(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: 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(prop(this.props.formElement), '');
};
this.addRow = () => {
const source = 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 = 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(PropertyHeader, { label: formElement.props && formElement.props.text, buttons: React.createElement("button", { className: "headerButton", onClick: this.addRow }, "+") },
React.createElement("div", { className: celled(this.context.theme) }, lines.length > 0 ? lines : undefined)));
}
};
Map.contextType = EditorContext;
Map = tslib_1.__decorate([
observer
], Map);
export { Map };
//# sourceMappingURL=map.js.map