summaryrefslogtreecommitdiff
path: root/apps/web/src/components/app/index.ts
diff options
context:
space:
mode:
authorJosh Kingsley <josh@joshkingsley.me>2025-11-24 15:46:22 +0200
committerJosh Kingsley <josh@joshkingsley.me>2025-11-24 15:46:22 +0200
commitd724cc0bf6ff6d351319e6fb00f5184a04e16ac0 (patch)
treecb43253479df5db8f4844e17e68a48ea5a212df4 /apps/web/src/components/app/index.ts
parent7c966e105cd9f65853de1aba0ecce63aa56aca0b (diff)
chore: improve dev tasks
Diffstat (limited to 'apps/web/src/components/app/index.ts')
-rw-r--r--apps/web/src/components/app/index.ts93
1 files changed, 93 insertions, 0 deletions
diff --git a/apps/web/src/components/app/index.ts b/apps/web/src/components/app/index.ts
new file mode 100644
index 0000000..a2c0c9d
--- /dev/null
+++ b/apps/web/src/components/app/index.ts
@@ -0,0 +1,93 @@
+import { produce } from "immer";
+import defaultDoc from "../../defaultDoc";
+import NotiveElement, { customElement } from "../../element";
+import {
+ changeSelectedSubdivisions,
+ getSelectedSubdivisionsCount,
+} from "../../grid";
+import { Doc } from "../../types";
+import ntvGrid, { NotiveGridElement } from "../grid";
+import renderGrid from "../grid/renderGrid";
+import { GridSelection } from "../grid/selection";
+import ntvToolbar from "../toolbar";
+import "./index.css";
+
+@customElement("ntv-app")
+export class NotiveAppElement extends NotiveElement {
+ doc: Doc = defaultDoc();
+
+ #selectedGridId?: string;
+ #selection?: GridSelection;
+
+ setSelection(gridId: string, selection: GridSelection) {
+ const grid = this.doc.grids.find((grid) => grid.id === gridId);
+ if (!grid) throw new Error("Invalid grid ID");
+
+ this.#selectedGridId = gridId;
+ this.#selection = selection;
+ this.#updateGridSelections();
+
+ this.#toolbar.subdivisions = getSelectedSubdivisionsCount(grid, selection);
+ }
+
+ clearSelection() {
+ this.#selectedGridId = undefined;
+ this.#selection = undefined;
+ this.#updateGridSelections();
+ this.#toolbar.subdivisions = undefined;
+ }
+
+ #updateGridSelections() {
+ this.querySelectorAll<NotiveGridElement>("ntv-grid").forEach((grid) => {
+ grid.selection =
+ this.#selectedGridId === grid.grid?.id ? this.#selection : undefined;
+ });
+ }
+
+ #toolbar = ntvToolbar({
+ onsubdivisionschange: ({ subdivisions }) => {
+ if (!subdivisions) return;
+
+ const gridId = this.#selectedGridId;
+ const selection = this.#selection;
+
+ if (!gridId || !selection) return;
+
+ const gridIndex = this.doc.grids.findIndex((grid) => grid.id === gridId);
+
+ this.doc = produce(this.doc, (doc) => {
+ doc.grids[gridIndex] = changeSelectedSubdivisions(
+ this.doc.grids[gridIndex],
+ selection,
+ subdivisions,
+ );
+ });
+
+ this.querySelector<NotiveGridElement>(
+ `ntv-grid[data-grid-id="${gridId}"]`,
+ )!.grid = renderGrid(this.doc.grids[gridIndex]);
+
+ this.clearSelection();
+ },
+ });
+
+ connectedCallback() {
+ this.append(
+ this.#toolbar,
+ ...this.doc.grids.map((grid) =>
+ ntvGrid({
+ grid: renderGrid(grid),
+ dataset: { gridId: grid.id },
+ ongridselectionchange: (event) => {
+ this.setSelection(grid.id, event.selection);
+ },
+ oncellchange: (event) => {
+ console.log(event);
+ },
+ }),
+ ),
+ );
+ }
+}
+
+export default NotiveAppElement.makeFactory();