@pascal-app/nodes 1.0.3 → 1.0.4

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 (708) hide show
  1. package/dist/block/definition.d.ts.map +1 -1
  2. package/dist/block/definition.js +18 -3
  3. package/dist/block/floorplan.d.ts +11 -1
  4. package/dist/block/floorplan.d.ts.map +1 -1
  5. package/dist/block/floorplan.js +81 -13
  6. package/dist/block/geometry.d.ts +2 -2
  7. package/dist/block/geometry.d.ts.map +1 -1
  8. package/dist/block/geometry.js +39 -24
  9. package/dist/block/hosted-edit.d.ts.map +1 -1
  10. package/dist/block/hosted-edit.js +25 -0
  11. package/dist/block/material-slots.d.ts +1 -3
  12. package/dist/block/material-slots.d.ts.map +1 -1
  13. package/dist/block/material-slots.js +1 -11
  14. package/dist/block/paint.d.ts.map +1 -1
  15. package/dist/block/paint.js +4 -10
  16. package/dist/block/panel.d.ts.map +1 -1
  17. package/dist/block/panel.js +8 -3
  18. package/dist/block/selection.d.ts.map +1 -1
  19. package/dist/block/selection.js +2 -2
  20. package/dist/box-vent/definition.d.ts.map +1 -1
  21. package/dist/box-vent/definition.js +2 -5
  22. package/dist/box-vent/panel.d.ts.map +1 -1
  23. package/dist/box-vent/panel.js +5 -28
  24. package/dist/cabinet/countertop-layout.d.ts +13 -2
  25. package/dist/cabinet/countertop-layout.d.ts.map +1 -1
  26. package/dist/cabinet/definition.d.ts.map +1 -1
  27. package/dist/cabinet/definition.js +1 -2
  28. package/dist/cabinet/floorplan.d.ts.map +1 -1
  29. package/dist/cabinet/floorplan.js +125 -28
  30. package/dist/cabinet/geometry/shared.d.ts +1 -2
  31. package/dist/cabinet/geometry/shared.d.ts.map +1 -1
  32. package/dist/cabinet/geometry/shared.js +1 -2
  33. package/dist/cabinet/run-layout.d.ts.map +1 -1
  34. package/dist/cabinet/run-layout.js +8 -5
  35. package/dist/cabinet/run-ops.d.ts +13 -2
  36. package/dist/cabinet/run-ops.d.ts.map +1 -1
  37. package/dist/cabinet/tool.d.ts.map +1 -1
  38. package/dist/cabinet/tool.js +22 -24
  39. package/dist/cabinet/wall-snap.d.ts.map +1 -1
  40. package/dist/cabinet/wall-snap.js +8 -8
  41. package/dist/ceiling/boundary-editor.d.ts.map +1 -1
  42. package/dist/ceiling/boundary-editor.js +5 -3
  43. package/dist/ceiling/definition.d.ts +4 -4
  44. package/dist/ceiling/definition.d.ts.map +1 -1
  45. package/dist/ceiling/definition.js +15 -15
  46. package/dist/ceiling/floorplan-affordances.d.ts +84 -4
  47. package/dist/ceiling/floorplan-affordances.d.ts.map +1 -1
  48. package/dist/ceiling/floorplan-affordances.js +0 -1
  49. package/dist/ceiling/floorplan-move.d.ts.map +1 -1
  50. package/dist/ceiling/floorplan-move.js +0 -1
  51. package/dist/ceiling/floorplan.d.ts +1 -1
  52. package/dist/ceiling/floorplan.d.ts.map +1 -1
  53. package/dist/ceiling/floorplan.js +2 -1
  54. package/dist/ceiling/height-bounds.d.ts +19 -0
  55. package/dist/ceiling/height-bounds.d.ts.map +1 -0
  56. package/dist/ceiling/height-bounds.js +24 -0
  57. package/dist/ceiling/hole-editor.d.ts.map +1 -1
  58. package/dist/ceiling/hole-editor.js +3 -4
  59. package/dist/ceiling/materials.d.ts +1 -1
  60. package/dist/ceiling/materials.d.ts.map +1 -1
  61. package/dist/ceiling/materials.js +10 -3
  62. package/dist/ceiling/paint.d.ts +2 -8
  63. package/dist/ceiling/paint.d.ts.map +1 -1
  64. package/dist/ceiling/paint.js +121 -24
  65. package/dist/ceiling/panel.d.ts.map +1 -1
  66. package/dist/ceiling/panel.js +40 -23
  67. package/dist/ceiling/renderer.d.ts.map +1 -1
  68. package/dist/ceiling/renderer.js +41 -5
  69. package/dist/chimney/move-tool.d.ts.map +1 -1
  70. package/dist/chimney/move-tool.js +8 -2
  71. package/dist/chimney/paint.d.ts.map +1 -1
  72. package/dist/chimney/paint.js +3 -10
  73. package/dist/column/definition.d.ts.map +1 -1
  74. package/dist/column/definition.js +24 -2
  75. package/dist/column/floorplan-affordances.d.ts.map +1 -1
  76. package/dist/column/floorplan-affordances.js +5 -0
  77. package/dist/column/floorplan.d.ts +1 -1
  78. package/dist/column/floorplan.d.ts.map +1 -1
  79. package/dist/column/floorplan.js +47 -2
  80. package/dist/column/hosted-resize.d.ts +101 -2
  81. package/dist/column/hosted-resize.d.ts.map +1 -1
  82. package/dist/column/panel.d.ts.map +1 -1
  83. package/dist/column/panel.js +147 -146
  84. package/dist/column/renderer.d.ts.map +1 -1
  85. package/dist/column/renderer.js +6 -4
  86. package/dist/column/surface.d.ts.map +1 -1
  87. package/dist/column/surface.js +7 -0
  88. package/dist/construction-dimension/floorplan.js +7 -3
  89. package/dist/cupola/definition.d.ts.map +1 -1
  90. package/dist/cupola/definition.js +2 -8
  91. package/dist/cupola/panel.d.ts.map +1 -1
  92. package/dist/cupola/panel.js +5 -23
  93. package/dist/door/definition.d.ts.map +1 -1
  94. package/dist/door/definition.js +12 -3
  95. package/dist/door/door-math.d.ts +5 -10
  96. package/dist/door/door-math.d.ts.map +1 -1
  97. package/dist/door/door-math.js +14 -15
  98. package/dist/door/floorplan-move.d.ts.map +1 -1
  99. package/dist/door/floorplan-move.js +3 -1
  100. package/dist/door/floorplan.d.ts.map +1 -1
  101. package/dist/door/floorplan.js +55 -21
  102. package/dist/door/mechanism.d.ts +4 -0
  103. package/dist/door/mechanism.d.ts.map +1 -0
  104. package/dist/door/mechanism.js +24 -0
  105. package/dist/door/move-tool.d.ts.map +1 -1
  106. package/dist/door/move-tool.js +72 -48
  107. package/dist/door/paint.d.ts.map +1 -1
  108. package/dist/door/paint.js +3 -0
  109. package/dist/door/panel.d.ts.map +1 -1
  110. package/dist/door/panel.js +34 -259
  111. package/dist/door/placement.d.ts +45 -0
  112. package/dist/door/placement.d.ts.map +1 -0
  113. package/dist/door/placement.js +51 -0
  114. package/dist/door/preview.d.ts.map +1 -1
  115. package/dist/door/preview.js +2 -0
  116. package/dist/door/renderer.d.ts.map +1 -1
  117. package/dist/door/renderer.js +3 -2
  118. package/dist/door/tool.d.ts.map +1 -1
  119. package/dist/door/tool.js +92 -21
  120. package/dist/dormer/csg-geometry.d.ts.map +1 -1
  121. package/dist/dormer/csg-geometry.js +2 -0
  122. package/dist/dormer/paint.d.ts.map +1 -1
  123. package/dist/dormer/paint.js +2 -5
  124. package/dist/dormer/panel.d.ts.map +1 -1
  125. package/dist/dormer/panel.js +4 -14
  126. package/dist/downspout/definition.d.ts.map +1 -1
  127. package/dist/downspout/definition.js +2 -2
  128. package/dist/duct-fitting/definition.d.ts.map +1 -1
  129. package/dist/duct-fitting/definition.js +2 -1
  130. package/dist/duct-fitting/geometry.d.ts.map +1 -1
  131. package/dist/duct-fitting/geometry.js +1 -1
  132. package/dist/duct-fitting/move-tool.d.ts.map +1 -1
  133. package/dist/duct-fitting/move-tool.js +8 -2
  134. package/dist/duct-segment/definition.d.ts.map +1 -1
  135. package/dist/duct-segment/definition.js +2 -2
  136. package/dist/duct-segment/geometry.d.ts.map +1 -1
  137. package/dist/duct-segment/geometry.js +1 -1
  138. package/dist/duct-segment/move-tool.d.ts.map +1 -1
  139. package/dist/duct-segment/move-tool.js +8 -2
  140. package/dist/elevator/definition.d.ts.map +1 -1
  141. package/dist/elevator/definition.js +1 -2
  142. package/dist/elevator/panel.d.ts.map +1 -1
  143. package/dist/elevator/panel.js +5 -27
  144. package/dist/elevator/parametrics.js +1 -1
  145. package/dist/elevator/renderer.d.ts.map +1 -1
  146. package/dist/elevator/renderer.js +3 -4
  147. package/dist/eyebrow-vent/definition.d.ts.map +1 -1
  148. package/dist/eyebrow-vent/definition.js +2 -5
  149. package/dist/eyebrow-vent/paint.d.ts.map +1 -1
  150. package/dist/eyebrow-vent/paint.js +3 -6
  151. package/dist/eyebrow-vent/panel.d.ts.map +1 -1
  152. package/dist/eyebrow-vent/panel.js +5 -23
  153. package/dist/fence/actions/move-endpoint.d.ts +1 -1
  154. package/dist/fence/actions/move-endpoint.d.ts.map +1 -1
  155. package/dist/fence/actions/move-endpoint.js +2 -1
  156. package/dist/fence/definition.d.ts +2 -1
  157. package/dist/fence/definition.d.ts.map +1 -1
  158. package/dist/fence/definition.js +83 -28
  159. package/dist/fence/drafting.d.ts +36 -0
  160. package/dist/fence/drafting.d.ts.map +1 -0
  161. package/dist/fence/drafting.js +210 -0
  162. package/dist/fence/feature-tool.d.ts +4 -0
  163. package/dist/fence/feature-tool.d.ts.map +1 -0
  164. package/dist/fence/feature-tool.js +140 -0
  165. package/dist/fence/features.d.ts +2 -0
  166. package/dist/fence/features.d.ts.map +1 -0
  167. package/dist/fence/features.js +12 -0
  168. package/dist/fence/floorplan-affordances.d.ts.map +1 -1
  169. package/dist/fence/floorplan-affordances.js +2 -1
  170. package/dist/fence/floorplan.d.ts +2 -3
  171. package/dist/fence/floorplan.d.ts.map +1 -1
  172. package/dist/fence/floorplan.js +131 -71
  173. package/dist/fence/geometry-parts.d.ts +50 -0
  174. package/dist/fence/geometry-parts.d.ts.map +1 -0
  175. package/dist/fence/geometry-parts.js +1144 -0
  176. package/dist/fence/geometry.d.ts +2 -3
  177. package/dist/fence/geometry.d.ts.map +1 -1
  178. package/dist/fence/geometry.js +84 -7
  179. package/dist/fence/index.d.ts +1 -0
  180. package/dist/fence/index.d.ts.map +1 -1
  181. package/dist/fence/index.js +1 -0
  182. package/dist/fence/inspector-editors.d.ts +15 -0
  183. package/dist/fence/inspector-editors.d.ts.map +1 -1
  184. package/dist/fence/inspector-editors.js +128 -3
  185. package/dist/fence/lift.d.ts.map +1 -1
  186. package/dist/fence/lift.js +5 -2
  187. package/dist/fence/move-tool.js +2 -1
  188. package/dist/fence/panel-model.d.ts +4 -0
  189. package/dist/fence/panel-model.d.ts.map +1 -0
  190. package/dist/fence/panel-model.js +12 -0
  191. package/dist/fence/parametrics.d.ts +0 -12
  192. package/dist/fence/parametrics.d.ts.map +1 -1
  193. package/dist/fence/parametrics.js +185 -18
  194. package/dist/fence/system.d.ts.map +1 -1
  195. package/dist/fence/system.js +141 -31
  196. package/dist/fence/tool.d.ts.map +1 -1
  197. package/dist/fence/tool.js +256 -47
  198. package/dist/fence-feature/actions.d.ts +7 -0
  199. package/dist/fence-feature/actions.d.ts.map +1 -0
  200. package/dist/fence-feature/actions.js +26 -0
  201. package/dist/fence-feature/definition.d.ts +4 -0
  202. package/dist/fence-feature/definition.d.ts.map +1 -0
  203. package/dist/fence-feature/definition.js +112 -0
  204. package/dist/fence-feature/floorplan-affordances.d.ts +3 -0
  205. package/dist/fence-feature/floorplan-affordances.d.ts.map +1 -0
  206. package/dist/fence-feature/floorplan-affordances.js +37 -0
  207. package/dist/fence-feature/floorplan.d.ts +4 -0
  208. package/dist/fence-feature/floorplan.d.ts.map +1 -0
  209. package/dist/fence-feature/floorplan.js +120 -0
  210. package/dist/fence-feature/geometry.d.ts +5 -0
  211. package/dist/fence-feature/geometry.d.ts.map +1 -0
  212. package/dist/fence-feature/geometry.js +43 -0
  213. package/dist/fence-feature/handles.d.ts +5 -0
  214. package/dist/fence-feature/handles.d.ts.map +1 -0
  215. package/dist/fence-feature/handles.js +84 -0
  216. package/dist/fence-feature/inspector.d.ts +6 -0
  217. package/dist/fence-feature/inspector.d.ts.map +1 -0
  218. package/dist/fence-feature/inspector.js +214 -0
  219. package/dist/fence-feature/interaction.d.ts +3 -0
  220. package/dist/fence-feature/interaction.d.ts.map +1 -0
  221. package/dist/fence-feature/interaction.js +41 -0
  222. package/dist/fence-feature/move-session.d.ts +9 -0
  223. package/dist/fence-feature/move-session.d.ts.map +1 -0
  224. package/dist/fence-feature/move-session.js +48 -0
  225. package/dist/fence-feature/move-tool.d.ts +5 -0
  226. package/dist/fence-feature/move-tool.d.ts.map +1 -0
  227. package/dist/fence-feature/move-tool.js +58 -0
  228. package/dist/fence-feature/pick-target.d.ts +7 -0
  229. package/dist/fence-feature/pick-target.d.ts.map +1 -0
  230. package/dist/fence-feature/pick-target.js +52 -0
  231. package/dist/floor-opening/definition.d.ts +3 -0
  232. package/dist/floor-opening/definition.d.ts.map +1 -0
  233. package/dist/floor-opening/definition.js +41 -0
  234. package/dist/floor-opening/floorplan.d.ts +156 -0
  235. package/dist/floor-opening/floorplan.d.ts.map +1 -0
  236. package/dist/floor-opening/floorplan.js +63 -0
  237. package/dist/gutter/definition.d.ts.map +1 -1
  238. package/dist/gutter/definition.js +2 -2
  239. package/dist/imported-mesh/definition.d.ts.map +1 -1
  240. package/dist/imported-mesh/definition.js +2 -0
  241. package/dist/imported-mesh/geometry.d.ts +1 -1
  242. package/dist/imported-mesh/geometry.d.ts.map +1 -1
  243. package/dist/imported-mesh/geometry.js +40 -12
  244. package/dist/index.d.ts +13 -2
  245. package/dist/index.d.ts.map +1 -1
  246. package/dist/index.js +20 -2
  247. package/dist/item/authored-face-host.d.ts +10 -0
  248. package/dist/item/authored-face-host.d.ts.map +1 -0
  249. package/dist/item/authored-face-host.js +87 -0
  250. package/dist/item/authored-params.d.ts +15 -0
  251. package/dist/item/authored-params.d.ts.map +1 -0
  252. package/dist/item/authored-params.js +72 -0
  253. package/dist/item/definition.d.ts +2 -2
  254. package/dist/item/definition.d.ts.map +1 -1
  255. package/dist/item/definition.js +33 -4
  256. package/dist/item/floorplan.d.ts +1 -1
  257. package/dist/item/floorplan.d.ts.map +1 -1
  258. package/dist/item/floorplan.js +35 -5
  259. package/dist/item/index.d.ts +1 -0
  260. package/dist/item/index.d.ts.map +1 -1
  261. package/dist/item/index.js +1 -0
  262. package/dist/item/model-loader.d.ts +2 -0
  263. package/dist/item/model-loader.d.ts.map +1 -1
  264. package/dist/item/model-loader.js +55 -23
  265. package/dist/item/move-tool.js +4 -4
  266. package/dist/item/paint.d.ts.map +1 -1
  267. package/dist/item/paint.js +5 -24
  268. package/dist/item/panel.d.ts +1 -3
  269. package/dist/item/panel.d.ts.map +1 -1
  270. package/dist/item/panel.js +20 -24
  271. package/dist/item/placement-notice.d.ts +14 -0
  272. package/dist/item/placement-notice.d.ts.map +1 -0
  273. package/dist/item/placement-notice.js +38 -0
  274. package/dist/item/plan-symbols.d.ts +67 -0
  275. package/dist/item/plan-symbols.d.ts.map +1 -0
  276. package/dist/item/plan-symbols.js +407 -0
  277. package/dist/item/renderer.d.ts +10 -0
  278. package/dist/item/renderer.d.ts.map +1 -1
  279. package/dist/item/renderer.js +64 -38
  280. package/dist/item/script-param-defaults.d.ts +12 -0
  281. package/dist/item/script-param-defaults.d.ts.map +1 -0
  282. package/dist/item/script-param-defaults.js +34 -0
  283. package/dist/lean-to-extension/definition.d.ts.map +1 -1
  284. package/dist/lean-to-extension/definition.js +1 -2
  285. package/dist/lean-to-extension/geometry.d.ts.map +1 -1
  286. package/dist/lean-to-extension/geometry.js +1 -1
  287. package/dist/lean-to-extension/layout.d.ts.map +1 -1
  288. package/dist/lean-to-extension/layout.js +2 -3
  289. package/dist/lean-to-extension/placement-validation.d.ts.map +1 -1
  290. package/dist/lean-to-extension/placement-validation.js +5 -5
  291. package/dist/lean-to-extension/tool.d.ts.map +1 -1
  292. package/dist/lean-to-extension/tool.js +5 -5
  293. package/dist/lineset/move-tool.d.ts.map +1 -1
  294. package/dist/lineset/move-tool.js +8 -2
  295. package/dist/liquid-line/move-tool.d.ts.map +1 -1
  296. package/dist/liquid-line/move-tool.js +8 -2
  297. package/dist/measurement/definition.js +1 -1
  298. package/dist/pipe-fitting/move-tool.d.ts.map +1 -1
  299. package/dist/pipe-fitting/move-tool.js +8 -2
  300. package/dist/pipe-segment/move-tool.d.ts.map +1 -1
  301. package/dist/pipe-segment/move-tool.js +8 -2
  302. package/dist/procedural-item/animation.d.ts +8 -0
  303. package/dist/procedural-item/animation.d.ts.map +1 -0
  304. package/dist/procedural-item/animation.js +116 -0
  305. package/dist/procedural-item/definition.d.ts.map +1 -1
  306. package/dist/procedural-item/definition.js +74 -8
  307. package/dist/procedural-item/geometry.d.ts +5 -1
  308. package/dist/procedural-item/geometry.d.ts.map +1 -1
  309. package/dist/procedural-item/geometry.js +239 -15
  310. package/dist/procedural-item/renderer.d.ts.map +1 -1
  311. package/dist/procedural-item/renderer.js +272 -23
  312. package/dist/ridge-vent/panel.d.ts.map +1 -1
  313. package/dist/ridge-vent/panel.js +5 -23
  314. package/dist/ridge-vent/renderer.d.ts.map +1 -1
  315. package/dist/ridge-vent/renderer.js +9 -8
  316. package/dist/roof/definition.d.ts.map +1 -1
  317. package/dist/roof/definition.js +4 -1
  318. package/dist/roof/floorplan.d.ts +8 -0
  319. package/dist/roof/floorplan.d.ts.map +1 -1
  320. package/dist/roof/floorplan.js +194 -18
  321. package/dist/roof/panel-model.d.ts.map +1 -1
  322. package/dist/roof/panel-model.js +10 -6
  323. package/dist/roof/panel.d.ts.map +1 -1
  324. package/dist/roof/panel.js +3 -10
  325. package/dist/roof/renderer.d.ts.map +1 -1
  326. package/dist/roof/renderer.js +5 -2
  327. package/dist/roof-segment/panel.d.ts.map +1 -1
  328. package/dist/roof-segment/panel.js +5 -24
  329. package/dist/roof-segment/renderer.d.ts.map +1 -1
  330. package/dist/roof-segment/renderer.js +17 -8
  331. package/dist/separator/definition.d.ts +3 -0
  332. package/dist/separator/definition.d.ts.map +1 -0
  333. package/dist/separator/definition.js +39 -0
  334. package/dist/separator/renderer.d.ts +5 -0
  335. package/dist/separator/renderer.d.ts.map +1 -0
  336. package/dist/separator/renderer.js +36 -0
  337. package/dist/shared/duct-body-paint.d.ts +0 -4
  338. package/dist/shared/duct-body-paint.d.ts.map +1 -1
  339. package/dist/shared/duct-body-paint.js +1 -5
  340. package/dist/shared/item-interaction-actions.d.ts +6 -0
  341. package/dist/shared/item-interaction-actions.d.ts.map +1 -0
  342. package/dist/shared/item-interaction-actions.js +27 -0
  343. package/dist/shared/item-interactions.d.ts +9 -0
  344. package/dist/shared/item-interactions.d.ts.map +1 -0
  345. package/dist/shared/item-interactions.js +74 -0
  346. package/dist/shared/item-light-placement.d.ts +2 -0
  347. package/dist/shared/item-light-placement.d.ts.map +1 -0
  348. package/dist/shared/item-light-placement.js +3 -0
  349. package/dist/shared/move-roof-tool.js +2 -1
  350. package/dist/shared/node-batch/batchable.d.ts +12 -0
  351. package/dist/shared/node-batch/batchable.d.ts.map +1 -0
  352. package/dist/shared/node-batch/batchable.js +41 -0
  353. package/dist/shared/node-batch/candidates.d.ts +7 -5
  354. package/dist/shared/node-batch/candidates.d.ts.map +1 -1
  355. package/dist/shared/node-batch/candidates.js +43 -59
  356. package/dist/shared/node-batch/release.d.ts +8 -0
  357. package/dist/shared/node-batch/release.d.ts.map +1 -0
  358. package/dist/shared/node-batch/release.js +16 -0
  359. package/dist/shared/node-batch/system.d.ts.map +1 -1
  360. package/dist/shared/node-batch/system.js +17 -12
  361. package/dist/shared/node-batch/types.d.ts +4 -1
  362. package/dist/shared/node-batch/types.d.ts.map +1 -1
  363. package/dist/shared/opening-documentation.d.ts +13 -1
  364. package/dist/shared/opening-documentation.d.ts.map +1 -1
  365. package/dist/shared/opening-documentation.js +245 -59
  366. package/dist/shared/opening-guides-runtime.d.ts.map +1 -1
  367. package/dist/shared/opening-guides-runtime.js +17 -14
  368. package/dist/shared/opening-placement-dimensions.d.ts.map +1 -1
  369. package/dist/shared/opening-placement-dimensions.js +3 -3
  370. package/dist/shared/opening-plane-offset.d.ts +23 -0
  371. package/dist/shared/opening-plane-offset.d.ts.map +1 -0
  372. package/dist/shared/opening-plane-offset.js +24 -0
  373. package/dist/shared/polygon-centroid-move.d.ts.map +1 -1
  374. package/dist/shared/polygon-centroid-move.js +4 -1
  375. package/dist/shared/polygon-vertex-affordance.d.ts.map +1 -1
  376. package/dist/shared/polygon-vertex-affordance.js +19 -15
  377. package/dist/shared/run-hangers.d.ts.map +1 -1
  378. package/dist/shared/run-hangers.js +5 -4
  379. package/dist/shared/scripted-opening-handles.d.ts +18 -0
  380. package/dist/shared/scripted-opening-handles.d.ts.map +1 -0
  381. package/dist/shared/scripted-opening-handles.js +53 -0
  382. package/dist/shared/scripted-opening.d.ts +25 -0
  383. package/dist/shared/scripted-opening.d.ts.map +1 -0
  384. package/dist/shared/scripted-opening.js +72 -0
  385. package/dist/shared/slot-paint.d.ts +14 -2
  386. package/dist/shared/slot-paint.d.ts.map +1 -1
  387. package/dist/shared/slot-paint.js +29 -29
  388. package/dist/shared/surface-paint.d.ts.map +1 -1
  389. package/dist/shared/surface-paint.js +2 -5
  390. package/dist/shared/swap-preview-material.d.ts +11 -0
  391. package/dist/shared/swap-preview-material.d.ts.map +1 -0
  392. package/dist/shared/swap-preview-material.js +16 -0
  393. package/dist/shared/system-checks.d.ts.map +1 -1
  394. package/dist/shared/system-checks.js +5 -3
  395. package/dist/shared/wall-attach-target.d.ts +3 -10
  396. package/dist/shared/wall-attach-target.d.ts.map +1 -1
  397. package/dist/shared/wall-attach-target.js +3 -63
  398. package/dist/shared/wall-opening-ceiling.d.ts +5 -15
  399. package/dist/shared/wall-opening-ceiling.d.ts.map +1 -1
  400. package/dist/shared/wall-opening-ceiling.js +10 -18
  401. package/dist/shelf/definition.d.ts.map +1 -1
  402. package/dist/shelf/definition.js +1 -1
  403. package/dist/shelf/geometry.d.ts.map +1 -1
  404. package/dist/shelf/geometry.js +1 -2
  405. package/dist/shelf/paint.d.ts.map +1 -1
  406. package/dist/shelf/paint.js +4 -10
  407. package/dist/site/line-ribbon.d.ts +31 -0
  408. package/dist/site/line-ribbon.d.ts.map +1 -0
  409. package/dist/site/line-ribbon.js +117 -0
  410. package/dist/site/lot-mask.d.ts +18 -0
  411. package/dist/site/lot-mask.d.ts.map +1 -0
  412. package/dist/site/lot-mask.js +35 -0
  413. package/dist/site/panel.d.ts +10 -0
  414. package/dist/site/panel.d.ts.map +1 -0
  415. package/dist/site/panel.js +155 -0
  416. package/dist/site/parametrics.d.ts +7 -0
  417. package/dist/site/parametrics.d.ts.map +1 -1
  418. package/dist/site/parametrics.js +8 -0
  419. package/dist/site/recessed-slab-ground-holes.d.ts.map +1 -1
  420. package/dist/site/recessed-slab-ground-holes.js +5 -2
  421. package/dist/site/renderer.d.ts.map +1 -1
  422. package/dist/site/renderer.js +150 -19
  423. package/dist/site/setbacks.d.ts +33 -0
  424. package/dist/site/setbacks.d.ts.map +1 -0
  425. package/dist/site/setbacks.js +204 -0
  426. package/dist/site/terrain-geometry.d.ts +28 -1
  427. package/dist/site/terrain-geometry.d.ts.map +1 -1
  428. package/dist/site/terrain-geometry.js +78 -4
  429. package/dist/site/terrain-holes.d.ts +15 -0
  430. package/dist/site/terrain-holes.d.ts.map +1 -0
  431. package/dist/site/terrain-holes.js +74 -0
  432. package/dist/site/terrain-mesh.d.ts +9 -2
  433. package/dist/site/terrain-mesh.d.ts.map +1 -1
  434. package/dist/site/terrain-mesh.js +36 -9
  435. package/dist/site/terrain-renderer.d.ts +9 -2
  436. package/dist/site/terrain-renderer.d.ts.map +1 -1
  437. package/dist/site/terrain-renderer.js +14 -4
  438. package/dist/slab/boundary-editor.d.ts +1 -1
  439. package/dist/slab/boundary-editor.d.ts.map +1 -1
  440. package/dist/slab/boundary-editor.js +13 -13
  441. package/dist/slab/definition.d.ts.map +1 -1
  442. package/dist/slab/definition.js +19 -3
  443. package/dist/slab/dependency-tracker.d.ts.map +1 -1
  444. package/dist/slab/dependency-tracker.js +67 -7
  445. package/dist/slab/elevation-limit.d.ts.map +1 -1
  446. package/dist/slab/elevation-limit.js +2 -2
  447. package/dist/slab/floorplan-affordances.d.ts +176 -4
  448. package/dist/slab/floorplan-affordances.d.ts.map +1 -1
  449. package/dist/slab/floorplan-affordances.js +0 -1
  450. package/dist/slab/floorplan-move.d.ts.map +1 -1
  451. package/dist/slab/floorplan-move.js +3 -4
  452. package/dist/slab/floorplan.d.ts +7 -0
  453. package/dist/slab/floorplan.d.ts.map +1 -1
  454. package/dist/slab/floorplan.js +22 -5
  455. package/dist/slab/geometry.d.ts.map +1 -1
  456. package/dist/slab/geometry.js +186 -76
  457. package/dist/slab/move-tool.js +7 -6
  458. package/dist/slab/paint.d.ts +18 -5
  459. package/dist/slab/paint.d.ts.map +1 -1
  460. package/dist/slab/paint.js +458 -9
  461. package/dist/slab/panel.d.ts.map +1 -1
  462. package/dist/slab/panel.js +28 -9
  463. package/dist/slab/placement-ownership.d.ts +2 -1
  464. package/dist/slab/placement-ownership.d.ts.map +1 -1
  465. package/dist/slab/placement-ownership.js +2 -2
  466. package/dist/slab/surface-split.d.ts +24 -0
  467. package/dist/slab/surface-split.d.ts.map +1 -0
  468. package/dist/slab/surface-split.js +389 -0
  469. package/dist/slab/tool.d.ts.map +1 -1
  470. package/dist/slab/tool.js +3 -3
  471. package/dist/stair/baluster-geometry.d.ts +21 -0
  472. package/dist/stair/baluster-geometry.d.ts.map +1 -0
  473. package/dist/stair/baluster-geometry.js +74 -0
  474. package/dist/stair/baluster-guard.d.ts +50 -0
  475. package/dist/stair/baluster-guard.d.ts.map +1 -0
  476. package/dist/stair/baluster-guard.js +71 -0
  477. package/dist/stair/boards-guard.d.ts +37 -0
  478. package/dist/stair/boards-guard.d.ts.map +1 -0
  479. package/dist/stair/boards-guard.js +61 -0
  480. package/dist/stair/cable-guard.d.ts +39 -0
  481. package/dist/stair/cable-guard.d.ts.map +1 -0
  482. package/dist/stair/cable-guard.js +105 -0
  483. package/dist/stair/construction-controls.d.ts +15 -0
  484. package/dist/stair/construction-controls.d.ts.map +1 -0
  485. package/dist/stair/construction-controls.js +29 -0
  486. package/dist/stair/continuous-railings.d.ts +10 -0
  487. package/dist/stair/continuous-railings.d.ts.map +1 -0
  488. package/dist/stair/continuous-railings.js +159 -0
  489. package/dist/stair/definition.d.ts.map +1 -1
  490. package/dist/stair/definition.js +16 -37
  491. package/dist/stair/documentation.d.ts +1 -1
  492. package/dist/stair/documentation.d.ts.map +1 -1
  493. package/dist/stair/documentation.js +10 -17
  494. package/dist/stair/floorplan-affordances.d.ts.map +1 -1
  495. package/dist/stair/floorplan-affordances.js +9 -25
  496. package/dist/stair/floorplan.d.ts +1 -23
  497. package/dist/stair/floorplan.d.ts.map +1 -1
  498. package/dist/stair/floorplan.js +102 -86
  499. package/dist/stair/glass-guard.d.ts +72 -0
  500. package/dist/stair/glass-guard.d.ts.map +1 -0
  501. package/dist/stair/glass-guard.js +167 -0
  502. package/dist/stair/guard-path.d.ts +119 -0
  503. package/dist/stair/guard-path.d.ts.map +1 -0
  504. package/dist/stair/guard-path.js +208 -0
  505. package/dist/stair/materials.d.ts +11 -0
  506. package/dist/stair/materials.d.ts.map +1 -0
  507. package/dist/stair/materials.js +51 -0
  508. package/dist/stair/metal-guard.d.ts +38 -0
  509. package/dist/stair/metal-guard.d.ts.map +1 -0
  510. package/dist/stair/metal-guard.js +79 -0
  511. package/dist/stair/paint.d.ts +32 -0
  512. package/dist/stair/paint.d.ts.map +1 -1
  513. package/dist/stair/paint.js +75 -36
  514. package/dist/stair/panel.d.ts.map +1 -1
  515. package/dist/stair/panel.js +154 -17
  516. package/dist/stair/parametrics.d.ts +1 -1
  517. package/dist/stair/parametrics.d.ts.map +1 -1
  518. package/dist/stair/parametrics.js +32 -15
  519. package/dist/stair/plan-entry.d.ts +31 -0
  520. package/dist/stair/plan-entry.d.ts.map +1 -0
  521. package/dist/stair/plan-entry.js +325 -0
  522. package/dist/stair/post-and-rail-guard.d.ts +31 -0
  523. package/dist/stair/post-and-rail-guard.d.ts.map +1 -0
  524. package/dist/stair/post-and-rail-guard.js +63 -0
  525. package/dist/stair/railing-controls.d.ts +9 -0
  526. package/dist/stair/railing-controls.d.ts.map +1 -0
  527. package/dist/stair/railing-controls.js +49 -0
  528. package/dist/stair/renderer.d.ts.map +1 -1
  529. package/dist/stair/renderer.js +259 -259
  530. package/dist/stair/use-stair-render-data.d.ts +317 -0
  531. package/dist/stair/use-stair-render-data.d.ts.map +1 -0
  532. package/dist/stair/use-stair-render-data.js +73 -0
  533. package/dist/stair-segment/definition.d.ts.map +1 -1
  534. package/dist/stair-segment/definition.js +51 -10
  535. package/dist/stair-segment/panel.d.ts.map +1 -1
  536. package/dist/stair-segment/panel.js +36 -42
  537. package/dist/stair-segment/parametrics.d.ts +1 -1
  538. package/dist/stair-segment/parametrics.d.ts.map +1 -1
  539. package/dist/stair-segment/parametrics.js +21 -8
  540. package/dist/stair-segment/renderer.d.ts.map +1 -1
  541. package/dist/stair-segment/renderer.js +16 -28
  542. package/dist/turbine-vent/definition.d.ts.map +1 -1
  543. package/dist/turbine-vent/definition.js +2 -5
  544. package/dist/turbine-vent/paint.d.ts.map +1 -1
  545. package/dist/turbine-vent/paint.js +2 -5
  546. package/dist/turbine-vent/panel.d.ts.map +1 -1
  547. package/dist/turbine-vent/panel.js +5 -23
  548. package/dist/unit/unit-panel.d.ts.map +1 -1
  549. package/dist/unit/unit-panel.js +6 -1
  550. package/dist/wall/actions.d.ts.map +1 -1
  551. package/dist/wall/actions.js +7 -2
  552. package/dist/wall/construction-dimensions.js +8 -5
  553. package/dist/wall/contextual-dimensions.js +4 -4
  554. package/dist/wall/curtain-wall-materials.d.ts +1 -1
  555. package/dist/wall/curtain-wall-materials.d.ts.map +1 -1
  556. package/dist/wall/curtain-wall-materials.js +2 -2
  557. package/dist/wall/curve-tool.d.ts.map +1 -1
  558. package/dist/wall/curve-tool.js +4 -0
  559. package/dist/wall/definition.d.ts.map +1 -1
  560. package/dist/wall/definition.js +41 -17
  561. package/dist/wall/floorplan-move.d.ts +1 -1
  562. package/dist/wall/floorplan-move.d.ts.map +1 -1
  563. package/dist/wall/floorplan-move.js +20 -83
  564. package/dist/wall/floorplan-tool.d.ts.map +1 -1
  565. package/dist/wall/floorplan-tool.js +10 -11
  566. package/dist/wall/floorplan.d.ts +3 -1
  567. package/dist/wall/floorplan.d.ts.map +1 -1
  568. package/dist/wall/floorplan.js +184 -21
  569. package/dist/wall/measurement.d.ts.map +1 -1
  570. package/dist/wall/measurement.js +5 -5
  571. package/dist/wall/move-endpoint-tool.d.ts.map +1 -1
  572. package/dist/wall/move-endpoint-tool.js +20 -7
  573. package/dist/wall/move-shared.d.ts.map +1 -1
  574. package/dist/wall/move-shared.js +11 -7
  575. package/dist/wall/move-tool.d.ts.map +1 -1
  576. package/dist/wall/move-tool.js +118 -148
  577. package/dist/wall/paint.d.ts +26 -15
  578. package/dist/wall/paint.d.ts.map +1 -1
  579. package/dist/wall/paint.js +306 -117
  580. package/dist/wall/panel-model.d.ts +18 -0
  581. package/dist/wall/panel-model.d.ts.map +1 -1
  582. package/dist/wall/panel-model.js +77 -19
  583. package/dist/wall/panel.d.ts.map +1 -1
  584. package/dist/wall/panel.js +217 -41
  585. package/dist/wall/parametrics.d.ts.map +1 -1
  586. package/dist/wall/parametrics.js +3 -0
  587. package/dist/wall/rectangle-command.d.ts +111 -12
  588. package/dist/wall/rectangle-command.d.ts.map +1 -1
  589. package/dist/wall/rectangle-tool.d.ts.map +1 -1
  590. package/dist/wall/rectangle-tool.js +26 -8
  591. package/dist/wall/renderer.d.ts.map +1 -1
  592. package/dist/wall/renderer.js +4 -2
  593. package/dist/wall/split-floorplan-layer.d.ts.map +1 -1
  594. package/dist/wall/split-floorplan-layer.js +7 -7
  595. package/dist/wall/split-session.d.ts.map +1 -1
  596. package/dist/wall/split-session.js +7 -1
  597. package/dist/wall/system.d.ts.map +1 -1
  598. package/dist/wall/system.js +36 -4
  599. package/dist/wall/tool.d.ts.map +1 -1
  600. package/dist/wall/tool.js +105 -49
  601. package/dist/wall/treatment-level-data.d.ts +3 -2
  602. package/dist/wall/treatment-level-data.d.ts.map +1 -1
  603. package/dist/wall/treatment-level-data.js +17 -13
  604. package/dist/wall/treatments.d.ts +10 -10
  605. package/dist/wall/treatments.d.ts.map +1 -1
  606. package/dist/wall/treatments.js +67 -54
  607. package/dist/wall/wall-batch-system.d.ts +7 -0
  608. package/dist/wall/wall-batch-system.d.ts.map +1 -1
  609. package/dist/wall/wall-batch-system.js +35 -3
  610. package/dist/wall/wall-batch.d.ts +6 -0
  611. package/dist/wall/wall-batch.d.ts.map +1 -1
  612. package/dist/wall/wall-batch.js +7 -1
  613. package/dist/window/definition.d.ts.map +1 -1
  614. package/dist/window/definition.js +12 -4
  615. package/dist/window/floorplan-move.d.ts.map +1 -1
  616. package/dist/window/floorplan-move.js +3 -1
  617. package/dist/window/floorplan.d.ts.map +1 -1
  618. package/dist/window/floorplan.js +145 -60
  619. package/dist/window/mechanism.d.ts +4 -0
  620. package/dist/window/mechanism.d.ts.map +1 -0
  621. package/dist/window/mechanism.js +20 -0
  622. package/dist/window/move-tool.d.ts.map +1 -1
  623. package/dist/window/move-tool.js +79 -48
  624. package/dist/window/paint.d.ts.map +1 -1
  625. package/dist/window/paint.js +3 -0
  626. package/dist/window/panel.d.ts.map +1 -1
  627. package/dist/window/panel.js +32 -88
  628. package/dist/window/placement.d.ts +23 -0
  629. package/dist/window/placement.d.ts.map +1 -0
  630. package/dist/window/placement.js +66 -0
  631. package/dist/window/preview.d.ts.map +1 -1
  632. package/dist/window/preview.js +2 -0
  633. package/dist/window/renderer.d.ts.map +1 -1
  634. package/dist/window/renderer.js +3 -2
  635. package/dist/window/tool.d.ts.map +1 -1
  636. package/dist/window/tool.js +96 -24
  637. package/dist/window/window-math.d.ts +6 -14
  638. package/dist/window/window-math.d.ts.map +1 -1
  639. package/dist/window/window-math.js +14 -20
  640. package/dist/zone/contextual-dimensions.d.ts.map +1 -1
  641. package/dist/zone/contextual-dimensions.js +6 -28
  642. package/dist/zone/definition.d.ts.map +1 -1
  643. package/dist/zone/definition.js +3 -3
  644. package/dist/zone/floorplan-affordances.d.ts +200 -0
  645. package/dist/zone/floorplan-affordances.d.ts.map +1 -1
  646. package/dist/zone/floorplan.d.ts +1 -1
  647. package/dist/zone/floorplan.d.ts.map +1 -1
  648. package/dist/zone/floorplan.js +93 -53
  649. package/dist/zone/quantities-panel.d.ts.map +1 -1
  650. package/dist/zone/quantities-panel.js +3 -14
  651. package/dist/zone/quick-measurement.d.ts +2 -2
  652. package/dist/zone/quick-measurement.d.ts.map +1 -1
  653. package/dist/zone/quick-measurement.js +6 -5
  654. package/dist/zone/renderer.d.ts +1 -1
  655. package/dist/zone/renderer.d.ts.map +1 -1
  656. package/dist/zone/renderer.js +58 -146
  657. package/dist/zone/room-clear-dimensions.js +3 -3
  658. package/dist/zone/room-documentation.d.ts.map +1 -1
  659. package/dist/zone/room-documentation.js +2 -6
  660. package/package.json +11 -11
  661. package/dist/block/slots.d.ts +0 -4
  662. package/dist/block/slots.d.ts.map +0 -1
  663. package/dist/block/slots.js +0 -17
  664. package/dist/cabinet/slots.d.ts +0 -4
  665. package/dist/cabinet/slots.d.ts.map +0 -1
  666. package/dist/cabinet/slots.js +0 -24
  667. package/dist/ceiling/slots.d.ts +0 -6
  668. package/dist/ceiling/slots.d.ts.map +0 -1
  669. package/dist/ceiling/slots.js +0 -7
  670. package/dist/column/slots.d.ts +0 -9
  671. package/dist/column/slots.d.ts.map +0 -1
  672. package/dist/column/slots.js +0 -19
  673. package/dist/door/slots.d.ts +0 -9
  674. package/dist/door/slots.d.ts.map +0 -1
  675. package/dist/door/slots.js +0 -20
  676. package/dist/elevator/slots.d.ts +0 -8
  677. package/dist/elevator/slots.d.ts.map +0 -1
  678. package/dist/elevator/slots.js +0 -17
  679. package/dist/fence/slots.d.ts +0 -10
  680. package/dist/fence/slots.d.ts.map +0 -1
  681. package/dist/fence/slots.js +0 -23
  682. package/dist/item/__fixtures__/main-floorplan.d.ts +0 -26
  683. package/dist/item/__fixtures__/main-floorplan.d.ts.map +0 -1
  684. package/dist/item/__fixtures__/main-floorplan.js +0 -297
  685. package/dist/lean-to-extension/slots.d.ts +0 -5
  686. package/dist/lean-to-extension/slots.d.ts.map +0 -1
  687. package/dist/lean-to-extension/slots.js +0 -15
  688. package/dist/shelf/slots.d.ts +0 -9
  689. package/dist/shelf/slots.d.ts.map +0 -1
  690. package/dist/shelf/slots.js +0 -30
  691. package/dist/slab/slots.d.ts +0 -10
  692. package/dist/slab/slots.d.ts.map +0 -1
  693. package/dist/slab/slots.js +0 -20
  694. package/dist/stair/floor-stack.d.ts +0 -10
  695. package/dist/stair/floor-stack.d.ts.map +0 -1
  696. package/dist/stair/floor-stack.js +0 -115
  697. package/dist/stair/slots.d.ts +0 -7
  698. package/dist/stair/slots.d.ts.map +0 -1
  699. package/dist/stair/slots.js +0 -13
  700. package/dist/wall/drawing-mode.d.ts +0 -12
  701. package/dist/wall/drawing-mode.d.ts.map +0 -1
  702. package/dist/wall/drawing-mode.js +0 -38
  703. package/dist/wall/slots.d.ts +0 -10
  704. package/dist/wall/slots.d.ts.map +0 -1
  705. package/dist/wall/slots.js +0 -92
  706. package/dist/window/slots.d.ts +0 -5
  707. package/dist/window/slots.d.ts.map +0 -1
  708. package/dist/window/slots.js +0 -11
@@ -219,70 +219,10 @@ export function snapLocalXToNeighbors(args) {
219
219
  return bestDelta === null ? null : localX + bestDelta;
220
220
  }
221
221
  /**
222
- * Does a wall-hosted opening of `width × height` centred at `(clampedX,
223
- * clampedY)` (wall-local) overlap any OTHER child of `wallId` (door / window /
224
- * wall-mounted item)? AABB test in the wall's local face plane. `ignoreId`
225
- * excludes the moving node itself. Returns `true` (blocked) if the wall is
226
- * gone.
227
- *
228
- * Single source of truth for door + window placement collision — door-math and
229
- * window-math had byte-identical copies of this. Y conventions differ per kind
230
- * (items store bottom Y; doors/windows store centre Y), handled inline.
222
+ * Whether a wall-hosted opening would overlap another child of its wall. The rule lives in
223
+ * core, shared with every agent surface (`planWallOpening`); re-exported for the tools here.
231
224
  */
232
- export function hasWallChildOverlap(wallId, nodes, clampedX, clampedY, width, height, ignoreId) {
233
- const wallNode = nodes[wallId];
234
- if (!wallNode)
235
- return true;
236
- const halfW = width / 2;
237
- const halfH = height / 2;
238
- const newBottom = clampedY - halfH;
239
- const newTop = clampedY + halfH;
240
- const newLeft = clampedX - halfW;
241
- const newRight = clampedX + halfW;
242
- for (const childId of Array.isArray(wallNode.children) ? wallNode.children : []) {
243
- if (childId === ignoreId)
244
- continue;
245
- const child = nodes[childId];
246
- if (!child || child.metadata.isTransient)
247
- continue;
248
- let childLeft;
249
- let childRight;
250
- let childBottom;
251
- let childTop;
252
- if (child.type === 'item') {
253
- const item = child;
254
- if (item.asset.attachTo !== 'wall' && item.asset.attachTo !== 'wall-side')
255
- continue;
256
- const [w, h] = getScaledDimensions(item);
257
- childLeft = item.position[0] - w / 2;
258
- childRight = item.position[0] + w / 2;
259
- childBottom = item.position[1]; // items store bottom Y
260
- childTop = item.position[1] + h;
261
- }
262
- else if (child.type === 'window') {
263
- const win = child;
264
- childLeft = win.position[0] - win.width / 2;
265
- childRight = win.position[0] + win.width / 2;
266
- childBottom = win.position[1] - win.height / 2; // windows store centre Y
267
- childTop = win.position[1] + win.height / 2;
268
- }
269
- else if (child.type === 'door') {
270
- const door = child;
271
- childLeft = door.position[0] - door.width / 2;
272
- childRight = door.position[0] + door.width / 2;
273
- childBottom = door.position[1] - door.height / 2; // doors store centre Y
274
- childTop = door.position[1] + door.height / 2;
275
- }
276
- else {
277
- continue;
278
- }
279
- const xOverlap = newLeft < childRight && newRight > childLeft;
280
- const yOverlap = newBottom < childTop && newTop > childBottom;
281
- if (xOverlap && yOverlap)
282
- return true;
283
- }
284
- return false;
285
- }
225
+ export { hasWallChildOverlap } from '@pascal-app/core/building';
286
226
  /**
287
227
  * Resolve the placement state from the raw collision result and whether the
288
228
  * user is force-placing (held Alt). Force-place lifts the collision block, so the
@@ -1,4 +1,5 @@
1
- import { type AnyNode, type AnyNodeId, type WallNode } from '@pascal-app/core';
1
+ import { type AnyNode, type AnyNodeId, type DoorNode } from '@pascal-app/core';
2
+ import { resolveWallOpeningCeiling } from '@pascal-app/core/building';
2
3
  /**
3
4
  * Structural subset of `SceneApi` the opening-cap readers need — matches
4
5
  * both handle-descriptor callbacks (which receive the full SceneApi) and
@@ -8,23 +9,12 @@ export type WallCeilingSceneReader = {
8
9
  get: (id: AnyNodeId) => unknown;
9
10
  nodes: () => Readonly<Record<AnyNodeId, AnyNode>>;
10
11
  };
11
- /**
12
- * Available wall-local Y span for an opening hosted on `wall`: the wall's
13
- * resolved top (storey plane for plane-bound walls, stored height for
14
- * explicit ones) minus the wall's elected slab base. Wall-local Y = 0 sits
15
- * at the elected base (where the viewer positions the wall mesh), so this
16
- * is the ceiling an opening's top edge must stay under.
17
- *
18
- * Uses the same slab election as the viewer's WallSystem
19
- * (`spatialGridManager.getSlabSupportForWall`) so the cap agrees with the
20
- * rendered wall; headless callers with an empty spatial grid elect base 0
21
- * and fall back to the full storey height.
22
- */
23
- export declare function resolveWallOpeningCeiling(wall: WallNode, nodes: Readonly<Record<AnyNodeId, AnyNode>>): number;
12
+ /** The ceiling an opening's top edge must stay under: the shared rule in core. */
13
+ export { resolveWallOpeningCeiling };
24
14
  /**
25
15
  * Height cap for a wall-hosted opening's resize handles. Infinity only when
26
16
  * the opening is unhosted (no wallId, or the wall is gone) — roof-hosted
27
17
  * openings clamp elsewhere.
28
18
  */
29
- export declare function readHostWallCeiling(wallId: string | null | undefined, scene: WallCeilingSceneReader): number;
19
+ export declare function readHostWallCeiling(wallId: string | null | undefined, scene: WallCeilingSceneReader, opening?: Pick<DoorNode, 'position' | 'width' | 'height'>): number;
30
20
  //# sourceMappingURL=wall-opening-ceiling.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"wall-opening-ceiling.d.ts","sourceRoot":"","sources":["../../src/shared/wall-opening-ceiling.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,SAAS,EAEd,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AAEzB;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,GAAG,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,OAAO,CAAA;IAC/B,KAAK,EAAE,MAAM,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAA;CAClD,CAAA;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,GAC1C,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACjC,KAAK,EAAE,sBAAsB,GAC5B,MAAM,CAKR"}
1
+ {"version":3,"file":"wall-opening-ceiling.d.ts","sourceRoot":"","sources":["../../src/shared/wall-opening-ceiling.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,QAAQ,EAId,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAA;AAErE;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,GAAG,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,OAAO,CAAA;IAC/B,KAAK,EAAE,MAAM,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAA;CAClD,CAAA;AAED,kFAAkF;AAClF,OAAO,EAAE,yBAAyB,EAAE,CAAA;AAEpC;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACjC,KAAK,EAAE,sBAAsB,EAC7B,OAAO,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC,GACxD,MAAM,CASR"}
@@ -1,29 +1,21 @@
1
- import { getWallEffectiveHeightForNodes, } from '@pascal-app/core';
2
- /**
3
- * Available wall-local Y span for an opening hosted on `wall`: the wall's
4
- * resolved top (storey plane for plane-bound walls, stored height for
5
- * explicit ones) minus the wall's elected slab base. Wall-local Y = 0 sits
6
- * at the elected base (where the viewer positions the wall mesh), so this
7
- * is the ceiling an opening's top edge must stay under.
8
- *
9
- * Uses the same slab election as the viewer's WallSystem
10
- * (`spatialGridManager.getSlabSupportForWall`) so the cap agrees with the
11
- * rendered wall; headless callers with an empty spatial grid elect base 0
12
- * and fall back to the full storey height.
13
- */
14
- export function resolveWallOpeningCeiling(wall, nodes) {
15
- return getWallEffectiveHeightForNodes(wall, nodes);
16
- }
1
+ import { getOpeningFloorDatum, wallSupportForNodes, } from '@pascal-app/core';
2
+ import { resolveWallOpeningCeiling } from '@pascal-app/core/building';
3
+ /** The ceiling an opening's top edge must stay under: the shared rule in core. */
4
+ export { resolveWallOpeningCeiling };
17
5
  /**
18
6
  * Height cap for a wall-hosted opening's resize handles. Infinity only when
19
7
  * the opening is unhosted (no wallId, or the wall is gone) — roof-hosted
20
8
  * openings clamp elsewhere.
21
9
  */
22
- export function readHostWallCeiling(wallId, scene) {
10
+ export function readHostWallCeiling(wallId, scene, opening) {
23
11
  if (!wallId)
24
12
  return Number.POSITIVE_INFINITY;
25
13
  const wall = scene.get(wallId);
26
14
  if (!wall)
27
15
  return Number.POSITIVE_INFINITY;
28
- return resolveWallOpeningCeiling(wall, scene.nodes());
16
+ const nodes = scene.nodes();
17
+ const lift = opening
18
+ ? getOpeningFloorDatum(wall, opening, nodes) - wallSupportForNodes(wall, nodes).elevation
19
+ : 0;
20
+ return resolveWallOpeningCeiling(wall, nodes) - lift;
29
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/shelf/definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,cAAc,EAA8B,MAAM,kBAAkB,CAAA;AASpG,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AA4HpC,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,OAAO,SAAS,CAyJ5D,CAAA"}
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/shelf/definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,cAAc,EAA8B,MAAM,kBAAkB,CAAA;AAUpG,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AA2HpC,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,OAAO,SAAS,CAyJ5D,CAAA"}
@@ -1,3 +1,4 @@
1
+ import { shelfSlots } from '@pascal-app/core';
1
2
  import { restingFloorplanAffectedIds } from '../shared/resting-surface-plan';
2
3
  import { sanitizeShelfDimensions } from './dimensions';
3
4
  import { buildShelfFloorplan } from './floorplan';
@@ -7,7 +8,6 @@ import { buildShelfGeometry, shelfRowSurfaceYs } from './geometry';
7
8
  import { shelfPaint } from './paint';
8
9
  import { shelfParametrics } from './parametrics';
9
10
  import { ShelfNode } from './schema';
10
- import { shelfSlots } from './slots';
11
11
  const SIDE_HANDLE_OFFSET = 0.18;
12
12
  const HEIGHT_HANDLE_OFFSET = 0.22;
13
13
  const ROTATE_CORNER_OFFSET = 0.32;
@@ -1 +1 @@
1
- {"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../src/shelf/geometry.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EAGrB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAIL,KAAK,aAAa,EAEnB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAe,KAAK,EAAuB,MAAM,OAAO,CAAA;AAE/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AA0EzC,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,SAAS,EAClB,GAAG,CAAC,EAAE,eAAe,EACrB,OAAO,GAAE,aAA0B,GAClC,KAAK,CAkCP;AAySD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,EAAE,CAM3D"}
1
+ {"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../src/shelf/geometry.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EAKrB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAIL,KAAK,aAAa,EAEnB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAe,KAAK,EAAuB,MAAM,OAAO,CAAA;AAE/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAyEzC,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,SAAS,EAClB,GAAG,CAAC,EAAE,eAAe,EACrB,OAAO,GAAE,aAA0B,GAClC,KAAK,CAkCP;AAySD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,EAAE,CAM3D"}
@@ -1,8 +1,7 @@
1
- import { SHELF_BOARD_INSET as BOARD_INSET, getMaterialPresetByRef, shelfBoardDimensions, } from '@pascal-app/core';
1
+ import { SHELF_BOARD_INSET as BOARD_INSET, getMaterialPresetByRef, SHELF_SLOT_DEFAULT_COLOR, shelfBoardDimensions, } from '@pascal-app/core';
2
2
  import { applyMaterialPresetToMaterials, createDefaultMaterial, createMaterial, resolveMaterialRef, } from '@pascal-app/viewer';
3
3
  import { BoxGeometry, Group, Mesh } from 'three';
4
4
  import { sanitizeShelfDimensions } from './dimensions';
5
- import { SHELF_SLOT_DEFAULT_COLOR } from './slots';
6
5
  function getShelfSlotMaterial(node, slotId, materials, shading) {
7
6
  const ref = node.slots?.[slotId];
8
7
  if (ref) {
@@ -1 +1 @@
1
- {"version":3,"file":"paint.d.ts","sourceRoot":"","sources":["../../src/shelf/paint.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,eAAe,EAOrB,MAAM,kBAAkB,CAAA;AAmLzB,eAAO,MAAM,UAAU,EAAE,eA0BxB,CAAA"}
1
+ {"version":3,"file":"paint.d.ts","sourceRoot":"","sources":["../../src/shelf/paint.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,eAAe,EAOrB,MAAM,kBAAkB,CAAA;AAmLzB,eAAO,MAAM,UAAU,EAAE,eAoBxB,CAAA"}
@@ -1,4 +1,4 @@
1
- import { generateSceneMaterialId, parseMaterialRef, toSceneMaterialRef, useScene, } from '@pascal-app/core';
1
+ import { generateSceneMaterialId, slotPaintMaterial, toSceneMaterialRef, useScene, } from '@pascal-app/core';
2
2
  import { createMaterial, createMaterialFromPresetRef, useViewer } from '@pascal-app/viewer';
3
3
  function deepEqual(a, b) {
4
4
  if (Object.is(a, b))
@@ -162,15 +162,9 @@ export const shelfPaint = {
162
162
  applyPreview: ({ role, root, material, materialPreset }) => applyShelfPreview(role, root, material, materialPreset),
163
163
  getEffectiveMaterial: ({ node, role }) => {
164
164
  const shelf = node;
165
- const parsed = parseMaterialRef(shelf.slots?.[role]);
166
- if (parsed) {
167
- if (parsed.kind === 'library') {
168
- return { material: undefined, materialPreset: shelf.slots?.[role] };
169
- }
170
- const sceneMaterial = useScene.getState().materials[parsed.id];
171
- if (sceneMaterial)
172
- return { material: sceneMaterial.material, materialPreset: undefined };
173
- }
165
+ const painted = slotPaintMaterial(shelf.slots?.[role], useScene.getState().materials);
166
+ if (painted)
167
+ return painted;
174
168
  // No (or dangling) slot ref — surface the legacy whole-shelf paint the
175
169
  // geometry builder still falls back to, so the picker matches what renders.
176
170
  if (shelf.materialPreset || shelf.material) {
@@ -0,0 +1,31 @@
1
+ /**
2
+ * A patterned RIBBON along a draped polyline — the way a property line or a
3
+ * setback line is drawn on the ground in 3D. WebGL ignores line widths, so
4
+ * a thick line is a flat mesh: the polyline (already draped on the terrain
5
+ * by `buildDrapedPolyline`) is walked by arc length, the on / off pattern
6
+ * is unrolled along it (metres: dash, gap, dot, gap, dot, gap — the
7
+ * standard property line; dash, gap — a setback), and every "on" run
8
+ * becomes quads `width` wide lying flat in the XZ plane at the draped
9
+ * height. Pure; the renderer wraps the geometry in a mesh.
10
+ *
11
+ * The property line draws dark and thick in the standard dash-dot-dot
12
+ * pattern; the setbacks draw black and dashed.
13
+ */
14
+ import { type TerrainField } from '@pascal-app/core';
15
+ import { BufferGeometry } from 'three';
16
+ /** The standard property line: a long dash, two dots (metres). */
17
+ export declare const PROPERTY_LINE_PATTERN: readonly number[];
18
+ /** A setback line: dashed. */
19
+ export declare const SETBACK_LINE_PATTERN: readonly number[];
20
+ /**
21
+ * Re-drape a ribbon on a changed field: every vertex keeps its XZ and takes
22
+ * the ground's height there plus `lift` (a sculpt stroke mid-flight).
23
+ */
24
+ export declare function updateRibbonHeights(geometry: BufferGeometry, field: TerrainField | null, lift: number): void;
25
+ /**
26
+ * Build the ribbon. `positions` is the draped polyline (xyz per vertex,
27
+ * consecutive, NOT closed — pass the closing vertex yourself); `pattern`
28
+ * alternates on / off lengths in metres; `width` is the ribbon's full width.
29
+ */
30
+ export declare function buildPatternedRibbon(positions: Float32Array, pattern: readonly number[], width: number, step?: number): BufferGeometry;
31
+ //# sourceMappingURL=line-ribbon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-ribbon.d.ts","sourceRoot":"","sources":["../../src/site/line-ribbon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACrE,OAAO,EAAmB,cAAc,EAAE,MAAM,OAAO,CAAA;AAEvD,kEAAkE;AAClE,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAAqC,CAAA;AACxF,8BAA8B;AAC9B,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAAe,CAAA;AAyBjE;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,YAAY,GAAG,IAAI,EAC1B,IAAI,EAAE,MAAM,GACX,IAAI,CAWN;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,YAAY,EACvB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,KAAK,EAAE,MAAM,EACb,IAAI,SAAO,GACV,cAAc,CAmDhB"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * A patterned RIBBON along a draped polyline — the way a property line or a
3
+ * setback line is drawn on the ground in 3D. WebGL ignores line widths, so
4
+ * a thick line is a flat mesh: the polyline (already draped on the terrain
5
+ * by `buildDrapedPolyline`) is walked by arc length, the on / off pattern
6
+ * is unrolled along it (metres: dash, gap, dot, gap, dot, gap — the
7
+ * standard property line; dash, gap — a setback), and every "on" run
8
+ * becomes quads `width` wide lying flat in the XZ plane at the draped
9
+ * height. Pure; the renderer wraps the geometry in a mesh.
10
+ *
11
+ * The property line draws dark and thick in the standard dash-dot-dot
12
+ * pattern; the setbacks draw black and dashed.
13
+ */
14
+ import { surfaceHeightAt } from '@pascal-app/core';
15
+ import { BufferAttribute, BufferGeometry } from 'three';
16
+ /** The standard property line: a long dash, two dots (metres). */
17
+ export const PROPERTY_LINE_PATTERN = [3.0, 0.6, 0.35, 0.6, 0.35, 0.6];
18
+ /** A setback line: dashed. */
19
+ export const SETBACK_LINE_PATTERN = [1.2, 0.6];
20
+ /** The draped polyline's vertices, xyz per vertex. */
21
+ function vertexAt(positions, i) {
22
+ return [positions[i * 3] ?? 0, positions[i * 3 + 1] ?? 0, positions[i * 3 + 2] ?? 0];
23
+ }
24
+ /** Point at arc length `s` along the polyline (plan length), with the local XZ direction. */
25
+ function sample(positions, cum, s) {
26
+ const count = cum.length;
27
+ let i = 0;
28
+ while (i + 1 < count - 1 && cum[i + 1] < s)
29
+ i++;
30
+ const a = vertexAt(positions, i);
31
+ const b = vertexAt(positions, Math.min(count - 1, i + 1));
32
+ const seg = cum[i + 1] - cum[i];
33
+ const t = seg > 1e-9 ? Math.max(0, Math.min(1, (s - cum[i]) / seg)) : 0;
34
+ const p = [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t];
35
+ const dx = b[0] - a[0];
36
+ const dz = b[2] - a[2];
37
+ const len = Math.hypot(dx, dz) || 1;
38
+ return { p, d: [dx / len, dz / len] };
39
+ }
40
+ /**
41
+ * Re-drape a ribbon on a changed field: every vertex keeps its XZ and takes
42
+ * the ground's height there plus `lift` (a sculpt stroke mid-flight).
43
+ */
44
+ export function updateRibbonHeights(geometry, field, lift) {
45
+ const attribute = geometry.getAttribute('position');
46
+ if (!attribute)
47
+ return;
48
+ const array = attribute.array;
49
+ for (let i = 0; i < attribute.count; i++) {
50
+ const x = array[i * 3] ?? 0;
51
+ const z = array[i * 3 + 2] ?? 0;
52
+ array[i * 3 + 1] = field ? surfaceHeightAt(field, x, z) + lift : lift;
53
+ }
54
+ attribute.needsUpdate = true;
55
+ geometry.computeBoundingSphere();
56
+ }
57
+ /**
58
+ * Build the ribbon. `positions` is the draped polyline (xyz per vertex,
59
+ * consecutive, NOT closed — pass the closing vertex yourself); `pattern`
60
+ * alternates on / off lengths in metres; `width` is the ribbon's full width.
61
+ */
62
+ export function buildPatternedRibbon(positions, pattern, width, step = 0.25) {
63
+ const count = Math.floor(positions.length / 3);
64
+ const geometry = new BufferGeometry();
65
+ if (count < 2 || pattern.length < 2)
66
+ return geometry;
67
+ // cumulative PLAN arc length per vertex
68
+ const cum = [0];
69
+ for (let i = 1; i < count; i++) {
70
+ const a = vertexAt(positions, i - 1);
71
+ const b = vertexAt(positions, i);
72
+ cum.push(cum[i - 1] + Math.hypot(b[0] - a[0], b[2] - a[2]));
73
+ }
74
+ const total = cum[count - 1];
75
+ if (total < 1e-6)
76
+ return geometry;
77
+ const period = pattern.reduce((s, v) => s + v, 0);
78
+ if (period <= 0)
79
+ return geometry;
80
+ const verts = [];
81
+ const index = [];
82
+ const half = width / 2;
83
+ // walk the pattern along the line; each "on" run is a strip of quads
84
+ let s = 0;
85
+ let k = 0;
86
+ while (s < total) {
87
+ const len = pattern[k % pattern.length];
88
+ const on = k % 2 === 0;
89
+ const s0 = s;
90
+ const s1 = Math.min(total, s + len);
91
+ if (on && s1 - s0 > 1e-6) {
92
+ // subdivide the run so it follows corners and the drape
93
+ const n = Math.max(1, Math.ceil((s1 - s0) / step));
94
+ const base = verts.length / 3;
95
+ for (let j = 0; j <= n; j++) {
96
+ const { p, d } = sample(positions, cum, s0 + ((s1 - s0) * j) / n);
97
+ // the ribbon's normal in plan is the line direction turned 90°
98
+ const nx = -d[1] * half;
99
+ const nz = d[0] * half;
100
+ verts.push(p[0] + nx, p[1], p[2] + nz, p[0] - nx, p[1], p[2] - nz);
101
+ }
102
+ for (let j = 0; j < n; j++) {
103
+ const a = base + j * 2;
104
+ index.push(a, a + 1, a + 2, a + 1, a + 3, a + 2);
105
+ }
106
+ }
107
+ s = s1;
108
+ k++;
109
+ if (k > 100000)
110
+ break;
111
+ }
112
+ geometry.setAttribute('position', new BufferAttribute(new Float32Array(verts), 3));
113
+ geometry.setIndex(index);
114
+ geometry.computeVertexNormals();
115
+ geometry.computeBoundingSphere();
116
+ return geometry;
117
+ }
@@ -0,0 +1,18 @@
1
+ import type { Material } from 'three';
2
+ import type { Node } from 'three/webgpu';
3
+ type Point = readonly [number, number];
4
+ /**
5
+ * True for a fragment inside the lot polygon (even-odd crossing count on its
6
+ * local x, z). Unrolled edge by edge into the graph: a parcel has tens of
7
+ * corners, so a loop and a uniform array would buy nothing.
8
+ */
9
+ export declare function insideLotNode(polygon: ReadonlyArray<Point>): Node<"bool">;
10
+ /**
11
+ * The ground material cut to the lot: the terrain field is the padded,
12
+ * north-up box around the parcel, and only the parcel itself is ground the
13
+ * project owns. Per fragment, so the edge is the property line exactly and
14
+ * follows a sculpt stroke with no rebuild; the shadow pass honours the mask too.
15
+ */
16
+ export declare function lotMaskedMaterial(material: Material, polygon: ReadonlyArray<Point>): Material;
17
+ export {};
18
+ //# sourceMappingURL=lot-mask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lot-mask.d.ts","sourceRoot":"","sources":["../../src/site/lot-mask.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAErC,OAAO,KAAK,EAAE,IAAI,EAAgB,MAAM,cAAc,CAAA;AAEtD,KAAK,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAEtC;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,gBAgB1D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG,QAAQ,CAI7F"}
@@ -0,0 +1,35 @@
1
+ import { float, mod, positionLocal, select } from 'three/tsl';
2
+ /**
3
+ * True for a fragment inside the lot polygon (even-odd crossing count on its
4
+ * local x, z). Unrolled edge by edge into the graph: a parcel has tens of
5
+ * corners, so a loop and a uniform array would buy nothing.
6
+ */
7
+ export function insideLotNode(polygon) {
8
+ const at = positionLocal.xz;
9
+ let crossings = float(0);
10
+ for (let i = 0; i < polygon.length; i++) {
11
+ const [ax, az] = polygon[i];
12
+ const [bx, bz] = polygon[(i + 1) % polygon.length];
13
+ if (az === bz)
14
+ continue;
15
+ const slope = (bx - ax) / (bz - az);
16
+ const crossesAt = at.y.sub(az).mul(slope).add(ax);
17
+ const crosses = at.y
18
+ .greaterThanEqual(Math.min(az, bz))
19
+ .and(at.y.lessThan(Math.max(az, bz)))
20
+ .and(at.x.lessThan(crossesAt));
21
+ crossings = crossings.add(select(crosses, float(1), float(0)));
22
+ }
23
+ return mod(crossings, float(2)).greaterThan(0.5);
24
+ }
25
+ /**
26
+ * The ground material cut to the lot: the terrain field is the padded,
27
+ * north-up box around the parcel, and only the parcel itself is ground the
28
+ * project owns. Per fragment, so the edge is the property line exactly and
29
+ * follows a sculpt stroke with no rebuild; the shadow pass honours the mask too.
30
+ */
31
+ export function lotMaskedMaterial(material, polygon) {
32
+ const masked = material.clone();
33
+ masked.maskNode = insideLotNode(polygon);
34
+ return masked;
35
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Site inspector — address → real parcel, plus the zoning inputs the site
3
+ * plan draws from. Mounted through `siteParametrics.customPanel`.
4
+ *
5
+ * The address lookup goes through the host's parcel provider
6
+ * (`setParcelProvider`) and is hidden when the host has none.
7
+ */
8
+ export declare function SiteNodePanel(): import("react").JSX.Element | null;
9
+ export default SiteNodePanel;
10
+ //# sourceMappingURL=panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/site/panel.tsx"],"names":[],"mappings":"AA6BA;;;;;;GAMG;AACH,wBAAgB,aAAa,uCA8T5B;AAWD,eAAe,aAAa,CAAA"}
@@ -0,0 +1,155 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useScene } from '@pascal-app/core';
4
+ import { ActionButton, ActionGroup, describeSiteEdges, dropInLot, PanelSection, PanelWrapper, useParcelProvider, } from '@pascal-app/editor';
5
+ import { useViewer } from '@pascal-app/viewer';
6
+ import { MapPin, Search } from 'lucide-react';
7
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
8
+ const METRES_PER_FOOT = 0.3048;
9
+ /**
10
+ * Site inspector — address → real parcel, plus the zoning inputs the site
11
+ * plan draws from. Mounted through `siteParametrics.customPanel`.
12
+ *
13
+ * The address lookup goes through the host's parcel provider
14
+ * (`setParcelProvider`) and is hidden when the host has none.
15
+ */
16
+ export function SiteNodePanel() {
17
+ const selectedId = useViewer((s) => s.selection.selectedIds[0]);
18
+ // The selected site node, else THE site node: the sidebar's Site header
19
+ // mounts this panel directly, where nothing may be selected.
20
+ const node = useScene((s) => {
21
+ const selected = selectedId
22
+ ? s.nodes[selectedId]
23
+ : undefined;
24
+ if (selected?.type === 'site')
25
+ return selected;
26
+ for (const id of s.rootNodeIds) {
27
+ const n = s.nodes[id];
28
+ if (n?.type === 'site')
29
+ return n;
30
+ }
31
+ return undefined;
32
+ });
33
+ const [query, setQuery] = useState('');
34
+ const [suggestions, setSuggestions] = useState([]);
35
+ const [picked, setPicked] = useState(null);
36
+ const [status, setStatus] = useState(null);
37
+ const [busy, setBusy] = useState(false);
38
+ const requestSeq = useRef(0);
39
+ const parcelProvider = useParcelProvider();
40
+ const update = useCallback((patch) => {
41
+ if (!node)
42
+ return;
43
+ useScene.getState().updateNode(node.id, patch);
44
+ }, [node]);
45
+ // Seed the address box from the node so reopening the panel shows what the
46
+ // lot was resolved from.
47
+ useEffect(() => {
48
+ if (!node?.address)
49
+ return;
50
+ const parts = [node.address.street, node.address.city, node.address.state, node.address.zip];
51
+ setQuery((current) => current || parts.filter(Boolean).join(', '));
52
+ }, [node?.address]);
53
+ // Debounced autocomplete. `seq` guards against an earlier response landing
54
+ // after a later one.
55
+ useEffect(() => {
56
+ const q = query.trim();
57
+ if (!parcelProvider || q.length < 4 || picked) {
58
+ setSuggestions([]);
59
+ return;
60
+ }
61
+ const seq = ++requestSeq.current;
62
+ const timer = setTimeout(() => {
63
+ parcelProvider('autocomplete', { q })
64
+ .then((data) => {
65
+ if (seq !== requestSeq.current)
66
+ return;
67
+ const list = data?.suggestions;
68
+ setSuggestions(Array.isArray(list) ? list : []);
69
+ })
70
+ .catch(() => {
71
+ if (seq === requestSeq.current)
72
+ setSuggestions([]);
73
+ });
74
+ }, 300);
75
+ return () => clearTimeout(timer);
76
+ }, [parcelProvider, query, picked]);
77
+ const edges = useMemo(() => describeSiteEdges(node ?? null), [node]);
78
+ // One engine for every path (Lot panel, Generate, here): resolve the
79
+ // parcel, map the streets, pick the street-facing edge, default the
80
+ // setbacks when the site has none, re-centre a building that fell outside
81
+ // the new ring. See @pascal-app/editor `dropInLot`.
82
+ const findParcel = useCallback(async () => {
83
+ if (!node)
84
+ return;
85
+ const address = query.trim();
86
+ if (!address) {
87
+ setStatus('Type an address first.');
88
+ return;
89
+ }
90
+ setBusy(true);
91
+ setStatus('Looking up the parcel and the streets around it…');
92
+ try {
93
+ const result = await dropInLot({
94
+ address,
95
+ ...(picked?.lat != null && picked?.lng != null
96
+ ? { latitude: picked.lat, longitude: picked.lng, state: picked.state }
97
+ : {}),
98
+ street: picked?.line1,
99
+ city: picked?.city,
100
+ zip: picked?.postcode,
101
+ }, { siteId: node.id });
102
+ setStatus(result.message);
103
+ }
104
+ catch (error) {
105
+ setStatus(error instanceof Error ? error.message : 'Parcel lookup failed.');
106
+ }
107
+ finally {
108
+ setBusy(false);
109
+ }
110
+ }, [node, picked, query]);
111
+ if (!node)
112
+ return null;
113
+ const setbacks = node.setbacks;
114
+ const setbackField = (key, label, optional = false) => (_jsxs("label", { className: "flex items-center justify-between gap-3 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: label }), _jsxs("span", { className: "flex items-center gap-1", children: [_jsx("input", { className: "w-20 rounded-md border border-border/70 bg-background px-2 py-1 text-right text-foreground", defaultValue: setbacks?.[key] != null
115
+ ? String(Math.round((setbacks[key] / METRES_PER_FOOT) * 10) / 10)
116
+ : '', inputMode: "decimal", onFocus: (event) => event.target.select(), onBlur: (event) => {
117
+ const raw = event.target.value.trim();
118
+ if (raw === '' && optional) {
119
+ const next = { ...(setbacks ?? { front: 0, rear: 0, side: 0 }) };
120
+ delete next[key];
121
+ update({ setbacks: next });
122
+ return;
123
+ }
124
+ const feet = Number(raw);
125
+ if (!Number.isFinite(feet) || feet < 0)
126
+ return;
127
+ update({
128
+ setbacks: {
129
+ ...(setbacks ?? { front: 0, rear: 0, side: 0 }),
130
+ [key]: feet * METRES_PER_FOOT,
131
+ },
132
+ });
133
+ }, placeholder: optional ? 'side' : '0' }, `${key}-${setbacks?.[key] ?? 'none'}`), _jsx("span", { className: "text-muted-foreground text-xs", children: "ft" })] })] }, key));
134
+ return (_jsxs(PanelWrapper, { title: "Site", children: [parcelProvider ? (_jsxs(PanelSection, { title: "Address", children: [_jsxs("label", { className: "space-y-1 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Street address" }), _jsx("input", { className: "w-full rounded-md border border-border/70 bg-background px-2 py-1.5 text-foreground", onChange: (event) => {
135
+ setQuery(event.target.value);
136
+ setPicked(null);
137
+ }, placeholder: "1200 W Cass St, Tampa, FL", value: query })] }), suggestions.length > 0 ? (_jsx("ul", { className: "max-h-44 space-y-0.5 overflow-y-auto rounded-md border border-border/70 bg-card p-1", children: suggestions.map((s) => (_jsx("li", { children: _jsxs("button", { className: "flex w-full items-start gap-2 rounded px-2 py-1.5 text-left text-foreground text-xs hover:bg-muted", onClick: () => {
138
+ setPicked(s);
139
+ setQuery(s.label ?? [s.line1, s.line2].filter(Boolean).join(', '));
140
+ setSuggestions([]);
141
+ }, type: "button", children: [_jsx(MapPin, { className: "mt-0.5 size-3 shrink-0 text-muted-foreground" }), _jsx("span", { children: s.label ?? [s.line1, s.line2].filter(Boolean).join(', ') })] }) }, `${s.label}-${s.lat}-${s.lng}`))) })) : null, _jsx(ActionGroup, { children: _jsx(ActionButton, { disabled: busy, icon: _jsx(Search, { className: "size-4" }), label: busy ? 'Finding…' : 'Find parcel', onClick: findParcel }) }), status ? _jsx("p", { className: "text-muted-foreground text-xs", children: status }) : null] })) : null, node.parcel ? (_jsxs(PanelSection, { title: "Parcel", children: [_jsx(Row, { label: "APN", value: node.parcel.apn || '—' }), _jsx(Row, { label: "County", value: node.parcel.county || '—' }), _jsx(Row, { label: "Lot area", value: node.parcel.lotAreaSqFt
142
+ ? `${Math.round(node.parcel.lotAreaSqFt).toLocaleString()} sq ft`
143
+ : '—' }), _jsx(Row, { label: "Source", value: node.parcel.layer || node.parcel.source || '—' }), node.parcel.notes?.length ? (_jsx("p", { className: "text-muted-foreground text-xs leading-snug", children: node.parcel.notes.join(' ') })) : null] })) : null, _jsxs(PanelSection, { title: "Setbacks", children: [setbackField('front', 'Front'), setbackField('side', 'Side'), setbackField('rear', 'Rear'), setbackField('left', 'Left (override)', true), setbackField('right', 'Right (override)', true), _jsxs("label", { className: "space-y-1 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Source / citation" }), _jsx("input", { className: "w-full rounded-md border border-border/70 bg-background px-2 py-1.5 text-foreground", defaultValue: node.setbacksSource ?? '', onBlur: (event) => update({ setbacksSource: event.target.value || undefined }), placeholder: "e.g. Tampa LDC \u00A727-156" }, node.setbacksSource ?? '')] }), _jsxs("label", { className: "space-y-1 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Zone" }), _jsx("input", { className: "w-full rounded-md border border-border/70 bg-background px-2 py-1.5 text-foreground", defaultValue: node.zone ?? '', onBlur: (event) => update({ zone: event.target.value || undefined }), placeholder: "e.g. RS-60" }, node.zone ?? '')] })] }), _jsxs(PanelSection, { title: "Terrain", children: [_jsxs("label", { className: "space-y-1 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Contour interval (site plan and 3D)" }), _jsxs("select", { className: "w-full rounded-md border border-border/70 bg-background px-2 py-1.5 text-foreground", onChange: (event) => update({ contourIntervalIn: Number(event.target.value) }), value: String(node.contourIntervalIn ?? 12), children: [_jsx("option", { value: "0", children: "none" }), _jsx("option", { value: "6", children: "every 6 in" }), _jsx("option", { value: "12", children: "every 12 in" }), _jsx("option", { value: "24", children: "every 24 in" })] })] }), _jsxs("label", { className: "flex items-center gap-2 text-sm", children: [_jsx("input", { checked: node.contours3d ?? false, onChange: (event) => update({ contours3d: event.target.checked }), type: "checkbox" }), _jsx("span", { className: "text-muted-foreground", children: "Show the contour lines in 3D" })] }), node.terrainContours ? (_jsxs("p", { className: "text-muted-foreground text-xs", children: [node.terrainContours.lines.length, " surveyed lines at ", node.terrainContours.intervalFt, ' ', "ft (", node.terrainContours.datum, ") \u2014 ", node.terrainContours.source ?? 'survey'] })) : (_jsx("p", { className: "text-muted-foreground text-xs", children: "No surveyed lines \u2014 contours are drawn from the sculpted ground." }))] }), _jsxs(PanelSection, { title: "Orientation", children: [_jsxs("label", { className: "space-y-1 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Front (street) edge" }), _jsxs("select", { className: "w-full rounded-md border border-border/70 bg-background px-2 py-1.5 text-foreground", onChange: (event) => update({
144
+ frontEdge: event.target.value === '' ? undefined : Number(event.target.value),
145
+ }), value: node.frontEdge == null ? '' : String(node.frontEdge), children: [_jsx("option", { value: "", children: "Auto \u2014 most north-facing edge" }), edges.map((edge) => (_jsx("option", { value: String(edge.index), children: edge.label }, edge.index)))] })] }), _jsxs("label", { className: "flex items-center justify-between gap-3 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "North rotation" }), _jsxs("span", { className: "flex items-center gap-1", children: [_jsx("input", { className: "w-20 rounded-md border border-border/70 bg-background px-2 py-1 text-right text-foreground", defaultValue: String(Math.round((((node.northRotation ?? 0) * 180) / Math.PI) * 10) / 10), inputMode: "decimal", onFocus: (event) => event.target.select(), onBlur: (event) => {
146
+ const deg = Number(event.target.value.trim());
147
+ if (!Number.isFinite(deg))
148
+ return;
149
+ update({ northRotation: (deg * Math.PI) / 180 });
150
+ } }, String(node.northRotation ?? 0)), _jsx("span", { className: "text-muted-foreground text-xs", children: "\u00B0" })] })] })] })] }));
151
+ }
152
+ function Row({ label, value }) {
153
+ return (_jsxs("div", { className: "flex items-center justify-between gap-3 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: label }), _jsx("span", { className: "truncate font-medium text-foreground", children: value })] }));
154
+ }
155
+ export default SiteNodePanel;
@@ -1,3 +1,10 @@
1
1
  import type { ParametricDescriptor, SiteNode } from '@pascal-app/core';
2
+ /**
3
+ * Inspector descriptor for site.
4
+ *
5
+ * `customPanel` mounts `<SitePanel>` — address autocomplete, the parcel
6
+ * lookup, setbacks and the front-edge picker need async network state and
7
+ * feet↔metres conversion that the auto-derived field kinds don't cover.
8
+ */
2
9
  export declare const siteParametrics: ParametricDescriptor<SiteNode>;
3
10
  //# sourceMappingURL=parametrics.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parametrics.d.ts","sourceRoot":"","sources":["../../src/site/parametrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEtE,eAAO,MAAM,eAAe,EAAE,oBAAoB,CAAC,QAAQ,CAE1D,CAAA"}
1
+ {"version":3,"file":"parametrics.d.ts","sourceRoot":"","sources":["../../src/site/parametrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEtE;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,oBAAoB,CAAC,QAAQ,CAG1D,CAAA"}