diff --git a/demo/spreadsheet-shape-projection.html b/demo/spreadsheet-shape-projection.html
index 8a4d5a1..daefeae 100644
--- a/demo/spreadsheet-shape-projection.html
+++ b/demo/spreadsheet-shape-projection.html
@@ -21,10 +21,16 @@
folk-shape {
background: rgb(187, 178, 178);
}
+
+ h1 {
+ margin: 0;
+ width: fit-content;
+ }
+ Spatial projection into a spreadsheet
diff --git a/src/folk-space-projector.ts b/src/folk-space-projector.ts
index f40fe62..a2837a7 100644
--- a/src/folk-space-projector.ts
+++ b/src/folk-space-projector.ts
@@ -1,7 +1,7 @@
import { css, PropertyValues } from '@lit/reactive-element';
import { FolkBaseSet } from './folk-base-set';
import { FolkShape } from './folk-shape';
-import { FolkSpreadsheet, FolkSpreadSheetCell, templateCells } from './folk-spreadsheet';
+import { CellTemplate, FolkSpreadsheet, FolkSpreadSheetCell, templateCells } from './folk-spreadsheet';
import { DOMRectTransform } from './common/DOMRectTransform';
FolkShape.define();
@@ -120,17 +120,31 @@ export class FolkSpaceProjector extends FolkBaseSet {
super.update(changedProperties);
if (changedProperties.has('sourceElements')) {
- const cells = templateCells(this.sourceElements.size, 5, {});
- this.#spreadsheet.setHTMLUnsafe(cells);
+ const cells: Record = {};
+
+ let row = 1;
+ for (const el of this.sourceElements) {
+ if (!(el instanceof FolkShape)) {
+ cells[`A${row}`] = { readonly: true };
+ cells[`B${row}`] = { readonly: true };
+ cells[`C${row}`] = { readonly: true };
+ cells[`D${row}`] = { readonly: true };
+ cells[`E${row}`] = { readonly: true };
+ }
+ row++;
+ }
+
+ const html = templateCells(this.sourceElements.size, 5, cells);
+ this.#spreadsheet.setHTMLUnsafe(html);
}
if (this.sourcesMap.size !== this.sourceElements.size) return;
this.#lock = true;
- const rects = this.sourceRects;
- for (let i = 0; i < rects.length; i += 1) {
- const row = i + 1;
- const rect = rects[i];
+ let row = 1;
+ for (const el of this.sourceElements) {
+ const rect = this.sourcesMap.get(el)!;
+
if (rect instanceof DOMRectTransform) {
const { x, y } = rect.toParentSpace(rect.topLeft);
this.#spreadsheet.getCell('A', row)!.expression = Math.round(x);
@@ -143,8 +157,11 @@ export class FolkSpaceProjector extends FolkBaseSet {
this.#spreadsheet.getCell('B', row)!.expression = Math.round(rect.y);
this.#spreadsheet.getCell('C', row)!.expression = Math.round(rect.width);
this.#spreadsheet.getCell('D', row)!.expression = Math.round(rect.height);
+ this.#spreadsheet.getCell('E', row)!.expression = 0;
}
+ row += 1;
}
+
Promise.resolve().then(() => {
this.#lock = false;
});
diff --git a/src/folk-spreadsheet.ts b/src/folk-spreadsheet.ts
index 4492218..15d1fbe 100644
--- a/src/folk-spreadsheet.ts
+++ b/src/folk-spreadsheet.ts
@@ -106,6 +106,10 @@ const styles = css`
justify-content: end;
}
+ ::slotted(folk-cell[readonly]) {
+ color: grey;
+ }
+
::slotted(folk-cell:hover) {
outline: 1px solid #1b73e8;
z-index: 5;
@@ -132,21 +136,30 @@ export function relativeColumnName(name: string, num: number) {
return alphabet[index + num];
}
-export function templateCells(numberOfRows: number, numberOfColumns: number, expressions: Record = {}) {
- const cells: string[] = [];
+export interface CellTemplate {
+ expression?: string;
+ readonly?: boolean;
+}
+
+export function templateCells(numberOfRows: number, numberOfColumns: number, cells: Record = {}) {
+ const html: string[] = [];
for (let i = 0; i < numberOfRows; i += 1) {
for (let j = 0; j < numberOfColumns; j += 1) {
const column = getColumnName(j);
const row = i + 1;
- const expression = expressions[`${column}${row}`];
- cells.push(
- ``
+ const { expression, readonly } = cells[`${column}${row}`] || {};
+ html.push(
+ ``
);
}
}
- return cells.join('\n');
+ return html.join('\n');
}
declare global {
@@ -168,7 +181,7 @@ export class FolkSpreadsheet extends HTMLElement {
#shadow = this.attachShadow({ mode: 'open' });
- #textarea: HTMLTextAreaElement | null = null;
+ #textarea!: HTMLTextAreaElement;
#editedCell: FolkSpreadSheetCell | null = null;
@@ -326,7 +339,7 @@ export class FolkSpreadsheet extends HTMLElement {
}
#focusTextarea(cell: FolkSpreadSheetCell) {
- if (this.#textarea === null) return;
+ if (cell.readonly) return;
this.#editedCell = cell;
const gridColumn = getColumnIndex(cell.column) + 2;
const gridRow = cell.row + 1;
@@ -339,7 +352,6 @@ export class FolkSpreadsheet extends HTMLElement {
#resetTextarea() {
if (this.#editedCell === null) return;
- if (this.#textarea === null) return;
this.#textarea.style.setProperty('--text-column', '0');
this.#textarea.style.setProperty('--text-row', '0');
this.#editedCell.expression = this.#textarea.value;
@@ -471,6 +483,13 @@ export class FolkSpreadSheetCell extends HTMLElement {
this.#evaluate();
}
+ get readonly() {
+ return this.hasAttribute('readonly');
+ }
+ set readonly(readonly) {
+ readonly ? this.setAttribute('readonly', '') : this.removeAttribute('readonly');
+ }
+
#value: any;
get value() {
return this.#value;