@pascal-app/viewer 0.1.1 → 0.1.3

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.
Files changed (84) hide show
  1. package/dist/components/renderers/building/building-renderer.d.ts +5 -0
  2. package/dist/components/renderers/building/building-renderer.d.ts.map +1 -0
  3. package/dist/components/renderers/building/building-renderer.js +11 -0
  4. package/dist/components/renderers/ceiling/ceiling-renderer.d.ts +5 -0
  5. package/dist/components/renderers/ceiling/ceiling-renderer.d.ts.map +1 -0
  6. package/dist/components/renderers/ceiling/ceiling-renderer.js +24 -0
  7. package/dist/components/renderers/guide/guide-renderer.d.ts +5 -0
  8. package/dist/components/renderers/guide/guide-renderer.d.ts.map +1 -0
  9. package/dist/components/renderers/guide/guide-renderer.js +36 -0
  10. package/dist/components/renderers/item/item-renderer.d.ts +5 -0
  11. package/dist/components/renderers/item/item-renderer.d.ts.map +1 -0
  12. package/dist/components/renderers/item/item-renderer.js +70 -0
  13. package/dist/components/renderers/level/level-renderer.d.ts +5 -0
  14. package/dist/components/renderers/level/level-renderer.d.ts.map +1 -0
  15. package/dist/components/renderers/level/level-renderer.js +11 -0
  16. package/dist/components/renderers/node-renderer.d.ts +5 -0
  17. package/dist/components/renderers/node-renderer.d.ts.map +1 -0
  18. package/dist/components/renderers/node-renderer.js +19 -0
  19. package/dist/components/renderers/roof/roof-renderer.d.ts +5 -0
  20. package/dist/components/renderers/roof/roof-renderer.d.ts.map +1 -0
  21. package/dist/components/renderers/roof/roof-renderer.js +10 -0
  22. package/dist/components/renderers/scan/scan-renderer.d.ts +5 -0
  23. package/dist/components/renderers/scan/scan-renderer.d.ts.map +1 -0
  24. package/dist/components/renderers/scan/scan-renderer.js +50 -0
  25. package/dist/components/renderers/scene-renderer.d.ts +2 -0
  26. package/dist/components/renderers/scene-renderer.d.ts.map +1 -0
  27. package/dist/components/renderers/scene-renderer.js +8 -0
  28. package/dist/components/renderers/slab/slab-renderer.d.ts +5 -0
  29. package/dist/components/renderers/slab/slab-renderer.d.ts.map +1 -0
  30. package/dist/components/renderers/slab/slab-renderer.js +10 -0
  31. package/dist/components/renderers/wall/wall-renderer.d.ts +5 -0
  32. package/dist/components/renderers/wall/wall-renderer.d.ts.map +1 -0
  33. package/dist/components/renderers/wall/wall-renderer.js +11 -0
  34. package/dist/components/renderers/zone/zone-renderer.d.ts +5 -0
  35. package/dist/components/renderers/zone/zone-renderer.d.ts.map +1 -0
  36. package/dist/components/renderers/zone/zone-renderer.js +154 -0
  37. package/dist/components/viewer/index.d.ts +13 -0
  38. package/dist/components/viewer/index.d.ts.map +1 -0
  39. package/dist/components/viewer/index.js +29 -0
  40. package/dist/components/viewer/lights.d.ts +2 -0
  41. package/dist/components/viewer/lights.d.ts.map +1 -0
  42. package/dist/components/viewer/lights.js +10 -0
  43. package/dist/components/viewer/post-processing.d.ts +17 -0
  44. package/dist/components/viewer/post-processing.d.ts.map +1 -0
  45. package/dist/components/viewer/post-processing.js +139 -0
  46. package/dist/components/viewer/selection-manager.d.ts +2 -0
  47. package/dist/components/viewer/selection-manager.d.ts.map +1 -0
  48. package/dist/components/viewer/selection-manager.js +279 -0
  49. package/dist/components/viewer/viewer-camera.d.ts +2 -0
  50. package/dist/components/viewer/viewer-camera.d.ts.map +1 -0
  51. package/dist/components/viewer/viewer-camera.js +7 -0
  52. package/dist/hooks/use-asset-url.d.ts +6 -0
  53. package/dist/hooks/use-asset-url.d.ts.map +1 -0
  54. package/dist/hooks/use-asset-url.js +21 -0
  55. package/dist/hooks/use-gltf-ktx2.d.ts +4 -0
  56. package/dist/hooks/use-gltf-ktx2.d.ts.map +1 -0
  57. package/dist/hooks/use-gltf-ktx2.js +16 -0
  58. package/dist/hooks/use-grid-events.d.ts +12 -0
  59. package/dist/hooks/use-grid-events.d.ts.map +1 -0
  60. package/dist/hooks/use-grid-events.js +33 -0
  61. package/dist/hooks/use-node-events.d.ts +49 -0
  62. package/dist/hooks/use-node-events.d.ts.map +1 -0
  63. package/dist/hooks/use-node-events.js +38 -0
  64. package/dist/index.d.ts +4 -81
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +3 -19168
  67. package/dist/store/use-viewer.d.ts +35 -0
  68. package/dist/store/use-viewer.d.ts.map +1 -0
  69. package/dist/store/use-viewer.js +46 -0
  70. package/dist/systems/guide/guide-system.d.ts +2 -0
  71. package/dist/systems/guide/guide-system.d.ts.map +1 -0
  72. package/dist/systems/guide/guide-system.js +16 -0
  73. package/dist/systems/level/level-system.d.ts +2 -0
  74. package/dist/systems/level/level-system.d.ts.map +1 -0
  75. package/dist/systems/level/level-system.js +23 -0
  76. package/dist/systems/scan/scan-system.d.ts +2 -0
  77. package/dist/systems/scan/scan-system.d.ts.map +1 -0
  78. package/dist/systems/scan/scan-system.js +16 -0
  79. package/dist/systems/wall/wall-cutout.d.ts +2 -0
  80. package/dist/systems/wall/wall-cutout.d.ts.map +1 -0
  81. package/dist/systems/wall/wall-cutout.js +103 -0
  82. package/package.json +36 -32
  83. package/dist/index.js.map +0 -1
  84. package/types.d.ts +0 -81
@@ -0,0 +1,35 @@
1
+ import type { AnyNode, BaseNode, BuildingNode, LevelNode, ZoneNode } from "@pascal-app/core";
2
+ import type { Object3D } from "three";
3
+ type SelectionPath = {
4
+ buildingId: BuildingNode["id"] | null;
5
+ levelId: LevelNode["id"] | null;
6
+ zoneId: ZoneNode["id"] | null;
7
+ selectedIds: BaseNode["id"][];
8
+ };
9
+ type Outliner = {
10
+ selectedObjects: Object3D[];
11
+ hoveredObjects: Object3D[];
12
+ };
13
+ type ViewerState = {
14
+ selection: SelectionPath;
15
+ hoveredId: AnyNode['id'] | ZoneNode['id'] | null;
16
+ setHoveredId: (id: AnyNode['id'] | ZoneNode['id'] | null) => void;
17
+ cameraMode: 'perspective' | 'orthographic';
18
+ setCameraMode: (mode: 'perspective' | 'orthographic') => void;
19
+ levelMode: 'stacked' | 'exploded' | 'solo' | 'manual';
20
+ setLevelMode: (mode: 'stacked' | 'exploded' | 'solo' | 'manual') => void;
21
+ wallMode: 'up' | 'cutaway' | 'down';
22
+ setWallMode: (mode: 'up' | 'cutaway' | 'down') => void;
23
+ showScans: boolean;
24
+ setShowScans: (show: boolean) => void;
25
+ showGuides: boolean;
26
+ setShowGuides: (show: boolean) => void;
27
+ setSelection: (updates: Partial<SelectionPath>) => void;
28
+ resetSelection: () => void;
29
+ outliner: Outliner;
30
+ exportScene: (() => Promise<void>) | null;
31
+ setExportScene: (fn: (() => Promise<void>) | null) => void;
32
+ };
33
+ declare const useViewer: import("zustand").UseBoundStore<import("zustand").StoreApi<ViewerState>>;
34
+ export default useViewer;
35
+ //# sourceMappingURL=use-viewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-viewer.d.ts","sourceRoot":"","sources":["../../src/store/use-viewer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,QAAQ,EACT,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAItC,KAAK,aAAa,GAAG;IACnB,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACtC,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;CAC/B,CAAC;AAEF,KAAK,QAAQ,GAAG;IACd,eAAe,EAAE,QAAQ,EAAE,CAAC;IAC5B,cAAc,EAAE,QAAQ,EAAE,CAAC;CAC5B,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,SAAS,EAAE,aAAa,CAAA;IACxB,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAChD,YAAY,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,IAAI,CAAA;IAEjE,UAAU,EAAE,aAAa,GAAG,cAAc,CAAA;IAC1C,aAAa,EAAE,CAAC,IAAI,EAAE,aAAa,GAAG,cAAc,KAAK,IAAI,CAAA;IAE7D,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAA;IACrD,YAAY,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,KAAK,IAAI,CAAA;IAExE,QAAQ,EAAE,IAAI,GAAG,SAAS,GAAG,MAAM,CAAA;IACnC,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,GAAG,MAAM,KAAK,IAAI,CAAA;IAEtD,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAErC,UAAU,EAAE,OAAO,CAAA;IACnB,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAGtC,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAA;IACvD,cAAc,EAAE,MAAM,IAAI,CAAA;IAE1B,QAAQ,EAAE,QAAQ,CAAA;IAGlB,WAAW,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAA;IACzC,cAAc,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,CAAA;CAC3D,CAAA;AAED,QAAA,MAAM,SAAS,0EAqDZ,CAAC;AAEJ,eAAe,SAAS,CAAC"}
@@ -0,0 +1,46 @@
1
+ "use client";
2
+ import { create } from "zustand";
3
+ const useViewer = create()((set, get) => ({
4
+ selection: { buildingId: null, levelId: null, zoneId: null, selectedIds: [] },
5
+ hoveredId: null,
6
+ setHoveredId: (id) => set({ hoveredId: id }),
7
+ cameraMode: "perspective",
8
+ setCameraMode: (mode) => set({ cameraMode: mode }),
9
+ levelMode: "stacked",
10
+ setLevelMode: (mode) => set({ levelMode: mode }),
11
+ wallMode: 'cutaway',
12
+ setWallMode: (mode) => set({ wallMode: mode }),
13
+ showScans: true,
14
+ setShowScans: (show) => set({ showScans: show }),
15
+ showGuides: true,
16
+ setShowGuides: (show) => set({ showGuides: show }),
17
+ setSelection: (updates) => set((state) => {
18
+ const newSelection = { ...state.selection, ...updates };
19
+ // Hierarchy Guard: If we change a high-level parent, reset the children
20
+ if (updates.buildingId !== undefined) {
21
+ newSelection.levelId = null;
22
+ newSelection.zoneId = null;
23
+ newSelection.selectedIds = [];
24
+ }
25
+ else if (updates.levelId !== undefined) {
26
+ newSelection.zoneId = null;
27
+ newSelection.selectedIds = [];
28
+ }
29
+ else if (updates.zoneId !== undefined) {
30
+ newSelection.selectedIds = [];
31
+ }
32
+ return { selection: newSelection };
33
+ }),
34
+ resetSelection: () => set({
35
+ selection: {
36
+ buildingId: null,
37
+ levelId: null,
38
+ zoneId: null,
39
+ selectedIds: [],
40
+ },
41
+ }),
42
+ outliner: { selectedObjects: [], hoveredObjects: [] },
43
+ exportScene: null,
44
+ setExportScene: (fn) => set({ exportScene: fn }),
45
+ }));
46
+ export default useViewer;
@@ -0,0 +1,2 @@
1
+ export declare const GuideSystem: () => null;
2
+ //# sourceMappingURL=guide-system.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guide-system.d.ts","sourceRoot":"","sources":["../../../src/systems/guide/guide-system.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,YAavB,CAAA"}
@@ -0,0 +1,16 @@
1
+ import { sceneRegistry } from '@pascal-app/core';
2
+ import { useEffect } from 'react';
3
+ import useViewer from '../../store/use-viewer';
4
+ export const GuideSystem = () => {
5
+ const showGuides = useViewer((state) => state.showGuides);
6
+ useEffect(() => {
7
+ const guides = sceneRegistry.byType.guide || new Set();
8
+ guides.forEach((guideId) => {
9
+ const node = sceneRegistry.nodes.get(guideId);
10
+ if (node) {
11
+ node.visible = showGuides;
12
+ }
13
+ });
14
+ }, [showGuides]);
15
+ return null;
16
+ };
@@ -0,0 +1,2 @@
1
+ export declare const LevelSystem: () => null;
2
+ //# sourceMappingURL=level-system.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"level-system.d.ts","sourceRoot":"","sources":["../../../src/systems/level/level-system.tsx"],"names":[],"mappings":"AAQA,eAAO,MAAM,WAAW,YAkBvB,CAAA"}
@@ -0,0 +1,23 @@
1
+ import { sceneRegistry, useScene } from '@pascal-app/core';
2
+ import { useFrame } from '@react-three/fiber';
3
+ import { lerp } from 'three/src/math/MathUtils.js';
4
+ import useViewer from '../../store/use-viewer';
5
+ const LEVEL_HEIGHT = 2.5;
6
+ const EXPLODED_GAP = 5;
7
+ export const LevelSystem = () => {
8
+ useFrame((_, delta) => {
9
+ const levelMode = useViewer.getState().levelMode;
10
+ const selectedLevel = useViewer.getState().selection.levelId;
11
+ sceneRegistry.byType.level.forEach((levelId) => {
12
+ const obj = sceneRegistry.nodes.get(levelId);
13
+ if (obj) {
14
+ const level = useScene.getState().nodes[levelId];
15
+ const targetY = (level.level || 0) *
16
+ (LEVEL_HEIGHT + (levelMode === 'exploded' ? EXPLODED_GAP : 0));
17
+ obj.position.y = lerp(obj.position.y, targetY, delta * 3);
18
+ obj.visible = levelMode !== 'solo' || level?.id === selectedLevel || !selectedLevel;
19
+ }
20
+ });
21
+ });
22
+ return null;
23
+ };
@@ -0,0 +1,2 @@
1
+ export declare const ScanSystem: () => null;
2
+ //# sourceMappingURL=scan-system.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-system.d.ts","sourceRoot":"","sources":["../../../src/systems/scan/scan-system.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,YAatB,CAAA"}
@@ -0,0 +1,16 @@
1
+ import { sceneRegistry } from '@pascal-app/core';
2
+ import { useEffect } from 'react';
3
+ import useViewer from '../../store/use-viewer';
4
+ export const ScanSystem = () => {
5
+ const showScans = useViewer((state) => state.showScans);
6
+ useEffect(() => {
7
+ const scans = sceneRegistry.byType.scan || new Set();
8
+ scans.forEach((scanId) => {
9
+ const node = sceneRegistry.nodes.get(scanId);
10
+ if (node) {
11
+ node.visible = showScans;
12
+ }
13
+ });
14
+ }, [showScans]);
15
+ return null;
16
+ };
@@ -0,0 +1,2 @@
1
+ export declare const WallCutout: () => null;
2
+ //# sourceMappingURL=wall-cutout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wall-cutout.d.ts","sourceRoot":"","sources":["../../../src/systems/wall/wall-cutout.tsx"],"names":[],"mappings":"AAgDA,eAAO,MAAM,UAAU,YAkEtB,CAAA"}
@@ -0,0 +1,103 @@
1
+ import { sceneRegistry, useScene } from '@pascal-app/core';
2
+ import { useFrame } from '@react-three/fiber';
3
+ import { useRef } from 'react';
4
+ import { Fn, float, fract, length, mix, positionLocal, smoothstep, step, vec2 } from 'three/tsl';
5
+ import { MeshStandardNodeMaterial, Vector3 } from 'three/webgpu';
6
+ import useViewer from '../../store/use-viewer';
7
+ const tmpVec = new Vector3();
8
+ const u = new Vector3();
9
+ const v = new Vector3();
10
+ // Dot pattern shader
11
+ const dotPattern = Fn(() => {
12
+ // Create a repeating grid pattern based on world position
13
+ const scale = float(0.1); // Dot grid spacing (10cm)
14
+ const dotSize = float(0.3); // Size of dots relative to grid
15
+ // Use XY coordinates for pattern on wall face
16
+ const uv = vec2(positionLocal.x, positionLocal.y).div(scale);
17
+ const gridUV = fract(uv);
18
+ // Distance from center of grid cell (creates circular dots)
19
+ const dist = length(gridUV.sub(0.5));
20
+ // Create dots: 1 where we want dots, 0 elsewhere
21
+ const dots = step(dist, dotSize.mul(0.5));
22
+ // Vertical fade: fade out as Y increases (from bottom to top)
23
+ const fadeHeight = float(2.5); // Fade over 2.5 meters
24
+ const yFade = float(1).sub(smoothstep(float(0), fadeHeight, positionLocal.y));
25
+ return dots.mul(yFade);
26
+ });
27
+ const invsibleWallMaterial = new MeshStandardNodeMaterial({
28
+ transparent: true,
29
+ opacityNode: mix(float(0.0), float(0.24), dotPattern()),
30
+ color: 'white',
31
+ depthWrite: false,
32
+ emissive: 'white',
33
+ });
34
+ const wallMaterial = new MeshStandardNodeMaterial({
35
+ color: 'white',
36
+ roughness: 1,
37
+ metalness: 0,
38
+ });
39
+ export const WallCutout = () => {
40
+ const lastCameraPosition = useRef(new Vector3());
41
+ const lastCameraTarget = useRef(new Vector3());
42
+ const lastUpdateTime = useRef(0);
43
+ const lastWallMode = useRef(useViewer.getState().wallMode);
44
+ const lastNumberOfWalls = useRef(0);
45
+ useFrame(({ camera, clock }) => {
46
+ const wallMode = useViewer.getState().wallMode;
47
+ const currentTime = clock.elapsedTime;
48
+ const currentCameraPosition = camera.position;
49
+ camera.getWorldDirection(tmpVec);
50
+ tmpVec.add(currentCameraPosition);
51
+ // Throttle: only update if camera moved significantly AND enough time passed
52
+ const distanceMoved = currentCameraPosition.distanceTo(lastCameraPosition.current);
53
+ const directionChanged = tmpVec.distanceTo(lastCameraTarget.current);
54
+ const timeSinceUpdate = currentTime - lastUpdateTime.current;
55
+ // Update if moved > 0.5m OR direction changed > 0.3 AND at least 100ms passed
56
+ if (((distanceMoved > 0.5 || directionChanged > 0.3) && timeSinceUpdate > 0.1) ||
57
+ lastWallMode.current !== wallMode ||
58
+ sceneRegistry.byType.wall.size !== lastNumberOfWalls.current) {
59
+ // Camera has moved, update cutout logic here
60
+ // Update last known positions and time
61
+ lastCameraPosition.current.copy(currentCameraPosition);
62
+ lastCameraTarget.current.copy(tmpVec);
63
+ lastUpdateTime.current = currentTime;
64
+ camera.getWorldDirection(u);
65
+ const walls = sceneRegistry.byType.wall;
66
+ walls.forEach((wallId) => {
67
+ const wallMesh = sceneRegistry.nodes.get(wallId);
68
+ if (!wallMesh)
69
+ return;
70
+ const wallNode = useScene.getState().nodes[wallId];
71
+ if (!wallNode || wallNode.type !== 'wall')
72
+ return;
73
+ let hideWall = wallNode.frontSide === 'interior' && wallNode.backSide === 'interior';
74
+ if (wallMode === 'up') {
75
+ hideWall = false;
76
+ }
77
+ else if (wallMode === 'down') {
78
+ hideWall = true;
79
+ }
80
+ else {
81
+ wallMesh.getWorldDirection(v);
82
+ if (v.dot(u) < 0) {
83
+ // Front side
84
+ if (wallNode.frontSide === 'exterior' && wallNode.backSide !== 'exterior') {
85
+ hideWall = true;
86
+ }
87
+ }
88
+ else {
89
+ // Back side
90
+ if (wallNode.backSide === 'exterior' && wallNode.frontSide !== 'exterior') {
91
+ hideWall = true;
92
+ }
93
+ }
94
+ }
95
+ ;
96
+ wallMesh.material = hideWall ? invsibleWallMaterial : wallMaterial;
97
+ });
98
+ lastWallMode.current = wallMode;
99
+ lastNumberOfWalls.current = sceneRegistry.byType.wall.size;
100
+ }
101
+ });
102
+ return null;
103
+ };
package/package.json CHANGED
@@ -1,51 +1,55 @@
1
1
  {
2
2
  "name": "@pascal-app/viewer",
3
- "version": "0.1.1",
4
- "description": "React Three Fiber component for viewing Pascal 3D scenes",
5
- "private": false,
3
+ "version": "0.1.3",
4
+ "description": "3D viewer component for Pascal building editor",
6
5
  "type": "module",
7
6
  "main": "./dist/index.js",
8
- "module": "./dist/index.js",
9
7
  "types": "./dist/index.d.ts",
10
8
  "exports": {
11
9
  ".": {
10
+ "types": "./dist/index.d.ts",
12
11
  "import": "./dist/index.js",
13
- "types": "./dist/index.d.ts"
12
+ "default": "./dist/index.js"
14
13
  }
15
14
  },
16
15
  "files": [
17
16
  "dist",
18
- "types.d.ts"
17
+ "README.md"
19
18
  ],
20
- "sideEffects": false,
21
19
  "scripts": {
22
- "build": "tsup",
23
- "dev": "tsup --watch",
24
- "typecheck": "tsc --noEmit"
25
- },
26
- "dependencies": {
27
- "@react-spring/three": "^10.0.0",
28
- "@react-three/csg": "^4.0.0",
29
- "@react-three/uikit": "^1.0.0",
30
- "clsx": "^2.1.1",
31
- "immer": "^10.2.0",
32
- "mitt": "^3.0.1",
33
- "nanoid": "^5.1.6",
34
- "tailwind-merge": "^3.4.0",
35
- "three-custom-shader-material": "^6.1.0",
36
- "zod": "^4.2.1",
37
- "zustand": "^5.0.9"
20
+ "build": "tsc --declaration --emitDeclarationOnly && tsc",
21
+ "prepublishOnly": "npm run build"
38
22
  },
39
23
  "peerDependencies": {
40
- "react": "^19.0.0",
41
- "react-dom": "^19.0.0",
42
- "three": ">=0.156",
43
- "@react-three/fiber": ">=9.0.0",
44
- "@react-three/drei": ">=10.0.0"
24
+ "@pascal-app/core": "^0.1.3",
25
+ "@react-three/drei": "^10",
26
+ "@react-three/fiber": "^9",
27
+ "react": "^18 || ^19",
28
+ "three": "^0.182"
29
+ },
30
+ "dependencies": {
31
+ "zustand": "^5"
45
32
  },
46
33
  "devDependencies": {
47
- "@pascal/core": "0.1.0",
48
- "@types/react": "^19.0.0",
49
- "tsup": "^8.5.1"
50
- }
34
+ "@repo/typescript-config": "*",
35
+ "@types/react": "^19.2.2",
36
+ "typescript": "5.9.2",
37
+ "@types/three": "^0.182.0"
38
+ },
39
+ "keywords": [
40
+ "3d",
41
+ "building",
42
+ "editor",
43
+ "viewer",
44
+ "architecture",
45
+ "webgpu",
46
+ "three.js",
47
+ "react-three-fiber"
48
+ ],
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "https://github.com/your-username/pascal-editor.git",
52
+ "directory": "packages/viewer"
53
+ },
54
+ "license": "MIT"
51
55
  }