@pascal-app/nodes 0.1.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 (408) hide show
  1. package/README.md +34 -0
  2. package/dist/building/definition.js +1 -1
  3. package/dist/cabinet/definition.d.ts.map +1 -1
  4. package/dist/cabinet/definition.js +809 -72
  5. package/dist/cabinet/geometry.d.ts.map +1 -1
  6. package/dist/cabinet/geometry.js +4 -0
  7. package/dist/cabinet/move-frame.js +3 -3
  8. package/dist/cabinet/panel.d.ts.map +1 -1
  9. package/dist/cabinet/panel.js +1 -0
  10. package/dist/cabinet/placement-snap.d.ts +8 -0
  11. package/dist/cabinet/placement-snap.d.ts.map +1 -0
  12. package/dist/cabinet/placement-snap.js +19 -0
  13. package/dist/cabinet/presets.js +8 -8
  14. package/dist/cabinet/quick-actions.d.ts.map +1 -1
  15. package/dist/cabinet/quick-actions.js +9 -3
  16. package/dist/cabinet/resize-limits.d.ts +11 -0
  17. package/dist/cabinet/resize-limits.d.ts.map +1 -0
  18. package/dist/cabinet/resize-limits.js +22 -0
  19. package/dist/cabinet/run-layout.d.ts +8 -2
  20. package/dist/cabinet/run-layout.d.ts.map +1 -1
  21. package/dist/cabinet/run-layout.js +59 -7
  22. package/dist/cabinet/run-ops.d.ts +44 -3
  23. package/dist/cabinet/run-ops.d.ts.map +1 -1
  24. package/dist/cabinet/run-ops.js +646 -110
  25. package/dist/cabinet/run-panel.d.ts +2 -1
  26. package/dist/cabinet/run-panel.d.ts.map +1 -1
  27. package/dist/cabinet/run-panel.js +38 -4
  28. package/dist/cabinet/stack-transitions.js +4 -4
  29. package/dist/cabinet/tool.d.ts.map +1 -1
  30. package/dist/cabinet/tool.js +95 -17
  31. package/dist/cabinet/wall-snap.d.ts.map +1 -1
  32. package/dist/cabinet/wall-snap.js +2 -6
  33. package/dist/ceiling/boundary-editor.d.ts.map +1 -1
  34. package/dist/ceiling/boundary-editor.js +2 -2
  35. package/dist/ceiling/definition.d.ts +1 -1
  36. package/dist/ceiling/definition.d.ts.map +1 -1
  37. package/dist/ceiling/definition.js +36 -5
  38. package/dist/ceiling/floorplan-affordances.d.ts +4 -4
  39. package/dist/ceiling/floorplan-move.d.ts +4 -4
  40. package/dist/ceiling/floorplan-move.d.ts.map +1 -1
  41. package/dist/ceiling/floorplan-move.js +5 -4
  42. package/dist/ceiling/hole-editor.d.ts.map +1 -1
  43. package/dist/ceiling/hole-editor.js +2 -2
  44. package/dist/ceiling/move-tool.d.ts.map +1 -1
  45. package/dist/ceiling/move-tool.js +4 -3
  46. package/dist/ceiling/panel.d.ts.map +1 -1
  47. package/dist/ceiling/panel.js +65 -3
  48. package/dist/ceiling/renderer.d.ts.map +1 -1
  49. package/dist/ceiling/renderer.js +6 -2
  50. package/dist/ceiling/tool.d.ts.map +1 -1
  51. package/dist/ceiling/tool.js +12 -1
  52. package/dist/chimney/definition.d.ts.map +1 -1
  53. package/dist/chimney/definition.js +1 -0
  54. package/dist/chimney/tool.d.ts.map +1 -1
  55. package/dist/chimney/tool.js +16 -1
  56. package/dist/column/definition.d.ts.map +1 -1
  57. package/dist/column/definition.js +14 -2
  58. package/dist/column/floorplan-affordances.d.ts.map +1 -1
  59. package/dist/column/floorplan-affordances.js +19 -14
  60. package/dist/column/floorplan-move.d.ts.map +1 -1
  61. package/dist/column/floorplan-move.js +7 -2
  62. package/dist/column/floorplan.d.ts +9 -1
  63. package/dist/column/floorplan.d.ts.map +1 -1
  64. package/dist/column/floorplan.js +59 -4
  65. package/dist/column/tool.d.ts.map +1 -1
  66. package/dist/column/tool.js +33 -7
  67. package/dist/construction-dimension/definition.d.ts +4 -0
  68. package/dist/construction-dimension/definition.d.ts.map +1 -0
  69. package/dist/construction-dimension/definition.js +83 -0
  70. package/dist/construction-dimension/drawing-coordination.d.ts +7 -0
  71. package/dist/construction-dimension/drawing-coordination.d.ts.map +1 -0
  72. package/dist/construction-dimension/drawing-coordination.js +54 -0
  73. package/dist/construction-dimension/floorplan-affordances.d.ts +4 -0
  74. package/dist/construction-dimension/floorplan-affordances.d.ts.map +1 -0
  75. package/dist/construction-dimension/floorplan-affordances.js +114 -0
  76. package/dist/construction-dimension/floorplan-tool.d.ts +21 -0
  77. package/dist/construction-dimension/floorplan-tool.d.ts.map +1 -0
  78. package/dist/construction-dimension/floorplan-tool.js +557 -0
  79. package/dist/construction-dimension/floorplan.d.ts +3 -0
  80. package/dist/construction-dimension/floorplan.d.ts.map +1 -0
  81. package/dist/construction-dimension/floorplan.js +457 -0
  82. package/dist/construction-dimension/geometry.d.ts +31 -0
  83. package/dist/construction-dimension/geometry.d.ts.map +1 -0
  84. package/dist/construction-dimension/geometry.js +144 -0
  85. package/dist/construction-dimension/index.d.ts +4 -0
  86. package/dist/construction-dimension/index.d.ts.map +1 -0
  87. package/dist/construction-dimension/index.js +3 -0
  88. package/dist/construction-dimension/panel.d.ts +2 -0
  89. package/dist/construction-dimension/panel.d.ts.map +1 -0
  90. package/dist/construction-dimension/panel.js +128 -0
  91. package/dist/construction-dimension/parametrics.d.ts +3 -0
  92. package/dist/construction-dimension/parametrics.d.ts.map +1 -0
  93. package/dist/construction-dimension/parametrics.js +4 -0
  94. package/dist/construction-dimension/schema.d.ts +2 -0
  95. package/dist/construction-dimension/schema.d.ts.map +1 -0
  96. package/dist/construction-dimension/schema.js +1 -0
  97. package/dist/door/contextual-dimensions.d.ts +3 -0
  98. package/dist/door/contextual-dimensions.d.ts.map +1 -0
  99. package/dist/door/contextual-dimensions.js +7 -0
  100. package/dist/door/definition.d.ts.map +1 -1
  101. package/dist/door/definition.js +13 -8
  102. package/dist/door/floorplan-affordances.d.ts +2 -5
  103. package/dist/door/floorplan-affordances.d.ts.map +1 -1
  104. package/dist/door/floorplan-affordances.js +9 -18
  105. package/dist/door/floorplan.d.ts +3 -4
  106. package/dist/door/floorplan.d.ts.map +1 -1
  107. package/dist/door/floorplan.js +88 -6
  108. package/dist/door/move-tool.d.ts.map +1 -1
  109. package/dist/door/move-tool.js +2 -2
  110. package/dist/door/panel.d.ts.map +1 -1
  111. package/dist/door/panel.js +3 -1
  112. package/dist/door/schema.d.ts +1 -1
  113. package/dist/door/schema.d.ts.map +1 -1
  114. package/dist/door/schema.js +1 -1
  115. package/dist/door/tool.d.ts.map +1 -1
  116. package/dist/door/tool.js +63 -6
  117. package/dist/dormer/definition.d.ts.map +1 -1
  118. package/dist/dormer/definition.js +1 -0
  119. package/dist/dormer/tool.d.ts.map +1 -1
  120. package/dist/dormer/tool.js +23 -1
  121. package/dist/duct-segment/tool.d.ts.map +1 -1
  122. package/dist/duct-segment/tool.js +20 -9
  123. package/dist/duct-terminal/tool.d.ts.map +1 -1
  124. package/dist/duct-terminal/tool.js +9 -6
  125. package/dist/elevator/floorplan-affordances.d.ts +2 -6
  126. package/dist/elevator/floorplan-affordances.d.ts.map +1 -1
  127. package/dist/elevator/floorplan-affordances.js +13 -12
  128. package/dist/fence/actions/move-endpoint.d.ts.map +1 -1
  129. package/dist/fence/actions/move-endpoint.js +29 -1
  130. package/dist/fence/definition.d.ts.map +1 -1
  131. package/dist/fence/definition.js +67 -14
  132. package/dist/fence/floorplan-affordances.d.ts.map +1 -1
  133. package/dist/fence/floorplan-affordances.js +48 -11
  134. package/dist/fence/floorplan-move.d.ts.map +1 -1
  135. package/dist/fence/floorplan-move.js +38 -3
  136. package/dist/fence/geometry.d.ts.map +1 -1
  137. package/dist/fence/geometry.js +9 -1
  138. package/dist/fence/lift.d.ts +15 -0
  139. package/dist/fence/lift.d.ts.map +1 -0
  140. package/dist/fence/lift.js +23 -0
  141. package/dist/fence/move-tool.d.ts.map +1 -1
  142. package/dist/fence/move-tool.js +25 -5
  143. package/dist/fence/system.d.ts +3 -0
  144. package/dist/fence/system.d.ts.map +1 -0
  145. package/dist/fence/system.js +41 -0
  146. package/dist/fence/tool.d.ts.map +1 -1
  147. package/dist/fence/tool.js +103 -32
  148. package/dist/hvac-equipment/tool.d.ts.map +1 -1
  149. package/dist/hvac-equipment/tool.js +8 -3
  150. package/dist/index.d.ts +2 -0
  151. package/dist/index.d.ts.map +1 -1
  152. package/dist/index.js +6 -0
  153. package/dist/item/definition.d.ts.map +1 -1
  154. package/dist/item/definition.js +7 -1
  155. package/dist/item/floorplan-move.d.ts.map +1 -1
  156. package/dist/item/floorplan-move.js +50 -43
  157. package/dist/item/floorplan.d.ts +1 -0
  158. package/dist/item/floorplan.d.ts.map +1 -1
  159. package/dist/item/floorplan.js +49 -0
  160. package/dist/item/renderer.d.ts +3 -0
  161. package/dist/item/renderer.d.ts.map +1 -1
  162. package/dist/item/renderer.js +96 -8
  163. package/dist/level/definition.d.ts.map +1 -1
  164. package/dist/level/definition.js +7 -3
  165. package/dist/lineset/tool.d.ts.map +1 -1
  166. package/dist/lineset/tool.js +5 -1
  167. package/dist/liquid-line/tool.d.ts.map +1 -1
  168. package/dist/liquid-line/tool.js +7 -1
  169. package/dist/measurement/definition.d.ts.map +1 -1
  170. package/dist/measurement/definition.js +5 -0
  171. package/dist/measurement/floorplan.d.ts.map +1 -1
  172. package/dist/measurement/floorplan.js +11 -10
  173. package/dist/measurement/index.d.ts +1 -1
  174. package/dist/measurement/index.d.ts.map +1 -1
  175. package/dist/measurement/index.js +1 -1
  176. package/dist/measurement/resolve.d.ts +5 -0
  177. package/dist/measurement/resolve.d.ts.map +1 -1
  178. package/dist/measurement/resolve.js +2 -2
  179. package/dist/measurement/surface-query.js +5 -5
  180. package/dist/measurement/tool.d.ts +6 -1
  181. package/dist/measurement/tool.d.ts.map +1 -1
  182. package/dist/measurement/tool.js +7 -11
  183. package/dist/pipe-segment/tool.d.ts.map +1 -1
  184. package/dist/pipe-segment/tool.js +22 -19
  185. package/dist/roof-segment/floorplan-affordances.d.ts.map +1 -1
  186. package/dist/roof-segment/floorplan-affordances.js +14 -8
  187. package/dist/shared/construction-dimension-standards.d.ts +34 -0
  188. package/dist/shared/construction-dimension-standards.d.ts.map +1 -0
  189. package/dist/shared/construction-dimension-standards.js +18 -0
  190. package/dist/shared/construction-length.d.ts +10 -0
  191. package/dist/shared/construction-length.d.ts.map +1 -0
  192. package/dist/shared/construction-length.js +57 -0
  193. package/dist/shared/dimension-string.d.ts +20 -0
  194. package/dist/shared/dimension-string.d.ts.map +1 -0
  195. package/dist/shared/dimension-string.js +19 -0
  196. package/dist/shared/draft-axis-guides.d.ts +36 -0
  197. package/dist/shared/draft-axis-guides.d.ts.map +1 -0
  198. package/dist/shared/draft-axis-guides.js +107 -0
  199. package/dist/shared/move-roof-tool.d.ts.map +1 -1
  200. package/dist/shared/move-roof-tool.js +17 -3
  201. package/dist/shared/opening-documentation-fields.d.ts +16 -0
  202. package/dist/shared/opening-documentation-fields.d.ts.map +1 -0
  203. package/dist/shared/opening-documentation-fields.js +54 -0
  204. package/dist/shared/opening-documentation.d.ts +47 -0
  205. package/dist/shared/opening-documentation.d.ts.map +1 -0
  206. package/dist/shared/opening-documentation.js +300 -0
  207. package/dist/shared/opening-guides-runtime.d.ts.map +1 -1
  208. package/dist/shared/opening-guides-runtime.js +3 -2
  209. package/dist/shared/opening-placement-dimensions.d.ts.map +1 -1
  210. package/dist/shared/opening-placement-dimensions.js +14 -5
  211. package/dist/shared/wall-opening-ceiling.d.ts +30 -0
  212. package/dist/shared/wall-opening-ceiling.d.ts.map +1 -0
  213. package/dist/shared/wall-opening-ceiling.js +29 -0
  214. package/dist/shelf/floorplan-affordances.d.ts.map +1 -1
  215. package/dist/shelf/floorplan-affordances.js +10 -5
  216. package/dist/shelf/floorplan-move.d.ts +2 -16
  217. package/dist/shelf/floorplan-move.d.ts.map +1 -1
  218. package/dist/shelf/floorplan-move.js +19 -40
  219. package/dist/shelf/tool.d.ts.map +1 -1
  220. package/dist/shelf/tool.js +8 -3
  221. package/dist/site/recessed-slab-ground-holes.d.ts.map +1 -1
  222. package/dist/site/recessed-slab-ground-holes.js +1 -4
  223. package/dist/site/renderer.d.ts.map +1 -1
  224. package/dist/site/renderer.js +118 -28
  225. package/dist/site/terrain-drape.d.ts +91 -0
  226. package/dist/site/terrain-drape.d.ts.map +1 -0
  227. package/dist/site/terrain-drape.js +205 -0
  228. package/dist/site/terrain-geometry.d.ts +131 -0
  229. package/dist/site/terrain-geometry.d.ts.map +1 -0
  230. package/dist/site/terrain-geometry.js +259 -0
  231. package/dist/site/terrain-mesh.d.ts +49 -0
  232. package/dist/site/terrain-mesh.d.ts.map +1 -0
  233. package/dist/site/terrain-mesh.js +122 -0
  234. package/dist/site/terrain-renderer.d.ts +28 -0
  235. package/dist/site/terrain-renderer.d.ts.map +1 -0
  236. package/dist/site/terrain-renderer.js +69 -0
  237. package/dist/skylight/definition.d.ts.map +1 -1
  238. package/dist/skylight/definition.js +1 -0
  239. package/dist/skylight/tool.d.ts.map +1 -1
  240. package/dist/skylight/tool.js +16 -1
  241. package/dist/slab/definition.d.ts.map +1 -1
  242. package/dist/slab/definition.js +87 -10
  243. package/dist/slab/elevation-limit.d.ts +43 -0
  244. package/dist/slab/elevation-limit.d.ts.map +1 -0
  245. package/dist/slab/elevation-limit.js +124 -0
  246. package/dist/slab/floorplan-affordances.d.ts +16 -0
  247. package/dist/slab/floorplan-affordances.d.ts.map +1 -1
  248. package/dist/slab/geometry.d.ts.map +1 -1
  249. package/dist/slab/geometry.js +98 -5
  250. package/dist/slab/panel.d.ts.map +1 -1
  251. package/dist/slab/panel.js +82 -4
  252. package/dist/slab/parametrics.d.ts +1 -1
  253. package/dist/slab/parametrics.d.ts.map +1 -1
  254. package/dist/slab/parametrics.js +13 -1
  255. package/dist/slab/placement-ownership.d.ts +3 -0
  256. package/dist/slab/placement-ownership.d.ts.map +1 -0
  257. package/dist/slab/placement-ownership.js +3 -0
  258. package/dist/slab/quick-measurement.d.ts.map +1 -1
  259. package/dist/slab/quick-measurement.js +3 -2
  260. package/dist/slab/system.d.ts.map +1 -1
  261. package/dist/slab/system.js +14 -4
  262. package/dist/slab/tool.d.ts.map +1 -1
  263. package/dist/slab/tool.js +81 -23
  264. package/dist/solar-panel/definition.d.ts.map +1 -1
  265. package/dist/solar-panel/definition.js +1 -0
  266. package/dist/solar-panel/tool.d.ts.map +1 -1
  267. package/dist/solar-panel/tool.js +17 -1
  268. package/dist/spawn/definition.d.ts.map +1 -1
  269. package/dist/spawn/definition.js +1 -0
  270. package/dist/spawn/floorplan-affordances.d.ts.map +1 -1
  271. package/dist/spawn/floorplan-affordances.js +7 -4
  272. package/dist/spawn/floorplan-move.d.ts.map +1 -1
  273. package/dist/spawn/floorplan-move.js +8 -6
  274. package/dist/spawn/renderer.d.ts +4 -0
  275. package/dist/spawn/renderer.d.ts.map +1 -1
  276. package/dist/spawn/renderer.js +32 -18
  277. package/dist/spawn/tool.d.ts +2 -2
  278. package/dist/spawn/tool.d.ts.map +1 -1
  279. package/dist/spawn/tool.js +78 -11
  280. package/dist/stair/definition.d.ts.map +1 -1
  281. package/dist/stair/definition.js +15 -7
  282. package/dist/stair/destination.d.ts +16 -0
  283. package/dist/stair/destination.d.ts.map +1 -0
  284. package/dist/stair/destination.js +24 -0
  285. package/dist/stair/documentation.d.ts +8 -0
  286. package/dist/stair/documentation.d.ts.map +1 -0
  287. package/dist/stair/documentation.js +245 -0
  288. package/dist/stair/floor-stack.d.ts.map +1 -1
  289. package/dist/stair/floor-stack.js +38 -0
  290. package/dist/stair/floorplan-affordances.d.ts.map +1 -1
  291. package/dist/stair/floorplan-affordances.js +28 -9
  292. package/dist/stair/floorplan-move.d.ts +3 -5
  293. package/dist/stair/floorplan-move.d.ts.map +1 -1
  294. package/dist/stair/floorplan-move.js +14 -16
  295. package/dist/stair/floorplan.d.ts.map +1 -1
  296. package/dist/stair/floorplan.js +27 -14
  297. package/dist/stair/panel.d.ts.map +1 -1
  298. package/dist/stair/panel.js +35 -2
  299. package/dist/stair/renderer.d.ts.map +1 -1
  300. package/dist/stair/renderer.js +4 -3
  301. package/dist/structural-grid/coordination.d.ts +16 -0
  302. package/dist/structural-grid/coordination.d.ts.map +1 -0
  303. package/dist/structural-grid/coordination.js +105 -0
  304. package/dist/structural-grid/definition.d.ts +4 -0
  305. package/dist/structural-grid/definition.d.ts.map +1 -0
  306. package/dist/structural-grid/definition.js +51 -0
  307. package/dist/structural-grid/floorplan-tool.d.ts +16 -0
  308. package/dist/structural-grid/floorplan-tool.d.ts.map +1 -0
  309. package/dist/structural-grid/floorplan-tool.js +183 -0
  310. package/dist/structural-grid/floorplan.d.ts +3 -0
  311. package/dist/structural-grid/floorplan.d.ts.map +1 -0
  312. package/dist/structural-grid/floorplan.js +61 -0
  313. package/dist/structural-grid/index.d.ts +2 -0
  314. package/dist/structural-grid/index.d.ts.map +1 -0
  315. package/dist/structural-grid/index.js +1 -0
  316. package/dist/structural-grid/schema.d.ts +2 -0
  317. package/dist/structural-grid/schema.d.ts.map +1 -0
  318. package/dist/structural-grid/schema.js +1 -0
  319. package/dist/wall/construction-dimensions.d.ts +32 -0
  320. package/dist/wall/construction-dimensions.d.ts.map +1 -0
  321. package/dist/wall/construction-dimensions.js +1031 -0
  322. package/dist/wall/contextual-dimensions.d.ts +13 -0
  323. package/dist/wall/contextual-dimensions.d.ts.map +1 -0
  324. package/dist/wall/contextual-dimensions.js +221 -0
  325. package/dist/wall/definition.d.ts.map +1 -1
  326. package/dist/wall/definition.js +20 -1
  327. package/dist/wall/floorplan-affordances.d.ts.map +1 -1
  328. package/dist/wall/floorplan-affordances.js +23 -8
  329. package/dist/wall/floorplan-overrides.d.ts +9 -6
  330. package/dist/wall/floorplan-overrides.d.ts.map +1 -1
  331. package/dist/wall/floorplan-overrides.js +20 -11
  332. package/dist/wall/floorplan.d.ts +12 -3
  333. package/dist/wall/floorplan.d.ts.map +1 -1
  334. package/dist/wall/floorplan.js +121 -79
  335. package/dist/wall/measurement.d.ts.map +1 -1
  336. package/dist/wall/measurement.js +17 -4
  337. package/dist/wall/move-endpoint-tool.d.ts.map +1 -1
  338. package/dist/wall/move-endpoint-tool.js +74 -27
  339. package/dist/wall/move-shared.d.ts.map +1 -1
  340. package/dist/wall/move-shared.js +3 -2
  341. package/dist/wall/move-tool.d.ts.map +1 -1
  342. package/dist/wall/move-tool.js +15 -3
  343. package/dist/wall/paint.d.ts.map +1 -1
  344. package/dist/wall/paint.js +10 -6
  345. package/dist/wall/panel.d.ts.map +1 -1
  346. package/dist/wall/panel.js +32 -5
  347. package/dist/wall/parametrics.d.ts.map +1 -1
  348. package/dist/wall/parametrics.js +2 -0
  349. package/dist/wall/preview.d.ts +8 -0
  350. package/dist/wall/preview.d.ts.map +1 -0
  351. package/dist/wall/preview.js +39 -0
  352. package/dist/wall/quick-measurement.d.ts.map +1 -1
  353. package/dist/wall/quick-measurement.js +3 -2
  354. package/dist/wall/renderer.d.ts.map +1 -1
  355. package/dist/wall/renderer.js +7 -5
  356. package/dist/wall/system.d.ts +1 -1
  357. package/dist/wall/system.d.ts.map +1 -1
  358. package/dist/wall/system.js +37 -2
  359. package/dist/wall/tool.d.ts.map +1 -1
  360. package/dist/wall/tool.js +148 -96
  361. package/dist/wall/treatment-level-data.d.ts +14 -0
  362. package/dist/wall/treatment-level-data.d.ts.map +1 -0
  363. package/dist/wall/treatment-level-data.js +31 -0
  364. package/dist/wall/treatments.d.ts +8 -2
  365. package/dist/wall/treatments.d.ts.map +1 -1
  366. package/dist/wall/treatments.js +58 -15
  367. package/dist/window/contextual-dimensions.d.ts +3 -0
  368. package/dist/window/contextual-dimensions.d.ts.map +1 -0
  369. package/dist/window/contextual-dimensions.js +7 -0
  370. package/dist/window/definition.d.ts.map +1 -1
  371. package/dist/window/definition.js +15 -10
  372. package/dist/window/floorplan-affordances.d.ts +2 -5
  373. package/dist/window/floorplan-affordances.d.ts.map +1 -1
  374. package/dist/window/floorplan-affordances.js +9 -15
  375. package/dist/window/floorplan-move.d.ts.map +1 -1
  376. package/dist/window/floorplan-move.js +1 -1
  377. package/dist/window/floorplan.d.ts.map +1 -1
  378. package/dist/window/floorplan.js +7 -1
  379. package/dist/window/move-tool.d.ts.map +1 -1
  380. package/dist/window/move-tool.js +3 -3
  381. package/dist/window/panel.d.ts.map +1 -1
  382. package/dist/window/panel.js +4 -1
  383. package/dist/window/schema.d.ts +1 -1
  384. package/dist/window/schema.d.ts.map +1 -1
  385. package/dist/window/schema.js +1 -1
  386. package/dist/window/tool.d.ts.map +1 -1
  387. package/dist/window/tool.js +64 -7
  388. package/dist/window/window-math.d.ts +7 -3
  389. package/dist/window/window-math.d.ts.map +1 -1
  390. package/dist/window/window-math.js +8 -3
  391. package/dist/zone/contextual-dimensions.d.ts +3 -0
  392. package/dist/zone/contextual-dimensions.d.ts.map +1 -0
  393. package/dist/zone/contextual-dimensions.js +43 -0
  394. package/dist/zone/definition.d.ts.map +1 -1
  395. package/dist/zone/definition.js +9 -1
  396. package/dist/zone/floorplan-affordances.d.ts +36 -0
  397. package/dist/zone/floorplan-affordances.d.ts.map +1 -1
  398. package/dist/zone/floorplan.d.ts.map +1 -1
  399. package/dist/zone/floorplan.js +59 -3
  400. package/dist/zone/quantities-panel.d.ts.map +1 -1
  401. package/dist/zone/quantities-panel.js +48 -4
  402. package/dist/zone/room-clear-dimensions.d.ts +3 -0
  403. package/dist/zone/room-clear-dimensions.d.ts.map +1 -0
  404. package/dist/zone/room-clear-dimensions.js +406 -0
  405. package/dist/zone/room-documentation.d.ts +11 -0
  406. package/dist/zone/room-documentation.d.ts.map +1 -0
  407. package/dist/zone/room-documentation.js +97 -0
  408. package/package.json +7 -7
@@ -1,8 +1,10 @@
1
1
  import { getFenceControlHandle, isSplineFence, } from '@pascal-app/core';
2
+ import { clearStructuralElevationGuide, publishStructuralElevationGuide, resolveStructuralElevationSnap, } from '@pascal-app/editor';
2
3
  import { buildFenceFloorplan } from './floorplan';
3
4
  import { fenceControlPointAffordance, fenceCurveAffordance, fenceMoveEndpointAffordance, fenceTangentAffordance, } from './floorplan-affordances';
4
5
  import { fenceFloorplanMoveTarget } from './floorplan-move';
5
6
  import { buildFenceGeometry } from './geometry';
7
+ import { resolveFenceLiftElevation } from './lift';
6
8
  import { fencePaint } from './paint';
7
9
  import { fenceParametrics } from './parametrics';
8
10
  import { FenceNode } from './schema';
@@ -13,6 +15,9 @@ const SIDE_HANDLE_TOP_INSET = 0.08;
13
15
  const SIDE_HANDLE_MIN_HEIGHT = 0.4;
14
16
  const HEIGHT_HANDLE_OFFSET = 0.45;
15
17
  const MIN_FENCE_HEIGHT = 0.3;
18
+ function fenceBaseElevation(n, sceneApi) {
19
+ return resolveFenceLiftElevation(n, (id) => sceneApi?.get(id));
20
+ }
16
21
  function fenceMidpointFrame(n) {
17
22
  const dx = n.end[0] - n.start[0];
18
23
  const dz = n.end[1] - n.start[1];
@@ -24,6 +29,14 @@ function fenceMidpointFrame(n) {
24
29
  normalZ: dx / len,
25
30
  };
26
31
  }
32
+ function fenceElevationGuideSource(n) {
33
+ const { midX, midZ } = fenceMidpointFrame(n);
34
+ return {
35
+ nodeId: n.id,
36
+ levelId: n.parentId,
37
+ anchor: [midX, midZ],
38
+ };
39
+ }
27
40
  // Side-move arrows: click to hand the fence to its move tool. Same shape
28
41
  // as wall — front + back faces, positioned past the fence thickness near
29
42
  // the top so they don't compete with endpoint pickers in the floating
@@ -34,11 +47,12 @@ function fenceSideMoveHandle(side) {
34
47
  kind: 'tap-action',
35
48
  onActivate: (node, _scene, editor) => editor.engageMove(node),
36
49
  placement: {
37
- position: (n) => {
50
+ position: (n, sceneApi) => {
38
51
  const { midX, midZ, normalX, normalZ } = fenceMidpointFrame(n);
39
52
  const offset = Math.max((n.thickness ?? 0.1) / 2 + SIDE_HANDLE_OFFSET, SIDE_HANDLE_MIN_OFFSET);
40
53
  const h = n.height ?? 1.8;
41
- const handleY = Math.max(h - SIDE_HANDLE_TOP_INSET, SIDE_HANDLE_MIN_HEIGHT);
54
+ const handleY = fenceBaseElevation(n, sceneApi) +
55
+ Math.max(h - SIDE_HANDLE_TOP_INSET, SIDE_HANDLE_MIN_HEIGHT);
42
56
  return [midX + sign * normalX * offset, handleY, midZ + sign * normalZ * offset];
43
57
  },
44
58
  rotationY: (n) => {
@@ -69,9 +83,13 @@ function fenceHeightHandle() {
69
83
  currentValue: (n) => n.height ?? 1.8,
70
84
  apply: (_n, newHeight) => ({ height: newHeight }),
71
85
  placement: {
72
- position: (n) => {
86
+ position: (n, sceneApi) => {
73
87
  const { midX, midZ } = fenceMidpointFrame(n);
74
- return [midX, (n.height ?? 1.8) + HEIGHT_HANDLE_OFFSET, midZ];
88
+ return [
89
+ midX,
90
+ fenceBaseElevation(n, sceneApi) + (n.height ?? 1.8) + HEIGHT_HANDLE_OFFSET,
91
+ midZ,
92
+ ];
75
93
  },
76
94
  rotationY: (n) => {
77
95
  const { normalX, normalZ } = fenceMidpointFrame(n);
@@ -80,6 +98,32 @@ function fenceHeightHandle() {
80
98
  },
81
99
  };
82
100
  }
101
+ function fenceElevationHandle(currentBase) {
102
+ return {
103
+ kind: 'linear-resize',
104
+ axis: 'y',
105
+ anchor: 'min',
106
+ shape: 'tracker',
107
+ gridSnap: true,
108
+ currentValue: () => currentBase,
109
+ magneticSnap: (n, newValue, sceneApi) => resolveStructuralElevationSnap(fenceElevationGuideSource(n), newValue, sceneApi.nodes()),
110
+ onDrag: (n, sceneApi) => publishStructuralElevationGuide(fenceElevationGuideSource(n), fenceBaseElevation(n, sceneApi), sceneApi.nodes()),
111
+ onDragEnd: (n) => clearStructuralElevationGuide(n.id),
112
+ apply: (initial, newBase, sceneApi) => {
113
+ const supportBase = resolveFenceLiftElevation({ ...initial, supportOffset: undefined }, (id) => sceneApi.get(id));
114
+ const nextOffset = newBase - supportBase;
115
+ return {
116
+ supportOffset: Math.abs(nextOffset) < 1e-6 ? undefined : nextOffset,
117
+ };
118
+ },
119
+ placement: {
120
+ position: (n, sceneApi) => {
121
+ const { midX, midZ } = fenceMidpointFrame(n);
122
+ return [midX, fenceBaseElevation(n, sceneApi), midZ];
123
+ },
124
+ },
125
+ };
126
+ }
83
127
  // Corner picker — dashed vertical leader + billboarded hex disc at the
84
128
  // endpoint. Tap engages the endpoint-move flow (sister to the wall
85
129
  // pickers). nodeHeight controls the leader's vertical reach so the
@@ -92,9 +136,9 @@ function fenceCornerPicker(endpoint) {
92
136
  nodeHeight: (n) => n.height ?? 1.8,
93
137
  onActivate: (node, _scene, editor) => editor.engageEndpointMove(node, endpoint),
94
138
  placement: {
95
- position: (n) => {
139
+ position: (n, sceneApi) => {
96
140
  const corner = endpoint === 'start' ? n.start : n.end;
97
- return [corner[0], 0, corner[1]];
141
+ return [corner[0], fenceBaseElevation(n, sceneApi), corner[1]];
98
142
  },
99
143
  },
100
144
  };
@@ -108,9 +152,9 @@ function fenceControlPointPicker(index) {
108
152
  nodeHeight: (n) => n.height ?? 1.8,
109
153
  onActivate: (node, _scene, editor) => editor.engageControlPointMove(node, index),
110
154
  placement: {
111
- position: (n) => {
155
+ position: (n, sceneApi) => {
112
156
  const point = n.path?.[index] ?? n.start;
113
- return [point[0], 0, point[1]];
157
+ return [point[0], fenceBaseElevation(n, sceneApi), point[1]];
114
158
  },
115
159
  },
116
160
  };
@@ -125,23 +169,26 @@ function fenceTangentPicker(index, side) {
125
169
  nodeHeight: (n) => (n.height ?? 1.8) * 0.6,
126
170
  onActivate: (node, _scene, editor) => editor.engageTangentMove(node, index, side),
127
171
  placement: {
128
- position: (n) => {
172
+ position: (n, sceneApi) => {
129
173
  const point = n.path?.[index] ?? n.start;
174
+ const baseElevation = fenceBaseElevation(n, sceneApi);
130
175
  if (!n.path)
131
- return [point[0], 0, point[1]];
176
+ return [point[0], baseElevation, point[1]];
132
177
  const handle = getFenceControlHandle(n.path, n.tangents, index);
133
178
  return [
134
179
  point[0] + sign * handle.x * TANGENT_HANDLE_ARM_SCALE,
135
- 0,
180
+ baseElevation,
136
181
  point[1] + sign * handle.y * TANGENT_HANDLE_ARM_SCALE,
137
182
  ];
138
183
  },
139
184
  },
140
185
  };
141
186
  }
142
- const fenceHandles = (node) => {
187
+ const fenceHandles = (node, sceneApi) => {
188
+ const elevationHandle = fenceElevationHandle(fenceBaseElevation(node, sceneApi));
143
189
  if (isSplineFence(node) && node.path) {
144
190
  return [
191
+ elevationHandle,
145
192
  fenceHeightHandle(),
146
193
  ...node.path.flatMap((_, index) => [
147
194
  fenceControlPointPicker(index),
@@ -153,6 +200,7 @@ const fenceHandles = (node) => {
153
200
  return [
154
201
  fenceSideMoveHandle('front'),
155
202
  fenceSideMoveHandle('back'),
203
+ elevationHandle,
156
204
  fenceHeightHandle(),
157
205
  fenceCornerPicker('start'),
158
206
  fenceCornerPicker('end'),
@@ -174,7 +222,7 @@ const fenceHandles = (node) => {
174
222
  export const fenceDefinition = {
175
223
  kind: 'fence',
176
224
  snapProfile: 'structural',
177
- schemaVersion: 1,
225
+ schemaVersion: 2,
178
226
  schema: FenceNode,
179
227
  category: 'structure',
180
228
  surfaceRole: 'wall',
@@ -226,8 +274,13 @@ export const fenceDefinition = {
226
274
  tool: () => import('./tool'),
227
275
  // Stage B: pure geometry function. Generic <GeometrySystem> rebuilds
228
276
  // on dirtyNodes; <ParametricNodeRenderer> mounts the empty group.
229
- // `renderer` + `system` fields dropped along with their files.
230
277
  geometry: buildFenceGeometry,
278
+ // Dependency tracker only — a hosted railing (`supportSlabId`) renders at
279
+ // its slab's elevation, so host elevation edits must re-dirty the fence.
280
+ system: {
281
+ module: () => import('./system'),
282
+ priority: 4,
283
+ },
231
284
  // Stage C: floor-plan rendering. FloorplanRegistryLayer iterates kinds
232
285
  // with `floorplan` set and renders via FloorplanGeometryRenderer.
233
286
  // Legacy `floorplanFenceEntries` short-circuits to [] when fence is
@@ -1 +1 @@
1
- {"version":3,"file":"floorplan-affordances.d.ts","sourceRoot":"","sources":["../../src/fence/floorplan-affordances.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,mBAAmB,EAQzB,MAAM,kBAAkB,CAAA;AAoFzB;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,EAAE,mBAAmB,CAAC,SAAS,CAsC/D,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,EAAE,mBAAmB,CAAC,SAAS,CAqCtE,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,EAAE,mBAAmB,CAAC,SAAS,CAoDjE,CAAA;AAED,eAAO,MAAM,2BAA2B,EAAE,mBAAmB,CAAC,SAAS,CAkFtE,CAAA"}
1
+ {"version":3,"file":"floorplan-affordances.d.ts","sourceRoot":"","sources":["../../src/fence/floorplan-affordances.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,mBAAmB,EASzB,MAAM,kBAAkB,CAAA;AAoFzB;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,EAAE,mBAAmB,CAAC,SAAS,CAsC/D,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,EAAE,mBAAmB,CAAC,SAAS,CAqCtE,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,EAAE,mBAAmB,CAAC,SAAS,CAoDjE,CAAA;AAED,eAAO,MAAM,2BAA2B,EAAE,mBAAmB,CAAC,SAAS,CA4HtE,CAAA"}
@@ -1,4 +1,4 @@
1
- import { getMaxWallCurveOffset, getWallChordFrame, normalizeWallCurveOffset, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
1
+ import { getMaxWallCurveOffset, getWallChordFrame, normalizeWallCurveOffset, resolveFenceSupportSlabPatch, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
2
2
  import { alignFloorplanDraftPoint, getSegmentGridStep, isAlignmentGuideActive, isAngleSnapActive, isGridSnapActive, isMagneticSnapActive, isSegmentLongEnough, snapBuildingLocalToWorldGrid, snapFenceDraftPoint, snapScalarToGrid, useAlignmentGuides, } from '@pascal-app/editor';
3
3
  /**
4
4
  * Floor-plan 2D drag affordances for fence — sister to the 3D
@@ -204,6 +204,9 @@ export const fenceMoveEndpointAffordance = {
204
204
  const { walls, fences } = collectLevel(nodes, parentId);
205
205
  const linkedOriginals = collectLinkedFences(fences, node.id, originalMovingPoint);
206
206
  const affectedIds = [node.id, ...linkedOriginals.map((l) => l.id)];
207
+ let lastPatches = new Map();
208
+ let lastStart = originalStart;
209
+ let lastEnd = originalEnd;
207
210
  return {
208
211
  affectedIds,
209
212
  apply({ planPoint, modifiers }) {
@@ -249,22 +252,56 @@ export const fenceMoveEndpointAffordance = {
249
252
  start: pointsNearlyEqual(l.start, originalMovingPoint) ? aligned : l.start,
250
253
  end: pointsNearlyEqual(l.end, originalMovingPoint) ? aligned : l.end,
251
254
  }));
252
- useScene.getState().updateNodes([
253
- { id: node.id, data: { start: nextStart, end: nextEnd } },
254
- ...linkedUpdates.map((u) => ({
255
- id: u.id,
256
- data: { start: u.start, end: u.end },
257
- })),
255
+ lastStart = nextStart;
256
+ lastEnd = nextEnd;
257
+ const nextPatches = new Map([
258
+ [node.id, { start: nextStart, end: nextEnd }],
259
+ ...linkedUpdates.map((update) => [update.id, { start: update.start, end: update.end }]),
258
260
  ]);
261
+ // Re-elect the slab lift host as the endpoint drags (uncapped max
262
+ // election — 2D has no camera ray). Fences run no per-frame
263
+ // election: `supportSlabId` IS the lift.
264
+ const patchedNodes = { ...sceneNodes };
265
+ for (const [id, patch] of nextPatches) {
266
+ patchedNodes[id] = { ...patchedNodes[id], ...patch };
267
+ }
268
+ for (const id of nextPatches.keys()) {
269
+ const fence = patchedNodes[id];
270
+ if (fence?.type !== 'fence')
271
+ continue;
272
+ const patch = resolveFenceSupportSlabPatch(fence, patchedNodes);
273
+ if (patch.supportSlabId !== fence.supportSlabId) {
274
+ nextPatches.set(id, { ...nextPatches.get(id), ...patch });
275
+ }
276
+ }
277
+ const overrides = useLiveNodeOverrides.getState();
278
+ const scene = useScene.getState();
279
+ for (const linked of linkedOriginals) {
280
+ if (!nextPatches.has(linked.id)) {
281
+ overrides.clear(linked.id);
282
+ scene.markDirty(linked.id);
283
+ }
284
+ }
285
+ for (const [id, patch] of nextPatches) {
286
+ overrides.set(id, patch);
287
+ scene.markDirty(id);
288
+ }
289
+ lastPatches = nextPatches;
259
290
  },
260
291
  canCommit() {
261
292
  // Pointer-up always runs canCommit — drop the alignment guide here
262
293
  // so it doesn't linger after a commit / reject.
263
294
  useAlignmentGuides.getState().clear();
264
- const finalFence = useScene.getState().nodes[node.id];
265
- return (!!finalFence &&
266
- finalFence.type === 'fence' &&
267
- isSegmentLongEnough(finalFence.start, finalFence.end));
295
+ return isSegmentLongEnough(lastStart, lastEnd);
296
+ },
297
+ commit() {
298
+ useScene.getState().updateNodes(Array.from(lastPatches, ([id, data]) => ({
299
+ id,
300
+ data,
301
+ })));
302
+ const overrides = useLiveNodeOverrides.getState();
303
+ for (const id of affectedIds)
304
+ overrides.clear(id);
268
305
  },
269
306
  };
270
307
  },
@@ -1 +1 @@
1
- {"version":3,"file":"floorplan-move.d.ts","sourceRoot":"","sources":["../../src/fence/floorplan-move.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,mBAAmB,EAIzB,MAAM,kBAAkB,CAAA;AAuDzB;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,EAAE,mBAAmB,CAAC,SAAS,CAiJnE,CAAA"}
1
+ {"version":3,"file":"floorplan-move.d.ts","sourceRoot":"","sources":["../../src/fence/floorplan-move.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,mBAAmB,EAKzB,MAAM,kBAAkB,CAAA;AAuDzB;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,EAAE,mBAAmB,CAAC,SAAS,CA4LnE,CAAA"}
@@ -1,4 +1,4 @@
1
- import { useLiveNodeOverrides, useScene, } from '@pascal-app/core';
1
+ import { resolveFenceSupportSlabPatch, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
2
2
  import { getSegmentGridStep, isGridSnapActive, isSegmentLongEnough, snapPointToGrid, } from '@pascal-app/editor';
3
3
  import { useViewer } from '@pascal-app/viewer';
4
4
  function pointsEqual(a, b) {
@@ -125,6 +125,27 @@ export const fenceFloorplanMoveTarget = ({ node }) => {
125
125
  // tracked change. Drop the override AFTER the scene write so
126
126
  // mid-commit reads still see the new position (override wins until
127
127
  // cleared; scene wins after).
128
+ // The re-elected slab lift host rides in the same write (uncapped max
129
+ // election — 2D has no camera ray): a fence moved onto / off an
130
+ // elevated deck must land on the right surface, since fences run no
131
+ // per-frame election (`supportSlabId` IS the lift). One updateNodes
132
+ // keeps the whole move a single tracked change. Election runs on the
133
+ // committed endpoints against the pre-write store (the patch only
134
+ // reads the parent level + the slab grid).
135
+ const baselineNodes = useScene.getState().nodes;
136
+ const supportFor = (start, end, path, id) => {
137
+ const fence = baselineNodes[id];
138
+ return fence?.type === 'fence'
139
+ ? resolveFenceSupportSlabPatch({
140
+ start,
141
+ end,
142
+ path,
143
+ curveOffset: fence.curveOffset,
144
+ thickness: fence.thickness,
145
+ parentId: fence.parentId,
146
+ }, baselineNodes)
147
+ : {};
148
+ };
128
149
  const fenceUpdate = isNew
129
150
  ? {
130
151
  id: fenceId,
@@ -133,9 +154,18 @@ export const fenceFloorplanMoveTarget = ({ node }) => {
133
154
  end: lastNextEnd,
134
155
  path: lastNextPath,
135
156
  metadata: { ...originalMetadata, isNew: false },
157
+ ...supportFor(lastNextStart, lastNextEnd, lastNextPath, fenceId),
136
158
  },
137
159
  }
138
- : { id: fenceId, data: { start: lastNextStart, end: lastNextEnd, path: lastNextPath } };
160
+ : {
161
+ id: fenceId,
162
+ data: {
163
+ start: lastNextStart,
164
+ end: lastNextEnd,
165
+ path: lastNextPath,
166
+ ...supportFor(lastNextStart, lastNextEnd, lastNextPath, fenceId),
167
+ },
168
+ };
139
169
  const linkedUpdates = linkedOriginals.map((l) => ({
140
170
  id: l.id,
141
171
  ...projectLinked(l, lastNextStart, lastNextEnd, lastDelta[0], lastDelta[1]),
@@ -144,7 +174,12 @@ export const fenceFloorplanMoveTarget = ({ node }) => {
144
174
  fenceUpdate,
145
175
  ...linkedUpdates.map((u) => ({
146
176
  id: u.id,
147
- data: { start: u.start, end: u.end, path: u.path },
177
+ data: {
178
+ start: u.start,
179
+ end: u.end,
180
+ path: u.path,
181
+ ...supportFor(u.start, u.end, u.path, u.id),
182
+ },
148
183
  })),
149
184
  ]);
150
185
  const overrides = useLiveNodeOverrides.getState();
@@ -1 +1 @@
1
- {"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../src/fence/geometry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAA0B,MAAM,kBAAkB,CAAA;AAC/E,OAAO,EAEL,KAAK,WAAW,EAKhB,KAAK,aAAa,EAGnB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAa,KAAK,EAAqC,MAAM,OAAO,CAAA;AAC3E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAwFzC,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,EACf,GAAG,CAAC,EAAE,eAAe,EACrB,OAAO,GAAE,aAA0B,EACnC,QAAQ,UAAO,EACf,WAAW,GAAE,WAAoB,EACjC,UAAU,CAAC,EAAE,MAAM,GAClB,KAAK,CAwBP"}
1
+ {"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../src/fence/geometry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,eAAe,EAA0B,MAAM,kBAAkB,CAAA;AAC/F,OAAO,EAEL,KAAK,WAAW,EAKhB,KAAK,aAAa,EAGnB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAa,KAAK,EAAqC,MAAM,OAAO,CAAA;AAE3E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAwFzC,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,EACf,GAAG,CAAC,EAAE,eAAe,EACrB,OAAO,GAAE,aAA0B,EACnC,QAAQ,UAAO,EACf,WAAW,GAAE,WAAoB,EACjC,UAAU,CAAC,EAAE,MAAM,GAClB,KAAK,CAgCP"}
@@ -1,6 +1,7 @@
1
1
  import { getMaterialPresetByRef } from '@pascal-app/core';
2
2
  import { applyMaterialPresetToMaterials, createDefaultMaterial, createMaterial, createSurfaceRoleMaterial, generateFenceSlotGeometries, resolveMaterialRef, resolveSlotDefaultMaterial, } from '@pascal-app/viewer';
3
3
  import { FrontSide, Group, Mesh } from 'three';
4
+ import { resolveFenceLiftElevation } from './lift';
4
5
  import { FENCE_SLOT_DEFAULTS } from './slots';
5
6
  const FENCE_SLOT_ORDER = ['posts', 'infill', 'base', 'rail'];
6
7
  const fenceMaterialCache = new Map();
@@ -50,6 +51,13 @@ function getLegacyFenceMaterial(node, shading) {
50
51
  export function buildFenceGeometry(node, ctx, shading = 'rendered', textures = true, colorPreset = 'clay', sceneTheme) {
51
52
  const group = new Group();
52
53
  const geometries = generateFenceSlotGeometries(node);
54
+ // A hosted railing (`supportSlabId`) stands on its slab's walking surface.
55
+ // The builder emits local-space children, so the lift lives on an inner
56
+ // group rather than the registered (React-transformed) root.
57
+ const lift = ctx ? resolveFenceLiftElevation(node, (id) => ctx.resolve(id)) : 0;
58
+ const meshParent = new Group();
59
+ meshParent.position.y = lift;
60
+ group.add(meshParent);
53
61
  for (const slotId of FENCE_SLOT_ORDER) {
54
62
  const geometry = geometries[slotId];
55
63
  if (geometry.getAttribute('position') === undefined)
@@ -59,7 +67,7 @@ export function buildFenceGeometry(node, ctx, shading = 'rendered', textures = t
59
67
  mesh.castShadow = true;
60
68
  mesh.receiveShadow = true;
61
69
  mesh.userData.slotId = slotId;
62
- group.add(mesh);
70
+ meshParent.add(mesh);
63
71
  }
64
72
  return group;
65
73
  }
@@ -0,0 +1,15 @@
1
+ import type { AnyNode } from '@pascal-app/core';
2
+ import type { FenceNode } from './schema';
3
+ /**
4
+ * Elevation (meters above the level plane) a hosted fence stands at.
5
+ *
6
+ * A fence carrying `supportSlabId` is a railing on that slab's walking
7
+ * surface (drawn onto a deck, or placed by a deck preset). The
8
+ * host pins the lift only while it still exists as a slab on the fence's
9
+ * own level — a stale host (deleted slab, reparented fence) silently
10
+ * falls back to the level floor, mirroring the read-path rules of the
11
+ * other `supportSlabId` carriers. Pure so it is unit-testable and
12
+ * callable from the geometry builder with `ctx.resolve`.
13
+ */
14
+ export declare function resolveFenceLiftElevation(node: Pick<FenceNode, 'supportSlabId' | 'supportOffset' | 'parentId'>, resolve: (id: string) => AnyNode | undefined): number;
15
+ //# sourceMappingURL=lift.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lift.d.ts","sourceRoot":"","sources":["../../src/fence/lift.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,kBAAkB,CAAA;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEzC;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,eAAe,GAAG,eAAe,GAAG,UAAU,CAAC,EACrE,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,GAAG,SAAS,GAC3C,MAAM,CAQR"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Elevation (meters above the level plane) a hosted fence stands at.
3
+ *
4
+ * A fence carrying `supportSlabId` is a railing on that slab's walking
5
+ * surface (drawn onto a deck, or placed by a deck preset). The
6
+ * host pins the lift only while it still exists as a slab on the fence's
7
+ * own level — a stale host (deleted slab, reparented fence) silently
8
+ * falls back to the level floor, mirroring the read-path rules of the
9
+ * other `supportSlabId` carriers. Pure so it is unit-testable and
10
+ * callable from the geometry builder with `ctx.resolve`.
11
+ */
12
+ export function resolveFenceLiftElevation(node, resolve) {
13
+ const offset = node.supportOffset ?? 0;
14
+ if (!node.supportSlabId)
15
+ return offset;
16
+ const host = resolve(node.supportSlabId);
17
+ if (host?.type !== 'slab')
18
+ return offset;
19
+ if ((host.parentId ?? null) !== (node.parentId ?? null))
20
+ return offset;
21
+ const elevation = host.elevation;
22
+ return (Number.isFinite(elevation) ? elevation : 0) + offset;
23
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"move-tool.d.ts","sourceRoot":"","sources":["../../src/fence/move-tool.tsx"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,SAAS,EAUf,MAAM,kBAAkB,CAAA;AAsHzB,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAwQvD,CAAA;AAED,eAAe,aAAa,CAAA"}
1
+ {"version":3,"file":"move-tool.d.ts","sourceRoot":"","sources":["../../src/fence/move-tool.tsx"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,SAAS,EAWf,MAAM,kBAAkB,CAAA;AAsHzB,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAgSvD,CAAA;AAED,eAAe,aAAa,CAAA"}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { constrainWallMoveDeltaToAxis, emitter, getPerpendicularWallMoveAxis, isCurvedWall, isSplineFence, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
3
+ import { constrainWallMoveDeltaToAxis, emitter, getPerpendicularWallMoveAxis, isCurvedWall, isSplineFence, resolveFenceSupportSlabPatch, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
4
4
  import { CursorSphere, consumePlacementDragRelease, getSegmentGridStep, isGridSnapActive, isMagneticSnapActive, markToolCancelConsumed, snapFenceDraftPoint, triggerSFX, useEditor, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { useCallback, useEffect, useRef, useState } from 'react';
@@ -132,10 +132,30 @@ export const MoveFenceTool = ({ node }) => {
132
132
  }
133
133
  };
134
134
  const applyCommittedUpdates = (updates) => {
135
- useScene.getState().updateNodes(updates.map((entry) => ({
136
- id: entry.id,
137
- data: { start: entry.start, end: entry.end, path: entry.path },
138
- })));
135
+ // Fold the re-elected slab lift host into the same write — a fence
136
+ // moved onto / off an elevated deck must land on the right surface
137
+ // (fences run no per-frame election; `supportSlabId` IS the lift),
138
+ // and one updateNodes keeps the whole move a single undo step.
139
+ // Election runs on the committed endpoints against the pre-write
140
+ // store (the patch only reads the parent level + the slab grid).
141
+ const baselineNodes = useScene.getState().nodes;
142
+ useScene.getState().updateNodes(updates.map((entry) => {
143
+ const fence = baselineNodes[entry.id];
144
+ const support = fence?.type === 'fence'
145
+ ? resolveFenceSupportSlabPatch({
146
+ start: entry.start,
147
+ end: entry.end,
148
+ path: entry.path,
149
+ curveOffset: fence.curveOffset,
150
+ thickness: fence.thickness,
151
+ parentId: fence.parentId,
152
+ }, baselineNodes)
153
+ : {};
154
+ return {
155
+ id: entry.id,
156
+ data: { start: entry.start, end: entry.end, path: entry.path, ...support },
157
+ };
158
+ }));
139
159
  for (const entry of updates) {
140
160
  useScene.getState().markDirty(entry.id);
141
161
  }
@@ -0,0 +1,3 @@
1
+ declare const FenceSystems: () => null;
2
+ export default FenceSystems;
3
+ //# sourceMappingURL=system.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../src/fence/system.tsx"],"names":[],"mappings":"AA+BA,QAAA,MAAM,YAAY,YAgBjB,CAAA;AAED,eAAe,YAAY,CAAA"}
@@ -0,0 +1,41 @@
1
+ 'use client';
2
+ import { useScene } from '@pascal-app/core';
3
+ import { useEffect } from 'react';
4
+ import { resolveFenceLiftElevation } from './lift';
5
+ /**
6
+ * Hosted-railing dependency tracker. A fence with `supportSlabId` renders at
7
+ * its host slab's elevation, but a store update only dirties the node that
8
+ * changed — editing the slab's elevation (or restoring a deleted host) would
9
+ * leave the railing floating at the stale height. Watch each hosted fence's
10
+ * resolved lift and dirty the fence when it moves; `GeometrySystem` rebuilds
11
+ * through `def.geometry` as usual. (Deleting the host needs no help here:
12
+ * `deleteNodesAction` strips `supportSlabId` and dirties the fence itself.)
13
+ */
14
+ function fenceLiftSignatures(nodes) {
15
+ const signatures = new Map();
16
+ for (const node of Object.values(nodes)) {
17
+ if (node.type !== 'fence')
18
+ continue;
19
+ const fence = node;
20
+ if (!fence.supportSlabId)
21
+ continue;
22
+ signatures.set(fence.id, resolveFenceLiftElevation(fence, (id) => nodes[id]));
23
+ }
24
+ return signatures;
25
+ }
26
+ const FenceSystems = () => {
27
+ useEffect(() => {
28
+ let previous = fenceLiftSignatures(useScene.getState().nodes);
29
+ return useScene.subscribe((state) => {
30
+ const current = fenceLiftSignatures(state.nodes);
31
+ for (const [fenceId, lift] of current.entries()) {
32
+ if (previous.get(fenceId) !== lift) {
33
+ state.markDirty(fenceId);
34
+ }
35
+ }
36
+ previous = current;
37
+ });
38
+ }, []);
39
+ return null;
40
+ };
41
+ export default FenceSystems;
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/fence/tool.tsx"],"names":[],"mappings":"AAqbA,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAM7B,CAAA;AA+cD,eAAe,SAAS,CAAA"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/fence/tool.tsx"],"names":[],"mappings":"AAycA,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAM7B,CAAA;AAweD,eAAe,SAAS,CAAA"}