@tomino/dynamic-form-semantic-ui
Version:
Semantic UI form renderer based on dynamic form generation
117 lines (103 loc) • 3.54 kB
text/typescript
import { FormComponentProps } from '@tomino/dynamic-form';
import { FormDataSet, SchemaDataSet } from './form_store';
import { GridChildProps } from '../layouts/grid_view';
import { EditorContextType } from './editor_context';
import { bindGetValue } from '../helpers';
export function findConflict(
props: FormComponentProps,
context: EditorContextType,
cells: FormDataSet<GridChildProps>[],
start: number,
end: number
) {
const getValue = bindGetValue(props, context);
return cells.find(
e =>
(getValue(e, 'column') >= start && getValue(e, 'column') <= end) ||
(getValue(e, 'column') + getValue(e, 'width') - 1 >= start &&
getValue(e, 'column') + getValue(e, 'width') - 1 <= end)
);
}
export function adjustPosition(
props: FormComponentProps,
context: EditorContextType,
where: string,
source: FormDataSet<GridChildProps>,
target: FormDataSet<GridChildProps>,
parent: FormDataSet<GridChildProps>
) {
const getValue = bindGetValue(props, context);
if (!parent) {
// TODO: fix
return getValue(target, 'column');
}
let dimensions = parent.elements.reduce(
(prev, next) => ({
rows: prev.rows < next.props.row ? next.props.row : prev.rows,
columns: prev.columns < next.props.column ? next.props.column : prev.columns
}),
{ rows: 0, columns: 0 }
);
// adjust from left or right
let column =
where === 'left'
? getValue(target, 'column')
: getValue(target, 'column') - getValue(target, 'width') + 1;
// if (adjust) {
// source.props.column = position.props.column - source.props.width + 1;
// }
// adjust to min width
column = column < 1 ? 1 : column;
// adjust to max width
column =
column + source.props.width > dimensions.columns
? dimensions.columns - getValue(source, 'width') + 1
: column;
let cells = parent.elements.filter(e => e.props.row === target.props.row && e !== source);
// try one adjustment moving the item left or right from the conflict cell
let conflict = findConflict(props, context, cells, column, column + source.props.width - 1);
// TRYING TO SOLVE IT FOR THE USER
// if (conflict) {
// column = where === 'left' ? conflict.props.column - source.props.width : conflict.props.column + conflict.props.width;
// }
// // if it fails again we give up
// if (column >= 0) {
// conflict = findConflict(cells, column, column + source.props.width - 1);
// }
if (conflict) {
return -1;
}
return column;
}
export function bind(formElement: FormDataSet, item: any) {
// we can either drop on existing control
// or on an empty cell
if (formElement.parent) {
// find the parent path
let parent = formElement.parent;
let parentPath = '';
while (parent) {
if (parent.props.value && parent.props.value.source) {
parentPath = parentPath + parent.props.value + '.';
}
parent = parent.parent;
}
let path = item.name.replace(parentPath, '');
formElement.setValue('source', path);
return;
}
// if it is an empty cell, we will guess the control
const schema: SchemaDataSet = item.schema;
item.label = item.name;
item.source = item.name;
if (schema.type === 'boolean') {
item.name = 'Checkbox';
} else if (schema.type === 'array') {
item.name = 'Table';
} else if (schema.type === 'number' || schema.type === 'integer') {
item.name = 'Input';
item.controlProps = { type: 'number' };
} else if (schema.type === 'string') {
item.name = 'Input';
}
}