summaryrefslogtreecommitdiff
path: root/web/src
diff options
context:
space:
mode:
Diffstat (limited to 'web/src')
-rw-r--r--web/src/components/grid/index.ts2
-rw-r--r--web/src/components/toolbar/index.ts39
-rw-r--r--web/src/index.ts33
-rw-r--r--web/src/selection.ts19
-rw-r--r--web/src/types.ts40
5 files changed, 124 insertions, 9 deletions
diff --git a/web/src/components/grid/index.ts b/web/src/components/grid/index.ts
index fbb9c60..5301afb 100644
--- a/web/src/components/grid/index.ts
+++ b/web/src/components/grid/index.ts
@@ -27,7 +27,7 @@ class NotiveGridElement extends HTMLElement {
throw new Error("ntv-grid requries gridId attribute");
}
- window.addEventListener("ntv:selection-changed", () => this.draw());
+ window.addEventListener("ntv:selectionchange", () => this.draw());
this.canvasEl.addEventListener(
"mousedown",
diff --git a/web/src/components/toolbar/index.ts b/web/src/components/toolbar/index.ts
index e672a48..666114b 100644
--- a/web/src/components/toolbar/index.ts
+++ b/web/src/components/toolbar/index.ts
@@ -33,7 +33,7 @@ class NotiveToolbarElement extends HTMLElement {
connectedCallback() {
this.#render();
- window.addEventListener("ntv:selection-changed", () => {
+ window.addEventListener("ntv:selectionchange", () => {
if (window.notive.pendingSelection) {
this.#subdivisionsInputEl.disabled = true;
this.#subdivisionsInputEl.value = "";
@@ -51,6 +51,12 @@ class NotiveToolbarElement extends HTMLElement {
this.#subdivisionsInputEl.disabled = false;
this.#subdivisionsInputEl.value = subdivisionsCount.toString();
});
+
+ this.#subdivisionsInputEl.addEventListener("change", () => {
+ window.notive.subdivideSelection(
+ parseInt(this.#subdivisionsInputEl.value),
+ );
+ });
}
#render() {
@@ -61,9 +67,36 @@ class NotiveToolbarElement extends HTMLElement {
h.button({ dataset: { variant: "menu" } }, "Format"),
),
h.section(
- h.button({ dataset: { variant: "icon" } }, "-"),
+ h.button(
+ {
+ dataset: { variant: "icon" },
+ onclick: () => {
+ const subdivisions = Math.max(
+ 1,
+ parseInt(this.#subdivisionsInputEl.value) - 1,
+ );
+
+ this.#subdivisionsInputEl.value = subdivisions.toString();
+ window.notive.subdivideSelection(subdivisions);
+ },
+ },
+ "-",
+ ),
this.#subdivisionsInputEl,
- h.button({ dataset: { variant: "icon" } }, "+"),
+ h.button(
+ {
+ dataset: { variant: "icon" },
+
+ onclick: () => {
+ const subdivisions =
+ parseInt(this.#subdivisionsInputEl.value) + 1;
+
+ this.#subdivisionsInputEl.value = subdivisions.toString();
+ window.notive.subdivideSelection(subdivisions);
+ },
+ },
+ "+",
+ ),
),
);
}
diff --git a/web/src/index.ts b/web/src/index.ts
index 6ab61c9..a6f0ac7 100644
--- a/web/src/index.ts
+++ b/web/src/index.ts
@@ -1,8 +1,10 @@
import Ratio from "./math/Ratio";
-import { Cell, CellRef, Doc, Grid } from "./types";
+import { Cell, CellRef, Doc, Grid, mapRowsInRange } from "./types";
import { ActiveCellSelection, Selection } from "./selection";
-import renderGrid, { RenderedGrid } from "./components/grid/renderGrid";
-import cellAtCoord from "./components/grid/cellAtCoord";
+import renderGrid, {
+ getRenderedCell,
+ RenderedGrid,
+} from "./components/grid/renderGrid";
function defaultDoc(): Doc {
const defaultCells: Cell[] = Array.from({ length: 16 }, () => ({
@@ -29,7 +31,12 @@ function defaultDoc(): Doc {
baseCellWidthRatio: new Ratio(1, 16),
parts: [
{
- rows: Array.from({ length: 4 }, () => ({
+ rows: Array.from({ length: 2 }, () => ({
+ cells: [...defaultCells],
+ })),
+ },
+ {
+ rows: Array.from({ length: 2 }, () => ({
cells: [...defaultCells],
})),
},
@@ -92,7 +99,23 @@ export default class Notive {
}
#dispatchSelectionChanged() {
- window.dispatchEvent(new CustomEvent("ntv:selection-changed"));
+ window.dispatchEvent(new CustomEvent("ntv:selectionchange"));
+ }
+
+ subdivideSelection(subdivisions: number) {
+ const selection = this.selection;
+
+ if (!selection) return;
+
+ const newDoc = mapRowsInRange(
+ this.doc,
+ selection.gridId,
+ selection.startCellRef(),
+ selection.endCellRef(),
+ (row, rowRef) => {
+ return row;
+ },
+ );
}
}
diff --git a/web/src/selection.ts b/web/src/selection.ts
index 294db52..abaf8b5 100644
--- a/web/src/selection.ts
+++ b/web/src/selection.ts
@@ -17,6 +17,9 @@ export abstract class Selection {
abstract extend(cellRef: CellRef): Selection;
abstract getSelectedCells(grid: RenderedGrid): RenderedCell[][];
+
+ abstract startCellRef(): CellRef;
+ abstract endCellRef(): CellRef;
}
export class ActiveCellSelection extends Selection {
@@ -34,6 +37,14 @@ export class ActiveCellSelection extends Selection {
getSelectedCells(grid: RenderedGrid): RenderedCell[][] {
return [[getRenderedCell(grid, this.activeCellRef)!]];
}
+
+ startCellRef(): CellRef {
+ return this.activeCellRef;
+ }
+
+ endCellRef(): CellRef {
+ return this.activeCellRef;
+ }
}
export type CellRange = [CellRef, CellRef];
@@ -101,4 +112,12 @@ export class RangeSelection extends Selection {
return row.renderedCells.slice(firstCellIndex, lastCellIndex + 1);
});
}
+
+ startCellRef(): CellRef {
+ return this.range[0];
+ }
+
+ endCellRef(): CellRef {
+ return this.range[1];
+ }
}
diff --git a/web/src/types.ts b/web/src/types.ts
index d932389..8b1b650 100644
--- a/web/src/types.ts
+++ b/web/src/types.ts
@@ -44,3 +44,43 @@ export function cellRefEquals(a: CellRef, b: CellRef): boolean {
a.cellIndex === b.cellIndex
);
}
+
+export function mapRowsInRange(
+ doc: Doc,
+ gridId: string,
+ startRef: CellRef,
+ endRef: CellRef,
+ mapFn: (row: Row, ref: RowRef) => Row,
+): Doc {
+ const firstPartIndex = Math.min(startRef.partIndex, endRef.partIndex);
+ const lastPartIndex = Math.max(startRef.partIndex, endRef.partIndex);
+ const firstRowIndex = Math.min(startRef.rowIndex, endRef.rowIndex);
+ const lastRowIndex = Math.max(startRef.rowIndex, endRef.rowIndex);
+
+ return {
+ ...doc,
+ grids: doc.grids.map((grid) => {
+ if (grid.id !== gridId) return grid;
+
+ return {
+ ...grid,
+ parts: grid.parts.map((part, partIndex) => {
+ if (partIndex < firstPartIndex || partIndex > lastPartIndex) {
+ return part;
+ }
+
+ return {
+ ...part,
+ rows: part.rows.map((row, rowIndex) => {
+ if (rowIndex < firstRowIndex || rowIndex > lastRowIndex) {
+ return row;
+ }
+
+ return mapFn(row, { partIndex, rowIndex });
+ }),
+ };
+ }),
+ };
+ }),
+ };
+}