UNPKG

@tomino/dynamic-form-semantic-ui

Version:

Semantic UI form renderer based on dynamic form generation

149 lines 7.1 kB
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