@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.
Files changed (471) hide show
  1. package/dist/events/bus.d.ts +67 -13
  2. package/dist/events/bus.d.ts.map +1 -1
  3. package/dist/hooks/scene-registry/item-clip-registry.d.ts +18 -0
  4. package/dist/hooks/scene-registry/item-clip-registry.d.ts.map +1 -0
  5. package/dist/hooks/scene-registry/item-clip-registry.js +10 -0
  6. package/dist/hooks/scene-registry/scene-registry.d.ts +14 -23
  7. package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
  8. package/dist/hooks/scene-registry/scene-registry.js +59 -26
  9. package/dist/hooks/scene-registry/scene-registry.test.d.ts +2 -0
  10. package/dist/hooks/scene-registry/scene-registry.test.d.ts.map +1 -0
  11. package/dist/hooks/scene-registry/scene-registry.test.js +26 -0
  12. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +14 -0
  13. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -0
  14. package/dist/hooks/spatial-grid/floor-placed-elevation.js +51 -0
  15. package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts +2 -0
  16. package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts.map +1 -0
  17. package/dist/hooks/spatial-grid/floor-placed-elevation.test.js +366 -0
  18. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +79 -11
  19. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
  20. package/dist/hooks/spatial-grid/spatial-grid-manager.js +508 -141
  21. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +28 -1
  22. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
  23. package/dist/hooks/spatial-grid/spatial-grid-sync.js +109 -18
  24. package/dist/hooks/spatial-grid/wall-slab-overlap.test.d.ts +2 -0
  25. package/dist/hooks/spatial-grid/wall-slab-overlap.test.d.ts.map +1 -0
  26. package/dist/hooks/spatial-grid/wall-slab-overlap.test.js +363 -0
  27. package/dist/index.d.ts +36 -8
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +33 -6
  30. package/dist/lib/level-name.d.ts +4 -0
  31. package/dist/lib/level-name.d.ts.map +1 -0
  32. package/dist/lib/level-name.js +10 -0
  33. package/dist/lib/measurement-geometry.d.ts +19 -0
  34. package/dist/lib/measurement-geometry.d.ts.map +1 -0
  35. package/dist/lib/measurement-geometry.js +232 -0
  36. package/dist/lib/measurement-geometry.test.d.ts +2 -0
  37. package/dist/lib/measurement-geometry.test.d.ts.map +1 -0
  38. package/dist/lib/measurement-geometry.test.js +102 -0
  39. package/dist/lib/polygon-geometry.d.ts +0 -1
  40. package/dist/lib/polygon-geometry.d.ts.map +1 -1
  41. package/dist/lib/polygon-geometry.js +0 -18
  42. package/dist/lib/polygon-relations.d.ts +10 -0
  43. package/dist/lib/polygon-relations.d.ts.map +1 -0
  44. package/dist/lib/polygon-relations.js +73 -0
  45. package/dist/lib/selection-proxy.d.ts +4 -0
  46. package/dist/lib/selection-proxy.d.ts.map +1 -0
  47. package/dist/lib/selection-proxy.js +12 -0
  48. package/dist/lib/slab-polygon.d.ts +31 -2
  49. package/dist/lib/slab-polygon.d.ts.map +1 -1
  50. package/dist/lib/slab-polygon.js +525 -31
  51. package/dist/lib/slab-polygon.test.d.ts +2 -0
  52. package/dist/lib/slab-polygon.test.d.ts.map +1 -0
  53. package/dist/lib/slab-polygon.test.js +635 -0
  54. package/dist/lib/slots.d.ts +14 -0
  55. package/dist/lib/slots.d.ts.map +1 -0
  56. package/dist/lib/slots.js +26 -0
  57. package/dist/lib/space-detection-pause.test.d.ts +2 -0
  58. package/dist/lib/space-detection-pause.test.d.ts.map +1 -0
  59. package/dist/lib/space-detection-pause.test.js +42 -0
  60. package/dist/lib/space-detection.d.ts +54 -2
  61. package/dist/lib/space-detection.d.ts.map +1 -1
  62. package/dist/lib/space-detection.js +599 -124
  63. package/dist/lib/space-detection.test.d.ts +2 -0
  64. package/dist/lib/space-detection.test.d.ts.map +1 -0
  65. package/dist/lib/space-detection.test.js +376 -0
  66. package/dist/lib/wall-distance.d.ts +60 -0
  67. package/dist/lib/wall-distance.d.ts.map +1 -0
  68. package/dist/lib/wall-distance.js +85 -0
  69. package/dist/lib/zone-quantities.d.ts +21 -0
  70. package/dist/lib/zone-quantities.d.ts.map +1 -0
  71. package/dist/lib/zone-quantities.js +183 -0
  72. package/dist/lib/zone-quantities.test.d.ts +2 -0
  73. package/dist/lib/zone-quantities.test.d.ts.map +1 -0
  74. package/dist/lib/zone-quantities.test.js +82 -0
  75. package/dist/material-library.d.ts +20 -1
  76. package/dist/material-library.d.ts.map +1 -1
  77. package/dist/material-library.js +3737 -200
  78. package/dist/registry/__bench__/relations-resolver.bench.d.ts +15 -0
  79. package/dist/registry/__bench__/relations-resolver.bench.d.ts.map +1 -0
  80. package/dist/registry/__bench__/relations-resolver.bench.js +170 -0
  81. package/dist/registry/handles.d.ts +394 -0
  82. package/dist/registry/handles.d.ts.map +1 -0
  83. package/dist/registry/handles.js +24 -0
  84. package/dist/registry/index.d.ts +7 -0
  85. package/dist/registry/index.d.ts.map +1 -0
  86. package/dist/registry/index.js +4 -0
  87. package/dist/registry/registry.d.ts +136 -0
  88. package/dist/registry/registry.d.ts.map +1 -0
  89. package/dist/registry/registry.js +282 -0
  90. package/dist/registry/registry.test.d.ts +2 -0
  91. package/dist/registry/registry.test.d.ts.map +1 -0
  92. package/dist/registry/registry.test.js +196 -0
  93. package/dist/registry/relations-resolver.d.ts +42 -0
  94. package/dist/registry/relations-resolver.d.ts.map +1 -0
  95. package/dist/registry/relations-resolver.js +77 -0
  96. package/dist/registry/relations-resolver.test.d.ts +2 -0
  97. package/dist/registry/relations-resolver.test.d.ts.map +1 -0
  98. package/dist/registry/relations-resolver.test.js +183 -0
  99. package/dist/registry/scene-api.d.ts +44 -0
  100. package/dist/registry/scene-api.d.ts.map +1 -0
  101. package/dist/registry/scene-api.js +111 -0
  102. package/dist/registry/scene-api.test.d.ts +2 -0
  103. package/dist/registry/scene-api.test.d.ts.map +1 -0
  104. package/dist/registry/scene-api.test.js +183 -0
  105. package/dist/registry/subtree.d.ts +67 -0
  106. package/dist/registry/subtree.d.ts.map +1 -0
  107. package/dist/registry/subtree.js +123 -0
  108. package/dist/registry/subtree.test.d.ts +2 -0
  109. package/dist/registry/subtree.test.d.ts.map +1 -0
  110. package/dist/registry/subtree.test.js +163 -0
  111. package/dist/registry/types.d.ts +2099 -0
  112. package/dist/registry/types.d.ts.map +1 -0
  113. package/dist/registry/types.js +1 -0
  114. package/dist/schema/index.d.ts +35 -4
  115. package/dist/schema/index.d.ts.map +1 -1
  116. package/dist/schema/index.js +32 -4
  117. package/dist/schema/material.d.ts +13 -2
  118. package/dist/schema/material.d.ts.map +1 -1
  119. package/dist/schema/material.js +17 -5
  120. package/dist/schema/material.test.d.ts +2 -0
  121. package/dist/schema/material.test.d.ts.map +1 -0
  122. package/dist/schema/material.test.js +43 -0
  123. package/dist/schema/nodes/box-vent.d.ts +74 -0
  124. package/dist/schema/nodes/box-vent.d.ts.map +1 -0
  125. package/dist/schema/nodes/box-vent.js +63 -0
  126. package/dist/schema/nodes/building.d.ts +1 -1
  127. package/dist/schema/nodes/building.d.ts.map +1 -1
  128. package/dist/schema/nodes/building.js +3 -2
  129. package/dist/schema/nodes/cabinet.d.ts +534 -0
  130. package/dist/schema/nodes/cabinet.d.ts.map +1 -0
  131. package/dist/schema/nodes/cabinet.js +137 -0
  132. package/dist/schema/nodes/ceiling.d.ts +5 -2
  133. package/dist/schema/nodes/ceiling.d.ts.map +1 -1
  134. package/dist/schema/nodes/ceiling.js +5 -1
  135. package/dist/schema/nodes/chimney.d.ts +158 -0
  136. package/dist/schema/nodes/chimney.d.ts.map +1 -0
  137. package/dist/schema/nodes/chimney.js +67 -0
  138. package/dist/schema/nodes/column.d.ts +600 -7
  139. package/dist/schema/nodes/column.d.ts.map +1 -1
  140. package/dist/schema/nodes/column.js +589 -6
  141. package/dist/schema/nodes/cupola.d.ts +66 -0
  142. package/dist/schema/nodes/cupola.d.ts.map +1 -0
  143. package/dist/schema/nodes/cupola.js +28 -0
  144. package/dist/schema/nodes/door.d.ts +13 -5
  145. package/dist/schema/nodes/door.d.ts.map +1 -1
  146. package/dist/schema/nodes/door.js +12 -0
  147. package/dist/schema/nodes/dormer.d.ts +228 -0
  148. package/dist/schema/nodes/dormer.d.ts.map +1 -0
  149. package/dist/schema/nodes/dormer.js +119 -0
  150. package/dist/schema/nodes/downspout.d.ts +75 -0
  151. package/dist/schema/nodes/downspout.d.ts.map +1 -0
  152. package/dist/schema/nodes/downspout.js +63 -0
  153. package/dist/schema/nodes/duct-fitting.d.ts +91 -0
  154. package/dist/schema/nodes/duct-fitting.d.ts.map +1 -0
  155. package/dist/schema/nodes/duct-fitting.js +92 -0
  156. package/dist/schema/nodes/duct-segment.d.ts +61 -0
  157. package/dist/schema/nodes/duct-segment.d.ts.map +1 -0
  158. package/dist/schema/nodes/duct-segment.js +73 -0
  159. package/dist/schema/nodes/duct-terminal.d.ts +57 -0
  160. package/dist/schema/nodes/duct-terminal.d.ts.map +1 -0
  161. package/dist/schema/nodes/duct-terminal.js +51 -0
  162. package/dist/schema/nodes/elevator.d.ts +106 -0
  163. package/dist/schema/nodes/elevator.d.ts.map +1 -0
  164. package/dist/schema/nodes/elevator.js +57 -0
  165. package/dist/schema/nodes/eyebrow-vent.d.ts +68 -0
  166. package/dist/schema/nodes/eyebrow-vent.d.ts.map +1 -0
  167. package/dist/schema/nodes/eyebrow-vent.js +40 -0
  168. package/dist/schema/nodes/fence.d.ts +19 -2
  169. package/dist/schema/nodes/fence.d.ts.map +1 -1
  170. package/dist/schema/nodes/fence.js +27 -2
  171. package/dist/schema/nodes/gutter.d.ts +84 -0
  172. package/dist/schema/nodes/gutter.d.ts.map +1 -0
  173. package/dist/schema/nodes/gutter.js +76 -0
  174. package/dist/schema/nodes/hvac-equipment.d.ts +63 -0
  175. package/dist/schema/nodes/hvac-equipment.d.ts.map +1 -0
  176. package/dist/schema/nodes/hvac-equipment.js +55 -0
  177. package/dist/schema/nodes/item.d.ts +12 -0
  178. package/dist/schema/nodes/item.d.ts.map +1 -1
  179. package/dist/schema/nodes/item.js +20 -0
  180. package/dist/schema/nodes/level.d.ts +1 -1
  181. package/dist/schema/nodes/level.d.ts.map +1 -1
  182. package/dist/schema/nodes/level.js +4 -0
  183. package/dist/schema/nodes/lineset.d.ts +42 -0
  184. package/dist/schema/nodes/lineset.d.ts.map +1 -0
  185. package/dist/schema/nodes/lineset.js +38 -0
  186. package/dist/schema/nodes/liquid-line.d.ts +34 -0
  187. package/dist/schema/nodes/liquid-line.d.ts.map +1 -0
  188. package/dist/schema/nodes/liquid-line.js +24 -0
  189. package/dist/schema/nodes/measurement.d.ts +306 -0
  190. package/dist/schema/nodes/measurement.d.ts.map +1 -0
  191. package/dist/schema/nodes/measurement.js +87 -0
  192. package/dist/schema/nodes/measurement.test.d.ts +2 -0
  193. package/dist/schema/nodes/measurement.test.d.ts.map +1 -0
  194. package/dist/schema/nodes/measurement.test.js +139 -0
  195. package/dist/schema/nodes/pipe-fitting.d.ts +56 -0
  196. package/dist/schema/nodes/pipe-fitting.d.ts.map +1 -0
  197. package/dist/schema/nodes/pipe-fitting.js +45 -0
  198. package/dist/schema/nodes/pipe-segment.d.ts +48 -0
  199. package/dist/schema/nodes/pipe-segment.d.ts.map +1 -0
  200. package/dist/schema/nodes/pipe-segment.js +36 -0
  201. package/dist/schema/nodes/pipe-trap.d.ts +43 -0
  202. package/dist/schema/nodes/pipe-trap.d.ts.map +1 -0
  203. package/dist/schema/nodes/pipe-trap.js +36 -0
  204. package/dist/schema/nodes/ridge-vent-defaults.test.d.ts +2 -0
  205. package/dist/schema/nodes/ridge-vent-defaults.test.d.ts.map +1 -0
  206. package/dist/schema/nodes/ridge-vent-defaults.test.js +205 -0
  207. package/dist/schema/nodes/ridge-vent.d.ts +82 -0
  208. package/dist/schema/nodes/ridge-vent.d.ts.map +1 -0
  209. package/dist/schema/nodes/ridge-vent.js +248 -0
  210. package/dist/schema/nodes/roof-segment-shape.d.ts +90 -0
  211. package/dist/schema/nodes/roof-segment-shape.d.ts.map +1 -0
  212. package/dist/schema/nodes/roof-segment-shape.js +318 -0
  213. package/dist/schema/nodes/roof-segment-shape.test.d.ts +2 -0
  214. package/dist/schema/nodes/roof-segment-shape.test.d.ts.map +1 -0
  215. package/dist/schema/nodes/roof-segment-shape.test.js +175 -0
  216. package/dist/schema/nodes/roof-segment-surface.test.d.ts +2 -0
  217. package/dist/schema/nodes/roof-segment-surface.test.d.ts.map +1 -0
  218. package/dist/schema/nodes/roof-segment-surface.test.js +48 -0
  219. package/dist/schema/nodes/roof-segment-trim.test.d.ts +2 -0
  220. package/dist/schema/nodes/roof-segment-trim.test.d.ts.map +1 -0
  221. package/dist/schema/nodes/roof-segment-trim.test.js +107 -0
  222. package/dist/schema/nodes/roof-segment-walls.d.ts +101 -0
  223. package/dist/schema/nodes/roof-segment-walls.d.ts.map +1 -0
  224. package/dist/schema/nodes/roof-segment-walls.js +330 -0
  225. package/dist/schema/nodes/roof-segment-walls.test.d.ts +2 -0
  226. package/dist/schema/nodes/roof-segment-walls.test.d.ts.map +1 -0
  227. package/dist/schema/nodes/roof-segment-walls.test.js +92 -0
  228. package/dist/schema/nodes/roof-segment.d.ts +273 -3
  229. package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
  230. package/dist/schema/nodes/roof-segment.js +539 -3
  231. package/dist/schema/nodes/roof.d.ts +8 -8
  232. package/dist/schema/nodes/roof.d.ts.map +1 -1
  233. package/dist/schema/nodes/roof.js +4 -16
  234. package/dist/schema/nodes/shelf.d.ts +106 -0
  235. package/dist/schema/nodes/shelf.d.ts.map +1 -0
  236. package/dist/schema/nodes/shelf.js +90 -0
  237. package/dist/schema/nodes/site.d.ts +1 -122
  238. package/dist/schema/nodes/site.d.ts.map +1 -1
  239. package/dist/schema/nodes/site.js +2 -6
  240. package/dist/schema/nodes/skylight.d.ts +279 -0
  241. package/dist/schema/nodes/skylight.d.ts.map +1 -0
  242. package/dist/schema/nodes/skylight.js +152 -0
  243. package/dist/schema/nodes/slab.d.ts +5 -2
  244. package/dist/schema/nodes/slab.d.ts.map +1 -1
  245. package/dist/schema/nodes/slab.js +5 -1
  246. package/dist/schema/nodes/solar-panel.d.ts +117 -0
  247. package/dist/schema/nodes/solar-panel.d.ts.map +1 -0
  248. package/dist/schema/nodes/solar-panel.js +47 -0
  249. package/dist/schema/nodes/stair-segment.d.ts +4 -4
  250. package/dist/schema/nodes/stair.d.ts +13 -12
  251. package/dist/schema/nodes/stair.d.ts.map +1 -1
  252. package/dist/schema/nodes/stair.js +3 -0
  253. package/dist/schema/nodes/surface-hole-metadata.d.ts +2 -0
  254. package/dist/schema/nodes/surface-hole-metadata.d.ts.map +1 -1
  255. package/dist/schema/nodes/surface-hole-metadata.js +3 -1
  256. package/dist/schema/nodes/turbine-vent.d.ts +68 -0
  257. package/dist/schema/nodes/turbine-vent.d.ts.map +1 -0
  258. package/dist/schema/nodes/turbine-vent.js +41 -0
  259. package/dist/schema/nodes/wall.d.ts +245 -6
  260. package/dist/schema/nodes/wall.d.ts.map +1 -1
  261. package/dist/schema/nodes/wall.js +257 -0
  262. package/dist/schema/nodes/wall.test.d.ts +2 -0
  263. package/dist/schema/nodes/wall.test.d.ts.map +1 -0
  264. package/dist/schema/nodes/wall.test.js +208 -0
  265. package/dist/schema/nodes/window.d.ts +11 -3
  266. package/dist/schema/nodes/window.d.ts.map +1 -1
  267. package/dist/schema/nodes/window.js +12 -0
  268. package/dist/schema/nodes/zone.d.ts +2 -0
  269. package/dist/schema/nodes/zone.d.ts.map +1 -1
  270. package/dist/schema/nodes/zone.js +6 -0
  271. package/dist/schema/scene-material.d.ts +41 -0
  272. package/dist/schema/scene-material.d.ts.map +1 -0
  273. package/dist/schema/scene-material.js +9 -0
  274. package/dist/schema/types.d.ts +2850 -655
  275. package/dist/schema/types.d.ts.map +1 -1
  276. package/dist/schema/types.js +49 -0
  277. package/dist/services/alignment-anchors.d.ts +100 -0
  278. package/dist/services/alignment-anchors.d.ts.map +1 -0
  279. package/dist/services/alignment-anchors.js +312 -0
  280. package/dist/services/alignment-anchors.test.d.ts +2 -0
  281. package/dist/services/alignment-anchors.test.d.ts.map +1 -0
  282. package/dist/services/alignment-anchors.test.js +383 -0
  283. package/dist/services/alignment.d.ts +131 -0
  284. package/dist/services/alignment.d.ts.map +1 -0
  285. package/dist/services/alignment.js +171 -0
  286. package/dist/services/alignment.test.d.ts +2 -0
  287. package/dist/services/alignment.test.d.ts.map +1 -0
  288. package/dist/services/alignment.test.js +92 -0
  289. package/dist/services/drag-session.d.ts +47 -0
  290. package/dist/services/drag-session.d.ts.map +1 -0
  291. package/dist/services/drag-session.js +100 -0
  292. package/dist/services/drag-session.test.d.ts +2 -0
  293. package/dist/services/drag-session.test.d.ts.map +1 -0
  294. package/dist/services/drag-session.test.js +219 -0
  295. package/dist/services/hosting.d.ts +88 -0
  296. package/dist/services/hosting.d.ts.map +1 -0
  297. package/dist/services/hosting.js +131 -0
  298. package/dist/services/hosting.test.d.ts +2 -0
  299. package/dist/services/hosting.test.d.ts.map +1 -0
  300. package/dist/services/hosting.test.js +230 -0
  301. package/dist/services/index.d.ts +13 -0
  302. package/dist/services/index.d.ts.map +1 -0
  303. package/dist/services/index.js +12 -0
  304. package/dist/services/level-height.d.ts +28 -0
  305. package/dist/services/level-height.d.ts.map +1 -0
  306. package/dist/services/level-height.js +62 -0
  307. package/dist/services/movement.d.ts +48 -0
  308. package/dist/services/movement.d.ts.map +1 -0
  309. package/dist/services/movement.js +65 -0
  310. package/dist/services/movement.test.d.ts +2 -0
  311. package/dist/services/movement.test.d.ts.map +1 -0
  312. package/dist/services/movement.test.js +133 -0
  313. package/dist/services/opening-guides.d.ts +141 -0
  314. package/dist/services/opening-guides.d.ts.map +1 -0
  315. package/dist/services/opening-guides.js +267 -0
  316. package/dist/services/opening-guides.test.d.ts +2 -0
  317. package/dist/services/opening-guides.test.d.ts.map +1 -0
  318. package/dist/services/opening-guides.test.js +208 -0
  319. package/dist/services/port-connectivity.d.ts +115 -0
  320. package/dist/services/port-connectivity.d.ts.map +1 -0
  321. package/dist/services/port-connectivity.js +300 -0
  322. package/dist/services/port-connectivity.test.d.ts +2 -0
  323. package/dist/services/port-connectivity.test.d.ts.map +1 -0
  324. package/dist/services/port-connectivity.test.js +297 -0
  325. package/dist/services/riser-diagram.d.ts +40 -0
  326. package/dist/services/riser-diagram.d.ts.map +1 -0
  327. package/dist/services/riser-diagram.js +110 -0
  328. package/dist/services/riser-diagram.test.d.ts +2 -0
  329. package/dist/services/riser-diagram.test.d.ts.map +1 -0
  330. package/dist/services/riser-diagram.test.js +66 -0
  331. package/dist/services/single-undo-dance.test.d.ts +2 -0
  332. package/dist/services/single-undo-dance.test.d.ts.map +1 -0
  333. package/dist/services/single-undo-dance.test.js +210 -0
  334. package/dist/services/snap.d.ts +80 -0
  335. package/dist/services/snap.d.ts.map +1 -0
  336. package/dist/services/snap.js +140 -0
  337. package/dist/services/snap.test.d.ts +2 -0
  338. package/dist/services/snap.test.d.ts.map +1 -0
  339. package/dist/services/snap.test.js +137 -0
  340. package/dist/services/system-graph.d.ts +30 -0
  341. package/dist/services/system-graph.d.ts.map +1 -0
  342. package/dist/services/system-graph.js +164 -0
  343. package/dist/services/system-graph.test.d.ts +2 -0
  344. package/dist/services/system-graph.test.d.ts.map +1 -0
  345. package/dist/services/system-graph.test.js +138 -0
  346. package/dist/services/validate-dwv.d.ts +32 -0
  347. package/dist/services/validate-dwv.d.ts.map +1 -0
  348. package/dist/services/validate-dwv.js +118 -0
  349. package/dist/services/validate-dwv.test.d.ts +2 -0
  350. package/dist/services/validate-dwv.test.d.ts.map +1 -0
  351. package/dist/services/validate-dwv.test.js +109 -0
  352. package/dist/solar-panel-presets.d.ts +17 -0
  353. package/dist/solar-panel-presets.d.ts.map +1 -0
  354. package/dist/solar-panel-presets.js +43 -0
  355. package/dist/store/actions/node-actions.d.ts +14 -2
  356. package/dist/store/actions/node-actions.d.ts.map +1 -1
  357. package/dist/store/actions/node-actions.js +585 -15
  358. package/dist/store/actions/node-mutation-sanitize.test.d.ts +2 -0
  359. package/dist/store/actions/node-mutation-sanitize.test.d.ts.map +1 -0
  360. package/dist/store/actions/node-mutation-sanitize.test.js +147 -0
  361. package/dist/store/actions/reparent.test.d.ts +2 -0
  362. package/dist/store/actions/reparent.test.d.ts.map +1 -0
  363. package/dist/store/actions/reparent.test.js +212 -0
  364. package/dist/store/actions/ridge-vent-update.test.d.ts +2 -0
  365. package/dist/store/actions/ridge-vent-update.test.d.ts.map +1 -0
  366. package/dist/store/actions/ridge-vent-update.test.js +264 -0
  367. package/dist/store/history-control.d.ts +11 -0
  368. package/dist/store/history-control.d.ts.map +1 -1
  369. package/dist/store/history-control.js +33 -0
  370. package/dist/store/use-interactive.d.ts +39 -0
  371. package/dist/store/use-interactive.d.ts.map +1 -1
  372. package/dist/store/use-interactive.js +75 -0
  373. package/dist/store/use-live-node-overrides.d.ts +22 -0
  374. package/dist/store/use-live-node-overrides.d.ts.map +1 -0
  375. package/dist/store/use-live-node-overrides.js +59 -0
  376. package/dist/store/use-scene-dirty-tracking.test.d.ts +2 -0
  377. package/dist/store/use-scene-dirty-tracking.test.d.ts.map +1 -0
  378. package/dist/store/use-scene-dirty-tracking.test.js +68 -0
  379. package/dist/store/use-scene-elevator-migration.test.d.ts +2 -0
  380. package/dist/store/use-scene-elevator-migration.test.d.ts.map +1 -0
  381. package/dist/store/use-scene-elevator-migration.test.js +109 -0
  382. package/dist/store/use-scene-measurement-roundtrip.test.d.ts +2 -0
  383. package/dist/store/use-scene-measurement-roundtrip.test.d.ts.map +1 -0
  384. package/dist/store/use-scene-measurement-roundtrip.test.js +97 -0
  385. package/dist/store/use-scene-plugins.test.d.ts +2 -0
  386. package/dist/store/use-scene-plugins.test.d.ts.map +1 -0
  387. package/dist/store/use-scene-plugins.test.js +51 -0
  388. package/dist/store/use-scene-wall-slot-migration.test.d.ts +2 -0
  389. package/dist/store/use-scene-wall-slot-migration.test.d.ts.map +1 -0
  390. package/dist/store/use-scene-wall-slot-migration.test.js +210 -0
  391. package/dist/store/use-scene-window-migration.test.d.ts +2 -0
  392. package/dist/store/use-scene-window-migration.test.d.ts.map +1 -0
  393. package/dist/store/use-scene-window-migration.test.js +85 -0
  394. package/dist/store/use-scene.d.ts +28 -2
  395. package/dist/store/use-scene.d.ts.map +1 -1
  396. package/dist/store/use-scene.js +546 -49
  397. package/dist/systems/elevator/elevator-dispatch.d.ts +12 -0
  398. package/dist/systems/elevator/elevator-dispatch.d.ts.map +1 -0
  399. package/dist/systems/elevator/elevator-dispatch.js +57 -0
  400. package/dist/systems/elevator/elevator-geometry.d.ts +15 -0
  401. package/dist/systems/elevator/elevator-geometry.d.ts.map +1 -0
  402. package/dist/systems/elevator/elevator-geometry.js +50 -0
  403. package/dist/systems/elevator/elevator-opening-sync.d.ts +6 -0
  404. package/dist/systems/elevator/elevator-opening-sync.d.ts.map +1 -0
  405. package/dist/systems/elevator/elevator-opening-sync.js +218 -0
  406. package/dist/systems/elevator/elevator-opening-sync.test.d.ts +2 -0
  407. package/dist/systems/elevator/elevator-opening-sync.test.d.ts.map +1 -0
  408. package/dist/systems/elevator/elevator-opening-sync.test.js +146 -0
  409. package/dist/systems/elevator/elevator-opening-system.d.ts +2 -0
  410. package/dist/systems/elevator/elevator-opening-system.d.ts.map +1 -0
  411. package/dist/systems/elevator/elevator-opening-system.js +48 -0
  412. package/dist/systems/elevator/elevator-runtime-system.d.ts +2 -0
  413. package/dist/systems/elevator/elevator-runtime-system.d.ts.map +1 -0
  414. package/dist/systems/elevator/elevator-runtime-system.js +8 -0
  415. package/dist/systems/elevator/elevator-runtime.d.ts +18 -0
  416. package/dist/systems/elevator/elevator-runtime.d.ts.map +1 -0
  417. package/dist/systems/elevator/elevator-runtime.js +225 -0
  418. package/dist/systems/elevator/elevator-runtime.test.d.ts +2 -0
  419. package/dist/systems/elevator/elevator-runtime.test.d.ts.map +1 -0
  420. package/dist/systems/elevator/elevator-runtime.test.js +64 -0
  421. package/dist/systems/elevator/elevator-service.d.ts +19 -0
  422. package/dist/systems/elevator/elevator-service.d.ts.map +1 -0
  423. package/dist/systems/elevator/elevator-service.js +111 -0
  424. package/dist/systems/fence/fence-centerline.d.ts +12 -0
  425. package/dist/systems/fence/fence-centerline.d.ts.map +1 -0
  426. package/dist/systems/fence/fence-centerline.js +37 -0
  427. package/dist/systems/fence/fence-spline.d.ts +39 -0
  428. package/dist/systems/fence/fence-spline.d.ts.map +1 -0
  429. package/dist/systems/fence/fence-spline.js +196 -0
  430. package/dist/systems/fence/fence-spline.test.d.ts +2 -0
  431. package/dist/systems/fence/fence-spline.test.d.ts.map +1 -0
  432. package/dist/systems/fence/fence-spline.test.js +136 -0
  433. package/dist/systems/stair/stair-footprint.d.ts +44 -0
  434. package/dist/systems/stair/stair-footprint.d.ts.map +1 -0
  435. package/dist/systems/stair/stair-footprint.js +178 -0
  436. package/dist/systems/stair/stair-opening-preview.d.ts +2447 -0
  437. package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -0
  438. package/dist/systems/stair/stair-opening-preview.js +93 -0
  439. package/dist/systems/stair/stair-opening-preview.test.d.ts +2 -0
  440. package/dist/systems/stair/stair-opening-preview.test.d.ts.map +1 -0
  441. package/dist/systems/stair/stair-opening-preview.test.js +80 -0
  442. package/dist/systems/stair/stair-opening-sync.d.ts.map +1 -1
  443. package/dist/systems/stair/stair-opening-sync.js +155 -147
  444. package/dist/systems/stair/stair-opening-sync.test.js +424 -2
  445. package/dist/systems/stair/stair-opening-system.d.ts +2 -0
  446. package/dist/systems/stair/stair-opening-system.d.ts.map +1 -0
  447. package/dist/systems/stair/stair-opening-system.js +104 -0
  448. package/dist/systems/wall/wall-mitering.d.ts.map +1 -1
  449. package/dist/systems/wall/wall-mitering.js +38 -2
  450. package/dist/systems/wall/wall-mitering.test.d.ts +2 -0
  451. package/dist/systems/wall/wall-mitering.test.d.ts.map +1 -0
  452. package/dist/systems/wall/wall-mitering.test.js +63 -0
  453. package/dist/systems/wall/wall-move.d.ts +48 -0
  454. package/dist/systems/wall/wall-move.d.ts.map +1 -0
  455. package/dist/systems/wall/wall-move.js +193 -0
  456. package/dist/utils/clone-scene-graph.d.ts +7 -4
  457. package/dist/utils/clone-scene-graph.d.ts.map +1 -1
  458. package/dist/utils/clone-scene-graph.js +29 -7
  459. package/dist/utils/clone-scene-graph.test.d.ts +2 -0
  460. package/dist/utils/clone-scene-graph.test.d.ts.map +1 -0
  461. package/dist/utils/clone-scene-graph.test.js +62 -0
  462. package/dist/utils/heal-scene-graph.d.ts +18 -0
  463. package/dist/utils/heal-scene-graph.d.ts.map +1 -0
  464. package/dist/utils/heal-scene-graph.js +90 -0
  465. package/dist/utils/heal-scene-graph.test.d.ts +2 -0
  466. package/dist/utils/heal-scene-graph.test.d.ts.map +1 -0
  467. package/dist/utils/heal-scene-graph.test.js +88 -0
  468. package/dist/validation/validate-build-json.d.ts +44 -0
  469. package/dist/validation/validate-build-json.d.ts.map +1 -0
  470. package/dist/validation/validate-build-json.js +256 -0
  471. package/package.json +11 -4
@@ -0,0 +1,63 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import { calculateLevelMiters, getWallMiterBoundaryPoints } from './wall-mitering';
3
+ function wall(id, start, end) {
4
+ return {
5
+ id,
6
+ type: 'wall',
7
+ object: 'node',
8
+ visible: true,
9
+ parentId: 'level_test',
10
+ children: [],
11
+ start,
12
+ end,
13
+ thickness: 0.1,
14
+ height: 2.5,
15
+ frontSide: 'interior',
16
+ backSide: 'exterior',
17
+ metadata: {},
18
+ };
19
+ }
20
+ function maxBoundaryCoord(walls) {
21
+ const miter = calculateLevelMiters(walls);
22
+ let max = 0;
23
+ for (const w of walls) {
24
+ const bp = getWallMiterBoundaryPoints(w, miter);
25
+ expect(bp).not.toBeNull();
26
+ if (!bp)
27
+ continue;
28
+ for (const p of [bp.startLeft, bp.startRight, bp.endLeft, bp.endRight]) {
29
+ expect(Number.isFinite(p.x)).toBe(true);
30
+ expect(Number.isFinite(p.y)).toBe(true);
31
+ max = Math.max(max, Math.abs(p.x), Math.abs(p.y));
32
+ }
33
+ }
34
+ return max;
35
+ }
36
+ describe('wall mitering miter limit', () => {
37
+ // Two 3 m walls sharing the origin, meeting at decreasing angles. Without a
38
+ // miter limit the joint point runs to infinity as the angle → 0 (∝ 1/sin θ),
39
+ // which is the "infinite wall" seen when a room-preset preview lands on top of
40
+ // an existing wall. The boundary must stay bounded near the wall length.
41
+ test.each([90, 30, 10, 5, 1, 0.1, 0.01])('stays bounded at a %s° junction', (deg) => {
42
+ const rad = (deg * Math.PI) / 180;
43
+ const walls = [
44
+ wall('A', [0, 0], [3, 0]),
45
+ wall('B', [0, 0], [3 * Math.cos(rad), 3 * Math.sin(rad)]),
46
+ ];
47
+ // 3 m walls + a few cm of joint: anything past ~4 m is a runaway spike.
48
+ expect(maxBoundaryCoord(walls)).toBeLessThan(4);
49
+ });
50
+ test('still miters a normal 90° corner', () => {
51
+ const walls = [wall('A', [0, 0], [3, 0]), wall('B', [0, 0], [0, 3])];
52
+ const miter = calculateLevelMiters(walls);
53
+ const bpA = getWallMiterBoundaryPoints(walls[0], miter);
54
+ expect(bpA).not.toBeNull();
55
+ if (!bpA)
56
+ throw new Error('expected miter boundary points');
57
+ // The shared corner is pulled to the mitred intersection, offset from the
58
+ // raw butt position (halfThickness 0.05) by the diagonal of the joint.
59
+ const startSideX = Math.min(bpA.startLeft.x, bpA.startRight.x);
60
+ expect(startSideX).toBeLessThan(-0.001);
61
+ expect(startSideX).toBeGreaterThan(-0.5);
62
+ });
63
+ });
@@ -0,0 +1,48 @@
1
+ import type { WallNode } from '../../schema';
2
+ export type WallPlanPoint = [number, number];
3
+ export type WallMoveAxis = [number, number];
4
+ export type WallMoveEndpoint = 'start' | 'end';
5
+ export type WallMoveBridgePlan<TWall extends Pick<WallNode, 'id' | 'start' | 'end'>> = {
6
+ wall: TWall;
7
+ originalPoint: WallPlanPoint;
8
+ movedEndpoint: WallMoveEndpoint;
9
+ };
10
+ export type WallMoveLinkedWallTargetPlan<TWall extends Pick<WallNode, 'id' | 'start' | 'end'>> = {
11
+ wall: TWall;
12
+ originalPoint: WallPlanPoint;
13
+ targetPoint: WallPlanPoint;
14
+ };
15
+ export type WallMoveJunctionPlan<TWall extends Pick<WallNode, 'id' | 'start' | 'end'>> = {
16
+ linkedWallsToMove: TWall[];
17
+ linkedWallTargetPlans: Array<WallMoveLinkedWallTargetPlan<TWall>>;
18
+ bridgePlans: Array<WallMoveBridgePlan<TWall>>;
19
+ wallsToDelete: TWall[];
20
+ };
21
+ export declare function getPerpendicularWallMoveAxis(start: WallPlanPoint, end: WallPlanPoint): WallMoveAxis | null;
22
+ export declare function constrainWallMoveDeltaToAxis(deltaX: number, deltaZ: number, axis: WallMoveAxis | null): WallPlanPoint;
23
+ /**
24
+ * Apply a junction plan to a list of linked walls, producing the per-wall
25
+ * endpoint updates. Mirrors the 3D `MoveWallTool`'s drag-preview behavior
26
+ * so the 2D move handler can drive the same scene topology.
27
+ *
28
+ * `linkedWallTargetPlans` take precedence over `linkedWallsToMove` — when
29
+ * the planner emits a target plan for a same-direction-consumed wall the
30
+ * matchPoint/targetPoint pair encodes the pivot, not the original ↔ next
31
+ * endpoint mapping.
32
+ */
33
+ export declare function getLinkedWallUpdates<TWall extends Pick<WallNode, 'id' | 'start' | 'end'>>(linkedWalls: Array<{
34
+ wall: TWall;
35
+ matchPoint?: WallPlanPoint;
36
+ targetPoint?: WallPlanPoint;
37
+ }>, originalStart: WallPlanPoint, originalEnd: WallPlanPoint, nextStart: WallPlanPoint, nextEnd: WallPlanPoint): Array<{
38
+ id: TWall['id'];
39
+ start: WallPlanPoint;
40
+ end: WallPlanPoint;
41
+ }>;
42
+ export declare function getPlannedLinkedWallUpdates<TWall extends Pick<WallNode, 'id' | 'start' | 'end'>>(plan: WallMoveJunctionPlan<TWall>, originalStart: WallPlanPoint, originalEnd: WallPlanPoint, nextStart: WallPlanPoint, nextEnd: WallPlanPoint): Array<{
43
+ id: TWall['id'];
44
+ start: WallPlanPoint;
45
+ end: WallPlanPoint;
46
+ }>;
47
+ export declare function planWallMoveJunctions<TWall extends Pick<WallNode, 'id' | 'start' | 'end'>>(linkedWalls: TWall[], originalStart: WallPlanPoint, originalEnd: WallPlanPoint, nextStart: WallPlanPoint, nextEnd: WallPlanPoint): WallMoveJunctionPlan<TWall>;
48
+ //# sourceMappingURL=wall-move.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wall-move.d.ts","sourceRoot":"","sources":["../../../src/systems/wall/wall-move.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAI5C,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAE5C,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAC3C,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,KAAK,CAAA;AAE9C,MAAM,MAAM,kBAAkB,CAAC,KAAK,SAAS,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,OAAO,GAAG,KAAK,CAAC,IAAI;IACrF,IAAI,EAAE,KAAK,CAAA;IACX,aAAa,EAAE,aAAa,CAAA;IAC5B,aAAa,EAAE,gBAAgB,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,4BAA4B,CAAC,KAAK,SAAS,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,OAAO,GAAG,KAAK,CAAC,IAAI;IAC/F,IAAI,EAAE,KAAK,CAAA;IACX,aAAa,EAAE,aAAa,CAAA;IAC5B,WAAW,EAAE,aAAa,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,oBAAoB,CAAC,KAAK,SAAS,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,OAAO,GAAG,KAAK,CAAC,IAAI;IACvF,iBAAiB,EAAE,KAAK,EAAE,CAAA;IAC1B,qBAAqB,EAAE,KAAK,CAAC,4BAA4B,CAAC,KAAK,CAAC,CAAC,CAAA;IACjE,WAAW,EAAE,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAA;IAC7C,aAAa,EAAE,KAAK,EAAE,CAAA;CACvB,CAAA;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,aAAa,GACjB,YAAY,GAAG,IAAI,CAUrB;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,YAAY,GAAG,IAAI,GACxB,aAAa,CAMf;AAkDD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,SAAS,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,OAAO,GAAG,KAAK,CAAC,EACvF,WAAW,EAAE,KAAK,CAAC;IACjB,IAAI,EAAE,KAAK,CAAA;IACX,UAAU,CAAC,EAAE,aAAa,CAAA;IAC1B,WAAW,CAAC,EAAE,aAAa,CAAA;CAC5B,CAAC,EACF,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,aAAa,EAC1B,SAAS,EAAE,aAAa,EACxB,OAAO,EAAE,aAAa,GACrB,KAAK,CAAC;IAAE,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAAC,KAAK,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,aAAa,CAAA;CAAE,CAAC,CA2BtE;AAED,wBAAgB,2BAA2B,CAAC,KAAK,SAAS,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,OAAO,GAAG,KAAK,CAAC,EAC9F,IAAI,EAAE,oBAAoB,CAAC,KAAK,CAAC,EACjC,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,aAAa,EAC1B,SAAS,EAAE,aAAa,EACxB,OAAO,EAAE,aAAa,GACrB,KAAK,CAAC;IAAE,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAAC,KAAK,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,aAAa,CAAA;CAAE,CAAC,CAyBtE;AAED,wBAAgB,qBAAqB,CAAC,KAAK,SAAS,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,OAAO,GAAG,KAAK,CAAC,EACxF,WAAW,EAAE,KAAK,EAAE,EACpB,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,aAAa,EAC1B,SAAS,EAAE,aAAa,EACxB,OAAO,EAAE,aAAa,GACrB,oBAAoB,CAAC,KAAK,CAAC,CAmI7B"}
@@ -0,0 +1,193 @@
1
+ const AXIS_EPSILON = 1e-6;
2
+ export function getPerpendicularWallMoveAxis(start, end) {
3
+ const dx = end[0] - start[0];
4
+ const dz = end[1] - start[1];
5
+ const length = Math.hypot(dx, dz);
6
+ if (length < AXIS_EPSILON)
7
+ return null;
8
+ // Perpendicular (normal) direction for moving the wall "sideways".
9
+ // This matches the arrow handles shown in the editor.
10
+ return [-dz / length, dx / length];
11
+ }
12
+ export function constrainWallMoveDeltaToAxis(deltaX, deltaZ, axis) {
13
+ if (axis) {
14
+ const projected = deltaX * axis[0] + deltaZ * axis[1];
15
+ return [axis[0] * projected, axis[1] * projected];
16
+ }
17
+ return [deltaX, deltaZ];
18
+ }
19
+ function pointsEqual(a, b) {
20
+ return Math.abs(a[0] - b[0]) <= AXIS_EPSILON && Math.abs(a[1] - b[1]) <= AXIS_EPSILON;
21
+ }
22
+ function wallTouchesPoint(wall, point) {
23
+ return pointsEqual(wall.start, point) || pointsEqual(wall.end, point);
24
+ }
25
+ function otherWallEndpoint(wall, point) {
26
+ return pointsEqual(wall.start, point) ? wall.end : wall.start;
27
+ }
28
+ function wallLengthFromPoint(wall, point) {
29
+ const freeEndpoint = otherWallEndpoint(wall, point);
30
+ return Math.hypot(freeEndpoint[0] - point[0], freeEndpoint[1] - point[1]);
31
+ }
32
+ function getMoveWallRelation(wall, sharedPoint, nextPoint) {
33
+ const moveX = nextPoint[0] - sharedPoint[0];
34
+ const moveZ = nextPoint[1] - sharedPoint[1];
35
+ const moveLength = Math.hypot(moveX, moveZ);
36
+ if (moveLength < AXIS_EPSILON)
37
+ return 'stationary';
38
+ const freeEndpoint = otherWallEndpoint(wall, sharedPoint);
39
+ const wallX = freeEndpoint[0] - sharedPoint[0];
40
+ const wallZ = freeEndpoint[1] - sharedPoint[1];
41
+ const wallLength = Math.hypot(wallX, wallZ);
42
+ if (wallLength < AXIS_EPSILON)
43
+ return 'stationary';
44
+ const normalizedCross = Math.abs(moveX * wallZ - moveZ * wallX) / (moveLength * wallLength);
45
+ if (normalizedCross > 1e-4)
46
+ return 'off-axis';
47
+ const normalizedDot = (moveX * wallX + moveZ * wallZ) / (moveLength * wallLength);
48
+ return normalizedDot >= 0 ? 'same-direction' : 'opposite-direction';
49
+ }
50
+ /**
51
+ * Apply a junction plan to a list of linked walls, producing the per-wall
52
+ * endpoint updates. Mirrors the 3D `MoveWallTool`'s drag-preview behavior
53
+ * so the 2D move handler can drive the same scene topology.
54
+ *
55
+ * `linkedWallTargetPlans` take precedence over `linkedWallsToMove` — when
56
+ * the planner emits a target plan for a same-direction-consumed wall the
57
+ * matchPoint/targetPoint pair encodes the pivot, not the original ↔ next
58
+ * endpoint mapping.
59
+ */
60
+ export function getLinkedWallUpdates(linkedWalls, originalStart, originalEnd, nextStart, nextEnd) {
61
+ return linkedWalls.map(({ wall, matchPoint, targetPoint }) => {
62
+ if (matchPoint && targetPoint) {
63
+ return {
64
+ id: wall.id,
65
+ start: pointsEqual(wall.start, matchPoint) ? targetPoint : wall.start,
66
+ end: pointsEqual(wall.end, matchPoint) ? targetPoint : wall.end,
67
+ };
68
+ }
69
+ const targetStart = targetPoint ?? nextStart;
70
+ const targetEnd = targetPoint ?? nextEnd;
71
+ return {
72
+ id: wall.id,
73
+ start: pointsEqual(wall.start, originalStart)
74
+ ? targetStart
75
+ : pointsEqual(wall.start, originalEnd)
76
+ ? targetEnd
77
+ : wall.start,
78
+ end: pointsEqual(wall.end, originalStart)
79
+ ? targetStart
80
+ : pointsEqual(wall.end, originalEnd)
81
+ ? targetEnd
82
+ : wall.end,
83
+ };
84
+ });
85
+ }
86
+ export function getPlannedLinkedWallUpdates(plan, originalStart, originalEnd, nextStart, nextEnd) {
87
+ const movePlans = new Map();
88
+ for (const wall of plan.linkedWallsToMove) {
89
+ movePlans.set(wall.id, { wall });
90
+ }
91
+ for (const targetPlan of plan.linkedWallTargetPlans) {
92
+ movePlans.set(targetPlan.wall.id, {
93
+ wall: targetPlan.wall,
94
+ matchPoint: targetPlan.originalPoint,
95
+ targetPoint: targetPlan.targetPoint,
96
+ });
97
+ }
98
+ return getLinkedWallUpdates(Array.from(movePlans.values()), originalStart, originalEnd, nextStart, nextEnd);
99
+ }
100
+ export function planWallMoveJunctions(linkedWalls, originalStart, originalEnd, nextStart, nextEnd) {
101
+ const linkedWallsToMove = new Map();
102
+ const linkedWallTargetPlans = new Map();
103
+ const bridgePlans = new Map();
104
+ const wallsToDelete = new Map();
105
+ const addStandardEndpointPlan = (endpoint, point, nextPoint, relatedWalls, keySuffix = '', useTargetPlans = false) => {
106
+ const hasSideBranch = relatedWalls.some((entry) => entry.relation === 'off-axis');
107
+ const hasOppositeBridge = relatedWalls.some((entry) => entry.relation === 'opposite-direction' && hasSideBranch);
108
+ for (const { wall, relation } of relatedWalls) {
109
+ if (relation === 'stationary' ||
110
+ relation === 'same-direction' ||
111
+ (relation === 'opposite-direction' && !hasSideBranch)) {
112
+ if (useTargetPlans) {
113
+ linkedWallTargetPlans.set(wall.id, {
114
+ wall,
115
+ originalPoint: point,
116
+ targetPoint: nextPoint,
117
+ });
118
+ }
119
+ else {
120
+ linkedWallsToMove.set(wall.id, wall);
121
+ }
122
+ continue;
123
+ }
124
+ if (relation === 'off-axis' && hasOppositeBridge) {
125
+ continue;
126
+ }
127
+ bridgePlans.set(`${wall.id}:${endpoint}${keySuffix}`, {
128
+ wall,
129
+ originalPoint: point,
130
+ movedEndpoint: endpoint,
131
+ });
132
+ }
133
+ };
134
+ const addEndpointPlan = (endpoint, point, nextPoint) => {
135
+ const moveLength = Math.hypot(nextPoint[0] - point[0], nextPoint[1] - point[1]);
136
+ const linkedAtEndpoint = linkedWalls
137
+ .filter((wall) => wallTouchesPoint(wall, point))
138
+ .map((wall) => ({
139
+ wall,
140
+ relation: getMoveWallRelation(wall, point, nextPoint),
141
+ }));
142
+ const consumedSameDirectionWall = linkedAtEndpoint
143
+ .filter((entry) => entry.relation === 'same-direction')
144
+ .map((entry) => ({
145
+ ...entry,
146
+ distance: wallLengthFromPoint(entry.wall, point),
147
+ }))
148
+ .filter((entry) => moveLength + AXIS_EPSILON >= entry.distance)
149
+ .sort((a, b) => a.distance - b.distance)[0];
150
+ if (consumedSameDirectionWall) {
151
+ const pivotPoint = [
152
+ ...otherWallEndpoint(consumedSameDirectionWall.wall, point),
153
+ ];
154
+ const bridgeSource = linkedAtEndpoint.find((entry) => entry.relation === 'opposite-direction');
155
+ wallsToDelete.set(consumedSameDirectionWall.wall.id, consumedSameDirectionWall.wall);
156
+ linkedWallTargetPlans.set(consumedSameDirectionWall.wall.id, {
157
+ wall: consumedSameDirectionWall.wall,
158
+ originalPoint: point,
159
+ targetPoint: pivotPoint,
160
+ });
161
+ if (bridgeSource) {
162
+ linkedWallTargetPlans.set(bridgeSource.wall.id, {
163
+ wall: bridgeSource.wall,
164
+ originalPoint: point,
165
+ targetPoint: pivotPoint,
166
+ });
167
+ bridgePlans.set(`${bridgeSource.wall.id}:${endpoint}:through`, {
168
+ wall: bridgeSource.wall,
169
+ originalPoint: pivotPoint,
170
+ movedEndpoint: endpoint,
171
+ });
172
+ return;
173
+ }
174
+ const linkedAtPivot = linkedWalls
175
+ .filter((wall) => wall.id !== consumedSameDirectionWall.wall.id && wallTouchesPoint(wall, pivotPoint))
176
+ .map((wall) => ({
177
+ wall,
178
+ relation: getMoveWallRelation(wall, pivotPoint, nextPoint),
179
+ }));
180
+ addStandardEndpointPlan(endpoint, pivotPoint, nextPoint, linkedAtPivot, ':through-pivot', true);
181
+ return;
182
+ }
183
+ addStandardEndpointPlan(endpoint, point, nextPoint, linkedAtEndpoint);
184
+ };
185
+ addEndpointPlan('start', originalStart, nextStart);
186
+ addEndpointPlan('end', originalEnd, nextEnd);
187
+ return {
188
+ linkedWallsToMove: Array.from(linkedWallsToMove.values()),
189
+ linkedWallTargetPlans: Array.from(linkedWallTargetPlans.values()),
190
+ bridgePlans: Array.from(bridgePlans.values()),
191
+ wallsToDelete: Array.from(wallsToDelete.values()),
192
+ };
193
+ }
@@ -4,6 +4,7 @@ export type SceneGraph = {
4
4
  nodes: Record<AnyNodeId, AnyNode>;
5
5
  rootNodeIds: AnyNodeId[];
6
6
  collections?: Record<CollectionId, Collection>;
7
+ installedPlugins?: string[];
7
8
  };
8
9
  /**
9
10
  * Deep clones a scene graph with all node IDs regenerated while preserving
@@ -33,10 +34,12 @@ export declare function cloneLevelSubtree(nodes: Record<AnyNodeId, AnyNode>, lev
33
34
  newLevelId: AnyNodeId;
34
35
  idMap: Map<string, string>;
35
36
  };
37
+ export type ForkSceneGraphOptions = {
38
+ preserveScans?: boolean;
39
+ };
36
40
  /**
37
- * Forks a scene graph for use as a new project: clones with new IDs and strips
38
- * scan and guide nodes (and their references) since those contain user-uploaded
39
- * imagery that shouldn't carry over to a forked project.
41
+ * Forks a scene graph for use as a new project: clones with new IDs and, by
42
+ * default, strips scan and guide nodes since they contain user-uploaded imagery.
40
43
  */
41
- export declare function forkSceneGraph(sceneGraph: SceneGraph): SceneGraph;
44
+ export declare function forkSceneGraph(sceneGraph: SceneGraph, options?: ForkSceneGraphOptions): SceneGraph;
42
45
  //# sourceMappingURL=clone-scene-graph.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"clone-scene-graph.d.ts","sourceRoot":"","sources":["../../src/utils/clone-scene-graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAErE,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IACjC,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;CAC/C,CAAA;AAUD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAuGlE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EACjC,OAAO,EAAE,SAAS,GACjB;IAAE,WAAW,EAAE,OAAO,EAAE,CAAC;IAAC,UAAU,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CA8E/E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAgEjE"}
1
+ {"version":3,"file":"clone-scene-graph.d.ts","sourceRoot":"","sources":["../../src/utils/clone-scene-graph.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAErE,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IACjC,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;IAC9C,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC5B,CAAA;AAUD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAmHlE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EACjC,OAAO,EAAE,SAAS,GACjB;IAAE,WAAW,EAAE,OAAO,EAAE,CAAC;IAAC,UAAU,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAwF/E;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,CAAA;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,UAAU,EACtB,OAAO,GAAE,qBAA0B,GAClC,UAAU,CAqEZ"}
@@ -1,3 +1,4 @@
1
+ import { remapMeasurementReferences } from '../lib/measurement-geometry';
1
2
  import { generateId } from '../schema/base';
2
3
  /**
3
4
  * Extracts the type prefix from a node ID (e.g., "wall_abc123" -> "wall")
@@ -16,7 +17,7 @@ function extractIdPrefix(id) {
16
17
  * - Multi-scene in-memory scenarios
17
18
  */
18
19
  export function cloneSceneGraph(sceneGraph) {
19
- const { nodes, rootNodeIds, collections } = sceneGraph;
20
+ const { nodes, rootNodeIds, collections, installedPlugins } = sceneGraph;
20
21
  // Build ID mapping: old ID -> new ID
21
22
  const idMap = new Map();
22
23
  // Pass 1: Generate new IDs for all nodes
@@ -57,6 +58,14 @@ export function cloneSceneGraph(sceneGraph) {
57
58
  ;
58
59
  clonedNode.wallId = idMap.get(clonedNode.wallId);
59
60
  }
61
+ // Remap roofSegmentId (doors/windows/items hosted on roof wall faces)
62
+ if ('roofSegmentId' in clonedNode && typeof clonedNode.roofSegmentId === 'string') {
63
+ ;
64
+ clonedNode.roofSegmentId = idMap.get(clonedNode.roofSegmentId);
65
+ }
66
+ if (clonedNode.type === 'measurement') {
67
+ clonedNode.measurement = remapMeasurementReferences(clonedNode.measurement, idMap);
68
+ }
60
69
  clonedNodes[newId] = clonedNode;
61
70
  }
62
71
  // Remap root node IDs
@@ -102,6 +111,7 @@ export function cloneSceneGraph(sceneGraph) {
102
111
  nodes: clonedNodes,
103
112
  rootNodeIds: clonedRootNodeIds,
104
113
  ...(clonedCollections && { collections: clonedCollections }),
114
+ ...(installedPlugins && { installedPlugins: [...installedPlugins] }),
105
115
  };
106
116
  }
107
117
  /**
@@ -119,7 +129,7 @@ export function cloneSceneGraph(sceneGraph) {
119
129
  */
120
130
  export function cloneLevelSubtree(nodes, levelId) {
121
131
  const levelNode = nodes[levelId];
122
- if (!levelNode || levelNode.type !== 'level') {
132
+ if (levelNode?.type !== 'level') {
123
133
  throw new Error(`Node "${levelId}" is not a level`);
124
134
  }
125
135
  // Recursively collect the level node + all descendants via children arrays
@@ -185,17 +195,28 @@ export function cloneLevelSubtree(nodes, levelId) {
185
195
  ;
186
196
  cloned.wallId = idMap.get(cloned.wallId) ?? cloned.wallId;
187
197
  }
198
+ // Remap roofSegmentId (doors/windows/items hosted on roof wall faces)
199
+ if ('roofSegmentId' in cloned && typeof cloned.roofSegmentId === 'string') {
200
+ ;
201
+ cloned.roofSegmentId =
202
+ idMap.get(cloned.roofSegmentId) ?? cloned.roofSegmentId;
203
+ }
204
+ if (cloned.type === 'measurement') {
205
+ cloned.measurement = remapMeasurementReferences(cloned.measurement, idMap);
206
+ }
188
207
  clonedNodes.push(cloned);
189
208
  }
190
209
  return { clonedNodes, newLevelId, idMap };
191
210
  }
192
211
  /**
193
- * Forks a scene graph for use as a new project: clones with new IDs and strips
194
- * scan and guide nodes (and their references) since those contain user-uploaded
195
- * imagery that shouldn't carry over to a forked project.
212
+ * Forks a scene graph for use as a new project: clones with new IDs and, by
213
+ * default, strips scan and guide nodes since they contain user-uploaded imagery.
196
214
  */
197
- export function forkSceneGraph(sceneGraph) {
198
- const { nodes, rootNodeIds, collections } = sceneGraph;
215
+ export function forkSceneGraph(sceneGraph, options = {}) {
216
+ if (options.preserveScans) {
217
+ return cloneSceneGraph(sceneGraph);
218
+ }
219
+ const { nodes, rootNodeIds, collections, installedPlugins } = sceneGraph;
199
220
  // First, identify scan and guide node IDs to exclude (user-uploaded imagery)
200
221
  const excludedNodeIds = new Set();
201
222
  for (const [nodeId, node] of Object.entries(nodes)) {
@@ -247,5 +268,6 @@ export function forkSceneGraph(sceneGraph) {
247
268
  nodes: filteredNodes,
248
269
  rootNodeIds: filteredRootNodeIds,
249
270
  ...(filteredCollections && { collections: filteredCollections }),
271
+ ...(installedPlugins && { installedPlugins }),
250
272
  });
251
273
  }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=clone-scene-graph.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clone-scene-graph.test.d.ts","sourceRoot":"","sources":["../../src/utils/clone-scene-graph.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,62 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import { forkSceneGraph } from './clone-scene-graph';
3
+ function makeNode(id, type, extra = {}) {
4
+ return {
5
+ object: 'node',
6
+ id,
7
+ type,
8
+ parentId: null,
9
+ visible: true,
10
+ metadata: {},
11
+ ...extra,
12
+ };
13
+ }
14
+ function makeSceneGraph() {
15
+ const site = makeNode('site_1', 'site', { children: ['level_1'] });
16
+ const level = makeNode('level_1', 'level', {
17
+ parentId: 'site_1',
18
+ children: ['wall_1', 'scan_1', 'guide_1'],
19
+ });
20
+ const wall = makeNode('wall_1', 'wall', { parentId: 'level_1' });
21
+ const scan = makeNode('scan_1', 'scan', { parentId: 'level_1', url: 'scan.glb' });
22
+ const guide = makeNode('guide_1', 'guide', { parentId: 'level_1', url: 'guide.png' });
23
+ return {
24
+ nodes: {
25
+ ['site_1']: site,
26
+ ['level_1']: level,
27
+ ['wall_1']: wall,
28
+ ['scan_1']: scan,
29
+ ['guide_1']: guide,
30
+ },
31
+ rootNodeIds: ['site_1'],
32
+ collections: {
33
+ ['collection_1']: {
34
+ id: 'collection_1',
35
+ name: 'References',
36
+ nodeIds: ['scan_1', 'guide_1'],
37
+ },
38
+ },
39
+ installedPlugins: ['pascal:trees'],
40
+ };
41
+ }
42
+ describe('forkSceneGraph', () => {
43
+ test('strips scan and guide nodes by default', () => {
44
+ const forked = forkSceneGraph(makeSceneGraph());
45
+ const nodes = Object.values(forked.nodes);
46
+ expect(nodes.some((node) => node.type === 'scan')).toBe(false);
47
+ expect(nodes.some((node) => node.type === 'guide')).toBe(false);
48
+ expect(nodes.some((node) => node.type === 'wall')).toBe(true);
49
+ expect(forked.collections).toEqual({});
50
+ expect(forked.installedPlugins).toEqual(['pascal:trees']);
51
+ });
52
+ test('preserves scan and guide nodes when requested', () => {
53
+ const forked = forkSceneGraph(makeSceneGraph(), { preserveScans: true });
54
+ const nodes = Object.values(forked.nodes);
55
+ expect(nodes.some((node) => node.type === 'scan')).toBe(true);
56
+ expect(nodes.some((node) => node.type === 'guide')).toBe(true);
57
+ expect(nodes.map((node) => node.id)).not.toContain('scan_1');
58
+ expect(nodes.map((node) => node.id)).not.toContain('guide_1');
59
+ expect(Object.values(forked.collections ?? {}).flatMap((collection) => collection.nodeIds)).toHaveLength(2);
60
+ expect(forked.installedPlugins).toEqual(['pascal:trees']);
61
+ });
62
+ });
@@ -0,0 +1,18 @@
1
+ export interface HealSceneResult {
2
+ nodes: Record<string, unknown>;
3
+ /** Ids of zero-length walls that were dropped. */
4
+ droppedWallIds: string[];
5
+ /** Count of non-string (e.g. null) entries removed from `children` arrays. */
6
+ strippedChildRefs: number;
7
+ /**
8
+ * Count of child references removed because the child's `parentId` points at
9
+ * a different node (stale reparent leftovers), plus same-array duplicates.
10
+ */
11
+ strippedStaleChildRefs: number;
12
+ }
13
+ /**
14
+ * Returns a healed copy of a `nodes` map. Pure — does not mutate `input`.
15
+ * Nodes that need no repair are passed through by reference.
16
+ */
17
+ export declare function healSceneNodes(input: Record<string, unknown>): HealSceneResult;
18
+ //# sourceMappingURL=heal-scene-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heal-scene-graph.d.ts","sourceRoot":"","sources":["../../src/utils/heal-scene-graph.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,kDAAkD;IAClD,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,8EAA8E;IAC9E,iBAAiB,EAAE,MAAM,CAAA;IACzB;;;OAGG;IACH,sBAAsB,EAAE,MAAM,CAAA;CAC/B;AAgBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,CA0D9E"}
@@ -0,0 +1,90 @@
1
+ // Repairs scene-graph corruption that pre-dates the source fixes, so existing
2
+ // saved scenes still load. Known kinds of damage:
3
+ //
4
+ // 1. A `children` array containing a non-string entry. The capture wall-merge
5
+ // re-attached a wall-hosted item without minting an id, so `undefined` was
6
+ // pushed into the wall's children — which serializes to `[null]`. The wall
7
+ // schema rejects `null` children, so the whole scene fails to load.
8
+ // 2. A zero-length wall (start === end). It renders nothing, but lingers as a
9
+ // junk node and is a foot-gun for snapping/mitering.
10
+ // 3. A child referenced by a parent it no longer belongs to: the child's
11
+ // `parentId` points at node B while node A's `children` still lists it
12
+ // (stale leftover from a reparent that didn't clean the old parent). The
13
+ // duplicate reference renders the child twice (duplicate React keys in the
14
+ // 2D plan, doubled hosted geometry in 3D). Same-array duplicates are
15
+ // collapsed too.
16
+ //
17
+ // All are also prevented at the source now; this is the load-time safety net
18
+ // for already-saved scenes.
19
+ const ZERO_LENGTH_EPS = 1e-6;
20
+ function isWallLike(node) {
21
+ if (!node || typeof node !== 'object')
22
+ return false;
23
+ const n = node;
24
+ return (n.type === 'wall' &&
25
+ Array.isArray(n.start) &&
26
+ Array.isArray(n.end) &&
27
+ typeof n.start[0] === 'number' &&
28
+ typeof n.start[1] === 'number' &&
29
+ typeof n.end[0] === 'number' &&
30
+ typeof n.end[1] === 'number');
31
+ }
32
+ /**
33
+ * Returns a healed copy of a `nodes` map. Pure — does not mutate `input`.
34
+ * Nodes that need no repair are passed through by reference.
35
+ */
36
+ export function healSceneNodes(input) {
37
+ const droppedWallIds = [];
38
+ // Pass 1: drop childless zero-length walls. (Only childless ones — a wall
39
+ // carrying a door/window must keep its hosts, degenerate or not.)
40
+ const kept = {};
41
+ for (const [id, node] of Object.entries(input)) {
42
+ if (isWallLike(node)) {
43
+ const children = node.children;
44
+ const childless = !Array.isArray(children) || children.length === 0;
45
+ const dx = node.end[0] - node.start[0];
46
+ const dz = node.end[1] - node.start[1];
47
+ if (childless && Math.hypot(dx, dz) <= ZERO_LENGTH_EPS) {
48
+ droppedWallIds.push(id);
49
+ continue;
50
+ }
51
+ }
52
+ kept[id] = node;
53
+ }
54
+ const dropped = new Set(droppedWallIds);
55
+ let strippedChildRefs = 0;
56
+ let strippedStaleChildRefs = 0;
57
+ // Pass 2: clean `children` arrays — drop non-string entries (the `[null]`
58
+ // bug), references to walls we just removed, same-array duplicates, and
59
+ // stale references whose child's `parentId` names a different parent.
60
+ const nodes = {};
61
+ for (const [id, node] of Object.entries(kept)) {
62
+ const children = node?.children;
63
+ if (Array.isArray(children)) {
64
+ const seen = new Set();
65
+ const cleaned = children.filter((c) => {
66
+ if (typeof c !== 'string' || dropped.has(c)) {
67
+ strippedChildRefs++;
68
+ return false;
69
+ }
70
+ if (seen.has(c)) {
71
+ strippedStaleChildRefs++;
72
+ return false;
73
+ }
74
+ seen.add(c);
75
+ const child = kept[c];
76
+ if (child && typeof child.parentId === 'string' && child.parentId !== id) {
77
+ strippedStaleChildRefs++;
78
+ return false;
79
+ }
80
+ return true;
81
+ });
82
+ if (cleaned.length !== children.length) {
83
+ nodes[id] = { ...node, children: cleaned };
84
+ continue;
85
+ }
86
+ }
87
+ nodes[id] = node;
88
+ }
89
+ return { nodes, droppedWallIds, strippedChildRefs, strippedStaleChildRefs };
90
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=heal-scene-graph.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heal-scene-graph.test.d.ts","sourceRoot":"","sources":["../../src/utils/heal-scene-graph.test.ts"],"names":[],"mappings":""}