@geometra/renderer-three 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Razroo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # @geometra/renderer-three
2
+
3
+ **Three.js helpers alongside Geometra** — not a replacement for `@geometra/renderer-canvas`. Geometra’s WebSocket geometry protocol still drives the 2D canvas; Three.js owns WebGL for meshes, scenes, and cameras.
4
+
5
+ This package ships the **split-view host** pattern (Three.js pane + Geometra pane) as one bootstrap, plus small WebGL sizing utilities.
6
+
7
+ ## Install
8
+
9
+ Peer dependencies (your app must install them):
10
+
11
+ ```bash
12
+ npm install three @geometra/renderer-canvas @geometra/client @geometra/core
13
+ npm install @geometra/renderer-three
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```ts
19
+ import * as THREE from 'three'
20
+ import { createThreeGeometraSplitHost } from '@geometra/renderer-three'
21
+
22
+ const host = createThreeGeometraSplitHost({
23
+ container: document.getElementById('app')!,
24
+ geometraWidth: 420,
25
+ url: 'ws://localhost:8080/geometra-ws',
26
+ binaryFraming: true,
27
+ autoFocus: true,
28
+ threeBackground: 0x07131f,
29
+ onThreeReady: ({ scene, camera }) => {
30
+ scene.add(new THREE.AmbientLight(0xffffff, 0.6))
31
+ camera.position.set(0, 2, 8)
32
+ },
33
+ onThreeFrame: ({ scene, camera, delta }) => {
34
+ // animate meshes, controls.update(), etc.
35
+ },
36
+ })
37
+
38
+ // later
39
+ host.destroy()
40
+ ```
41
+
42
+ `createThreeGeometraSplitHost` forwards all [`createBrowserCanvasClient`](https://github.com/razroo/geometra/tree/main/packages/renderer-canvas) options except `canvas` (it creates the Geometra canvas for you).
43
+
44
+ ### Geometra resize
45
+
46
+ The Geometra thin client listens to `window` resize by default. When only the Geometra column changes size, this host dispatches a synthetic `window` `resize` after layout so server layout width/height stay in sync.
47
+
48
+ ## Roadmap (not in v0)
49
+
50
+ - Optional **scene-graph extension** to the GEOM protocol (headless + WebGL from the same JSON).
51
+ - **Stacked** overlay (full-viewport WebGL + partial Geometra HUD) with explicit pointer routing.
52
+ - **Node / headless Three** helpers for parity with “AI talks the same protocol” stories.
53
+
54
+ ## Releasing (GitHub + npm)
55
+
56
+ Same pattern as [`geometra-auth`](https://github.com/razroo/geometra-auth): publishing runs when a **GitHub Release is published**, not on every tag push.
57
+
58
+ 1. **Repository secret:** add **`NPM_TOKEN`** (automation token with publish rights for `@geometra/renderer-three`) under **Settings → Secrets and variables → Actions**.
59
+
60
+ 2. **Version:** set `"version"` in `package.json` to the release you want (e.g. `0.2.0`), commit, and push to `main`.
61
+
62
+ 3. **Tag** must match that version with a `v` prefix:
63
+
64
+ ```bash
65
+ git tag v0.2.0
66
+ git push origin v0.2.0
67
+ ```
68
+
69
+ 4. **Create the GitHub release** (triggers [`.github/workflows/release.yml`](.github/workflows/release.yml)):
70
+
71
+ ```bash
72
+ gh release create v0.2.0 --repo razroo/geometra-renderer-three --title "v0.2.0" --generate-notes
73
+ ```
74
+
75
+ Or publish a **draft** release from the web UI, then **Publish release** when ready.
76
+
77
+ The workflow checks that `v$TAG` matches `package.json`, runs `npm ci` / `npm run build`, then **`npm publish --provenance --access public`**.
78
+
79
+ ## License
80
+
81
+ MIT
@@ -0,0 +1,3 @@
1
+ export { createThreeGeometraSplitHost, type ThreeGeometraSplitHostHandle, type ThreeGeometraSplitHostOptions, type ThreeFrameContext, type ThreeRuntimeContext, } from './split-host.js';
2
+ export { setWebGLDrawingBufferSize } from './utils.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,KAAK,4BAA4B,EACjC,KAAK,6BAA6B,EAClC,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { createThreeGeometraSplitHost, } from './split-host.js';
2
+ export { setWebGLDrawingBufferSize } from './utils.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,GAK7B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,64 @@
1
+ import * as THREE from 'three';
2
+ import { type BrowserCanvasClientHandle, type BrowserCanvasClientOptions } from '@geometra/renderer-canvas';
3
+ export interface ThreeGeometraSplitHostOptions extends Omit<BrowserCanvasClientOptions, 'canvas'> {
4
+ /** Host element; a flex row is appended as a child (existing children are left untouched). */
5
+ container: HTMLElement;
6
+ /** Geometra column width in CSS pixels. Default: 420. */
7
+ geometraWidth?: number;
8
+ /** When true, Geometra panel is on the left. Default: false (Three.js left, Geometra right). */
9
+ geometraOnLeft?: boolean;
10
+ /** Clear color for the Three.js scene. Default: `0x000000`. */
11
+ threeBackground?: THREE.ColorRepresentation;
12
+ /** Perspective camera FOV in degrees. Default: 50. */
13
+ cameraFov?: number;
14
+ /** Near plane. Default: 0.1. */
15
+ cameraNear?: number;
16
+ /** Far plane. Default: 2000. */
17
+ cameraFar?: number;
18
+ /** Initial camera position. Default: `(0, 0, 5)`. */
19
+ cameraPosition?: THREE.Vector3Tuple;
20
+ /**
21
+ * Called once after scene, camera, and renderer are created.
22
+ * Add meshes, lights, controls, etc.
23
+ */
24
+ onThreeReady?: (ctx: ThreeRuntimeContext) => void;
25
+ /**
26
+ * Called every frame before `renderer.render`.
27
+ * Use for animations; return nothing.
28
+ */
29
+ onThreeFrame?: (ctx: ThreeFrameContext) => void;
30
+ }
31
+ export interface ThreeRuntimeContext {
32
+ renderer: THREE.WebGLRenderer;
33
+ scene: THREE.Scene;
34
+ camera: THREE.PerspectiveCamera;
35
+ threeCanvas: HTMLCanvasElement;
36
+ }
37
+ export interface ThreeFrameContext extends ThreeRuntimeContext {
38
+ clock: THREE.Clock;
39
+ delta: number;
40
+ elapsed: number;
41
+ }
42
+ export interface ThreeGeometraSplitHostHandle {
43
+ root: HTMLDivElement;
44
+ threePanel: HTMLDivElement;
45
+ geometraPanel: HTMLDivElement;
46
+ threeCanvas: HTMLCanvasElement;
47
+ geometraCanvas: HTMLCanvasElement;
48
+ renderer: THREE.WebGLRenderer;
49
+ scene: THREE.Scene;
50
+ camera: THREE.PerspectiveCamera;
51
+ clock: THREE.Clock;
52
+ geometra: BrowserCanvasClientHandle;
53
+ /** Stops the render loop, disconnects observers, disposes WebGL, and tears down the Geometra client. */
54
+ destroy(): void;
55
+ }
56
+ /**
57
+ * Side-by-side host: Three.js `WebGLRenderer` on one flex pane and Geometra’s streamed canvas UI on the other.
58
+ *
59
+ * This is the recommended **hybrid** layout: 3D stays in Three; chrome and data panes stay in Geometra’s protocol.
60
+ * Geometra’s client still uses `resizeTarget: window` by default; when only the Geometra column changes size,
61
+ * a `ResizeObserver` dispatches a synthetic `resize` on `window` so layout width/height track the panel.
62
+ */
63
+ export declare function createThreeGeometraSplitHost(options: ThreeGeometraSplitHostOptions): ThreeGeometraSplitHostHandle;
64
+ //# sourceMappingURL=split-host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split-host.d.ts","sourceRoot":"","sources":["../src/split-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAChC,MAAM,2BAA2B,CAAA;AAElC,MAAM,WAAW,6BAA8B,SAAQ,IAAI,CAAC,0BAA0B,EAAE,QAAQ,CAAC;IAC/F,8FAA8F;IAC9F,SAAS,EAAE,WAAW,CAAA;IACtB,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,gGAAgG;IAChG,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,+DAA+D;IAC/D,eAAe,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAA;IAC3C,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qDAAqD;IACrD,cAAc,CAAC,EAAE,KAAK,CAAC,YAAY,CAAA;IACnC;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,IAAI,CAAA;IACjD;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,IAAI,CAAA;CAChD;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAA;IAC7B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAA;IAClB,MAAM,EAAE,KAAK,CAAC,iBAAiB,CAAA;IAC/B,WAAW,EAAE,iBAAiB,CAAA;CAC/B;AAED,MAAM,WAAW,iBAAkB,SAAQ,mBAAmB;IAC5D,KAAK,EAAE,KAAK,CAAC,KAAK,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,cAAc,CAAA;IACpB,UAAU,EAAE,cAAc,CAAA;IAC1B,aAAa,EAAE,cAAc,CAAA;IAC7B,WAAW,EAAE,iBAAiB,CAAA;IAC9B,cAAc,EAAE,iBAAiB,CAAA;IACjC,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAA;IAC7B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAA;IAClB,MAAM,EAAE,KAAK,CAAC,iBAAiB,CAAA;IAC/B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAA;IAClB,QAAQ,EAAE,yBAAyB,CAAA;IACnC,wGAAwG;IACxG,OAAO,IAAI,IAAI,CAAA;CAChB;AAgBD;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,6BAA6B,GACrC,4BAA4B,CAgJ9B"}
@@ -0,0 +1,135 @@
1
+ import * as THREE from 'three';
2
+ import { createBrowserCanvasClient, } from '@geometra/renderer-canvas';
3
+ function panelStyle(el, flex) {
4
+ el.style.flex = flex;
5
+ el.style.minWidth = '0';
6
+ el.style.minHeight = '0';
7
+ el.style.position = 'relative';
8
+ el.style.overflow = 'hidden';
9
+ }
10
+ function fullSizeCanvas(canvas) {
11
+ canvas.style.display = 'block';
12
+ canvas.style.width = '100%';
13
+ canvas.style.height = '100%';
14
+ }
15
+ /**
16
+ * Side-by-side host: Three.js `WebGLRenderer` on one flex pane and Geometra’s streamed canvas UI on the other.
17
+ *
18
+ * This is the recommended **hybrid** layout: 3D stays in Three; chrome and data panes stay in Geometra’s protocol.
19
+ * Geometra’s client still uses `resizeTarget: window` by default; when only the Geometra column changes size,
20
+ * a `ResizeObserver` dispatches a synthetic `resize` on `window` so layout width/height track the panel.
21
+ */
22
+ export function createThreeGeometraSplitHost(options) {
23
+ const { container, geometraWidth = 420, geometraOnLeft = false, threeBackground = 0x000000, cameraFov = 50, cameraNear = 0.1, cameraFar = 2000, cameraPosition = [0, 0, 5], onThreeReady, onThreeFrame, window: providedWindow, ...browserOptions } = options;
24
+ const doc = container.ownerDocument;
25
+ const win = providedWindow ?? doc.defaultView;
26
+ if (!win) {
27
+ throw new Error('createThreeGeometraSplitHost requires a browser window');
28
+ }
29
+ const root = doc.createElement('div');
30
+ root.style.display = 'flex';
31
+ root.style.flexDirection = 'row';
32
+ root.style.width = '100%';
33
+ root.style.height = '100%';
34
+ root.style.minHeight = '0';
35
+ root.style.minWidth = '0';
36
+ container.appendChild(root);
37
+ const threePanel = doc.createElement('div');
38
+ panelStyle(threePanel, '1 1 0%');
39
+ const geometraPanel = doc.createElement('div');
40
+ panelStyle(geometraPanel, '0 0 auto');
41
+ geometraPanel.style.width = `${geometraWidth}px`;
42
+ geometraPanel.style.flexShrink = '0';
43
+ if (geometraOnLeft) {
44
+ root.append(geometraPanel, threePanel);
45
+ }
46
+ else {
47
+ root.append(threePanel, geometraPanel);
48
+ }
49
+ const threeCanvas = doc.createElement('canvas');
50
+ fullSizeCanvas(threeCanvas);
51
+ threePanel.appendChild(threeCanvas);
52
+ const geometraCanvas = doc.createElement('canvas');
53
+ fullSizeCanvas(geometraCanvas);
54
+ geometraPanel.appendChild(geometraCanvas);
55
+ const glRenderer = new THREE.WebGLRenderer({
56
+ canvas: threeCanvas,
57
+ antialias: true,
58
+ alpha: false,
59
+ });
60
+ glRenderer.setPixelRatio(win.devicePixelRatio || 1);
61
+ const scene = new THREE.Scene();
62
+ scene.background = new THREE.Color(threeBackground);
63
+ const camera = new THREE.PerspectiveCamera(cameraFov, 1, cameraNear, cameraFar);
64
+ camera.position.set(cameraPosition[0], cameraPosition[1], cameraPosition[2]);
65
+ const clock = new THREE.Clock();
66
+ const resizeThree = () => {
67
+ const w = Math.max(1, Math.floor(threePanel.clientWidth));
68
+ const h = Math.max(1, Math.floor(threePanel.clientHeight));
69
+ camera.aspect = w / h;
70
+ camera.updateProjectionMatrix();
71
+ glRenderer.setSize(w, h, false);
72
+ };
73
+ resizeThree();
74
+ const geometraHandle = createBrowserCanvasClient({
75
+ ...browserOptions,
76
+ canvas: geometraCanvas,
77
+ window: win,
78
+ });
79
+ const triggerGeometraResize = () => {
80
+ win.requestAnimationFrame(() => {
81
+ win.dispatchEvent(new Event('resize'));
82
+ });
83
+ };
84
+ const roContainer = new ResizeObserver(() => {
85
+ resizeThree();
86
+ triggerGeometraResize();
87
+ });
88
+ roContainer.observe(threePanel);
89
+ roContainer.observe(geometraPanel);
90
+ const ctxBase = {
91
+ renderer: glRenderer,
92
+ scene,
93
+ camera,
94
+ threeCanvas,
95
+ };
96
+ onThreeReady?.(ctxBase);
97
+ let raf = 0;
98
+ let destroyed = false;
99
+ const loop = () => {
100
+ if (destroyed)
101
+ return;
102
+ raf = win.requestAnimationFrame(loop);
103
+ const delta = clock.getDelta();
104
+ const elapsed = clock.elapsedTime;
105
+ onThreeFrame?.({ ...ctxBase, clock, delta, elapsed });
106
+ glRenderer.render(scene, camera);
107
+ };
108
+ raf = win.requestAnimationFrame(loop);
109
+ const destroy = () => {
110
+ if (destroyed)
111
+ return;
112
+ destroyed = true;
113
+ win.cancelAnimationFrame(raf);
114
+ roContainer.disconnect();
115
+ geometraHandle.destroy();
116
+ glRenderer.dispose();
117
+ if (root.parentNode === container) {
118
+ container.removeChild(root);
119
+ }
120
+ };
121
+ return {
122
+ root,
123
+ threePanel,
124
+ geometraPanel,
125
+ threeCanvas,
126
+ geometraCanvas,
127
+ renderer: glRenderer,
128
+ scene,
129
+ camera,
130
+ clock,
131
+ geometra: geometraHandle,
132
+ destroy,
133
+ };
134
+ }
135
+ //# sourceMappingURL=split-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split-host.js","sourceRoot":"","sources":["../src/split-host.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { WebGLRenderer } from 'three';
2
+ /**
3
+ * Resize drawing buffer to match CSS pixel size × device pixel ratio.
4
+ * Use when you manage your own canvas layout (no `renderer.setSize`).
5
+ */
6
+ export declare function setWebGLDrawingBufferSize(renderer: WebGLRenderer, cssWidth: number, cssHeight: number, pixelRatio?: number): void;
7
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAE1C;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,aAAa,EACvB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,GAClB,IAAI,CAKN"}
package/dist/utils.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Resize drawing buffer to match CSS pixel size × device pixel ratio.
3
+ * Use when you manage your own canvas layout (no `renderer.setSize`).
4
+ */
5
+ export function setWebGLDrawingBufferSize(renderer, cssWidth, cssHeight, pixelRatio) {
6
+ const pr = pixelRatio ?? (typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1);
7
+ const w = Math.max(1, Math.floor(cssWidth * pr));
8
+ const h = Math.max(1, Math.floor(cssHeight * pr));
9
+ renderer.setDrawingBufferSize(w, h, pr);
10
+ }
11
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,QAAuB,EACvB,QAAgB,EAChB,SAAiB,EACjB,UAAmB;IAEnB,MAAM,EAAE,GAAG,UAAU,IAAI,CAAC,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC3F,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAA;IAChD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC,CAAA;IACjD,QAAQ,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;AACzC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@geometra/renderer-three",
3
+ "version": "0.1.2",
4
+ "description": "Three.js render target helpers for Geometra — stack WebGL with the geometry-streamed canvas client",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/razroo/geometra-renderer-three"
10
+ },
11
+ "keywords": [
12
+ "geometra",
13
+ "three",
14
+ "three.js",
15
+ "webgl",
16
+ "renderer",
17
+ "dom-free",
18
+ "websocket"
19
+ ],
20
+ "main": "./dist/index.js",
21
+ "types": "./dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.js"
26
+ }
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "README.md",
31
+ "LICENSE"
32
+ ],
33
+ "scripts": {
34
+ "build": "rm -rf dist && tsc -p tsconfig.build.json",
35
+ "check": "tsc --noEmit -p tsconfig.json",
36
+ "release:gate": "npm run check && npm run build",
37
+ "prepare": "npm run build",
38
+ "prepublishOnly": "npm run build"
39
+ },
40
+ "peerDependencies": {
41
+ "@geometra/renderer-canvas": "^1.2.1",
42
+ "three": ">=0.160.0 <0.180.0"
43
+ },
44
+ "devDependencies": {
45
+ "@geometra/client": "^1.2.1",
46
+ "@geometra/renderer-canvas": "^1.2.1",
47
+ "@types/three": "^0.170.0",
48
+ "three": "^0.170.0",
49
+ "typescript": "^6.0.2"
50
+ },
51
+ "overrides": {
52
+ "@geometra/renderer-canvas": {
53
+ "@geometra/client": "^1.2.1"
54
+ }
55
+ }
56
+ }