@tomino/dynamic-form-semantic-ui
Version:
Semantic UI form renderer based on dynamic form generation
283 lines • 9.68 kB
JavaScript
import React from 'react';
import { toJS } from 'mobx';
import { Context } from './context';
export function merge(...catalogues) {
if (!catalogues.some(c => c.createComponent)) {
throw new Error('The catalogue needs to define a createComponent function!');
}
return {
createComponent: catalogues.find(c => c.createComponent).createComponent,
cssClass: catalogues.map(c => (c.cssClass ? c.cssClass + ' ' : '')).join(''),
components: Object.assign({}, ...catalogues.map(c => c.components))
};
}
const composites = ['definitions', 'properties', 'items'];
export function schemaDatasetToJS(schema, faker = true) {
let result = cleanSchemaDataset(toJS(schema), faker);
if (!result) {
return null;
}
if (result.type === 'object' && !result.properties) {
result.properties = {};
}
return result;
}
export function formDatasetToJS(form) {
return cleanForm(toJS(form));
}
function cleanForm(form) {
if (!form) {
return null;
}
let result = {};
for (let key of Object.getOwnPropertyNames(form)) {
if (key === 'parent' || key === 'isSelected') {
continue;
}
let value = form[key];
if (Array.isArray(value)) {
if (value.length > 0) {
result[key] = value.map(v => (typeof v === 'object' ? cleanForm(v) : v));
}
}
else if (value != null && typeof value === 'object') {
if (Object.getOwnPropertyNames(value).length > 0) {
result[key] = cleanForm(value);
}
}
else if (value) {
result[key] = value;
}
}
if (Object.keys(result).length === 0) {
return undefined;
}
return result;
}
function cleanSchemaDataset(schema, faker) {
const cleaned = {};
if (schema == null) {
return;
}
let keys = Object.getOwnPropertyNames(schema || {});
for (let key of keys) {
let value = schema[key];
if (value == null || value === '') {
continue;
}
if (key === 'errors' || key === 'imports' || typeof schema[key] === 'function') {
}
else if (key === 'reference') {
if (faker) {
cleaned.properties = cleanSchemaDataset(schema.reference.properties, faker);
}
}
else if (composites.indexOf(key) >= 0) {
if ((faker || !schema.$ref) && value && Object.getOwnPropertyNames(value).length > 0) {
cleaned[key] = cleanSchemaDataset(schema[key], faker);
}
}
else if (key === '$enum') {
if (schema.$enum.length > 0) {
cleaned.enum = schema.$enum.map((e) => e.value);
cleaned.$enum = schema.$enum.map((e) => ({
text: e.text,
value: e.value,
icon: e.icon
}));
}
}
else if (Array.isArray(value)) {
if (value.length > 0) {
cleaned[key] = value.map(v => (typeof v === 'object' ? cleanSchemaDataset(v, faker) : v));
}
}
else if (typeof value === 'object') {
if (Object.getOwnPropertyNames(value).length > 0) {
cleaned[key] = cleanSchemaDataset(value, faker);
}
}
else {
cleaned[key] = value;
}
}
if (faker) {
if (schema.properties) {
cleaned.required = Object.getOwnPropertyNames(schema.properties);
}
}
return cleaned;
}
export function simpleHandle(props, handleName, context, args) {
return handle(props.handlers, handleName, props.owner, props, props.formElement, context, args);
}
export function handle(handlers, handle, owner, props, formElement, context, args) {
if (!handlers[handle]) {
console.error('Handler does not exist: ' + handle);
return;
}
return handle && handlers[handle]
? handlers[handle]({ owner, props, formElement, context, args })
: null;
}
export function bindGetValue(props, context) {
return function (element, propName, defaultValue) {
return getPropValue(props, element, context, propName, defaultValue);
};
}
export function getValues(props, ...propNames) {
const context = React.useContext(Context);
return propNames.map(p => getPropValue(props, props.formElement, context, p));
}
export function getValue(props, context, propName, defaultValue, path = '') {
return getPropValue(props, props.formElement, context, propName, defaultValue, path);
}
export function getPropValue(props, formElement, context, propName = undefined, defaultValue = undefined, path = '') {
if (!propName) {
propName = 'value';
}
let prop = formElement.props ? formElement.props[propName] : null;
if (prop == null) {
return defaultValue;
}
if (typeof prop !== 'object' || Array.isArray(prop)) {
return prop;
}
if (prop.value != null) {
return prop.value;
}
else if (prop.handler) {
return handle(props.handlers, prop.handler, props.owner, props, props.formElement, context);
}
else if (prop.source) {
return props.owner.getValue
? props.owner.getValue(prop.source + path)
: props.owner[prop.source];
}
return defaultValue === null ? '' : defaultValue;
}
export function safeGetValue(props, context, propName = null, defaultValue = null) {
let value = getValue(props, context, propName, defaultValue);
if (value == null) {
return value;
}
return value.toString();
}
export function setValue(props, context, value, propName = undefined, path = '') {
setPropValue(props, props.owner, context, value, propName, path);
}
export function setPropValue(props, owner, context, value, propName = undefined, path = '') {
if (!propName) {
propName = 'value';
}
let prop = props.formElement.props[propName];
if (prop == null) {
return;
}
if (typeof prop !== 'object') {
owner.setValue(propName, value);
}
if (prop.parse) {
handle(props.handlers, prop.parse, props.owner, props, props.formElement, context, {
current: value,
previous: getValue(props, context, propName)
});
return;
}
if (prop.source) {
owner.setValue(prop.source, path ? { [path.substring(1)]: value } : value, prop.validate ? props.handlers[prop.validate] : undefined);
}
else if (prop.handler) {
handle(props.handlers, prop.handler, props.owner, props, context, value);
}
}
export function prop(formElement, propName = 'value', type = 'source') {
return formElement && formElement.props && formElement.props[propName]
? formElement.props[propName][type]
: null;
}
export function isNullOrEmpty(val) {
return val == null || val == '';
}
export function valueSource(formElement) {
return prop(formElement, 'value', 'source');
}
export function valueHandler(formElement) {
return prop(formElement, 'value', 'handler');
}
export function value(formElement) {
return prop(formElement, 'value', 'value');
}
function stripUid(obj) {
if (obj.uid) {
delete obj.uid;
}
for (let key of Object.keys(obj)) {
let property = obj[key];
if (property.uid) {
delete property.uid;
}
if (Array.isArray(property)) {
for (let e of property) {
stripUid(e);
}
}
else if (typeof property === 'object') {
stripUid(property);
}
}
return obj;
}
export function clone(dataset) {
return stripUid(formDatasetToJS(dataset));
}
export function parseProps(props, context) {
const value = getValue(props, context, undefined, undefined) || '';
const controlSource = valueSource(props.formElement);
let error = '';
let disabled = false;
const label = getValue(props, context, 'label');
if (controlSource !== '' && props.owner.getSchema(controlSource, false) != null) {
error = controlSource ? props.owner.getError(controlSource) : null;
disabled = props.readOnly || (controlSource && props.owner.getSchema(controlSource).readOnly);
}
return { value, label, error, disabled };
}
export function processControl(props, createCallback = true) {
const context = React.useContext(Context);
const { formElement, owner } = props;
let handleChange;
if (createCallback) {
handleChange = React.useCallback((e, uiProps) => {
const source = valueSource(formElement);
if (!source) {
return;
}
setValue(props, context, uiProps.checked != null
? uiProps.checked
: uiProps.value != null
? uiProps.value
: e.currentTarget.checked !== undefined
? e.currentTarget.checked
: e.currentTarget.value);
const changeHandler = props.formElement.props.onChange;
if (changeHandler) {
simpleHandle(props, changeHandler, context);
}
}, [context, formElement, props]);
}
const { error, value, disabled } = parseProps(props, context);
const source = valueSource(formElement);
return {
context,
owner,
formElement,
error,
value,
disabled,
source,
handleChange,
controlProps: formElement.props
};
}
//# sourceMappingURL=helpers.js.map