@pascal-app/core 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/events/bus.d.ts +67 -13
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/hooks/scene-registry/item-clip-registry.d.ts +18 -0
- package/dist/hooks/scene-registry/item-clip-registry.d.ts.map +1 -0
- package/dist/hooks/scene-registry/item-clip-registry.js +10 -0
- package/dist/hooks/scene-registry/scene-registry.d.ts +14 -23
- package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
- package/dist/hooks/scene-registry/scene-registry.js +59 -26
- package/dist/hooks/scene-registry/scene-registry.test.d.ts +2 -0
- package/dist/hooks/scene-registry/scene-registry.test.d.ts.map +1 -0
- package/dist/hooks/scene-registry/scene-registry.test.js +26 -0
- package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +14 -0
- package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -0
- package/dist/hooks/spatial-grid/floor-placed-elevation.js +51 -0
- package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts +2 -0
- package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts.map +1 -0
- package/dist/hooks/spatial-grid/floor-placed-elevation.test.js +366 -0
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +79 -11
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-manager.js +508 -141
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +28 -1
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-sync.js +109 -18
- package/dist/hooks/spatial-grid/wall-slab-overlap.test.d.ts +2 -0
- package/dist/hooks/spatial-grid/wall-slab-overlap.test.d.ts.map +1 -0
- package/dist/hooks/spatial-grid/wall-slab-overlap.test.js +363 -0
- package/dist/index.d.ts +36 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -6
- package/dist/lib/level-name.d.ts +4 -0
- package/dist/lib/level-name.d.ts.map +1 -0
- package/dist/lib/level-name.js +10 -0
- package/dist/lib/measurement-geometry.d.ts +19 -0
- package/dist/lib/measurement-geometry.d.ts.map +1 -0
- package/dist/lib/measurement-geometry.js +232 -0
- package/dist/lib/measurement-geometry.test.d.ts +2 -0
- package/dist/lib/measurement-geometry.test.d.ts.map +1 -0
- package/dist/lib/measurement-geometry.test.js +102 -0
- package/dist/lib/polygon-geometry.d.ts +0 -1
- package/dist/lib/polygon-geometry.d.ts.map +1 -1
- package/dist/lib/polygon-geometry.js +0 -18
- package/dist/lib/polygon-relations.d.ts +10 -0
- package/dist/lib/polygon-relations.d.ts.map +1 -0
- package/dist/lib/polygon-relations.js +73 -0
- package/dist/lib/selection-proxy.d.ts +4 -0
- package/dist/lib/selection-proxy.d.ts.map +1 -0
- package/dist/lib/selection-proxy.js +12 -0
- package/dist/lib/slab-polygon.d.ts +31 -2
- package/dist/lib/slab-polygon.d.ts.map +1 -1
- package/dist/lib/slab-polygon.js +525 -31
- package/dist/lib/slab-polygon.test.d.ts +2 -0
- package/dist/lib/slab-polygon.test.d.ts.map +1 -0
- package/dist/lib/slab-polygon.test.js +635 -0
- package/dist/lib/slots.d.ts +14 -0
- package/dist/lib/slots.d.ts.map +1 -0
- package/dist/lib/slots.js +26 -0
- package/dist/lib/space-detection-pause.test.d.ts +2 -0
- package/dist/lib/space-detection-pause.test.d.ts.map +1 -0
- package/dist/lib/space-detection-pause.test.js +42 -0
- package/dist/lib/space-detection.d.ts +54 -2
- package/dist/lib/space-detection.d.ts.map +1 -1
- package/dist/lib/space-detection.js +599 -124
- package/dist/lib/space-detection.test.d.ts +2 -0
- package/dist/lib/space-detection.test.d.ts.map +1 -0
- package/dist/lib/space-detection.test.js +376 -0
- package/dist/lib/wall-distance.d.ts +60 -0
- package/dist/lib/wall-distance.d.ts.map +1 -0
- package/dist/lib/wall-distance.js +85 -0
- package/dist/lib/zone-quantities.d.ts +21 -0
- package/dist/lib/zone-quantities.d.ts.map +1 -0
- package/dist/lib/zone-quantities.js +183 -0
- package/dist/lib/zone-quantities.test.d.ts +2 -0
- package/dist/lib/zone-quantities.test.d.ts.map +1 -0
- package/dist/lib/zone-quantities.test.js +82 -0
- package/dist/material-library.d.ts +20 -1
- package/dist/material-library.d.ts.map +1 -1
- package/dist/material-library.js +3737 -200
- package/dist/registry/__bench__/relations-resolver.bench.d.ts +15 -0
- package/dist/registry/__bench__/relations-resolver.bench.d.ts.map +1 -0
- package/dist/registry/__bench__/relations-resolver.bench.js +170 -0
- package/dist/registry/handles.d.ts +394 -0
- package/dist/registry/handles.d.ts.map +1 -0
- package/dist/registry/handles.js +24 -0
- package/dist/registry/index.d.ts +7 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +4 -0
- package/dist/registry/registry.d.ts +136 -0
- package/dist/registry/registry.d.ts.map +1 -0
- package/dist/registry/registry.js +282 -0
- package/dist/registry/registry.test.d.ts +2 -0
- package/dist/registry/registry.test.d.ts.map +1 -0
- package/dist/registry/registry.test.js +196 -0
- package/dist/registry/relations-resolver.d.ts +42 -0
- package/dist/registry/relations-resolver.d.ts.map +1 -0
- package/dist/registry/relations-resolver.js +77 -0
- package/dist/registry/relations-resolver.test.d.ts +2 -0
- package/dist/registry/relations-resolver.test.d.ts.map +1 -0
- package/dist/registry/relations-resolver.test.js +183 -0
- package/dist/registry/scene-api.d.ts +44 -0
- package/dist/registry/scene-api.d.ts.map +1 -0
- package/dist/registry/scene-api.js +111 -0
- package/dist/registry/scene-api.test.d.ts +2 -0
- package/dist/registry/scene-api.test.d.ts.map +1 -0
- package/dist/registry/scene-api.test.js +183 -0
- package/dist/registry/subtree.d.ts +67 -0
- package/dist/registry/subtree.d.ts.map +1 -0
- package/dist/registry/subtree.js +123 -0
- package/dist/registry/subtree.test.d.ts +2 -0
- package/dist/registry/subtree.test.d.ts.map +1 -0
- package/dist/registry/subtree.test.js +163 -0
- package/dist/registry/types.d.ts +2099 -0
- package/dist/registry/types.d.ts.map +1 -0
- package/dist/registry/types.js +1 -0
- package/dist/schema/index.d.ts +35 -4
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +32 -4
- package/dist/schema/material.d.ts +13 -2
- package/dist/schema/material.d.ts.map +1 -1
- package/dist/schema/material.js +17 -5
- package/dist/schema/material.test.d.ts +2 -0
- package/dist/schema/material.test.d.ts.map +1 -0
- package/dist/schema/material.test.js +43 -0
- package/dist/schema/nodes/box-vent.d.ts +74 -0
- package/dist/schema/nodes/box-vent.d.ts.map +1 -0
- package/dist/schema/nodes/box-vent.js +63 -0
- package/dist/schema/nodes/building.d.ts +1 -1
- package/dist/schema/nodes/building.d.ts.map +1 -1
- package/dist/schema/nodes/building.js +3 -2
- package/dist/schema/nodes/cabinet.d.ts +534 -0
- package/dist/schema/nodes/cabinet.d.ts.map +1 -0
- package/dist/schema/nodes/cabinet.js +137 -0
- package/dist/schema/nodes/ceiling.d.ts +5 -2
- package/dist/schema/nodes/ceiling.d.ts.map +1 -1
- package/dist/schema/nodes/ceiling.js +5 -1
- package/dist/schema/nodes/chimney.d.ts +158 -0
- package/dist/schema/nodes/chimney.d.ts.map +1 -0
- package/dist/schema/nodes/chimney.js +67 -0
- package/dist/schema/nodes/column.d.ts +600 -7
- package/dist/schema/nodes/column.d.ts.map +1 -1
- package/dist/schema/nodes/column.js +589 -6
- package/dist/schema/nodes/cupola.d.ts +66 -0
- package/dist/schema/nodes/cupola.d.ts.map +1 -0
- package/dist/schema/nodes/cupola.js +28 -0
- package/dist/schema/nodes/door.d.ts +13 -5
- package/dist/schema/nodes/door.d.ts.map +1 -1
- package/dist/schema/nodes/door.js +12 -0
- package/dist/schema/nodes/dormer.d.ts +228 -0
- package/dist/schema/nodes/dormer.d.ts.map +1 -0
- package/dist/schema/nodes/dormer.js +119 -0
- package/dist/schema/nodes/downspout.d.ts +75 -0
- package/dist/schema/nodes/downspout.d.ts.map +1 -0
- package/dist/schema/nodes/downspout.js +63 -0
- package/dist/schema/nodes/duct-fitting.d.ts +91 -0
- package/dist/schema/nodes/duct-fitting.d.ts.map +1 -0
- package/dist/schema/nodes/duct-fitting.js +92 -0
- package/dist/schema/nodes/duct-segment.d.ts +61 -0
- package/dist/schema/nodes/duct-segment.d.ts.map +1 -0
- package/dist/schema/nodes/duct-segment.js +73 -0
- package/dist/schema/nodes/duct-terminal.d.ts +57 -0
- package/dist/schema/nodes/duct-terminal.d.ts.map +1 -0
- package/dist/schema/nodes/duct-terminal.js +51 -0
- package/dist/schema/nodes/elevator.d.ts +106 -0
- package/dist/schema/nodes/elevator.d.ts.map +1 -0
- package/dist/schema/nodes/elevator.js +57 -0
- package/dist/schema/nodes/eyebrow-vent.d.ts +68 -0
- package/dist/schema/nodes/eyebrow-vent.d.ts.map +1 -0
- package/dist/schema/nodes/eyebrow-vent.js +40 -0
- package/dist/schema/nodes/fence.d.ts +19 -2
- package/dist/schema/nodes/fence.d.ts.map +1 -1
- package/dist/schema/nodes/fence.js +27 -2
- package/dist/schema/nodes/gutter.d.ts +84 -0
- package/dist/schema/nodes/gutter.d.ts.map +1 -0
- package/dist/schema/nodes/gutter.js +76 -0
- package/dist/schema/nodes/hvac-equipment.d.ts +63 -0
- package/dist/schema/nodes/hvac-equipment.d.ts.map +1 -0
- package/dist/schema/nodes/hvac-equipment.js +55 -0
- package/dist/schema/nodes/item.d.ts +12 -0
- package/dist/schema/nodes/item.d.ts.map +1 -1
- package/dist/schema/nodes/item.js +20 -0
- package/dist/schema/nodes/level.d.ts +1 -1
- package/dist/schema/nodes/level.d.ts.map +1 -1
- package/dist/schema/nodes/level.js +4 -0
- package/dist/schema/nodes/lineset.d.ts +42 -0
- package/dist/schema/nodes/lineset.d.ts.map +1 -0
- package/dist/schema/nodes/lineset.js +38 -0
- package/dist/schema/nodes/liquid-line.d.ts +34 -0
- package/dist/schema/nodes/liquid-line.d.ts.map +1 -0
- package/dist/schema/nodes/liquid-line.js +24 -0
- package/dist/schema/nodes/measurement.d.ts +306 -0
- package/dist/schema/nodes/measurement.d.ts.map +1 -0
- package/dist/schema/nodes/measurement.js +87 -0
- package/dist/schema/nodes/measurement.test.d.ts +2 -0
- package/dist/schema/nodes/measurement.test.d.ts.map +1 -0
- package/dist/schema/nodes/measurement.test.js +139 -0
- package/dist/schema/nodes/pipe-fitting.d.ts +56 -0
- package/dist/schema/nodes/pipe-fitting.d.ts.map +1 -0
- package/dist/schema/nodes/pipe-fitting.js +45 -0
- package/dist/schema/nodes/pipe-segment.d.ts +48 -0
- package/dist/schema/nodes/pipe-segment.d.ts.map +1 -0
- package/dist/schema/nodes/pipe-segment.js +36 -0
- package/dist/schema/nodes/pipe-trap.d.ts +43 -0
- package/dist/schema/nodes/pipe-trap.d.ts.map +1 -0
- package/dist/schema/nodes/pipe-trap.js +36 -0
- package/dist/schema/nodes/ridge-vent-defaults.test.d.ts +2 -0
- package/dist/schema/nodes/ridge-vent-defaults.test.d.ts.map +1 -0
- package/dist/schema/nodes/ridge-vent-defaults.test.js +205 -0
- package/dist/schema/nodes/ridge-vent.d.ts +82 -0
- package/dist/schema/nodes/ridge-vent.d.ts.map +1 -0
- package/dist/schema/nodes/ridge-vent.js +248 -0
- package/dist/schema/nodes/roof-segment-shape.d.ts +90 -0
- package/dist/schema/nodes/roof-segment-shape.d.ts.map +1 -0
- package/dist/schema/nodes/roof-segment-shape.js +318 -0
- package/dist/schema/nodes/roof-segment-shape.test.d.ts +2 -0
- package/dist/schema/nodes/roof-segment-shape.test.d.ts.map +1 -0
- package/dist/schema/nodes/roof-segment-shape.test.js +175 -0
- package/dist/schema/nodes/roof-segment-surface.test.d.ts +2 -0
- package/dist/schema/nodes/roof-segment-surface.test.d.ts.map +1 -0
- package/dist/schema/nodes/roof-segment-surface.test.js +48 -0
- package/dist/schema/nodes/roof-segment-trim.test.d.ts +2 -0
- package/dist/schema/nodes/roof-segment-trim.test.d.ts.map +1 -0
- package/dist/schema/nodes/roof-segment-trim.test.js +107 -0
- package/dist/schema/nodes/roof-segment-walls.d.ts +101 -0
- package/dist/schema/nodes/roof-segment-walls.d.ts.map +1 -0
- package/dist/schema/nodes/roof-segment-walls.js +330 -0
- package/dist/schema/nodes/roof-segment-walls.test.d.ts +2 -0
- package/dist/schema/nodes/roof-segment-walls.test.d.ts.map +1 -0
- package/dist/schema/nodes/roof-segment-walls.test.js +92 -0
- package/dist/schema/nodes/roof-segment.d.ts +273 -3
- package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
- package/dist/schema/nodes/roof-segment.js +539 -3
- package/dist/schema/nodes/roof.d.ts +8 -8
- package/dist/schema/nodes/roof.d.ts.map +1 -1
- package/dist/schema/nodes/roof.js +4 -16
- package/dist/schema/nodes/shelf.d.ts +106 -0
- package/dist/schema/nodes/shelf.d.ts.map +1 -0
- package/dist/schema/nodes/shelf.js +90 -0
- package/dist/schema/nodes/site.d.ts +1 -122
- package/dist/schema/nodes/site.d.ts.map +1 -1
- package/dist/schema/nodes/site.js +2 -6
- package/dist/schema/nodes/skylight.d.ts +279 -0
- package/dist/schema/nodes/skylight.d.ts.map +1 -0
- package/dist/schema/nodes/skylight.js +152 -0
- package/dist/schema/nodes/slab.d.ts +5 -2
- package/dist/schema/nodes/slab.d.ts.map +1 -1
- package/dist/schema/nodes/slab.js +5 -1
- package/dist/schema/nodes/solar-panel.d.ts +117 -0
- package/dist/schema/nodes/solar-panel.d.ts.map +1 -0
- package/dist/schema/nodes/solar-panel.js +47 -0
- package/dist/schema/nodes/stair-segment.d.ts +4 -4
- package/dist/schema/nodes/stair.d.ts +13 -12
- package/dist/schema/nodes/stair.d.ts.map +1 -1
- package/dist/schema/nodes/stair.js +3 -0
- package/dist/schema/nodes/surface-hole-metadata.d.ts +2 -0
- package/dist/schema/nodes/surface-hole-metadata.d.ts.map +1 -1
- package/dist/schema/nodes/surface-hole-metadata.js +3 -1
- package/dist/schema/nodes/turbine-vent.d.ts +68 -0
- package/dist/schema/nodes/turbine-vent.d.ts.map +1 -0
- package/dist/schema/nodes/turbine-vent.js +41 -0
- package/dist/schema/nodes/wall.d.ts +245 -6
- package/dist/schema/nodes/wall.d.ts.map +1 -1
- package/dist/schema/nodes/wall.js +257 -0
- package/dist/schema/nodes/wall.test.d.ts +2 -0
- package/dist/schema/nodes/wall.test.d.ts.map +1 -0
- package/dist/schema/nodes/wall.test.js +208 -0
- package/dist/schema/nodes/window.d.ts +11 -3
- package/dist/schema/nodes/window.d.ts.map +1 -1
- package/dist/schema/nodes/window.js +12 -0
- package/dist/schema/nodes/zone.d.ts +2 -0
- package/dist/schema/nodes/zone.d.ts.map +1 -1
- package/dist/schema/nodes/zone.js +6 -0
- package/dist/schema/scene-material.d.ts +41 -0
- package/dist/schema/scene-material.d.ts.map +1 -0
- package/dist/schema/scene-material.js +9 -0
- package/dist/schema/types.d.ts +2850 -655
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +49 -0
- package/dist/services/alignment-anchors.d.ts +100 -0
- package/dist/services/alignment-anchors.d.ts.map +1 -0
- package/dist/services/alignment-anchors.js +312 -0
- package/dist/services/alignment-anchors.test.d.ts +2 -0
- package/dist/services/alignment-anchors.test.d.ts.map +1 -0
- package/dist/services/alignment-anchors.test.js +383 -0
- package/dist/services/alignment.d.ts +131 -0
- package/dist/services/alignment.d.ts.map +1 -0
- package/dist/services/alignment.js +171 -0
- package/dist/services/alignment.test.d.ts +2 -0
- package/dist/services/alignment.test.d.ts.map +1 -0
- package/dist/services/alignment.test.js +92 -0
- package/dist/services/drag-session.d.ts +47 -0
- package/dist/services/drag-session.d.ts.map +1 -0
- package/dist/services/drag-session.js +100 -0
- package/dist/services/drag-session.test.d.ts +2 -0
- package/dist/services/drag-session.test.d.ts.map +1 -0
- package/dist/services/drag-session.test.js +219 -0
- package/dist/services/hosting.d.ts +88 -0
- package/dist/services/hosting.d.ts.map +1 -0
- package/dist/services/hosting.js +131 -0
- package/dist/services/hosting.test.d.ts +2 -0
- package/dist/services/hosting.test.d.ts.map +1 -0
- package/dist/services/hosting.test.js +230 -0
- package/dist/services/index.d.ts +13 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +12 -0
- package/dist/services/level-height.d.ts +28 -0
- package/dist/services/level-height.d.ts.map +1 -0
- package/dist/services/level-height.js +62 -0
- package/dist/services/movement.d.ts +48 -0
- package/dist/services/movement.d.ts.map +1 -0
- package/dist/services/movement.js +65 -0
- package/dist/services/movement.test.d.ts +2 -0
- package/dist/services/movement.test.d.ts.map +1 -0
- package/dist/services/movement.test.js +133 -0
- package/dist/services/opening-guides.d.ts +141 -0
- package/dist/services/opening-guides.d.ts.map +1 -0
- package/dist/services/opening-guides.js +267 -0
- package/dist/services/opening-guides.test.d.ts +2 -0
- package/dist/services/opening-guides.test.d.ts.map +1 -0
- package/dist/services/opening-guides.test.js +208 -0
- package/dist/services/port-connectivity.d.ts +115 -0
- package/dist/services/port-connectivity.d.ts.map +1 -0
- package/dist/services/port-connectivity.js +300 -0
- package/dist/services/port-connectivity.test.d.ts +2 -0
- package/dist/services/port-connectivity.test.d.ts.map +1 -0
- package/dist/services/port-connectivity.test.js +297 -0
- package/dist/services/riser-diagram.d.ts +40 -0
- package/dist/services/riser-diagram.d.ts.map +1 -0
- package/dist/services/riser-diagram.js +110 -0
- package/dist/services/riser-diagram.test.d.ts +2 -0
- package/dist/services/riser-diagram.test.d.ts.map +1 -0
- package/dist/services/riser-diagram.test.js +66 -0
- package/dist/services/single-undo-dance.test.d.ts +2 -0
- package/dist/services/single-undo-dance.test.d.ts.map +1 -0
- package/dist/services/single-undo-dance.test.js +210 -0
- package/dist/services/snap.d.ts +80 -0
- package/dist/services/snap.d.ts.map +1 -0
- package/dist/services/snap.js +140 -0
- package/dist/services/snap.test.d.ts +2 -0
- package/dist/services/snap.test.d.ts.map +1 -0
- package/dist/services/snap.test.js +137 -0
- package/dist/services/system-graph.d.ts +30 -0
- package/dist/services/system-graph.d.ts.map +1 -0
- package/dist/services/system-graph.js +164 -0
- package/dist/services/system-graph.test.d.ts +2 -0
- package/dist/services/system-graph.test.d.ts.map +1 -0
- package/dist/services/system-graph.test.js +138 -0
- package/dist/services/validate-dwv.d.ts +32 -0
- package/dist/services/validate-dwv.d.ts.map +1 -0
- package/dist/services/validate-dwv.js +118 -0
- package/dist/services/validate-dwv.test.d.ts +2 -0
- package/dist/services/validate-dwv.test.d.ts.map +1 -0
- package/dist/services/validate-dwv.test.js +109 -0
- package/dist/solar-panel-presets.d.ts +17 -0
- package/dist/solar-panel-presets.d.ts.map +1 -0
- package/dist/solar-panel-presets.js +43 -0
- package/dist/store/actions/node-actions.d.ts +14 -2
- package/dist/store/actions/node-actions.d.ts.map +1 -1
- package/dist/store/actions/node-actions.js +585 -15
- package/dist/store/actions/node-mutation-sanitize.test.d.ts +2 -0
- package/dist/store/actions/node-mutation-sanitize.test.d.ts.map +1 -0
- package/dist/store/actions/node-mutation-sanitize.test.js +147 -0
- package/dist/store/actions/reparent.test.d.ts +2 -0
- package/dist/store/actions/reparent.test.d.ts.map +1 -0
- package/dist/store/actions/reparent.test.js +212 -0
- package/dist/store/actions/ridge-vent-update.test.d.ts +2 -0
- package/dist/store/actions/ridge-vent-update.test.d.ts.map +1 -0
- package/dist/store/actions/ridge-vent-update.test.js +264 -0
- package/dist/store/history-control.d.ts +11 -0
- package/dist/store/history-control.d.ts.map +1 -1
- package/dist/store/history-control.js +33 -0
- package/dist/store/use-interactive.d.ts +39 -0
- package/dist/store/use-interactive.d.ts.map +1 -1
- package/dist/store/use-interactive.js +75 -0
- package/dist/store/use-live-node-overrides.d.ts +22 -0
- package/dist/store/use-live-node-overrides.d.ts.map +1 -0
- package/dist/store/use-live-node-overrides.js +59 -0
- package/dist/store/use-scene-dirty-tracking.test.d.ts +2 -0
- package/dist/store/use-scene-dirty-tracking.test.d.ts.map +1 -0
- package/dist/store/use-scene-dirty-tracking.test.js +68 -0
- package/dist/store/use-scene-elevator-migration.test.d.ts +2 -0
- package/dist/store/use-scene-elevator-migration.test.d.ts.map +1 -0
- package/dist/store/use-scene-elevator-migration.test.js +109 -0
- package/dist/store/use-scene-measurement-roundtrip.test.d.ts +2 -0
- package/dist/store/use-scene-measurement-roundtrip.test.d.ts.map +1 -0
- package/dist/store/use-scene-measurement-roundtrip.test.js +97 -0
- package/dist/store/use-scene-plugins.test.d.ts +2 -0
- package/dist/store/use-scene-plugins.test.d.ts.map +1 -0
- package/dist/store/use-scene-plugins.test.js +51 -0
- package/dist/store/use-scene-wall-slot-migration.test.d.ts +2 -0
- package/dist/store/use-scene-wall-slot-migration.test.d.ts.map +1 -0
- package/dist/store/use-scene-wall-slot-migration.test.js +210 -0
- package/dist/store/use-scene-window-migration.test.d.ts +2 -0
- package/dist/store/use-scene-window-migration.test.d.ts.map +1 -0
- package/dist/store/use-scene-window-migration.test.js +85 -0
- package/dist/store/use-scene.d.ts +28 -2
- package/dist/store/use-scene.d.ts.map +1 -1
- package/dist/store/use-scene.js +546 -49
- package/dist/systems/elevator/elevator-dispatch.d.ts +12 -0
- package/dist/systems/elevator/elevator-dispatch.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-dispatch.js +57 -0
- package/dist/systems/elevator/elevator-geometry.d.ts +15 -0
- package/dist/systems/elevator/elevator-geometry.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-geometry.js +50 -0
- package/dist/systems/elevator/elevator-opening-sync.d.ts +6 -0
- package/dist/systems/elevator/elevator-opening-sync.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-opening-sync.js +218 -0
- package/dist/systems/elevator/elevator-opening-sync.test.d.ts +2 -0
- package/dist/systems/elevator/elevator-opening-sync.test.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-opening-sync.test.js +146 -0
- package/dist/systems/elevator/elevator-opening-system.d.ts +2 -0
- package/dist/systems/elevator/elevator-opening-system.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-opening-system.js +48 -0
- package/dist/systems/elevator/elevator-runtime-system.d.ts +2 -0
- package/dist/systems/elevator/elevator-runtime-system.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-runtime-system.js +8 -0
- package/dist/systems/elevator/elevator-runtime.d.ts +18 -0
- package/dist/systems/elevator/elevator-runtime.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-runtime.js +225 -0
- package/dist/systems/elevator/elevator-runtime.test.d.ts +2 -0
- package/dist/systems/elevator/elevator-runtime.test.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-runtime.test.js +64 -0
- package/dist/systems/elevator/elevator-service.d.ts +19 -0
- package/dist/systems/elevator/elevator-service.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-service.js +111 -0
- package/dist/systems/fence/fence-centerline.d.ts +12 -0
- package/dist/systems/fence/fence-centerline.d.ts.map +1 -0
- package/dist/systems/fence/fence-centerline.js +37 -0
- package/dist/systems/fence/fence-spline.d.ts +39 -0
- package/dist/systems/fence/fence-spline.d.ts.map +1 -0
- package/dist/systems/fence/fence-spline.js +196 -0
- package/dist/systems/fence/fence-spline.test.d.ts +2 -0
- package/dist/systems/fence/fence-spline.test.d.ts.map +1 -0
- package/dist/systems/fence/fence-spline.test.js +136 -0
- package/dist/systems/stair/stair-footprint.d.ts +44 -0
- package/dist/systems/stair/stair-footprint.d.ts.map +1 -0
- package/dist/systems/stair/stair-footprint.js +178 -0
- package/dist/systems/stair/stair-opening-preview.d.ts +2447 -0
- package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -0
- package/dist/systems/stair/stair-opening-preview.js +93 -0
- package/dist/systems/stair/stair-opening-preview.test.d.ts +2 -0
- package/dist/systems/stair/stair-opening-preview.test.d.ts.map +1 -0
- package/dist/systems/stair/stair-opening-preview.test.js +80 -0
- package/dist/systems/stair/stair-opening-sync.d.ts.map +1 -1
- package/dist/systems/stair/stair-opening-sync.js +155 -147
- package/dist/systems/stair/stair-opening-sync.test.js +424 -2
- package/dist/systems/stair/stair-opening-system.d.ts +2 -0
- package/dist/systems/stair/stair-opening-system.d.ts.map +1 -0
- package/dist/systems/stair/stair-opening-system.js +104 -0
- package/dist/systems/wall/wall-mitering.d.ts.map +1 -1
- package/dist/systems/wall/wall-mitering.js +38 -2
- package/dist/systems/wall/wall-mitering.test.d.ts +2 -0
- package/dist/systems/wall/wall-mitering.test.d.ts.map +1 -0
- package/dist/systems/wall/wall-mitering.test.js +63 -0
- package/dist/systems/wall/wall-move.d.ts +48 -0
- package/dist/systems/wall/wall-move.d.ts.map +1 -0
- package/dist/systems/wall/wall-move.js +193 -0
- package/dist/utils/clone-scene-graph.d.ts +7 -4
- package/dist/utils/clone-scene-graph.d.ts.map +1 -1
- package/dist/utils/clone-scene-graph.js +29 -7
- package/dist/utils/clone-scene-graph.test.d.ts +2 -0
- package/dist/utils/clone-scene-graph.test.d.ts.map +1 -0
- package/dist/utils/clone-scene-graph.test.js +62 -0
- package/dist/utils/heal-scene-graph.d.ts +18 -0
- package/dist/utils/heal-scene-graph.d.ts.map +1 -0
- package/dist/utils/heal-scene-graph.js +90 -0
- package/dist/utils/heal-scene-graph.test.d.ts +2 -0
- package/dist/utils/heal-scene-graph.test.d.ts.map +1 -0
- package/dist/utils/heal-scene-graph.test.js +88 -0
- package/dist/validation/validate-build-json.d.ts +44 -0
- package/dist/validation/validate-build-json.d.ts.map +1 -0
- package/dist/validation/validate-build-json.js +256 -0
- package/package.json +11 -4
|
@@ -1,4 +1,389 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { nodeRegistry } from '../../registry/registry';
|
|
2
|
+
import { AnyNode as AnyNodeSchema, createDefaultRidgeVentsForSegment, getEffectiveWallSurfaceMaterial, getWallSurfaceMaterialSignature, isAutoRidgeVentEnabled, isDefaultRidgeVentNode, } from '../../schema';
|
|
3
|
+
const DEFAULT_RIDGE_VENT_REFRESH_FIELDS = new Set([
|
|
4
|
+
'roofType',
|
|
5
|
+
'width',
|
|
6
|
+
'depth',
|
|
7
|
+
'pitch',
|
|
8
|
+
'overhang',
|
|
9
|
+
'wallThickness',
|
|
10
|
+
'shingleThickness',
|
|
11
|
+
'gambrelLowerWidthRatio',
|
|
12
|
+
'mansardSteepWidthRatio',
|
|
13
|
+
'dutchHipWidthRatio',
|
|
14
|
+
'dutchWaistLengthRatio',
|
|
15
|
+
'dutchGabletRake',
|
|
16
|
+
]);
|
|
17
|
+
const NUMBER_FORMAT_BOUNDS = {
|
|
18
|
+
safeint: [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER],
|
|
19
|
+
int32: [-2147483648, 2147483647],
|
|
20
|
+
uint32: [0, 4294967295],
|
|
21
|
+
float32: [-3.4028234663852886e38, 3.4028234663852886e38],
|
|
22
|
+
};
|
|
23
|
+
const INTEGER_NUMBER_FORMATS = new Set(['safeint', 'int32', 'uint32']);
|
|
24
|
+
function getSchemaDef(schema) {
|
|
25
|
+
return schema?._zod?.def ?? schema?.def;
|
|
26
|
+
}
|
|
27
|
+
function getSchemaDefault(schema) {
|
|
28
|
+
const def = getSchemaDef(schema);
|
|
29
|
+
if (!(def?.type === 'default' || def?.type === 'prefault'))
|
|
30
|
+
return undefined;
|
|
31
|
+
return def.defaultValue;
|
|
32
|
+
}
|
|
33
|
+
function unwrapSchema(schema) {
|
|
34
|
+
let current = schema ?? null;
|
|
35
|
+
while (current) {
|
|
36
|
+
const def = getSchemaDef(current);
|
|
37
|
+
if (!(def?.type === 'default' ||
|
|
38
|
+
def?.type === 'prefault' ||
|
|
39
|
+
def?.type === 'optional' ||
|
|
40
|
+
def?.type === 'nullable' ||
|
|
41
|
+
def?.type === 'catch' ||
|
|
42
|
+
def?.type === 'readonly' ||
|
|
43
|
+
def?.type === 'nonoptional')) {
|
|
44
|
+
return current;
|
|
45
|
+
}
|
|
46
|
+
current = def.innerType ?? null;
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
function getObjectShape(schema) {
|
|
51
|
+
const unwrapped = unwrapSchema(schema);
|
|
52
|
+
const def = getSchemaDef(unwrapped);
|
|
53
|
+
if (def?.type !== 'object')
|
|
54
|
+
return null;
|
|
55
|
+
return unwrapped?.shape ?? def.shape ?? null;
|
|
56
|
+
}
|
|
57
|
+
function schemaAllowsValue(schema, value) {
|
|
58
|
+
const unwrapped = unwrapSchema(schema);
|
|
59
|
+
if (!unwrapped)
|
|
60
|
+
return false;
|
|
61
|
+
const def = getSchemaDef(unwrapped);
|
|
62
|
+
if (unwrapped._zod?.values?.has(value))
|
|
63
|
+
return true;
|
|
64
|
+
if (Array.isArray(def?.values) && def.values.includes(value))
|
|
65
|
+
return true;
|
|
66
|
+
if (def?.entries && Object.values(def.entries).includes(value))
|
|
67
|
+
return true;
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
function getNodeSchemaForType(type) {
|
|
71
|
+
const schema = AnyNodeSchema;
|
|
72
|
+
const options = getSchemaDef(schema)?.options;
|
|
73
|
+
if (!options)
|
|
74
|
+
return null;
|
|
75
|
+
for (const option of options) {
|
|
76
|
+
const shape = getObjectShape(option);
|
|
77
|
+
if (shape?.type && schemaAllowsValue(shape.type, type)) {
|
|
78
|
+
return option;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
function applyLowerLimit(current, candidate) {
|
|
84
|
+
if (!current)
|
|
85
|
+
return candidate;
|
|
86
|
+
if (candidate.value > current.value)
|
|
87
|
+
return candidate;
|
|
88
|
+
if (candidate.value === current.value && !candidate.inclusive)
|
|
89
|
+
return candidate;
|
|
90
|
+
return current;
|
|
91
|
+
}
|
|
92
|
+
function applyUpperLimit(current, candidate) {
|
|
93
|
+
if (!current)
|
|
94
|
+
return candidate;
|
|
95
|
+
if (candidate.value < current.value)
|
|
96
|
+
return candidate;
|
|
97
|
+
if (candidate.value === current.value && !candidate.inclusive)
|
|
98
|
+
return candidate;
|
|
99
|
+
return current;
|
|
100
|
+
}
|
|
101
|
+
function getNumberConstraints(schema) {
|
|
102
|
+
const unwrapped = unwrapSchema(schema) ?? schema;
|
|
103
|
+
const def = getSchemaDef(unwrapped);
|
|
104
|
+
const constraints = { integer: false };
|
|
105
|
+
const minValue = unwrapped.minValue;
|
|
106
|
+
if (typeof minValue === 'number') {
|
|
107
|
+
constraints.min = applyLowerLimit(constraints.min, { value: minValue, inclusive: true });
|
|
108
|
+
}
|
|
109
|
+
const maxValue = unwrapped.maxValue;
|
|
110
|
+
if (typeof maxValue === 'number') {
|
|
111
|
+
constraints.max = applyUpperLimit(constraints.max, { value: maxValue, inclusive: true });
|
|
112
|
+
}
|
|
113
|
+
for (const check of def?.checks ?? []) {
|
|
114
|
+
const checkDef = check._zod?.def;
|
|
115
|
+
if (!checkDef)
|
|
116
|
+
continue;
|
|
117
|
+
if (checkDef.check === 'greater_than' && typeof checkDef.value === 'number') {
|
|
118
|
+
constraints.min = applyLowerLimit(constraints.min, {
|
|
119
|
+
value: checkDef.value,
|
|
120
|
+
inclusive: checkDef.inclusive !== false,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
else if (checkDef.check === 'less_than' && typeof checkDef.value === 'number') {
|
|
124
|
+
constraints.max = applyUpperLimit(constraints.max, {
|
|
125
|
+
value: checkDef.value,
|
|
126
|
+
inclusive: checkDef.inclusive !== false,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
else if (checkDef.check === 'number_format' && checkDef.format) {
|
|
130
|
+
constraints.integer ||= INTEGER_NUMBER_FORMATS.has(checkDef.format);
|
|
131
|
+
const bounds = NUMBER_FORMAT_BOUNDS[checkDef.format];
|
|
132
|
+
if (bounds) {
|
|
133
|
+
constraints.min = applyLowerLimit(constraints.min, {
|
|
134
|
+
value: bounds[0],
|
|
135
|
+
inclusive: true,
|
|
136
|
+
});
|
|
137
|
+
constraints.max = applyUpperLimit(constraints.max, {
|
|
138
|
+
value: bounds[1],
|
|
139
|
+
inclusive: true,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const bag = unwrapped._zod?.bag;
|
|
145
|
+
if (typeof bag?.minimum === 'number') {
|
|
146
|
+
constraints.min = applyLowerLimit(constraints.min, { value: bag.minimum, inclusive: true });
|
|
147
|
+
}
|
|
148
|
+
if (typeof bag?.exclusiveMinimum === 'number') {
|
|
149
|
+
constraints.min = applyLowerLimit(constraints.min, {
|
|
150
|
+
value: bag.exclusiveMinimum,
|
|
151
|
+
inclusive: false,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
if (typeof bag?.maximum === 'number') {
|
|
155
|
+
constraints.max = applyUpperLimit(constraints.max, { value: bag.maximum, inclusive: true });
|
|
156
|
+
}
|
|
157
|
+
if (typeof bag?.exclusiveMaximum === 'number') {
|
|
158
|
+
constraints.max = applyUpperLimit(constraints.max, {
|
|
159
|
+
value: bag.exclusiveMaximum,
|
|
160
|
+
inclusive: false,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return constraints;
|
|
164
|
+
}
|
|
165
|
+
function nextAbove(value) {
|
|
166
|
+
return value === 0 ? Number.EPSILON : value + Math.abs(value) * Number.EPSILON;
|
|
167
|
+
}
|
|
168
|
+
function nextBelow(value) {
|
|
169
|
+
return value === 0 ? -Number.EPSILON : value - Math.abs(value) * Number.EPSILON;
|
|
170
|
+
}
|
|
171
|
+
function clampNumber(value, constraints) {
|
|
172
|
+
let next = value;
|
|
173
|
+
let rounded = false;
|
|
174
|
+
let clamped = false;
|
|
175
|
+
if (constraints.integer && !Number.isInteger(next)) {
|
|
176
|
+
next = Math.round(next);
|
|
177
|
+
rounded = true;
|
|
178
|
+
}
|
|
179
|
+
if (constraints.min) {
|
|
180
|
+
const min = constraints.min.inclusive ? constraints.min.value : nextAbove(constraints.min.value);
|
|
181
|
+
if (next < min) {
|
|
182
|
+
next = min;
|
|
183
|
+
clamped = true;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (constraints.max) {
|
|
187
|
+
const max = constraints.max.inclusive ? constraints.max.value : nextBelow(constraints.max.value);
|
|
188
|
+
if (next > max) {
|
|
189
|
+
next = max;
|
|
190
|
+
clamped = true;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
value: next,
|
|
195
|
+
action: clamped ? 'clamped' : rounded ? 'rounded' : undefined,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function getFiniteFallbackNumber(fallback, constraints) {
|
|
199
|
+
if (typeof fallback !== 'number' || !Number.isFinite(fallback))
|
|
200
|
+
return undefined;
|
|
201
|
+
return clampNumber(fallback, constraints).value;
|
|
202
|
+
}
|
|
203
|
+
function sanitizeNumber(schema, value, fallback, path) {
|
|
204
|
+
const constraints = schema ? getNumberConstraints(schema) : { integer: false };
|
|
205
|
+
if (!Number.isFinite(value)) {
|
|
206
|
+
const replacement = getFiniteFallbackNumber(fallback, constraints);
|
|
207
|
+
if (replacement === undefined) {
|
|
208
|
+
return {
|
|
209
|
+
value,
|
|
210
|
+
omit: true,
|
|
211
|
+
issues: [{ path, from: value, action: 'dropped' }],
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
value: replacement,
|
|
216
|
+
issues: [{ path, from: value, to: replacement, action: 'dropped' }],
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
const clamped = clampNumber(value, constraints);
|
|
220
|
+
if (!Object.is(clamped.value, value)) {
|
|
221
|
+
return {
|
|
222
|
+
value: clamped.value,
|
|
223
|
+
issues: [
|
|
224
|
+
{
|
|
225
|
+
path,
|
|
226
|
+
from: value,
|
|
227
|
+
to: clamped.value,
|
|
228
|
+
action: clamped.action ?? 'clamped',
|
|
229
|
+
},
|
|
230
|
+
],
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
return { value, issues: [] };
|
|
234
|
+
}
|
|
235
|
+
function sanitizeNumericValue(schema, value, fallback, path) {
|
|
236
|
+
const defaultFallback = schema ? getSchemaDefault(schema) : undefined;
|
|
237
|
+
const effectiveFallback = fallback === undefined ? defaultFallback : fallback;
|
|
238
|
+
const unwrapped = unwrapSchema(schema);
|
|
239
|
+
const def = getSchemaDef(unwrapped);
|
|
240
|
+
if (def?.type === 'number') {
|
|
241
|
+
if (typeof value !== 'number')
|
|
242
|
+
return { value, issues: [] };
|
|
243
|
+
return sanitizeNumber(unwrapped, value, effectiveFallback, path);
|
|
244
|
+
}
|
|
245
|
+
if (typeof value === 'number') {
|
|
246
|
+
return sanitizeNumber(null, value, effectiveFallback, path);
|
|
247
|
+
}
|
|
248
|
+
if (def?.type === 'tuple' && Array.isArray(value)) {
|
|
249
|
+
const fallbackItems = Array.isArray(effectiveFallback) ? effectiveFallback : [];
|
|
250
|
+
const next = [...value];
|
|
251
|
+
const issues = [];
|
|
252
|
+
for (let index = 0; index < next.length; index += 1) {
|
|
253
|
+
const itemSchema = def.items?.[index] ?? def.rest ?? null;
|
|
254
|
+
const child = sanitizeNumericValue(itemSchema, next[index], fallbackItems[index], [
|
|
255
|
+
...path,
|
|
256
|
+
index,
|
|
257
|
+
]);
|
|
258
|
+
issues.push(...child.issues);
|
|
259
|
+
if (child.omit) {
|
|
260
|
+
return { value, omit: true, issues };
|
|
261
|
+
}
|
|
262
|
+
next[index] = child.value;
|
|
263
|
+
}
|
|
264
|
+
return { value: issues.length > 0 ? next : value, issues };
|
|
265
|
+
}
|
|
266
|
+
if (def?.type === 'array' && Array.isArray(value)) {
|
|
267
|
+
const fallbackItems = Array.isArray(effectiveFallback) ? effectiveFallback : [];
|
|
268
|
+
const next = [];
|
|
269
|
+
const issues = [];
|
|
270
|
+
let omitted = false;
|
|
271
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
272
|
+
const child = sanitizeNumericValue(def.element ?? null, value[index], fallbackItems[index], [
|
|
273
|
+
...path,
|
|
274
|
+
index,
|
|
275
|
+
]);
|
|
276
|
+
issues.push(...child.issues);
|
|
277
|
+
if (child.omit) {
|
|
278
|
+
omitted = true;
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
next.push(child.value);
|
|
282
|
+
}
|
|
283
|
+
return { value: issues.length > 0 || omitted ? next : value, issues };
|
|
284
|
+
}
|
|
285
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
286
|
+
const shape = def?.type === 'object' ? (unwrapped?.shape ?? def.shape ?? {}) : {};
|
|
287
|
+
const fallbackObject = effectiveFallback &&
|
|
288
|
+
typeof effectiveFallback === 'object' &&
|
|
289
|
+
!Array.isArray(effectiveFallback)
|
|
290
|
+
? effectiveFallback
|
|
291
|
+
: {};
|
|
292
|
+
const input = value;
|
|
293
|
+
const next = { ...input };
|
|
294
|
+
const issues = [];
|
|
295
|
+
for (const key of Object.keys(input)) {
|
|
296
|
+
const child = sanitizeNumericValue(shape[key] ?? null, input[key], fallbackObject[key], [
|
|
297
|
+
...path,
|
|
298
|
+
key,
|
|
299
|
+
]);
|
|
300
|
+
issues.push(...child.issues);
|
|
301
|
+
if (child.omit) {
|
|
302
|
+
delete next[key];
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
next[key] = child.value;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return { value: issues.length > 0 ? next : value, issues };
|
|
309
|
+
}
|
|
310
|
+
return { value, issues: [] };
|
|
311
|
+
}
|
|
312
|
+
function formatNumericValue(value) {
|
|
313
|
+
if (Number.isNaN(value))
|
|
314
|
+
return 'NaN';
|
|
315
|
+
if (value === Infinity)
|
|
316
|
+
return 'Infinity';
|
|
317
|
+
if (value === -Infinity)
|
|
318
|
+
return '-Infinity';
|
|
319
|
+
return String(value);
|
|
320
|
+
}
|
|
321
|
+
function numericSanitizeIssuesToMessage(issues) {
|
|
322
|
+
return issues
|
|
323
|
+
.map((issue) => {
|
|
324
|
+
const path = issue.path.map(String).join('.') || '<root>';
|
|
325
|
+
const to = issue.to === undefined ? '' : ` -> ${formatNumericValue(issue.to)}`;
|
|
326
|
+
return `${path}: ${formatNumericValue(issue.from)} ${issue.action}${to}`;
|
|
327
|
+
})
|
|
328
|
+
.join('; ');
|
|
329
|
+
}
|
|
330
|
+
function warnSanitizedNodeMutation(mutation, nodeId, issues) {
|
|
331
|
+
console.warn(`[Scene] Sanitized invalid numeric node ${mutation}`, nodeId, numericSanitizeIssuesToMessage(issues));
|
|
332
|
+
}
|
|
333
|
+
function parseCreatedNode(node, parentId) {
|
|
334
|
+
const candidate = { ...node, parentId };
|
|
335
|
+
const parsed = AnyNodeSchema.safeParse(candidate);
|
|
336
|
+
if (parsed.success)
|
|
337
|
+
return parsed.data;
|
|
338
|
+
const schema = getNodeSchemaForType(candidate.type);
|
|
339
|
+
const sanitized = sanitizeNumericValue(schema, candidate, undefined, []);
|
|
340
|
+
if (sanitized.issues.length === 0) {
|
|
341
|
+
return candidate;
|
|
342
|
+
}
|
|
343
|
+
warnSanitizedNodeMutation('create', node.id, sanitized.issues);
|
|
344
|
+
return sanitized.value;
|
|
345
|
+
}
|
|
346
|
+
function parseUpdatedNode(currentNode, data) {
|
|
347
|
+
const candidate = { ...currentNode, ...data };
|
|
348
|
+
const parsed = AnyNodeSchema.safeParse(candidate);
|
|
349
|
+
if (parsed.success)
|
|
350
|
+
return parsed.data;
|
|
351
|
+
const schema = getNodeSchemaForType(candidate.type);
|
|
352
|
+
const sanitized = sanitizeNumericValue(schema, data, currentNode, []);
|
|
353
|
+
if (sanitized.issues.length === 0) {
|
|
354
|
+
return candidate;
|
|
355
|
+
}
|
|
356
|
+
warnSanitizedNodeMutation('update', currentNode.id, sanitized.issues);
|
|
357
|
+
return { ...currentNode, ...sanitized.value };
|
|
358
|
+
}
|
|
359
|
+
function shouldRefreshDefaultRidgeVents(data) {
|
|
360
|
+
return Object.keys(data).some((key) => DEFAULT_RIDGE_VENT_REFRESH_FIELDS.has(key));
|
|
361
|
+
}
|
|
362
|
+
function refreshDefaultRidgeVentsForSegment(nextNodes, segment) {
|
|
363
|
+
const childIds = Array.isArray(segment.children) ? segment.children : [];
|
|
364
|
+
if (!isAutoRidgeVentEnabled(segment, nextNodes))
|
|
365
|
+
return [];
|
|
366
|
+
const defaultIds = childIds.filter((childId) => isDefaultRidgeVentNode(nextNodes[childId], segment.id));
|
|
367
|
+
const defaultIdSet = new Set(defaultIds);
|
|
368
|
+
for (const id of defaultIds) {
|
|
369
|
+
delete nextNodes[id];
|
|
370
|
+
}
|
|
371
|
+
const nextVents = createDefaultRidgeVentsForSegment(segment);
|
|
372
|
+
for (const vent of nextVents) {
|
|
373
|
+
nextNodes[vent.id] = {
|
|
374
|
+
...vent,
|
|
375
|
+
parentId: segment.id,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
nextNodes[segment.id] = {
|
|
379
|
+
...segment,
|
|
380
|
+
children: [
|
|
381
|
+
...childIds.filter((childId) => !defaultIdSet.has(childId)),
|
|
382
|
+
...nextVents.map((vent) => vent.id),
|
|
383
|
+
],
|
|
384
|
+
};
|
|
385
|
+
return nextVents.map((vent) => vent.id);
|
|
386
|
+
}
|
|
2
387
|
// Track pending RAF for updateNodesAction to prevent multiple queued callbacks
|
|
3
388
|
let pendingRafId = null;
|
|
4
389
|
let pendingUpdates = new Set();
|
|
@@ -154,21 +539,25 @@ export const createNodesAction = (set, get, ops) => {
|
|
|
154
539
|
const nextRootIds = [...state.rootNodeIds];
|
|
155
540
|
for (const { node, parentId } of ops) {
|
|
156
541
|
const effectiveParentId = parentId ?? node.parentId ?? null;
|
|
157
|
-
|
|
158
|
-
const newNode = {
|
|
159
|
-
...node,
|
|
160
|
-
parentId: effectiveParentId,
|
|
161
|
-
};
|
|
542
|
+
const newNode = parseCreatedNode(node, effectiveParentId);
|
|
162
543
|
nextNodes[newNode.id] = newNode;
|
|
163
|
-
// 2. Update the Parent's children list
|
|
544
|
+
// 2. Update the Parent's children list. We append to ANY container
|
|
545
|
+
// parent (kind has `children` in its schema) — if the field is
|
|
546
|
+
// present but undefined (e.g. an old saved scene from before the
|
|
547
|
+
// kind gained children), we initialise to `[]` first so the
|
|
548
|
+
// reparenting goes through. Without this, hosting items on an
|
|
549
|
+
// old shelf (v1, before `children` was added) silently no-ops:
|
|
550
|
+
// the item is reparented to the shelf but the shelf's children
|
|
551
|
+
// array is never updated, so `ParametricNodeRenderer` doesn't
|
|
552
|
+
// mount it and the item "disappears".
|
|
164
553
|
if (effectiveParentId && nextNodes[effectiveParentId]) {
|
|
165
554
|
const parent = nextNodes[effectiveParentId];
|
|
166
|
-
|
|
167
|
-
|
|
555
|
+
if ('children' in parent) {
|
|
556
|
+
const existing = parent.children;
|
|
557
|
+
const children = Array.isArray(existing) ? existing : [];
|
|
168
558
|
nextNodes[effectiveParentId] = {
|
|
169
559
|
...parent,
|
|
170
|
-
|
|
171
|
-
children: Array.from(new Set([...parent.children, newNode.id])), // We don't verify child types here
|
|
560
|
+
children: Array.from(new Set([...children, newNode.id])),
|
|
172
561
|
};
|
|
173
562
|
}
|
|
174
563
|
}
|
|
@@ -190,41 +579,183 @@ export const createNodesAction = (set, get, ops) => {
|
|
|
190
579
|
get().markDirty(node.parentId);
|
|
191
580
|
});
|
|
192
581
|
};
|
|
582
|
+
export const applyNodeChangesAction = (set, get, changes) => {
|
|
583
|
+
if (get().readOnly)
|
|
584
|
+
return;
|
|
585
|
+
const createOps = changes.create ?? [];
|
|
586
|
+
const updateOps = changes.update ?? [];
|
|
587
|
+
const deleteOps = changes.delete ?? [];
|
|
588
|
+
const nodesToMarkDirty = new Set();
|
|
589
|
+
const parentsToMarkDirty = new Set();
|
|
590
|
+
set((state) => {
|
|
591
|
+
const nextNodes = { ...state.nodes };
|
|
592
|
+
const nextCollections = { ...state.collections };
|
|
593
|
+
const nextRootIds = [...state.rootNodeIds];
|
|
594
|
+
let resolvedRootIds = nextRootIds;
|
|
595
|
+
for (const { id, data } of updateOps) {
|
|
596
|
+
const currentNode = nextNodes[id];
|
|
597
|
+
if (!currentNode)
|
|
598
|
+
continue;
|
|
599
|
+
const updatedNode = parseUpdatedNode(currentNode, data);
|
|
600
|
+
if (data.parentId !== undefined && data.parentId !== currentNode.parentId) {
|
|
601
|
+
const oldParentId = currentNode.parentId;
|
|
602
|
+
if (oldParentId && nextNodes[oldParentId]) {
|
|
603
|
+
const oldParent = nextNodes[oldParentId];
|
|
604
|
+
nextNodes[oldParent.id] = {
|
|
605
|
+
...oldParent,
|
|
606
|
+
children: oldParent.children.filter((childId) => childId !== id),
|
|
607
|
+
};
|
|
608
|
+
parentsToMarkDirty.add(oldParent.id);
|
|
609
|
+
}
|
|
610
|
+
const newParentId = data.parentId;
|
|
611
|
+
if (newParentId && nextNodes[newParentId]) {
|
|
612
|
+
const newParent = nextNodes[newParentId];
|
|
613
|
+
nextNodes[newParent.id] = {
|
|
614
|
+
...newParent,
|
|
615
|
+
children: Array.from(new Set([...newParent.children, id])),
|
|
616
|
+
};
|
|
617
|
+
parentsToMarkDirty.add(newParent.id);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
nextNodes[id] = updatedNode;
|
|
621
|
+
if (updatedNode.type === 'roof-segment' && shouldRefreshDefaultRidgeVents(data)) {
|
|
622
|
+
for (const ventId of refreshDefaultRidgeVentsForSegment(nextNodes, updatedNode)) {
|
|
623
|
+
nodesToMarkDirty.add(ventId);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
nodesToMarkDirty.add(id);
|
|
627
|
+
}
|
|
628
|
+
for (const { node, parentId } of createOps) {
|
|
629
|
+
const effectiveParentId = parentId ?? node.parentId ?? null;
|
|
630
|
+
const newNode = parseCreatedNode(node, effectiveParentId);
|
|
631
|
+
nextNodes[newNode.id] = newNode;
|
|
632
|
+
nodesToMarkDirty.add(newNode.id);
|
|
633
|
+
if (effectiveParentId && nextNodes[effectiveParentId]) {
|
|
634
|
+
const parent = nextNodes[effectiveParentId];
|
|
635
|
+
if ('children' in parent && Array.isArray(parent.children)) {
|
|
636
|
+
nextNodes[effectiveParentId] = {
|
|
637
|
+
...parent,
|
|
638
|
+
children: Array.from(new Set([...parent.children, newNode.id])),
|
|
639
|
+
};
|
|
640
|
+
parentsToMarkDirty.add(effectiveParentId);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
else if (!effectiveParentId && !nextRootIds.includes(newNode.id)) {
|
|
644
|
+
nextRootIds.push(newNode.id);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
const allIdsToDelete = new Set();
|
|
648
|
+
const collectDelete = (id) => {
|
|
649
|
+
if (allIdsToDelete.has(id))
|
|
650
|
+
return;
|
|
651
|
+
allIdsToDelete.add(id);
|
|
652
|
+
const node = nextNodes[id];
|
|
653
|
+
if (node && 'children' in node && Array.isArray(node.children)) {
|
|
654
|
+
for (const childId of node.children) {
|
|
655
|
+
collectDelete(childId);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
for (const id of deleteOps) {
|
|
660
|
+
collectDelete(id);
|
|
661
|
+
}
|
|
662
|
+
for (const id of allIdsToDelete) {
|
|
663
|
+
const node = nextNodes[id];
|
|
664
|
+
if (!node)
|
|
665
|
+
continue;
|
|
666
|
+
const parentId = node.parentId;
|
|
667
|
+
if (parentId && nextNodes[parentId] && !allIdsToDelete.has(parentId)) {
|
|
668
|
+
const parent = nextNodes[parentId];
|
|
669
|
+
if (parent.children) {
|
|
670
|
+
nextNodes[parent.id] = {
|
|
671
|
+
...parent,
|
|
672
|
+
children: parent.children.filter((childId) => childId !== id),
|
|
673
|
+
};
|
|
674
|
+
parentsToMarkDirty.add(parent.id);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
resolvedRootIds = resolvedRootIds.filter((rootId) => rootId !== id);
|
|
678
|
+
if ('collectionIds' in node && node.collectionIds) {
|
|
679
|
+
for (const collectionId of node.collectionIds) {
|
|
680
|
+
const collection = nextCollections[collectionId];
|
|
681
|
+
if (collection) {
|
|
682
|
+
nextCollections[collectionId] = {
|
|
683
|
+
...collection,
|
|
684
|
+
nodeIds: collection.nodeIds.filter((nodeId) => nodeId !== id),
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
delete nextNodes[id];
|
|
690
|
+
}
|
|
691
|
+
return { nodes: nextNodes, rootNodeIds: resolvedRootIds, collections: nextCollections };
|
|
692
|
+
});
|
|
693
|
+
for (const id of nodesToMarkDirty) {
|
|
694
|
+
get().markDirty(id);
|
|
695
|
+
}
|
|
696
|
+
for (const id of parentsToMarkDirty) {
|
|
697
|
+
get().markDirty(id);
|
|
698
|
+
const parent = get().nodes[id];
|
|
699
|
+
if (parent && 'children' in parent && Array.isArray(parent.children)) {
|
|
700
|
+
for (const childId of parent.children) {
|
|
701
|
+
get().markDirty(childId);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
};
|
|
193
706
|
export const updateNodesAction = (set, get, updates) => {
|
|
194
707
|
if (get().readOnly)
|
|
195
708
|
return;
|
|
196
709
|
const parentsToUpdate = new Set();
|
|
710
|
+
const extraNodesToUpdate = new Set();
|
|
197
711
|
set((state) => {
|
|
198
712
|
const nextNodes = { ...state.nodes };
|
|
199
713
|
for (const { id, data } of updates) {
|
|
200
714
|
const currentNode = nextNodes[id];
|
|
201
715
|
if (!currentNode)
|
|
202
716
|
continue;
|
|
717
|
+
const updatedNode = parseUpdatedNode(currentNode, data);
|
|
203
718
|
// Handle Reparenting Logic
|
|
204
719
|
if (data.parentId !== undefined && data.parentId !== currentNode.parentId) {
|
|
205
720
|
// 1. Remove from old parent
|
|
206
721
|
const oldParentId = currentNode.parentId;
|
|
207
722
|
if (oldParentId && nextNodes[oldParentId]) {
|
|
208
723
|
const oldParent = nextNodes[oldParentId];
|
|
724
|
+
const oldChildren = Array.isArray(oldParent.children)
|
|
725
|
+
? oldParent.children
|
|
726
|
+
: [];
|
|
209
727
|
nextNodes[oldParent.id] = {
|
|
210
728
|
...oldParent,
|
|
211
|
-
children:
|
|
729
|
+
children: oldChildren.filter((childId) => childId !== id),
|
|
212
730
|
};
|
|
213
731
|
parentsToUpdate.add(oldParent.id);
|
|
214
732
|
}
|
|
215
|
-
// 2. Add to new parent
|
|
733
|
+
// 2. Add to new parent. Defensive against parents that don't yet
|
|
734
|
+
// carry a `children` array — older saved scenes can predate the
|
|
735
|
+
// schema field on a particular kind (shelf v1 → v2 added one),
|
|
736
|
+
// and a spread of `undefined` here throws and aborts the entire
|
|
737
|
+
// `set` callback. Initialising to `[]` matches what the schema's
|
|
738
|
+
// default would have produced.
|
|
216
739
|
const newParentId = data.parentId;
|
|
217
740
|
if (newParentId && nextNodes[newParentId]) {
|
|
218
741
|
const newParent = nextNodes[newParentId];
|
|
742
|
+
const newChildren = Array.isArray(newParent.children)
|
|
743
|
+
? newParent.children
|
|
744
|
+
: [];
|
|
219
745
|
nextNodes[newParent.id] = {
|
|
220
746
|
...newParent,
|
|
221
|
-
children: Array.from(new Set([...
|
|
747
|
+
children: Array.from(new Set([...newChildren, id])),
|
|
222
748
|
};
|
|
223
749
|
parentsToUpdate.add(newParent.id);
|
|
224
750
|
}
|
|
225
751
|
}
|
|
226
752
|
// Apply the update
|
|
227
|
-
nextNodes[id] =
|
|
753
|
+
nextNodes[id] = updatedNode;
|
|
754
|
+
if (updatedNode.type === 'roof-segment' && shouldRefreshDefaultRidgeVents(data)) {
|
|
755
|
+
for (const ventId of refreshDefaultRidgeVentsForSegment(nextNodes, updatedNode)) {
|
|
756
|
+
extraNodesToUpdate.add(ventId);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
228
759
|
}
|
|
229
760
|
return { nodes: nextNodes };
|
|
230
761
|
});
|
|
@@ -235,6 +766,9 @@ export const updateNodesAction = (set, get, updates) => {
|
|
|
235
766
|
for (const pId of parentsToUpdate) {
|
|
236
767
|
pendingUpdates.add(pId);
|
|
237
768
|
}
|
|
769
|
+
for (const id of extraNodesToUpdate) {
|
|
770
|
+
pendingUpdates.add(id);
|
|
771
|
+
}
|
|
238
772
|
if (pendingRafId !== null) {
|
|
239
773
|
cancelAnimationFrame(pendingRafId);
|
|
240
774
|
}
|
|
@@ -251,6 +785,7 @@ export const deleteNodesAction = (set, get, ids) => {
|
|
|
251
785
|
return;
|
|
252
786
|
const parentsToMarkDirty = new Set();
|
|
253
787
|
const nodesToMarkDirty = new Set();
|
|
788
|
+
const deletedIds = new Set();
|
|
254
789
|
const mergePlans = buildWallMergePlans(get().nodes, ids);
|
|
255
790
|
set((state) => {
|
|
256
791
|
const nextNodes = { ...state.nodes };
|
|
@@ -264,6 +799,13 @@ export const deleteNodesAction = (set, get, ids) => {
|
|
|
264
799
|
return;
|
|
265
800
|
allIds.add(id);
|
|
266
801
|
const node = nextNodes[id];
|
|
802
|
+
const cascadeDeletes = node
|
|
803
|
+
? nodeRegistry.get(node.type)?.parametrics?.onDeleteCascade?.(node, nextNodes, allIds)
|
|
804
|
+
: null;
|
|
805
|
+
if (cascadeDeletes) {
|
|
806
|
+
for (const companionId of cascadeDeletes)
|
|
807
|
+
collect(companionId);
|
|
808
|
+
}
|
|
267
809
|
if (node && 'children' in node) {
|
|
268
810
|
for (const cid of node.children)
|
|
269
811
|
collect(cid);
|
|
@@ -274,6 +816,29 @@ export const deleteNodesAction = (set, get, ids) => {
|
|
|
274
816
|
for (const plan of mergePlans) {
|
|
275
817
|
allIds.add(plan.secondaryWallId);
|
|
276
818
|
}
|
|
819
|
+
for (const id of allIds)
|
|
820
|
+
deletedIds.add(id);
|
|
821
|
+
// Let each deleted kind undo what it imposed on its neighbours (e.g. an
|
|
822
|
+
// auto-inserted elbow re-extends the duct runs it trimmed back onto the
|
|
823
|
+
// corner it replaced). Read against pre-deletion `nextNodes`; skip
|
|
824
|
+
// patches that target a node also being deleted.
|
|
825
|
+
for (const id of allIds) {
|
|
826
|
+
const node = nextNodes[id];
|
|
827
|
+
if (!node)
|
|
828
|
+
continue;
|
|
829
|
+
const onDelete = nodeRegistry.get(node.type)?.parametrics?.onDelete;
|
|
830
|
+
if (!onDelete)
|
|
831
|
+
continue;
|
|
832
|
+
for (const { id: targetId, data } of onDelete(node, nextNodes)) {
|
|
833
|
+
if (allIds.has(targetId))
|
|
834
|
+
continue;
|
|
835
|
+
const target = nextNodes[targetId];
|
|
836
|
+
if (!target)
|
|
837
|
+
continue;
|
|
838
|
+
nextNodes[targetId] = { ...target, ...data };
|
|
839
|
+
nodesToMarkDirty.add(targetId);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
277
842
|
for (const plan of mergePlans) {
|
|
278
843
|
const primaryWall = nextNodes[plan.primaryWallId];
|
|
279
844
|
if (!(primaryWall && primaryWall.type === 'wall') || allIds.has(plan.primaryWallId)) {
|
|
@@ -328,6 +893,11 @@ export const deleteNodesAction = (set, get, ids) => {
|
|
|
328
893
|
}
|
|
329
894
|
return { nodes: nextNodes, rootNodeIds: nextRootIds, collections: nextCollections };
|
|
330
895
|
});
|
|
896
|
+
// Deleted ids must leave the dirty set: every consumer skips missing
|
|
897
|
+
// nodes without clearing them, so a mark on a deleted node would sit in
|
|
898
|
+
// the set (and defeat the consumers' empty-set early exit) forever.
|
|
899
|
+
for (const id of deletedIds)
|
|
900
|
+
get().clearDirty(id);
|
|
331
901
|
// Mark affected nodes dirty: parents of deleted nodes and their remaining children
|
|
332
902
|
// (e.g. deleting a slab affects sibling walls via level elevation changes)
|
|
333
903
|
parentsToMarkDirty.forEach((parentId) => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-mutation-sanitize.test.d.ts","sourceRoot":"","sources":["../../../src/store/actions/node-mutation-sanitize.test.ts"],"names":[],"mappings":""}
|