@pascal-app/nodes 1.0.5 → 1.0.7

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 (566) hide show
  1. package/README.md +1 -0
  2. package/dist/beam/actions/move-endpoint.d.ts +24 -0
  3. package/dist/beam/actions/move-endpoint.d.ts.map +1 -0
  4. package/dist/beam/actions/move-endpoint.js +54 -0
  5. package/dist/beam/definition.d.ts +14 -0
  6. package/dist/beam/definition.d.ts.map +1 -0
  7. package/dist/beam/definition.js +173 -0
  8. package/dist/beam/draft-settings.d.ts +17 -0
  9. package/dist/beam/draft-settings.d.ts.map +1 -0
  10. package/dist/beam/draft-settings.js +81 -0
  11. package/dist/beam/drafting.d.ts +35 -0
  12. package/dist/beam/drafting.d.ts.map +1 -0
  13. package/dist/beam/drafting.js +103 -0
  14. package/dist/beam/floorplan-affordances.d.ts +8 -0
  15. package/dist/beam/floorplan-affordances.d.ts.map +1 -0
  16. package/dist/beam/floorplan-affordances.js +40 -0
  17. package/dist/beam/floorplan-move.d.ts +11 -0
  18. package/dist/beam/floorplan-move.d.ts.map +1 -0
  19. package/dist/beam/floorplan-move.js +54 -0
  20. package/dist/beam/floorplan.d.ts +11 -0
  21. package/dist/beam/floorplan.d.ts.map +1 -0
  22. package/dist/beam/floorplan.js +91 -0
  23. package/dist/beam/geometry.d.ts +19 -0
  24. package/dist/beam/geometry.d.ts.map +1 -0
  25. package/dist/beam/geometry.js +63 -0
  26. package/dist/beam/index.d.ts +3 -0
  27. package/dist/beam/index.d.ts.map +1 -0
  28. package/dist/beam/index.js +2 -0
  29. package/dist/beam/move-endpoint-tool.d.ts +21 -0
  30. package/dist/beam/move-endpoint-tool.d.ts.map +1 -0
  31. package/dist/beam/move-endpoint-tool.js +49 -0
  32. package/dist/beam/move-tool.d.ts +12 -0
  33. package/dist/beam/move-tool.d.ts.map +1 -0
  34. package/dist/beam/move-tool.js +114 -0
  35. package/dist/beam/panel-model.d.ts +28 -0
  36. package/dist/beam/panel-model.d.ts.map +1 -0
  37. package/dist/beam/panel-model.js +123 -0
  38. package/dist/beam/panel.d.ts +13 -0
  39. package/dist/beam/panel.d.ts.map +1 -0
  40. package/dist/beam/panel.js +107 -0
  41. package/dist/beam/parametrics.d.ts +3 -0
  42. package/dist/beam/parametrics.d.ts.map +1 -0
  43. package/dist/beam/parametrics.js +4 -0
  44. package/dist/beam/renderer.d.ts +13 -0
  45. package/dist/beam/renderer.d.ts.map +1 -0
  46. package/dist/beam/renderer.js +36 -0
  47. package/dist/beam/schema.d.ts +2 -0
  48. package/dist/beam/schema.d.ts.map +1 -0
  49. package/dist/beam/schema.js +1 -0
  50. package/dist/beam/tool.d.ts +13 -0
  51. package/dist/beam/tool.d.ts.map +1 -0
  52. package/dist/beam/tool.js +152 -0
  53. package/dist/box-vent/panel.d.ts.map +1 -1
  54. package/dist/box-vent/panel.js +8 -7
  55. package/dist/cabinet/batchable.d.ts +10 -0
  56. package/dist/cabinet/batchable.d.ts.map +1 -0
  57. package/dist/cabinet/batchable.js +12 -0
  58. package/dist/cabinet/compartment-card.d.ts.map +1 -1
  59. package/dist/cabinet/compartment-card.js +142 -46
  60. package/dist/cabinet/countertop-layout.d.ts +5 -0
  61. package/dist/cabinet/countertop-layout.d.ts.map +1 -1
  62. package/dist/cabinet/definition.d.ts.map +1 -1
  63. package/dist/cabinet/definition.js +3 -0
  64. package/dist/cabinet/dimension-input.d.ts +6 -0
  65. package/dist/cabinet/dimension-input.d.ts.map +1 -0
  66. package/dist/cabinet/dimension-input.js +8 -0
  67. package/dist/cabinet/essential-controls.d.ts.map +1 -1
  68. package/dist/cabinet/essential-controls.js +82 -17
  69. package/dist/cabinet/index.d.ts +1 -1
  70. package/dist/cabinet/index.d.ts.map +1 -1
  71. package/dist/cabinet/index.js +1 -1
  72. package/dist/cabinet/kitchen-catalog.d.ts +17 -4
  73. package/dist/cabinet/kitchen-catalog.d.ts.map +1 -1
  74. package/dist/cabinet/kitchen-catalog.js +45 -7
  75. package/dist/cabinet/kitchen-collection.d.ts.map +1 -1
  76. package/dist/cabinet/kitchen-collection.js +21 -5
  77. package/dist/cabinet/kitchen-module-actions.d.ts.map +1 -1
  78. package/dist/cabinet/kitchen-module-actions.js +107 -14
  79. package/dist/cabinet/neighbor-placement.d.ts +10 -0
  80. package/dist/cabinet/neighbor-placement.d.ts.map +1 -1
  81. package/dist/cabinet/panel.d.ts.map +1 -1
  82. package/dist/cabinet/panel.js +127 -50
  83. package/dist/cabinet/run-finishing.d.ts +5 -0
  84. package/dist/cabinet/run-finishing.d.ts.map +1 -1
  85. package/dist/cabinet/run-ops.d.ts +5 -0
  86. package/dist/cabinet/run-ops.d.ts.map +1 -1
  87. package/dist/cabinet/run-panel.d.ts.map +1 -1
  88. package/dist/cabinet/run-panel.js +203 -52
  89. package/dist/cabinet/tool.d.ts.map +1 -1
  90. package/dist/cabinet/tool.js +8 -5
  91. package/dist/ceiling/build-up-section.d.ts +7 -0
  92. package/dist/ceiling/build-up-section.d.ts.map +1 -0
  93. package/dist/ceiling/build-up-section.js +57 -0
  94. package/dist/ceiling/definition.d.ts.map +1 -1
  95. package/dist/ceiling/definition.js +3 -1
  96. package/dist/ceiling/floorplan-affordances.d.ts +112 -0
  97. package/dist/ceiling/floorplan-affordances.d.ts.map +1 -1
  98. package/dist/ceiling/materials.d.ts +5 -0
  99. package/dist/ceiling/materials.d.ts.map +1 -1
  100. package/dist/ceiling/materials.js +17 -0
  101. package/dist/ceiling/panel-model.d.ts +13 -0
  102. package/dist/ceiling/panel-model.d.ts.map +1 -0
  103. package/dist/ceiling/panel-model.js +49 -0
  104. package/dist/ceiling/panel.d.ts.map +1 -1
  105. package/dist/ceiling/panel.js +82 -18
  106. package/dist/ceiling/renderer.d.ts.map +1 -1
  107. package/dist/ceiling/renderer.js +10 -4
  108. package/dist/ceiling/tool.d.ts.map +1 -1
  109. package/dist/ceiling/tool.js +24 -4
  110. package/dist/chimney/panel.d.ts.map +1 -1
  111. package/dist/chimney/panel.js +113 -41
  112. package/dist/column/definition.d.ts.map +1 -1
  113. package/dist/column/definition.js +3 -0
  114. package/dist/column/floorplan.d.ts.map +1 -1
  115. package/dist/column/floorplan.js +17 -0
  116. package/dist/column/hosted-resize.d.ts +28 -1
  117. package/dist/column/hosted-resize.d.ts.map +1 -1
  118. package/dist/column/panel.d.ts.map +1 -1
  119. package/dist/column/panel.js +125 -37
  120. package/dist/column/post-options.d.ts +10 -0
  121. package/dist/column/post-options.d.ts.map +1 -0
  122. package/dist/column/post-options.js +71 -0
  123. package/dist/column/post-placement.d.ts +78 -0
  124. package/dist/column/post-placement.d.ts.map +1 -0
  125. package/dist/column/post-placement.js +157 -0
  126. package/dist/column/post-section.d.ts +17 -0
  127. package/dist/column/post-section.d.ts.map +1 -0
  128. package/dist/column/post-section.js +95 -0
  129. package/dist/column/post-tool.d.ts +11 -0
  130. package/dist/column/post-tool.d.ts.map +1 -0
  131. package/dist/column/post-tool.js +94 -0
  132. package/dist/column/tool.d.ts +3 -10
  133. package/dist/column/tool.d.ts.map +1 -1
  134. package/dist/column/tool.js +13 -1
  135. package/dist/cupola/panel.d.ts.map +1 -1
  136. package/dist/cupola/panel.js +14 -7
  137. package/dist/door/actions.d.ts +7 -0
  138. package/dist/door/actions.d.ts.map +1 -0
  139. package/dist/door/actions.js +32 -0
  140. package/dist/door/contextual-dimensions.d.ts.map +1 -1
  141. package/dist/door/contextual-dimensions.js +11 -1
  142. package/dist/door/definition.d.ts.map +1 -1
  143. package/dist/door/definition.js +34 -7
  144. package/dist/door/floorplan-affordances.d.ts.map +1 -1
  145. package/dist/door/floorplan-affordances.js +5 -2
  146. package/dist/door/floorplan-move.d.ts.map +1 -1
  147. package/dist/door/floorplan-move.js +28 -6
  148. package/dist/door/floorplan.d.ts +2 -0
  149. package/dist/door/floorplan.d.ts.map +1 -1
  150. package/dist/door/floorplan.js +89 -16
  151. package/dist/door/move-tool.d.ts.map +1 -1
  152. package/dist/door/move-tool.js +60 -16
  153. package/dist/door/paint.d.ts +2 -7
  154. package/dist/door/paint.d.ts.map +1 -1
  155. package/dist/door/paint.js +26 -2
  156. package/dist/door/panel.d.ts.map +1 -1
  157. package/dist/door/panel.js +242 -90
  158. package/dist/door/parametrics.js +1 -1
  159. package/dist/door/placement.d.ts.map +1 -1
  160. package/dist/door/placement.js +9 -2
  161. package/dist/door/swing.d.ts +22 -0
  162. package/dist/door/swing.d.ts.map +1 -0
  163. package/dist/door/swing.js +36 -0
  164. package/dist/door/tool.d.ts.map +1 -1
  165. package/dist/door/tool.js +76 -29
  166. package/dist/dormer/panel-actions-section.d.ts.map +1 -1
  167. package/dist/dormer/panel-actions-section.js +3 -1
  168. package/dist/dormer/panel-position-section.d.ts.map +1 -1
  169. package/dist/dormer/panel-position-section.js +4 -3
  170. package/dist/dormer/panel-windows-section.d.ts.map +1 -1
  171. package/dist/dormer/panel-windows-section.js +38 -1
  172. package/dist/dormer/panel.d.ts.map +1 -1
  173. package/dist/dormer/panel.js +24 -18
  174. package/dist/downspout/inspector-editors.d.ts.map +1 -1
  175. package/dist/downspout/inspector-editors.js +3 -2
  176. package/dist/duct-fitting/inspector-editors.d.ts.map +1 -1
  177. package/dist/duct-fitting/inspector-editors.js +6 -1
  178. package/dist/duct-fitting/tool.d.ts.map +1 -1
  179. package/dist/duct-fitting/tool.js +11 -2
  180. package/dist/duct-terminal/tool.d.ts.map +1 -1
  181. package/dist/duct-terminal/tool.js +11 -2
  182. package/dist/elevator/panel.d.ts.map +1 -1
  183. package/dist/elevator/panel.js +41 -18
  184. package/dist/eyebrow-vent/panel.d.ts.map +1 -1
  185. package/dist/eyebrow-vent/panel.js +16 -6
  186. package/dist/fence/drafting.d.ts +2 -3
  187. package/dist/fence/drafting.d.ts.map +1 -1
  188. package/dist/fence/drafting.js +2 -3
  189. package/dist/fence/inspector-editors.d.ts.map +1 -1
  190. package/dist/fence/inspector-editors.js +64 -21
  191. package/dist/fence/move-endpoint-tool.d.ts.map +1 -1
  192. package/dist/fence/move-endpoint-tool.js +11 -2
  193. package/dist/fence/system.d.ts.map +1 -1
  194. package/dist/fence/system.js +13 -0
  195. package/dist/fence-feature/actions.d.ts.map +1 -1
  196. package/dist/fence-feature/actions.js +5 -2
  197. package/dist/fence-feature/inspector.d.ts.map +1 -1
  198. package/dist/fence-feature/inspector.js +150 -34
  199. package/dist/fence-feature/move-session.d.ts +1 -1
  200. package/dist/floor-opening/floorplan.d.ts +29 -6
  201. package/dist/floor-opening/floorplan.d.ts.map +1 -1
  202. package/dist/floor-opening/floorplan.js +172 -14
  203. package/dist/gutter/downspouts-panel.d.ts.map +1 -1
  204. package/dist/gutter/downspouts-panel.js +14 -2
  205. package/dist/hvac-equipment/tool.d.ts.map +1 -1
  206. package/dist/hvac-equipment/tool.js +3 -2
  207. package/dist/i18n/definition-messages.d.ts +5 -0
  208. package/dist/i18n/definition-messages.d.ts.map +1 -0
  209. package/dist/i18n/definition-messages.js +771 -0
  210. package/dist/index.d.ts +4 -1
  211. package/dist/index.d.ts.map +1 -1
  212. package/dist/index.js +6 -1
  213. package/dist/item/authored-params.d.ts.map +1 -1
  214. package/dist/item/authored-params.js +19 -4
  215. package/dist/item/floorplan.d.ts +1 -1
  216. package/dist/item/floorplan.d.ts.map +1 -1
  217. package/dist/item/panel.d.ts.map +1 -1
  218. package/dist/item/panel.js +9 -7
  219. package/dist/liquid-line/tool.d.ts.map +1 -1
  220. package/dist/liquid-line/tool.js +10 -3
  221. package/dist/measurement/tool.d.ts +1 -1
  222. package/dist/measurement/tool.d.ts.map +1 -1
  223. package/dist/measurement/tool.js +8 -8
  224. package/dist/pipe-fitting/tool.d.ts.map +1 -1
  225. package/dist/pipe-fitting/tool.js +3 -2
  226. package/dist/pipe-trap/tool.d.ts.map +1 -1
  227. package/dist/pipe-trap/tool.js +7 -2
  228. package/dist/procedural-item/renderer.d.ts.map +1 -1
  229. package/dist/procedural-item/renderer.js +8 -1
  230. package/dist/ridge-vent/panel.d.ts.map +1 -1
  231. package/dist/ridge-vent/panel.js +22 -9
  232. package/dist/roof/barrel-panel.d.ts.map +1 -1
  233. package/dist/roof/barrel-panel.js +7 -3
  234. package/dist/roof/definition.d.ts.map +1 -1
  235. package/dist/roof/definition.js +33 -3
  236. package/dist/roof/floorplan-overrides.d.ts +22 -0
  237. package/dist/roof/floorplan-overrides.d.ts.map +1 -0
  238. package/dist/roof/floorplan-overrides.js +46 -0
  239. package/dist/roof/floorplan-tool.d.ts +9 -0
  240. package/dist/roof/floorplan-tool.d.ts.map +1 -0
  241. package/dist/roof/floorplan-tool.js +168 -0
  242. package/dist/roof/floorplan.d.ts.map +1 -1
  243. package/dist/roof/floorplan.js +131 -41
  244. package/dist/roof/glazing-controls.d.ts +2 -1
  245. package/dist/roof/glazing-controls.d.ts.map +1 -1
  246. package/dist/roof/glazing-controls.js +51 -13
  247. package/dist/roof/glazing-panel-editor.d.ts.map +1 -1
  248. package/dist/roof/glazing-panel-editor.js +40 -13
  249. package/dist/roof/glazing-panel.d.ts.map +1 -1
  250. package/dist/roof/glazing-panel.js +73 -9
  251. package/dist/roof/paint.d.ts +19 -0
  252. package/dist/roof/paint.d.ts.map +1 -0
  253. package/dist/roof/paint.js +158 -0
  254. package/dist/roof/panel.d.ts.map +1 -1
  255. package/dist/roof/panel.js +90 -22
  256. package/dist/roof/renderer.d.ts.map +1 -1
  257. package/dist/roof/renderer.js +13 -2
  258. package/dist/roof/roof-footprint-source.d.ts +17 -0
  259. package/dist/roof/roof-footprint-source.d.ts.map +1 -1
  260. package/dist/roof/roof-footprint-source.js +14 -0
  261. package/dist/roof/roof-footprint.d.ts +36 -2
  262. package/dist/roof/roof-footprint.d.ts.map +1 -1
  263. package/dist/roof/roof-footprint.js +124 -2
  264. package/dist/roof/roof-materials.d.ts.map +1 -1
  265. package/dist/roof/roof-materials.js +10 -1
  266. package/dist/roof/roof-placement-mode.d.ts +0 -2
  267. package/dist/roof/roof-placement-mode.d.ts.map +1 -1
  268. package/dist/roof/roof-placement-mode.js +8 -6
  269. package/dist/roof/roof-plan-creases.d.ts +50 -0
  270. package/dist/roof/roof-plan-creases.d.ts.map +1 -0
  271. package/dist/roof/roof-plan-creases.js +194 -0
  272. package/dist/roof/roof-ridge-mode.d.ts +20 -0
  273. package/dist/roof/roof-ridge-mode.d.ts.map +1 -0
  274. package/dist/roof/roof-ridge-mode.js +16 -0
  275. package/dist/roof/tool.d.ts +17 -4
  276. package/dist/roof/tool.d.ts.map +1 -1
  277. package/dist/roof/tool.js +211 -113
  278. package/dist/roof/wall-catch.d.ts +106 -0
  279. package/dist/roof/wall-catch.d.ts.map +1 -0
  280. package/dist/roof/wall-catch.js +267 -0
  281. package/dist/roof-segment/build-up-section.d.ts +9 -0
  282. package/dist/roof-segment/build-up-section.d.ts.map +1 -0
  283. package/dist/roof-segment/build-up-section.js +191 -0
  284. package/dist/roof-segment/definition.d.ts.map +1 -1
  285. package/dist/roof-segment/definition.js +50 -5
  286. package/dist/roof-segment/floorplan-affordances.d.ts.map +1 -1
  287. package/dist/roof-segment/floorplan-affordances.js +68 -19
  288. package/dist/roof-segment/floorplan.d.ts.map +1 -1
  289. package/dist/roof-segment/floorplan.js +16 -12
  290. package/dist/roof-segment/paint.d.ts +3 -1
  291. package/dist/roof-segment/paint.d.ts.map +1 -1
  292. package/dist/roof-segment/paint.js +43 -2
  293. package/dist/roof-segment/panel-model.d.ts +23 -0
  294. package/dist/roof-segment/panel-model.d.ts.map +1 -0
  295. package/dist/roof-segment/panel-model.js +64 -0
  296. package/dist/roof-segment/panel.d.ts.map +1 -1
  297. package/dist/roof-segment/panel.js +96 -14
  298. package/dist/roof-segment/parametrics.d.ts.map +1 -1
  299. package/dist/roof-segment/parametrics.js +4 -0
  300. package/dist/roof-segment/renderer.d.ts.map +1 -1
  301. package/dist/roof-segment/renderer.js +26 -5
  302. package/dist/separator/definition.d.ts.map +1 -1
  303. package/dist/separator/definition.js +10 -12
  304. package/dist/separator/floorplan-affordances.d.ts +9 -0
  305. package/dist/separator/floorplan-affordances.d.ts.map +1 -0
  306. package/dist/separator/floorplan-affordances.js +23 -0
  307. package/dist/separator/floorplan.d.ts +9 -0
  308. package/dist/separator/floorplan.d.ts.map +1 -0
  309. package/dist/separator/floorplan.js +54 -0
  310. package/dist/separator/renderer.d.ts +4 -0
  311. package/dist/separator/renderer.d.ts.map +1 -1
  312. package/dist/separator/renderer.js +21 -6
  313. package/dist/separator/selection.d.ts +10 -0
  314. package/dist/separator/selection.d.ts.map +1 -0
  315. package/dist/separator/selection.js +35 -0
  316. package/dist/shared/build-up-controls.d.ts +88 -0
  317. package/dist/shared/build-up-controls.d.ts.map +1 -0
  318. package/dist/shared/build-up-controls.js +139 -0
  319. package/dist/shared/curtain-opening-limits.d.ts.map +1 -1
  320. package/dist/shared/curtain-opening-limits.js +44 -14
  321. package/dist/shared/item-interaction-actions.d.ts.map +1 -1
  322. package/dist/shared/item-interaction-actions.js +11 -2
  323. package/dist/shared/layer-thickness.d.ts +2 -0
  324. package/dist/shared/layer-thickness.d.ts.map +1 -0
  325. package/dist/shared/layer-thickness.js +3 -0
  326. package/dist/shared/move-roof-tool.d.ts.map +1 -1
  327. package/dist/shared/move-roof-tool.js +100 -5
  328. package/dist/shared/node-batch/batchable.d.ts +2 -0
  329. package/dist/shared/node-batch/batchable.d.ts.map +1 -1
  330. package/dist/shared/node-batch/batchable.js +4 -0
  331. package/dist/shared/node-batch/candidates.d.ts +21 -5
  332. package/dist/shared/node-batch/candidates.d.ts.map +1 -1
  333. package/dist/shared/node-batch/candidates.js +85 -50
  334. package/dist/shared/node-batch/system.d.ts.map +1 -1
  335. package/dist/shared/node-batch/system.js +24 -15
  336. package/dist/shared/opening-casing-move.d.ts +16 -0
  337. package/dist/shared/opening-casing-move.d.ts.map +1 -0
  338. package/dist/shared/opening-casing-move.js +33 -0
  339. package/dist/shared/opening-casing-section.d.ts +15 -0
  340. package/dist/shared/opening-casing-section.d.ts.map +1 -0
  341. package/dist/shared/opening-casing-section.js +38 -0
  342. package/dist/shared/opening-casing.d.ts +26 -0
  343. package/dist/shared/opening-casing.d.ts.map +1 -0
  344. package/dist/shared/opening-casing.js +80 -0
  345. package/dist/shared/opening-depth-position.d.ts +13 -0
  346. package/dist/shared/opening-depth-position.d.ts.map +1 -0
  347. package/dist/shared/opening-depth-position.js +34 -0
  348. package/dist/shared/opening-documentation.d.ts.map +1 -1
  349. package/dist/shared/opening-documentation.js +17 -8
  350. package/dist/shared/opening-guides-runtime.d.ts +2 -1
  351. package/dist/shared/opening-guides-runtime.d.ts.map +1 -1
  352. package/dist/shared/opening-guides-runtime.js +11 -7
  353. package/dist/shared/opening-labels.d.ts +11 -0
  354. package/dist/shared/opening-labels.d.ts.map +1 -0
  355. package/dist/shared/opening-labels.js +46 -0
  356. package/dist/shared/opening-placement-dimensions.d.ts.map +1 -1
  357. package/dist/shared/opening-placement-dimensions.js +11 -9
  358. package/dist/shared/opening-plane-offset.d.ts +4 -3
  359. package/dist/shared/opening-plane-offset.d.ts.map +1 -1
  360. package/dist/shared/opening-plane-offset.js +7 -4
  361. package/dist/shared/opening-swap.d.ts +8 -0
  362. package/dist/shared/opening-swap.d.ts.map +1 -0
  363. package/dist/shared/opening-swap.js +18 -0
  364. package/dist/shared/polygon-vertex-affordance.d.ts +19 -0
  365. package/dist/shared/polygon-vertex-affordance.d.ts.map +1 -1
  366. package/dist/shared/polygon-vertex-affordance.js +65 -6
  367. package/dist/shared/roof-opening-host.d.ts +2 -1
  368. package/dist/shared/roof-opening-host.d.ts.map +1 -1
  369. package/dist/shared/roof-opening-host.js +14 -5
  370. package/dist/shared/roof-wall-opening-cut.d.ts.map +1 -1
  371. package/dist/shared/roof-wall-opening-cut.js +14 -6
  372. package/dist/shared/roof-wall-opening-placement.d.ts +2 -1
  373. package/dist/shared/roof-wall-opening-placement.d.ts.map +1 -1
  374. package/dist/shared/roof-wall-opening-placement.js +6 -4
  375. package/dist/shared/run-hanger-inspector.d.ts.map +1 -1
  376. package/dist/shared/run-hanger-inspector.js +39 -5
  377. package/dist/shared/system-check-panel.d.ts.map +1 -1
  378. package/dist/shared/system-check-panel.js +94 -15
  379. package/dist/shared/wall-attach-target.d.ts.map +1 -1
  380. package/dist/shared/wall-attach-target.js +6 -3
  381. package/dist/shelf/definition.d.ts.map +1 -1
  382. package/dist/shelf/definition.js +2 -0
  383. package/dist/site/ground-hole.d.ts +3 -3
  384. package/dist/site/ground-hole.js +3 -3
  385. package/dist/site/ground-veil.d.ts +5 -12
  386. package/dist/site/ground-veil.d.ts.map +1 -1
  387. package/dist/site/ground-veil.js +9 -33
  388. package/dist/site/panel.d.ts.map +1 -1
  389. package/dist/site/panel.js +52 -12
  390. package/dist/site/renderer.d.ts.map +1 -1
  391. package/dist/site/renderer.js +52 -23
  392. package/dist/skylight/panel.d.ts.map +1 -1
  393. package/dist/skylight/panel.js +49 -19
  394. package/dist/slab/deck-geometry.d.ts +28 -0
  395. package/dist/slab/deck-geometry.d.ts.map +1 -0
  396. package/dist/slab/deck-geometry.js +320 -0
  397. package/dist/slab/definition.d.ts +2 -1
  398. package/dist/slab/definition.d.ts.map +1 -1
  399. package/dist/slab/definition.js +6 -1
  400. package/dist/slab/dependency-tracker.d.ts.map +1 -1
  401. package/dist/slab/dependency-tracker.js +3 -0
  402. package/dist/slab/floorplan-affordances.d.ts +500 -0
  403. package/dist/slab/floorplan-affordances.d.ts.map +1 -1
  404. package/dist/slab/geometry.d.ts.map +1 -1
  405. package/dist/slab/geometry.js +46 -9
  406. package/dist/slab/panel.d.ts.map +1 -1
  407. package/dist/slab/panel.js +97 -21
  408. package/dist/slab/renderer.d.ts +11 -0
  409. package/dist/slab/renderer.d.ts.map +1 -0
  410. package/dist/slab/renderer.js +19 -0
  411. package/dist/slab/system.d.ts.map +1 -1
  412. package/dist/slab/system.js +12 -1
  413. package/dist/solar-panel/panel.d.ts.map +1 -1
  414. package/dist/solar-panel/panel.js +49 -14
  415. package/dist/stair/construction-controls.d.ts +3 -1
  416. package/dist/stair/construction-controls.d.ts.map +1 -1
  417. package/dist/stair/construction-controls.js +75 -12
  418. package/dist/stair/paint.d.ts +6 -0
  419. package/dist/stair/paint.d.ts.map +1 -1
  420. package/dist/stair/panel.d.ts.map +1 -1
  421. package/dist/stair/panel.js +243 -51
  422. package/dist/stair/parametrics.d.ts.map +1 -1
  423. package/dist/stair/parametrics.js +7 -0
  424. package/dist/stair/placement-defaults.d.ts +18 -0
  425. package/dist/stair/placement-defaults.d.ts.map +1 -0
  426. package/dist/stair/placement-defaults.js +27 -0
  427. package/dist/stair/railing-controls.d.ts.map +1 -1
  428. package/dist/stair/railing-controls.js +78 -18
  429. package/dist/stair/renderer.d.ts.map +1 -1
  430. package/dist/stair/renderer.js +16 -10
  431. package/dist/stair/structure-controls.d.ts +18 -0
  432. package/dist/stair/structure-controls.d.ts.map +1 -0
  433. package/dist/stair/structure-controls.js +275 -0
  434. package/dist/stair/tool.d.ts.map +1 -1
  435. package/dist/stair/tool.js +13 -9
  436. package/dist/stair/use-stair-render-data.d.ts +41 -0
  437. package/dist/stair/use-stair-render-data.d.ts.map +1 -1
  438. package/dist/stair-segment/panel.d.ts.map +1 -1
  439. package/dist/stair-segment/panel.js +65 -18
  440. package/dist/turbine-vent/panel.d.ts.map +1 -1
  441. package/dist/turbine-vent/panel.js +14 -5
  442. package/dist/unit/unit-panel.d.ts.map +1 -1
  443. package/dist/unit/unit-panel.js +28 -12
  444. package/dist/wall/actions.d.ts +1 -1
  445. package/dist/wall/actions.d.ts.map +1 -1
  446. package/dist/wall/actions.js +17 -13
  447. package/dist/wall/construction-dimensions.d.ts +6 -0
  448. package/dist/wall/construction-dimensions.d.ts.map +1 -1
  449. package/dist/wall/construction-dimensions.js +8 -0
  450. package/dist/wall/contextual-dimensions.d.ts +6 -0
  451. package/dist/wall/contextual-dimensions.d.ts.map +1 -1
  452. package/dist/wall/contextual-dimensions.js +104 -17
  453. package/dist/wall/curtain-opening-frame.d.ts.map +1 -1
  454. package/dist/wall/curtain-opening-frame.js +6 -4
  455. package/dist/wall/curtain-wall-layout.d.ts +1 -1
  456. package/dist/wall/curtain-wall-layout.d.ts.map +1 -1
  457. package/dist/wall/curtain-wall-layout.js +6 -4
  458. package/dist/wall/curtain-wall-materials.d.ts.map +1 -1
  459. package/dist/wall/curtain-wall-materials.js +8 -3
  460. package/dist/wall/curtain-wall-panel.d.ts.map +1 -1
  461. package/dist/wall/curtain-wall-panel.js +241 -37
  462. package/dist/wall/curve-tool.d.ts.map +1 -1
  463. package/dist/wall/curve-tool.js +2 -3
  464. package/dist/wall/definition.d.ts.map +1 -1
  465. package/dist/wall/definition.js +20 -5
  466. package/dist/wall/floorplan-affordances.d.ts.map +1 -1
  467. package/dist/wall/floorplan-affordances.js +9 -6
  468. package/dist/wall/floorplan-move.d.ts.map +1 -1
  469. package/dist/wall/floorplan-move.js +66 -16
  470. package/dist/wall/floorplan.d.ts +4 -5
  471. package/dist/wall/floorplan.d.ts.map +1 -1
  472. package/dist/wall/floorplan.js +62 -46
  473. package/dist/wall/move-endpoint-tool.d.ts.map +1 -1
  474. package/dist/wall/move-endpoint-tool.js +1 -0
  475. package/dist/wall/move-tool.d.ts.map +1 -1
  476. package/dist/wall/move-tool.js +77 -12
  477. package/dist/wall/paint.d.ts +2 -2
  478. package/dist/wall/paint.d.ts.map +1 -1
  479. package/dist/wall/paint.js +11 -4
  480. package/dist/wall/panel-model.d.ts +17 -2
  481. package/dist/wall/panel-model.d.ts.map +1 -1
  482. package/dist/wall/panel-model.js +158 -18
  483. package/dist/wall/panel.d.ts +8 -0
  484. package/dist/wall/panel.d.ts.map +1 -1
  485. package/dist/wall/panel.js +228 -156
  486. package/dist/wall/parametrics.d.ts +1 -1
  487. package/dist/wall/parametrics.d.ts.map +1 -1
  488. package/dist/wall/parametrics.js +14 -1
  489. package/dist/wall/railing-wall-adapter.d.ts +7 -0
  490. package/dist/wall/railing-wall-adapter.d.ts.map +1 -0
  491. package/dist/wall/railing-wall-adapter.js +38 -0
  492. package/dist/wall/railing-wall-floorplan.d.ts +8 -0
  493. package/dist/wall/railing-wall-floorplan.d.ts.map +1 -0
  494. package/dist/wall/railing-wall-floorplan.js +27 -0
  495. package/dist/wall/railing-wall-geometry.d.ts +12 -0
  496. package/dist/wall/railing-wall-geometry.d.ts.map +1 -0
  497. package/dist/wall/railing-wall-geometry.js +51 -0
  498. package/dist/wall/railing-wall-guard.d.ts +81 -0
  499. package/dist/wall/railing-wall-guard.d.ts.map +1 -0
  500. package/dist/wall/railing-wall-guard.js +435 -0
  501. package/dist/wall/railing-wall-materials.d.ts +11 -0
  502. package/dist/wall/railing-wall-materials.d.ts.map +1 -0
  503. package/dist/wall/railing-wall-materials.js +31 -0
  504. package/dist/wall/railing-wall-panel-model.d.ts +30 -0
  505. package/dist/wall/railing-wall-panel-model.d.ts.map +1 -0
  506. package/dist/wall/railing-wall-panel-model.js +117 -0
  507. package/dist/wall/railing-wall-panel.d.ts +17 -0
  508. package/dist/wall/railing-wall-panel.d.ts.map +1 -0
  509. package/dist/wall/railing-wall-panel.js +42 -0
  510. package/dist/wall/rectangle-command.d.ts +79 -1
  511. package/dist/wall/rectangle-command.d.ts.map +1 -1
  512. package/dist/wall/rectangle-tool.d.ts.map +1 -1
  513. package/dist/wall/rectangle-tool.js +2 -0
  514. package/dist/wall/renderer.d.ts.map +1 -1
  515. package/dist/wall/renderer.js +3 -1
  516. package/dist/wall/skirting-floor-gaps.d.ts +8 -0
  517. package/dist/wall/skirting-floor-gaps.d.ts.map +1 -0
  518. package/dist/wall/skirting-floor-gaps.js +36 -0
  519. package/dist/wall/system.d.ts +0 -14
  520. package/dist/wall/system.d.ts.map +1 -1
  521. package/dist/wall/system.js +6 -1
  522. package/dist/wall/tool.d.ts +16 -0
  523. package/dist/wall/tool.d.ts.map +1 -1
  524. package/dist/wall/tool.js +160 -47
  525. package/dist/wall/treatments.d.ts +3 -0
  526. package/dist/wall/treatments.d.ts.map +1 -1
  527. package/dist/wall/treatments.js +30 -7
  528. package/dist/window/actions.d.ts +7 -0
  529. package/dist/window/actions.d.ts.map +1 -0
  530. package/dist/window/actions.js +29 -0
  531. package/dist/window/definition.d.ts.map +1 -1
  532. package/dist/window/definition.js +11 -2
  533. package/dist/window/floorplan-move.d.ts.map +1 -1
  534. package/dist/window/floorplan-move.js +5 -0
  535. package/dist/window/floorplan.d.ts +2 -0
  536. package/dist/window/floorplan.d.ts.map +1 -1
  537. package/dist/window/floorplan.js +58 -1
  538. package/dist/window/mechanism.d.ts.map +1 -1
  539. package/dist/window/mechanism.js +21 -1
  540. package/dist/window/move-tool.d.ts.map +1 -1
  541. package/dist/window/move-tool.js +10 -3
  542. package/dist/window/paint.d.ts +2 -7
  543. package/dist/window/paint.d.ts.map +1 -1
  544. package/dist/window/paint.js +31 -3
  545. package/dist/window/panel.d.ts.map +1 -1
  546. package/dist/window/panel.js +311 -69
  547. package/dist/window/placement.d.ts.map +1 -1
  548. package/dist/window/placement.js +5 -1
  549. package/dist/window/swing.d.ts +13 -0
  550. package/dist/window/swing.d.ts.map +1 -0
  551. package/dist/window/swing.js +16 -0
  552. package/dist/window/tool.d.ts.map +1 -1
  553. package/dist/window/tool.js +19 -14
  554. package/dist/zone/floorplan-affordances.d.ts +136 -0
  555. package/dist/zone/floorplan-affordances.d.ts.map +1 -1
  556. package/dist/zone/quantities-panel.d.ts.map +1 -1
  557. package/dist/zone/quantities-panel.js +34 -9
  558. package/dist/zone/renderer.d.ts.map +1 -1
  559. package/dist/zone/renderer.js +9 -5
  560. package/package.json +14 -14
  561. package/dist/site/generic-foundation-geometry.d.ts +0 -16
  562. package/dist/site/generic-foundation-geometry.d.ts.map +0 -1
  563. package/dist/site/generic-foundation-geometry.js +0 -75
  564. package/dist/site/generic-foundation.d.ts +0 -4
  565. package/dist/site/generic-foundation.d.ts.map +0 -1
  566. package/dist/site/generic-foundation.js +0 -91
@@ -0,0 +1,88 @@
1
+ import { type InsulationKind, type InteriorFinishKind, type MessageDescriptor, type NominalLumber, type PanelKind, type PascalI18n } from '@pascal-app/core';
2
+ type LinearUnit = 'metric' | 'imperial';
3
+ /**
4
+ * A select over standard sizes (panel thicknesses, spacings). A stored value
5
+ * off the list stays selectable, so a scene written elsewhere reads back as
6
+ * it is.
7
+ */
8
+ export declare function SizeSelect({ label, value, sizes, format, onChange, }: {
9
+ label: string;
10
+ value: number;
11
+ sizes: readonly number[];
12
+ format: (value: number) => string;
13
+ onChange: (value: number) => void;
14
+ }): import("react").JSX.Element;
15
+ /** A free thickness, typed as `5/8`, `3 1/2"` or `90mm`; a bare number is inches or millimetres. */
16
+ export declare function ThicknessField({ label, metres, onCommit, unit, }: {
17
+ label: string;
18
+ metres: number;
19
+ onCommit: (metres: number) => void;
20
+ unit: LinearUnit;
21
+ }): import("react").JSX.Element;
22
+ export declare function BuildUpReadout({ label, value }: {
23
+ label: string;
24
+ value: string;
25
+ }): import("react").JSX.Element;
26
+ /** A spacing on centre, as the viewer's unit names it: `16" o.c.` or `406 mm o.c.`. */
27
+ export declare function formatSpacing(metres: number, unit: LinearUnit, i18n: PascalI18n): string;
28
+ export declare const NONE = "none";
29
+ /** What each panel, insulation and finish kind is called. */
30
+ export declare const LAYER_KIND_LABELS: Record<PanelKind | InsulationKind | InteriorFinishKind, MessageDescriptor>;
31
+ /** `base` with `change` applied and no longer a preset; a layer set to `undefined` goes. */
32
+ export declare function editedBuildUp<T extends {
33
+ presetId?: string;
34
+ }>(base: T, change: Partial<T>): T;
35
+ export declare function FramingSizeFields({ framing, onChange, sizeLabel, unit, }: {
36
+ framing: {
37
+ size: NominalLumber;
38
+ spacing: number;
39
+ };
40
+ onChange: (change: {
41
+ size?: NominalLumber;
42
+ spacing?: number;
43
+ }) => void;
44
+ sizeLabel: string;
45
+ unit: LinearUnit;
46
+ }): import("react").JSX.Element;
47
+ /** A structural panel; with `optional`, None takes it out and a new one is `added`. */
48
+ export declare function PanelFields({ added, label, layer, onChange, optional, unit, }: {
49
+ added?: number;
50
+ label: string;
51
+ layer: {
52
+ kind: PanelKind;
53
+ thickness: number;
54
+ } | undefined;
55
+ onChange: (layer: {
56
+ kind: PanelKind;
57
+ thickness: number;
58
+ } | undefined) => void;
59
+ optional?: boolean;
60
+ unit: LinearUnit;
61
+ }): import("react").JSX.Element;
62
+ /** A new insulation layer is cavity fill as deep as the framing, or 2 in of rigid board. */
63
+ export declare function InsulationFields({ framingDepth, layer, onChange, unit, }: {
64
+ framingDepth: number;
65
+ layer: {
66
+ kind: InsulationKind;
67
+ thickness: number;
68
+ } | undefined;
69
+ onChange: (layer: {
70
+ kind: InsulationKind;
71
+ thickness: number;
72
+ } | undefined) => void;
73
+ unit: LinearUnit;
74
+ }): import("react").JSX.Element;
75
+ export declare function FinishFields({ label, layer, onChange, unit, }: {
76
+ label: string;
77
+ layer: {
78
+ kind: InteriorFinishKind;
79
+ thickness: number;
80
+ } | undefined;
81
+ onChange: (layer: {
82
+ kind: InteriorFinishKind;
83
+ thickness: number;
84
+ } | undefined) => void;
85
+ unit: LinearUnit;
86
+ }): import("react").JSX.Element;
87
+ export {};
88
+ //# sourceMappingURL=build-up-controls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-up-controls.d.ts","sourceRoot":"","sources":["../../src/shared/build-up-controls.tsx"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,kBAAkB,EAEvB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAElB,KAAK,SAAS,EACd,KAAK,UAAU,EAIhB,MAAM,kBAAkB,CAAA;AAKzB,KAAK,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAA;AAIvC;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,KAAK,EACL,KAAK,EACL,MAAM,EACN,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IACjC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAClC,+BAeA;AAED,oGAAoG;AACpG,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,MAAM,EACN,QAAQ,EACR,IAAI,GACL,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,IAAI,EAAE,UAAU,CAAA;CACjB,+BA2BA;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,+BAShF;AAED,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CASxF;AAED,eAAO,MAAM,IAAI,SAAS,CAAA;AAQ1B,6DAA6D;AAC7D,eAAO,MAAM,iBAAiB,EAAE,MAAM,CACpC,SAAS,GAAG,cAAc,GAAG,kBAAkB,EAC/C,iBAAiB,CAUlB,CAAA;AAmCD,4FAA4F;AAC5F,wBAAgB,aAAa,CAAC,CAAC,SAAS;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAK7F;AAED,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,QAAQ,EACR,SAAS,EACT,IAAI,GACL,EAAE;IACD,OAAO,EAAE;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IACjD,QAAQ,EAAE,CAAC,MAAM,EAAE;QAAE,IAAI,CAAC,EAAE,aAAa,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;IACtE,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,UAAU,CAAA;CACjB,+BAmBA;AAED,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,EAC1B,KAA6B,EAC7B,KAAK,EACL,KAAK,EACL,QAAQ,EACR,QAAgB,EAChB,IAAI,GACL,EAAE;IACD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAA;IACzD,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,KAAK,IAAI,CAAA;IAC7E,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,EAAE,UAAU,CAAA;CACjB,+BA8BA;AAED,4FAA4F;AAC5F,wBAAgB,gBAAgB,CAAC,EAC/B,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,IAAI,GACL,EAAE;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAA;IAC9D,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,KAAK,IAAI,CAAA;IAClF,IAAI,EAAE,UAAU,CAAA;CACjB,+BA6BA;AAED,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,KAAK,EACL,QAAQ,EACR,IAAI,GACL,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE;QAAE,IAAI,EAAE,kBAAkB,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAA;IAClE,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,kBAAkB,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,KAAK,IAAI,CAAA;IACtF,IAAI,EAAE,UAAU,CAAA;CACjB,+BA0BA"}
@@ -0,0 +1,139 @@
1
+ 'use client';
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { DRYWALL_THICKNESSES, FRAMING_SPACINGS, LUMBER_DEPTH, PANEL_THICKNESSES, PLASTER_THICKNESS, usePascalI18n, WOOD_PLANK_THICKNESS, } from '@pascal-app/core';
4
+ import { SelectControl } from '@pascal-app/editor';
5
+ import { useState } from 'react';
6
+ import { formatLayerThickness, parseLayerThickness } from './layer-thickness.js';
7
+ const key = (value) => value.toFixed(6);
8
+ /**
9
+ * A select over standard sizes (panel thicknesses, spacings). A stored value
10
+ * off the list stays selectable, so a scene written elsewhere reads back as
11
+ * it is.
12
+ */
13
+ export function SizeSelect({ label, value, sizes, format, onChange, }) {
14
+ const listed = sizes.some((size) => Math.abs(size - value) < 1e-6);
15
+ const choices = listed ? sizes : [value, ...sizes];
16
+ const current = choices.find((size) => Math.abs(size - value) < 1e-6) ?? value;
17
+ return (_jsx(SelectControl, { label: label, onChange: (next) => {
18
+ const picked = choices.find((size) => key(size) === next);
19
+ if (picked !== undefined)
20
+ onChange(picked);
21
+ }, options: choices.map((size) => ({ label: format(size), value: key(size) })), value: key(current) }));
22
+ }
23
+ /** A free thickness, typed as `5/8`, `3 1/2"` or `90mm`; a bare number is inches or millimetres. */
24
+ export function ThicknessField({ label, metres, onCommit, unit, }) {
25
+ const [draft, setDraft] = useState(null);
26
+ return (_jsxs("label", { className: "flex h-10 w-full items-center justify-between gap-2 rounded-lg border border-border/50 bg-black/4 px-3 text-sm dark:bg-[#2C2C2E]", children: [_jsx("span", { className: "select-none text-muted-foreground", children: label }), _jsx("input", { className: "w-24 bg-transparent text-right text-foreground outline-none", onBlur: () => {
27
+ if (draft !== null) {
28
+ const parsed = parseLayerThickness(draft, unit);
29
+ if (parsed !== null)
30
+ onCommit(parsed);
31
+ }
32
+ setDraft(null);
33
+ }, onChange: (event) => setDraft(event.target.value), onKeyDown: (event) => {
34
+ if (event.key === 'Enter')
35
+ event.currentTarget.blur();
36
+ if (event.key === 'Escape') {
37
+ setDraft(null);
38
+ event.currentTarget.blur();
39
+ }
40
+ }, spellCheck: false, value: draft ?? formatLayerThickness(metres, unit) })] }));
41
+ }
42
+ export function BuildUpReadout({ label, value }) {
43
+ return (_jsxs("div", { className: "flex items-center justify-between gap-2 px-2 py-1", children: [_jsx("span", { className: "font-medium text-[10px] text-muted-foreground uppercase tracking-wider", children: label }), _jsx("span", { className: "truncate text-[11px] text-muted-foreground tabular-nums", children: value })] }));
44
+ }
45
+ /** A spacing on centre, as the viewer's unit names it: `16" o.c.` or `406 mm o.c.`. */
46
+ export function formatSpacing(metres, unit, i18n) {
47
+ const spacing = unit === 'imperial' ? formatLayerThickness(metres, unit) : `${Math.round(metres * 1000)} mm`;
48
+ return i18n._({
49
+ id: 'node.shared.buildUpControls.spacingOC',
50
+ message: '{spacing} o.c.',
51
+ comment: 'A framing spacing on centre (centre of one member to the next), e.g. 16" o.c.',
52
+ values: { spacing },
53
+ });
54
+ }
55
+ export const NONE = 'none';
56
+ const INCH = 0.0254;
57
+ const NONE_LABEL = /* i18n */ {
58
+ id: 'node.shared.buildUpControls.none',
59
+ message: 'None',
60
+ };
61
+ /** What each panel, insulation and finish kind is called. */
62
+ export const LAYER_KIND_LABELS = {
63
+ osb: /* i18n */ { id: 'node.shared.buildUpControls.osb', message: 'OSB' },
64
+ plywood: /* i18n */ { id: 'node.shared.buildUpControls.plywood', message: 'Plywood' },
65
+ batt: /* i18n */ { id: 'node.shared.buildUpControls.batt', message: 'Batt' },
66
+ blown: /* i18n */ { id: 'node.shared.buildUpControls.blown', message: 'Blown' },
67
+ rigid: /* i18n */ { id: 'node.shared.buildUpControls.rigidBoard', message: 'Rigid board' },
68
+ drywall: /* i18n */ { id: 'node.shared.buildUpControls.drywall', message: 'Drywall' },
69
+ plaster: /* i18n */ { id: 'node.shared.buildUpControls.plaster', message: 'Plaster' },
70
+ 'wood-plank': /* i18n */ { id: 'node.shared.buildUpControls.woodPlank', message: 'Wood plank' },
71
+ };
72
+ const PANEL_OPTIONS = [
73
+ { label: LAYER_KIND_LABELS.osb, value: 'osb' },
74
+ { label: LAYER_KIND_LABELS.plywood, value: 'plywood' },
75
+ ];
76
+ const OPTIONAL_PANEL_OPTIONS = [
77
+ { label: NONE_LABEL, value: NONE },
78
+ ...PANEL_OPTIONS,
79
+ ];
80
+ const LUMBER_OPTIONS = Object.keys(LUMBER_DEPTH).map((size) => ({ label: size, value: size }));
81
+ const INSULATION_OPTIONS = [
82
+ { label: NONE_LABEL, value: NONE },
83
+ { label: LAYER_KIND_LABELS.batt, value: 'batt' },
84
+ { label: LAYER_KIND_LABELS.blown, value: 'blown' },
85
+ { label: LAYER_KIND_LABELS.rigid, value: 'rigid' },
86
+ ];
87
+ const FINISH_OPTIONS = [
88
+ { label: NONE_LABEL, value: NONE },
89
+ { label: LAYER_KIND_LABELS.drywall, value: 'drywall' },
90
+ { label: LAYER_KIND_LABELS.plaster, value: 'plaster' },
91
+ { label: LAYER_KIND_LABELS['wood-plank'], value: 'wood-plank' },
92
+ ];
93
+ const FINISH_THICKNESS = {
94
+ drywall: DRYWALL_THICKNESSES[0],
95
+ plaster: PLASTER_THICKNESS,
96
+ 'wood-plank': WOOD_PLANK_THICKNESS,
97
+ };
98
+ /** `base` with `change` applied and no longer a preset; a layer set to `undefined` goes. */
99
+ export function editedBuildUp(base, change) {
100
+ const next = { ...base, ...change };
101
+ delete next.presetId;
102
+ for (const field of Object.keys(next))
103
+ if (next[field] === undefined)
104
+ delete next[field];
105
+ return next;
106
+ }
107
+ export function FramingSizeFields({ framing, onChange, sizeLabel, unit, }) {
108
+ const i18n = usePascalI18n();
109
+ return (_jsxs(_Fragment, { children: [_jsx(SelectControl, { label: sizeLabel, onChange: (size) => onChange({ size }), options: LUMBER_OPTIONS, value: framing.size }), _jsx(SizeSelect, { format: (value) => formatSpacing(value, unit, i18n), label: i18n._({ id: 'node.shared.buildUpControls.spacing', message: 'Spacing' }), onChange: (spacing) => onChange({ spacing }), sizes: FRAMING_SPACINGS, value: framing.spacing })] }));
110
+ }
111
+ /** A structural panel; with `optional`, None takes it out and a new one is `added`. */
112
+ export function PanelFields({ added = PANEL_THICKNESSES[0], label, layer, onChange, optional = false, unit, }) {
113
+ const i18n = usePascalI18n();
114
+ return (_jsxs(_Fragment, { children: [_jsx(SelectControl, { label: label, onChange: (kind) => onChange(kind === NONE ? undefined : { thickness: layer?.thickness ?? added, kind }), options: (optional ? OPTIONAL_PANEL_OPTIONS : PANEL_OPTIONS).map((option) => ({
115
+ ...option,
116
+ label: i18n._(option.label),
117
+ })), value: layer?.kind ?? NONE }), layer && (_jsx(SizeSelect, { format: (value) => formatLayerThickness(value, unit), label: i18n._({
118
+ id: 'node.shared.buildUpControls.labelThickness',
119
+ message: '{label} thickness',
120
+ values: { label },
121
+ }), onChange: (thickness) => onChange({ ...layer, thickness }), sizes: PANEL_THICKNESSES, value: layer.thickness }))] }));
122
+ }
123
+ /** A new insulation layer is cavity fill as deep as the framing, or 2 in of rigid board. */
124
+ export function InsulationFields({ framingDepth, layer, onChange, unit, }) {
125
+ const i18n = usePascalI18n();
126
+ return (_jsxs(_Fragment, { children: [_jsx(SelectControl, { label: i18n._({ id: 'node.shared.buildUpControls.insulation', message: 'Insulation' }), onChange: (kind) => onChange(kind === NONE
127
+ ? undefined
128
+ : { kind, thickness: kind === 'rigid' ? 2 * INCH : framingDepth }), options: INSULATION_OPTIONS.map((option) => ({ ...option, label: i18n._(option.label) })), value: layer?.kind ?? NONE }), layer && (_jsx(ThicknessField, { label: i18n._({
129
+ id: 'node.shared.buildUpControls.insulationThickness',
130
+ message: 'Insulation thickness',
131
+ }), metres: layer.thickness, onCommit: (thickness) => onChange({ ...layer, thickness }), unit: unit }))] }));
132
+ }
133
+ export function FinishFields({ label, layer, onChange, unit, }) {
134
+ const i18n = usePascalI18n();
135
+ return (_jsxs(_Fragment, { children: [_jsx(SelectControl, { label: label, onChange: (kind) => onChange(kind === NONE ? undefined : { kind, thickness: FINISH_THICKNESS[kind] }), options: FINISH_OPTIONS.map((option) => ({ ...option, label: i18n._(option.label) })), value: layer?.kind ?? NONE }), layer?.kind === 'drywall' && (_jsx(SizeSelect, { format: (value) => formatLayerThickness(value, unit), label: i18n._({
136
+ id: 'node.shared.buildUpControls.drywallThickness',
137
+ message: 'Drywall thickness',
138
+ }), onChange: (thickness) => onChange({ kind: 'drywall', thickness }), sizes: DRYWALL_THICKNESSES, value: layer.thickness }))] }));
139
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"curtain-opening-limits.d.ts","sourceRoot":"","sources":["../../src/shared/curtain-opening-limits.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,QAAQ,EAGb,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAA;AAGzB,KAAK,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAA;AAEpC,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,EAC3C,IAAI,EAAE,GAAG,GAAG,GAAG,EACf,IAAI,EAAE,MAAM,sBAcb;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;;;;;;;SAwB5C;AAED,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,OAAO,EACvD,OAAO,EAAE,CAAC,EACV,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EACjB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,GAC1C,OAAO,CAAC,CAAC,CAAC,CAsBZ"}
1
+ {"version":3,"file":"curtain-opening-limits.d.ts","sourceRoot":"","sources":["../../src/shared/curtain-opening-limits.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,QAAQ,EAKb,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAA;AAIzB,KAAK,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAA;AAEpC,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,EAC3C,IAAI,EAAE,GAAG,GAAG,GAAG,EACf,IAAI,EAAE,MAAM,sBAuBb;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;;;;;;;SA0B5C;AAED,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,OAAO,EACvD,OAAO,EAAE,CAAC,EACV,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EACjB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,GAC1C,OAAO,CAAC,CAAC,CAAC,CAyDZ"}
@@ -1,21 +1,30 @@
1
- import { getCurtainWallConfig, getWallCurveLength, } from '@pascal-app/core';
1
+ import { getCurtainWallConfig, getDoorOpeningSize, getWallCurveLength, openingHostFacing, } from '@pascal-app/core';
2
+ import { clampDoorToWall } from '@pascal-app/core/building';
2
3
  import { resolveWallOpeningCeiling } from './wall-opening-ceiling.js';
3
4
  export function curtainOpeningResizeMax(opening, nodes, axis, sign) {
4
5
  const limits = curtainOpeningLimits(opening, nodes);
5
6
  if (!limits)
6
7
  return undefined;
8
+ const size = getDoorOpeningSize(opening);
9
+ const extraWidth = size.width - opening.width;
10
+ const extraHeight = size.height - opening.height;
11
+ const centerX = opening.position[0] - size.leafOffsetX * openingHostFacing(opening);
7
12
  if (axis === 'y') {
8
- const anchor = opening.position[1] - (sign * opening.height) / 2;
9
- return Math.max(0, sign > 0 ? limits.top - anchor : anchor - limits.bottom);
13
+ const anchor = opening.position[1] + extraHeight / 2 - (sign * size.height) / 2;
14
+ return Math.max(0, sign > 0 ? limits.top - anchor - extraHeight : anchor - limits.bottom - extraHeight);
10
15
  }
11
16
  const direction = Math.cos(opening.rotation[1]) >= 0 ? sign : -sign;
12
- const anchor = opening.position[0] - (direction * opening.width) / 2;
13
- return Math.max(0, direction > 0 ? limits.length - limits.margin - anchor : anchor - limits.margin);
17
+ const anchor = centerX - (direction * size.width) / 2;
18
+ return Math.max(0, direction > 0
19
+ ? limits.length - limits.margin - anchor - extraWidth
20
+ : anchor - limits.margin - extraWidth);
14
21
  }
15
22
  export function curtainOpeningLimits(opening, nodes) {
16
23
  const wall = nodes[(opening.parentId ?? opening.wallId)];
17
24
  if (wall?.type !== 'wall' || wall.wallType !== 'curtain')
18
25
  return null;
26
+ const size = getDoorOpeningSize(opening);
27
+ const centerX = opening.position[0] - size.leafOffsetX * openingHostFacing(opening);
19
28
  const margin = getCurtainWallConfig(wall).perimeterWidth;
20
29
  const length = getWallCurveLength(wall);
21
30
  const top = resolveWallOpeningCeiling(wall, nodes) - margin;
@@ -25,29 +34,50 @@ export function curtainOpeningLimits(opening, nodes) {
25
34
  length,
26
35
  top,
27
36
  bottom,
28
- width: Math.max(0, 2 * Math.min(opening.position[0] - margin, length - margin - opening.position[0])),
37
+ width: Math.max(0, 2 * Math.min(centerX - margin, length - margin - centerX) - (size.width - opening.width)),
29
38
  height: Math.max(0, opening.type === 'door'
30
- ? top
39
+ ? top - (size.height - opening.height)
31
40
  : 2 * Math.min(opening.position[1] - bottom, top - opening.position[1])),
32
41
  };
33
42
  }
34
43
  export function constrainCurtainOpening(opening, patch, nodes) {
35
- const limits = curtainOpeningLimits(opening, nodes);
36
- if (!limits || !('width' in patch || 'height' in patch || 'position' in patch))
44
+ let next = { ...opening, ...patch };
45
+ const wall = nodes[(next.parentId ?? next.wallId)];
46
+ if (next.type === 'door' &&
47
+ wall?.type === 'wall' &&
48
+ 'transomHeight' in next &&
49
+ next.transomHeight) {
50
+ const { transomHeight } = clampDoorToWall(wall, next.position[0], next.width, next.height, next, nodes);
51
+ if (transomHeight !== undefined && transomHeight !== next.transomHeight) {
52
+ patch = { ...patch, transomHeight };
53
+ next = { ...opening, ...patch };
54
+ }
55
+ }
56
+ const limits = curtainOpeningLimits(next, nodes);
57
+ if (!limits ||
58
+ !('width' in patch ||
59
+ 'height' in patch ||
60
+ 'position' in patch ||
61
+ 'sidelightLeft' in patch ||
62
+ 'sidelightRight' in patch ||
63
+ 'transomHeight' in patch))
37
64
  return patch;
38
- const next = { ...opening, ...patch };
65
+ const size = getDoorOpeningSize(next);
66
+ const extraWidth = size.width - next.width;
67
+ const extraHeight = size.height - next.height;
68
+ const offset = size.leafOffsetX * openingHostFacing(next);
39
69
  const moving = patch.position !== undefined && patch.width === undefined && patch.height === undefined;
40
- const availableWidth = Math.max(0, limits.length - 2 * limits.margin);
41
- const availableHeight = Math.max(0, limits.top - limits.bottom);
70
+ const availableWidth = Math.max(0, limits.length - 2 * limits.margin - extraWidth);
71
+ const availableHeight = Math.max(0, limits.top - limits.bottom - extraHeight);
42
72
  const widthLimit = moving || limits.width < 0.01 ? availableWidth : limits.width;
43
73
  const heightLimit = moving || limits.height < 0.01 ? availableHeight : limits.height;
44
74
  const width = Math.min(Math.max(0.01, next.width), widthLimit);
45
75
  const height = Math.min(Math.max(0.01, next.height), heightLimit);
46
76
  if (width < 0.01 || height < 0.01)
47
77
  return {};
48
- const x = Math.max(limits.margin + width / 2, Math.min(limits.length - limits.margin - width / 2, next.position[0]));
78
+ const x = Math.max(limits.margin + (width + extraWidth) / 2, Math.min(limits.length - limits.margin - (width + extraWidth) / 2, next.position[0] - offset));
49
79
  const y = opening.type === 'door'
50
80
  ? height / 2
51
81
  : Math.max(limits.bottom + height / 2, Math.min(limits.top - height / 2, next.position[1]));
52
- return { ...patch, width, height, position: [x, y, next.position[2]] };
82
+ return { ...patch, width, height, position: [x + offset, y, next.position[2]] };
53
83
  }
@@ -1 +1 @@
1
- {"version":3,"file":"item-interaction-actions.d.ts","sourceRoot":"","sources":["../../src/shared/item-interaction-actions.tsx"],"names":[],"mappings":"AAOA;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,sBAAsB,uCAsB7C"}
1
+ {"version":3,"file":"item-interaction-actions.d.ts","sourceRoot":"","sources":["../../src/shared/item-interaction-actions.tsx"],"names":[],"mappings":"AAaA;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,sBAAsB,uCAiC7C"}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { nodeMechanism, useInteractive, useScene } from '@pascal-app/core';
3
+ import { nodeMechanism, useInteractive, usePascalI18n, useScene, } from '@pascal-app/core';
4
4
  import { ActionMenuButton } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { Lightbulb, LightbulbOff } from 'lucide-react';
@@ -10,6 +10,7 @@ import { itemHasLights, itemLightsOn, toggleItemLights } from './item-interactio
10
10
  * comes from the action menu's `capabilities.mechanism` button.
11
11
  */
12
12
  export default function ItemInteractionActions() {
13
+ const i18n = usePascalI18n();
13
14
  const selected = useViewer((s) => s.selection.selectedIds);
14
15
  const node = useScene((s) => selected.length === 1 ? s.nodes[selected[0]] : undefined);
15
16
  const hasLights = itemHasLights(node);
@@ -20,7 +21,15 @@ export default function ItemInteractionActions() {
20
21
  // E runs the mechanism when there is one, and only otherwise the light.
21
22
  , {
22
23
  // E runs the mechanism when there is one, and only otherwise the light.
23
- keys: nodeMechanism(node) ? undefined : ['E'], label: lit ? 'Turn light off' : 'Turn light on', onClick: (event) => {
24
+ keys: nodeMechanism(node) ? undefined : ['E'], label: lit
25
+ ? i18n._({
26
+ id: 'node.shared.itemInteractionActions.turnLightOff',
27
+ message: 'Turn light off',
28
+ })
29
+ : i18n._({
30
+ id: 'node.shared.itemInteractionActions.turnLightOn',
31
+ message: 'Turn light on',
32
+ }), onClick: (event) => {
24
33
  event.stopPropagation();
25
34
  toggleItemLights(node);
26
35
  }, pressed: lit, children: lit ? _jsx(Lightbulb, { className: "h-4 w-4" }) : _jsx(LightbulbOff, { className: "h-4 w-4" }) }));
@@ -0,0 +1,2 @@
1
+ export { formatLayerDepth, formatLayerThickness, parseLayerThickness } from '@pascal-app/editor';
2
+ //# sourceMappingURL=layer-thickness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layer-thickness.d.ts","sourceRoot":"","sources":["../../src/shared/layer-thickness.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,3 @@
1
+ // The layer thickness reader and writer live in the editor, which the floor panels share with
2
+ // the roof, ceiling and wall layers here.
3
+ export { formatLayerDepth, formatLayerThickness, parseLayerThickness } from '@pascal-app/editor';
@@ -1 +1 @@
1
- {"version":3,"file":"move-roof-tool.d.ts","sourceRoot":"","sources":["../../src/shared/move-roof-tool.tsx"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,QAAQ,EACb,KAAK,eAAe,EAIpB,KAAK,SAAS,EACd,KAAK,gBAAgB,EAQtB,MAAM,kBAAkB,CAAA;AA2DzB,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;IAClC,IAAI,EAAE,QAAQ,GAAG,eAAe,GAAG,SAAS,GAAG,gBAAgB,CAAA;CAChE,CAsmBA,CAAA;eAEc,YAAY"}
1
+ {"version":3,"file":"move-roof-tool.d.ts","sourceRoot":"","sources":["../../src/shared/move-roof-tool.tsx"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,QAAQ,EACb,KAAK,eAAe,EAIpB,KAAK,SAAS,EACd,KAAK,gBAAgB,EAQtB,MAAM,kBAAkB,CAAA;AAmEzB,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;IAClC,IAAI,EAAE,QAAQ,GAAG,eAAe,GAAG,SAAS,GAAG,gBAAgB,CAAA;CAChE,CA8sBA,CAAA;eAEc,YAAY"}
@@ -1,10 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { collectAlignmentAnchors, emitter, movingAlignmentAnchors, nodeRegistry, resolveAlignment, resolveStairSurfaceSnap, resolveSupportSlabPatch, sceneRegistry, seatRoofs, useLiveNodeOverrides, useLiveTransforms, useScene, } from '@pascal-app/core';
3
- import { CursorSphere, commitFreshPlacementSubtree, consumePlacementDragRelease, DragBoundingBox, getFloorStackPreviewPosition, isMagneticSnapActive, isTypingTarget, resolvePlanarCursorPosition, selectPlacedNode, stripPlacementMetadataFlags, triggerSFX, useAlignmentGuides, useEditor, useFreshPlacementVisibility, } from '@pascal-app/editor';
3
+ import { CursorSphere, commitFreshPlacementSubtree, consumePlacementDragRelease, DragBoundingBox, getFloorStackPreviewPosition, isGridSnapActive, isMagneticSnapActive, isTypingTarget, resolvePlanarCursorPosition, selectPlacedNode, stripPlacementMetadataFlags, triggerSFX, useAlignmentGuides, useEditor, useFreshPlacementVisibility, } from '@pascal-app/editor';
4
4
  import { useViewer } from '@pascal-app/viewer';
5
5
  import { useCallback, useEffect, useRef, useState } from 'react';
6
6
  import * as THREE from 'three';
7
7
  import { snapFenceDraftPoint } from '../fence/drafting.js';
8
+ import { bearingWallThickness, catchRoofOnWalls, placeRoofOnWalls, roofCatchWalls, segmentWallLine, } from '../roof/wall-catch.js';
8
9
  import { clearStairMovePreview, publishStairMovePreview } from '../stair/surface-move-preview.js';
9
10
  /** Figma-style alignment-snap threshold (meters), matching the other tools. */
10
11
  const ALIGNMENT_THRESHOLD_M = 0.08;
@@ -185,6 +186,74 @@ export const MoveRoofTool = ({ node: sourceNode }) => {
185
186
  useAlignmentGuides.getState().set(ar.guides);
186
187
  return ar.snap && isMagneticSnapActive() ? [lx + ar.snap.dx, lz + ar.snap.dz] : [lx, lz];
187
188
  };
189
+ // A roof's wall line lands on the walls under it, as in the plan's segment move
190
+ // (`catchRoofOnWalls`); that catch replaces the cursor's own snap onto a wall.
191
+ const catchesWalls = movingNode.type === 'roof' || movingNode.type === 'roof-segment';
192
+ const catchWalls = catchesWalls ? roofCatchWalls(useScene.getState().nodes, levelId) : [];
193
+ let rawAnchor = null;
194
+ const catchOnWalls = (raw, snapped) => {
195
+ const nodes = useScene.getState().nodes;
196
+ const roof = movingNode.type === 'roof'
197
+ ? movingNode
198
+ : nodes[movingNode.parentId];
199
+ if (roof?.type !== 'roof' || catchWalls.length === 0)
200
+ return null;
201
+ // A segment's place is in its roof's frame; the walls are in the level's plan.
202
+ const cos = Math.cos(-roof.rotation);
203
+ const sin = Math.sin(-roof.rotation);
204
+ const toPlan = ([x, z]) => movingNode.type === 'roof'
205
+ ? [x, z]
206
+ : [roof.position[0] + x * cos - z * sin, roof.position[2] + x * sin + z * cos];
207
+ const fromPlan = ([x, z]) => {
208
+ if (movingNode.type === 'roof')
209
+ return [x, z];
210
+ const dx = x - roof.position[0];
211
+ const dz = z - roof.position[2];
212
+ return [dx * cos + dz * sin, -dx * sin + dz * cos];
213
+ };
214
+ const lines = movingNode.type === 'roof'
215
+ ? roof.children
216
+ .map((id) => nodes[id])
217
+ .filter((child) => child?.type === 'roof-segment')
218
+ .map((segment) => segmentWallLine({ position: [raw[0], 0, raw[1]], rotation: pendingRotation }, segment))
219
+ : movingNode.type === 'roof-segment'
220
+ ? [
221
+ segmentWallLine(roof, {
222
+ ...movingNode,
223
+ position: [raw[0], 0, raw[1]],
224
+ rotation: pendingRotation,
225
+ }),
226
+ ]
227
+ : [];
228
+ const angle = movingNode.type === 'roof' ? -pendingRotation : -(roof.rotation + pendingRotation);
229
+ const caught = catchRoofOnWalls({ lines, walls: catchWalls, angle });
230
+ if (!(caught.u || caught.v))
231
+ return null;
232
+ return fromPlan(placeRoofOnWalls(toPlan(raw), toPlan(snapped), caught, angle));
233
+ };
234
+ // Dropped onto the walls under it, a roof's segments take their thickness for their gable
235
+ // and heel walls.
236
+ const bearingThicknesses = (position, rotation) => {
237
+ const nodes = useScene.getState().nodes;
238
+ const roof = movingNode.type === 'roof'
239
+ ? { ...movingNode, position, rotation }
240
+ : nodes[movingNode.parentId];
241
+ if (roof?.type !== 'roof' || catchWalls.length === 0)
242
+ return [];
243
+ const segments = movingNode.type === 'roof'
244
+ ? roof.children
245
+ .map((id) => nodes[id])
246
+ .filter((child) => child?.type === 'roof-segment')
247
+ : movingNode.type === 'roof-segment'
248
+ ? [{ ...movingNode, position, rotation }]
249
+ : [];
250
+ return segments.flatMap((segment) => {
251
+ const thickness = bearingWallThickness(segmentWallLine(roof, segment), catchWalls);
252
+ return thickness === null || thickness === segment.wallThickness
253
+ ? []
254
+ : [{ id: segment.id, data: { wallThickness: thickness } }];
255
+ });
256
+ };
188
257
  const localToWorldPoint = (localPoint, y) => {
189
258
  if (buildingObj) {
190
259
  const worldPoint = buildingObj.localToWorld(new THREE.Vector3(localPoint[0], y, localPoint[1]));
@@ -236,9 +305,10 @@ export const MoveRoofTool = ({ node: sourceNode }) => {
236
305
  revealFreshPlacement();
237
306
  const y = event.position[1];
238
307
  const roofBypassSnap = event.nativeEvent?.altKey === true;
308
+ const cursor = [event.localPosition[0], event.localPosition[2]];
239
309
  const snappedLocal = snapFenceDraftPoint({
240
- point: [event.localPosition[0], event.localPosition[2]],
241
- walls: levelWalls,
310
+ point: cursor,
311
+ walls: catchesWalls ? [] : levelWalls,
242
312
  fences: levelFences,
243
313
  bypassSnap: roofBypassSnap,
244
314
  magnetic: !roofBypassSnap && isMagneticSnapActive(),
@@ -253,7 +323,26 @@ export const MoveRoofTool = ({ node: sourceNode }) => {
253
323
  });
254
324
  dragAnchorRef.current = resolved.anchor;
255
325
  let [localX, localZ] = resolved.point;
256
- if (alignTopLevel) {
326
+ // The catch reads the unsnapped place, so the walls win over the grid near them.
327
+ let caught = null;
328
+ if (catchesWalls) {
329
+ const [cursorX, , cursorZ] = localToWorldPoint(cursor, y);
330
+ const raw = resolvePlanarCursorPosition({
331
+ cursor: computeLocal(cursorX, cursorZ, y, cursor[0], cursor[1]),
332
+ original: [movingNode.position[0], movingNode.position[2]],
333
+ anchor: rawAnchor,
334
+ mode: useAbsoluteCursorPlacement ? 'absolute' : 'relative',
335
+ });
336
+ rawAnchor = raw.anchor;
337
+ if (!roofBypassSnap && (isGridSnapActive() || isMagneticSnapActive()))
338
+ caught = catchOnWalls(raw.point, [localX, localZ]);
339
+ }
340
+ if (caught) {
341
+ ;
342
+ [localX, localZ] = caught;
343
+ useAlignmentGuides.getState().clear();
344
+ }
345
+ else if (alignTopLevel) {
257
346
  const aligned = alignLocalPoint(localX, localZ, event.nativeEvent?.altKey === true);
258
347
  localX = aligned[0];
259
348
  localZ = aligned[1];
@@ -382,7 +471,13 @@ export const MoveRoofTool = ({ node: sourceNode }) => {
382
471
  if (movingNode.type === 'roof' || movingNode.type === 'roof-segment') {
383
472
  // Moved or turned onto the walls that carry it, a roof goes to the level above them.
384
473
  const scene = useScene.getState();
385
- scene.applyNodeChanges(seatRoofs(scene.nodes, { update: [{ id: movingNode.id, data: patch }] }).changes);
474
+ const thicknesses = bearingThicknesses(position, pendingRotation);
475
+ const own = thicknesses.find(({ id }) => id === movingNode.id)?.data;
476
+ const update = [
477
+ { id: movingNode.id, data: { ...patch, ...own } },
478
+ ...thicknesses.filter(({ id }) => id !== movingNode.id),
479
+ ];
480
+ scene.applyNodeChanges(seatRoofs(scene.nodes, { update }).changes);
386
481
  }
387
482
  else {
388
483
  useScene.getState().updateNodes([
@@ -9,4 +9,6 @@ export declare const doorBatchable: BatchableConfig;
9
9
  export declare const windowBatchable: BatchableConfig;
10
10
  /** Imported meshes and blocks build their own geometry per node, rebuilt in place. */
11
11
  export declare const perNodeGeometryBatchable: BatchableConfig;
12
+ /** Parametric furniture that changes only through edits (shelves): its meshes hold still between marks. */
13
+ export declare const staticBatchable: BatchableConfig;
12
14
  //# sourceMappingURL=batchable.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"batchable.d.ts","sourceRoot":"","sources":["../../../src/shared/node-batch/batchable.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,eAAe,EAGrB,MAAM,kBAAkB,CAAA;AAEzB,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,SAAU,OAAO,aAAa,MAAM,WAA8B,CAAA;AAE/F,eAAO,MAAM,eAAe,EAAE,eAI7B,CAAA;AAED,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,EAAE,eAI9B,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,eAgB3B,CAAA;AAMD,eAAO,MAAM,aAAa,EAAE,eAI3B,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,eAI7B,CAAA;AAED,sFAAsF;AACtF,eAAO,MAAM,wBAAwB,EAAE,eAGtC,CAAA"}
1
+ {"version":3,"file":"batchable.d.ts","sourceRoot":"","sources":["../../../src/shared/node-batch/batchable.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,eAAe,EAGrB,MAAM,kBAAkB,CAAA;AAEzB,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,SAAU,OAAO,aAAa,MAAM,WAA8B,CAAA;AAE/F,eAAO,MAAM,eAAe,EAAE,eAI7B,CAAA;AAED,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,EAAE,eAI9B,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,eAgB3B,CAAA;AAMD,eAAO,MAAM,aAAa,EAAE,eAI3B,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,eAI7B,CAAA;AAED,sFAAsF;AACtF,eAAO,MAAM,wBAAwB,EAAE,eAGtC,CAAA;AAED,2GAA2G;AAC3G,eAAO,MAAM,eAAe,EAAE,eAE7B,CAAA"}
@@ -41,3 +41,7 @@ export const perNodeGeometryBatchable = {
41
41
  scope: 'level',
42
42
  batchKey: nodeMeshBatchKey,
43
43
  };
44
+ /** Parametric furniture that changes only through edits (shelves): its meshes hold still between marks. */
45
+ export const staticBatchable = {
46
+ scope: 'level',
47
+ };
@@ -6,8 +6,23 @@ import type { BatchCandidate } from './types.js';
6
6
  */
7
7
  export declare function batchableKinds(): ReadonlyMap<string, BatchableConfig>;
8
8
  export declare function batchableConfig(node: AnyNode | undefined): BatchableConfig | undefined;
9
- /** A wall-scoped node (door, window) moves with its host wall. */
10
- export declare function isWallHosted(node: AnyNode | undefined): boolean;
9
+ /**
10
+ * The node's hosts between it and its level, nearest first, or null when the
11
+ * chain does not reach a level or a host is hidden — a hidden host hides its
12
+ * children through group visibility, while batch instances hang off the level
13
+ * root and would keep drawing them — or a host draws itself because it moves
14
+ * (an animating item, a door mid-swing): what it carries moves with it. A host's edits, gestures and tint release
15
+ * the nodes it carries ({@link hostsBusy}), so a batched copy never stays
16
+ * behind when the host moves.
17
+ */
18
+ export declare function hostChain(node: AnyNode, nodes: Record<string, AnyNode | undefined>): {
19
+ levelId: string;
20
+ hosts: AnyNode[];
21
+ } | null;
22
+ /** Whether any host of `nodeId` (not the node itself) satisfies `busy`. */
23
+ export declare function hostsBusy(nodeId: string, nodes: Record<string, AnyNode | undefined>, busy: (hostId: string) => boolean): boolean;
24
+ /** Adds every batchable node carried by `nodeId` (its descendants, at any depth) to `out`. */
25
+ export declare function addBatchableDescendants(nodeId: string, nodes: Record<string, AnyNode | undefined>, out: Set<string>): void;
11
26
  export declare function collectBatchCandidate(nodeId: string): BatchCandidate | null;
12
27
  export declare function hideBatchedNode(candidate: BatchCandidate): void;
13
28
  /**
@@ -22,9 +37,10 @@ export declare function hideBatchedNode(candidate: BatchCandidate): void;
22
37
  export declare function revealAllBatchedHolds(): void;
23
38
  export declare function revealBatchedNode(nodeId: string): void;
24
39
  /**
25
- * Nodes the viewer is lighting up — plus hosted openings whose host wall is
26
- * lit or mid-gesture: a dragged wall carries its doors with it through live
27
- * overrides, and a batched copy would stay behind until commit.
40
+ * Nodes the viewer is lighting up — plus nodes whose host is lit or
41
+ * mid-gesture: a dragged wall carries its doors, a moved cabinet run its
42
+ * modules, through live overrides and transforms, and a batched copy would
43
+ * stay behind until commit.
28
44
  */
29
45
  export declare function collectTintedNodes(nodeIds: ReadonlySet<string>): Set<string>;
30
46
  export declare function getBatchableNodeIds(): ReadonlySet<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"candidates.d.ts","sourceRoot":"","sources":["../../../src/shared/node-batch/candidates.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAEZ,KAAK,eAAe,EAOrB,MAAM,kBAAkB,CAAA;AAIzB,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,SAAS,CAAA;AAWzD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,CAYrE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,eAAe,GAAG,SAAS,CAEtF;AAED,kEAAkE;AAClE,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAE/D;AAsDD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAsE3E;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,CAI/D;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAQ5C;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAKtD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAyB5E;AAED,wBAAgB,mBAAmB,IAAI,WAAW,CAAC,MAAM,CAAC,CAOzD"}
1
+ {"version":3,"file":"candidates.d.ts","sourceRoot":"","sources":["../../../src/shared/node-batch/candidates.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAEZ,KAAK,eAAe,EAOrB,MAAM,kBAAkB,CAAA;AAIzB,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,SAAS,CAAA;AAWzD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,CAYrE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,eAAe,GAAG,SAAS,CAEtF;AAgCD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC,GACzC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,EAAE,CAAA;CAAE,GAAG,IAAI,CAiB9C;AAkBD,2EAA2E;AAC3E,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC,EAC1C,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,GAChC,OAAO,CAOT;AAED,8FAA8F;AAC9F,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC,EAC1C,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,GACf,IAAI,CAQN;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CA+E3E;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,CAI/D;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAQ5C;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAKtD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAqB5E;AAED,wBAAgB,mBAAmB,IAAI,WAAW,CAAC,MAAM,CAAC,CAOzD"}