/** @jsxImportSource react */ import { VDOM, getContent, contentAppend } from "../Widget"; import { StyledContainerBase, StyledContainerConfig } from "../Container"; import { Instance } from "../Instance"; import { isArray } from "../../util/isArray"; import { isUndefined } from "../../util/isUndefined"; import { isNumber } from "../../util/isNumber"; import { RenderingContext } from "../RenderingContext"; function validContent(r: any): any { let content: any[] = []; for (let key in r) if (key != "label") contentAppend(content, r[key]); return content; } interface LayoutState { rows: any[]; currentRow: number; labelCells: any[]; fieldCells: any[]; rowCapacities: number[]; } export interface LabelsTopLayoutConfig extends StyledContainerConfig { vertical?: boolean; columns?: number; } export class LabelsTopLayout extends StyledContainerBase { declare vertical?: boolean; declare columns?: number; constructor(config?: LabelsTopLayoutConfig) { super(config); } init(): void { if (this.vertical && isUndefined(this.columns)) this.columns = 1; super.init(); } render(context: RenderingContext, instance: any, key: any): any { let { children, data } = instance; let state: LayoutState = { rows: [], currentRow: 0, labelCells: [], fieldCells: [], rowCapacities: [this.columns!], }; const processContent = (r: any) => { if (!r) return; if (isArray(r.content) && r.useParentLayout) r.content.forEach((x: any) => processContent(x)); else if (r.atomic && r.type == "layout-cell") this.addItem(state, isArray(r.content) && r.content.length == 1 ? r.content[0] : r.content, r.data); else this.addItem(state, r, {}); }; children.forEach((item: any) => processContent(item.vdom)); this.addRow(state); return ( {state.rows}
); } addRow(state: LayoutState): void { if (state.labelCells.length > 0) state.rows.push({state.labelCells}); if (state.fieldCells.length > 0) state.rows.push({state.fieldCells}); state.labelCells = []; state.fieldCells = []; state.currentRow++; if (state.currentRow == state.rowCapacities.length) state.rowCapacities.push(this.columns!); } addItem(state: LayoutState, item: any, data: any): void { while (state.labelCells.length == state.rowCapacities[state.currentRow]) this.addRow(state); if (data.rowSpan > 1) { for (let row = state.currentRow + 1; row < state.currentRow + data.rowSpan; row++) { if (row == state.rowCapacities.length) state.rowCapacities.push(this.columns!); state.rowCapacities[row] -= data.colSpan || 1; } } if (data.colSpan > 1) state.rowCapacities[state.currentRow] -= data.colSpan - 1; state.labelCells.push( {getContent(item.label)} , ); state.fieldCells.push( {validContent(item)} , ); } } LabelsTopLayout.prototype.baseClass = "labelstoplayout"; LabelsTopLayout.prototype.vertical = false; LabelsTopLayout.prototype.columns = undefined; export interface LabelsTopLayoutCellConfig extends StyledContainerConfig { colSpan?: number; rowSpan?: number; } export class LabelsTopLayoutCell extends StyledContainerBase { declare colSpan?: number; declare rowSpan?: number; constructor(config?: LabelsTopLayoutCellConfig) { super(config); } declareData(...args: any[]): void { super.declareData(...args, { colSpan: undefined, rowSpan: undefined, }); } render(context: RenderingContext, instance: any, key: any): any { let { content } = (this as any).renderChildren(context, instance); return { atomic: true, type: "layout-cell", data: instance.data, content, }; } } LabelsTopLayoutCell.prototype.useParentLayout = true;