@pascal-app/core 0.9.1 → 1.0.0-beta.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 (378) hide show
  1. package/README.md +17 -10
  2. package/dist/events/bus.d.ts +49 -2
  3. package/dist/events/bus.d.ts.map +1 -1
  4. package/dist/hooks/scene-registry/item-clip-registry.d.ts +18 -0
  5. package/dist/hooks/scene-registry/item-clip-registry.d.ts.map +1 -0
  6. package/dist/hooks/scene-registry/item-clip-registry.js +10 -0
  7. package/dist/hooks/scene-registry/scene-registry.d.ts +8 -1
  8. package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
  9. package/dist/hooks/scene-registry/scene-registry.js +27 -1
  10. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +17 -1
  11. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -1
  12. package/dist/hooks/spatial-grid/floor-placed-elevation.js +61 -8
  13. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +135 -28
  14. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
  15. package/dist/hooks/spatial-grid/spatial-grid-manager.js +427 -271
  16. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +46 -1
  17. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
  18. package/dist/hooks/spatial-grid/spatial-grid-sync.js +208 -9
  19. package/dist/hooks/spatial-grid/support-host-id.d.ts +3 -0
  20. package/dist/hooks/spatial-grid/support-host-id.d.ts.map +1 -0
  21. package/dist/hooks/spatial-grid/support-host-id.js +2 -0
  22. package/dist/hooks/spatial-grid/support-host-patch.d.ts +51 -0
  23. package/dist/hooks/spatial-grid/support-host-patch.d.ts.map +1 -0
  24. package/dist/hooks/spatial-grid/support-host-patch.js +164 -0
  25. package/dist/index.d.ts +33 -11
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +32 -10
  28. package/dist/lib/level-name.d.ts +4 -0
  29. package/dist/lib/level-name.d.ts.map +1 -0
  30. package/dist/lib/level-name.js +10 -0
  31. package/dist/lib/measurement-geometry.d.ts +23 -0
  32. package/dist/lib/measurement-geometry.d.ts.map +1 -0
  33. package/dist/lib/measurement-geometry.js +249 -0
  34. package/dist/lib/polygon-geometry.d.ts +0 -1
  35. package/dist/lib/polygon-geometry.d.ts.map +1 -1
  36. package/dist/lib/polygon-geometry.js +0 -18
  37. package/dist/lib/selection-proxy.d.ts +4 -0
  38. package/dist/lib/selection-proxy.d.ts.map +1 -0
  39. package/dist/lib/selection-proxy.js +12 -0
  40. package/dist/lib/slab-polygon.d.ts +31 -2
  41. package/dist/lib/slab-polygon.d.ts.map +1 -1
  42. package/dist/lib/slab-polygon.js +557 -31
  43. package/dist/lib/slots.d.ts +14 -0
  44. package/dist/lib/slots.d.ts.map +1 -0
  45. package/dist/lib/slots.js +26 -0
  46. package/dist/lib/space-detection.d.ts +40 -6
  47. package/dist/lib/space-detection.d.ts.map +1 -1
  48. package/dist/lib/space-detection.js +574 -192
  49. package/dist/lib/terrain-brush.d.ts +163 -0
  50. package/dist/lib/terrain-brush.d.ts.map +1 -0
  51. package/dist/lib/terrain-brush.js +359 -0
  52. package/dist/lib/terrain-codec.d.ts +51 -0
  53. package/dist/lib/terrain-codec.d.ts.map +1 -0
  54. package/dist/lib/terrain-codec.js +167 -0
  55. package/dist/lib/terrain-field.d.ts +150 -0
  56. package/dist/lib/terrain-field.d.ts.map +1 -0
  57. package/dist/lib/terrain-field.js +248 -0
  58. package/dist/lib/terrain-raycast.d.ts +44 -0
  59. package/dist/lib/terrain-raycast.d.ts.map +1 -0
  60. package/dist/lib/terrain-raycast.js +188 -0
  61. package/dist/lib/terrain-source.d.ts +60 -0
  62. package/dist/lib/terrain-source.d.ts.map +1 -0
  63. package/dist/lib/terrain-source.js +90 -0
  64. package/dist/lib/terrain-support.d.ts +60 -0
  65. package/dist/lib/terrain-support.d.ts.map +1 -0
  66. package/dist/lib/terrain-support.js +150 -0
  67. package/dist/lib/wall-distance.d.ts +60 -0
  68. package/dist/lib/wall-distance.d.ts.map +1 -0
  69. package/dist/lib/wall-distance.js +85 -0
  70. package/dist/lib/zone-quantities.d.ts +21 -0
  71. package/dist/lib/zone-quantities.d.ts.map +1 -0
  72. package/dist/lib/zone-quantities.js +428 -0
  73. package/dist/material-library.d.ts +28 -1
  74. package/dist/material-library.d.ts.map +1 -1
  75. package/dist/material-library.js +2233 -441
  76. package/dist/registry/handles.d.ts +91 -3
  77. package/dist/registry/handles.d.ts.map +1 -1
  78. package/dist/registry/index.d.ts +3 -3
  79. package/dist/registry/index.d.ts.map +1 -1
  80. package/dist/registry/index.js +1 -1
  81. package/dist/registry/registry.d.ts +46 -3
  82. package/dist/registry/registry.d.ts.map +1 -1
  83. package/dist/registry/registry.js +82 -1
  84. package/dist/registry/subtree.d.ts.map +1 -1
  85. package/dist/registry/subtree.js +8 -1
  86. package/dist/registry/types.d.ts +781 -39
  87. package/dist/registry/types.d.ts.map +1 -1
  88. package/dist/schema/index.d.ts +27 -8
  89. package/dist/schema/index.d.ts.map +1 -1
  90. package/dist/schema/index.js +23 -6
  91. package/dist/schema/material.d.ts +3 -2
  92. package/dist/schema/material.d.ts.map +1 -1
  93. package/dist/schema/material.js +7 -5
  94. package/dist/schema/nodes/box-vent.d.ts +2 -2
  95. package/dist/schema/nodes/cabinet.d.ts +536 -0
  96. package/dist/schema/nodes/cabinet.d.ts.map +1 -0
  97. package/dist/schema/nodes/cabinet.js +139 -0
  98. package/dist/schema/nodes/ceiling.d.ts +4 -3
  99. package/dist/schema/nodes/ceiling.d.ts.map +1 -1
  100. package/dist/schema/nodes/ceiling.js +11 -1
  101. package/dist/schema/nodes/chimney.d.ts +4 -4
  102. package/dist/schema/nodes/column.d.ts +4 -2
  103. package/dist/schema/nodes/column.d.ts.map +1 -1
  104. package/dist/schema/nodes/column.js +5 -0
  105. package/dist/schema/nodes/construction-dimension.d.ts +195 -0
  106. package/dist/schema/nodes/construction-dimension.d.ts.map +1 -0
  107. package/dist/schema/nodes/construction-dimension.js +151 -0
  108. package/dist/schema/nodes/cupola.d.ts +2 -2
  109. package/dist/schema/nodes/door.d.ts +42 -5
  110. package/dist/schema/nodes/door.d.ts.map +1 -1
  111. package/dist/schema/nodes/door.js +32 -0
  112. package/dist/schema/nodes/dormer.d.ts +8 -8
  113. package/dist/schema/nodes/dormer.js +1 -1
  114. package/dist/schema/nodes/downspout.d.ts +2 -2
  115. package/dist/schema/nodes/duct-fitting.d.ts +91 -0
  116. package/dist/schema/nodes/duct-fitting.d.ts.map +1 -0
  117. package/dist/schema/nodes/duct-fitting.js +92 -0
  118. package/dist/schema/nodes/duct-segment.d.ts +61 -0
  119. package/dist/schema/nodes/duct-segment.d.ts.map +1 -0
  120. package/dist/schema/nodes/duct-segment.js +73 -0
  121. package/dist/schema/nodes/duct-terminal.d.ts +58 -0
  122. package/dist/schema/nodes/duct-terminal.d.ts.map +1 -0
  123. package/dist/schema/nodes/duct-terminal.js +53 -0
  124. package/dist/schema/nodes/elevator.d.ts +3 -2
  125. package/dist/schema/nodes/elevator.d.ts.map +1 -1
  126. package/dist/schema/nodes/elevator.js +3 -0
  127. package/dist/schema/nodes/eyebrow-vent.d.ts +2 -2
  128. package/dist/schema/nodes/fence.d.ts +20 -2
  129. package/dist/schema/nodes/fence.d.ts.map +1 -1
  130. package/dist/schema/nodes/fence.js +33 -2
  131. package/dist/schema/nodes/gutter.d.ts +2 -2
  132. package/dist/schema/nodes/hvac-equipment.d.ts +64 -0
  133. package/dist/schema/nodes/hvac-equipment.d.ts.map +1 -0
  134. package/dist/schema/nodes/hvac-equipment.js +57 -0
  135. package/dist/schema/nodes/item.d.ts +9 -0
  136. package/dist/schema/nodes/item.d.ts.map +1 -1
  137. package/dist/schema/nodes/item.js +24 -0
  138. package/dist/schema/nodes/level.d.ts +2 -1
  139. package/dist/schema/nodes/level.d.ts.map +1 -1
  140. package/dist/schema/nodes/level.js +12 -31
  141. package/dist/schema/nodes/lineset.d.ts +42 -0
  142. package/dist/schema/nodes/lineset.d.ts.map +1 -0
  143. package/dist/schema/nodes/lineset.js +38 -0
  144. package/dist/schema/nodes/liquid-line.d.ts +34 -0
  145. package/dist/schema/nodes/liquid-line.d.ts.map +1 -0
  146. package/dist/schema/nodes/liquid-line.js +24 -0
  147. package/dist/schema/nodes/measurement.d.ts +306 -0
  148. package/dist/schema/nodes/measurement.d.ts.map +1 -0
  149. package/dist/schema/nodes/measurement.js +87 -0
  150. package/dist/schema/nodes/pipe-fitting.d.ts +56 -0
  151. package/dist/schema/nodes/pipe-fitting.d.ts.map +1 -0
  152. package/dist/schema/nodes/pipe-fitting.js +45 -0
  153. package/dist/schema/nodes/pipe-segment.d.ts +48 -0
  154. package/dist/schema/nodes/pipe-segment.d.ts.map +1 -0
  155. package/dist/schema/nodes/pipe-segment.js +36 -0
  156. package/dist/schema/nodes/pipe-trap.d.ts +43 -0
  157. package/dist/schema/nodes/pipe-trap.d.ts.map +1 -0
  158. package/dist/schema/nodes/pipe-trap.js +36 -0
  159. package/dist/schema/nodes/ridge-vent.d.ts +18 -3
  160. package/dist/schema/nodes/ridge-vent.d.ts.map +1 -1
  161. package/dist/schema/nodes/ridge-vent.js +221 -3
  162. package/dist/schema/nodes/roof-segment-shape.d.ts +90 -0
  163. package/dist/schema/nodes/roof-segment-shape.d.ts.map +1 -0
  164. package/dist/schema/nodes/roof-segment-shape.js +318 -0
  165. package/dist/schema/nodes/roof-segment-walls.d.ts +101 -0
  166. package/dist/schema/nodes/roof-segment-walls.d.ts.map +1 -0
  167. package/dist/schema/nodes/roof-segment-walls.js +330 -0
  168. package/dist/schema/nodes/roof-segment.d.ts +84 -8
  169. package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
  170. package/dist/schema/nodes/roof-segment.js +290 -5
  171. package/dist/schema/nodes/roof.d.ts +8 -8
  172. package/dist/schema/nodes/shelf.d.ts +4 -2
  173. package/dist/schema/nodes/shelf.d.ts.map +1 -1
  174. package/dist/schema/nodes/shelf.js +8 -0
  175. package/dist/schema/nodes/site.d.ts +9 -0
  176. package/dist/schema/nodes/site.d.ts.map +1 -1
  177. package/dist/schema/nodes/site.js +8 -6
  178. package/dist/schema/nodes/skylight.d.ts +10 -10
  179. package/dist/schema/nodes/slab.d.ts +8 -2
  180. package/dist/schema/nodes/slab.d.ts.map +1 -1
  181. package/dist/schema/nodes/slab.js +18 -2
  182. package/dist/schema/nodes/solar-panel.d.ts +4 -4
  183. package/dist/schema/nodes/spawn.d.ts +1 -0
  184. package/dist/schema/nodes/spawn.d.ts.map +1 -1
  185. package/dist/schema/nodes/spawn.js +2 -0
  186. package/dist/schema/nodes/stair-segment.d.ts +4 -4
  187. package/dist/schema/nodes/stair.d.ts +16 -13
  188. package/dist/schema/nodes/stair.d.ts.map +1 -1
  189. package/dist/schema/nodes/stair.js +11 -1
  190. package/dist/schema/nodes/structural-grid.d.ts +27 -0
  191. package/dist/schema/nodes/structural-grid.d.ts.map +1 -0
  192. package/dist/schema/nodes/structural-grid.js +17 -0
  193. package/dist/schema/nodes/turbine-vent.d.ts +2 -2
  194. package/dist/schema/nodes/wall.d.ts +248 -6
  195. package/dist/schema/nodes/wall.d.ts.map +1 -1
  196. package/dist/schema/nodes/wall.js +266 -0
  197. package/dist/schema/nodes/window.d.ts +40 -3
  198. package/dist/schema/nodes/window.d.ts.map +1 -1
  199. package/dist/schema/nodes/window.js +30 -0
  200. package/dist/schema/nodes/zone.d.ts +22 -0
  201. package/dist/schema/nodes/zone.d.ts.map +1 -1
  202. package/dist/schema/nodes/zone.js +21 -0
  203. package/dist/schema/scene-material.d.ts +41 -0
  204. package/dist/schema/scene-material.d.ts.map +1 -0
  205. package/dist/schema/scene-material.js +9 -0
  206. package/dist/schema/terrain.d.ts +28 -0
  207. package/dist/schema/terrain.d.ts.map +1 -0
  208. package/dist/schema/terrain.js +30 -0
  209. package/dist/schema/types.d.ts +1300 -97
  210. package/dist/schema/types.d.ts.map +1 -1
  211. package/dist/schema/types.js +27 -0
  212. package/dist/services/__fixtures__/wall-plane-top-boundary-repro.d.ts +80 -0
  213. package/dist/services/__fixtures__/wall-plane-top-boundary-repro.d.ts.map +1 -0
  214. package/dist/services/__fixtures__/wall-plane-top-boundary-repro.js +89 -0
  215. package/dist/services/alignment-anchors.d.ts.map +1 -1
  216. package/dist/services/alignment-anchors.js +30 -1
  217. package/dist/services/alignment.d.ts +5 -0
  218. package/dist/services/alignment.d.ts.map +1 -1
  219. package/dist/services/alignment.js +2 -0
  220. package/dist/services/hosting.d.ts +8 -0
  221. package/dist/services/hosting.d.ts.map +1 -1
  222. package/dist/services/hosting.js +13 -4
  223. package/dist/services/index.d.ts +9 -2
  224. package/dist/services/index.d.ts.map +1 -1
  225. package/dist/services/index.js +9 -2
  226. package/dist/services/level-height.d.ts +27 -0
  227. package/dist/services/level-height.d.ts.map +1 -0
  228. package/dist/services/level-height.js +94 -0
  229. package/dist/services/opening-guides.d.ts +141 -0
  230. package/dist/services/opening-guides.d.ts.map +1 -0
  231. package/dist/services/opening-guides.js +267 -0
  232. package/dist/services/port-connectivity.d.ts +115 -0
  233. package/dist/services/port-connectivity.d.ts.map +1 -0
  234. package/dist/services/port-connectivity.js +300 -0
  235. package/dist/services/riser-diagram.d.ts +40 -0
  236. package/dist/services/riser-diagram.d.ts.map +1 -0
  237. package/dist/services/riser-diagram.js +110 -0
  238. package/dist/services/snap.d.ts +9 -1
  239. package/dist/services/snap.d.ts.map +1 -1
  240. package/dist/services/snap.js +21 -1
  241. package/dist/services/storey.d.ts +103 -0
  242. package/dist/services/storey.d.ts.map +1 -0
  243. package/dist/services/storey.js +296 -0
  244. package/dist/services/system-graph.d.ts +30 -0
  245. package/dist/services/system-graph.d.ts.map +1 -0
  246. package/dist/services/system-graph.js +164 -0
  247. package/dist/services/validate-dwv.d.ts +32 -0
  248. package/dist/services/validate-dwv.d.ts.map +1 -0
  249. package/dist/services/validate-dwv.js +118 -0
  250. package/dist/store/actions/node-actions.d.ts.map +1 -1
  251. package/dist/store/actions/node-actions.js +141 -4
  252. package/dist/store/history-control.d.ts +31 -0
  253. package/dist/store/history-control.d.ts.map +1 -1
  254. package/dist/store/history-control.js +130 -0
  255. package/dist/store/use-live-terrain.d.ts +65 -0
  256. package/dist/store/use-live-terrain.d.ts.map +1 -0
  257. package/dist/store/use-live-terrain.js +31 -0
  258. package/dist/store/use-live-transforms.d.ts +8 -0
  259. package/dist/store/use-live-transforms.d.ts.map +1 -1
  260. package/dist/store/use-scene.d.ts +47 -3
  261. package/dist/store/use-scene.d.ts.map +1 -1
  262. package/dist/store/use-scene.js +992 -55
  263. package/dist/systems/elevator/elevator-opening-system.d.ts +1 -0
  264. package/dist/systems/elevator/elevator-opening-system.d.ts.map +1 -1
  265. package/dist/systems/elevator/elevator-opening-system.js +27 -21
  266. package/dist/systems/elevator/elevator-service.d.ts +0 -2
  267. package/dist/systems/elevator/elevator-service.d.ts.map +1 -1
  268. package/dist/systems/elevator/elevator-service.js +2 -24
  269. package/dist/systems/fence/fence-centerline.d.ts +12 -0
  270. package/dist/systems/fence/fence-centerline.d.ts.map +1 -0
  271. package/dist/systems/fence/fence-centerline.js +37 -0
  272. package/dist/systems/fence/fence-spline.d.ts +39 -0
  273. package/dist/systems/fence/fence-spline.d.ts.map +1 -0
  274. package/dist/systems/fence/fence-spline.js +196 -0
  275. package/dist/systems/slab/slab-placement.d.ts +11 -0
  276. package/dist/systems/slab/slab-placement.d.ts.map +1 -0
  277. package/dist/systems/slab/slab-placement.js +14 -0
  278. package/dist/systems/slab/slab-support.d.ts +137 -0
  279. package/dist/systems/slab/slab-support.d.ts.map +1 -0
  280. package/dist/systems/slab/slab-support.js +557 -0
  281. package/dist/systems/stair/stair-footprint.d.ts.map +1 -1
  282. package/dist/systems/stair/stair-footprint.js +21 -11
  283. package/dist/systems/stair/stair-opening-preview.d.ts +1300 -505
  284. package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
  285. package/dist/systems/stair/stair-opening-sync.d.ts.map +1 -1
  286. package/dist/systems/stair/stair-opening-sync.js +19 -33
  287. package/dist/systems/stair/stair-opening-system.d.ts.map +1 -1
  288. package/dist/systems/stair/stair-opening-system.js +32 -4
  289. package/dist/systems/stair/stair-rise.d.ts +22 -0
  290. package/dist/systems/stair/stair-rise.d.ts.map +1 -0
  291. package/dist/systems/stair/stair-rise.js +79 -0
  292. package/dist/systems/wall/wall-curve.d.ts +10 -0
  293. package/dist/systems/wall/wall-curve.d.ts.map +1 -1
  294. package/dist/systems/wall/wall-curve.js +1 -1
  295. package/dist/systems/wall/wall-mitering.d.ts.map +1 -1
  296. package/dist/systems/wall/wall-mitering.js +44 -8
  297. package/dist/systems/wall/wall-top.d.ts +40 -0
  298. package/dist/systems/wall/wall-top.d.ts.map +1 -0
  299. package/dist/systems/wall/wall-top.js +46 -0
  300. package/dist/utils/clone-scene-graph.d.ts +1 -0
  301. package/dist/utils/clone-scene-graph.d.ts.map +1 -1
  302. package/dist/utils/clone-scene-graph.js +56 -5
  303. package/dist/utils/heal-scene-graph.d.ts +18 -0
  304. package/dist/utils/heal-scene-graph.d.ts.map +1 -0
  305. package/dist/utils/heal-scene-graph.js +106 -0
  306. package/dist/validation/validate-build-json.d.ts +3 -0
  307. package/dist/validation/validate-build-json.d.ts.map +1 -1
  308. package/dist/validation/validate-build-json.js +90 -5
  309. package/package.json +4 -4
  310. package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts +0 -2
  311. package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts.map +0 -1
  312. package/dist/hooks/spatial-grid/floor-placed-elevation.test.js +0 -273
  313. package/dist/lib/space-detection-pause.test.d.ts +0 -2
  314. package/dist/lib/space-detection-pause.test.d.ts.map +0 -1
  315. package/dist/lib/space-detection-pause.test.js +0 -42
  316. package/dist/lib/space-detection.test.d.ts +0 -2
  317. package/dist/lib/space-detection.test.d.ts.map +0 -1
  318. package/dist/lib/space-detection.test.js +0 -77
  319. package/dist/registry/registry.test.d.ts +0 -2
  320. package/dist/registry/registry.test.d.ts.map +0 -1
  321. package/dist/registry/registry.test.js +0 -183
  322. package/dist/registry/relations-resolver.test.d.ts +0 -2
  323. package/dist/registry/relations-resolver.test.d.ts.map +0 -1
  324. package/dist/registry/relations-resolver.test.js +0 -183
  325. package/dist/registry/scene-api.test.d.ts +0 -2
  326. package/dist/registry/scene-api.test.d.ts.map +0 -1
  327. package/dist/registry/scene-api.test.js +0 -183
  328. package/dist/registry/subtree.test.d.ts +0 -2
  329. package/dist/registry/subtree.test.d.ts.map +0 -1
  330. package/dist/registry/subtree.test.js +0 -133
  331. package/dist/schema/asset-url.test.d.ts +0 -2
  332. package/dist/schema/asset-url.test.d.ts.map +0 -1
  333. package/dist/schema/asset-url.test.js +0 -134
  334. package/dist/services/alignment-anchors.test.d.ts +0 -2
  335. package/dist/services/alignment-anchors.test.d.ts.map +0 -1
  336. package/dist/services/alignment-anchors.test.js +0 -383
  337. package/dist/services/alignment.test.d.ts +0 -2
  338. package/dist/services/alignment.test.d.ts.map +0 -1
  339. package/dist/services/alignment.test.js +0 -92
  340. package/dist/services/drag-session.test.d.ts +0 -2
  341. package/dist/services/drag-session.test.d.ts.map +0 -1
  342. package/dist/services/drag-session.test.js +0 -219
  343. package/dist/services/hosting.test.d.ts +0 -2
  344. package/dist/services/hosting.test.d.ts.map +0 -1
  345. package/dist/services/hosting.test.js +0 -199
  346. package/dist/services/movement.test.d.ts +0 -2
  347. package/dist/services/movement.test.d.ts.map +0 -1
  348. package/dist/services/movement.test.js +0 -133
  349. package/dist/services/single-undo-dance.test.d.ts +0 -2
  350. package/dist/services/single-undo-dance.test.d.ts.map +0 -1
  351. package/dist/services/single-undo-dance.test.js +0 -210
  352. package/dist/services/snap.test.d.ts +0 -2
  353. package/dist/services/snap.test.d.ts.map +0 -1
  354. package/dist/services/snap.test.js +0 -95
  355. package/dist/store/actions/node-mutation-sanitize.test.d.ts +0 -2
  356. package/dist/store/actions/node-mutation-sanitize.test.d.ts.map +0 -1
  357. package/dist/store/actions/node-mutation-sanitize.test.js +0 -147
  358. package/dist/store/actions/reparent.test.d.ts +0 -2
  359. package/dist/store/actions/reparent.test.d.ts.map +0 -1
  360. package/dist/store/actions/reparent.test.js +0 -212
  361. package/dist/store/use-scene-elevator-migration.test.d.ts +0 -2
  362. package/dist/store/use-scene-elevator-migration.test.d.ts.map +0 -1
  363. package/dist/store/use-scene-elevator-migration.test.js +0 -109
  364. package/dist/systems/elevator/elevator-opening-sync.test.d.ts +0 -2
  365. package/dist/systems/elevator/elevator-opening-sync.test.d.ts.map +0 -1
  366. package/dist/systems/elevator/elevator-opening-sync.test.js +0 -146
  367. package/dist/systems/elevator/elevator-runtime.test.d.ts +0 -2
  368. package/dist/systems/elevator/elevator-runtime.test.d.ts.map +0 -1
  369. package/dist/systems/elevator/elevator-runtime.test.js +0 -64
  370. package/dist/systems/stair/stair-opening-preview.test.d.ts +0 -2
  371. package/dist/systems/stair/stair-opening-preview.test.d.ts.map +0 -1
  372. package/dist/systems/stair/stair-opening-preview.test.js +0 -80
  373. package/dist/systems/stair/stair-opening-sync.test.d.ts +0 -2
  374. package/dist/systems/stair/stair-opening-sync.test.d.ts.map +0 -1
  375. package/dist/systems/stair/stair-opening-sync.test.js +0 -446
  376. package/dist/utils/clone-scene-graph.test.d.ts +0 -2
  377. package/dist/utils/clone-scene-graph.test.d.ts.map +0 -1
  378. package/dist/utils/clone-scene-graph.test.js +0 -59
@@ -19,7 +19,7 @@ export declare const EyebrowVentNode: z.ZodObject<{
19
19
  type: z.ZodDefault<z.ZodLiteral<"eyebrow-vent">>;
20
20
  material: z.ZodOptional<z.ZodObject<{
21
21
  id: z.ZodOptional<z.ZodString>;
22
- preset: z.ZodOptional<z.ZodEnum<{
22
+ preset: z.ZodOptional<z.ZodCatch<z.ZodEnum<{
23
23
  custom: "custom";
24
24
  white: "white";
25
25
  brick: "brick";
@@ -30,7 +30,7 @@ export declare const EyebrowVentNode: z.ZodObject<{
30
30
  plaster: "plaster";
31
31
  tile: "tile";
32
32
  marble: "marble";
33
- }>>;
33
+ }>>>;
34
34
  properties: z.ZodOptional<z.ZodObject<{
35
35
  color: z.ZodDefault<z.ZodString>;
36
36
  roughness: z.ZodDefault<z.ZodNumber>;
@@ -3,11 +3,17 @@ export declare const FenceStyle: z.ZodEnum<{
3
3
  slat: "slat";
4
4
  rail: "rail";
5
5
  privacy: "privacy";
6
+ horizontal: "horizontal";
6
7
  }>;
7
8
  export declare const FenceBaseStyle: z.ZodEnum<{
8
9
  floating: "floating";
9
10
  grounded: "grounded";
10
11
  }>;
12
+ export declare const FencePostCap: z.ZodEnum<{
13
+ flat: "flat";
14
+ none: "none";
15
+ pyramid: "pyramid";
16
+ }>;
11
17
  export declare const FenceNode: z.ZodObject<{
12
18
  object: z.ZodDefault<z.ZodLiteral<"node">>;
13
19
  name: z.ZodOptional<z.ZodString>;
@@ -28,7 +34,7 @@ export declare const FenceNode: z.ZodObject<{
28
34
  type: z.ZodDefault<z.ZodLiteral<"fence">>;
29
35
  material: z.ZodOptional<z.ZodObject<{
30
36
  id: z.ZodOptional<z.ZodString>;
31
- preset: z.ZodOptional<z.ZodEnum<{
37
+ preset: z.ZodOptional<z.ZodCatch<z.ZodEnum<{
32
38
  custom: "custom";
33
39
  white: "white";
34
40
  brick: "brick";
@@ -39,7 +45,7 @@ export declare const FenceNode: z.ZodObject<{
39
45
  plaster: "plaster";
40
46
  tile: "tile";
41
47
  marble: "marble";
42
- }>>;
48
+ }>>>;
43
49
  properties: z.ZodOptional<z.ZodObject<{
44
50
  color: z.ZodDefault<z.ZodString>;
45
51
  roughness: z.ZodDefault<z.ZodNumber>;
@@ -59,10 +65,15 @@ export declare const FenceNode: z.ZodObject<{
59
65
  }, z.core.$strip>>;
60
66
  }, z.core.$strip>>;
61
67
  materialPreset: z.ZodOptional<z.ZodString>;
68
+ slots: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
62
69
  start: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
63
70
  end: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
71
+ path: z.ZodOptional<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>>;
72
+ tangents: z.ZodOptional<z.ZodArray<z.ZodNullable<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>>>;
64
73
  height: z.ZodDefault<z.ZodNumber>;
65
74
  thickness: z.ZodDefault<z.ZodNumber>;
75
+ supportSlabId: z.ZodOptional<z.ZodString>;
76
+ supportOffset: z.ZodOptional<z.ZodNumber>;
66
77
  curveOffset: z.ZodOptional<z.ZodNumber>;
67
78
  baseHeight: z.ZodDefault<z.ZodNumber>;
68
79
  postSpacing: z.ZodDefault<z.ZodNumber>;
@@ -70,6 +81,12 @@ export declare const FenceNode: z.ZodObject<{
70
81
  topRailHeight: z.ZodDefault<z.ZodNumber>;
71
82
  groundClearance: z.ZodDefault<z.ZodNumber>;
72
83
  edgeInset: z.ZodDefault<z.ZodNumber>;
84
+ slatGap: z.ZodDefault<z.ZodNumber>;
85
+ postCap: z.ZodDefault<z.ZodEnum<{
86
+ flat: "flat";
87
+ none: "none";
88
+ pyramid: "pyramid";
89
+ }>>;
73
90
  baseStyle: z.ZodDefault<z.ZodEnum<{
74
91
  floating: "floating";
75
92
  grounded: "grounded";
@@ -80,6 +97,7 @@ export declare const FenceNode: z.ZodObject<{
80
97
  slat: "slat";
81
98
  rail: "rail";
82
99
  privacy: "privacy";
100
+ horizontal: "horizontal";
83
101
  }>>;
84
102
  }, z.core.$strip>;
85
103
  export type FenceNode = z.infer<typeof FenceNode>;
@@ -1 +1 @@
1
- {"version":3,"file":"fence.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/fence.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,UAAU;;;;EAAsC,CAAA;AAC7D,eAAO,MAAM,cAAc;;;EAAmC,CAAA;AAE9D,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+BrB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAA"}
1
+ {"version":3,"file":"fence.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/fence.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,UAAU;;;;;EAAoD,CAAA;AAC3E,eAAO,MAAM,cAAc;;;EAAmC,CAAA;AAC9D,eAAO,MAAM,YAAY;;;;EAAsC,CAAA;AAE/D,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6DrB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAA"}
@@ -2,17 +2,40 @@ import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
3
  import { BaseNode, nodeType, objectId } from '../base';
4
4
  import { MaterialSchema } from '../material';
5
- export const FenceStyle = z.enum(['slat', 'rail', 'privacy']);
5
+ export const FenceStyle = z.enum(['slat', 'rail', 'privacy', 'horizontal']);
6
6
  export const FenceBaseStyle = z.enum(['floating', 'grounded']);
7
+ export const FencePostCap = z.enum(['none', 'flat', 'pyramid']);
7
8
  export const FenceNode = BaseNode.extend({
8
9
  id: objectId('fence'),
9
10
  type: nodeType('fence'),
10
11
  material: MaterialSchema.optional(),
11
12
  materialPreset: z.string().optional(),
13
+ // Unified paint-slot refs (`scene:`/`library:` MaterialRef per slot id),
14
+ // matching the slot model items/slab/shelf use. Absent = declared default.
15
+ slots: z.record(z.string(), z.string()).optional(),
12
16
  start: z.tuple([z.number(), z.number()]),
13
17
  end: z.tuple([z.number(), z.number()]),
18
+ // Optional spline control points in level coordinate meters. When present
19
+ // (>= 2 points) the fence centerline is a smooth Catmull-Rom curve through
20
+ // these points and start/end/curveOffset no longer define the centerline.
21
+ // start/end are kept in sync with the first/last path point so consumers
22
+ // that read endpoints (handles, bbox, miter references) stay valid. Absent =
23
+ // the straight or single-arc fence defined by start/end (+ curveOffset).
24
+ path: z.array(z.tuple([z.number(), z.number()])).optional(),
25
+ // Optional per-control-point tangent handles, parallel to `path` (same
26
+ // length when present). Each entry is the OUT-handle offset vector [dx, dy]
27
+ // from its path point, in level meters; the IN handle is its mirror so the
28
+ // curve stays smooth through the point. `null` = use the automatic
29
+ // Catmull-Rom tangent for that point. Only meaningful for spline fences.
30
+ tangents: z.array(z.tuple([z.number(), z.number()]).nullable()).optional(),
14
31
  height: z.number().default(1.8),
15
32
  thickness: z.number().default(0.08),
33
+ // Persisted slab-support host — the fence sits on that slab's walking
34
+ // surface (see ItemNode.supportSlabId for the host rules).
35
+ supportSlabId: z.string().optional(),
36
+ // Manual vertical offset from the elected slab or level support. This moves
37
+ // the complete fence body without changing its height.
38
+ supportOffset: z.number().finite().optional(),
16
39
  curveOffset: z.number().optional(),
17
40
  baseHeight: z.number().default(0.22),
18
41
  postSpacing: z.number().default(2),
@@ -20,6 +43,10 @@ export const FenceNode = BaseNode.extend({
20
43
  topRailHeight: z.number().default(0.04),
21
44
  groundClearance: z.number().default(0),
22
45
  edgeInset: z.number().default(0.015),
46
+ // Reveal between the boards of a `horizontal` fence (0 = flush cladding).
47
+ slatGap: z.number().default(0.01),
48
+ // Topper drawn on each `horizontal`-fence post.
49
+ postCap: FencePostCap.default('pyramid'),
23
50
  baseStyle: FenceBaseStyle.default('grounded'),
24
51
  showInfill: z.boolean().default(true),
25
52
  color: z.string().default('#ffffff'),
@@ -27,8 +54,12 @@ export const FenceNode = BaseNode.extend({
27
54
  }).describe(dedent `
28
55
  Fence node - used to represent a fence segment in the building/site level coordinate system
29
56
  - start/end: fence endpoints in level coordinate system
57
+ - path: optional list of [x, y] points; when set (>= 2) the centerline is a smooth spline through them
58
+ - tangents: optional per-point handle vectors (parallel to path); null entries fall back to the automatic tangent
30
59
  - height/thickness: overall fence dimensions in meters
31
- - curveOffset: midpoint sagitta offset used to bend the fence into an arc
60
+ - supportSlabId: optional slab host; the fence stands on that slab's walking surface (elevation)
61
+ - supportOffset: manual vertical offset from the elected support surface
62
+ - curveOffset: midpoint sagitta offset used to bend the fence into an arc (ignored when path is set)
32
63
  - baseHeight/postSpacing/postSize/topRailHeight: exact geometric controls from the plan3D fence model
33
64
  - groundClearance/edgeInset/baseStyle: fence support and inset configuration
34
65
  - showInfill: whether to draw intermediate posts/slats between end posts
@@ -25,7 +25,7 @@ export declare const GutterNode: z.ZodObject<{
25
25
  type: z.ZodDefault<z.ZodLiteral<"gutter">>;
26
26
  material: z.ZodOptional<z.ZodObject<{
27
27
  id: z.ZodOptional<z.ZodString>;
28
- preset: z.ZodOptional<z.ZodEnum<{
28
+ preset: z.ZodOptional<z.ZodCatch<z.ZodEnum<{
29
29
  custom: "custom";
30
30
  white: "white";
31
31
  brick: "brick";
@@ -36,7 +36,7 @@ export declare const GutterNode: z.ZodObject<{
36
36
  plaster: "plaster";
37
37
  tile: "tile";
38
38
  marble: "marble";
39
- }>>;
39
+ }>>>;
40
40
  properties: z.ZodOptional<z.ZodObject<{
41
41
  color: z.ZodDefault<z.ZodString>;
42
42
  roughness: z.ZodDefault<z.ZodNumber>;
@@ -0,0 +1,64 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * HVAC equipment — the boxes duct systems start and end at: furnace,
4
+ * air handler, outdoor condenser.
5
+ *
6
+ * Phase 3 of the HVAC node system. Furnaces and air handlers expose
7
+ * typed duct ports (supply plenum on top, return drop on the side) so
8
+ * duct runs and fittings snap onto them. Every unit also exposes a
9
+ * refrigerant service port on its valve face — a condenser, the outdoor
10
+ * half of a split system, carries no duct ports but pipes to the indoor
11
+ * coil through a `lineset` run mating onto that port.
12
+ *
13
+ * Floor-placed: `position` is level-local meters with y at the base,
14
+ * `rotation` is yaw radians (the editor's default R-rotate applies).
15
+ */
16
+ export declare const HvacEquipmentNode: z.ZodObject<{
17
+ object: z.ZodDefault<z.ZodLiteral<"node">>;
18
+ name: z.ZodOptional<z.ZodString>;
19
+ parentId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
20
+ visible: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
21
+ camera: z.ZodOptional<z.ZodObject<{
22
+ position: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
23
+ target: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
24
+ mode: z.ZodDefault<z.ZodEnum<{
25
+ perspective: "perspective";
26
+ orthographic: "orthographic";
27
+ }>>;
28
+ fov: z.ZodOptional<z.ZodNumber>;
29
+ zoom: z.ZodOptional<z.ZodNumber>;
30
+ }, z.core.$strip>>;
31
+ metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
32
+ id: z.ZodDefault<z.ZodTemplateLiteral<`hvac-equipment_${string}`>>;
33
+ type: z.ZodDefault<z.ZodLiteral<"hvac-equipment">>;
34
+ position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
35
+ rotation: z.ZodDefault<z.ZodNumber>;
36
+ supportSlabId: z.ZodOptional<z.ZodString>;
37
+ equipmentType: z.ZodDefault<z.ZodEnum<{
38
+ furnace: "furnace";
39
+ "air-handler": "air-handler";
40
+ condenser: "condenser";
41
+ }>>;
42
+ width: z.ZodDefault<z.ZodNumber>;
43
+ depth: z.ZodDefault<z.ZodNumber>;
44
+ height: z.ZodDefault<z.ZodNumber>;
45
+ supplyShape: z.ZodDefault<z.ZodEnum<{
46
+ round: "round";
47
+ rect: "rect";
48
+ oval: "oval";
49
+ }>>;
50
+ returnShape: z.ZodDefault<z.ZodEnum<{
51
+ round: "round";
52
+ rect: "rect";
53
+ oval: "oval";
54
+ }>>;
55
+ supplyDiameter: z.ZodDefault<z.ZodNumber>;
56
+ returnDiameter: z.ZodDefault<z.ZodNumber>;
57
+ supplyWidth: z.ZodDefault<z.ZodNumber>;
58
+ supplyHeight: z.ZodDefault<z.ZodNumber>;
59
+ returnWidth: z.ZodDefault<z.ZodNumber>;
60
+ returnHeight: z.ZodDefault<z.ZodNumber>;
61
+ }, z.core.$strip>;
62
+ export type HvacEquipmentNode = z.infer<typeof HvacEquipmentNode>;
63
+ export type HvacEquipmentNodeId = HvacEquipmentNode['id'];
64
+ //# sourceMappingURL=hvac-equipment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hvac-equipment.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/hvac-equipment.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyC7B,CAAA;AACD,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AACjE,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAA"}
@@ -0,0 +1,57 @@
1
+ import dedent from 'dedent';
2
+ import { z } from 'zod';
3
+ import { BaseNode, nodeType, objectId } from '../base';
4
+ /**
5
+ * HVAC equipment — the boxes duct systems start and end at: furnace,
6
+ * air handler, outdoor condenser.
7
+ *
8
+ * Phase 3 of the HVAC node system. Furnaces and air handlers expose
9
+ * typed duct ports (supply plenum on top, return drop on the side) so
10
+ * duct runs and fittings snap onto them. Every unit also exposes a
11
+ * refrigerant service port on its valve face — a condenser, the outdoor
12
+ * half of a split system, carries no duct ports but pipes to the indoor
13
+ * coil through a `lineset` run mating onto that port.
14
+ *
15
+ * Floor-placed: `position` is level-local meters with y at the base,
16
+ * `rotation` is yaw radians (the editor's default R-rotate applies).
17
+ */
18
+ export const HvacEquipmentNode = BaseNode.extend({
19
+ id: objectId('hvac-equipment'),
20
+ type: nodeType('hvac-equipment'),
21
+ // Level-local meters, y at the unit's base.
22
+ position: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
23
+ // Yaw in radians.
24
+ rotation: z.number().default(0),
25
+ // Persisted slab-support host — see ItemNode.supportSlabId for the rules.
26
+ supportSlabId: z.string().optional(),
27
+ equipmentType: z.enum(['furnace', 'air-handler', 'condenser']).default('furnace'),
28
+ // Cabinet dimensions in meters. Defaults match a typical upflow
29
+ // furnace cabinet (~22" × 28" footprint, ~43" tall).
30
+ width: z.number().min(0.3).max(2).default(0.56),
31
+ depth: z.number().min(0.3).max(2).default(0.71),
32
+ height: z.number().min(0.4).max(2.5).default(1.1),
33
+ // Duct collar cross-section on the supply / return connections. Round is
34
+ // the default; rect and oval (flat-oval) match the duct shapes a run
35
+ // might mate with. Condensers carry no duct collars (ignored).
36
+ supplyShape: z.enum(['round', 'rect', 'oval']).default('round'),
37
+ returnShape: z.enum(['round', 'rect', 'oval']).default('round'),
38
+ // Round collar diameters in inches.
39
+ supplyDiameter: z.number().min(6).max(30).default(8),
40
+ returnDiameter: z.number().min(6).max(30).default(8),
41
+ // Rect / oval collar cross-section in inches: width is the horizontal
42
+ // face, height the vertical. For oval, height is also the end-cap
43
+ // semicircle diameter (width ≥ height).
44
+ supplyWidth: z.number().min(6).max(30).default(12),
45
+ supplyHeight: z.number().min(6).max(30).default(8),
46
+ returnWidth: z.number().min(6).max(30).default(14),
47
+ returnHeight: z.number().min(6).max(30).default(8),
48
+ }).describe(dedent `
49
+ HVAC equipment cabinet - furnace, air handler, or outdoor condenser.
50
+ - position: [x, y, z] level-local meters (y = base)
51
+ - rotation: yaw radians
52
+ - equipmentType: furnace | air-handler | condenser
53
+ - width / depth / height: cabinet size in meters
54
+ - supplyShape / returnShape: round | rect | oval duct collar cross-section (ignored by condenser)
55
+ - supplyDiameter / returnDiameter: round collar sizes in inches
56
+ - supplyWidth / supplyHeight / returnWidth / returnHeight: rect / oval collar cross-section in inches
57
+ `);
@@ -241,7 +241,16 @@ export declare const ItemNode: z.ZodObject<{
241
241
  children: z.ZodDefault<z.ZodArray<z.ZodDefault<z.ZodTemplateLiteral<`item_${string}`>>>>;
242
242
  wallId: z.ZodOptional<z.ZodString>;
243
243
  wallT: z.ZodOptional<z.ZodNumber>;
244
+ roofSegmentId: z.ZodOptional<z.ZodString>;
245
+ roofFace: z.ZodOptional<z.ZodEnum<{
246
+ front: "front";
247
+ back: "back";
248
+ right: "right";
249
+ left: "left";
250
+ }>>;
251
+ supportSlabId: z.ZodOptional<z.ZodString>;
244
252
  collectionIds: z.ZodOptional<z.ZodArray<z.ZodCustom<`collection_${string}`, `collection_${string}`>>>;
253
+ slots: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
245
254
  asset: z.ZodObject<{
246
255
  id: z.ZodString;
247
256
  category: z.ZodString;
@@ -1 +1 @@
1
- {"version":3,"file":"item.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/item.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAOvB,QAAA,MAAM,mBAAmB;;;;iBAIvB,CAAA;AAEF,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;iBASvB,CAAA;AAEF,QAAA,MAAM,wBAAwB;;;;;;;;;;iBAO5B,CAAA;AAEF,QAAA,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAIjB,CAAA;AAIF,QAAA,MAAM,qBAAqB;;;;;;;iBAOzB,CAAA;AAEF,QAAA,MAAM,iBAAiB;;;;;;iBAMrB,CAAA;AAEF,QAAA,MAAM,YAAY;;;;;;;;;;;;;2BAA2E,CAAA;AAI7F,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGrB,CAAA;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AACzE,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA;AACnD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AACnE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAC3D,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AACjD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAE3D,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2Cf,CAAA;AAEF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AACpD,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AAE/C,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6BnB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA;AAE/C,eAAO,MAAM,mCAAmC,MAAM,CAAA;AAEtD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAM/D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAI5E"}
1
+ {"version":3,"file":"item.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/item.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAOvB,QAAA,MAAM,mBAAmB;;;;iBAIvB,CAAA;AAEF,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;iBASvB,CAAA;AAEF,QAAA,MAAM,wBAAwB;;;;;;;;;;iBAO5B,CAAA;AAEF,QAAA,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAIjB,CAAA;AAIF,QAAA,MAAM,qBAAqB;;;;;;;iBAOzB,CAAA;AAEF,QAAA,MAAM,iBAAiB;;;;;;iBAMrB,CAAA;AAEF,QAAA,MAAM,YAAY;;;;;;;;;;;;;2BAA2E,CAAA;AAI7F,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGrB,CAAA;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AACzE,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA;AACnD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AACnE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAC3D,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AACjD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAE3D,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2Cf,CAAA;AAEF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AACpD,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AAE/C,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuDnB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA;AAE/C,eAAO,MAAM,mCAAmC,MAAM,CAAA;AAEtD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAM/D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAI5E"}
@@ -108,8 +108,32 @@ export const ItemNode = BaseNode.extend({
108
108
  // Wall attachment properties (only used when asset.attachTo is "wall" or "wall-side")
109
109
  wallId: z.string().optional(),
110
110
  wallT: z.number().optional(), // 0-1 parametric position along wall
111
+ // Alternative wall host: a roof-segment's generated wall face. When
112
+ // set, `position` is FACE-LOCAL — [u along the face, v = bottom edge,
113
+ // z from the wall mid-plane] — exactly the wall-child convention
114
+ // (ItemSystem's wall-side push applies the same way); the renderer
115
+ // mounts the node inside the face frame (`getRoofWallFaceFrame`).
116
+ roofSegmentId: z.string().optional(),
117
+ roofFace: z.enum(['front', 'back', 'right', 'left']).optional(),
118
+ // Persisted floor-support host (canonical doc — the same field on other
119
+ // floor-placed kinds and walls follows these rules). Written at
120
+ // placement/commit ONLY when overlapping slabs disagree on elevation
121
+ // (ambiguity); absent/null means "elect the support fresh on every
122
+ // read", which is the historical behavior. Read paths PREFER this slab
123
+ // while it still exists and still overlaps the node's footprint, and
124
+ // silently fall back to election otherwise. Deleting the host slab
125
+ // strips the field (deleteNodesAction); a host merely reshaped away is
126
+ // deliberately kept so hosting resumes if the slab's polygon returns.
127
+ // The sentinel value 'ground' (GROUND_SUPPORT_ID) pins the node to the
128
+ // level base — written when a pointer-capped commit elected the ground
129
+ // while a slab (e.g. an elevated deck) still overlapped the footprint.
130
+ supportSlabId: z.string().optional(),
111
131
  // Denormalized references to collections this node belongs to
112
132
  collectionIds: z.array(z.custom()).optional(),
133
+ // Per-slot material overrides. Key = slot id (see deriveSlotId), value = a
134
+ // MaterialRef string ('library:<id>' or 'scene:<id>'). Absent = authored /
135
+ // registry default. A dangling ref renders the default (never blocks).
136
+ slots: z.record(z.string(), z.string()).optional(),
113
137
  asset: assetSchema,
114
138
  }).describe(dedent `Item node - used to represent a item in the building
115
139
  - position: position in level coordinate system (or parent coordinate system if attached)
@@ -17,8 +17,9 @@ export declare const LevelNode: z.ZodObject<{
17
17
  metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
18
18
  id: z.ZodDefault<z.ZodTemplateLiteral<`level_${string}`>>;
19
19
  type: z.ZodDefault<z.ZodLiteral<"level">>;
20
- children: z.ZodDefault<z.ZodArray<z.ZodUnion<readonly [z.ZodDefault<z.ZodTemplateLiteral<`wall_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`fence_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`column_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`item_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`zone_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`slab_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`ceiling_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`roof_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`stair_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`scan_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`guide_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`spawn_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`shelf_${string}`>>]>>>;
20
+ children: z.ZodDefault<z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<`item_${string}` | `ceiling_${string}` | `column_${string}` | `wall_${string}` | `fence_${string}` | `construction-dimension_${string}` | `structural-grid_${string}` | `zone_${string}` | `slab_${string}` | `roof_${string}` | `stair_${string}` | `scan_${string}` | `guide_${string}` | `measurement_${string}` | `spawn_${string}` | `shelf_${string}` | `duct-segment_${string}` | `duct-fitting_${string}` | `duct-terminal_${string}` | `hvac-equipment_${string}` | `lineset_${string}` | `liquid-line_${string}` | `pipe-segment_${string}` | `pipe-fitting_${string}` | `pipe-trap_${string}`, string>>>>;
21
21
  level: z.ZodDefault<z.ZodNumber>;
22
+ height: z.ZodOptional<z.ZodNumber>;
22
23
  }, z.core.$strip>;
23
24
  export type LevelNode = z.infer<typeof LevelNode>;
24
25
  //# sourceMappingURL=level.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"level.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/level.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAgBvB,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;iBA8BrB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAA"}
1
+ {"version":3,"file":"level.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/level.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAyDvB,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;iBAqBrB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAA"}
@@ -1,43 +1,24 @@
1
1
  import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
3
  import { BaseNode, nodeType, objectId } from '../base';
4
- import { CeilingNode } from './ceiling';
5
- import { ColumnNode } from './column';
6
- import { FenceNode } from './fence';
7
- import { GuideNode } from './guide';
8
- import { ItemNode } from './item';
9
- import { RoofNode } from './roof';
10
- import { ScanNode } from './scan';
11
- import { ShelfNode } from './shelf';
12
- import { SlabNode } from './slab';
13
- import { SpawnNode } from './spawn';
14
- import { StairNode } from './stair';
15
- import { WallNode } from './wall';
16
- import { ZoneNode } from './zone';
4
+ const LevelChildId = z.string().transform((id) => id);
17
5
  export const LevelNode = BaseNode.extend({
18
6
  id: objectId('level'),
19
7
  type: nodeType('level'),
20
- children: z
21
- .array(z.union([
22
- WallNode.shape.id,
23
- FenceNode.shape.id,
24
- ColumnNode.shape.id,
25
- ItemNode.shape.id,
26
- ZoneNode.shape.id,
27
- SlabNode.shape.id,
28
- CeilingNode.shape.id,
29
- RoofNode.shape.id,
30
- StairNode.shape.id,
31
- ScanNode.shape.id,
32
- GuideNode.shape.id,
33
- SpawnNode.shape.id,
34
- ShelfNode.shape.id,
35
- ]))
36
- .default([]),
8
+ // The node registry owns child-kind validity. Persisted level relationships
9
+ // must also admit IDs minted by plugins that core cannot enumerate.
10
+ children: z.array(LevelChildId).default([]),
37
11
  // Specific props
38
12
  level: z.number().default(0),
13
+ /**
14
+ * Stored storey height in meters (floor-to-floor). No zod default on
15
+ * purpose: absence marks unmigrated legacy data and gates the load-time
16
+ * migration; a schema default would materialize silently through .parse().
17
+ */
18
+ height: z.number().optional(),
39
19
  }).describe(dedent `
40
20
  Level node - used to represent a level in the building
41
- - children: array of floor, wall, ceiling, roof, item nodes
21
+ - children: array of architectural, equipment, and MEP distribution nodes
42
22
  - level: level number
23
+ - height: storey height in meters (floor-to-floor); absent only on unmigrated legacy data
43
24
  `);
@@ -0,0 +1,42 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Refrigerant lineset — the copper pipe pair that links the outdoor
4
+ * condenser to the indoor coil (furnace / air handler) of a split system.
5
+ * It is the refrigerant-side analogue of a duct run: a polyline of points,
6
+ * but carrying two lines instead of one airway.
7
+ *
8
+ * Real linesets run a fat insulated SUCTION line (cool vapour back to the
9
+ * compressor) beside a thin bare LIQUID line (warm liquid out to the coil).
10
+ * The geometry builder draws a single copper line on the path centerline
11
+ * (sized to `suctionDiameter`, wrapped in a foam jacket when `insulated`);
12
+ * draw the liquid line as a second lineset rather than both off one path.
13
+ *
14
+ * Path coordinates are level-local meters: [x, y, z] tuples, same space as
15
+ * duct paths and grid events. Diameters are nominal copper OD in inches.
16
+ */
17
+ export declare const LinesetNode: z.ZodObject<{
18
+ object: z.ZodDefault<z.ZodLiteral<"node">>;
19
+ name: z.ZodOptional<z.ZodString>;
20
+ parentId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
21
+ visible: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
22
+ camera: z.ZodOptional<z.ZodObject<{
23
+ position: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
24
+ target: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
25
+ mode: z.ZodDefault<z.ZodEnum<{
26
+ perspective: "perspective";
27
+ orthographic: "orthographic";
28
+ }>>;
29
+ fov: z.ZodOptional<z.ZodNumber>;
30
+ zoom: z.ZodOptional<z.ZodNumber>;
31
+ }, z.core.$strip>>;
32
+ metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
33
+ id: z.ZodDefault<z.ZodTemplateLiteral<`lineset_${string}`>>;
34
+ type: z.ZodDefault<z.ZodLiteral<"lineset">>;
35
+ path: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
36
+ suctionDiameter: z.ZodDefault<z.ZodNumber>;
37
+ liquidDiameter: z.ZodDefault<z.ZodNumber>;
38
+ insulated: z.ZodDefault<z.ZodBoolean>;
39
+ }, z.core.$strip>;
40
+ export type LinesetNode = z.infer<typeof LinesetNode>;
41
+ export type LinesetNodeId = LinesetNode['id'];
42
+ //# sourceMappingURL=lineset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lineset.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/lineset.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;iBAqBvB,CAAA;AACD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AACrD,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC,IAAI,CAAC,CAAA"}
@@ -0,0 +1,38 @@
1
+ import dedent from 'dedent';
2
+ import { z } from 'zod';
3
+ import { BaseNode, nodeType, objectId } from '../base';
4
+ /**
5
+ * Refrigerant lineset — the copper pipe pair that links the outdoor
6
+ * condenser to the indoor coil (furnace / air handler) of a split system.
7
+ * It is the refrigerant-side analogue of a duct run: a polyline of points,
8
+ * but carrying two lines instead of one airway.
9
+ *
10
+ * Real linesets run a fat insulated SUCTION line (cool vapour back to the
11
+ * compressor) beside a thin bare LIQUID line (warm liquid out to the coil).
12
+ * The geometry builder draws a single copper line on the path centerline
13
+ * (sized to `suctionDiameter`, wrapped in a foam jacket when `insulated`);
14
+ * draw the liquid line as a second lineset rather than both off one path.
15
+ *
16
+ * Path coordinates are level-local meters: [x, y, z] tuples, same space as
17
+ * duct paths and grid events. Diameters are nominal copper OD in inches.
18
+ */
19
+ export const LinesetNode = BaseNode.extend({
20
+ id: objectId('lineset'),
21
+ type: nodeType('lineset'),
22
+ // Polyline path in level-local meters. Minimum two points (start, end).
23
+ path: z.array(z.tuple([z.number(), z.number(), z.number()])).min(2),
24
+ // Nominal suction-line copper OD in inches (the large insulated line).
25
+ // Common residential sizes are 3/4"–1-1/8".
26
+ suctionDiameter: z.number().min(0.25).max(2).default(0.875),
27
+ // Nominal liquid-line copper OD in inches (the small bare line).
28
+ // Common residential sizes are 1/4"–3/8".
29
+ liquidDiameter: z.number().min(0.125).max(1).default(0.375),
30
+ // Whether the suction line carries its foam insulation jacket. Bare = false.
31
+ insulated: z.boolean().default(true),
32
+ }).describe(dedent `
33
+ Refrigerant lineset - copper suction + liquid pair linking a condenser to an indoor coil.
34
+ - path: list of [x, y, z] points in level-local meters (min 2)
35
+ - suctionDiameter: nominal copper OD in inches of the large insulated line (typ. 3/4"-1-1/8")
36
+ - liquidDiameter: nominal copper OD in inches of the small bare line (typ. 1/4"-3/8")
37
+ - insulated: whether the suction line wears its foam jacket
38
+ `);
@@ -0,0 +1,34 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Standalone refrigerant liquid line — the thin bare-copper line that carries
4
+ * warm liquid out to the indoor coil. It is the line that used to be drawn as
5
+ * the lineset's second rail; broken out here as its own polyline run so it can
6
+ * be drawn on its own, including traced alongside an existing lineset.
7
+ *
8
+ * Path coordinates are level-local meters: [x, y, z] tuples, the same space as
9
+ * lineset and duct paths. Diameter is nominal copper OD in inches.
10
+ */
11
+ export declare const LiquidLineNode: z.ZodObject<{
12
+ object: z.ZodDefault<z.ZodLiteral<"node">>;
13
+ name: z.ZodOptional<z.ZodString>;
14
+ parentId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
15
+ visible: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
16
+ camera: z.ZodOptional<z.ZodObject<{
17
+ position: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
18
+ target: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
19
+ mode: z.ZodDefault<z.ZodEnum<{
20
+ perspective: "perspective";
21
+ orthographic: "orthographic";
22
+ }>>;
23
+ fov: z.ZodOptional<z.ZodNumber>;
24
+ zoom: z.ZodOptional<z.ZodNumber>;
25
+ }, z.core.$strip>>;
26
+ metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
27
+ id: z.ZodDefault<z.ZodTemplateLiteral<`liquid-line_${string}`>>;
28
+ type: z.ZodDefault<z.ZodLiteral<"liquid-line">>;
29
+ path: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
30
+ diameter: z.ZodDefault<z.ZodNumber>;
31
+ }, z.core.$strip>;
32
+ export type LiquidLineNode = z.infer<typeof LiquidLineNode>;
33
+ export type LiquidLineNodeId = LiquidLineNode['id'];
34
+ //# sourceMappingURL=liquid-line.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liquid-line.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/liquid-line.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;iBAa1B,CAAA;AACD,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA;AAC3D,MAAM,MAAM,gBAAgB,GAAG,cAAc,CAAC,IAAI,CAAC,CAAA"}
@@ -0,0 +1,24 @@
1
+ import dedent from 'dedent';
2
+ import { z } from 'zod';
3
+ import { BaseNode, nodeType, objectId } from '../base';
4
+ /**
5
+ * Standalone refrigerant liquid line — the thin bare-copper line that carries
6
+ * warm liquid out to the indoor coil. It is the line that used to be drawn as
7
+ * the lineset's second rail; broken out here as its own polyline run so it can
8
+ * be drawn on its own, including traced alongside an existing lineset.
9
+ *
10
+ * Path coordinates are level-local meters: [x, y, z] tuples, the same space as
11
+ * lineset and duct paths. Diameter is nominal copper OD in inches.
12
+ */
13
+ export const LiquidLineNode = BaseNode.extend({
14
+ id: objectId('liquid-line'),
15
+ type: nodeType('liquid-line'),
16
+ // Polyline path in level-local meters. Minimum two points (start, end).
17
+ path: z.array(z.tuple([z.number(), z.number(), z.number()])).min(2),
18
+ // Nominal copper OD in inches. Common residential sizes are 1/4"–3/8".
19
+ diameter: z.number().min(0.125).max(1).default(0.375),
20
+ }).describe(dedent `
21
+ Standalone refrigerant liquid line - a thin bare-copper polyline run.
22
+ - path: list of [x, y, z] points in level-local meters (min 2)
23
+ - diameter: nominal copper OD in inches (typ. 1/4"-3/8")
24
+ `);