diff --git a/index.html b/index.html
index 1781066..8b07c4c 100644
--- a/index.html
+++ b/index.html
@@ -9,19 +9,7 @@
-
-
-
-
-
-
-
-
-
+
diff --git a/package-lock.json b/package-lock.json
index 5082dce..54c14c0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,13 +11,40 @@
"@automerge/automerge-repo": "^1.2.1",
"@automerge/automerge-repo-network-websocket": "^1.2.1",
"@automerge/automerge-repo-storage-indexeddb": "^1.2.1",
+ "svelte": "^5.0.0-next.272",
"vite-plugin-top-level-await": "^1.4.4",
"vite-plugin-wasm": "^3.4.1"
},
"devDependencies": {
+ "@sveltejs/vite-plugin-svelte": "^5.0.3",
+ "@types/node": "^20.0.0",
+ "typescript": "^5.0.0",
"vite": "^6.0.5"
}
},
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@ampproject/remapping/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
"node_modules/@automerge/automerge": {
"version": "2.2.8",
"resolved": "https://registry.npmjs.org/@automerge/automerge/-/automerge-2.2.8.tgz",
@@ -558,6 +585,30 @@
"node": ">=18"
}
},
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
+ "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
@@ -567,6 +618,15 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
@@ -859,6 +919,46 @@
"win32"
]
},
+ "node_modules/@sveltejs/vite-plugin-svelte": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-5.0.3.tgz",
+ "integrity": "sha512-MCFS6CrQDu1yGwspm4qtli0e63vaPCehf6V7pIMP15AsWgMKrqDGCPFF/0kn4SP0ii4aySu4Pa62+fIRGFMjgw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1",
+ "debug": "^4.4.0",
+ "deepmerge": "^4.3.1",
+ "kleur": "^4.1.5",
+ "magic-string": "^0.30.15",
+ "vitefu": "^1.0.4"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22"
+ },
+ "peerDependencies": {
+ "svelte": "^5.0.0",
+ "vite": "^6.0.0"
+ }
+ },
+ "node_modules/@sveltejs/vite-plugin-svelte-inspector": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-4.0.1.tgz",
+ "integrity": "sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.7"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22"
+ },
+ "peerDependencies": {
+ "@sveltejs/vite-plugin-svelte": "^5.0.0",
+ "svelte": "^5.0.0",
+ "vite": "^6.0.0"
+ }
+ },
"node_modules/@swc/core": {
"version": "1.10.4",
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.4.tgz",
@@ -1103,13 +1203,12 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "22.10.5",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz",
- "integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==",
+ "version": "20.17.14",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.14.tgz",
+ "integrity": "sha512-w6qdYetNL5KRBiSClK/KWai+2IMEJuAj+EujKCumalFOwXtvOXaEan9AuwcRID2IcOIAWSIfR495hBtgKlx2zg==",
"license": "MIT",
- "peer": true,
"dependencies": {
- "undici-types": "~6.20.0"
+ "undici-types": "~6.19.2"
}
},
"node_modules/acorn": {
@@ -1124,6 +1223,15 @@
"node": ">=0.4.0"
}
},
+ "node_modules/acorn-typescript": {
+ "version": "1.4.13",
+ "resolved": "https://registry.npmjs.org/acorn-typescript/-/acorn-typescript-1.4.13.tgz",
+ "integrity": "sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==",
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": ">=8.9.0"
+ }
+ },
"node_modules/acorn-walk": {
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
@@ -1142,6 +1250,24 @@
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"license": "MIT"
},
+ "node_modules/aria-query": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
+ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/base-x": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz",
@@ -1198,6 +1324,15 @@
"cbor-extract": "^2.2.0"
}
},
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
@@ -1221,6 +1356,16 @@
}
}
},
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/detect-libc": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
@@ -1280,6 +1425,21 @@
"@esbuild/win32-x64": "0.24.2"
}
},
+ "node_modules/esm-env": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
+ "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
+ "license": "MIT"
+ },
+ "node_modules/esrap": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.3.tgz",
+ "integrity": "sha512-Xddc1RsoFJ4z9nR7W7BFaEPIp4UXoeQ0+077UdWLxbafMQFyU79sQJMk7kxNgRwQ9/aVgaKacCHC2pUACGwmYw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.4.15"
+ }
+ },
"node_modules/eventemitter3": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
@@ -1306,6 +1466,15 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
+ "node_modules/is-reference": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
+ "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.6"
+ }
+ },
"node_modules/isomorphic-ws": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz",
@@ -1315,6 +1484,31 @@
"ws": "*"
}
},
+ "node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/locate-character": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
+ "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
+ "license": "MIT"
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.17",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0"
+ }
+ },
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
@@ -1441,6 +1635,31 @@
"node": ">=0.10.0"
}
},
+ "node_modules/svelte": {
+ "version": "5.18.0",
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.18.0.tgz",
+ "integrity": "sha512-/Eb81lB8bVUxQPmkPVNBYrU9cZ544+9hE91ZUUXTMf7eWcGW84N1hS3gvv/XsUNOWLLg3IicXP2qa8W3KpTUHA==",
+ "license": "MIT",
+ "dependencies": {
+ "@ampproject/remapping": "^2.3.0",
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@types/estree": "^1.0.5",
+ "acorn": "^8.12.1",
+ "acorn-typescript": "^1.4.13",
+ "aria-query": "^5.3.1",
+ "axobject-query": "^4.1.0",
+ "clsx": "^2.1.1",
+ "esm-env": "^1.2.1",
+ "esrap": "^1.4.3",
+ "is-reference": "^3.0.3",
+ "locate-character": "^3.0.0",
+ "magic-string": "^0.30.11",
+ "zimmerframe": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/tiny-typed-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz",
@@ -1495,7 +1714,6 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"license": "Apache-2.0",
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -1505,11 +1723,10 @@
}
},
"node_modules/undici-types": {
- "version": "6.20.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
- "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
- "license": "MIT",
- "peer": true
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "license": "MIT"
},
"node_modules/uuid": {
"version": "9.0.1",
@@ -1637,6 +1854,25 @@
"vite": "^2 || ^3 || ^4 || ^5 || ^6"
}
},
+ "node_modules/vitefu": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.5.tgz",
+ "integrity": "sha512-h4Vflt9gxODPFNGPwp4zAMZRpZR7eslzwH2c5hn5kNZ5rhnKyRJ50U+yGCdc2IRaBs8O4haIgLNGrV5CrpMsCA==",
+ "dev": true,
+ "license": "MIT",
+ "workspaces": [
+ "tests/deps/*",
+ "tests/projects/*"
+ ],
+ "peerDependencies": {
+ "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0"
+ },
+ "peerDependenciesMeta": {
+ "vite": {
+ "optional": true
+ }
+ }
+ },
"node_modules/ws": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
@@ -1676,6 +1912,12 @@
"engines": {
"node": ">=6"
}
+ },
+ "node_modules/zimmerframe": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz",
+ "integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==",
+ "license": "MIT"
}
}
}
diff --git a/package.json b/package.json
index 6fc8e9b..7cf66bf 100644
--- a/package.json
+++ b/package.json
@@ -9,14 +9,16 @@
"preview": "vite preview"
},
"devDependencies": {
- "vite": "^6.0.5",
+ "@sveltejs/vite-plugin-svelte": "^5.0.3",
+ "@types/node": "^20.0.0",
"typescript": "^5.0.0",
- "@types/node": "^20.0.0"
+ "vite": "^6.0.5"
},
"dependencies": {
"@automerge/automerge-repo": "^1.2.1",
"@automerge/automerge-repo-network-websocket": "^1.2.1",
"@automerge/automerge-repo-storage-indexeddb": "^1.2.1",
+ "svelte": "^5.0.0-next.272",
"vite-plugin-top-level-await": "^1.4.4",
"vite-plugin-wasm": "^3.4.1"
}
diff --git a/src/components/Canvas.svelte b/src/components/Canvas.svelte
new file mode 100644
index 0000000..3d1075c
--- /dev/null
+++ b/src/components/Canvas.svelte
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/shapes/Circle.svelte b/src/components/shapes/Circle.svelte
new file mode 100644
index 0000000..bb56486
--- /dev/null
+++ b/src/components/shapes/Circle.svelte
@@ -0,0 +1,18 @@
+
+
+
\ No newline at end of file
diff --git a/src/components/shapes/Triangle.svelte b/src/components/shapes/Triangle.svelte
new file mode 100644
index 0000000..d8bd2b3
--- /dev/null
+++ b/src/components/shapes/Triangle.svelte
@@ -0,0 +1,19 @@
+
+
+
\ No newline at end of file
diff --git a/src/docManager.ts b/src/docManager.ts
index 8959e16..c70e2d4 100644
--- a/src/docManager.ts
+++ b/src/docManager.ts
@@ -19,26 +19,21 @@ export async function initRepo(): Promise> {
if (rootDocUrl && isValidAutomergeUrl(rootDocUrl)) {
handle = repo.find(rootDocUrl);
- await handle.whenReady();
-
- handle.change((doc: AppDocument) => {
- if (!doc.schemaVersion) {
- doc.schemaVersion = 1;
- }
- });
} else {
- handle = repo.create({
- schemaVersion: CURRENT_SCHEMA_VERSION,
- shapes: []
+ handle = repo.create();
+ handle.change((doc: AppDocument) => {
+ doc.schemaVersion = CURRENT_SCHEMA_VERSION;
+ doc.shapes = [];
});
- await handle.whenReady();
document.location.hash = handle.url;
}
+ await handle.whenReady();
return handle;
}
-export const updateDocWithNewCircle = (x: number, y: number, radius: number) => {
+export function updateDocWithNewCircle(x: number, y: number, radius: number): void {
+ console.log('Adding circle:', { x, y, radius }); // Debug log
handle.change((doc: AppDocument) => {
const circle: CircleShape = {
id: Date.now(),
@@ -48,11 +43,15 @@ export const updateDocWithNewCircle = (x: number, y: number, radius: number) =>
radius,
color: "red"
};
+ if (!doc.shapes) {
+ doc.shapes = [];
+ }
doc.shapes.push(circle);
});
}
-export const updateDocWithNewTriangle = (x1: number, y1: number, x2: number, y2: number, x3: number, y3: number) => {
+export function updateDocWithNewTriangle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): void {
+ console.log('Adding triangle:', { x1, y1, x2, y2, x3, y3 }); // Debug log
handle.change((doc: AppDocument) => {
const triangle: TriangleShape = {
id: Date.now(),
@@ -64,6 +63,9 @@ export const updateDocWithNewTriangle = (x1: number, y1: number, x2: number, y2:
],
color: "blue"
};
+ if (!doc.shapes) {
+ doc.shapes = [];
+ }
doc.shapes.push(triangle);
});
}
diff --git a/src/main.ts b/src/main.ts
index a06cd91..7e993da 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,116 +1,15 @@
-import { initRepo, updateDocWithNewCircle, updateDocWithNewTriangle, updateDocWithShapeMove } from "./docManager";
-import { createOrUpdateShapes } from "./canvasManager";
-import { CircleShape } from "./types";
-
-interface Config {
- THROTTLE_MS: number;
- DEFAULT_SHAPES: {
- CIRCLE: Omit;
- TRIANGLE: {
- x1: number;
- y1: number;
- x2: number;
- y2: number;
- x3: number;
- y3: number;
- };
- };
-}
-
-const CONFIG: Config = {
- THROTTLE_MS: 16,
- DEFAULT_SHAPES: {
- CIRCLE: { x: 100, y: 100, radius: 30 },
- TRIANGLE: { x1: 200, y1: 200, x2: 220, y2: 220, x3: 180, y3: 220 }
- }
-};
-
-function initDragAndDrop(container: SVGSVGElement): void {
- let isDragging = false;
- let selectedShapeId: string | null = null;
-
- const throttledMoveShape = throttle((shapeId: string, x: number, y: number) => {
- updateDocWithShapeMove(shapeId, x, y);
- }, CONFIG.THROTTLE_MS);
-
- container.addEventListener("mousedown", (e: MouseEvent) => {
- const target = e.target as SVGElement;
- if (target instanceof SVGCircleElement || target instanceof SVGPolygonElement) {
- isDragging = true;
- selectedShapeId = target.id;
- }
- });
-
- container.addEventListener("mousemove", (e: MouseEvent) => {
- if (!isDragging || !selectedShapeId) return;
-
- const svgPoint = getSVGPoint(container, e.clientX, e.clientY);
- throttledMoveShape(selectedShapeId, svgPoint.x, svgPoint.y);
- });
-
- container.addEventListener("mouseup", () => {
- isDragging = false;
- selectedShapeId = null;
- });
-}
-
-function getSVGPoint(container: SVGSVGElement, x: number, y: number): DOMPoint {
- const pt = container.createSVGPoint();
- pt.x = x;
- pt.y = y;
- const ctm = container.getScreenCTM();
- if (!ctm) {
- throw new Error("Could not get screen CTM");
- }
- return pt.matrixTransform(ctm.inverse());
-}
-
-function throttle void>(func: T, limit: number): T {
- let inThrottle = false;
- return function(this: any, ...args: Parameters) {
- if (!inThrottle) {
- func.apply(this, args);
- inThrottle = true;
- setTimeout(() => inThrottle = false, limit);
- }
- } as T;
-}
-
-async function initApp(): Promise {
- const container = document.querySelector("#shapesCanvas") as SVGSVGElement;
- if (!container) throw new Error("Canvas container not found");
+import Canvas from './components/Canvas.svelte';
+import { initRepo } from './docManager';
+import { mount } from 'svelte';
+async function initApp() {
const handle = await initRepo();
-
- const doc = handle.docSync();
- if (!doc) throw new Error("Failed to sync document");
-
- createOrUpdateShapes(container, doc.shapes);
-
- handle.on("change", (change) => {
- createOrUpdateShapes(container, change.doc.shapes, change.patches);
- });
-
- initShapeButtons();
- initDragAndDrop(container);
-}
-
-function initShapeButtons(): void {
- const circleButton = document.querySelector("#addCircleButton") as HTMLElement;
- const triangleButton = document.querySelector("#addTriangleButton") as HTMLElement;
-
- if (!circleButton || !triangleButton) {
- throw new Error("Shape buttons not found");
- }
-
- circleButton.addEventListener("click", () => {
- const { x, y, radius } = CONFIG.DEFAULT_SHAPES.CIRCLE;
- updateDocWithNewCircle(x, y, radius);
- });
-
- triangleButton.addEventListener("click", () => {
- const { x1, y1, x2, y2, x3, y3 } = CONFIG.DEFAULT_SHAPES.TRIANGLE;
- updateDocWithNewTriangle(x1, y1, x2, y2, x3, y3);
+
+ mount(Canvas, {
+ target: document.getElementById('app')!,
+ props: {
+ handle
+ }
});
}
diff --git a/vite.config.ts b/vite.config.ts
index 416f532..ab10530 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,6 +1,7 @@
import { defineConfig } from "vite"
+import { svelte } from '@sveltejs/vite-plugin-svelte'
import wasm from "vite-plugin-wasm"
-import topLevelAwait from 'vite-plugin-top-level-await'
+import topLevelAwait from "vite-plugin-top-level-await"
export default defineConfig({
// customize this to your repo name for github pages deploy
@@ -10,10 +11,14 @@ export default defineConfig({
target: "esnext",
},
- plugins: [wasm(), topLevelAwait()],
+ plugins: [
+ wasm(),
+ topLevelAwait(),
+ svelte()
+ ],
worker: {
format: "es",
- plugins: () => [wasm()],
+ plugins: () => [svelte()],
},
})