diff --git a/src/display/data-schema/data.d.ts b/src/display/data-schema/data.d.ts index 0e52a719..a5c50826 100644 --- a/src/display/data-schema/data.d.ts +++ b/src/display/data-schema/data.d.ts @@ -98,7 +98,7 @@ export interface Grid { id?: string; // Default: uid label?: string; show?: boolean; // Default: true - cells: (0 | 1)[][]; + cells: (0 | 1 | string)[][]; gap?: Gap; item: { components?: Component[]; diff --git a/src/display/data-schema/element-schema.js b/src/display/data-schema/element-schema.js index 30aa3c6c..16d7dd1b 100644 --- a/src/display/data-schema/element-schema.js +++ b/src/display/data-schema/element-schema.js @@ -30,7 +30,7 @@ export const groupSchema = Base.extend({ */ export const gridSchema = Base.extend({ type: z.literal('grid'), - cells: z.array(z.array(z.union([z.literal(0), z.literal(1)]))), + cells: z.array(z.array(z.union([z.literal(0), z.literal(1), z.string()]))), gap: Gap, item: z.object({ components: componentArraySchema.default([]), diff --git a/src/display/mixins/Base.js b/src/display/mixins/Base.js index 738fcadf..8d5573ae 100644 --- a/src/display/mixins/Base.js +++ b/src/display/mixins/Base.js @@ -92,8 +92,12 @@ export const Base = (superClass) => { ? Object.keys(nextProps) : Object.keys(actualChanges); - const { id, label, attrs } = validatedChanges; - if (id || label || attrs) { + if ( + ['id', 'label', 'attrs'].some((key) => + Object.hasOwn(validatedChanges, key), + ) + ) { + const { id, label, attrs } = validatedChanges; this._applyRaw({ id, label, ...attrs }, mergeStrategy); } diff --git a/src/display/mixins/Cellsable.js b/src/display/mixins/Cellsable.js index ad627c5e..d5e6524a 100644 --- a/src/display/mixins/Cellsable.js +++ b/src/display/mixins/Cellsable.js @@ -9,27 +9,31 @@ export const Cellsable = (superClass) => { const { cells } = relevantChanges; const { gap, item: itemProps } = this.props; - const currentItemIds = new Set(this.children.map((child) => child.id)); + const requiredItemIds = new Set(); + const childrenMap = new Map( + this.children.map((child) => [child.id, child]), + ); cells.forEach((row, rowIndex) => { row.forEach((col, colIndex) => { + if (!col) return; const id = `${this.id}.${rowIndex}.${colIndex}`; - if (col === 1) { - requiredItemIds.add(id); - if (!currentItemIds.has(id)) { - const item = newElement('item', this.context); - item.apply({ - type: 'item', - id, - ...itemProps, - attrs: { - x: colIndex * (itemProps.size.width + gap.x), - y: rowIndex * (itemProps.size.height + gap.y), - }, - }); - this.addChild(item); - } + requiredItemIds.add(id); + + const label = typeof col === 'string' ? col : ''; + const existingItem = childrenMap.get(id); + if (!existingItem) { + const attrs = { + gridIndex: { row: rowIndex, col: colIndex }, + x: colIndex * (itemProps.size.width + gap.x), + y: rowIndex * (itemProps.size.height + gap.y), + }; + const item = newElement('item', this.context); + item.apply({ type: 'item', id, ...itemProps, label, attrs }); + this.addChild(item); + } else { + existingItem.apply({ label }); } }); });