@pascal-app/core 1.0.0-beta.5 → 1.0.1

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 (417) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +23 -0
  3. package/dist/capture/index.d.ts +3 -0
  4. package/dist/capture/index.d.ts.map +1 -0
  5. package/dist/capture/index.js +2 -0
  6. package/dist/capture/schema.d.ts +417 -0
  7. package/dist/capture/schema.d.ts.map +1 -0
  8. package/dist/capture/schema.js +350 -0
  9. package/dist/capture/source.d.ts +60 -0
  10. package/dist/capture/source.d.ts.map +1 -0
  11. package/dist/capture/source.js +254 -0
  12. package/dist/events/bus.d.ts +58 -7
  13. package/dist/events/bus.d.ts.map +1 -1
  14. package/dist/events/hidden-wall-pointer-hold.d.ts +28 -0
  15. package/dist/events/hidden-wall-pointer-hold.d.ts.map +1 -0
  16. package/dist/events/hidden-wall-pointer-hold.js +37 -0
  17. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +4 -4
  18. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -1
  19. package/dist/hooks/spatial-grid/floor-placed-elevation.js +7 -12
  20. package/dist/hooks/spatial-grid/floor-placed-footprints.d.ts +4 -0
  21. package/dist/hooks/spatial-grid/floor-placed-footprints.d.ts.map +1 -0
  22. package/dist/hooks/spatial-grid/floor-placed-footprints.js +7 -0
  23. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +5 -8
  24. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
  25. package/dist/hooks/spatial-grid/spatial-grid-manager.js +23 -106
  26. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +2931 -2
  27. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
  28. package/dist/hooks/spatial-grid/spatial-grid-sync.js +207 -30
  29. package/dist/hooks/spatial-grid/support-host-patch.d.ts +45 -1
  30. package/dist/hooks/spatial-grid/support-host-patch.d.ts.map +1 -1
  31. package/dist/hooks/spatial-grid/support-host-patch.js +174 -9
  32. package/dist/hooks/spatial-grid/use-spatial-query.d.ts +1 -1
  33. package/dist/hooks/spatial-grid/use-spatial-query.js +1 -1
  34. package/dist/index.d.ts +74 -64
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +74 -61
  37. package/dist/lib/asset-storage.d.ts.map +1 -1
  38. package/dist/lib/asset-storage.js +4 -1
  39. package/dist/lib/door-operation.d.ts +1 -1
  40. package/dist/lib/item-polygon-overlap.d.ts +6 -0
  41. package/dist/lib/item-polygon-overlap.d.ts.map +1 -0
  42. package/dist/lib/item-polygon-overlap.js +67 -0
  43. package/dist/lib/level-name.d.ts +1 -1
  44. package/dist/lib/measurement-geometry.d.ts +4 -4
  45. package/dist/lib/plan-footprint.d.ts +41 -0
  46. package/dist/lib/plan-footprint.d.ts.map +1 -0
  47. package/dist/lib/plan-footprint.js +58 -0
  48. package/dist/lib/polygon-union.d.ts +4 -0
  49. package/dist/lib/polygon-union.d.ts.map +1 -0
  50. package/dist/lib/polygon-union.js +306 -0
  51. package/dist/lib/roof-overlap.d.ts +32 -0
  52. package/dist/lib/roof-overlap.d.ts.map +1 -0
  53. package/dist/lib/roof-overlap.js +72 -0
  54. package/dist/lib/room-topology-index.d.ts +1 -1
  55. package/dist/lib/room-topology-index.js +1 -1
  56. package/dist/lib/selection-proxy.d.ts +1 -1
  57. package/dist/lib/slab-polygon.d.ts +36 -3
  58. package/dist/lib/slab-polygon.d.ts.map +1 -1
  59. package/dist/lib/slab-polygon.js +135 -29
  60. package/dist/lib/space-detection.d.ts +12 -1
  61. package/dist/lib/space-detection.d.ts.map +1 -1
  62. package/dist/lib/space-detection.js +58 -25
  63. package/dist/lib/terrain-brush.d.ts +1 -1
  64. package/dist/lib/terrain-brush.js +1 -1
  65. package/dist/lib/terrain-codec.d.ts +2 -2
  66. package/dist/lib/terrain-codec.js +1 -1
  67. package/dist/lib/terrain-raycast.d.ts +1 -1
  68. package/dist/lib/terrain-raycast.js +1 -1
  69. package/dist/lib/terrain-source.d.ts +3 -3
  70. package/dist/lib/terrain-source.js +3 -3
  71. package/dist/lib/terrain-support.d.ts +1 -1
  72. package/dist/lib/terrain-support.js +3 -3
  73. package/dist/lib/unit-containment.d.ts +19 -0
  74. package/dist/lib/unit-containment.d.ts.map +1 -0
  75. package/dist/lib/unit-containment.js +158 -0
  76. package/dist/lib/unit-report.d.ts +19 -0
  77. package/dist/lib/unit-report.d.ts.map +1 -0
  78. package/dist/lib/unit-report.js +36 -0
  79. package/dist/lib/wall-distance.d.ts +2 -2
  80. package/dist/lib/wall-distance.js +1 -1
  81. package/dist/lib/zone-quantities.d.ts +1 -1
  82. package/dist/lib/zone-quantities.js +7 -7
  83. package/dist/material-library.d.ts +1 -1
  84. package/dist/material-library.js +1 -1
  85. package/dist/procedural-items/fixtures.d.ts +261 -0
  86. package/dist/procedural-items/fixtures.d.ts.map +1 -0
  87. package/dist/procedural-items/fixtures.js +349 -0
  88. package/dist/procedural-items/index.d.ts +10 -0
  89. package/dist/procedural-items/index.d.ts.map +1 -0
  90. package/dist/procedural-items/index.js +9 -0
  91. package/dist/procedural-items/integration.d.ts +92 -0
  92. package/dist/procedural-items/integration.d.ts.map +1 -0
  93. package/dist/procedural-items/integration.js +19 -0
  94. package/dist/procedural-items/library-colors.d.ts +56 -0
  95. package/dist/procedural-items/library-colors.d.ts.map +1 -0
  96. package/dist/procedural-items/library-colors.js +84 -0
  97. package/dist/procedural-items/materials.d.ts +5 -0
  98. package/dist/procedural-items/materials.d.ts.map +1 -0
  99. package/dist/procedural-items/materials.js +47 -0
  100. package/dist/procedural-items/node.d.ts +280 -0
  101. package/dist/procedural-items/node.d.ts.map +1 -0
  102. package/dist/procedural-items/node.js +71 -0
  103. package/dist/procedural-items/placement.d.ts +7 -0
  104. package/dist/procedural-items/placement.d.ts.map +1 -0
  105. package/dist/procedural-items/placement.js +48 -0
  106. package/dist/procedural-items/query.d.ts +50 -0
  107. package/dist/procedural-items/query.d.ts.map +1 -0
  108. package/dist/procedural-items/query.js +298 -0
  109. package/dist/procedural-items/recipe.d.ts +144 -0
  110. package/dist/procedural-items/recipe.d.ts.map +1 -0
  111. package/dist/procedural-items/recipe.js +372 -0
  112. package/dist/procedural-items/spatial.d.ts +19 -0
  113. package/dist/procedural-items/spatial.d.ts.map +1 -0
  114. package/dist/procedural-items/spatial.js +39 -0
  115. package/dist/registry/__bench__/relations-resolver.bench.js +2 -2
  116. package/dist/registry/handles.d.ts +36 -7
  117. package/dist/registry/handles.d.ts.map +1 -1
  118. package/dist/registry/index.d.ts +6 -7
  119. package/dist/registry/index.d.ts.map +1 -1
  120. package/dist/registry/index.js +4 -5
  121. package/dist/registry/registry.d.ts +13 -6
  122. package/dist/registry/registry.d.ts.map +1 -1
  123. package/dist/registry/registry.js +37 -4
  124. package/dist/registry/relations-resolver.d.ts +2 -2
  125. package/dist/registry/relations-resolver.js +1 -1
  126. package/dist/registry/scene-api.d.ts +18 -2
  127. package/dist/registry/scene-api.d.ts.map +1 -1
  128. package/dist/registry/scene-api.js +50 -2
  129. package/dist/registry/subtree.d.ts +1 -1
  130. package/dist/registry/subtree.js +2 -2
  131. package/dist/registry/types.d.ts +246 -21
  132. package/dist/registry/types.d.ts.map +1 -1
  133. package/dist/registry/use-registry-version.js +1 -1
  134. package/dist/registry/validate-relations.d.ts +4 -0
  135. package/dist/registry/validate-relations.d.ts.map +1 -0
  136. package/dist/registry/validate-relations.js +22 -0
  137. package/dist/schema/__bench__/node-parsers.bench.d.ts +24 -0
  138. package/dist/schema/__bench__/node-parsers.bench.d.ts.map +1 -0
  139. package/dist/schema/__bench__/node-parsers.bench.js +314 -0
  140. package/dist/schema/__fixtures__/node-fixtures.d.ts +28 -0
  141. package/dist/schema/__fixtures__/node-fixtures.d.ts.map +1 -0
  142. package/dist/schema/__fixtures__/node-fixtures.js +127 -0
  143. package/dist/schema/base.d.ts +1 -1
  144. package/dist/schema/base.d.ts.map +1 -1
  145. package/dist/schema/base.js +9 -2
  146. package/dist/schema/collections.d.ts +1 -1
  147. package/dist/schema/collections.js +1 -1
  148. package/dist/schema/compiled-node-parsers.d.ts +40 -0
  149. package/dist/schema/compiled-node-parsers.d.ts.map +1 -0
  150. package/dist/schema/compiled-node-parsers.js +95 -0
  151. package/dist/schema/index.d.ts +73 -66
  152. package/dist/schema/index.d.ts.map +1 -1
  153. package/dist/schema/index.js +65 -57
  154. package/dist/schema/material.d.ts +1 -0
  155. package/dist/schema/material.d.ts.map +1 -1
  156. package/dist/schema/material.js +2 -1
  157. package/dist/schema/nodes/automatic-downspout.d.ts +17 -0
  158. package/dist/schema/nodes/automatic-downspout.d.ts.map +1 -0
  159. package/dist/schema/nodes/automatic-downspout.js +237 -0
  160. package/dist/schema/nodes/block.d.ts +107 -0
  161. package/dist/schema/nodes/block.d.ts.map +1 -0
  162. package/dist/schema/nodes/block.js +206 -0
  163. package/dist/schema/nodes/box-vent.d.ts +8 -2
  164. package/dist/schema/nodes/box-vent.d.ts.map +1 -1
  165. package/dist/schema/nodes/box-vent.js +4 -2
  166. package/dist/schema/nodes/building.d.ts +2 -2
  167. package/dist/schema/nodes/building.d.ts.map +1 -1
  168. package/dist/schema/nodes/building.js +8 -5
  169. package/dist/schema/nodes/cabinet.d.ts +26 -4
  170. package/dist/schema/nodes/cabinet.d.ts.map +1 -1
  171. package/dist/schema/nodes/cabinet.js +29 -8
  172. package/dist/schema/nodes/ceiling.d.ts +2 -2
  173. package/dist/schema/nodes/ceiling.js +5 -5
  174. package/dist/schema/nodes/chimney.d.ts +2 -2
  175. package/dist/schema/nodes/chimney.js +2 -2
  176. package/dist/schema/nodes/column.d.ts +7 -6
  177. package/dist/schema/nodes/column.d.ts.map +1 -1
  178. package/dist/schema/nodes/column.js +3 -2
  179. package/dist/schema/nodes/construction-dimension.d.ts +1 -1
  180. package/dist/schema/nodes/construction-dimension.js +2 -2
  181. package/dist/schema/nodes/cupola.d.ts +9 -1
  182. package/dist/schema/nodes/cupola.d.ts.map +1 -1
  183. package/dist/schema/nodes/cupola.js +4 -2
  184. package/dist/schema/nodes/door.d.ts +1 -1
  185. package/dist/schema/nodes/door.js +2 -2
  186. package/dist/schema/nodes/dormer.d.ts +45 -2
  187. package/dist/schema/nodes/dormer.d.ts.map +1 -1
  188. package/dist/schema/nodes/dormer.js +133 -9
  189. package/dist/schema/nodes/downspout.d.ts +11 -1
  190. package/dist/schema/nodes/downspout.d.ts.map +1 -1
  191. package/dist/schema/nodes/downspout.js +26 -2
  192. package/dist/schema/nodes/duct-fitting.d.ts +18 -1
  193. package/dist/schema/nodes/duct-fitting.d.ts.map +1 -1
  194. package/dist/schema/nodes/duct-fitting.js +26 -5
  195. package/dist/schema/nodes/duct-segment.d.ts +23 -1
  196. package/dist/schema/nodes/duct-segment.d.ts.map +1 -1
  197. package/dist/schema/nodes/duct-segment.js +21 -1
  198. package/dist/schema/nodes/duct-terminal.d.ts +1 -1
  199. package/dist/schema/nodes/duct-terminal.js +1 -1
  200. package/dist/schema/nodes/elevator.d.ts +1 -1
  201. package/dist/schema/nodes/elevator.js +2 -2
  202. package/dist/schema/nodes/eyebrow-vent.d.ts +8 -2
  203. package/dist/schema/nodes/eyebrow-vent.d.ts.map +1 -1
  204. package/dist/schema/nodes/eyebrow-vent.js +4 -2
  205. package/dist/schema/nodes/fence.d.ts +1 -1
  206. package/dist/schema/nodes/fence.js +2 -2
  207. package/dist/schema/nodes/guide.d.ts +1 -1
  208. package/dist/schema/nodes/guide.js +2 -2
  209. package/dist/schema/nodes/gutter.d.ts +36 -2
  210. package/dist/schema/nodes/gutter.d.ts.map +1 -1
  211. package/dist/schema/nodes/gutter.js +310 -3
  212. package/dist/schema/nodes/hanger-overrides.d.ts +7 -0
  213. package/dist/schema/nodes/hanger-overrides.d.ts.map +1 -0
  214. package/dist/schema/nodes/hanger-overrides.js +6 -0
  215. package/dist/schema/nodes/hvac-equipment.d.ts +1 -1
  216. package/dist/schema/nodes/hvac-equipment.js +1 -1
  217. package/dist/schema/nodes/imported-mesh.d.ts +40 -0
  218. package/dist/schema/nodes/imported-mesh.d.ts.map +1 -0
  219. package/dist/schema/nodes/imported-mesh.js +27 -0
  220. package/dist/schema/nodes/item.d.ts +3 -2
  221. package/dist/schema/nodes/item.d.ts.map +1 -1
  222. package/dist/schema/nodes/item.js +8 -3
  223. package/dist/schema/nodes/lean-to-extension.d.ts +212 -0
  224. package/dist/schema/nodes/lean-to-extension.d.ts.map +1 -0
  225. package/dist/schema/nodes/lean-to-extension.js +114 -0
  226. package/dist/schema/nodes/level.d.ts +2 -2
  227. package/dist/schema/nodes/level.d.ts.map +1 -1
  228. package/dist/schema/nodes/level.js +1 -1
  229. package/dist/schema/nodes/lineset.d.ts +1 -1
  230. package/dist/schema/nodes/lineset.js +1 -1
  231. package/dist/schema/nodes/liquid-line.d.ts +1 -1
  232. package/dist/schema/nodes/liquid-line.js +1 -1
  233. package/dist/schema/nodes/measurement.d.ts +1 -1
  234. package/dist/schema/nodes/measurement.js +2 -2
  235. package/dist/schema/nodes/pipe-fitting.d.ts +10 -2
  236. package/dist/schema/nodes/pipe-fitting.d.ts.map +1 -1
  237. package/dist/schema/nodes/pipe-fitting.js +7 -3
  238. package/dist/schema/nodes/pipe-segment.d.ts +24 -2
  239. package/dist/schema/nodes/pipe-segment.d.ts.map +1 -1
  240. package/dist/schema/nodes/pipe-segment.js +21 -1
  241. package/dist/schema/nodes/pipe-trap.d.ts +2 -2
  242. package/dist/schema/nodes/pipe-trap.js +1 -1
  243. package/dist/schema/nodes/ridge-vent.d.ts +2 -2
  244. package/dist/schema/nodes/ridge-vent.d.ts.map +1 -1
  245. package/dist/schema/nodes/ridge-vent.js +7 -4
  246. package/dist/schema/nodes/roof-segment-shape.d.ts +5 -1
  247. package/dist/schema/nodes/roof-segment-shape.d.ts.map +1 -1
  248. package/dist/schema/nodes/roof-segment-shape.js +65 -2
  249. package/dist/schema/nodes/roof-segment-walls.d.ts +4 -2
  250. package/dist/schema/nodes/roof-segment-walls.d.ts.map +1 -1
  251. package/dist/schema/nodes/roof-segment-walls.js +2 -2
  252. package/dist/schema/nodes/roof-segment.d.ts +42 -2
  253. package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
  254. package/dist/schema/nodes/roof-segment.js +81 -4
  255. package/dist/schema/nodes/roof.d.ts +23 -2
  256. package/dist/schema/nodes/roof.d.ts.map +1 -1
  257. package/dist/schema/nodes/roof.js +17 -3
  258. package/dist/schema/nodes/scan.d.ts +19 -2
  259. package/dist/schema/nodes/scan.d.ts.map +1 -1
  260. package/dist/schema/nodes/scan.js +13 -3
  261. package/dist/schema/nodes/shelf.d.ts +3 -3
  262. package/dist/schema/nodes/shelf.d.ts.map +1 -1
  263. package/dist/schema/nodes/shelf.js +3 -4
  264. package/dist/schema/nodes/site.d.ts +1 -1
  265. package/dist/schema/nodes/site.js +2 -2
  266. package/dist/schema/nodes/skylight.d.ts +5 -5
  267. package/dist/schema/nodes/skylight.js +2 -2
  268. package/dist/schema/nodes/slab.d.ts +1 -1
  269. package/dist/schema/nodes/slab.js +3 -3
  270. package/dist/schema/nodes/solar-panel.d.ts +1 -1
  271. package/dist/schema/nodes/solar-panel.js +3 -3
  272. package/dist/schema/nodes/spawn.d.ts +1 -1
  273. package/dist/schema/nodes/spawn.js +1 -1
  274. package/dist/schema/nodes/stair-segment.d.ts +1 -1
  275. package/dist/schema/nodes/stair-segment.js +2 -2
  276. package/dist/schema/nodes/stair.d.ts +2 -2
  277. package/dist/schema/nodes/stair.js +3 -3
  278. package/dist/schema/nodes/structural-grid.d.ts +1 -1
  279. package/dist/schema/nodes/structural-grid.js +1 -1
  280. package/dist/schema/nodes/turbine-vent.d.ts +8 -2
  281. package/dist/schema/nodes/turbine-vent.d.ts.map +1 -1
  282. package/dist/schema/nodes/turbine-vent.js +4 -2
  283. package/dist/schema/nodes/unit.d.ts +33 -0
  284. package/dist/schema/nodes/unit.d.ts.map +1 -0
  285. package/dist/schema/nodes/unit.js +13 -0
  286. package/dist/schema/nodes/wall.d.ts +5 -5
  287. package/dist/schema/nodes/wall.d.ts.map +1 -1
  288. package/dist/schema/nodes/wall.js +13 -6
  289. package/dist/schema/nodes/window.d.ts +10 -3
  290. package/dist/schema/nodes/window.d.ts.map +1 -1
  291. package/dist/schema/nodes/window.js +6 -2
  292. package/dist/schema/nodes/zone.d.ts +2 -2
  293. package/dist/schema/nodes/zone.js +2 -2
  294. package/dist/schema/scene-material.js +2 -2
  295. package/dist/schema/types.d.ts +815 -118
  296. package/dist/schema/types.d.ts.map +1 -1
  297. package/dist/schema/types.js +79 -46
  298. package/dist/services/alignment-anchors.d.ts +6 -11
  299. package/dist/services/alignment-anchors.d.ts.map +1 -1
  300. package/dist/services/alignment-anchors.js +7 -34
  301. package/dist/services/drag-session.d.ts +4 -4
  302. package/dist/services/drag-session.js +1 -1
  303. package/dist/services/hosting.d.ts +4 -10
  304. package/dist/services/hosting.d.ts.map +1 -1
  305. package/dist/services/hosting.js +6 -16
  306. package/dist/services/index.d.ts +16 -13
  307. package/dist/services/index.d.ts.map +1 -1
  308. package/dist/services/index.js +16 -13
  309. package/dist/services/level-height.d.ts +2 -2
  310. package/dist/services/level-height.js +3 -3
  311. package/dist/services/movement.d.ts +3 -3
  312. package/dist/services/movement.js +2 -2
  313. package/dist/services/port-connectivity.d.ts +1 -1
  314. package/dist/services/port-connectivity.js +1 -1
  315. package/dist/services/riser-diagram.d.ts +1 -1
  316. package/dist/services/shelf-board.d.ts +5 -0
  317. package/dist/services/shelf-board.d.ts.map +1 -0
  318. package/dist/services/shelf-board.js +15 -0
  319. package/dist/services/storey.d.ts +2 -2
  320. package/dist/services/storey.js +2 -2
  321. package/dist/services/surface-hosting-procedural-parity.fixtures.d.ts +13 -0
  322. package/dist/services/surface-hosting-procedural-parity.fixtures.d.ts.map +1 -0
  323. package/dist/services/surface-hosting-procedural-parity.fixtures.js +4691 -0
  324. package/dist/services/surface-hosting-shelf-parity.fixtures.d.ts +1060 -0
  325. package/dist/services/surface-hosting-shelf-parity.fixtures.d.ts.map +1 -0
  326. package/dist/services/surface-hosting-shelf-parity.fixtures.js +3127 -0
  327. package/dist/services/surface-hosting.d.ts +88 -0
  328. package/dist/services/surface-hosting.d.ts.map +1 -0
  329. package/dist/services/surface-hosting.js +268 -0
  330. package/dist/services/surface-region.d.ts +8 -0
  331. package/dist/services/surface-region.d.ts.map +1 -0
  332. package/dist/services/surface-region.js +44 -0
  333. package/dist/services/system-graph.d.ts +12 -1
  334. package/dist/services/system-graph.d.ts.map +1 -1
  335. package/dist/services/system-graph.js +36 -6
  336. package/dist/services/validate-dwv.d.ts +1 -1
  337. package/dist/services/validate-dwv.js +1 -1
  338. package/dist/store/actions/node-actions.d.ts +9 -2
  339. package/dist/store/actions/node-actions.d.ts.map +1 -1
  340. package/dist/store/actions/node-actions.js +475 -24
  341. package/dist/store/history-control.d.ts +3 -3
  342. package/dist/store/history-invalidation.d.ts +3 -0
  343. package/dist/store/history-invalidation.d.ts.map +1 -0
  344. package/dist/store/history-invalidation.js +72 -0
  345. package/dist/store/scene-hydration.d.ts +5 -0
  346. package/dist/store/scene-hydration.d.ts.map +1 -0
  347. package/dist/store/scene-hydration.js +57 -0
  348. package/dist/store/use-interactive.d.ts +2 -2
  349. package/dist/store/use-live-terrain.d.ts +1 -1
  350. package/dist/store/use-scene.d.ts +7 -4
  351. package/dist/store/use-scene.d.ts.map +1 -1
  352. package/dist/store/use-scene.js +361 -87
  353. package/dist/systems/elevator/elevator-dispatch.d.ts +2 -2
  354. package/dist/systems/elevator/elevator-dispatch.js +1 -1
  355. package/dist/systems/elevator/elevator-geometry.d.ts +1 -1
  356. package/dist/systems/elevator/elevator-opening-sync.d.ts +1 -1
  357. package/dist/systems/elevator/elevator-opening-sync.js +2 -2
  358. package/dist/systems/elevator/elevator-opening-system.js +3 -3
  359. package/dist/systems/elevator/elevator-runtime.d.ts +3 -3
  360. package/dist/systems/elevator/elevator-runtime.js +3 -3
  361. package/dist/systems/elevator/elevator-service.d.ts +1 -1
  362. package/dist/systems/elevator/elevator-service.js +1 -1
  363. package/dist/systems/fence/fence-centerline.d.ts +2 -2
  364. package/dist/systems/fence/fence-centerline.js +2 -2
  365. package/dist/systems/fence/fence-spline.d.ts +2 -2
  366. package/dist/systems/roof/roof-elevation-system.d.ts +3 -0
  367. package/dist/systems/roof/roof-elevation-system.d.ts.map +1 -0
  368. package/dist/systems/roof/roof-elevation-system.js +94 -0
  369. package/dist/systems/roof/roof-elevation.d.ts +4 -0
  370. package/dist/systems/roof/roof-elevation.d.ts.map +1 -0
  371. package/dist/systems/roof/roof-elevation.js +95 -0
  372. package/dist/systems/roof/roof-footprint.d.ts +17 -0
  373. package/dist/systems/roof/roof-footprint.d.ts.map +1 -0
  374. package/dist/systems/roof/roof-footprint.js +83 -0
  375. package/dist/systems/slab/slab-placement.d.ts +1 -1
  376. package/dist/systems/slab/slab-support.d.ts +1 -1
  377. package/dist/systems/slab/slab-support.js +4 -4
  378. package/dist/systems/stair/stair-flight.d.ts +17 -0
  379. package/dist/systems/stair/stair-flight.d.ts.map +1 -0
  380. package/dist/systems/stair/stair-flight.js +27 -0
  381. package/dist/systems/stair/stair-footprint.d.ts +1 -1
  382. package/dist/systems/stair/stair-opening-preview.d.ts +1621 -1267
  383. package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
  384. package/dist/systems/stair/stair-opening-preview.js +2 -2
  385. package/dist/systems/stair/stair-opening-sync.d.ts +1 -1
  386. package/dist/systems/stair/stair-opening-sync.js +6 -6
  387. package/dist/systems/stair/stair-opening-system.d.ts +1 -0
  388. package/dist/systems/stair/stair-opening-system.d.ts.map +1 -1
  389. package/dist/systems/stair/stair-opening-system.js +100 -103
  390. package/dist/systems/stair/stair-rise.d.ts +1 -1
  391. package/dist/systems/stair/stair-rise.d.ts.map +1 -1
  392. package/dist/systems/stair/stair-rise.js +23 -24
  393. package/dist/systems/wall/wall-curve.d.ts +3 -2
  394. package/dist/systems/wall/wall-curve.d.ts.map +1 -1
  395. package/dist/systems/wall/wall-curve.js +73 -0
  396. package/dist/systems/wall/wall-footprint.d.ts +3 -2
  397. package/dist/systems/wall/wall-footprint.d.ts.map +1 -1
  398. package/dist/systems/wall/wall-footprint.js +3 -2
  399. package/dist/systems/wall/wall-mitering.d.ts +1 -1
  400. package/dist/systems/wall/wall-mitering.js +1 -1
  401. package/dist/systems/wall/wall-move.d.ts +1 -1
  402. package/dist/systems/wall/wall-top.d.ts +1 -1
  403. package/dist/systems/wall/wall-topology.d.ts +2 -2
  404. package/dist/systems/wall/wall-topology.js +4 -4
  405. package/dist/utils/clone-scene-graph.d.ts +3 -3
  406. package/dist/utils/clone-scene-graph.d.ts.map +1 -1
  407. package/dist/utils/clone-scene-graph.js +35 -3
  408. package/dist/utils/scene-migrations.d.ts +3 -3
  409. package/dist/utils/scene-migrations.js +3 -3
  410. package/dist/utils/vertical-scene-migration.js +5 -5
  411. package/dist/validation/validate-build-json.d.ts +7 -1
  412. package/dist/validation/validate-build-json.d.ts.map +1 -1
  413. package/dist/validation/validate-build-json.js +92 -4
  414. package/package.json +23 -5
  415. package/dist/systems/elevator/elevator-runtime-system.d.ts +0 -2
  416. package/dist/systems/elevator/elevator-runtime-system.d.ts.map +0 -1
  417. package/dist/systems/elevator/elevator-runtime-system.js +0 -8
@@ -1,7 +1,7 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
- import { BaseNode, nodeType, objectId } from '../base';
4
- import { MaterialSchema } from '../material';
3
+ import { BaseNode, nodeType, objectId } from '../base.js';
4
+ import { MaterialSchema } from '../material.js';
5
5
  export const ColumnStyle = z.enum([
6
6
  'plain',
7
7
  'faceted',
@@ -62,6 +62,7 @@ export const ColumnSupportStyle = z.enum([
62
62
  export const ColumnNode = BaseNode.extend({
63
63
  id: objectId('column'),
64
64
  type: nodeType('column'),
65
+ children: z.array(z.string()).default([]),
65
66
  position: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
66
67
  rotation: z.number().default(0),
67
68
  // Persisted slab-support host — see ItemNode.supportSlabId for the rules.
@@ -86,7 +86,7 @@ export declare const ConstructionDimensionNode: z.ZodObject<{
86
86
  fov: z.ZodOptional<z.ZodNumber>;
87
87
  zoom: z.ZodOptional<z.ZodNumber>;
88
88
  }, z.core.$strip>>;
89
- metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
89
+ metadata: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
90
90
  id: z.ZodDefault<z.ZodTemplateLiteral<`construction-dimension_${string}`>>;
91
91
  type: z.ZodDefault<z.ZodLiteral<"construction-dimension">>;
92
92
  anchors: z.ZodDefault<z.ZodArray<z.ZodUnion<readonly [z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>, z.ZodObject<{
@@ -1,7 +1,7 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
- import { BaseNode, nodeType, objectId } from '../base';
4
- import { MeasurementAnchor } from './measurement';
3
+ import { BaseNode, nodeType, objectId } from '../base.js';
4
+ import { MeasurementAnchor } from './measurement.js';
5
5
  const FiniteCoordinate = z.number().finite();
6
6
  export const ConstructionDimensionBaseline = z
7
7
  .object({
@@ -1,4 +1,11 @@
1
1
  import { z } from 'zod';
2
+ export declare const CupolaMaterialRole: z.ZodEnum<{
3
+ roof: "roof";
4
+ body: "body";
5
+ base: "base";
6
+ louvers: "louvers";
7
+ }>;
8
+ export type CupolaMaterialRole = z.infer<typeof CupolaMaterialRole>;
2
9
  export declare const CupolaNode: z.ZodObject<{
3
10
  object: z.ZodDefault<z.ZodLiteral<"node">>;
4
11
  name: z.ZodOptional<z.ZodString>;
@@ -14,7 +21,7 @@ export declare const CupolaNode: z.ZodObject<{
14
21
  fov: z.ZodOptional<z.ZodNumber>;
15
22
  zoom: z.ZodOptional<z.ZodNumber>;
16
23
  }, z.core.$strip>>;
17
- metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
24
+ metadata: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
18
25
  id: z.ZodDefault<z.ZodTemplateLiteral<`cupola_${string}`>>;
19
26
  type: z.ZodDefault<z.ZodLiteral<"cupola">>;
20
27
  material: z.ZodOptional<z.ZodObject<{
@@ -49,6 +56,7 @@ export declare const CupolaNode: z.ZodObject<{
49
56
  scale: z.ZodOptional<z.ZodNumber>;
50
57
  }, z.core.$strip>>;
51
58
  }, z.core.$strip>>;
59
+ slots: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
52
60
  materialPreset: z.ZodDefault<z.ZodString>;
53
61
  roofSegmentId: z.ZodOptional<z.ZodString>;
54
62
  position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
@@ -1 +1 @@
1
- {"version":3,"file":"cupola.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/cupola.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6BtB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAA"}
1
+ {"version":3,"file":"cupola.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/cupola.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,kBAAkB;;;;;EAA8C,CAAA;AAC7E,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAEnE,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8BtB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAA"}
@@ -1,11 +1,13 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
- import { BaseNode, nodeType, objectId } from '../base';
4
- import { MaterialSchema } from '../material';
3
+ import { BaseNode, nodeType, objectId } from '../base.js';
4
+ import { MaterialSchema } from '../material.js';
5
+ export const CupolaMaterialRole = z.enum(['base', 'body', 'roof', 'louvers']);
5
6
  export const CupolaNode = BaseNode.extend({
6
7
  id: objectId('cupola'),
7
8
  type: nodeType('cupola'),
8
9
  material: MaterialSchema.optional(),
10
+ slots: z.record(z.string(), z.string()).optional(),
9
11
  // Default to the white preset so a freshly-placed cupola reads as clean
10
12
  // painted metal and the paint inspector shows "White" (matches box-vent).
11
13
  materialPreset: z.string().default('preset-white'),
@@ -64,7 +64,7 @@ export declare const DoorNode: z.ZodObject<{
64
64
  fov: z.ZodOptional<z.ZodNumber>;
65
65
  zoom: z.ZodOptional<z.ZodNumber>;
66
66
  }, z.core.$strip>>;
67
- metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
67
+ metadata: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
68
68
  id: z.ZodDefault<z.ZodTemplateLiteral<`door_${string}`>>;
69
69
  type: z.ZodDefault<z.ZodLiteral<"door">>;
70
70
  material: z.ZodOptional<z.ZodObject<{
@@ -1,7 +1,7 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
- import { BaseNode, nodeType, objectId } from '../base';
4
- import { MaterialSchema } from '../material';
3
+ import { BaseNode, nodeType, objectId } from '../base.js';
4
+ import { MaterialSchema } from '../material.js';
5
5
  export const DoorSegment = z.object({
6
6
  type: z.enum(['panel', 'glass', 'empty']),
7
7
  heightRatio: z.number(),
@@ -1,10 +1,24 @@
1
1
  import { z } from 'zod';
2
- import { MaterialSchema } from '../material';
2
+ import { MaterialSchema } from '../material.js';
3
+ import { type RoofSegmentNode } from './roof-segment.js';
4
+ import { WindowNode } from './window.js';
3
5
  export type DormerSurfaceMaterialRole = 'top' | 'side' | 'wall';
4
6
  export type DormerSurfaceMaterialSpec = {
5
7
  material?: z.infer<typeof MaterialSchema>;
6
8
  materialPreset?: string;
7
9
  };
10
+ export declare const DormerWallFace: z.ZodEnum<{
11
+ front: "front";
12
+ back: "back";
13
+ right: "right";
14
+ left: "left";
15
+ }>;
16
+ export type DormerWallFace = z.infer<typeof DormerWallFace>;
17
+ export type DormerWallFaceFrame = {
18
+ origin: [number, number, number];
19
+ yaw: number;
20
+ width: number;
21
+ };
8
22
  /**
9
23
  * Default dormer dimensions and window controls. Values match the
10
24
  * legacy archive so existing scenes don't shift visually.
@@ -44,7 +58,7 @@ export declare const DormerNode: z.ZodObject<{
44
58
  fov: z.ZodOptional<z.ZodNumber>;
45
59
  zoom: z.ZodOptional<z.ZodNumber>;
46
60
  }, z.core.$strip>>;
47
- metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
61
+ metadata: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
48
62
  id: z.ZodDefault<z.ZodTemplateLiteral<`dormer_${string}`>>;
49
63
  type: z.ZodDefault<z.ZodLiteral<"dormer">>;
50
64
  material: z.ZodOptional<z.ZodObject<{
@@ -193,8 +207,13 @@ export declare const DormerNode: z.ZodObject<{
193
207
  gambrel: "gambrel";
194
208
  dutch: "dutch";
195
209
  mansard: "mansard";
210
+ conical: "conical";
196
211
  }>>;
197
212
  roofHeight: z.ZodDefault<z.ZodNumber>;
213
+ shedHighSide: z.ZodDefault<z.ZodEnum<{
214
+ front: "front";
215
+ back: "back";
216
+ }>>;
198
217
  wallSkirtHeight: z.ZodDefault<z.ZodNumber>;
199
218
  windowWidth: z.ZodDefault<z.ZodNumber>;
200
219
  windowHeight: z.ZodDefault<z.ZodNumber>;
@@ -215,8 +234,31 @@ export declare const DormerNode: z.ZodObject<{
215
234
  windowSill: z.ZodDefault<z.ZodBoolean>;
216
235
  windowSillDepth: z.ZodDefault<z.ZodNumber>;
217
236
  windowSillThickness: z.ZodDefault<z.ZodNumber>;
237
+ children: z.ZodDefault<z.ZodArray<z.ZodDefault<z.ZodTemplateLiteral<`window_${string}`>>>>;
218
238
  }, z.core.$strip>;
219
239
  export type DormerNode = z.infer<typeof DormerNode>;
240
+ export declare function getDormerWallFaceFrame(dormer: Pick<DormerNode, 'width' | 'depth'>, face: DormerWallFace): DormerWallFaceFrame;
241
+ export declare function dormerWallFacePointToDormer(dormer: Pick<DormerNode, 'width' | 'depth'>, face: DormerWallFace, point: [number, number, number]): [number, number, number];
242
+ export declare function dormerPointToWallFace(dormer: Pick<DormerNode, 'width' | 'depth'>, face: DormerWallFace, point: [number, number, number]): [number, number, number];
243
+ export declare function getDormerWallVerticalBounds(dormer: Pick<DormerNode, 'height' | 'wallSkirtHeight'>): {
244
+ min: number;
245
+ max: number;
246
+ };
247
+ type DormerWallProfile = Pick<DormerNode, 'width' | 'depth' | 'height' | 'wallSkirtHeight' | 'roofType' | 'roofHeight' | 'shedHighSide'>;
248
+ export declare function getDormerWallOpeningVerticalBounds(dormer: DormerWallProfile, face: DormerWallFace, centerX: number, width: number): {
249
+ min: number;
250
+ max: number;
251
+ };
252
+ export declare function getDormerWallHorizontalBoundsAtHeight(dormer: DormerWallProfile, face: DormerWallFace, height: number): {
253
+ min: number;
254
+ max: number;
255
+ };
256
+ export declare function getDormerExposedFaces(dormer: Pick<DormerNode, 'depth' | 'position' | 'rotation' | 'wallSkirtHeight' | 'windowOffsetY'>, hostSegment: RoofSegmentNode): {
257
+ front: boolean;
258
+ back: boolean;
259
+ };
260
+ export declare function getDormerDefaultWindowFace(dormer: Pick<DormerNode, 'depth' | 'position' | 'rotation' | 'wallSkirtHeight' | 'windowOffsetY'>, hostSegment?: RoofSegmentNode): Extract<DormerWallFace, 'front' | 'back'>;
261
+ export declare function createDormerDefaultWindow(dormer: Pick<DormerNode, 'id' | 'width' | 'wallSkirtHeight' | 'windowWidth' | 'windowHeight' | 'windowOffsetX' | 'windowOffsetY' | 'windowFrameThickness' | 'windowFrameDepth' | 'windowColumns' | 'windowRows' | 'windowDividerThickness' | 'windowShape' | 'windowArchHeight' | 'windowCornerRadii' | 'windowSill' | 'windowSillDepth' | 'windowSillThickness'>, id: string, face?: Extract<DormerWallFace, 'front' | 'back'>): WindowNode;
220
262
  /**
221
263
  * Per-surface material resolution. Fall-through order:
222
264
  * top → topMaterial[Preset] → legacy
@@ -225,4 +267,5 @@ export type DormerNode = z.infer<typeof DormerNode>;
225
267
  * where legacy is `node.material` / `node.materialPreset`.
226
268
  */
227
269
  export declare function getEffectiveDormerSurfaceMaterial(node: DormerNode, role: DormerSurfaceMaterialRole): DormerSurfaceMaterialSpec;
270
+ export {};
228
271
  //# sourceMappingURL=dormer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dormer.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/dormer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAG5C,MAAM,MAAM,yBAAyB,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAA;AAC/D,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA;IACzC,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;CAmBlB,CAAA;AASV,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4DtB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAA;AAEnD;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,yBAAyB,GAC9B,yBAAyB,CAuB3B"}
1
+ {"version":3,"file":"dormer.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/dormer.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,10 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
- import { BaseNode, nodeType, objectId } from '../base';
4
- import { MaterialSchema } from '../material';
5
- import { RoofType } from './roof-segment';
3
+ import { BaseNode, nodeType, objectId } from '../base.js';
4
+ import { MaterialSchema } from '../material.js';
5
+ import { getRoofSegmentSurfaceY, RoofType } from './roof-segment.js';
6
+ import { WindowNode } from './window.js';
7
+ export const DormerWallFace = z.enum(['front', 'back', 'right', 'left']);
6
8
  /**
7
9
  * Default dormer dimensions and window controls. Values match the
8
10
  * legacy archive so existing scenes don't shift visually.
@@ -52,13 +54,13 @@ export const DormerNode = BaseNode.extend({
52
54
  height: z.number().default(DORMER_DEFAULTS.WALL_HEIGHT),
53
55
  roofType: RoofType.default('gable'),
54
56
  roofHeight: z.number().default(DORMER_DEFAULTS.ROOF_HEIGHT),
57
+ shedHighSide: z.enum(['back', 'front']).default('back'),
55
58
  // Height of the hung wall (the "skirt") that extends below the eave
56
59
  // into the host roof — this is the wall area the window opening is
57
60
  // cut through. Larger values let the dormer host taller windows.
58
61
  wallSkirtHeight: z.number().default(DORMER_DEFAULTS.WALL_SKIRT_HEIGHT),
59
- // Window is rendered as parametric geometry on the dormer's front
60
- // face — not a child node. The fields below mirror the legacy panel
61
- // controls; geometry beyond the simple opening box is deferred.
62
+ // Legacy inline-window controls. Existing scenes are promoted to a hosted
63
+ // WindowNode during scene migration; these fields remain for archive data.
62
64
  windowWidth: z.number().default(DORMER_DEFAULTS.WINDOW_WIDTH),
63
65
  windowHeight: z.number().default(DORMER_DEFAULTS.WINDOW_HEIGHT),
64
66
  windowOffsetX: z.number().default(DORMER_DEFAULTS.WINDOW_OFFSET_X),
@@ -79,13 +81,135 @@ export const DormerNode = BaseNode.extend({
79
81
  windowSill: z.boolean().default(false),
80
82
  windowSillDepth: z.number().default(DORMER_DEFAULTS.WINDOW_SILL_DEPTH),
81
83
  windowSillThickness: z.number().default(DORMER_DEFAULTS.WINDOW_SILL_THICKNESS),
84
+ // Hosted windows use the same recursive scene-graph contract as walls and
85
+ // roof segments. Legacy window* fields above are retained for migration.
86
+ children: z.array(WindowNode.shape.id).default([]),
82
87
  }).describe(dedent `
83
88
  Dormer — a small house-shaped protrusion sitting on top of a roof
84
89
  segment. width × depth × height defines the box base; roofType and
85
- roofHeight define the dormer's own roof shape. The window opening
86
- is parametric geometry on the dormer's front face, not a hosted
87
- child node.
90
+ roofHeight define the dormer's own roof shape. shedHighSide controls
91
+ the pitch direction for shed roofs. WindowNode children are hosted on
92
+ its wall faces and use the regular window item model.
88
93
  `);
94
+ export function getDormerWallFaceFrame(dormer, face) {
95
+ switch (face) {
96
+ case 'back':
97
+ return { origin: [0, 0, -dormer.depth / 2], yaw: Math.PI, width: dormer.width };
98
+ case 'right':
99
+ return { origin: [dormer.width / 2, 0, 0], yaw: Math.PI / 2, width: dormer.depth };
100
+ case 'left':
101
+ return { origin: [-dormer.width / 2, 0, 0], yaw: -Math.PI / 2, width: dormer.depth };
102
+ default:
103
+ return { origin: [0, 0, dormer.depth / 2], yaw: 0, width: dormer.width };
104
+ }
105
+ }
106
+ export function dormerWallFacePointToDormer(dormer, face, point) {
107
+ const frame = getDormerWallFaceFrame(dormer, face);
108
+ const cos = Math.cos(frame.yaw);
109
+ const sin = Math.sin(frame.yaw);
110
+ const [x, y, z] = point;
111
+ return [
112
+ frame.origin[0] + x * cos + z * sin,
113
+ frame.origin[1] + y,
114
+ frame.origin[2] - x * sin + z * cos,
115
+ ];
116
+ }
117
+ export function dormerPointToWallFace(dormer, face, point) {
118
+ const frame = getDormerWallFaceFrame(dormer, face);
119
+ const cos = Math.cos(frame.yaw);
120
+ const sin = Math.sin(frame.yaw);
121
+ const dx = point[0] - frame.origin[0];
122
+ const dz = point[2] - frame.origin[2];
123
+ return [cos * dx - sin * dz, point[1] - frame.origin[1], sin * dx + cos * dz];
124
+ }
125
+ export function getDormerWallVerticalBounds(dormer) {
126
+ return {
127
+ min: -(dormer.wallSkirtHeight ?? DORMER_DEFAULTS.WALL_SKIRT_HEIGHT),
128
+ max: Math.max(0, dormer.height),
129
+ };
130
+ }
131
+ function getDormerWallCeilingAt(dormer, face, faceX) {
132
+ const eaveHeight = Math.max(0, dormer.height);
133
+ if (dormer.roofType !== 'shed')
134
+ return eaveHeight;
135
+ const depth = Math.max(dormer.depth, Number.EPSILON);
136
+ const [, , dormerZ] = dormerWallFacePointToDormer(dormer, face, [faceX, 0, 0]);
137
+ const frontWeight = Math.max(0, Math.min(1, dormerZ / depth + 0.5));
138
+ const highSideWeight = dormer.shedHighSide === 'front' ? frontWeight : 1 - frontWeight;
139
+ return eaveHeight + Math.max(0, dormer.roofHeight) * highSideWeight;
140
+ }
141
+ export function getDormerWallOpeningVerticalBounds(dormer, face, centerX, width) {
142
+ const halfWidth = width / 2;
143
+ return {
144
+ min: -(dormer.wallSkirtHeight ?? DORMER_DEFAULTS.WALL_SKIRT_HEIGHT),
145
+ max: Math.min(getDormerWallCeilingAt(dormer, face, centerX - halfWidth), getDormerWallCeilingAt(dormer, face, centerX + halfWidth)),
146
+ };
147
+ }
148
+ export function getDormerWallHorizontalBoundsAtHeight(dormer, face, height) {
149
+ const halfWidth = getDormerWallFaceFrame(dormer, face).width / 2;
150
+ const leftCeiling = getDormerWallCeilingAt(dormer, face, -halfWidth);
151
+ const rightCeiling = getDormerWallCeilingAt(dormer, face, halfWidth);
152
+ if (height <= Math.min(leftCeiling, rightCeiling)) {
153
+ return { min: -halfWidth, max: halfWidth };
154
+ }
155
+ if (leftCeiling === rightCeiling) {
156
+ return { min: -halfWidth, max: halfWidth };
157
+ }
158
+ const crossing = -halfWidth + ((height - leftCeiling) / (rightCeiling - leftCeiling)) * (halfWidth * 2);
159
+ if (rightCeiling > leftCeiling) {
160
+ const min = Math.min(halfWidth, crossing);
161
+ return { min, max: halfWidth };
162
+ }
163
+ const max = Math.max(-halfWidth, crossing);
164
+ return { min: -halfWidth, max };
165
+ }
166
+ const DORMER_WINDOW_CENTER_MIN_CLEARANCE = 0.01;
167
+ export function getDormerExposedFaces(dormer, hostSegment) {
168
+ const halfDepth = dormer.depth / 2;
169
+ const [dormerX, dormerY, dormerZ] = dormer.position;
170
+ const faceDX = halfDepth * Math.sin(dormer.rotation);
171
+ const faceDZ = halfDepth * Math.cos(dormer.rotation);
172
+ const windowCenterY = dormerY - dormer.wallSkirtHeight / 2 + dormer.windowOffsetY;
173
+ const clears = (faceX, faceZ) => windowCenterY - getRoofSegmentSurfaceY(hostSegment, faceX, faceZ) >
174
+ DORMER_WINDOW_CENTER_MIN_CLEARANCE;
175
+ return {
176
+ front: clears(dormerX + faceDX, dormerZ + faceDZ),
177
+ back: clears(dormerX - faceDX, dormerZ - faceDZ),
178
+ };
179
+ }
180
+ export function getDormerDefaultWindowFace(dormer, hostSegment) {
181
+ if (!hostSegment)
182
+ return 'front';
183
+ const exposed = getDormerExposedFaces(dormer, hostSegment);
184
+ return !exposed.front && exposed.back ? 'back' : 'front';
185
+ }
186
+ export function createDormerDefaultWindow(dormer, id, face = 'front') {
187
+ const skirt = dormer.wallSkirtHeight ?? DORMER_DEFAULTS.WALL_SKIRT_HEIGHT;
188
+ const equalRatios = (count) => Array.from({ length: Math.max(1, count) }, () => 1);
189
+ return WindowNode.parse({
190
+ id,
191
+ parentId: dormer.id,
192
+ dormerId: dormer.id,
193
+ dormerFace: face,
194
+ position: [dormer.windowOffsetX, -skirt / 2 + dormer.windowOffsetY, 0],
195
+ rotation: [0, 0, 0],
196
+ side: 'front',
197
+ width: dormer.windowWidth,
198
+ height: dormer.windowHeight,
199
+ openingShape: dormer.windowShape,
200
+ archHeight: dormer.windowArchHeight,
201
+ openingCornerRadii: dormer.windowCornerRadii,
202
+ frameThickness: dormer.windowFrameThickness,
203
+ frameDepth: dormer.windowFrameDepth,
204
+ columnRatios: equalRatios(dormer.windowColumns),
205
+ rowRatios: equalRatios(dormer.windowRows),
206
+ columnDividerThickness: dormer.windowDividerThickness,
207
+ rowDividerThickness: dormer.windowDividerThickness,
208
+ sill: dormer.windowSill,
209
+ sillDepth: dormer.windowSillDepth,
210
+ sillThickness: dormer.windowSillThickness,
211
+ });
212
+ }
89
213
  /**
90
214
  * Per-surface material resolution. Fall-through order:
91
215
  * top → topMaterial[Preset] → legacy
@@ -14,7 +14,7 @@ export declare const DownspoutNode: z.ZodObject<{
14
14
  fov: z.ZodOptional<z.ZodNumber>;
15
15
  zoom: z.ZodOptional<z.ZodNumber>;
16
16
  }, z.core.$strip>>;
17
- metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
17
+ metadata: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
18
18
  id: z.ZodDefault<z.ZodTemplateLiteral<`downspout_${string}`>>;
19
19
  type: z.ZodDefault<z.ZodLiteral<"downspout">>;
20
20
  material: z.ZodOptional<z.ZodObject<{
@@ -49,10 +49,15 @@ export declare const DownspoutNode: z.ZodObject<{
49
49
  scale: z.ZodOptional<z.ZodNumber>;
50
50
  }, z.core.$strip>>;
51
51
  }, z.core.$strip>>;
52
+ slots: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
52
53
  materialPreset: z.ZodDefault<z.ZodString>;
53
54
  gutterId: z.ZodOptional<z.ZodString>;
54
55
  outletId: z.ZodOptional<z.ZodString>;
55
56
  length: z.ZodDefault<z.ZodNumber>;
57
+ lengthMode: z.ZodOptional<z.ZodEnum<{
58
+ manual: "manual";
59
+ "to-ground": "to-ground";
60
+ }>>;
56
61
  diameter: z.ZodDefault<z.ZodNumber>;
57
62
  standoff: z.ZodDefault<z.ZodNumber>;
58
63
  shape: z.ZodDefault<z.ZodEnum<{
@@ -72,4 +77,9 @@ export declare const DownspoutNode: z.ZodObject<{
72
77
  }>>;
73
78
  }, z.core.$strip>;
74
79
  export type DownspoutNode = z.infer<typeof DownspoutNode>;
80
+ export declare function defaultDownspoutMetadata(): {
81
+ generatedBy: string;
82
+ };
83
+ export declare function isDefaultDownspoutNode(node: unknown, gutterId?: string): node is DownspoutNode;
84
+ export declare function usesAutomaticDownspoutLength(node: DownspoutNode): boolean;
75
85
  //# sourceMappingURL=downspout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"downspout.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/downspout.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkEzB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA"}
1
+ {"version":3,"file":"downspout.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/downspout.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAMvB,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoEzB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA;AASzD,wBAAgB,wBAAwB;;EAEvC;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,IAAI,aAAa,CAK9F;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAKzE"}
@@ -1,11 +1,13 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
- import { BaseNode, nodeType, objectId } from '../base';
4
- import { MaterialSchema } from '../material';
3
+ import { BaseNode, nodeType, objectId } from '../base.js';
4
+ import { MaterialSchema } from '../material.js';
5
+ const DEFAULT_DOWNSPOUT_GENERATOR = 'default-downspout';
5
6
  export const DownspoutNode = BaseNode.extend({
6
7
  id: objectId('downspout'),
7
8
  type: nodeType('downspout'),
8
9
  material: MaterialSchema.optional(),
10
+ slots: z.record(z.string(), z.string()).optional(),
9
11
  // Match the gutter family default — paint inspector reads "White"
10
12
  // instead of "no material" on a freshly placed downspout.
11
13
  materialPreset: z.string().default('preset-white'),
@@ -26,6 +28,7 @@ export const DownspoutNode = BaseNode.extend({
26
28
  // tool can default to the gutter's eave-Y minus building floor on
27
29
  // commit so the user doesn't have to set it on every drop.
28
30
  length: z.number().default(2.5),
31
+ lengthMode: z.enum(['to-ground', 'manual']).optional(),
29
32
  // Bore diameter, default 0.07 m ≈ 3″ to match the gutter outlet
30
33
  // default. Larger downspouts are common on commercial gutters.
31
34
  diameter: z.number().default(0.07),
@@ -61,3 +64,24 @@ export const DownspoutNode = BaseNode.extend({
61
64
  - strapStyle / strapSpacing: wall straps clamping the run
62
65
  - terminal: bottom treatment (splash block, kickout only, or straight down)
63
66
  `);
67
+ function metadataRecord(metadata) {
68
+ if (typeof metadata === 'object' && metadata !== null && !Array.isArray(metadata)) {
69
+ return metadata;
70
+ }
71
+ return {};
72
+ }
73
+ export function defaultDownspoutMetadata() {
74
+ return { generatedBy: DEFAULT_DOWNSPOUT_GENERATOR };
75
+ }
76
+ export function isDefaultDownspoutNode(node, gutterId) {
77
+ const parsed = DownspoutNode.safeParse(node);
78
+ if (!parsed.success)
79
+ return false;
80
+ if (gutterId && parsed.data.gutterId !== gutterId)
81
+ return false;
82
+ return metadataRecord(parsed.data.metadata).generatedBy === DEFAULT_DOWNSPOUT_GENERATOR;
83
+ }
84
+ export function usesAutomaticDownspoutLength(node) {
85
+ return (node.lengthMode === 'to-ground' ||
86
+ (node.lengthMode === undefined && isDefaultDownspoutNode(node)));
87
+ }
@@ -45,7 +45,7 @@ export declare const DuctFittingNode: z.ZodObject<{
45
45
  fov: z.ZodOptional<z.ZodNumber>;
46
46
  zoom: z.ZodOptional<z.ZodNumber>;
47
47
  }, z.core.$strip>>;
48
- metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
48
+ metadata: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
49
49
  id: z.ZodDefault<z.ZodTemplateLiteral<`duct-fitting_${string}`>>;
50
50
  type: z.ZodDefault<z.ZodLiteral<"duct-fitting">>;
51
51
  position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
@@ -56,12 +56,26 @@ export declare const DuctFittingNode: z.ZodObject<{
56
56
  cross: "cross";
57
57
  reducer: "reducer";
58
58
  transition: "transition";
59
+ "end-cap": "end-cap";
60
+ damper: "damper";
61
+ "access-panel": "access-panel";
62
+ coupling: "coupling";
59
63
  }>>;
60
64
  shape: z.ZodDefault<z.ZodEnum<{
61
65
  round: "round";
62
66
  rect: "rect";
63
67
  oval: "oval";
64
68
  }>>;
69
+ inletShape: z.ZodOptional<z.ZodEnum<{
70
+ round: "round";
71
+ rect: "rect";
72
+ oval: "oval";
73
+ }>>;
74
+ outletShape: z.ZodOptional<z.ZodEnum<{
75
+ round: "round";
76
+ rect: "rect";
77
+ oval: "oval";
78
+ }>>;
65
79
  width: z.ZodDefault<z.ZodNumber>;
66
80
  height: z.ZodDefault<z.ZodNumber>;
67
81
  shape2: z.ZodDefault<z.ZodEnum<{
@@ -84,6 +98,9 @@ export declare const DuctFittingNode: z.ZodObject<{
84
98
  supply: "supply";
85
99
  return: "return";
86
100
  }>>;
101
+ damperAngle: z.ZodDefault<z.ZodNumber>;
102
+ panelWidth: z.ZodDefault<z.ZodNumber>;
103
+ panelHeight: z.ZodDefault<z.ZodNumber>;
87
104
  slots: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
88
105
  }, z.core.$strip>;
89
106
  export type DuctFittingNode = z.infer<typeof DuctFittingNode>;
@@ -1 +1 @@
1
- {"version":3,"file":"duct-fitting.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/duct-fitting.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2D3B,CAAA;AACD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAC7D,MAAM,MAAM,iBAAiB,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA"}
1
+ {"version":3,"file":"duct-fitting.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/duct-fitting.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgF3B,CAAA;AACD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAC7D,MAAM,MAAM,iBAAiB,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA"}
@@ -1,6 +1,6 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
- import { BaseNode, nodeType, objectId } from '../base';
3
+ import { BaseNode, nodeType, objectId } from '../base.js';
4
4
  /**
5
5
  * Duct fitting — the junction pieces that connect round duct segments:
6
6
  * elbows (direction change), tees (branch takeoff), reducers (diameter
@@ -39,12 +39,27 @@ export const DuctFittingNode = BaseNode.extend({
39
39
  position: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
40
40
  // XYZ euler radians.
41
41
  rotation: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
42
- fittingType: z.enum(['elbow', 'tee', 'cross', 'reducer', 'transition']).default('elbow'),
42
+ fittingType: z
43
+ .enum([
44
+ 'elbow',
45
+ 'tee',
46
+ 'cross',
47
+ 'reducer',
48
+ 'transition',
49
+ 'end-cap',
50
+ 'damper',
51
+ 'access-panel',
52
+ 'coupling',
53
+ ])
54
+ .default('elbow'),
43
55
  // Run-leg cross-section: round collars, or a rect / flat-oval profile
44
56
  // matching the trunk the fitting sits in. Reducers ignore the shape.
45
57
  // When non-round, `diameter` carries the area-equivalent round size
46
58
  // (drives leg lengths + advertised ports).
47
59
  shape: z.enum(['round', 'rect', 'oval']).default('rect'),
60
+ // Adapter end profiles; omitted values use the fitting type's standard profiles.
61
+ inletShape: z.enum(['round', 'rect', 'oval']).optional(),
62
+ outletShape: z.enum(['round', 'rect', 'oval']).optional(),
48
63
  // Rect / oval run-leg profile in inches (used when shape ≠ 'round').
49
64
  width: z.number().min(4).max(60).default(14),
50
65
  height: z.number().min(3).max(40).default(8),
@@ -73,16 +88,22 @@ export const DuctFittingNode = BaseNode.extend({
73
88
  diameter2: z.number().min(2).max(48).default(6),
74
89
  ductMaterial: z.enum(['sheet-metal', 'flex', 'duct-board']).default('sheet-metal'),
75
90
  system: z.enum(['supply', 'return']).default('supply'),
91
+ damperAngle: z.number().finite().min(0).max(90).default(0),
92
+ panelWidth: z.number().finite().min(0.1).max(1.2).default(0.25),
93
+ panelHeight: z.number().finite().min(0.1).max(1.2).default(0.15),
76
94
  slots: z.record(z.string(), z.string()).optional(),
77
95
  }).describe(dedent `
78
96
  Duct fitting - elbow, tee, cross, reducer, or square-to-round transition between duct runs.
79
97
  - position: [x, y, z] level-local meters
80
98
  - rotation: [x, y, z] euler radians
81
- - fittingType: elbow | tee | cross | reducer | transition (rect end -X, round end +X)
82
- - shape: round | rect | oval run legs (matches the trunk; ignored by reducer / transition)
99
+ - fittingType: elbow | tee | cross | reducer | transition | end-cap | damper | access-panel | coupling
100
+ - damperAngle: blade opening in degrees, 0 closed, 90 open
101
+ - panelWidth / panelHeight: access door dimensions in meters; door lies in local XY with outward normal +Z; no flow ports
102
+ - inletShape / outletShape: round | rect | oval adapter end profiles; defaults are round-to-round for reducer and rect-to-round for transition
103
+ - shape: round | rect | oval run legs (matches the trunk)
83
104
  - width / height: rect / oval run-leg profile in inches (transition: the rect end)
84
105
  - shape2: round | rect | oval tee / cross branch (matches the duct drawn off the tap)
85
- - width2 / height2: rect / oval branch profile in inches
106
+ - width2 / height2: rect / oval branch or adapter outlet profile in inches
86
107
  - angle: elbow turn in degrees (45 or 90 typical)
87
108
  - branchAngle: tee branch angle off the outlet axis (90 straight tee, 45 downstream lateral, 135 upstream); cross branches are always square
88
109
  - diameter: main nominal diameter in inches
@@ -28,10 +28,32 @@ export declare const DuctSegmentNode: z.ZodObject<{
28
28
  fov: z.ZodOptional<z.ZodNumber>;
29
29
  zoom: z.ZodOptional<z.ZodNumber>;
30
30
  }, z.core.$strip>>;
31
- metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
31
+ metadata: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
32
32
  id: z.ZodDefault<z.ZodTemplateLiteral<`duct-segment_${string}`>>;
33
33
  type: z.ZodDefault<z.ZodLiteral<"duct-segment">>;
34
34
  path: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
35
+ autoHangers: z.ZodOptional<z.ZodBoolean>;
36
+ hangerOverrides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
37
+ fraction: z.ZodOptional<z.ZodNumber>;
38
+ skipped: z.ZodOptional<z.ZodBoolean>;
39
+ hostId: z.ZodOptional<z.ZodString>;
40
+ }, z.core.$strip>>>;
41
+ hangerStyle: z.ZodOptional<z.ZodEnum<{
42
+ double: "double";
43
+ single: "single";
44
+ }>>;
45
+ hangerSpacing: z.ZodOptional<z.ZodNumber>;
46
+ hangerMaxReach: z.ZodOptional<z.ZodNumber>;
47
+ wallAttachment: z.ZodOptional<z.ZodObject<{
48
+ wallId: z.ZodDefault<z.ZodTemplateLiteral<`wall_${string}`>>;
49
+ side: z.ZodEnum<{
50
+ front: "front";
51
+ back: "back";
52
+ }>;
53
+ startUV: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
54
+ endUV: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
55
+ offset: z.ZodNumber;
56
+ }, z.core.$strip>>;
35
57
  shape: z.ZodDefault<z.ZodEnum<{
36
58
  round: "round";
37
59
  rect: "rect";
@@ -1 +1 @@
1
- {"version":3,"file":"duct-segment.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/duct-segment.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyD3B,CAAA;AACD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAC7D,MAAM,MAAM,iBAAiB,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA"}
1
+ {"version":3,"file":"duct-segment.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/duct-segment.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4E3B,CAAA;AACD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAC7D,MAAM,MAAM,iBAAiB,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA"}