@pascal-app/nodes 1.0.6 → 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,157 @@
1
+ import { beamBottomElevation, createFramingPost, DEFAULT_FRAMING_POST_SIZE, emitter, FRAMING_POST_SIZES, framingPostFields, framingPostSize, framingPostTopAt, getFloorPlacedElevation, postStationsAlong, } from '@pascal-app/core';
2
+ import { getMovingNode, isGridSnapActive, snapBuildingLocalToWorldGrid, snapWallDraftPointDetailed, useEditor, } from '@pascal-app/editor';
3
+ /** Posts no further apart than this under a beam the panel posts: 8 ft, as a porch's are. */
4
+ export const FRAMING_POST_SPACING = 8 * 12 * 0.0254;
5
+ /**
6
+ * The Post tool is the column tool armed with a framing post's fields (`toolDefaults.column`,
7
+ * `role: 'post'`): its size and base, or null while it places ornamental columns.
8
+ */
9
+ export function framingPostToolChoices(defaults) {
10
+ if (defaults?.role !== 'post')
11
+ return null;
12
+ const width = typeof defaults.width === 'number' ? defaults.width : undefined;
13
+ const size = (width !== undefined && framingPostSize({ width, depth: width })) || DEFAULT_FRAMING_POST_SIZE;
14
+ const base = defaults.postBase;
15
+ return {
16
+ size,
17
+ base: base === 'post-base' || base === 'pier' ? base : 'none',
18
+ };
19
+ }
20
+ /** The column tool's defaults that make it the Post tool: a post of this size and base. */
21
+ export function framingPostToolDefaults(size = DEFAULT_FRAMING_POST_SIZE, base = 'none') {
22
+ return { ...framingPostFields(size, base) };
23
+ }
24
+ /**
25
+ * Drops a preset still following the cursor (a column preset's clone on the move tool): while it
26
+ * moves, no build tool mounts.
27
+ */
28
+ export function dropInflightColumnPlacement() {
29
+ if (!getMovingNode())
30
+ return;
31
+ emitter.emit('tool:cancel');
32
+ useEditor.getState().setMovingNode(null);
33
+ }
34
+ /**
35
+ * The size and base last picked, kept apart from the tool's defaults: a host clears those when it
36
+ * arms the column tool from a tile, and the Post tile should come back as the user left it.
37
+ */
38
+ let lastChoices = { size: DEFAULT_FRAMING_POST_SIZE, base: 'none' };
39
+ /**
40
+ * Arms the column tool as the Post tool (the Build panel's Post tile): a post of `size` on `base`,
41
+ * else as the tool has them, else as they were last picked.
42
+ */
43
+ export function armFramingPostTool(size, base) {
44
+ dropInflightColumnPlacement();
45
+ const editor = useEditor.getState();
46
+ const current = framingPostToolChoices(editor.toolDefaults.column) ?? lastChoices;
47
+ lastChoices = { size: size ?? current.size, base: base ?? current.base };
48
+ editor.setToolDefaults('column', framingPostToolDefaults(lastChoices.size, lastChoices.base));
49
+ if (!(editor.mode === 'build' && editor.tool === 'column'))
50
+ editor.armToolMode({ mode: 'build', tool: 'column' });
51
+ }
52
+ /** A point the wall snap reads as a wall: a segment of no length catches at the point. */
53
+ function pointReference(id, parentId, at) {
54
+ return {
55
+ object: 'node',
56
+ id: id,
57
+ type: 'wall',
58
+ parentId,
59
+ visible: true,
60
+ metadata: {},
61
+ children: [],
62
+ start: at,
63
+ end: at,
64
+ frontSide: 'unknown',
65
+ backSide: 'unknown',
66
+ };
67
+ }
68
+ /**
69
+ * What a post set on `levelId` snaps to: each beam's centreline (its ends, its middle and its run,
70
+ * so a post lands under a beam end or anywhere along it) and the other posts' and columns'
71
+ * centres.
72
+ */
73
+ export function postSnapTargets(nodes, levelId, ignoreIds = []) {
74
+ const targets = [];
75
+ for (const node of Object.values(nodes)) {
76
+ if (node.parentId !== levelId || node.visible === false || ignoreIds.includes(node.id))
77
+ continue;
78
+ if (node.type === 'beam') {
79
+ targets.push({ ...pointReference(node.id, node.parentId, node.start), end: node.end });
80
+ }
81
+ else if (node.type === 'column') {
82
+ targets.push(pointReference(node.id, node.parentId, [node.position[0], node.position[2]]));
83
+ }
84
+ }
85
+ return targets;
86
+ }
87
+ /**
88
+ * A post's plan point, snapped: a beam end, a point along a beam or another post catch it within
89
+ * the snap's reach, otherwise the grid while it snaps. `free` (Alt) places it as it is.
90
+ */
91
+ export function snapPostPoint(args) {
92
+ if (args.free)
93
+ return { point: args.point, snap: null };
94
+ const step = useEditor.getState().gridSnapStep;
95
+ const grid = isGridSnapActive();
96
+ const result = snapWallDraftPointDetailed({
97
+ point: args.point,
98
+ walls: postSnapTargets(args.nodes, args.levelId, args.ignoreIds),
99
+ // Beams and posts always catch a post; the grid is the snapping mode's to give.
100
+ magnetic: true,
101
+ gridSnap: (point) => (grid ? snapBuildingLocalToWorldGrid(point, step) : point),
102
+ });
103
+ return { point: result.point, snap: result.snap };
104
+ }
105
+ /** The runtime foot: the elected support's top under the post, plus its own lift. */
106
+ export const electedPostFoot = (nodes, levelId) => (post) => getFloorPlacedElevation({
107
+ node: post,
108
+ nodes: nodes,
109
+ position: post.position,
110
+ levelId,
111
+ }) + post.position[1];
112
+ /**
113
+ * A framing post at a plan point, standing from its foot up to the underside of the beam over it,
114
+ * else to the ceiling plane: what the Post tool places, and its ghost.
115
+ */
116
+ export function framingPostAt(args) {
117
+ const draft = createFramingPost({
118
+ position: args.point,
119
+ size: args.choices.size,
120
+ base: args.choices.base,
121
+ levelId: args.levelId,
122
+ });
123
+ const base = args.foot(draft);
124
+ const { top, beamId } = framingPostTopAt(args.nodes, args.levelId, args.point, {
125
+ baseElevation: base,
126
+ side: FRAMING_POST_SIZES[args.choices.size],
127
+ });
128
+ return {
129
+ post: createFramingPost({
130
+ position: args.point,
131
+ size: args.choices.size,
132
+ base: args.choices.base,
133
+ levelId: args.levelId,
134
+ height: top - base,
135
+ }),
136
+ beamId,
137
+ };
138
+ }
139
+ /**
140
+ * Posts under a beam: one at each end and evenly between, no further apart than `spacing`, each
141
+ * from its foot up to this beam's underside. Skips a station a post already stands at.
142
+ */
143
+ export function framingPostsUnderBeam(args) {
144
+ const levelId = args.beam.parentId;
145
+ if (!levelId)
146
+ return [];
147
+ const standing = Object.values(args.nodes).filter((node) => node.type === 'column' && node.parentId === levelId);
148
+ const underside = beamBottomElevation(args.nodes, args.beam);
149
+ return postStationsAlong(args.beam.start, args.beam.end, args.spacing ?? FRAMING_POST_SPACING)
150
+ .filter((point) => !standing.some((post) => Math.hypot(post.position[0] - point[0], post.position[2] - point[1]) <
151
+ Math.max(post.width, FRAMING_POST_SIZES[args.choices.size])))
152
+ .map((point) => {
153
+ const fields = { position: point, ...args.choices, levelId };
154
+ const foot = args.foot(createFramingPost(fields));
155
+ return createFramingPost({ ...fields, height: underside - foot });
156
+ });
157
+ }
@@ -0,0 +1,17 @@
1
+ import { type AnyNode, type AnyNodeId, type ColumnNode, type FramingPostSize } from '@pascal-app/core';
2
+ /** The fields that make a post another square size, its base kept in proportion. */
3
+ export declare function framingPostSizePatch(post: ColumnNode, size: FramingPostSize): Partial<ColumnNode>;
4
+ /** Where a post's top goes: the beam over it, else the ceiling plane, and its height to it from its foot. */
5
+ export declare function framingPostFit(nodes: Record<AnyNodeId, AnyNode>, post: ColumnNode, foot: number): {
6
+ height: number;
7
+ beamId: string | null;
8
+ } | null;
9
+ /**
10
+ * A framing post's settings in the column panel, in place of a column's styles: its size, its
11
+ * base, its wood, its height with a fit to the beam over it, and the deck-post height check.
12
+ */
13
+ export declare function FramingPostSection({ node, onUpdate, }: {
14
+ node: ColumnNode;
15
+ onUpdate: (updates: Partial<ColumnNode>) => void;
16
+ }): import("react").JSX.Element;
17
+ //# sourceMappingURL=post-section.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-section.d.ts","sourceRoot":"","sources":["../../src/column/post-section.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,UAAU,EAKf,KAAK,eAAe,EAOrB,MAAM,kBAAkB,CAAA;AAczB,oFAAoF;AACpF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAWjG;AAED,6GAA6G;AAC7G,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EACjC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,GACX;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CASlD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAA;CACjD,+BAyHA"}
@@ -0,0 +1,95 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { FRAMING_POST_BASE_LABELS, FRAMING_POST_MATERIAL_REF, FRAMING_POST_SIZES, framingPostBasePatch, framingPostHeightLimit, framingPostSize, framingPostTopAt, usePascalI18n, useScene, } from '@pascal-app/core';
4
+ import { formatLinearMeasurement, MetricControl, PanelSection, SegmentedControl, } from '@pascal-app/editor';
5
+ import { useViewer } from '@pascal-app/viewer';
6
+ import { electedPostFoot } from './post-placement.js';
7
+ /** Sawn lumber for a post kept dry inside; a post's default is treated (`FRAMING_POST_MATERIAL_REF`). */
8
+ const UNTREATED_REF = 'library:wood-woodfine2';
9
+ const CUSTOM = 'custom';
10
+ /** The fields that make a post another square size, its base kept in proportion. */
11
+ export function framingPostSizePatch(post, size) {
12
+ const side = FRAMING_POST_SIZES[size];
13
+ return {
14
+ width: side,
15
+ depth: side,
16
+ radius: side / 2,
17
+ ...framingPostBasePatch({ width: side, depth: side, slots: post.slots }, post.postBase ?? 'none'),
18
+ };
19
+ }
20
+ /** Where a post's top goes: the beam over it, else the ceiling plane, and its height to it from its foot. */
21
+ export function framingPostFit(nodes, post, foot) {
22
+ if (!post.parentId)
23
+ return null;
24
+ const { top, beamId } = framingPostTopAt(nodes, post.parentId, [post.position[0], post.position[2]], { baseElevation: foot, side: post.width });
25
+ return { height: top - foot, beamId };
26
+ }
27
+ /**
28
+ * A framing post's settings in the column panel, in place of a column's styles: its size, its
29
+ * base, its wood, its height with a fit to the beam over it, and the deck-post height check.
30
+ */
31
+ export function FramingPostSection({ node, onUpdate, }) {
32
+ const i18n = usePascalI18n();
33
+ const unit = useViewer((state) => state.unit);
34
+ const metricNotation = useViewer((state) => state.metricNotation);
35
+ const nodes = useScene((state) => state.nodes);
36
+ const size = framingPostSize(node) ?? CUSTOM;
37
+ const treated = (node.slots?.shaft ?? FRAMING_POST_MATERIAL_REF) === FRAMING_POST_MATERIAL_REF;
38
+ const limit = framingPostHeightLimit(node);
39
+ const length = (meters) => formatLinearMeasurement(meters, unit, metricNotation);
40
+ const fit = node.parentId !== null
41
+ ? framingPostFit(nodes, node, electedPostFoot(nodes, node.parentId)(node))
42
+ : null;
43
+ const fitBeam = fit?.beamId ? nodes[fit.beamId] : undefined;
44
+ return (_jsxs(PanelSection, { title: i18n._({ id: 'node.column.postSection.post', message: 'Post' }), children: [_jsx(SegmentedControl, { onChange: (next) => {
45
+ if (next !== CUSTOM)
46
+ onUpdate(framingPostSizePatch(node, next));
47
+ }, options: [
48
+ ...Object.keys(FRAMING_POST_SIZES).map((value) => ({
49
+ label: value,
50
+ value,
51
+ })),
52
+ ...(size === CUSTOM
53
+ ? [
54
+ {
55
+ label: i18n._({ id: 'node.column.postSection.custom', message: 'Custom' }),
56
+ value: CUSTOM,
57
+ },
58
+ ]
59
+ : []),
60
+ ], value: size }), _jsx(SegmentedControl, { onChange: (base) => onUpdate(framingPostBasePatch(node, base)), options: ['none', 'post-base', 'pier'].map((value) => ({
61
+ label: FRAMING_POST_BASE_LABELS[value],
62
+ value,
63
+ })), value: node.postBase ?? 'none' }), _jsx(SegmentedControl, { onChange: (wood) => onUpdate({
64
+ slots: {
65
+ ...node.slots,
66
+ shaft: wood === 'treated' ? FRAMING_POST_MATERIAL_REF : UNTREATED_REF,
67
+ },
68
+ }), options: [
69
+ {
70
+ label: i18n._({ id: 'node.column.postSection.treated', message: 'Treated' }),
71
+ value: 'treated',
72
+ },
73
+ {
74
+ label: i18n._({ id: 'node.column.postSection.untreated', message: 'Untreated' }),
75
+ value: 'untreated',
76
+ },
77
+ ], value: treated ? 'treated' : 'untreated' }), _jsx(MetricControl, { label: i18n._({ id: 'node.column.postSection.height', message: 'Height' }), min: 0.3, onChange: (height) => onUpdate({ height }), precision: 3, step: 0.01, unit: "m", value: node.height }), fit && Math.abs(fit.height - node.height) > 0.001 && fit.height > 0.3 && (_jsx("button", { className: "self-start rounded-full border border-border/50 px-3 py-1 text-muted-foreground text-xs hover:text-foreground", "data-post-fit": true, onClick: () => onUpdate({ height: fit.height }), type: "button", children: fitBeam
78
+ ? i18n._({
79
+ id: 'node.column.postSection.fitToTheBeamOverIt',
80
+ message: 'Fit to the beam over it ({height})',
81
+ values: { height: length(fit.height) },
82
+ })
83
+ : i18n._({
84
+ id: 'node.column.postSection.fitToTheCeilingPlane',
85
+ message: 'Fit to the ceiling plane ({height})',
86
+ values: { height: length(fit.height) },
87
+ }) })), limit && (_jsx("p", { className: "rounded-lg bg-accent/30 px-2.5 py-2 text-muted-foreground text-xs", role: "status", children: i18n._({
88
+ id: 'node.column.postSection.aSizeDeckPostStandsNo',
89
+ message: 'A {size} deck post stands no taller than {limit} (IRC Table R507.4, by species and the area it carries): check it, or use the next size up.',
90
+ values: { size: limit.size, limit: length(limit.limit) },
91
+ }) })), _jsx("button", { className: "self-start rounded-full border border-border/50 px-3 py-1 text-muted-foreground text-xs hover:text-foreground", onClick: () => onUpdate({ role: undefined, postBase: undefined }), title: i18n._({
92
+ id: 'node.column.postSection.keepItsShapeAndStyleIt',
93
+ message: 'Keep its shape and style it as a column',
94
+ }), type: "button", children: i18n._({ id: 'node.column.postSection.makeItAColumn', message: 'Make it a column' }) })] }));
95
+ }
@@ -0,0 +1,11 @@
1
+ import { type FramingPostToolChoices } from './post-placement.js';
2
+ /**
3
+ * The Post tool: the column tool armed with a framing post (`framingPostToolChoices`). The post
4
+ * snaps under a beam's end, anywhere along a beam, onto another post, else to the grid (Alt free);
5
+ * it stands from what it lands on up to the underside of the beam over it, else to the ceiling
6
+ * plane, and the ghost shows that height before the click. Repeats as the column tool does.
7
+ */
8
+ export declare function FramingPostTool({ choices }: {
9
+ choices: FramingPostToolChoices;
10
+ }): import("react").JSX.Element | null;
11
+ //# sourceMappingURL=post-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-tool.d.ts","sourceRoot":"","sources":["../../src/column/post-tool.tsx"],"names":[],"mappings":"AA2BA,OAAO,EAEL,KAAK,sBAAsB,EAG5B,MAAM,kBAAkB,CAAA;AAKzB;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,sBAAsB,CAAA;CAAE,sCA2F/E"}
@@ -0,0 +1,94 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { ColumnNode as ColumnNodeSchema, emitter, resolveSupportSlabPatch, useScene, } from '@pascal-app/core';
4
+ import { getFloorStackPreviewPosition, triggerSFX, useEditor, usePlacementPreview, useWallSnapIndicator, } from '@pascal-app/editor';
5
+ import { useViewer } from '@pascal-app/viewer';
6
+ import { useEffect, useRef, useState } from 'react';
7
+ import { stopPlacementCommitPropagation, subscribeFloorPlacementClicks, } from '../shared/floor-placement.js';
8
+ import { electedPostFoot, framingPostAt, snapPostPoint, } from './post-placement.js';
9
+ import { ColumnPreview } from './renderer.js';
10
+ /**
11
+ * The Post tool: the column tool armed with a framing post (`framingPostToolChoices`). The post
12
+ * snaps under a beam's end, anywhere along a beam, onto another post, else to the grid (Alt free);
13
+ * it stands from what it lands on up to the underside of the beam over it, else to the ceiling
14
+ * plane, and the ghost shows that height before the click. Repeats as the column tool does.
15
+ */
16
+ export function FramingPostTool({ choices }) {
17
+ const levelId = useViewer((state) => state.selection.levelId);
18
+ const cursorRef = useRef(null);
19
+ const [ghost, setGhost] = useState(null);
20
+ useEffect(() => {
21
+ if (!levelId)
22
+ return;
23
+ let last = null;
24
+ setGhost(null);
25
+ const place = (raw, free) => {
26
+ const nodes = useScene.getState().nodes;
27
+ const { point, snap } = snapPostPoint({ point: raw, nodes, levelId, free });
28
+ if (snap)
29
+ useWallSnapIndicator.getState().set({ x: point[0], z: point[1], kind: snap });
30
+ else
31
+ useWallSnapIndicator.getState().clear();
32
+ return {
33
+ point,
34
+ ...framingPostAt({ nodes, levelId, point, choices, foot: electedPostFoot(nodes, levelId) }),
35
+ };
36
+ };
37
+ const show = (placed) => {
38
+ const visual = getFloorStackPreviewPosition({
39
+ node: placed.post,
40
+ position: placed.post.position,
41
+ rotation: 0,
42
+ levelId,
43
+ });
44
+ cursorRef.current?.position.set(...visual);
45
+ usePlacementPreview.getState().set(placed.post);
46
+ setGhost(placed.post);
47
+ };
48
+ const onMove = (event) => {
49
+ const next = place([event.localPosition[0], event.localPosition[2]], event.nativeEvent?.altKey === true);
50
+ if (last &&
51
+ last.point[0] === next.point[0] &&
52
+ last.point[1] === next.point[1] &&
53
+ Math.abs(last.post.height - next.post.height) < 1e-6)
54
+ return;
55
+ if (!last || last.point[0] !== next.point[0] || last.point[1] !== next.point[1])
56
+ triggerSFX('sfx:grid-snap');
57
+ last = next;
58
+ show(next);
59
+ };
60
+ const onClick = (event) => {
61
+ // A click on a beam or a post is a node event, its point not the level's: use the move's.
62
+ const placed = last ??
63
+ place([event.localPosition[0], event.localPosition[2]], event.nativeEvent?.altKey === true);
64
+ stopPlacementCommitPropagation(event);
65
+ const nodes = useScene.getState().nodes;
66
+ const posts = Object.values(nodes).filter((node) => node.type === 'column' && node.role === 'post').length;
67
+ const post = ColumnNodeSchema.parse({
68
+ ...placed.post,
69
+ name: `Post ${posts + 1}`,
70
+ ...resolveSupportSlabPatch(placed.post, { ...nodes, [placed.post.id]: placed.post }),
71
+ });
72
+ useScene.getState().createNode(post, levelId);
73
+ triggerSFX('sfx:structure-build');
74
+ last = null;
75
+ if (useEditor.getState().getContinuation('point') === 'repeat')
76
+ return;
77
+ useViewer.getState().setSelection({ selectedIds: [post.id] });
78
+ usePlacementPreview.getState().clear();
79
+ useEditor.getState().setTool(null);
80
+ useEditor.getState().setMode('select');
81
+ };
82
+ emitter.on('grid:move', onMove);
83
+ const unsubscribeClicks = subscribeFloorPlacementClicks(onClick);
84
+ return () => {
85
+ emitter.off('grid:move', onMove);
86
+ unsubscribeClicks();
87
+ usePlacementPreview.getState().clear();
88
+ useWallSnapIndicator.getState().clear();
89
+ };
90
+ }, [levelId, choices]);
91
+ if (!levelId)
92
+ return null;
93
+ return (_jsx("group", { ref: cursorRef, visible: ghost !== null, children: ghost && _jsx(ColumnPreview, { node: ghost }) }));
94
+ }
@@ -1,14 +1,7 @@
1
1
  /**
2
- * Registry-driven column placement tool. Mirrors the shelf build tool:
3
- * a translucent `ColumnPreview` ghost follows the cursor (the piece the
4
- * legacy editor-side `ColumnTool` lacked — it only showed a sphere), grid
5
- * snap is layered with Figma-style alignment, and a `grid:click` commits.
6
- *
7
- * Lives in `packages/nodes` (not the editor) specifically so it can import
8
- * the column geometry for the ghost — the editor package can't depend on
9
- * `nodes`. Wired via `def.tool`, so `ToolManager`'s registry-first path
10
- * mounts it and the legacy `<ColumnTool>` branch no longer fires.
2
+ * The column tool, or the Post tool while the Build panel's Post tile has armed it with a framing
3
+ * post's fields (`toolDefaults.column`, `framingPostToolChoices`).
11
4
  */
12
- declare const ColumnTool: () => import("react").JSX.Element | null;
5
+ declare const ColumnTool: () => import("react").JSX.Element;
13
6
  export default ColumnTool;
14
7
  //# sourceMappingURL=tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/column/tool.tsx"],"names":[],"mappings":"AAwDA;;;;;;;;;;GAUG;AACH,QAAA,MAAM,UAAU,0CAkMf,CAAA;eAEc,UAAU"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/column/tool.tsx"],"names":[],"mappings":"AAyQA;;;GAGG;AACH,QAAA,MAAM,UAAU,mCAOf,CAAA;eAEc,UAAU"}
@@ -7,6 +7,8 @@ import { useThree } from '@react-three/fiber';
7
7
  import { useEffect, useMemo, useRef, useState } from 'react';
8
8
  import { getLevelLocalSnappedPosition, resolveAlignedFloorPlacement, stopPlacementCommitPropagation, subscribeFloorPlacementClicks, } from '../shared/floor-placement.js';
9
9
  import { collectStructuralGridAxes, resolveStructuralGridSnap, } from '../structural-grid/coordination.js';
10
+ import { framingPostToolChoices } from './post-placement.js';
11
+ import { FramingPostTool } from './post-tool.js';
10
12
  import { ColumnPreview } from './renderer.js';
11
13
  const DEFAULT_COLUMN_PRESET_ID = 'basicPillar';
12
14
  function createColumnFromPreset(presetId, position) {
@@ -29,7 +31,7 @@ function createColumnFromPreset(presetId, position) {
29
31
  * `nodes`. Wired via `def.tool`, so `ToolManager`'s registry-first path
30
32
  * mounts it and the legacy `<ColumnTool>` branch no longer fires.
31
33
  */
32
- const ColumnTool = () => {
34
+ const PillarTool = () => {
33
35
  const activeLevelId = useViewer((state) => state.selection.levelId);
34
36
  const camera = useThree((state) => state.camera);
35
37
  const cameraRef = useRef(camera);
@@ -192,4 +194,14 @@ const ColumnTool = () => {
192
194
  return null;
193
195
  return (_jsx("group", { ref: cursorRef, visible: cursorVisible, children: _jsx(ColumnPreview, { node: previewNode }) }));
194
196
  };
197
+ /**
198
+ * The column tool, or the Post tool while the Build panel's Post tile has armed it with a framing
199
+ * post's fields (`toolDefaults.column`, `framingPostToolChoices`).
200
+ */
201
+ const ColumnTool = () => {
202
+ const size = useEditor((state) => framingPostToolChoices(state.toolDefaults.column)?.size ?? null);
203
+ const base = useEditor((state) => framingPostToolChoices(state.toolDefaults.column)?.base ?? 'none');
204
+ const choices = useMemo(() => (size ? { size, base } : null), [size, base]);
205
+ return choices ? _jsx(FramingPostTool, { choices: choices }) : _jsx(PillarTool, {});
206
+ };
195
207
  export default ColumnTool;
@@ -1 +1 @@
1
- {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/cupola/panel.tsx"],"names":[],"mappings":"AA0BA;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,uCA4OlC"}
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/cupola/panel.tsx"],"names":[],"mappings":"AA2BA;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,uCAuPlC"}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { getActiveRoofHeight, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
3
+ import { getActiveRoofHeight, useLiveNodeOverrides, usePascalI18n, useScene, } from '@pascal-app/core';
4
4
  import { ActionButton, ActionGroup, duplicateNodeAndPickUp, PanelSection, PanelWrapper, SegmentedControl, SliderControl, triggerSFX, useEditor, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { Copy, Move, Trash2 } from 'lucide-react';
@@ -11,6 +11,7 @@ import { useCallback } from 'react';
11
11
  * flow the placement tool uses. Mirrors the box-vent panel.
12
12
  */
13
13
  export default function CupolaPanel() {
14
+ const i18n = usePascalI18n();
14
15
  const selectedId = useViewer((s) => s.selection.selectedIds[0]);
15
16
  const setSelection = useViewer((s) => s.setSelection);
16
17
  const updateNode = useScene((s) => s.updateNode);
@@ -78,11 +79,17 @@ export default function CupolaPanel() {
78
79
  }, [selectedId, node, deleteNode, setSelection]);
79
80
  if (!(node && node.type === 'cupola' && selectedId))
80
81
  return null;
81
- return (_jsxs(PanelWrapper, { icon: "/icons/roof.webp", onBack: node.roofSegmentId ? handleBack : undefined, onClose: handleClose, title: node.name || 'Cupola', width: 300, children: [_jsxs(PanelSection, { title: "Style", children: [_jsx(SegmentedControl, { onChange: (v) => handleUpdate({ roofStyle: v }), options: [
82
- { label: 'Dome', value: 'dome' },
83
- { label: 'Pyramid', value: 'pyramid' },
82
+ return (_jsxs(PanelWrapper, { icon: "/icons/roof.webp", onBack: node.roofSegmentId ? handleBack : undefined, onClose: handleClose, title: node.name || i18n._({ id: 'node.cupola.panel.cupola', message: 'Cupola' }), width: 300, children: [_jsxs(PanelSection, { title: i18n._({ id: 'node.cupola.panel.style', message: 'Style' }), children: [_jsx(SegmentedControl, { onChange: (v) => handleUpdate({ roofStyle: v }), options: [
83
+ { label: i18n._({ id: 'node.cupola.panel.dome', message: 'Dome' }), value: 'dome' },
84
+ {
85
+ label: i18n._({ id: 'node.cupola.panel.pyramid', message: 'Pyramid' }),
86
+ value: 'pyramid',
87
+ },
84
88
  ], value: node.roofStyle ?? 'dome' }), _jsx(SegmentedControl, { onChange: (v) => handleUpdate({ finial: v === 'on' }), options: [
85
- { label: 'Finial', value: 'on' },
86
- { label: 'No Finial', value: 'off' },
87
- ], value: (node.finial ?? true) ? 'on' : 'off' })] }), _jsxs(PanelSection, { title: "Dimensions", children: [_jsx(SliderControl, { label: "Width", max: 1000, min: 0.3, onChange: (v) => previewProp({ width: v }), onCommit: (v) => handleUpdate({ width: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.width }), _jsx(SliderControl, { label: "Depth", max: 1000, min: 0.3, onChange: (v) => previewProp({ depth: v }), onCommit: (v) => handleUpdate({ depth: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.depth }), _jsx(SliderControl, { label: "Height", max: 1000, min: 0.4, onChange: (v) => previewProp({ height: v }), onCommit: (v) => handleUpdate({ height: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.height })] }), _jsxs(PanelSection, { title: "Position", children: [_jsx(SliderControl, { label: "X", max: Math.round(((segment?.width ?? 10) / 2) * 100) / 100, min: -Math.round(((segment?.width ?? 10) / 2) * 100) / 100, onChange: (v) => previewProp({ position: [v, node.position[1] ?? 0, node.position[2] ?? 0] }), onCommit: (v) => handleUpdate({ position: [v, node.position[1] ?? 0, node.position[2] ?? 0] }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.position[0] ?? 0 }), _jsx(SliderControl, { label: "Y", max: Math.max((segment?.wallHeight ?? 3) + (segment ? getActiveRoofHeight(segment) : 3) + 2, (node.position[1] ?? 0) + 0.1), min: Math.min(0, (node.position[1] ?? 0) - 0.5), onChange: (v) => previewProp({ position: [node.position[0] ?? 0, v, node.position[2] ?? 0] }), onCommit: (v) => handleUpdate({ position: [node.position[0] ?? 0, v, node.position[2] ?? 0] }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.position[1] ?? 0 }), _jsx(SliderControl, { label: "Z", max: Math.round(((segment?.depth ?? 10) / 2) * 100) / 100, min: -Math.round(((segment?.depth ?? 10) / 2) * 100) / 100, onChange: (v) => previewProp({ position: [node.position[0] ?? 0, node.position[1] ?? 0, v] }), onCommit: (v) => handleUpdate({ position: [node.position[0] ?? 0, node.position[1] ?? 0, v] }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.position[2] ?? 0 }), _jsx(SliderControl, { label: "Rotation", max: 180, min: -180, onChange: (deg) => previewProp({ rotation: (deg * Math.PI) / 180 }), onCommit: (deg) => handleUpdate({ rotation: (deg * Math.PI) / 180 }), precision: 0, restoreOnCommit: false, step: 1, unit: "\u00B0", value: Math.round(((node.rotation ?? 0) * 180) / Math.PI) })] }), _jsx(PanelSection, { title: "Actions", children: _jsxs(ActionGroup, { children: [_jsx(ActionButton, { icon: _jsx(Move, { className: "h-3.5 w-3.5" }), label: "Move", onClick: handleMove }), _jsx(ActionButton, { icon: _jsx(Copy, { className: "h-3.5 w-3.5" }), label: "Duplicate", onClick: handleDuplicate }), _jsx(ActionButton, { className: "hover:bg-red-500/20", icon: _jsx(Trash2, { className: "h-3.5 w-3.5 text-red-600 dark:text-red-400" }), label: "Delete", onClick: handleDelete })] }) })] }));
89
+ { label: i18n._({ id: 'node.cupola.panel.finial', message: 'Finial' }), value: 'on' },
90
+ {
91
+ label: i18n._({ id: 'node.cupola.panel.noFinial', message: 'No Finial' }),
92
+ value: 'off',
93
+ },
94
+ ], value: (node.finial ?? true) ? 'on' : 'off' })] }), _jsxs(PanelSection, { title: i18n._({ id: 'node.cupola.panel.dimensions', message: 'Dimensions' }), children: [_jsx(SliderControl, { label: i18n._({ id: 'node.cupola.panel.width', message: 'Width' }), max: 1000, min: 0.3, onChange: (v) => previewProp({ width: v }), onCommit: (v) => handleUpdate({ width: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.width }), _jsx(SliderControl, { label: i18n._({ id: 'node.cupola.panel.depth', message: 'Depth' }), max: 1000, min: 0.3, onChange: (v) => previewProp({ depth: v }), onCommit: (v) => handleUpdate({ depth: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.depth }), _jsx(SliderControl, { label: i18n._({ id: 'node.cupola.panel.height', message: 'Height' }), max: 1000, min: 0.4, onChange: (v) => previewProp({ height: v }), onCommit: (v) => handleUpdate({ height: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.height })] }), _jsxs(PanelSection, { title: i18n._({ id: 'node.cupola.panel.position', message: 'Position' }), children: [_jsx(SliderControl, { label: "X", max: Math.round(((segment?.width ?? 10) / 2) * 100) / 100, min: -Math.round(((segment?.width ?? 10) / 2) * 100) / 100, onChange: (v) => previewProp({ position: [v, node.position[1] ?? 0, node.position[2] ?? 0] }), onCommit: (v) => handleUpdate({ position: [v, node.position[1] ?? 0, node.position[2] ?? 0] }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.position[0] ?? 0 }), _jsx(SliderControl, { label: "Y", max: Math.max((segment?.wallHeight ?? 3) + (segment ? getActiveRoofHeight(segment) : 3) + 2, (node.position[1] ?? 0) + 0.1), min: Math.min(0, (node.position[1] ?? 0) - 0.5), onChange: (v) => previewProp({ position: [node.position[0] ?? 0, v, node.position[2] ?? 0] }), onCommit: (v) => handleUpdate({ position: [node.position[0] ?? 0, v, node.position[2] ?? 0] }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.position[1] ?? 0 }), _jsx(SliderControl, { label: "Z", max: Math.round(((segment?.depth ?? 10) / 2) * 100) / 100, min: -Math.round(((segment?.depth ?? 10) / 2) * 100) / 100, onChange: (v) => previewProp({ position: [node.position[0] ?? 0, node.position[1] ?? 0, v] }), onCommit: (v) => handleUpdate({ position: [node.position[0] ?? 0, node.position[1] ?? 0, v] }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.position[2] ?? 0 }), _jsx(SliderControl, { label: i18n._({ id: 'node.cupola.panel.rotation', message: 'Rotation' }), max: 180, min: -180, onChange: (deg) => previewProp({ rotation: (deg * Math.PI) / 180 }), onCommit: (deg) => handleUpdate({ rotation: (deg * Math.PI) / 180 }), precision: 0, restoreOnCommit: false, step: 1, unit: "\u00B0", value: Math.round(((node.rotation ?? 0) * 180) / Math.PI) })] }), _jsx(PanelSection, { title: i18n._({ id: 'node.cupola.panel.actions', message: 'Actions' }), children: _jsxs(ActionGroup, { children: [_jsx(ActionButton, { icon: _jsx(Move, { className: "h-3.5 w-3.5" }), label: i18n._({ id: 'node.cupola.panel.move', message: 'Move' }), onClick: handleMove }), _jsx(ActionButton, { icon: _jsx(Copy, { className: "h-3.5 w-3.5" }), label: i18n._({ id: 'node.cupola.panel.duplicate', message: 'Duplicate' }), onClick: handleDuplicate }), _jsx(ActionButton, { className: "hover:bg-red-500/20", icon: _jsx(Trash2, { className: "h-3.5 w-3.5 text-red-600 dark:text-red-400" }), label: i18n._({ id: 'node.cupola.panel.delete', message: 'Delete' }), onClick: handleDelete })] }) })] }));
88
95
  }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The door's action-menu contributions, in 2D and 3D: swap the hinge side and swap the swing
3
+ * side without opening the panel's Swing section. One undo step each; a closed door opens so
4
+ * the new swing shows.
5
+ */
6
+ export default function DoorActions(): import("react").JSX.Element | null;
7
+ //# sourceMappingURL=actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/door/actions.tsx"],"names":[],"mappings":"AASA;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,uCAiClC"}
@@ -0,0 +1,32 @@
1
+ 'use client';
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { usePascalI18n, useScene } from '@pascal-app/core';
4
+ import { ActionMenuButton } from '@pascal-app/editor';
5
+ import { useViewer } from '@pascal-app/viewer';
6
+ import { ArrowLeftRight, ArrowUpDown } from 'lucide-react';
7
+ import { applyOpeningSwap } from '../shared/opening-swap.js';
8
+ import { doorMechanism } from './mechanism.js';
9
+ import { canSwapDoorHinge, canSwapDoorSwing, swapDoorHingePatch, swapDoorSwingPatch } from './swing.js';
10
+ /**
11
+ * The door's action-menu contributions, in 2D and 3D: swap the hinge side and swap the swing
12
+ * side without opening the panel's Swing section. One undo step each; a closed door opens so
13
+ * the new swing shows.
14
+ */
15
+ export default function DoorActions() {
16
+ const i18n = usePascalI18n();
17
+ const selected = useViewer((s) => s.selection.selectedIds);
18
+ const door = useScene((s) => {
19
+ const node = selected.length === 1 ? s.nodes[selected[0]] : undefined;
20
+ return node?.type === 'door' ? node : undefined;
21
+ });
22
+ const readOnly = useScene((s) => s.readOnly);
23
+ if (!door || readOnly || !canSwapDoorSwing(door))
24
+ return null;
25
+ return (_jsxs(_Fragment, { children: [canSwapDoorHinge(door) ? (_jsx(ActionMenuButton, { label: i18n._({ id: 'node.door.actions.swapHingeSide', message: 'Swap hinge side' }), onClick: (event) => {
26
+ event.stopPropagation();
27
+ applyOpeningSwap(door, swapDoorHingePatch(door), doorMechanism);
28
+ }, children: _jsx(ArrowLeftRight, { className: "h-4 w-4" }) })) : null, _jsx(ActionMenuButton, { label: i18n._({ id: 'node.door.actions.swapSwingSide', message: 'Swap swing side' }), onClick: (event) => {
29
+ event.stopPropagation();
30
+ applyOpeningSwap(door, swapDoorSwingPatch(door), doorMechanism);
31
+ }, children: _jsx(ArrowUpDown, { className: "h-4 w-4" }) })] }));
32
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"contextual-dimensions.d.ts","sourceRoot":"","sources":["../../src/door/contextual-dimensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAGpF,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,QAAQ,EACd,GAAG,EAAE,eAAe,GACnB,iBAAiB,GAAG,IAAI,CAK1B"}
1
+ {"version":3,"file":"contextual-dimensions.d.ts","sourceRoot":"","sources":["../../src/door/contextual-dimensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAIpF,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,QAAQ,EACd,GAAG,EAAE,eAAe,GACnB,iBAAiB,GAAG,IAAI,CAkB1B"}
@@ -1,6 +1,16 @@
1
+ import { getDoorOpeningSize, openingHostFacing } from '@pascal-app/core';
1
2
  import { buildWallHostedOpeningContextualDimensions } from '../wall/contextual-dimensions.js';
2
3
  export function buildDoorContextualDimensions(node, ctx) {
3
- return buildWallHostedOpeningContextualDimensions(node, ctx, {
4
+ const size = getDoorOpeningSize(node);
5
+ return buildWallHostedOpeningContextualDimensions({
6
+ ...node,
7
+ width: size.width,
8
+ position: [
9
+ node.position[0] - size.leafOffsetX * openingHostFacing(node),
10
+ node.position[1],
11
+ node.position[2],
12
+ ],
13
+ }, ctx, {
4
14
  showClearancesWhileMoving: false,
5
15
  useExteriorNormal: false,
6
16
  });
@@ -1 +1 @@
1
- {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/door/definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,cAAc,EAGf,MAAM,kBAAkB,CAAA;AA2BzB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAiKnC;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,OAAO,QAAQ,CA+H1D,CAAA"}
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/door/definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,cAAc,EAGf,MAAM,kBAAkB,CAAA;AA4BzB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AA8KnC;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,OAAO,QAAQ,CAiJ1D,CAAA"}