@pascal-app/core 1.0.0 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (345) hide show
  1. package/dist/capture/index.d.ts +2 -2
  2. package/dist/capture/index.js +2 -2
  3. package/dist/capture/schema.d.ts.map +1 -1
  4. package/dist/capture/schema.js +2 -0
  5. package/dist/capture/source.d.ts +1 -1
  6. package/dist/capture/source.js +1 -1
  7. package/dist/events/bus.d.ts +6 -3
  8. package/dist/events/bus.d.ts.map +1 -1
  9. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +4 -4
  10. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -1
  11. package/dist/hooks/spatial-grid/floor-placed-elevation.js +7 -12
  12. package/dist/hooks/spatial-grid/floor-placed-footprints.d.ts +4 -0
  13. package/dist/hooks/spatial-grid/floor-placed-footprints.d.ts.map +1 -0
  14. package/dist/hooks/spatial-grid/floor-placed-footprints.js +7 -0
  15. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +5 -8
  16. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
  17. package/dist/hooks/spatial-grid/spatial-grid-manager.js +23 -106
  18. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +263 -84
  19. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
  20. package/dist/hooks/spatial-grid/spatial-grid-sync.js +77 -13
  21. package/dist/hooks/spatial-grid/support-host-patch.d.ts +1 -1
  22. package/dist/hooks/spatial-grid/support-host-patch.js +6 -6
  23. package/dist/hooks/spatial-grid/use-spatial-query.d.ts +1 -1
  24. package/dist/hooks/spatial-grid/use-spatial-query.js +1 -1
  25. package/dist/index.d.ts +77 -72
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +74 -69
  28. package/dist/lib/door-operation.d.ts +1 -1
  29. package/dist/lib/item-polygon-overlap.d.ts +6 -0
  30. package/dist/lib/item-polygon-overlap.d.ts.map +1 -0
  31. package/dist/lib/item-polygon-overlap.js +67 -0
  32. package/dist/lib/level-name.d.ts +1 -1
  33. package/dist/lib/measurement-geometry.d.ts +4 -4
  34. package/dist/lib/node-visibility.d.ts +12 -0
  35. package/dist/lib/node-visibility.d.ts.map +1 -0
  36. package/dist/lib/node-visibility.js +12 -0
  37. package/dist/lib/plan-footprint.d.ts +41 -0
  38. package/dist/lib/plan-footprint.d.ts.map +1 -0
  39. package/dist/lib/plan-footprint.js +58 -0
  40. package/dist/lib/room-topology-index.d.ts +1 -1
  41. package/dist/lib/room-topology-index.js +1 -1
  42. package/dist/lib/selection-proxy.d.ts +1 -1
  43. package/dist/lib/slab-polygon.d.ts +2 -2
  44. package/dist/lib/slab-polygon.js +2 -2
  45. package/dist/lib/space-detection.d.ts +1 -1
  46. package/dist/lib/space-detection.d.ts.map +1 -1
  47. package/dist/lib/space-detection.js +16 -11
  48. package/dist/lib/terrain-brush.d.ts +1 -1
  49. package/dist/lib/terrain-brush.js +1 -1
  50. package/dist/lib/terrain-codec.d.ts +2 -2
  51. package/dist/lib/terrain-codec.js +1 -1
  52. package/dist/lib/terrain-raycast.d.ts +1 -1
  53. package/dist/lib/terrain-raycast.js +1 -1
  54. package/dist/lib/terrain-source.d.ts +3 -3
  55. package/dist/lib/terrain-source.js +3 -3
  56. package/dist/lib/terrain-support.d.ts +1 -1
  57. package/dist/lib/terrain-support.js +3 -3
  58. package/dist/lib/unit-containment.d.ts +19 -0
  59. package/dist/lib/unit-containment.d.ts.map +1 -0
  60. package/dist/lib/unit-containment.js +158 -0
  61. package/dist/lib/unit-report.d.ts +19 -0
  62. package/dist/lib/unit-report.d.ts.map +1 -0
  63. package/dist/lib/unit-report.js +36 -0
  64. package/dist/lib/wall-distance.d.ts +2 -2
  65. package/dist/lib/wall-distance.js +1 -1
  66. package/dist/lib/zone-quantities.d.ts +1 -1
  67. package/dist/lib/zone-quantities.js +7 -7
  68. package/dist/material-library.d.ts +1 -1
  69. package/dist/material-library.js +1 -1
  70. package/dist/procedural-items/fixtures.d.ts +261 -0
  71. package/dist/procedural-items/fixtures.d.ts.map +1 -0
  72. package/dist/procedural-items/fixtures.js +349 -0
  73. package/dist/procedural-items/index.d.ts +10 -0
  74. package/dist/procedural-items/index.d.ts.map +1 -0
  75. package/dist/procedural-items/index.js +9 -0
  76. package/dist/procedural-items/integration.d.ts +92 -0
  77. package/dist/procedural-items/integration.d.ts.map +1 -0
  78. package/dist/procedural-items/integration.js +19 -0
  79. package/dist/procedural-items/library-colors.d.ts +56 -0
  80. package/dist/procedural-items/library-colors.d.ts.map +1 -0
  81. package/dist/procedural-items/library-colors.js +84 -0
  82. package/dist/procedural-items/materials.d.ts +5 -0
  83. package/dist/procedural-items/materials.d.ts.map +1 -0
  84. package/dist/procedural-items/materials.js +47 -0
  85. package/dist/procedural-items/node.d.ts +280 -0
  86. package/dist/procedural-items/node.d.ts.map +1 -0
  87. package/dist/procedural-items/node.js +71 -0
  88. package/dist/procedural-items/placement.d.ts +7 -0
  89. package/dist/procedural-items/placement.d.ts.map +1 -0
  90. package/dist/procedural-items/placement.js +48 -0
  91. package/dist/procedural-items/query.d.ts +51 -0
  92. package/dist/procedural-items/query.d.ts.map +1 -0
  93. package/dist/procedural-items/query.js +342 -0
  94. package/dist/procedural-items/recipe.d.ts +144 -0
  95. package/dist/procedural-items/recipe.d.ts.map +1 -0
  96. package/dist/procedural-items/recipe.js +372 -0
  97. package/dist/procedural-items/spatial.d.ts +19 -0
  98. package/dist/procedural-items/spatial.d.ts.map +1 -0
  99. package/dist/procedural-items/spatial.js +39 -0
  100. package/dist/registry/__bench__/relations-resolver.bench.js +2 -2
  101. package/dist/registry/handles.d.ts +40 -5
  102. package/dist/registry/handles.d.ts.map +1 -1
  103. package/dist/registry/index.d.ts +6 -6
  104. package/dist/registry/index.d.ts.map +1 -1
  105. package/dist/registry/index.js +4 -4
  106. package/dist/registry/registry.d.ts +1 -1
  107. package/dist/registry/relations-resolver.d.ts +2 -2
  108. package/dist/registry/relations-resolver.js +1 -1
  109. package/dist/registry/scene-api.d.ts +2 -2
  110. package/dist/registry/scene-api.js +2 -2
  111. package/dist/registry/subtree.d.ts +1 -1
  112. package/dist/registry/subtree.d.ts.map +1 -1
  113. package/dist/registry/subtree.js +8 -2
  114. package/dist/registry/types.d.ts +32 -10
  115. package/dist/registry/types.d.ts.map +1 -1
  116. package/dist/registry/use-registry-version.js +1 -1
  117. package/dist/registry/validate-relations.d.ts +4 -0
  118. package/dist/registry/validate-relations.d.ts.map +1 -0
  119. package/dist/registry/validate-relations.js +22 -0
  120. package/dist/schema/__bench__/node-parsers.bench.js +3 -3
  121. package/dist/schema/__fixtures__/node-fixtures.d.ts +1 -1
  122. package/dist/schema/__fixtures__/node-fixtures.d.ts.map +1 -1
  123. package/dist/schema/__fixtures__/node-fixtures.js +4 -2
  124. package/dist/schema/base.js +1 -1
  125. package/dist/schema/collections.d.ts +1 -1
  126. package/dist/schema/collections.js +1 -1
  127. package/dist/schema/compiled-node-parsers.d.ts +1 -1
  128. package/dist/schema/compiled-node-parsers.js +1 -1
  129. package/dist/schema/index.d.ts +74 -70
  130. package/dist/schema/index.d.ts.map +1 -1
  131. package/dist/schema/index.js +65 -61
  132. package/dist/schema/material.d.ts +1 -1
  133. package/dist/schema/material.js +1 -1
  134. package/dist/schema/nodes/automatic-downspout.d.ts +4 -4
  135. package/dist/schema/nodes/automatic-downspout.js +5 -5
  136. package/dist/schema/nodes/block.d.ts +3 -3
  137. package/dist/schema/nodes/block.d.ts.map +1 -1
  138. package/dist/schema/nodes/block.js +24 -12
  139. package/dist/schema/nodes/box-vent.js +2 -2
  140. package/dist/schema/nodes/building.d.ts +1 -1
  141. package/dist/schema/nodes/building.d.ts.map +1 -1
  142. package/dist/schema/nodes/building.js +8 -5
  143. package/dist/schema/nodes/cabinet.d.ts +4 -4
  144. package/dist/schema/nodes/cabinet.js +4 -4
  145. package/dist/schema/nodes/ceiling.d.ts +1 -1
  146. package/dist/schema/nodes/ceiling.js +5 -5
  147. package/dist/schema/nodes/chimney.js +2 -2
  148. package/dist/schema/nodes/column.d.ts +1 -0
  149. package/dist/schema/nodes/column.d.ts.map +1 -1
  150. package/dist/schema/nodes/column.js +3 -2
  151. package/dist/schema/nodes/construction-dimension.d.ts +3 -3
  152. package/dist/schema/nodes/construction-dimension.js +2 -2
  153. package/dist/schema/nodes/cupola.d.ts +1 -1
  154. package/dist/schema/nodes/cupola.js +2 -2
  155. package/dist/schema/nodes/curtain-wall.d.ts +129 -0
  156. package/dist/schema/nodes/curtain-wall.d.ts.map +1 -0
  157. package/dist/schema/nodes/curtain-wall.js +49 -0
  158. package/dist/schema/nodes/door.d.ts +2 -2
  159. package/dist/schema/nodes/door.js +2 -2
  160. package/dist/schema/nodes/dormer.d.ts +3 -3
  161. package/dist/schema/nodes/dormer.js +4 -4
  162. package/dist/schema/nodes/downspout.js +2 -2
  163. package/dist/schema/nodes/duct-fitting.js +1 -1
  164. package/dist/schema/nodes/duct-segment.js +2 -2
  165. package/dist/schema/nodes/duct-terminal.js +1 -1
  166. package/dist/schema/nodes/elevator.js +2 -2
  167. package/dist/schema/nodes/eyebrow-vent.js +2 -2
  168. package/dist/schema/nodes/fence.js +2 -2
  169. package/dist/schema/nodes/guide.js +2 -2
  170. package/dist/schema/nodes/gutter.d.ts +1 -1
  171. package/dist/schema/nodes/gutter.js +4 -4
  172. package/dist/schema/nodes/hvac-equipment.js +1 -1
  173. package/dist/schema/nodes/imported-mesh.d.ts +40 -0
  174. package/dist/schema/nodes/imported-mesh.d.ts.map +1 -0
  175. package/dist/schema/nodes/imported-mesh.js +27 -0
  176. package/dist/schema/nodes/item.d.ts +3 -3
  177. package/dist/schema/nodes/item.js +3 -3
  178. package/dist/schema/nodes/lean-to-extension.js +4 -4
  179. package/dist/schema/nodes/level.d.ts +1 -1
  180. package/dist/schema/nodes/level.d.ts.map +1 -1
  181. package/dist/schema/nodes/level.js +1 -1
  182. package/dist/schema/nodes/lineset.js +1 -1
  183. package/dist/schema/nodes/liquid-line.js +1 -1
  184. package/dist/schema/nodes/measurement.js +2 -2
  185. package/dist/schema/nodes/pipe-fitting.d.ts +1 -1
  186. package/dist/schema/nodes/pipe-fitting.js +1 -1
  187. package/dist/schema/nodes/pipe-segment.d.ts +1 -1
  188. package/dist/schema/nodes/pipe-segment.js +2 -2
  189. package/dist/schema/nodes/pipe-trap.d.ts +1 -1
  190. package/dist/schema/nodes/pipe-trap.js +1 -1
  191. package/dist/schema/nodes/ridge-vent.d.ts +1 -1
  192. package/dist/schema/nodes/ridge-vent.js +3 -3
  193. package/dist/schema/nodes/roof-segment-shape.d.ts +1 -1
  194. package/dist/schema/nodes/roof-segment-shape.js +1 -1
  195. package/dist/schema/nodes/roof-segment-walls.d.ts +1 -1
  196. package/dist/schema/nodes/roof-segment-walls.js +1 -1
  197. package/dist/schema/nodes/roof-segment.d.ts +2 -2
  198. package/dist/schema/nodes/roof-segment.js +2 -2
  199. package/dist/schema/nodes/roof.d.ts +1 -1
  200. package/dist/schema/nodes/roof.js +3 -3
  201. package/dist/schema/nodes/scan.js +3 -3
  202. package/dist/schema/nodes/shelf.d.ts +1 -1
  203. package/dist/schema/nodes/shelf.d.ts.map +1 -1
  204. package/dist/schema/nodes/shelf.js +3 -4
  205. package/dist/schema/nodes/site.js +2 -2
  206. package/dist/schema/nodes/skylight.d.ts +4 -4
  207. package/dist/schema/nodes/skylight.js +2 -2
  208. package/dist/schema/nodes/slab.js +3 -3
  209. package/dist/schema/nodes/solar-panel.js +3 -3
  210. package/dist/schema/nodes/spawn.js +1 -1
  211. package/dist/schema/nodes/stair-segment.js +2 -2
  212. package/dist/schema/nodes/stair.d.ts +1 -1
  213. package/dist/schema/nodes/stair.js +3 -3
  214. package/dist/schema/nodes/structural-grid.js +1 -1
  215. package/dist/schema/nodes/turbine-vent.d.ts +1 -1
  216. package/dist/schema/nodes/turbine-vent.js +2 -2
  217. package/dist/schema/nodes/unit.d.ts +33 -0
  218. package/dist/schema/nodes/unit.d.ts.map +1 -0
  219. package/dist/schema/nodes/unit.js +13 -0
  220. package/dist/schema/nodes/wall.d.ts +75 -2
  221. package/dist/schema/nodes/wall.d.ts.map +1 -1
  222. package/dist/schema/nodes/wall.js +10 -6
  223. package/dist/schema/nodes/window.js +2 -2
  224. package/dist/schema/nodes/zone.js +1 -1
  225. package/dist/schema/scene-material.js +2 -2
  226. package/dist/schema/types.d.ts +417 -22
  227. package/dist/schema/types.d.ts.map +1 -1
  228. package/dist/schema/types.js +56 -49
  229. package/dist/services/__fixtures__/hosting.d.ts +3 -0
  230. package/dist/services/__fixtures__/hosting.d.ts.map +1 -0
  231. package/dist/services/__fixtures__/hosting.js +9 -0
  232. package/dist/services/__fixtures__/shelf-surface-rows.d.ts +4 -0
  233. package/dist/services/__fixtures__/shelf-surface-rows.d.ts.map +1 -0
  234. package/dist/services/__fixtures__/shelf-surface-rows.js +18 -0
  235. package/dist/services/alignment-anchors.d.ts +6 -11
  236. package/dist/services/alignment-anchors.d.ts.map +1 -1
  237. package/dist/services/alignment-anchors.js +7 -34
  238. package/dist/services/drag-session.d.ts +4 -4
  239. package/dist/services/drag-session.js +1 -1
  240. package/dist/services/hosting.d.ts +5 -8
  241. package/dist/services/hosting.d.ts.map +1 -1
  242. package/dist/services/hosting.js +25 -18
  243. package/dist/services/index.d.ts +16 -13
  244. package/dist/services/index.d.ts.map +1 -1
  245. package/dist/services/index.js +16 -13
  246. package/dist/services/level-height.d.ts +2 -2
  247. package/dist/services/level-height.js +3 -3
  248. package/dist/services/movement.d.ts +3 -3
  249. package/dist/services/movement.js +2 -2
  250. package/dist/services/port-connectivity.d.ts +1 -1
  251. package/dist/services/port-connectivity.js +1 -1
  252. package/dist/services/riser-diagram.d.ts +1 -1
  253. package/dist/services/shelf-board.d.ts +5 -0
  254. package/dist/services/shelf-board.d.ts.map +1 -0
  255. package/dist/services/shelf-board.js +15 -0
  256. package/dist/services/snap.d.ts +3 -0
  257. package/dist/services/snap.d.ts.map +1 -1
  258. package/dist/services/snap.js +11 -0
  259. package/dist/services/storey.d.ts +2 -2
  260. package/dist/services/storey.js +2 -2
  261. package/dist/services/surface-hosting-procedural-parity.fixtures.d.ts +13 -0
  262. package/dist/services/surface-hosting-procedural-parity.fixtures.d.ts.map +1 -0
  263. package/dist/services/surface-hosting-procedural-parity.fixtures.js +4691 -0
  264. package/dist/services/surface-hosting-shelf-parity.fixtures.d.ts +1060 -0
  265. package/dist/services/surface-hosting-shelf-parity.fixtures.d.ts.map +1 -0
  266. package/dist/services/surface-hosting-shelf-parity.fixtures.js +3127 -0
  267. package/dist/services/surface-hosting.d.ts +92 -0
  268. package/dist/services/surface-hosting.d.ts.map +1 -0
  269. package/dist/services/surface-hosting.js +305 -0
  270. package/dist/services/surface-region.d.ts +8 -0
  271. package/dist/services/surface-region.d.ts.map +1 -0
  272. package/dist/services/surface-region.js +44 -0
  273. package/dist/services/system-graph.d.ts +2 -2
  274. package/dist/services/system-graph.js +2 -2
  275. package/dist/services/validate-dwv.d.ts +1 -1
  276. package/dist/services/validate-dwv.js +1 -1
  277. package/dist/store/actions/node-actions.d.ts +2 -2
  278. package/dist/store/actions/node-actions.d.ts.map +1 -1
  279. package/dist/store/actions/node-actions.js +50 -104
  280. package/dist/store/history-control.d.ts +3 -3
  281. package/dist/store/history-invalidation.d.ts +1 -1
  282. package/dist/store/history-invalidation.js +1 -1
  283. package/dist/store/use-interactive.d.ts +2 -2
  284. package/dist/store/use-live-terrain.d.ts +1 -1
  285. package/dist/store/use-scene.d.ts +4 -4
  286. package/dist/store/use-scene.d.ts.map +1 -1
  287. package/dist/store/use-scene.js +50 -32
  288. package/dist/systems/elevator/elevator-dispatch.d.ts +2 -2
  289. package/dist/systems/elevator/elevator-dispatch.js +1 -1
  290. package/dist/systems/elevator/elevator-geometry.d.ts +1 -1
  291. package/dist/systems/elevator/elevator-opening-sync.d.ts +1 -1
  292. package/dist/systems/elevator/elevator-opening-sync.js +2 -2
  293. package/dist/systems/elevator/elevator-opening-system.js +3 -3
  294. package/dist/systems/elevator/elevator-runtime.d.ts +3 -3
  295. package/dist/systems/elevator/elevator-runtime.js +3 -3
  296. package/dist/systems/elevator/elevator-service.d.ts +1 -1
  297. package/dist/systems/elevator/elevator-service.js +1 -1
  298. package/dist/systems/fence/fence-centerline.d.ts +2 -2
  299. package/dist/systems/fence/fence-centerline.js +2 -2
  300. package/dist/systems/fence/fence-spline.d.ts +2 -2
  301. package/dist/systems/roof/roof-elevation-system.js +3 -3
  302. package/dist/systems/roof/roof-elevation.d.ts +2 -2
  303. package/dist/systems/roof/roof-elevation.js +6 -6
  304. package/dist/systems/roof/roof-footprint.d.ts +1 -1
  305. package/dist/systems/roof/roof-footprint.js +3 -3
  306. package/dist/systems/slab/slab-placement.d.ts +1 -1
  307. package/dist/systems/slab/slab-support.d.ts +1 -1
  308. package/dist/systems/slab/slab-support.js +4 -4
  309. package/dist/systems/stair/stair-flight.d.ts +2 -2
  310. package/dist/systems/stair/stair-flight.js +2 -2
  311. package/dist/systems/stair/stair-footprint.d.ts +1 -1
  312. package/dist/systems/stair/stair-opening-preview.d.ts +248 -87
  313. package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
  314. package/dist/systems/stair/stair-opening-preview.js +2 -2
  315. package/dist/systems/stair/stair-opening-sync.d.ts +1 -1
  316. package/dist/systems/stair/stair-opening-sync.js +6 -6
  317. package/dist/systems/stair/stair-opening-system.js +8 -8
  318. package/dist/systems/stair/stair-rise.d.ts +1 -1
  319. package/dist/systems/stair/stair-rise.js +3 -3
  320. package/dist/systems/wall/wall-curve.d.ts +2 -2
  321. package/dist/systems/wall/wall-footprint.d.ts +3 -3
  322. package/dist/systems/wall/wall-footprint.js +3 -3
  323. package/dist/systems/wall/wall-merge.d.ts +38 -0
  324. package/dist/systems/wall/wall-merge.d.ts.map +1 -0
  325. package/dist/systems/wall/wall-merge.js +240 -0
  326. package/dist/systems/wall/wall-mitering.d.ts +1 -1
  327. package/dist/systems/wall/wall-mitering.js +1 -1
  328. package/dist/systems/wall/wall-move.d.ts +1 -1
  329. package/dist/systems/wall/wall-operations.d.ts +28 -0
  330. package/dist/systems/wall/wall-operations.d.ts.map +1 -0
  331. package/dist/systems/wall/wall-operations.js +145 -0
  332. package/dist/systems/wall/wall-top.d.ts +1 -1
  333. package/dist/systems/wall/wall-topology.d.ts +9 -2
  334. package/dist/systems/wall/wall-topology.d.ts.map +1 -1
  335. package/dist/systems/wall/wall-topology.js +57 -9
  336. package/dist/utils/clone-scene-graph.d.ts +3 -3
  337. package/dist/utils/clone-scene-graph.d.ts.map +1 -1
  338. package/dist/utils/clone-scene-graph.js +9 -3
  339. package/dist/utils/scene-migrations.d.ts +3 -3
  340. package/dist/utils/scene-migrations.js +3 -3
  341. package/dist/utils/vertical-scene-migration.js +5 -5
  342. package/dist/validation/validate-build-json.d.ts +5 -2
  343. package/dist/validation/validate-build-json.d.ts.map +1 -1
  344. package/dist/validation/validate-build-json.js +57 -4
  345. package/package.json +15 -4
@@ -1,7 +1,9 @@
1
- import { nodeRegistry } from '../../registry/registry';
2
- import { AnyNode as AnyNodeSchema, createDefaultGuttersForSegment, createDefaultRidgeVentsForSegment, DownspoutNode as DownspoutNodeSchema, defaultDownspoutMetadata, generateId, getDefaultGutterSide, getEffectiveWallSurfaceMaterial, getWallSurfaceMaterialSignature, isAutoGutterEnabled, isAutoRidgeVentEnabled, isDefaultDownspoutNode, isDefaultGutterNode, isDefaultRidgeVentNode, parseNode, planAutomaticDownspouts, resolveAutomaticDownspoutLength, } from '../../schema';
3
- import { constrainWallCurveOffsetToAvoidIntersections } from '../../systems/wall/wall-curve';
4
- import { addActiveSceneCommitNodeIds, runWithSceneCommitNodeIds } from '../history-control';
1
+ import { nodeRegistry } from '../../registry/registry.js';
2
+ import { validateNodeRelations } from '../../registry/validate-relations.js';
3
+ import { AnyNode as AnyNodeSchema, createDefaultGuttersForSegment, createDefaultRidgeVentsForSegment, DownspoutNode as DownspoutNodeSchema, defaultDownspoutMetadata, generateId, getDefaultGutterSide, isAutoGutterEnabled, isAutoRidgeVentEnabled, isDefaultDownspoutNode, isDefaultGutterNode, isDefaultRidgeVentNode, parseNode, planAutomaticDownspouts, resolveAutomaticDownspoutLength, } from '../../schema/index.js';
4
+ import { constrainWallCurveOffsetToAvoidIntersections } from '../../systems/wall/wall-curve.js';
5
+ import { areWallStylesCompatible, areWallsCollinearAcrossPoint, buildMergedWallAttachmentUpdates, getWallEndpointAtPoint, resolveMergedWallEndpoints, } from '../../systems/wall/wall-merge.js';
6
+ import { activeSceneCommitNodeIds, addActiveSceneCommitNodeIds, runWithSceneCommitNodeIds, } from '../history-control.js';
5
7
  const DEFAULT_RIDGE_VENT_REFRESH_FIELDS = new Set([
6
8
  'roofType',
7
9
  'width',
@@ -367,6 +369,10 @@ function warnSanitizedNodeMutation(mutation, nodeId, issues) {
367
369
  }
368
370
  function parseCreatedNode(node, parentId) {
369
371
  const candidate = { ...node, parentId };
372
+ const registered = nodeRegistry.get(candidate.type)?.schema;
373
+ // Generated definitions must reject invalid geometry instead of retaining a failed parse.
374
+ if (registered?.meta?.()?.strictMutations === true)
375
+ return registered.parse(candidate);
370
376
  const parsed = parseNode(candidate);
371
377
  if (parsed.success)
372
378
  return parsed.data;
@@ -393,9 +399,19 @@ function mergeNodeUpdate(currentNode, patch) {
393
399
  }
394
400
  function parseUpdatedNode(currentNode, data) {
395
401
  const candidate = mergeNodeUpdate(currentNode, data);
402
+ // Graph links survive schemas that omit children; only an explicit patch may change them.
403
+ const preserveChildren = (updated) => !Object.hasOwn(data, 'children') &&
404
+ 'children' in currentNode &&
405
+ Array.isArray(currentNode.children)
406
+ ? { ...updated, children: currentNode.children }
407
+ : updated;
408
+ const registered = nodeRegistry.get(currentNode.type)?.schema;
409
+ // Generated definitions must reject invalid geometry instead of retaining a failed parse.
410
+ if (registered?.meta?.()?.strictMutations === true)
411
+ return preserveChildren(registered.parse(candidate));
396
412
  const parsed = parseNode(candidate);
397
413
  if (parsed.success)
398
- return parsed.data;
414
+ return preserveChildren(parsed.data);
399
415
  const schema = getNodeSchemaForType(candidate.type);
400
416
  const sanitized = sanitizeNumericValue(schema, data, currentNode, []);
401
417
  if (sanitized.issues.length === 0) {
@@ -735,100 +751,6 @@ function refreshDefaultGuttersForRoofIds(nextNodes, roofIds, dirtyIds, deletedId
735
751
  // Track pending RAF for updateNodesAction to prevent multiple queued callbacks
736
752
  let pendingRafId = null;
737
753
  let pendingUpdates = new Set();
738
- function pointsEqual(a, b, tolerance = 1e-6) {
739
- const dx = a[0] - b[0];
740
- const dz = a[1] - b[1];
741
- return dx * dx + dz * dz <= tolerance * tolerance;
742
- }
743
- function wallLength(wall) {
744
- return Math.hypot(wall.end[0] - wall.start[0], wall.end[1] - wall.start[1]);
745
- }
746
- function getWallEndpointAtPoint(wall, point) {
747
- if (pointsEqual(wall.start, point))
748
- return 'start';
749
- if (pointsEqual(wall.end, point))
750
- return 'end';
751
- return null;
752
- }
753
- function getWallFreeEndpoint(wall, sharedPoint) {
754
- return pointsEqual(wall.start, sharedPoint) ? wall.end : wall.start;
755
- }
756
- function areWallStylesCompatible(a, b) {
757
- const aInterior = getWallSurfaceMaterialSignature(getEffectiveWallSurfaceMaterial(a, 'interior'));
758
- const bInterior = getWallSurfaceMaterialSignature(getEffectiveWallSurfaceMaterial(b, 'interior'));
759
- const aExterior = getWallSurfaceMaterialSignature(getEffectiveWallSurfaceMaterial(a, 'exterior'));
760
- const bExterior = getWallSurfaceMaterialSignature(getEffectiveWallSurfaceMaterial(b, 'exterior'));
761
- return ((a.parentId ?? null) === (b.parentId ?? null) &&
762
- Math.abs((a.curveOffset ?? 0) - (b.curveOffset ?? 0)) <= 1e-6 &&
763
- Math.abs((a.thickness ?? 0.2) - (b.thickness ?? 0.2)) <= 1e-6 &&
764
- // Absent height means plane-bound (follows the storey), which must never
765
- // merge with an explicit height — even one that currently matches the plane.
766
- (a.height == null) === (b.height == null) &&
767
- Math.abs((a.height ?? 0) - (b.height ?? 0)) <= 1e-6 &&
768
- aInterior === bInterior &&
769
- aExterior === bExterior &&
770
- a.frontSide === b.frontSide &&
771
- a.backSide === b.backSide &&
772
- a.visible === b.visible);
773
- }
774
- function areWallsCollinearAcrossPoint(a, b, sharedPoint) {
775
- const freeA = getWallFreeEndpoint(a, sharedPoint);
776
- const freeB = getWallFreeEndpoint(b, sharedPoint);
777
- const ax = freeA[0] - sharedPoint[0];
778
- const az = freeA[1] - sharedPoint[1];
779
- const bx = freeB[0] - sharedPoint[0];
780
- const bz = freeB[1] - sharedPoint[1];
781
- const lenA = Math.hypot(ax, az);
782
- const lenB = Math.hypot(bx, bz);
783
- if (lenA < 1e-6 || lenB < 1e-6)
784
- return false;
785
- const cross = (ax * bz - az * bx) / (lenA * lenB);
786
- const dot = (ax * bx + az * bz) / (lenA * lenB);
787
- return Math.abs(cross) <= 1e-4 && dot < -0.999;
788
- }
789
- function resolveMergedWallEndpoints(primary, secondary, sharedPoint) {
790
- const primaryEndpoint = getWallEndpointAtPoint(primary, sharedPoint);
791
- const secondaryEndpoint = getWallEndpointAtPoint(secondary, sharedPoint);
792
- if (primaryEndpoint === 'end' && secondaryEndpoint === 'start') {
793
- return { start: primary.start, end: secondary.end };
794
- }
795
- if (primaryEndpoint === 'start' && secondaryEndpoint === 'end') {
796
- return { start: secondary.start, end: primary.end };
797
- }
798
- if (primaryEndpoint === 'start' && secondaryEndpoint === 'start') {
799
- return { start: primary.end, end: secondary.end };
800
- }
801
- return { start: primary.start, end: secondary.start };
802
- }
803
- function buildMergedWallAttachmentUpdates(primary, secondary, mergedWallId, mergedStart, mergedEnd, nodes) {
804
- const mergedLength = Math.max(Math.hypot(mergedEnd[0] - mergedStart[0], mergedEnd[1] - mergedStart[1]), 1e-6);
805
- const tangentX = (mergedEnd[0] - mergedStart[0]) / mergedLength;
806
- const tangentZ = (mergedEnd[1] - mergedStart[1]) / mergedLength;
807
- const updates = [];
808
- const wallChildren = [...(primary.children ?? []), ...(secondary.children ?? [])];
809
- for (const childId of wallChildren) {
810
- const child = nodes[childId];
811
- if (!(child && 'position' in child && Array.isArray(child.position))) {
812
- continue;
813
- }
814
- const sourceWall = child.parentId === secondary.id ? secondary : primary;
815
- const sourceLength = Math.max(wallLength(sourceWall), 1e-6);
816
- const localX = typeof child.position[0] === 'number' ? child.position[0] : 0;
817
- const worldX = sourceWall.start[0] + ((sourceWall.end[0] - sourceWall.start[0]) * localX) / sourceLength;
818
- const worldZ = sourceWall.start[1] + ((sourceWall.end[1] - sourceWall.start[1]) * localX) / sourceLength;
819
- const nextLocalX = Math.max(0, Math.min(mergedLength, (worldX - mergedStart[0]) * tangentX + (worldZ - mergedStart[1]) * tangentZ));
820
- updates.push({
821
- id: childId,
822
- data: {
823
- parentId: mergedWallId,
824
- wallId: mergedWallId,
825
- position: [nextLocalX, child.position[1], child.position[2]],
826
- ...('wallT' in child ? { wallT: nextLocalX / mergedLength } : {}),
827
- },
828
- });
829
- }
830
- return updates;
831
- }
832
754
  function buildWallMergePlans(nodes, idsToDelete) {
833
755
  const deletedWalls = idsToDelete
834
756
  .map((id) => nodes[id])
@@ -846,7 +768,7 @@ function buildWallMergePlans(nodes, idsToDelete) {
846
768
  return false;
847
769
  if ((node.parentId ?? null) !== (deletedWall.parentId ?? null))
848
770
  return false;
849
- return pointsEqual(node.start, junction) || pointsEqual(node.end, junction);
771
+ return getWallEndpointAtPoint(node, junction) !== null;
850
772
  });
851
773
  if (candidates.length !== 2) {
852
774
  continue;
@@ -1328,6 +1250,22 @@ const deleteNodesActionImpl = (set, get, ids) => {
1328
1250
  }
1329
1251
  }
1330
1252
  }
1253
+ const deletedZoneIds = new Set();
1254
+ for (const id of allIds) {
1255
+ if (nextNodes[id]?.type === 'zone')
1256
+ deletedZoneIds.add(id);
1257
+ }
1258
+ if (deletedZoneIds.size > 0) {
1259
+ for (const node of Object.values(nextNodes)) {
1260
+ if (node.type !== 'unit' || allIds.has(node.id))
1261
+ continue;
1262
+ const members = node.members.filter((id) => !deletedZoneIds.has(id));
1263
+ if (members.length === node.members.length)
1264
+ continue;
1265
+ nextNodes[node.id] = { ...node, members };
1266
+ nodesToMarkDirty.add(node.id);
1267
+ }
1268
+ }
1331
1269
  for (const id of allIds) {
1332
1270
  const node = nextNodes[id];
1333
1271
  if (!node)
@@ -1382,10 +1320,18 @@ const deleteNodesActionImpl = (set, get, ids) => {
1382
1320
  get().markDirty(id);
1383
1321
  });
1384
1322
  };
1323
+ function validatedSet(set) {
1324
+ return (change) => set((state) => {
1325
+ const patch = change(state);
1326
+ if (patch.nodes)
1327
+ validateNodeRelations(state.nodes, patch.nodes, activeSceneCommitNodeIds() ?? []);
1328
+ return patch;
1329
+ });
1330
+ }
1385
1331
  export const createNodesAction = (set, get, ops) => runWithSceneCommitNodeIds(ops.flatMap(({ node, parentId }) => {
1386
1332
  const effectiveParentId = parentId ?? node.parentId;
1387
1333
  return effectiveParentId ? [node.id, effectiveParentId] : [node.id];
1388
- }), () => createNodesActionImpl(set, get, ops));
1334
+ }), () => createNodesActionImpl(validatedSet(set), get, ops));
1389
1335
  export const applyNodeChangesAction = (set, get, changes) => runWithSceneCommitNodeIds([
1390
1336
  ...(changes.create ?? []).flatMap(({ node, parentId }) => {
1391
1337
  const effectiveParentId = parentId ?? node.parentId;
@@ -1393,6 +1339,6 @@ export const applyNodeChangesAction = (set, get, changes) => runWithSceneCommitN
1393
1339
  }),
1394
1340
  ...(changes.update ?? []).map(({ id }) => id),
1395
1341
  ...(changes.delete ?? []),
1396
- ], () => applyNodeChangesActionImpl(set, get, changes));
1397
- export const updateNodesAction = (set, get, updates) => runWithSceneCommitNodeIds(updates.map(({ id }) => id), () => updateNodesActionImpl(set, get, updates));
1398
- export const deleteNodesAction = (set, get, ids) => runWithSceneCommitNodeIds(ids, () => deleteNodesActionImpl(set, get, ids));
1342
+ ], () => applyNodeChangesActionImpl(validatedSet(set), get, changes));
1343
+ export const updateNodesAction = (set, get, updates) => runWithSceneCommitNodeIds(updates.map(({ id }) => id), () => updateNodesActionImpl(validatedSet(set), get, updates));
1344
+ export const deleteNodesAction = (set, get, ids) => runWithSceneCommitNodeIds(ids, () => deleteNodesActionImpl(validatedSet(set), get, ids));
@@ -1,6 +1,6 @@
1
- import type { Collection, CollectionId } from '../schema/collections';
2
- import type { SceneMaterial, SceneMaterialId } from '../schema/scene-material';
3
- import type { AnyNode, AnyNodeId } from '../schema/types';
1
+ import type { Collection, CollectionId } from '../schema/collections.js';
2
+ import type { SceneMaterial, SceneMaterialId } from '../schema/scene-material.js';
3
+ import type { AnyNode, AnyNodeId } from '../schema/types.js';
4
4
  export type SceneSnapshot = {
5
5
  nodes: Record<AnyNodeId, AnyNode>;
6
6
  rootNodeIds: AnyNodeId[];
@@ -1,3 +1,3 @@
1
- import type { AnyNode, AnyNodeId } from '../schema';
1
+ import type { AnyNode, AnyNodeId } from '../schema/index.js';
2
2
  export declare function getHistoryDirtyNodeIds(before: Record<string, AnyNode>, after: Record<string, AnyNode>): Set<AnyNodeId>;
3
3
  //# sourceMappingURL=history-invalidation.d.ts.map
@@ -1,4 +1,4 @@
1
- import { getAdjacentWallIds } from '../systems/wall/wall-mitering';
1
+ import { getAdjacentWallIds } from '../systems/wall/wall-mitering.js';
2
2
  export function getHistoryDirtyNodeIds(before, after) {
3
3
  const dirty = new Set();
4
4
  const changedWalls = new Set();
@@ -1,5 +1,5 @@
1
- import type { Interactive } from '../schema/nodes/item';
2
- import type { AnyNodeId } from '../schema/types';
1
+ import type { Interactive } from '../schema/nodes/item.js';
2
+ import type { AnyNodeId } from '../schema/types.js';
3
3
  export type ControlValue = boolean | number;
4
4
  export type ItemInteractiveState = {
5
5
  controlValues: ControlValue[];
@@ -1,4 +1,4 @@
1
- import type { HeightPatch, TerrainField } from '../lib/terrain-field';
1
+ import type { HeightPatch, TerrainField } from '../lib/terrain-field.js';
2
2
  /**
3
3
  * In-progress terrain edits, held as a live `TerrainField` rather than as node
4
4
  * data.
@@ -1,9 +1,9 @@
1
1
  import type { TemporalState } from 'zundo';
2
2
  import { type StoreApi, type UseBoundStore } from 'zustand';
3
- import type { Collection, CollectionId } from '../schema/collections';
4
- import { SceneMaterial, type SceneMaterialId } from '../schema/scene-material';
5
- import { type AnyNode, type AnyNodeId } from '../schema/types';
6
- import { type SceneCommitOrigin, type SceneSnapshot } from './history-control';
3
+ import type { Collection, CollectionId } from '../schema/collections.js';
4
+ import { SceneMaterial, type SceneMaterialId } from '../schema/scene-material.js';
5
+ import { type AnyNode, type AnyNodeId } from '../schema/types.js';
6
+ import { type SceneCommitOrigin, type SceneSnapshot } from './history-control.js';
7
7
  export type SceneState = {
8
8
  nodes: Record<AnyNodeId, AnyNode>;
9
9
  rootNodeIds: AnyNodeId[];
@@ -1 +1 @@
1
- {"version":3,"file":"use-scene.d.ts","sourceRoot":"","sources":["../../src/store/use-scene.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-scene.d.ts","sourceRoot":"","sources":["../../src/store/use-scene.ts"],"names":[],"mappings":"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"}
@@ -1,37 +1,37 @@
1
1
  'use client';
2
2
  import { temporal } from 'zundo';
3
3
  import { create } from 'zustand';
4
- import { parseMaterialRef, toSceneMaterialRef } from '../material-library';
5
- import { getNodePluginId, isNodeKindEnabled, nodeRegistry } from '../registry/registry';
6
- import { BuildingNode } from '../schema';
7
- import { generateCollectionId } from '../schema/collections';
8
- import { compiledNodeSchema } from '../schema/compiled-node-parsers';
9
- import { DoorNode as DoorNodeSchema } from '../schema/nodes/door';
10
- import { createDormerDefaultWindow, DormerNode as DormerNodeSchema, getDormerDefaultWindowFace, } from '../schema/nodes/dormer';
11
- import { ElevatorNode as ElevatorNodeSchema } from '../schema/nodes/elevator';
12
- import { LevelNode, normalizeLevelBaseElevation } from '../schema/nodes/level';
13
- import { getPitchFromActiveRoofHeight, } from '../schema/nodes/roof-segment';
14
- import { segmentPointToRoofWallFace } from '../schema/nodes/roof-segment-walls';
15
- import { ShelfNode as ShelfNodeSchema } from '../schema/nodes/shelf';
16
- import { SiteNode } from '../schema/nodes/site';
17
- import { getEffectiveStairSurfaceMaterial, StairNode as StairNodeSchema, } from '../schema/nodes/stair';
18
- import { StairSegmentNode as StairSegmentNodeSchema } from '../schema/nodes/stair-segment';
19
- import { getEffectiveWallSurfaceMaterial } from '../schema/nodes/wall';
20
- import { WindowNode as WindowNodeSchema } from '../schema/nodes/window';
21
- import { generateSceneMaterialId, SceneMaterial, } from '../schema/scene-material';
22
- import { AnyNode as AnyNodeSchema } from '../schema/types';
23
- import { syncAutoElevatorOpenings } from '../systems/elevator/elevator-opening-sync';
24
- import { syncAutoStairOpenings } from '../systems/stair/stair-opening-sync';
25
- import { syncStairRises } from '../systems/stair/stair-rise';
26
- import { healSceneNodes } from '../utils/heal-scene-graph';
27
- import { removeRetiredDrawingSheetNodes } from '../utils/retired-scene-nodes';
28
- import { migrateVerticalSceneNodes } from '../utils/vertical-scene-migration';
29
- import * as nodeActions from './actions/node-actions';
30
- import { areSceneSnapshotsEqual, getSceneHistoryPauseDepth, notifySceneCommit, pauseSceneHistory, resetSceneHistoryPauseDepth, resumeSceneHistory, runWithSceneCommitNodeIds, } from './history-control';
31
- import { getHistoryDirtyNodeIds } from './history-invalidation';
32
- import { invalidatePendingHydration, isHydrationNormalization, queueSceneNormalization, runSceneHydration, } from './scene-hydration';
33
- import useLiveNodeOverrides from './use-live-node-overrides';
34
- import useLiveTransforms from './use-live-transforms';
4
+ import { parseMaterialRef, toSceneMaterialRef } from '../material-library.js';
5
+ import { getNodePluginId, isNodeKindEnabled, nodeRegistry } from '../registry/registry.js';
6
+ import { BuildingNode } from '../schema/index.js';
7
+ import { generateCollectionId } from '../schema/collections.js';
8
+ import { compiledNodeSchema } from '../schema/compiled-node-parsers.js';
9
+ import { DoorNode as DoorNodeSchema } from '../schema/nodes/door.js';
10
+ import { createDormerDefaultWindow, DormerNode as DormerNodeSchema, getDormerDefaultWindowFace, } from '../schema/nodes/dormer.js';
11
+ import { ElevatorNode as ElevatorNodeSchema } from '../schema/nodes/elevator.js';
12
+ import { LevelNode, normalizeLevelBaseElevation } from '../schema/nodes/level.js';
13
+ import { getPitchFromActiveRoofHeight, } from '../schema/nodes/roof-segment.js';
14
+ import { segmentPointToRoofWallFace } from '../schema/nodes/roof-segment-walls.js';
15
+ import { ShelfNode as ShelfNodeSchema } from '../schema/nodes/shelf.js';
16
+ import { SiteNode } from '../schema/nodes/site.js';
17
+ import { getEffectiveStairSurfaceMaterial, StairNode as StairNodeSchema, } from '../schema/nodes/stair.js';
18
+ import { StairSegmentNode as StairSegmentNodeSchema } from '../schema/nodes/stair-segment.js';
19
+ import { getEffectiveWallSurfaceMaterial } from '../schema/nodes/wall.js';
20
+ import { WindowNode as WindowNodeSchema } from '../schema/nodes/window.js';
21
+ import { generateSceneMaterialId, SceneMaterial, } from '../schema/scene-material.js';
22
+ import { AnyNode as AnyNodeSchema } from '../schema/types.js';
23
+ import { syncAutoElevatorOpenings } from '../systems/elevator/elevator-opening-sync.js';
24
+ import { syncAutoStairOpenings } from '../systems/stair/stair-opening-sync.js';
25
+ import { syncStairRises } from '../systems/stair/stair-rise.js';
26
+ import { healSceneNodes } from '../utils/heal-scene-graph.js';
27
+ import { removeRetiredDrawingSheetNodes } from '../utils/retired-scene-nodes.js';
28
+ import { migrateVerticalSceneNodes } from '../utils/vertical-scene-migration.js';
29
+ import * as nodeActions from './actions/node-actions.js';
30
+ import { areSceneSnapshotsEqual, getSceneHistoryPauseDepth, notifySceneCommit, pauseSceneHistory, resetSceneHistoryPauseDepth, resumeSceneHistory, runWithSceneCommitNodeIds, } from './history-control.js';
31
+ import { getHistoryDirtyNodeIds } from './history-invalidation.js';
32
+ import { invalidatePendingHydration, isHydrationNormalization, queueSceneNormalization, runSceneHydration, } from './scene-hydration.js';
33
+ import useLiveNodeOverrides from './use-live-node-overrides.js';
34
+ import useLiveTransforms from './use-live-transforms.js';
35
35
  function getFiniteNumber(value, fallback) {
36
36
  return typeof value === 'number' && Number.isFinite(value) ? value : fallback;
37
37
  }
@@ -874,6 +874,12 @@ function migrateNodes(nodes) {
874
874
  children: validChildren,
875
875
  };
876
876
  }
877
+ // These kinds are not all schema-parsed on load, so defaults must also
878
+ // reach saved hosts that predate their children field.
879
+ if (['shelf', 'cabinet', 'cabinet-module', 'block', 'item', 'column'].includes(node.type) &&
880
+ patchedNodes[id].children === undefined) {
881
+ patchedNodes[id] = { ...patchedNodes[id], children: [] };
882
+ }
877
883
  }
878
884
  // Pass 2: elevator migration.
879
885
  // migrateElevatorParent mutates the parent level's children array (removes
@@ -985,9 +991,21 @@ function sceneHistorySnapshotFromState(state) {
985
991
  }
986
992
  }
987
993
  const historyNodes = {};
988
- for (const [id, node] of Object.entries(nodes)) {
994
+ for (const [id, sourceNode] of Object.entries(nodes)) {
989
995
  if (transientNodeIds.has(id))
990
996
  continue;
997
+ let node = sourceNode;
998
+ if (node.type === 'procedural-item') {
999
+ let attachments;
1000
+ for (const childId of transientNodeIds) {
1001
+ if (!Object.hasOwn(node.attachments, childId))
1002
+ continue;
1003
+ attachments ??= { ...node.attachments };
1004
+ delete attachments[childId];
1005
+ }
1006
+ if (attachments)
1007
+ node = { ...node, attachments };
1008
+ }
991
1009
  if (!('children' in node && Array.isArray(node.children))) {
992
1010
  historyNodes[id] = node;
993
1011
  continue;
@@ -1,5 +1,5 @@
1
- import type { AnyNode, AnyNodeId } from '../../schema';
2
- import type { ElevatorInteractiveState } from '../../store/use-interactive';
1
+ import type { AnyNode, AnyNodeId } from '../../schema/index.js';
2
+ import type { ElevatorInteractiveState } from '../../store/use-interactive.js';
3
3
  type ElevatorRuntimeMap = Record<AnyNodeId, ElevatorInteractiveState>;
4
4
  type ResolveElevatorDispatchTargetArgs = {
5
5
  elevators: ElevatorRuntimeMap;
@@ -1,4 +1,4 @@
1
- import { resolveElevatorServiceLevels } from './elevator-service';
1
+ import { resolveElevatorServiceLevels } from './elevator-service.js';
2
2
  function getRuntimeLevelId(runtime, elevator) {
3
3
  return runtime?.currentLevelId ?? elevator.defaultLevelId ?? elevator.fromLevelId ?? null;
4
4
  }
@@ -1,4 +1,4 @@
1
- import type { ElevatorDoorPanelStyle, ElevatorDoorStyle, ElevatorNode, ElevatorShaftStyle } from '../../schema';
1
+ import type { ElevatorDoorPanelStyle, ElevatorDoorStyle, ElevatorNode, ElevatorShaftStyle } from '../../schema/index.js';
2
2
  export type ElevatorDoorSide = 'left' | 'right';
3
3
  export declare function getResolvedElevatorDoorStyle(doorStyle: ElevatorNode['doorStyle'] | undefined): ElevatorDoorStyle;
4
4
  export declare function getResolvedElevatorDoorPanelStyle(doorPanelStyle: ElevatorNode['doorPanelStyle'] | undefined): ElevatorDoorPanelStyle;
@@ -1,4 +1,4 @@
1
- import type { AnyNode, AnyNodeId, CeilingNode, SlabNode } from '../../schema';
1
+ import type { AnyNode, AnyNodeId, CeilingNode, SlabNode } from '../../schema/index.js';
2
2
  export declare function syncAutoElevatorOpenings(nodes: Record<string, AnyNode>): {
3
3
  id: AnyNodeId;
4
4
  data: Partial<SlabNode | CeilingNode>;
@@ -1,5 +1,5 @@
1
- import { resolveLevelId } from '../../hooks/spatial-grid/spatial-grid-sync';
2
- import { resolveElevatorServiceLevels } from './elevator-service';
1
+ import { resolveLevelId } from '../../hooks/spatial-grid/spatial-grid-sync.js';
2
+ import { resolveElevatorServiceLevels } from './elevator-service.js';
3
3
  const ELEVATOR_OPENING_PADDING = 0.08;
4
4
  const DEFAULT_ELEVATOR_SHAFT_WALL_THICKNESS = 0.09;
5
5
  function pointsEqual(a, b, tolerance = 1e-5) {
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
  import { useEffect } from 'react';
3
- import { pauseSceneHistory, resumeSceneHistory } from '../../store/history-control';
4
- import useScene from '../../store/use-scene';
5
- import { syncAutoElevatorOpenings } from './elevator-opening-sync';
3
+ import { pauseSceneHistory, resumeSceneHistory } from '../../store/history-control.js';
4
+ import useScene from '../../store/use-scene.js';
5
+ import { syncAutoElevatorOpenings } from './elevator-opening-sync.js';
6
6
  function isOpeningRelevantNode(node) {
7
7
  return (node?.type === 'building' ||
8
8
  node?.type === 'ceiling' ||
@@ -1,6 +1,6 @@
1
- import type { AnyNodeId, ElevatorNode } from '../../schema';
2
- import { type ElevatorInteractiveState } from '../../store/use-interactive';
3
- import { type ElevatorLevelEntry } from './elevator-service';
1
+ import type { AnyNodeId, ElevatorNode } from '../../schema/index.js';
2
+ import { type ElevatorInteractiveState } from '../../store/use-interactive.js';
3
+ import { type ElevatorLevelEntry } from './elevator-service.js';
4
4
  export declare function createElevatorInteractiveState(levelId: AnyNodeId, carY: number): ElevatorInteractiveState;
5
5
  export declare function queueElevatorRequest(state: ElevatorInteractiveState, levelId: AnyNodeId): ElevatorInteractiveState;
6
6
  export declare function openElevatorDoorState(state: ElevatorInteractiveState): ElevatorInteractiveState;
@@ -1,6 +1,6 @@
1
- import { useInteractive } from '../../store/use-interactive';
2
- import useScene from '../../store/use-scene';
3
- import { resolveElevatorLevels } from './elevator-service';
1
+ import { useInteractive } from '../../store/use-interactive.js';
2
+ import useScene from '../../store/use-scene.js';
3
+ import { resolveElevatorLevels } from './elevator-service.js';
4
4
  const EPSILON = 0.001;
5
5
  function moveToward(current, target, maxDelta) {
6
6
  const delta = target - current;
@@ -1,4 +1,4 @@
1
- import type { AnyNode, ElevatorNode, LevelNode } from '../../schema';
1
+ import type { AnyNode, ElevatorNode, LevelNode } from '../../schema/index.js';
2
2
  export type ElevatorLevelEntry = {
3
3
  id: LevelNode['id'];
4
4
  label: string;
@@ -1,4 +1,4 @@
1
- import { getLevelElevations } from '../../services/storey';
1
+ import { getLevelElevations } from '../../services/storey.js';
2
2
  function getBuildingLevels(elevator, nodes) {
3
3
  const building = elevator.parentId && nodes[elevator.parentId]?.type === 'building'
4
4
  ? nodes[elevator.parentId]
@@ -1,5 +1,5 @@
1
- import type { FenceNode } from '../../schema';
2
- import type { Point2D } from '../wall/wall-mitering';
1
+ import type { FenceNode } from '../../schema/index.js';
2
+ import type { Point2D } from '../wall/wall-mitering.js';
3
3
  type CurveFrame = {
4
4
  point: Point2D;
5
5
  tangent: Point2D;
@@ -1,5 +1,5 @@
1
- import { getWallCurveFrameAt, getWallCurveLength, sampleWallCenterline } from '../wall/wall-curve';
2
- import { getFenceSplineFrameAt, getFenceSplineLength, isSplineFence, sampleFenceSpline, } from './fence-spline';
1
+ import { getWallCurveFrameAt, getWallCurveLength, sampleWallCenterline } from '../wall/wall-curve.js';
2
+ import { getFenceSplineFrameAt, getFenceSplineLength, isSplineFence, sampleFenceSpline, } from './fence-spline.js';
3
3
  /**
4
4
  * Unified fence centerline accessors. A fence is either:
5
5
  * - a spline fence (`path` of >= 2 control points) → smooth Catmull-Rom, or
@@ -1,5 +1,5 @@
1
- import type { FenceNode } from '../../schema';
2
- import type { Point2D } from '../wall/wall-mitering';
1
+ import type { FenceNode } from '../../schema/index.js';
2
+ import type { Point2D } from '../wall/wall-mitering.js';
3
3
  type FenceSplineLike = Pick<FenceNode, 'path'>;
4
4
  type TangentList = ReadonlyArray<readonly [number, number] | null> | undefined;
5
5
  export declare function isSplineFence(fence: FenceSplineLike): boolean;
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
  import { useEffect } from 'react';
3
- import { getSceneHistoryPauseDepth, notifySceneCommit, pauseSceneHistory, resumeSceneHistory, } from '../../store/history-control';
4
- import useScene from '../../store/use-scene';
5
- import { resolveRoofElevation } from './roof-elevation';
3
+ import { getSceneHistoryPauseDepth, notifySceneCommit, pauseSceneHistory, resumeSceneHistory, } from '../../store/history-control.js';
4
+ import useScene from '../../store/use-scene.js';
5
+ import { resolveRoofElevation } from './roof-elevation.js';
6
6
  const ROOF_ELEVATION_EPSILON = 1e-4;
7
7
  function sceneSnapshot() {
8
8
  const { nodes, rootNodeIds, collections, materials, installedPlugins } = useScene.getState();
@@ -1,4 +1,4 @@
1
- import type { AnyNode, LevelNode, RoofNode, WallNode } from '../../schema';
2
- export declare function resolveRoofWallTopElevation(targetLevelId: LevelNode['id'], wall: WallNode, nodes: Readonly<Record<string, AnyNode>>, elevations?: Map<string, import("../..").LevelElevation>): number;
1
+ import type { AnyNode, LevelNode, RoofNode, WallNode } from '../../schema/index.js';
2
+ export declare function resolveRoofWallTopElevation(targetLevelId: LevelNode['id'], wall: WallNode, nodes: Readonly<Record<string, AnyNode>>, elevations?: Map<string, import("../../index.js").LevelElevation>): number;
3
3
  export declare function resolveRoofElevation(roof: RoofNode, nodes: Readonly<Record<string, AnyNode>>): number;
4
4
  //# sourceMappingURL=roof-elevation.d.ts.map
@@ -1,9 +1,9 @@
1
- import { getWallBaseElevationForNodes, getWallEffectiveHeightForNodes, } from '../../hooks/spatial-grid/spatial-grid-manager';
2
- import { resolveLevelId } from '../../hooks/spatial-grid/spatial-grid-sync';
3
- import { findLevelBelowId, getLevelElevations } from '../../services/storey';
4
- import { wallOverlapsSlabFootprint } from '../slab/slab-support';
5
- import { getWallArcData } from '../wall/wall-curve';
6
- import { resolveRoomRoofFootprintOnLevel } from './roof-footprint';
1
+ import { getWallBaseElevationForNodes, getWallEffectiveHeightForNodes, } from '../../hooks/spatial-grid/spatial-grid-manager.js';
2
+ import { resolveLevelId } from '../../hooks/spatial-grid/spatial-grid-sync.js';
3
+ import { findLevelBelowId, getLevelElevations } from '../../services/storey.js';
4
+ import { wallOverlapsSlabFootprint } from '../slab/slab-support.js';
5
+ import { getWallArcData } from '../wall/wall-curve.js';
6
+ import { resolveRoomRoofFootprintOnLevel } from './roof-footprint.js';
7
7
  export function resolveRoofWallTopElevation(targetLevelId, wall, nodes, elevations = getLevelElevations(nodes)) {
8
8
  const sourceLevelY = elevations.get(resolveLevelId(wall, nodes))?.baseY ?? 0;
9
9
  const targetLevelY = elevations.get(targetLevelId)?.baseY ?? 0;
@@ -1,4 +1,4 @@
1
- import type { AnyNode, LevelNode, WallNode } from '../../schema';
1
+ import type { AnyNode, LevelNode, WallNode } from '../../schema/index.js';
2
2
  export type RoofFootprintTarget = {
3
3
  id: string;
4
4
  polygon: Array<[number, number]>;
@@ -1,6 +1,6 @@
1
- import { pointInPolygon as pointInPolygon2D } from '../../lib/polygon-relations';
2
- import { detectSpacesForLevel } from '../../lib/space-detection';
3
- import { getLevelBelow } from '../../services/storey';
1
+ import { pointInPolygon as pointInPolygon2D } from '../../lib/polygon-relations.js';
2
+ import { detectSpacesForLevel } from '../../lib/space-detection.js';
3
+ import { getLevelBelow } from '../../services/storey.js';
4
4
  function polygonArea(polygon) {
5
5
  return Math.abs(polygon.reduce((area, point, index) => {
6
6
  const next = polygon[(index + 1) % polygon.length];
@@ -1,4 +1,4 @@
1
- import type { SlabNode } from '../../schema';
1
+ import type { SlabNode } from '../../schema/index.js';
2
2
  /**
3
3
  * Translate a solid slab's authored vertical interval onto a chosen base plane.
4
4
  *
@@ -1,4 +1,4 @@
1
- import type { SlabNode, WallNode } from '../../schema';
1
+ import type { SlabNode, WallNode } from '../../schema/index.js';
2
2
  export type SlabElevationClamp = {
3
3
  elevation: number;
4
4
  clamped: boolean;
@@ -1,7 +1,7 @@
1
- import { getRenderableSlabPolygon } from '../../lib/slab-polygon';
2
- import { getWallCurveFrameAt, isCurvedWall } from '../wall/wall-curve';
3
- import { DEFAULT_WALL_THICKNESS } from '../wall/wall-footprint';
4
- import { MIN_WALL_HEIGHT } from '../wall/wall-top';
1
+ import { getRenderableSlabPolygon } from '../../lib/slab-polygon.js';
2
+ import { getWallCurveFrameAt, isCurvedWall } from '../wall/wall-curve.js';
3
+ import { DEFAULT_WALL_THICKNESS } from '../wall/wall-footprint.js';
4
+ import { MIN_WALL_HEIGHT } from '../wall/wall-top.js';
5
5
  /**
6
6
  * Clamp-never-ask upper bound for a slab's elevation. A plane-bound wall
7
7
  * (no stored `height`) keeps its top at the storey plane, so a slab that
@@ -1,5 +1,5 @@
1
- import type { AnyNode, StairNode } from '../../schema';
2
- import { StairSegmentNode } from '../../schema';
1
+ import type { AnyNode, StairNode } from '../../schema/index.js';
2
+ import { StairSegmentNode } from '../../schema/index.js';
3
3
  export type StairFlightOverrides = Partial<Pick<StairSegmentNode, 'width' | 'length' | 'height' | 'stepCount' | 'attachmentSide' | 'fillToFloor' | 'thickness'>>;
4
4
  /**
5
5
  * The single definition of a default straight flight. Anything left out falls
@@ -1,5 +1,5 @@
1
- import { StairSegmentNode } from '../../schema';
2
- import { resolveStairTotalRise } from './stair-rise';
1
+ import { StairSegmentNode } from '../../schema/index.js';
2
+ import { resolveStairTotalRise } from './stair-rise.js';
3
3
  const MIN_STAIR_FLIGHT_RISE = 0.1;
4
4
  const MIN_STAIR_FLIGHT_STEP_COUNT = 2;
5
5
  /**