@pascal-app/viewer 0.8.0 → 0.9.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/dist/components/error-boundary.d.ts +6 -0
- package/dist/components/error-boundary.d.ts.map +1 -1
- package/dist/components/error-boundary.js +6 -0
- package/dist/components/renderers/node-renderer.d.ts +6 -2
- package/dist/components/renderers/node-renderer.d.ts.map +1 -1
- package/dist/components/renderers/node-renderer.js +41 -22
- package/dist/components/renderers/parametric-node-renderer.d.ts +5 -0
- package/dist/components/renderers/parametric-node-renderer.d.ts.map +1 -0
- package/dist/components/renderers/parametric-node-renderer.js +37 -0
- package/dist/components/renderers/scene-renderer.d.ts +1 -1
- package/dist/components/renderers/scene-renderer.d.ts.map +1 -1
- package/dist/components/viewer/bvh-ecctrl.d.ts +77 -0
- package/dist/components/viewer/bvh-ecctrl.d.ts.map +1 -0
- package/dist/components/viewer/bvh-ecctrl.js +552 -0
- package/dist/components/viewer/frame-limiter.d.ts.map +1 -1
- package/dist/components/viewer/frame-limiter.js +39 -4
- package/dist/components/viewer/glb-interactive.d.ts +41 -0
- package/dist/components/viewer/glb-interactive.d.ts.map +1 -0
- package/dist/components/viewer/glb-interactive.js +394 -0
- package/dist/components/viewer/glb-reference-nodes.d.ts +29 -0
- package/dist/components/viewer/glb-reference-nodes.d.ts.map +1 -0
- package/dist/components/viewer/glb-reference-nodes.js +80 -0
- package/dist/components/viewer/glb-replace-instances.d.ts +18 -0
- package/dist/components/viewer/glb-replace-instances.d.ts.map +1 -0
- package/dist/components/viewer/glb-replace-instances.js +61 -0
- package/dist/components/viewer/glb-scene.d.ts +54 -0
- package/dist/components/viewer/glb-scene.d.ts.map +1 -0
- package/dist/components/viewer/glb-scene.js +920 -0
- package/dist/components/viewer/glb-walkthrough-controller.d.ts +12 -0
- package/dist/components/viewer/glb-walkthrough-controller.d.ts.map +1 -0
- package/dist/components/viewer/glb-walkthrough-controller.js +357 -0
- package/dist/components/viewer/index.d.ts +56 -3
- package/dist/components/viewer/index.d.ts.map +1 -1
- package/dist/components/viewer/index.js +280 -65
- package/dist/components/viewer/lights.d.ts +1 -1
- package/dist/components/viewer/lights.d.ts.map +1 -1
- package/dist/components/viewer/lights.js +201 -43
- package/dist/components/viewer/perf-monitor.d.ts +1 -1
- package/dist/components/viewer/perf-monitor.d.ts.map +1 -1
- package/dist/components/viewer/perf-monitor.js +115 -12
- package/dist/components/viewer/post-processing.d.ts +7 -1
- package/dist/components/viewer/post-processing.d.ts.map +1 -1
- package/dist/components/viewer/post-processing.js +395 -63
- package/dist/components/viewer/registered-systems.d.ts +12 -0
- package/dist/components/viewer/registered-systems.d.ts.map +1 -0
- package/dist/components/viewer/registered-systems.js +49 -0
- package/dist/components/viewer/scene-bvh.d.ts +18 -0
- package/dist/components/viewer/scene-bvh.d.ts.map +1 -0
- package/dist/components/viewer/scene-bvh.js +97 -0
- package/dist/components/viewer/scene-bvh.test.d.ts +2 -0
- package/dist/components/viewer/scene-bvh.test.d.ts.map +1 -0
- package/dist/components/viewer/scene-bvh.test.js +13 -0
- package/dist/components/viewer/scene-environment.d.ts +2 -0
- package/dist/components/viewer/scene-environment.d.ts.map +1 -0
- package/dist/components/viewer/scene-environment.js +79 -0
- package/dist/components/viewer/selection-manager.d.ts +1 -1
- package/dist/components/viewer/selection-manager.d.ts.map +1 -1
- package/dist/components/viewer/selection-manager.js +37 -14
- package/dist/components/viewer/viewer-camera.d.ts +1 -1
- package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
- package/dist/components/viewer/walkthrough-controls.d.ts +2 -1
- package/dist/components/viewer/walkthrough-controls.d.ts.map +1 -1
- package/dist/components/viewer/walkthrough-controls.js +20 -0
- package/dist/hooks/use-gltf-ktx2.d.ts.map +1 -1
- package/dist/hooks/use-gltf-ktx2.js +3 -22
- package/dist/hooks/use-node-events.d.ts +6 -74
- package/dist/hooks/use-node-events.d.ts.map +1 -1
- package/dist/hooks/use-node-events.js +28 -8
- package/dist/index.d.ts +48 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +82 -4
- package/dist/lib/backdrop.d.ts +33 -0
- package/dist/lib/backdrop.d.ts.map +1 -0
- package/dist/lib/backdrop.js +92 -0
- package/dist/lib/box-uv.d.ts +13 -0
- package/dist/lib/box-uv.d.ts.map +1 -0
- package/dist/lib/box-uv.js +32 -0
- package/dist/lib/csg-utils.d.ts +10 -0
- package/dist/lib/csg-utils.d.ts.map +1 -0
- package/dist/lib/csg-utils.js +93 -0
- package/dist/lib/csg-utils.test.d.ts +2 -0
- package/dist/lib/csg-utils.test.d.ts.map +1 -0
- package/dist/lib/csg-utils.test.js +45 -0
- package/dist/lib/drawable-geometry.d.ts +21 -0
- package/dist/lib/drawable-geometry.d.ts.map +1 -0
- package/dist/lib/drawable-geometry.js +22 -0
- package/dist/lib/edge-style.d.ts +4 -0
- package/dist/lib/edge-style.d.ts.map +1 -0
- package/dist/lib/edge-style.js +31 -0
- package/dist/lib/gpu-perf.d.ts +4 -0
- package/dist/lib/gpu-perf.d.ts.map +1 -0
- package/dist/lib/gpu-perf.js +23 -0
- package/dist/lib/ink-edges.d.ts +9 -0
- package/dist/lib/ink-edges.d.ts.map +1 -0
- package/dist/lib/ink-edges.js +49 -0
- package/dist/lib/isolation.d.ts +39 -0
- package/dist/lib/isolation.d.ts.map +1 -0
- package/dist/lib/isolation.js +103 -0
- package/dist/lib/ktx2-loader.d.ts +43 -0
- package/dist/lib/ktx2-loader.d.ts.map +1 -0
- package/dist/lib/ktx2-loader.js +136 -0
- package/dist/lib/layers.d.ts +28 -0
- package/dist/lib/layers.d.ts.map +1 -1
- package/dist/lib/layers.js +28 -0
- package/dist/lib/materials.d.ts +38 -15
- package/dist/lib/materials.d.ts.map +1 -1
- package/dist/lib/materials.js +364 -72
- package/dist/lib/merged-outline-node.d.ts.map +1 -1
- package/dist/lib/merged-outline-node.js +7 -0
- package/dist/lib/polygon-union.d.ts +4 -0
- package/dist/lib/polygon-union.d.ts.map +1 -0
- package/dist/lib/polygon-union.js +289 -0
- package/dist/lib/polygon-union.test.d.ts +2 -0
- package/dist/lib/polygon-union.test.d.ts.map +1 -0
- package/dist/lib/polygon-union.test.js +105 -0
- package/dist/lib/scene-themes.d.ts +30 -0
- package/dist/lib/scene-themes.d.ts.map +1 -0
- package/dist/lib/scene-themes.js +202 -0
- package/dist/lib/shadow-only.d.ts +4 -0
- package/dist/lib/shadow-only.d.ts.map +1 -0
- package/dist/lib/shadow-only.js +36 -0
- package/dist/lib/tsl-compat.d.ts +12 -0
- package/dist/lib/tsl-compat.d.ts.map +1 -0
- package/dist/lib/tsl-compat.js +13 -0
- package/dist/store/use-viewer.d.ts +92 -12
- package/dist/store/use-viewer.d.ts.map +1 -1
- package/dist/store/use-viewer.js +201 -6
- package/dist/store/use-viewer.test.d.ts +2 -0
- package/dist/store/use-viewer.test.d.ts.map +1 -0
- package/dist/store/use-viewer.test.js +42 -0
- package/dist/systems/ceiling/ceiling-system.d.ts +6 -2
- package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
- package/dist/systems/ceiling/ceiling-system.js +66 -13
- package/dist/systems/door/door-animation.test.d.ts +2 -0
- package/dist/systems/door/door-animation.test.d.ts.map +1 -0
- package/dist/systems/door/door-animation.test.js +51 -0
- package/dist/systems/door/door-floor-alignment.test.d.ts +2 -0
- package/dist/systems/door/door-floor-alignment.test.d.ts.map +1 -0
- package/dist/systems/door/door-floor-alignment.test.js +50 -0
- package/dist/systems/door/door-system.d.ts +24 -0
- package/dist/systems/door/door-system.d.ts.map +1 -1
- package/dist/systems/door/door-system.js +864 -180
- package/dist/systems/elevator/elevator-interaction-system.d.ts +2 -0
- package/dist/systems/elevator/elevator-interaction-system.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-interaction-system.js +62 -0
- package/dist/systems/fence/fence-system.d.ts +20 -0
- package/dist/systems/fence/fence-system.d.ts.map +1 -1
- package/dist/systems/fence/fence-system.js +229 -57
- package/dist/systems/floor-elevation/floor-elevation-system.d.ts +20 -0
- package/dist/systems/floor-elevation/floor-elevation-system.d.ts.map +1 -0
- package/dist/systems/floor-elevation/floor-elevation-system.js +78 -0
- package/dist/systems/geometry/geometry-system.d.ts +41 -0
- package/dist/systems/geometry/geometry-system.d.ts.map +1 -0
- package/dist/systems/geometry/geometry-system.js +348 -0
- package/dist/systems/geometry/geometry-system.test.d.ts +2 -0
- package/dist/systems/geometry/geometry-system.test.d.ts.map +1 -0
- package/dist/systems/geometry/geometry-system.test.js +30 -0
- package/dist/systems/interactive/control-widget.d.ts +10 -0
- package/dist/systems/interactive/control-widget.d.ts.map +1 -0
- package/dist/systems/interactive/control-widget.js +35 -0
- package/dist/systems/interactive/interactive-system.d.ts +1 -1
- package/dist/systems/interactive/interactive-system.d.ts.map +1 -1
- package/dist/systems/interactive/interactive-system.js +55 -56
- package/dist/systems/item/item-system.d.ts +7 -0
- package/dist/systems/item/item-system.d.ts.map +1 -1
- package/dist/systems/item/item-system.js +28 -17
- package/dist/systems/item-light/item-light-system.d.ts +1 -1
- package/dist/systems/item-light/item-light-system.d.ts.map +1 -1
- package/dist/systems/item-light/item-light-system.js +18 -5
- package/dist/systems/level/level-system.d.ts.map +1 -1
- package/dist/systems/level/level-system.js +28 -4
- package/dist/systems/level/level-utils.d.ts +0 -3
- package/dist/systems/level/level-utils.d.ts.map +1 -1
- package/dist/systems/level/level-utils.js +2 -41
- package/dist/systems/roof/roof-materials.d.ts +3 -2
- package/dist/systems/roof/roof-materials.d.ts.map +1 -1
- package/dist/systems/roof/roof-materials.js +59 -14
- package/dist/systems/roof/roof-system.d.ts +46 -6
- package/dist/systems/roof/roof-system.d.ts.map +1 -1
- package/dist/systems/roof/roof-system.js +1365 -170
- package/dist/systems/slab/slab-system.d.ts +5 -3
- package/dist/systems/slab/slab-system.d.ts.map +1 -1
- package/dist/systems/slab/slab-system.js +204 -68
- package/dist/systems/slab/slab-system.test.d.ts +2 -0
- package/dist/systems/slab/slab-system.test.d.ts.map +1 -0
- package/dist/systems/slab/slab-system.test.js +63 -0
- package/dist/systems/stair/stair-materials.d.ts +4 -3
- package/dist/systems/stair/stair-materials.d.ts.map +1 -1
- package/dist/systems/stair/stair-materials.js +30 -15
- package/dist/systems/stair/stair-system.d.ts.map +1 -1
- package/dist/systems/stair/stair-system.js +55 -63
- package/dist/systems/surface-hole-geometry.d.ts +3 -0
- package/dist/systems/surface-hole-geometry.d.ts.map +1 -0
- package/dist/systems/surface-hole-geometry.js +4 -0
- package/dist/systems/wall/opening-cutout-geometry.d.ts +31 -0
- package/dist/systems/wall/opening-cutout-geometry.d.ts.map +1 -0
- package/dist/systems/wall/opening-cutout-geometry.js +167 -0
- package/dist/systems/wall/opening-cutout-geometry.test.d.ts +2 -0
- package/dist/systems/wall/opening-cutout-geometry.test.d.ts.map +1 -0
- package/dist/systems/wall/opening-cutout-geometry.test.js +172 -0
- package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
- package/dist/systems/wall/wall-cutout.js +62 -17
- package/dist/systems/wall/wall-materials.d.ts +12 -7
- package/dist/systems/wall/wall-materials.d.ts.map +1 -1
- package/dist/systems/wall/wall-materials.js +279 -46
- package/dist/systems/wall/wall-opening-cutout.test.d.ts +2 -0
- package/dist/systems/wall/wall-opening-cutout.test.d.ts.map +1 -0
- package/dist/systems/wall/wall-opening-cutout.test.js +59 -0
- package/dist/systems/wall/wall-support-extension.test.d.ts +2 -0
- package/dist/systems/wall/wall-support-extension.test.d.ts.map +1 -0
- package/dist/systems/wall/wall-support-extension.test.js +48 -0
- package/dist/systems/wall/wall-system.d.ts +2 -2
- package/dist/systems/wall/wall-system.d.ts.map +1 -1
- package/dist/systems/wall/wall-system.js +493 -193
- package/dist/systems/window/window-animation-system.d.ts +12 -0
- package/dist/systems/window/window-animation-system.d.ts.map +1 -1
- package/dist/systems/window/window-animation-system.js +16 -5
- package/dist/systems/window/window-system.d.ts +7 -0
- package/dist/systems/window/window-system.d.ts.map +1 -1
- package/dist/systems/window/window-system.js +308 -18
- package/package.json +5 -6
- package/dist/components/renderers/building/building-renderer.d.ts +0 -5
- package/dist/components/renderers/building/building-renderer.d.ts.map +0 -1
- package/dist/components/renderers/building/building-renderer.js +0 -11
- package/dist/components/renderers/ceiling/ceiling-renderer.d.ts +0 -5
- package/dist/components/renderers/ceiling/ceiling-renderer.d.ts.map +0 -1
- package/dist/components/renderers/ceiling/ceiling-renderer.js +0 -58
- package/dist/components/renderers/column/column-renderer.d.ts +0 -5
- package/dist/components/renderers/column/column-renderer.d.ts.map +0 -1
- package/dist/components/renderers/column/column-renderer.js +0 -597
- package/dist/components/renderers/door/door-renderer.d.ts +0 -5
- package/dist/components/renderers/door/door-renderer.d.ts.map +0 -1
- package/dist/components/renderers/door/door-renderer.js +0 -16
- package/dist/components/renderers/fence/fence-renderer.d.ts +0 -5
- package/dist/components/renderers/fence/fence-renderer.d.ts.map +0 -1
- package/dist/components/renderers/fence/fence-renderer.js +0 -15
- package/dist/components/renderers/guide/guide-renderer.d.ts +0 -5
- package/dist/components/renderers/guide/guide-renderer.d.ts.map +0 -1
- package/dist/components/renderers/guide/guide-renderer.js +0 -38
- package/dist/components/renderers/item/item-renderer.d.ts +0 -5
- package/dist/components/renderers/item/item-renderer.d.ts.map +0 -1
- package/dist/components/renderers/item/item-renderer.js +0 -172
- package/dist/components/renderers/level/level-renderer.d.ts +0 -5
- package/dist/components/renderers/level/level-renderer.d.ts.map +0 -1
- package/dist/components/renderers/level/level-renderer.js +0 -11
- package/dist/components/renderers/roof/roof-materials.d.ts +0 -4
- package/dist/components/renderers/roof/roof-materials.d.ts.map +0 -1
- package/dist/components/renderers/roof/roof-materials.js +0 -16
- package/dist/components/renderers/roof/roof-renderer.d.ts +0 -5
- package/dist/components/renderers/roof/roof-renderer.d.ts.map +0 -1
- package/dist/components/renderers/roof/roof-renderer.js +0 -32
- package/dist/components/renderers/roof-segment/roof-segment-renderer.d.ts +0 -5
- package/dist/components/renderers/roof-segment/roof-segment-renderer.d.ts.map +0 -1
- package/dist/components/renderers/roof-segment/roof-segment-renderer.js +0 -40
- package/dist/components/renderers/scan/scan-renderer.d.ts +0 -5
- package/dist/components/renderers/scan/scan-renderer.d.ts.map +0 -1
- package/dist/components/renderers/scan/scan-renderer.js +0 -54
- package/dist/components/renderers/site/site-renderer.d.ts +0 -5
- package/dist/components/renderers/site/site-renderer.d.ts.map +0 -1
- package/dist/components/renderers/site/site-renderer.js +0 -106
- package/dist/components/renderers/slab/slab-renderer.d.ts +0 -5
- package/dist/components/renderers/slab/slab-renderer.d.ts.map +0 -1
- package/dist/components/renderers/slab/slab-renderer.js +0 -58
- package/dist/components/renderers/spawn/spawn-renderer.d.ts +0 -5
- package/dist/components/renderers/spawn/spawn-renderer.d.ts.map +0 -1
- package/dist/components/renderers/spawn/spawn-renderer.js +0 -32
- package/dist/components/renderers/stair/stair-renderer.d.ts +0 -5
- package/dist/components/renderers/stair/stair-renderer.d.ts.map +0 -1
- package/dist/components/renderers/stair/stair-renderer.js +0 -603
- package/dist/components/renderers/stair-segment/stair-segment-renderer.d.ts +0 -5
- package/dist/components/renderers/stair-segment/stair-segment-renderer.d.ts.map +0 -1
- package/dist/components/renderers/stair-segment/stair-segment-renderer.js +0 -51
- package/dist/components/renderers/wall/wall-renderer.d.ts +0 -5
- package/dist/components/renderers/wall/wall-renderer.d.ts.map +0 -1
- package/dist/components/renderers/wall/wall-renderer.js +0 -16
- package/dist/components/renderers/window/window-renderer.d.ts +0 -5
- package/dist/components/renderers/window/window-renderer.d.ts.map +0 -1
- package/dist/components/renderers/window/window-renderer.js +0 -21
- package/dist/components/renderers/zone/zone-renderer.d.ts +0 -5
- package/dist/components/renderers/zone/zone-renderer.d.ts.map +0 -1
- package/dist/components/renderers/zone/zone-renderer.js +0 -181
- package/dist/components/viewer/ground-occluder.d.ts +0 -2
- package/dist/components/viewer/ground-occluder.d.ts.map +0 -1
- package/dist/components/viewer/ground-occluder.js +0 -79
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* three runs at 0.185 but @types/three is pinned at 0.184: the 0.185 typings
|
|
3
|
+
* make tsgo's type inference allocate unboundedly (microsoft/typescript-go
|
|
4
|
+
* #2125 class) and OOM the machine. r185 renamed directionToColor /
|
|
5
|
+
* colorToDirection to packNormalToRGB / unpackRGBToNormal — re-export the new
|
|
6
|
+
* runtime names under the old names' signatures. Delete this file (and the
|
|
7
|
+
* @types/three pin) once tsgo handles the 0.185 types; the `typeof` references
|
|
8
|
+
* to the removed old names will fail the build as a reminder.
|
|
9
|
+
*/
|
|
10
|
+
export declare const packNormalToRGB: (node: import("three/webgpu").Node) => import("three/webgpu").Node<"vec3">;
|
|
11
|
+
export declare const unpackRGBToNormal: (node: import("three/webgpu").Node) => import("three/webgpu").Node<"vec3">;
|
|
12
|
+
//# sourceMappingURL=tsl-compat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tsl-compat.d.ts","sourceRoot":"","sources":["../../src/lib/tsl-compat.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,4EACV,CAAA;AAClB,eAAO,MAAM,iBAAiB,4EAEX,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as TSL from 'three/tsl';
|
|
2
|
+
/**
|
|
3
|
+
* three runs at 0.185 but @types/three is pinned at 0.184: the 0.185 typings
|
|
4
|
+
* make tsgo's type inference allocate unboundedly (microsoft/typescript-go
|
|
5
|
+
* #2125 class) and OOM the machine. r185 renamed directionToColor /
|
|
6
|
+
* colorToDirection to packNormalToRGB / unpackRGBToNormal — re-export the new
|
|
7
|
+
* runtime names under the old names' signatures. Delete this file (and the
|
|
8
|
+
* @types/three pin) once tsgo handles the 0.185 types; the `typeof` references
|
|
9
|
+
* to the removed old names will fail the build as a reminder.
|
|
10
|
+
*/
|
|
11
|
+
export const packNormalToRGB = TSL
|
|
12
|
+
.packNormalToRGB;
|
|
13
|
+
export const unpackRGBToNormal = TSL.unpackRGBToNormal;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { AnyNode, BaseNode, BuildingNode, LevelNode, ZoneNode } from '@pascal-app/core';
|
|
2
2
|
import type { Object3D } from 'three';
|
|
3
|
+
import type { EdgeMode } from '../lib/edge-style';
|
|
4
|
+
import type { ColorPreset, RenderShading } from '../lib/materials';
|
|
5
|
+
export type RenderContext = 'editor' | 'viewer';
|
|
3
6
|
type SelectionPath = {
|
|
4
7
|
buildingId: BuildingNode['id'] | null;
|
|
5
8
|
levelId: LevelNode['id'] | null;
|
|
@@ -20,30 +23,77 @@ type ViewerState = {
|
|
|
20
23
|
setHoveredId: (id: AnyNode['id'] | ZoneNode['id'] | null) => void;
|
|
21
24
|
cameraMode: 'perspective' | 'orthographic';
|
|
22
25
|
setCameraMode: (mode: 'perspective' | 'orthographic') => void;
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
sceneTheme: string;
|
|
27
|
+
setSceneTheme: (id: string) => void;
|
|
28
|
+
renderContext: RenderContext;
|
|
29
|
+
setRenderContext: (context: RenderContext) => void;
|
|
30
|
+
/** True during a GLB bake/export pass. Renderers that normally draw via a
|
|
31
|
+
* collective InstancedMesh (`def.system`) and mount only an invisible per-node
|
|
32
|
+
* proxy can watch this to emit real, visible geometry so the exporter — which
|
|
33
|
+
* clones only the `scene-renderer` subtree — captures them. Transient (never
|
|
34
|
+
* persisted). */
|
|
35
|
+
isExporting: boolean;
|
|
36
|
+
setExporting: (value: boolean) => void;
|
|
37
|
+
/** Item model loads that exhausted their retries — nodeId → asset URL. The
|
|
38
|
+
* scene renders without these items (they settle as skipped); a bake host
|
|
39
|
+
* can persist the map onto the artifact's metadata so a missing item is
|
|
40
|
+
* queryable instead of silently absent. Transient (never persisted). */
|
|
41
|
+
itemLoadFailures: Record<string, string>;
|
|
42
|
+
reportItemLoadFailure: (nodeId: string, url: string) => void;
|
|
43
|
+
clearItemLoadFailure: (nodeId: string) => void;
|
|
44
|
+
/** Suspend the render loop while the canvas is fully covered (e.g. studio gallery). */
|
|
45
|
+
renderPaused: boolean;
|
|
46
|
+
setRenderPaused: (value: boolean) => void;
|
|
47
|
+
shading: RenderShading;
|
|
48
|
+
shadingByContext: Partial<Record<RenderContext, RenderShading>>;
|
|
49
|
+
setShading: (shading: RenderShading) => void;
|
|
50
|
+
textures: boolean;
|
|
51
|
+
setTextures: (textures: boolean) => void;
|
|
52
|
+
colorPreset: ColorPreset;
|
|
53
|
+
setColorPreset: (preset: ColorPreset) => void;
|
|
54
|
+
edges: EdgeMode;
|
|
55
|
+
setEdges: (edges: EdgeMode) => void;
|
|
56
|
+
shadows: boolean;
|
|
57
|
+
setShadows: (shadows: boolean) => void;
|
|
25
58
|
unit: 'metric' | 'imperial';
|
|
26
59
|
setUnit: (unit: 'metric' | 'imperial') => void;
|
|
60
|
+
/** True once the user explicitly picked a unit. Until then `unit` is a
|
|
61
|
+
* locale-derived default and is not persisted, so the default can keep
|
|
62
|
+
* tracking the browser locale across sessions. */
|
|
63
|
+
unitExplicit: boolean;
|
|
27
64
|
levelMode: 'stacked' | 'exploded' | 'solo' | 'manual';
|
|
28
65
|
setLevelMode: (mode: 'stacked' | 'exploded' | 'solo' | 'manual') => void;
|
|
29
|
-
wallMode: 'up' | 'cutaway' | 'down';
|
|
30
|
-
setWallMode: (mode: 'up' | 'cutaway' | 'down') => void;
|
|
66
|
+
wallMode: 'up' | 'cutaway' | 'down' | 'translucent';
|
|
67
|
+
setWallMode: (mode: 'up' | 'cutaway' | 'down' | 'translucent') => void;
|
|
31
68
|
showScans: boolean;
|
|
32
69
|
setShowScans: (show: boolean) => void;
|
|
33
70
|
showGuides: boolean;
|
|
34
71
|
setShowGuides: (show: boolean) => void;
|
|
35
72
|
showGrid: boolean;
|
|
36
73
|
setShowGrid: (show: boolean) => void;
|
|
74
|
+
showMeasurements: boolean;
|
|
75
|
+
setShowMeasurements: (show: boolean) => void;
|
|
76
|
+
showZones: boolean;
|
|
77
|
+
setShowZones: (show: boolean) => void;
|
|
78
|
+
transparentBackground: boolean;
|
|
79
|
+
setTransparentBackground: (transparent: boolean) => void;
|
|
80
|
+
inkOpacity: number | null;
|
|
81
|
+
setInkOpacity: (opacity: number | null) => void;
|
|
37
82
|
projectId: string | null;
|
|
38
83
|
setProjectId: (id: string | null) => void;
|
|
39
84
|
projectPreferences: Record<string, {
|
|
40
85
|
showScans?: boolean;
|
|
41
86
|
showGuides?: boolean;
|
|
42
87
|
showGrid?: boolean;
|
|
88
|
+
showMeasurements?: boolean;
|
|
43
89
|
}>;
|
|
44
90
|
setSelection: (updates: Partial<SelectionPath>) => void;
|
|
45
91
|
resetSelection: () => void;
|
|
46
92
|
outliner: Outliner;
|
|
93
|
+
/** Bumped by GeometrySystem after each rebuild pass so selection/outline
|
|
94
|
+
* effects can re-apply to the freshly swapped meshes. */
|
|
95
|
+
geometryRevision: number;
|
|
96
|
+
bumpGeometryRevision: () => void;
|
|
47
97
|
exportScene: ((format?: 'glb' | 'stl' | 'obj') => Promise<void>) | null;
|
|
48
98
|
setExportScene: (fn: ((format?: 'glb' | 'stl' | 'obj') => Promise<void>) | null) => void;
|
|
49
99
|
debugColors: boolean;
|
|
@@ -52,22 +102,40 @@ type ViewerState = {
|
|
|
52
102
|
setWalkthroughMode: (mode: boolean) => void;
|
|
53
103
|
cameraDragging: boolean;
|
|
54
104
|
setCameraDragging: (dragging: boolean) => void;
|
|
105
|
+
/**
|
|
106
|
+
* True while a host-driven drag is in progress (editor handles —
|
|
107
|
+
* height arrow, width arrow, etc.). Suppresses node pointer event
|
|
108
|
+
* routing so the synthetic click on pointerup doesn't reroute
|
|
109
|
+
* selection to whatever mesh the cursor lands on at release.
|
|
110
|
+
* Conceptually a sibling of `cameraDragging` — both mean "user is
|
|
111
|
+
* dragging; don't treat the next pointerup as a click on the
|
|
112
|
+
* scene." Set by the host (e.g. `NodeArrowHandles` in the editor);
|
|
113
|
+
* the viewer only reads it.
|
|
114
|
+
*/
|
|
115
|
+
inputDragging: boolean;
|
|
116
|
+
setInputDragging: (dragging: boolean) => void;
|
|
55
117
|
};
|
|
56
118
|
declare const useViewer: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<ViewerState>, "setState" | "persist"> & {
|
|
57
119
|
setState(partial: ViewerState | Partial<ViewerState> | ((state: ViewerState) => ViewerState | Partial<ViewerState>), replace?: false | undefined): unknown;
|
|
58
120
|
setState(state: ViewerState | ((state: ViewerState) => ViewerState), replace: true): unknown;
|
|
59
121
|
persist: {
|
|
60
122
|
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<ViewerState, {
|
|
61
|
-
cameraMode: "perspective" | "orthographic";
|
|
62
|
-
theme: "light" | "dark";
|
|
63
|
-
unit: "metric" | "imperial";
|
|
64
123
|
levelMode: "manual" | "stacked" | "exploded" | "solo";
|
|
65
|
-
wallMode: "up" | "down" | "cutaway";
|
|
124
|
+
wallMode: "up" | "down" | "cutaway" | "translucent";
|
|
66
125
|
projectPreferences: Record<string, {
|
|
67
126
|
showScans?: boolean;
|
|
68
127
|
showGuides?: boolean;
|
|
69
128
|
showGrid?: boolean;
|
|
129
|
+
showMeasurements?: boolean;
|
|
70
130
|
}>;
|
|
131
|
+
unit?: "metric" | "imperial" | undefined;
|
|
132
|
+
cameraMode: "perspective" | "orthographic";
|
|
133
|
+
sceneTheme: string;
|
|
134
|
+
shadingByContext: Partial<Record<RenderContext, RenderShading>>;
|
|
135
|
+
textures: boolean;
|
|
136
|
+
colorPreset: ColorPreset;
|
|
137
|
+
edges: EdgeMode;
|
|
138
|
+
shadows: boolean;
|
|
71
139
|
}, unknown>>) => void;
|
|
72
140
|
clearStorage: () => void;
|
|
73
141
|
rehydrate: () => Promise<void> | void;
|
|
@@ -75,18 +143,30 @@ declare const useViewer: import("zustand").UseBoundStore<Omit<import("zustand").
|
|
|
75
143
|
onHydrate: (fn: (state: ViewerState) => void) => () => void;
|
|
76
144
|
onFinishHydration: (fn: (state: ViewerState) => void) => () => void;
|
|
77
145
|
getOptions: () => Partial<import("zustand/middleware").PersistOptions<ViewerState, {
|
|
78
|
-
cameraMode: "perspective" | "orthographic";
|
|
79
|
-
theme: "light" | "dark";
|
|
80
|
-
unit: "metric" | "imperial";
|
|
81
146
|
levelMode: "manual" | "stacked" | "exploded" | "solo";
|
|
82
|
-
wallMode: "up" | "down" | "cutaway";
|
|
147
|
+
wallMode: "up" | "down" | "cutaway" | "translucent";
|
|
83
148
|
projectPreferences: Record<string, {
|
|
84
149
|
showScans?: boolean;
|
|
85
150
|
showGuides?: boolean;
|
|
86
151
|
showGrid?: boolean;
|
|
152
|
+
showMeasurements?: boolean;
|
|
87
153
|
}>;
|
|
154
|
+
unit?: "metric" | "imperial" | undefined;
|
|
155
|
+
cameraMode: "perspective" | "orthographic";
|
|
156
|
+
sceneTheme: string;
|
|
157
|
+
shadingByContext: Partial<Record<RenderContext, RenderShading>>;
|
|
158
|
+
textures: boolean;
|
|
159
|
+
colorPreset: ColorPreset;
|
|
160
|
+
edges: EdgeMode;
|
|
161
|
+
shadows: boolean;
|
|
88
162
|
}, unknown>>;
|
|
89
163
|
};
|
|
90
164
|
}>;
|
|
165
|
+
/** Apply an authoritative country code (e.g. IP-derived by the host app) as
|
|
166
|
+
* the unit default. Stronger signal than the timezone heuristic used at store
|
|
167
|
+
* creation, but still a default: it never overrides an explicit user choice
|
|
168
|
+
* and is not persisted (the unit only sticks once the user touches the
|
|
169
|
+
* toggle). */
|
|
170
|
+
export declare function applyCountryUnitDefault(country: string | null | undefined): void;
|
|
91
171
|
export default useViewer;
|
|
92
172
|
//# sourceMappingURL=use-viewer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-viewer.d.ts","sourceRoot":"","sources":["../../src/store/use-viewer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC5F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"use-viewer.d.ts","sourceRoot":"","sources":["../../src/store/use-viewer.ts"],"names":[],"mappings":"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"}
|
package/dist/store/use-viewer.js
CHANGED
|
@@ -1,6 +1,123 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { create } from 'zustand';
|
|
3
3
|
import { persist } from 'zustand/middleware';
|
|
4
|
+
import { SCENE_THEME_IDS } from '../lib/scene-themes';
|
|
5
|
+
const CAMERA_MODES = ['perspective', 'orthographic'];
|
|
6
|
+
const RENDER_SHADINGS = ['solid', 'rendered'];
|
|
7
|
+
const COLOR_PRESETS = ['clay', 'white', 'mono', 'blueprint'];
|
|
8
|
+
const EDGE_MODES = ['off', 'soft', 'strong'];
|
|
9
|
+
const UNITS = ['metric', 'imperial'];
|
|
10
|
+
const LEVEL_MODES = ['stacked', 'exploded', 'solo', 'manual'];
|
|
11
|
+
const WALL_MODES = ['up', 'cutaway', 'down', 'translucent'];
|
|
12
|
+
// Countries still on imperial/US customary units: United States, Liberia, Myanmar.
|
|
13
|
+
const IMPERIAL_REGIONS = ['US', 'LR', 'MM'];
|
|
14
|
+
// IANA zones for those countries. The timezone tracks the OS clock (actual
|
|
15
|
+
// location), unlike navigator.language where en-US is a common default for
|
|
16
|
+
// users far outside the US.
|
|
17
|
+
const IMPERIAL_TIMEZONES = new Set([
|
|
18
|
+
'America/New_York',
|
|
19
|
+
'America/Detroit',
|
|
20
|
+
'America/Kentucky/Louisville',
|
|
21
|
+
'America/Kentucky/Monticello',
|
|
22
|
+
'America/Indiana/Indianapolis',
|
|
23
|
+
'America/Indiana/Vincennes',
|
|
24
|
+
'America/Indiana/Winamac',
|
|
25
|
+
'America/Indiana/Marengo',
|
|
26
|
+
'America/Indiana/Petersburg',
|
|
27
|
+
'America/Indiana/Vevay',
|
|
28
|
+
'America/Indiana/Tell_City',
|
|
29
|
+
'America/Indiana/Knox',
|
|
30
|
+
'America/Chicago',
|
|
31
|
+
'America/Menominee',
|
|
32
|
+
'America/North_Dakota/Center',
|
|
33
|
+
'America/North_Dakota/New_Salem',
|
|
34
|
+
'America/North_Dakota/Beulah',
|
|
35
|
+
'America/Denver',
|
|
36
|
+
'America/Boise',
|
|
37
|
+
'America/Phoenix',
|
|
38
|
+
'America/Los_Angeles',
|
|
39
|
+
'America/Anchorage',
|
|
40
|
+
'America/Juneau',
|
|
41
|
+
'America/Sitka',
|
|
42
|
+
'America/Metlakatla',
|
|
43
|
+
'America/Yakutat',
|
|
44
|
+
'America/Nome',
|
|
45
|
+
'America/Adak',
|
|
46
|
+
'Pacific/Honolulu',
|
|
47
|
+
'America/Puerto_Rico',
|
|
48
|
+
'Pacific/Guam',
|
|
49
|
+
'Africa/Monrovia', // Liberia
|
|
50
|
+
'Asia/Yangon', // Myanmar
|
|
51
|
+
'Asia/Rangoon', // Myanmar (legacy alias)
|
|
52
|
+
]);
|
|
53
|
+
function detectDefaultUnit() {
|
|
54
|
+
if (typeof navigator === 'undefined')
|
|
55
|
+
return 'metric';
|
|
56
|
+
try {
|
|
57
|
+
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
58
|
+
if (timeZone)
|
|
59
|
+
return IMPERIAL_TIMEZONES.has(timeZone) ? 'imperial' : 'metric';
|
|
60
|
+
// No timezone available: fall back to an explicit locale region subtag
|
|
61
|
+
// only (never maximize() — it turns a bare "en" into region US).
|
|
62
|
+
const region = new Intl.Locale(navigator.language).region;
|
|
63
|
+
return region && IMPERIAL_REGIONS.includes(region) ? 'imperial' : 'metric';
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return 'metric';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function pickString(value, allowed, fallback) {
|
|
70
|
+
return typeof value === 'string' && allowed.includes(value) ? value : fallback;
|
|
71
|
+
}
|
|
72
|
+
function normalizeShadingByContext(value) {
|
|
73
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
74
|
+
return {};
|
|
75
|
+
const next = {};
|
|
76
|
+
for (const [context, shading] of Object.entries(value)) {
|
|
77
|
+
if (context !== 'editor' && context !== 'viewer')
|
|
78
|
+
continue;
|
|
79
|
+
next[context] = pickString(shading, RENDER_SHADINGS, 'rendered');
|
|
80
|
+
}
|
|
81
|
+
return next;
|
|
82
|
+
}
|
|
83
|
+
function normalizeProjectPreferences(value) {
|
|
84
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
85
|
+
return {};
|
|
86
|
+
const next = {};
|
|
87
|
+
for (const [projectId, preferences] of Object.entries(value)) {
|
|
88
|
+
if (!preferences || typeof preferences !== 'object' || Array.isArray(preferences))
|
|
89
|
+
continue;
|
|
90
|
+
const record = preferences;
|
|
91
|
+
next[projectId] = {
|
|
92
|
+
...(typeof record.showScans === 'boolean' ? { showScans: record.showScans } : {}),
|
|
93
|
+
...(typeof record.showGuides === 'boolean' ? { showGuides: record.showGuides } : {}),
|
|
94
|
+
...(typeof record.showGrid === 'boolean' ? { showGrid: record.showGrid } : {}),
|
|
95
|
+
...(typeof record.showMeasurements === 'boolean'
|
|
96
|
+
? { showMeasurements: record.showMeasurements }
|
|
97
|
+
: {}),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return next;
|
|
101
|
+
}
|
|
102
|
+
function normalizePersistedViewerState(value) {
|
|
103
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
104
|
+
return {};
|
|
105
|
+
const state = value;
|
|
106
|
+
return {
|
|
107
|
+
cameraMode: pickString(state.cameraMode, CAMERA_MODES, 'perspective'),
|
|
108
|
+
sceneTheme: pickString(state.sceneTheme, SCENE_THEME_IDS, 'studio'),
|
|
109
|
+
shadingByContext: normalizeShadingByContext(state.shadingByContext),
|
|
110
|
+
textures: typeof state.textures === 'boolean' ? state.textures : true,
|
|
111
|
+
colorPreset: pickString(state.colorPreset, COLOR_PRESETS, 'clay'),
|
|
112
|
+
edges: pickString(state.edges, EDGE_MODES, 'soft'),
|
|
113
|
+
shadows: typeof state.shadows === 'boolean' ? state.shadows : true,
|
|
114
|
+
unit: pickString(state.unit, UNITS, detectDefaultUnit()),
|
|
115
|
+
unitExplicit: typeof state.unit === 'string' && UNITS.includes(state.unit),
|
|
116
|
+
levelMode: pickString(state.levelMode, LEVEL_MODES, 'stacked'),
|
|
117
|
+
wallMode: pickString(state.wallMode, WALL_MODES, 'up'),
|
|
118
|
+
projectPreferences: normalizeProjectPreferences(state.projectPreferences),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
4
121
|
const useViewer = create()(persist((set) => ({
|
|
5
122
|
selection: { buildingId: null, levelId: null, zoneId: null, selectedIds: [] },
|
|
6
123
|
previewSelectedIds: [],
|
|
@@ -11,10 +128,42 @@ const useViewer = create()(persist((set) => ({
|
|
|
11
128
|
setHoveredId: (id) => set((state) => (state.hoveredId === id ? state : { hoveredId: id })),
|
|
12
129
|
cameraMode: 'perspective',
|
|
13
130
|
setCameraMode: (mode) => set({ cameraMode: mode }),
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
131
|
+
sceneTheme: 'studio',
|
|
132
|
+
setSceneTheme: (id) => set({ sceneTheme: id }),
|
|
133
|
+
renderContext: 'editor',
|
|
134
|
+
setRenderContext: (context) => set({ renderContext: context }),
|
|
135
|
+
isExporting: false,
|
|
136
|
+
setExporting: (value) => set({ isExporting: value }),
|
|
137
|
+
itemLoadFailures: {},
|
|
138
|
+
reportItemLoadFailure: (nodeId, url) => set((state) => state.itemLoadFailures[nodeId] === url
|
|
139
|
+
? state
|
|
140
|
+
: { itemLoadFailures: { ...state.itemLoadFailures, [nodeId]: url } }),
|
|
141
|
+
clearItemLoadFailure: (nodeId) => set((state) => {
|
|
142
|
+
if (!(nodeId in state.itemLoadFailures))
|
|
143
|
+
return state;
|
|
144
|
+
const next = { ...state.itemLoadFailures };
|
|
145
|
+
delete next[nodeId];
|
|
146
|
+
return { itemLoadFailures: next };
|
|
147
|
+
}),
|
|
148
|
+
renderPaused: false,
|
|
149
|
+
setRenderPaused: (value) => set({ renderPaused: value }),
|
|
150
|
+
shading: 'rendered',
|
|
151
|
+
shadingByContext: {},
|
|
152
|
+
setShading: (shading) => set((state) => ({
|
|
153
|
+
shading,
|
|
154
|
+
shadingByContext: { ...state.shadingByContext, [state.renderContext]: shading },
|
|
155
|
+
})),
|
|
156
|
+
textures: true,
|
|
157
|
+
setTextures: (textures) => set({ textures }),
|
|
158
|
+
colorPreset: 'clay',
|
|
159
|
+
setColorPreset: (preset) => set({ colorPreset: preset }),
|
|
160
|
+
edges: 'soft',
|
|
161
|
+
setEdges: (edges) => set({ edges }),
|
|
162
|
+
shadows: true,
|
|
163
|
+
setShadows: (shadows) => set({ shadows }),
|
|
164
|
+
unit: detectDefaultUnit(),
|
|
165
|
+
unitExplicit: false,
|
|
166
|
+
setUnit: (unit) => set({ unit, unitExplicit: true }),
|
|
18
167
|
levelMode: 'stacked',
|
|
19
168
|
setLevelMode: (mode) => set({ levelMode: mode }),
|
|
20
169
|
wallMode: 'up',
|
|
@@ -52,6 +201,23 @@ const useViewer = create()(persist((set) => ({
|
|
|
52
201
|
}
|
|
53
202
|
return { showGrid: show, projectPreferences };
|
|
54
203
|
}),
|
|
204
|
+
showMeasurements: true,
|
|
205
|
+
setShowMeasurements: (show) => set((state) => {
|
|
206
|
+
const projectPreferences = { ...(state.projectPreferences || {}) };
|
|
207
|
+
if (state.projectId) {
|
|
208
|
+
projectPreferences[state.projectId] = {
|
|
209
|
+
...(projectPreferences[state.projectId] || {}),
|
|
210
|
+
showMeasurements: show,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
return { showMeasurements: show, projectPreferences };
|
|
214
|
+
}),
|
|
215
|
+
showZones: true,
|
|
216
|
+
setShowZones: (show) => set({ showZones: show }),
|
|
217
|
+
transparentBackground: false,
|
|
218
|
+
setTransparentBackground: (transparent) => set({ transparentBackground: transparent }),
|
|
219
|
+
inkOpacity: null,
|
|
220
|
+
setInkOpacity: (opacity) => set({ inkOpacity: opacity }),
|
|
55
221
|
projectId: null,
|
|
56
222
|
setProjectId: (id) => set((state) => {
|
|
57
223
|
if (!id)
|
|
@@ -62,6 +228,7 @@ const useViewer = create()(persist((set) => ({
|
|
|
62
228
|
showScans: prefs.showScans ?? true,
|
|
63
229
|
showGuides: prefs.showGuides ?? true,
|
|
64
230
|
showGrid: prefs.showGrid ?? true,
|
|
231
|
+
showMeasurements: prefs.showMeasurements ?? true,
|
|
65
232
|
};
|
|
66
233
|
}),
|
|
67
234
|
projectPreferences: {},
|
|
@@ -98,6 +265,8 @@ const useViewer = create()(persist((set) => ({
|
|
|
98
265
|
previewSelectedIds: [],
|
|
99
266
|
}),
|
|
100
267
|
outliner: { selectedObjects: [], hoveredObjects: [] },
|
|
268
|
+
geometryRevision: 0,
|
|
269
|
+
bumpGeometryRevision: () => set((state) => ({ geometryRevision: state.geometryRevision + 1 })),
|
|
101
270
|
exportScene: null,
|
|
102
271
|
setExportScene: (fn) => set({ exportScene: fn }),
|
|
103
272
|
debugColors: false,
|
|
@@ -106,15 +275,41 @@ const useViewer = create()(persist((set) => ({
|
|
|
106
275
|
setWalkthroughMode: (mode) => set({ walkthroughMode: mode }),
|
|
107
276
|
cameraDragging: false,
|
|
108
277
|
setCameraDragging: (dragging) => set({ cameraDragging: dragging }),
|
|
278
|
+
inputDragging: false,
|
|
279
|
+
setInputDragging: (dragging) => set({ inputDragging: dragging }),
|
|
109
280
|
}), {
|
|
110
281
|
name: 'viewer-preferences',
|
|
282
|
+
merge: (persistedState, currentState) => ({
|
|
283
|
+
...currentState,
|
|
284
|
+
...normalizePersistedViewerState(persistedState),
|
|
285
|
+
}),
|
|
111
286
|
partialize: (state) => ({
|
|
112
287
|
cameraMode: state.cameraMode,
|
|
113
|
-
|
|
114
|
-
|
|
288
|
+
sceneTheme: state.sceneTheme,
|
|
289
|
+
shadingByContext: state.shadingByContext,
|
|
290
|
+
textures: state.textures,
|
|
291
|
+
colorPreset: state.colorPreset,
|
|
292
|
+
edges: state.edges,
|
|
293
|
+
shadows: state.shadows,
|
|
294
|
+
...(state.unitExplicit ? { unit: state.unit } : {}),
|
|
115
295
|
levelMode: state.levelMode,
|
|
116
296
|
wallMode: state.wallMode,
|
|
117
297
|
projectPreferences: state.projectPreferences,
|
|
118
298
|
}),
|
|
119
299
|
}));
|
|
300
|
+
/** Apply an authoritative country code (e.g. IP-derived by the host app) as
|
|
301
|
+
* the unit default. Stronger signal than the timezone heuristic used at store
|
|
302
|
+
* creation, but still a default: it never overrides an explicit user choice
|
|
303
|
+
* and is not persisted (the unit only sticks once the user touches the
|
|
304
|
+
* toggle). */
|
|
305
|
+
export function applyCountryUnitDefault(country) {
|
|
306
|
+
if (!country)
|
|
307
|
+
return;
|
|
308
|
+
const state = useViewer.getState();
|
|
309
|
+
if (state.unitExplicit)
|
|
310
|
+
return;
|
|
311
|
+
const unit = IMPERIAL_REGIONS.includes(country.toUpperCase()) ? 'imperial' : 'metric';
|
|
312
|
+
if (state.unit !== unit)
|
|
313
|
+
useViewer.setState({ unit });
|
|
314
|
+
}
|
|
120
315
|
export default useViewer;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-viewer.test.d.ts","sourceRoot":"","sources":["../../src/store/use-viewer.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// @ts-expect-error — bun:test is provided by the Bun runtime; viewer does not
|
|
2
|
+
// include Bun ambient types in its production declaration build.
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, test } from 'bun:test';
|
|
4
|
+
import useViewer from './use-viewer';
|
|
5
|
+
const resetMeasurementPreferences = () => {
|
|
6
|
+
useViewer.setState({
|
|
7
|
+
projectId: null,
|
|
8
|
+
projectPreferences: {},
|
|
9
|
+
showMeasurements: true,
|
|
10
|
+
unit: 'metric',
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
beforeEach(resetMeasurementPreferences);
|
|
14
|
+
afterEach(resetMeasurementPreferences);
|
|
15
|
+
describe('measurement display preferences', () => {
|
|
16
|
+
test('stores global visibility per project and defaults new projects to visible', () => {
|
|
17
|
+
const viewer = useViewer.getState();
|
|
18
|
+
viewer.setProjectId('project-a');
|
|
19
|
+
viewer.setShowMeasurements(false);
|
|
20
|
+
expect(useViewer.getState()).toMatchObject({
|
|
21
|
+
projectId: 'project-a',
|
|
22
|
+
showMeasurements: false,
|
|
23
|
+
projectPreferences: {
|
|
24
|
+
'project-a': { showMeasurements: false },
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
useViewer.getState().setProjectId('project-b');
|
|
28
|
+
expect(useViewer.getState().showMeasurements).toBe(true);
|
|
29
|
+
useViewer.getState().setProjectId('project-a');
|
|
30
|
+
expect(useViewer.getState().showMeasurements).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
test('changes display units without changing measurement visibility preferences', () => {
|
|
33
|
+
const viewer = useViewer.getState();
|
|
34
|
+
viewer.setProjectId('project-a');
|
|
35
|
+
viewer.setShowMeasurements(false);
|
|
36
|
+
const preferences = useViewer.getState().projectPreferences;
|
|
37
|
+
useViewer.getState().setUnit('imperial');
|
|
38
|
+
expect(useViewer.getState().unit).toBe('imperial');
|
|
39
|
+
expect(useViewer.getState().projectPreferences).toEqual(preferences);
|
|
40
|
+
expect(useViewer.getState().showMeasurements).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -2,7 +2,11 @@ import { type CeilingNode } from '@pascal-app/core';
|
|
|
2
2
|
import * as THREE from 'three';
|
|
3
3
|
export declare const CeilingSystem: () => null;
|
|
4
4
|
/**
|
|
5
|
-
* Generates flat ceiling geometry from polygon (no extrusion)
|
|
5
|
+
* Generates flat ceiling geometry from polygon (no extrusion).
|
|
6
|
+
*
|
|
7
|
+
* `extraHoles` are transient, derived cutouts (e.g. recessed-fixture
|
|
8
|
+
* footprints) that are cut alongside the node's persisted `holes` but never
|
|
9
|
+
* stored on the node — they are recomputed on every rebuild.
|
|
6
10
|
*/
|
|
7
|
-
export declare function generateCeilingGeometry(ceilingNode: CeilingNode): THREE.BufferGeometry;
|
|
11
|
+
export declare function generateCeilingGeometry(ceilingNode: CeilingNode, extraHoles?: Array<Array<[number, number]>>): THREE.BufferGeometry;
|
|
8
12
|
//# sourceMappingURL=ceiling-system.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ceiling-system.d.ts","sourceRoot":"","sources":["../../../src/systems/ceiling/ceiling-system.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ceiling-system.d.ts","sourceRoot":"","sources":["../../../src/systems/ceiling/ceiling-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,WAAW,EAMjB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAgB9B,eAAO,MAAM,aAAa,YA4BzB,CAAA;AA2DD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,WAAW,EACxB,UAAU,GAAE,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAM,GAC9C,KAAK,CAAC,cAAc,CA6DtB"}
|