@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
@@ -1,5 +1,5 @@
1
1
  // The door tool's placement choices: the chips [O] Type and [L] Style.
2
- import { DOOR_STYLE_LABELS, DOOR_STYLES, DOOR_TYPE_SIZES, doorStyleLook, doorTypeFields, } from '@pascal-app/core/building';
2
+ import { DOOR_STYLE_LABELS, DOOR_STYLES, DOOR_TYPE_SIZES, doorStyleLook, doorTypeFields, NEW_DOOR_FRAME_THICKNESS, } from '@pascal-app/core/building';
3
3
  import { create } from 'zustand';
4
4
  /** The door panel's Type row and the tool's Type chip (garage types live under the panel's Garage). */
5
5
  export const doorTypeOptions = [
@@ -23,7 +23,14 @@ export const useDoorPlacement = create((set, get) => ({
23
23
  /** The door the tool places: the chips' type and style, written as add_door and the panel write them. */
24
24
  export function placedDoorFields() {
25
25
  const { type, style } = useDoorPlacement.getState();
26
- return { ...doorTypeFields(type), ...DOOR_TYPE_SIZES[type], ...doorStyleLook(style) };
26
+ return {
27
+ frameThickness: NEW_DOOR_FRAME_THICKNESS,
28
+ casingFaceA: true,
29
+ casingFaceB: true,
30
+ ...doorTypeFields(type),
31
+ ...DOOR_TYPE_SIZES[type],
32
+ ...doorStyleLook(style),
33
+ };
27
34
  }
28
35
  export const DOOR_PLACEMENT_HINTS = [
29
36
  {
@@ -0,0 +1,22 @@
1
+ import type { DoorNode } from '@pascal-app/core';
2
+ type SwingDoor = Pick<DoorNode, 'doorType' | 'hingesSide' | 'handleSide' | 'swingDirection'> & Partial<Pick<DoorNode, 'openingKind' | 'source'>>;
3
+ /** Whether a door swings on hinges (the panel's Swing section), so its swing can be swapped. */
4
+ export declare function canSwapDoorSwing(door: SwingDoor): boolean;
5
+ /** Whether a door has one hinge side to swap: a single hinged leaf. */
6
+ export declare function canSwapDoorHinge(door: SwingDoor): boolean;
7
+ /** The leaf hung from `side`'s jamb, with its handle on the free edge opposite the hinges. */
8
+ export declare function hingesSidePatch(side: 'left' | 'right'): Partial<DoorNode>;
9
+ /** The leaf hung from the other jamb: hinges and handle trade sides, so the handle stays on the free edge. */
10
+ export declare function swapDoorHingePatch(door: SwingDoor): Partial<DoorNode>;
11
+ /** The leaf swinging into the other side of the wall. */
12
+ export declare function swapDoorSwingPatch(door: SwingDoor): Partial<DoorNode>;
13
+ /**
14
+ * The swing that opens a door's leaf toward `side` of its wall: the face under the cursor while
15
+ * placing, so the door swings into the side it is placed from (R flips it to the other side). An
16
+ * inward door opens toward the face it is hung facing (`rotationY` 0 faces front, π back), so a
17
+ * door facing that side swings inward and one facing away swings outward. A garage door has no
18
+ * swing and keeps its own.
19
+ */
20
+ export declare function placementSwing(door: Pick<DoorNode, 'doorType' | 'swingDirection'>, rotationY: number, side: 'front' | 'back'): DoorNode['swingDirection'];
21
+ export {};
22
+ //# sourceMappingURL=swing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swing.d.ts","sourceRoot":"","sources":["../../src/door/swing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEhD,KAAK,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,gBAAgB,CAAC,GAC1F,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAA;AAInD,gGAAgG;AAChG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAMzD;AAED,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAEzD;AAED,8FAA8F;AAC9F,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAEzE;AAED,8GAA8G;AAC9G,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,CAErE;AAED,yDAAyD;AACzD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,CAErE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,UAAU,GAAG,gBAAgB,CAAC,EACnD,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,OAAO,GAAG,MAAM,GACrB,QAAQ,CAAC,gBAAgB,CAAC,CAI5B"}
@@ -0,0 +1,36 @@
1
+ const flip = (side) => (side === 'left' ? 'right' : 'left');
2
+ /** Whether a door swings on hinges (the panel's Swing section), so its swing can be swapped. */
3
+ export function canSwapDoorSwing(door) {
4
+ return (!door.source &&
5
+ door.openingKind !== 'opening' &&
6
+ (door.doorType === 'hinged' || door.doorType === 'double' || door.doorType === 'french'));
7
+ }
8
+ /** Whether a door has one hinge side to swap: a single hinged leaf. */
9
+ export function canSwapDoorHinge(door) {
10
+ return canSwapDoorSwing(door) && door.doorType === 'hinged';
11
+ }
12
+ /** The leaf hung from `side`'s jamb, with its handle on the free edge opposite the hinges. */
13
+ export function hingesSidePatch(side) {
14
+ return { hingesSide: side, handleSide: flip(side) };
15
+ }
16
+ /** The leaf hung from the other jamb: hinges and handle trade sides, so the handle stays on the free edge. */
17
+ export function swapDoorHingePatch(door) {
18
+ return { hingesSide: flip(door.hingesSide), handleSide: flip(door.handleSide) };
19
+ }
20
+ /** The leaf swinging into the other side of the wall. */
21
+ export function swapDoorSwingPatch(door) {
22
+ return { swingDirection: door.swingDirection === 'inward' ? 'outward' : 'inward' };
23
+ }
24
+ /**
25
+ * The swing that opens a door's leaf toward `side` of its wall: the face under the cursor while
26
+ * placing, so the door swings into the side it is placed from (R flips it to the other side). An
27
+ * inward door opens toward the face it is hung facing (`rotationY` 0 faces front, π back), so a
28
+ * door facing that side swings inward and one facing away swings outward. A garage door has no
29
+ * swing and keeps its own.
30
+ */
31
+ export function placementSwing(door, rotationY, side) {
32
+ if (door.doorType?.startsWith('garage-'))
33
+ return door.swingDirection;
34
+ const facing = Math.cos(rotationY) >= 0 ? 'front' : 'back';
35
+ return facing === side ? 'inward' : 'outward';
36
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/door/tool.tsx"],"names":[],"mappings":"AAuEA;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAsxBrB,CAAA;eAEc,QAAQ"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/door/tool.tsx"],"names":[],"mappings":"AAgFA;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAk2BrB,CAAA;eAEc,QAAQ"}
package/dist/door/tool.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { beginSceneHistoryDraft, DoorNode, emitter, holdHiddenWallPointerEvents, isCurvedWall, sceneRegistry, spatialGridManager, useScene, WallNode as WallNodeSchema, } from '@pascal-app/core';
2
+ import { beginSceneHistoryDraft, DEFAULT_WALL_THICKNESS, DoorNode, doorPositionForFacing, emitter, getDoorOpeningSize, getWallThickness, holdHiddenWallPointerEvents, isCurvedWall, isRailingWall, openingHostFacing, railingOpeningFields, resolveOpeningFrameDepth, sceneRegistry, spatialGridManager, useScene, WallNode as WallNodeSchema, } from '@pascal-app/core';
3
3
  import { placedDoorFace } from '@pascal-app/core/building';
4
4
  import { EDITOR_LAYER, getSideFromNormal, isMagneticSnapActive, isValidWallSideFace, triggerSFX, useAlignmentGuides, useEditor, useFacingPose, usePlacementPreview, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
@@ -13,6 +13,7 @@ import { collectWallOpeningAlignmentCandidates, resolveWallSlideAlignment, } fro
13
13
  import { clampToWall, hasWallChildOverlap, wallLocalToWorld } from './door-math.js';
14
14
  import { placedDoorFields, useDoorPlacement } from './placement.js';
15
15
  import DoorPreview from './preview.js';
16
+ import { placementSwing } from './swing.js';
16
17
  const edgeMaterial = new LineBasicNodeMaterial({
17
18
  color: 0xef_44_44,
18
19
  linewidth: 3,
@@ -55,10 +56,6 @@ const DoorTool = () => {
55
56
  rotation: [0, 0, 0],
56
57
  side: fallbackPose?.side ?? 'front',
57
58
  }), [fallbackPose?.side, placedType, placedStyle]);
58
- // The frame depth is a fixed parse default (the `side` flip doesn't change
59
- // it); a ref lets the facing-pose publish inside the setup effect read it
60
- // without re-subscribing every event listener.
61
- const frameDepthRef = useRef(ghostStub.frameDepth);
62
59
  useEffect(() => {
63
60
  useScene.temporal.getState().pause();
64
61
  // The draft is a created carry draft: undo history and every save leave it out
@@ -169,7 +166,7 @@ const DoorTool = () => {
169
166
  // On-host cursor: the green/red wireframe outline tracks a live draft.
170
167
  // Showing it always clears the off-host floating ghost (they never
171
168
  // coexist — a draft means the cursor is on a valid host).
172
- const updateCursor = (worldPosition, cursorRotationY, valid, indicatorYOffset) => {
169
+ const updateCursor = (worldPosition, cursorRotationY, valid, indicatorYOffset, hostThickness) => {
173
170
  setFallbackPose(null);
174
171
  const group = cursorGroupRef.current;
175
172
  if (!group)
@@ -184,7 +181,7 @@ const DoorTool = () => {
184
181
  useFacingPose.getState().set({
185
182
  position: [worldPosition[0], worldPosition[1] + indicatorYOffset, worldPosition[2]],
186
183
  rotationY: cursorRotationY,
187
- depth: frameDepthRef.current,
184
+ depth: resolveOpeningFrameDepth({ frameDepth: draftRef.current?.frameDepth }, hostThickness),
188
185
  });
189
186
  };
190
187
  // Off-host fallback: hide the wireframe outline and float the real door
@@ -231,28 +228,46 @@ const DoorTool = () => {
231
228
  showGhostAt([x, getLevelYOffset() + FALLBACK_HEIGHT / 2, z]);
232
229
  };
233
230
  // Settle a wall target: alignment snap → clamp → overlap check. Pure read.
234
- const resolveWallPlacement = (wall, rawLocalX, width, height, applySnap, ignoreId) => {
231
+ const resolveWallPlacement = (wall, rawLocalX, width, height, applySnap, ignoreId, rotationY = 0) => {
235
232
  // Along-wall alignment guides are DISPLAYED in every snapping mode; the
236
233
  // magnetic pull onto them is applied only when `applySnap` (magnetic
237
234
  // "lines" mode). The grid component lives in `snapToHalf`, which is itself
238
235
  // mode-aware (raw cursor when grid is off).
236
+ const draft = draftRef.current;
237
+ const size = getDoorOpeningSize({ ...draft, width, height });
238
+ const offset = size.leafOffsetX * openingHostFacing({ rotation: [0, rotationY, 0] });
239
+ const facingX = doorPositionForFacing({
240
+ ...draft,
241
+ width,
242
+ height,
243
+ rotation: [0, 0, 0],
244
+ position: [rawLocalX + size.leafOffsetX, height / 2, 0],
245
+ }, [0, rotationY, 0])[0];
239
246
  const localX = resolveWallSlideAlignment({
240
247
  wallNode: wall,
241
- rawLocalX,
242
- width,
248
+ rawLocalX: facingX - offset,
249
+ width: size.width,
243
250
  candidates: alignmentCandidates,
244
251
  applySnap,
245
252
  });
246
- const { clampedX, clampedY } = clampToWall(wall, localX, width, height);
247
- const valid = !hasWallChildOverlap(wall.id, useScene.getState().nodes, clampedX, clampedY, width, height, ignoreId);
248
- return { clampedX, clampedY, valid };
253
+ const cut = clampToWall(wall, localX + offset, width, height, { ...draft, rotation: [0, rotationY, 0] }, useScene.getState().nodes);
254
+ const fittedSize = getDoorOpeningSize({
255
+ ...draft,
256
+ width,
257
+ height,
258
+ transomHeight: cut.transomHeight ?? draft?.transomHeight,
259
+ });
260
+ const clampedX = cut.clampedX;
261
+ const clampedY = cut.clampedY;
262
+ const valid = !hasWallChildOverlap(wall.id, useScene.getState().nodes, cut.clampedX - offset, cut.clampedY + (fittedSize.height - height) / 2, fittedSize.width, fittedSize.height, ignoreId);
263
+ return { clampedX, clampedY, valid, transomHeight: cut.transomHeight };
249
264
  };
250
265
  // Shared create/update path for the wall draft — used by the direct
251
266
  // wall-mesh hover and the floor proximity snap. Reuses the existing draft
252
267
  // (reparenting only on an actual wall change to avoid churning the host's
253
268
  // children array, which flashes 0-vertex wall geometry in WebGPU).
254
269
  const applyWallTarget = (args) => {
255
- const { wall, rawLocalX, side, itemRotation, cursorRotationY, applySnap } = args;
270
+ const { wall, rawLocalX, side, itemRotation, swingSide, cursorRotationY, applySnap } = args;
256
271
  const placed = placedDoorFields();
257
272
  const width = draftRef.current?.width ?? placed.width ?? 0.9;
258
273
  const height = draftRef.current?.height ?? placed.height ?? 2.1;
@@ -269,20 +284,26 @@ const DoorTool = () => {
269
284
  createDraft(node, wall.id);
270
285
  draftRef.current = node;
271
286
  }
272
- const { clampedX, clampedY, valid } = resolveWallPlacement(wall, rawLocalX, width, height, applySnap, draftRef.current.id);
287
+ const { clampedX, clampedY, valid, transomHeight } = resolveWallPlacement(wall, rawLocalX, width, height, applySnap, draftRef.current.id, itemRotation);
288
+ // The leaf swings into the side the cursor is on (R sends it to the other side).
289
+ const swingDirection = placementSwing(draftRef.current, itemRotation, swingSide);
273
290
  if (wall.id === draftRef.current.parentId) {
274
291
  useScene.getState().updateNode(draftRef.current.id, {
275
292
  position: [clampedX, clampedY, 0],
293
+ ...(transomHeight === undefined ? {} : { transomHeight }),
276
294
  rotation: [0, itemRotation, 0],
277
295
  side,
296
+ swingDirection,
278
297
  });
279
298
  markHostDirty(wall.id);
280
299
  }
281
300
  else {
282
301
  useScene.getState().updateNode(draftRef.current.id, {
283
302
  position: [clampedX, clampedY, 0],
303
+ ...(transomHeight === undefined ? {} : { transomHeight }),
284
304
  rotation: [0, itemRotation, 0],
285
305
  side,
306
+ swingDirection,
286
307
  parentId: wall.id,
287
308
  wallId: wall.id,
288
309
  // The draft may arrive from a roof-segment face hover.
@@ -291,7 +312,7 @@ const DoorTool = () => {
291
312
  });
292
313
  }
293
314
  publishDraftPreview(wall);
294
- updateCursor(wallLocalToWorld(wall, clampedX, clampedY, getLevelYOffset(), getSlabElevationForWall(wall)), cursorRotationY, valid, -clampedY);
315
+ updateCursor(wallLocalToWorld(wall, clampedX, clampedY, getLevelYOffset(), getSlabElevationForWall(wall)), cursorRotationY, valid, -height / 2, getWallThickness(wall));
295
316
  if (draftRef.current) {
296
317
  publishOpeningGuidesForWallEvent({
297
318
  wall,
@@ -309,7 +330,7 @@ const DoorTool = () => {
309
330
  };
310
331
  // Promote the draft into a permanent door. Shared by the wall-mesh click
311
332
  // and the floor proximity click.
312
- const commitDoorAtWall = (wall, clampedX, clampedY, side, itemRotation) => {
333
+ const commitDoorAtWall = (wall, clampedX, clampedY, side, itemRotation, swingSide) => {
313
334
  const draft = draftRef.current;
314
335
  if (!draft)
315
336
  return;
@@ -326,15 +347,25 @@ const DoorTool = () => {
326
347
  const w = n.parentId ? state.nodes[n.parentId] : undefined;
327
348
  return w?.parentId === levelId;
328
349
  }).length;
350
+ // On a railing the door becomes a gap in the guard, as tall as the guard.
351
+ const railingGap = isRailingWall(wall) ? railingOpeningFields(wall) : null;
329
352
  const node = DoorNode.parse({
330
- name: `Door ${doorCount + 1}`,
331
- position: [clampedX, clampedY, 0],
353
+ name: `${railingGap ? 'Opening' : 'Door'} ${doorCount + 1}`,
354
+ position: [
355
+ clampedX,
356
+ railingGap ? clampedY + (railingGap.height - draft.height) / 2 : clampedY,
357
+ 0,
358
+ ],
332
359
  rotation: [0, itemRotation, 0],
333
360
  side,
334
361
  wallId: wall.id,
335
362
  parentId: wall.id,
336
363
  width: draft.width,
337
364
  height: draft.height,
365
+ sidelightLeft: draft.sidelightLeft,
366
+ sidelightRight: draft.sidelightRight,
367
+ transomHeight: draft.transomHeight,
368
+ slidingStyle: draft.slidingStyle,
338
369
  doorCategory: draft.doorCategory,
339
370
  doorType: draft.doorType,
340
371
  leafCount: draft.leafCount,
@@ -342,12 +373,14 @@ const DoorTool = () => {
342
373
  slideDirection: draft.slideDirection,
343
374
  trackStyle: draft.trackStyle,
344
375
  garagePanelCount: draft.garagePanelCount,
376
+ casingFaceA: draft.casingFaceA,
377
+ casingFaceB: draft.casingFaceB,
378
+ casingWidth: draft.casingWidth,
345
379
  frameThickness: draft.frameThickness,
346
- frameDepth: draft.frameDepth,
347
380
  threshold: draft.threshold,
348
381
  thresholdHeight: draft.thresholdHeight,
349
382
  hingesSide: draft.hingesSide,
350
- swingDirection: draft.swingDirection,
383
+ swingDirection: placementSwing(draft, itemRotation, swingSide),
351
384
  segments: draft.segments,
352
385
  contentPadding: draft.contentPadding,
353
386
  handle: draft.handle,
@@ -356,6 +389,7 @@ const DoorTool = () => {
356
389
  doorCloser: draft.doorCloser,
357
390
  panicBar: draft.panicBar,
358
391
  panicBarHeight: draft.panicBarHeight,
392
+ ...railingGap,
359
393
  });
360
394
  useScene.getState().createNode(node, wall.id);
361
395
  useViewer.getState().setSelection({ selectedIds: [node.id] });
@@ -383,8 +417,11 @@ const DoorTool = () => {
383
417
  return;
384
418
  }
385
419
  lastWallEvent = event;
386
- // An outside wall's door faces out whichever face is hovered, as add_door places it.
387
- const faceSide = placedDoorFace(event.node, getSideFromNormal(event.normal));
420
+ // An outside wall's door faces out whichever face is hovered, as add_door places it; the
421
+ // leaf still swings into the hovered side (R flips facing and swing together).
422
+ const hovered = getSideFromNormal(event.normal);
423
+ const swingSide = sideFlip ? (hovered === 'front' ? 'back' : 'front') : hovered;
424
+ const faceSide = placedDoorFace(event.node, hovered);
388
425
  const side = sideFlip ? (faceSide === 'front' ? 'back' : 'front') : faceSide;
389
426
  const flipOffset = sideFlip ? Math.PI : 0;
390
427
  const itemRotation = (faceSide === 'back' ? Math.PI : 0) + flipOffset;
@@ -400,6 +437,7 @@ const DoorTool = () => {
400
437
  rawLocalX: event.localPosition[0],
401
438
  side,
402
439
  itemRotation,
440
+ swingSide,
403
441
  cursorRotationY: cursorRotation,
404
442
  applySnap: isMagneticSnapActive(),
405
443
  });
@@ -413,14 +451,16 @@ const DoorTool = () => {
413
451
  event.node.parentId !== getLevelId()) {
414
452
  return;
415
453
  }
416
- const faceSide = placedDoorFace(event.node, getSideFromNormal(event.normal));
454
+ const hovered = getSideFromNormal(event.normal);
455
+ const swingSide = sideFlip ? (hovered === 'front' ? 'back' : 'front') : hovered;
456
+ const faceSide = placedDoorFace(event.node, hovered);
417
457
  const side = sideFlip ? (faceSide === 'front' ? 'back' : 'front') : faceSide;
418
458
  const itemRotation = (faceSide === 'back' ? Math.PI : 0) + (sideFlip ? Math.PI : 0);
419
- const { clampedX, clampedY, valid } = resolveWallPlacement(event.node, event.localPosition[0], draftRef.current.width, draftRef.current.height, isMagneticSnapActive(), draftRef.current.id);
459
+ const { clampedX, clampedY, valid } = resolveWallPlacement(event.node, event.localPosition[0], draftRef.current.width, draftRef.current.height, isMagneticSnapActive(), draftRef.current.id, itemRotation);
420
460
  // Alt force-places over a collision (the draft stays red as a warning).
421
461
  if (!valid && event.nativeEvent?.altKey !== true)
422
462
  return;
423
- commitDoorAtWall(event.node, clampedX, clampedY, side, itemRotation);
463
+ commitDoorAtWall(event.node, clampedX, clampedY, side, itemRotation, swingSide);
424
464
  event.stopPropagation();
425
465
  };
426
466
  // XR runtimes deliver selectend as a grid click, but do not replay the
@@ -476,12 +516,13 @@ const DoorTool = () => {
476
516
  width: draftRef.current?.width ?? 0.9,
477
517
  height: draftRef.current?.height ?? 2.1,
478
518
  ignoreId: draftRef.current?.id,
519
+ opening: draftRef.current ?? undefined,
479
520
  vertical: { kind: 'bottom-locked' },
480
521
  });
481
522
  const updateRoofCursor = (target, roof) => {
482
523
  const pose = getRoofWallOpeningCursorPose(target, roof);
483
524
  if (pose)
484
- updateCursor(pose.position, pose.rotationY, target.valid, -target.position[1]);
525
+ updateCursor(pose.position, pose.rotationY, target.valid, -target.position[1], DEFAULT_WALL_THICKNESS);
485
526
  };
486
527
  const onRoofHover = (event) => {
487
528
  hostKind = 'roof';
@@ -552,6 +593,10 @@ const DoorTool = () => {
552
593
  parentId: segment.id,
553
594
  width: draft.width,
554
595
  height: draft.height,
596
+ sidelightLeft: draft.sidelightLeft,
597
+ sidelightRight: draft.sidelightRight,
598
+ transomHeight: draft.transomHeight,
599
+ slidingStyle: draft.slidingStyle,
555
600
  doorCategory: draft.doorCategory,
556
601
  doorType: draft.doorType,
557
602
  leafCount: draft.leafCount,
@@ -559,8 +604,10 @@ const DoorTool = () => {
559
604
  slideDirection: draft.slideDirection,
560
605
  trackStyle: draft.trackStyle,
561
606
  garagePanelCount: draft.garagePanelCount,
607
+ casingFaceA: draft.casingFaceA,
608
+ casingFaceB: draft.casingFaceB,
609
+ casingWidth: draft.casingWidth,
562
610
  frameThickness: draft.frameThickness,
563
- frameDepth: draft.frameDepth,
564
611
  threshold: draft.threshold,
565
612
  thresholdHeight: draft.thresholdHeight,
566
613
  hingesSide: draft.hingesSide,
@@ -702,7 +749,7 @@ const DoorTool = () => {
702
749
  // unmount rather than reallocating (and orphaning) an EdgesGeometry on every
703
750
  // re-render during placement.
704
751
  const edgesGeo = useMemo(() => {
705
- const boxGeo = new BoxGeometry(FALLBACK_WIDTH, FALLBACK_HEIGHT, 0.07);
752
+ const boxGeo = new BoxGeometry(FALLBACK_WIDTH, FALLBACK_HEIGHT, resolveOpeningFrameDepth({}, DEFAULT_WALL_THICKNESS));
706
753
  const geo = new EdgesGeometry(boxGeo);
707
754
  boxGeo.dispose();
708
755
  return geo;
@@ -1 +1 @@
1
- {"version":3,"file":"panel-actions-section.d.ts","sourceRoot":"","sources":["../../src/dormer/panel-actions-section.tsx"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,WAAW,EACX,QAAQ,GACT,EAAE;IACD,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB,+BAmBA"}
1
+ {"version":3,"file":"panel-actions-section.d.ts","sourceRoot":"","sources":["../../src/dormer/panel-actions-section.tsx"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,WAAW,EACX,QAAQ,GACT,EAAE;IACD,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB,+BA0BA"}
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { usePascalI18n } from '@pascal-app/core';
3
4
  import { ActionButton, ActionGroup, PanelSection } from '@pascal-app/editor';
4
5
  import { Copy, Move, Trash2 } from 'lucide-react';
5
6
  /**
@@ -7,5 +8,6 @@ import { Copy, Move, Trash2 } from 'lucide-react';
7
8
  * inspector. Pure presentation — owners pass the three handlers.
8
9
  */
9
10
  export function DormerActionsSection({ onMove, onDuplicate, onDelete, }) {
10
- return (_jsx(PanelSection, { title: "Actions", children: _jsxs(ActionGroup, { children: [_jsx(ActionButton, { icon: _jsx(Move, { className: "h-3.5 w-3.5" }), label: "Move", onClick: onMove }), _jsx(ActionButton, { icon: _jsx(Copy, { className: "h-3.5 w-3.5" }), label: "Duplicate", onClick: onDuplicate }), _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: onDelete })] }) }));
11
+ const i18n = usePascalI18n();
12
+ return (_jsx(PanelSection, { title: i18n._({ id: 'node.dormer.panelActionsSection.actions', message: 'Actions' }), children: _jsxs(ActionGroup, { children: [_jsx(ActionButton, { icon: _jsx(Move, { className: "h-3.5 w-3.5" }), label: i18n._({ id: 'node.dormer.panelActionsSection.move', message: 'Move' }), onClick: onMove }), _jsx(ActionButton, { icon: _jsx(Copy, { className: "h-3.5 w-3.5" }), label: i18n._({ id: 'node.dormer.panelActionsSection.duplicate', message: 'Duplicate' }), onClick: onDuplicate }), _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.dormer.panelActionsSection.delete', message: 'Delete' }), onClick: onDelete })] }) }));
11
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"panel-position-section.d.ts","sourceRoot":"","sources":["../../src/dormer/panel-position-section.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,eAAe,EAGrB,MAAM,kBAAkB,CAAA;AAKzB;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,UAAU,EACV,WAAW,EACX,UAAU,GACX,EAAE;IACD,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,eAAe,GAAG,SAAS,CAAA;IACpC,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAA;IACnD,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAA;CACnD,+BA+LA"}
1
+ {"version":3,"file":"panel-position-section.d.ts","sourceRoot":"","sources":["../../src/dormer/panel-position-section.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,eAAe,EAIrB,MAAM,kBAAkB,CAAA;AAKzB;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,UAAU,EACV,WAAW,EACX,UAAU,GACX,EAAE;IACD,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,eAAe,GAAG,SAAS,CAAA;IACpC,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAA;IACnD,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAA;CACnD,+BAkMA"}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { sceneRegistry, useScene, } from '@pascal-app/core';
3
+ import { sceneRegistry, usePascalI18n, useScene, } from '@pascal-app/core';
4
4
  import { PanelSection, SliderControl } from '@pascal-app/editor';
5
5
  import { useMemo } from 'react';
6
6
  import { Vector3 } from 'three';
@@ -12,6 +12,7 @@ import { Vector3 } from 'three';
12
12
  * local commits, including the cross-segment reparent case.
13
13
  */
14
14
  export function DormerPositionSection({ node, segment, roof, selectedId, previewProp, commitProp, }) {
15
+ const i18n = usePascalI18n();
15
16
  const px = node.position[0];
16
17
  const py = node.position[1];
17
18
  const pz = node.position[2];
@@ -136,7 +137,7 @@ export function DormerPositionSection({ node, segment, roof, selectedId, preview
136
137
  }
137
138
  commitProp({ rotation: newWorldRot - ancestorWorldY });
138
139
  };
139
- return (_jsxs(PanelSection, { title: "Position", children: [_jsx(SliderControl, { label: "X", max: Math.round(worldMaxX * 10) / 10, min: Math.round(worldMinX * 10) / 10, onChange: (newWorldX) => {
140
+ return (_jsxs(PanelSection, { title: i18n._({ id: 'node.dormer.panelPositionSection.position', message: 'Position' }), children: [_jsx(SliderControl, { label: "X", max: Math.round(worldMaxX * 10) / 10, min: Math.round(worldMinX * 10) / 10, onChange: (newWorldX) => {
140
141
  if (!segment)
141
142
  return;
142
143
  const local = worldToSegLocal(newWorldX, worldZ_now, segment);
@@ -146,7 +147,7 @@ export function DormerPositionSection({ node, segment, roof, selectedId, preview
146
147
  return;
147
148
  const local = worldToSegLocal(worldX_now, newWorldZ, segment);
148
149
  previewProp({ position: [local.localX, py ?? 0, local.localZ] });
149
- }, onCommit: (newWorldZ) => commitWorldPosition(worldX_now, newWorldZ), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: worldZ_now }), _jsx(SliderControl, { label: "Rotation", max: 180, min: -180, onChange: (degrees) => {
150
+ }, onCommit: (newWorldZ) => commitWorldPosition(worldX_now, newWorldZ), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: worldZ_now }), _jsx(SliderControl, { label: i18n._({ id: 'node.dormer.panelPositionSection.rotation', message: 'Rotation' }), max: 180, min: -180, onChange: (degrees) => {
150
151
  const newWorldRot = (degrees * Math.PI) / 180;
151
152
  let ancestorWorldY = 0;
152
153
  if (segment) {
@@ -1 +1 @@
1
- {"version":3,"file":"panel-windows-section.d.ts","sourceRoot":"","sources":["../../src/dormer/panel-windows-section.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAIlD,wBAAgB,oBAAoB,CAAC,EACnC,OAAO,EACP,MAAM,EACN,KAAK,EACL,MAAM,EACN,MAAM,GACP,EAAE;IACD,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,MAAM,EAAE,OAAO,CAAA;IACf,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,MAAM,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAA;IACpC,MAAM,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAA;CACrC,+BAiEA"}
1
+ {"version":3,"file":"panel-windows-section.d.ts","sourceRoot":"","sources":["../../src/dormer/panel-windows-section.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAKlD,wBAAgB,oBAAoB,CAAC,EACnC,OAAO,EACP,MAAM,EACN,KAAK,EACL,MAAM,EACN,MAAM,GACP,EAAE;IACD,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,MAAM,EAAE,OAAO,CAAA;IACf,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,MAAM,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAA;IACpC,MAAM,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAA;CACrC,+BA0GA"}
@@ -1,7 +1,44 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { formatFixed, usePascalI18n } from '@pascal-app/core';
3
4
  import { ActionButton, PanelSection } from '@pascal-app/editor';
4
5
  import { Move, Pencil, Plus } from 'lucide-react';
5
6
  export function DormerWindowsSection({ windows, canAdd, onAdd, onEdit, onMove, }) {
6
- return (_jsxs(PanelSection, { title: `Windows (${windows.length})`, children: [windows.length > 0 ? (_jsx("div", { className: "flex flex-col gap-1", children: windows.map((window, index) => (_jsxs("div", { className: "flex items-center gap-1 rounded-lg border border-border/50 bg-black/4 dark:bg-[#2C2C2E] p-1", children: [_jsxs("button", { className: "min-w-0 flex-1 rounded-md px-2 py-1.5 text-left transition-colors hover:bg-black/8 dark:hover:bg-[#3e3e3e]", onClick: () => onEdit(window), type: "button", children: [_jsx("span", { className: "block truncate font-medium text-foreground text-xs", children: window.name || `Window ${index + 1}` }), _jsxs("span", { className: "block truncate text-[10px] text-muted-foreground capitalize", children: [window.dormerFace ?? 'front', " \u00B7 ", window.width.toFixed(2), " \u00D7", ' ', window.height.toFixed(2), " m"] })] }), _jsx("button", { "aria-label": `Edit ${window.name || `Window ${index + 1}`}`, className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground", onClick: () => onEdit(window), title: "Edit window", type: "button", children: _jsx(Pencil, { className: "h-3.5 w-3.5" }) }), _jsxs("button", { "aria-label": `Move ${window.name || `Window ${index + 1}`}`, className: "flex h-8 shrink-0 items-center justify-center gap-1 rounded-md px-2 text-muted-foreground text-xs transition-colors hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground", onClick: () => onMove(window), title: "Move window", type: "button", children: [_jsx(Move, { className: "h-3.5 w-3.5" }), "Move"] })] }, window.id))) })) : (_jsx("div", { className: "px-2 py-3 text-center text-muted-foreground text-xs", children: "No windows" })), _jsxs("div", { className: "px-1 pt-2 pb-1", children: [_jsx(ActionButton, { className: "w-full", disabled: !canAdd, icon: _jsx(Plus, { className: "h-3.5 w-3.5" }), label: "Add Window", onClick: onAdd }), !canAdd && (_jsx("p", { className: "px-1 pt-2 text-center text-[10px] text-muted-foreground", children: "Increase the dormer width to add another window." }))] })] }));
7
+ const i18n = usePascalI18n();
8
+ const windowName = (window, index) => window.name ||
9
+ i18n._({
10
+ id: 'node.dormer.panelWindowsSection.windowNumber',
11
+ message: 'Window {number}',
12
+ values: { number: index + 1 },
13
+ });
14
+ return (_jsxs(PanelSection, { title: i18n._({
15
+ id: 'node.dormer.panelWindowsSection.windowsLength',
16
+ message: 'Windows ({length})',
17
+ values: { length: windows.length },
18
+ }), children: [windows.length > 0 ? (_jsx("div", { className: "flex flex-col gap-1", children: windows.map((window, index) => (_jsxs("div", { className: "flex items-center gap-1 rounded-lg border border-border/50 bg-black/4 dark:bg-[#2C2C2E] p-1", children: [_jsxs("button", { className: "min-w-0 flex-1 rounded-md px-2 py-1.5 text-left transition-colors hover:bg-black/8 dark:hover:bg-[#3e3e3e]", onClick: () => onEdit(window), type: "button", children: [_jsx("span", { className: "block truncate font-medium text-foreground text-xs", children: windowName(window, index) }), _jsx("span", { className: "block truncate text-[10px] text-muted-foreground", children: i18n._({
19
+ id: 'node.dormer.panelWindowsSection.windowSummary',
20
+ message: '{face, select, back {Back} left {Left} right {Right} other {Front}} · {width} × {height} m',
21
+ values: {
22
+ face: window.dormerFace ?? 'front',
23
+ width: formatFixed(window.width, 2, i18n.getLocale()),
24
+ height: formatFixed(window.height, 2, i18n.getLocale()),
25
+ },
26
+ }) })] }), _jsx("button", { "aria-label": i18n._({
27
+ id: 'node.dormer.panelWindowsSection.editNamed',
28
+ message: 'Edit {name}',
29
+ values: { name: windowName(window, index) },
30
+ }), className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground", onClick: () => onEdit(window), title: i18n._({
31
+ id: 'node.dormer.panelWindowsSection.editWindow',
32
+ message: 'Edit window',
33
+ }), type: "button", children: _jsx(Pencil, { className: "h-3.5 w-3.5" }) }), _jsxs("button", { "aria-label": i18n._({
34
+ id: 'node.dormer.panelWindowsSection.moveNamed',
35
+ message: 'Move {name}',
36
+ values: { name: windowName(window, index) },
37
+ }), className: "flex h-8 shrink-0 items-center justify-center gap-1 rounded-md px-2 text-muted-foreground text-xs transition-colors hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground", onClick: () => onMove(window), title: i18n._({
38
+ id: 'node.dormer.panelWindowsSection.moveWindow',
39
+ message: 'Move window',
40
+ }), type: "button", children: [_jsx(Move, { className: "h-3.5 w-3.5" }), i18n._({ id: 'node.dormer.panelWindowsSection.move', message: 'Move' })] })] }, window.id))) })) : (_jsx("div", { className: "px-2 py-3 text-center text-muted-foreground text-xs", children: i18n._({ id: 'node.dormer.panelWindowsSection.noWindows', message: 'No windows' }) })), _jsxs("div", { className: "px-1 pt-2 pb-1", children: [_jsx(ActionButton, { className: "w-full", disabled: !canAdd, icon: _jsx(Plus, { className: "h-3.5 w-3.5" }), label: i18n._({ id: 'node.dormer.panelWindowsSection.addWindow', message: 'Add Window' }), onClick: onAdd }), !canAdd && (_jsx("p", { className: "px-1 pt-2 text-center text-[10px] text-muted-foreground", children: i18n._({
41
+ id: 'node.dormer.panelWindowsSection.increaseTheDormerWidthToAdd',
42
+ message: 'Increase the dormer width to add another window.',
43
+ }) }))] })] }));
7
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/dormer/panel.tsx"],"names":[],"mappings":"AAuDA,MAAM,CAAC,OAAO,UAAU,WAAW,uCA0VlC"}
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/dormer/panel.tsx"],"names":[],"mappings":"AA4DA,MAAM,CAAC,OAAO,UAAU,WAAW,uCAqWlC"}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { createDormerDefaultWindow, generateId, useLiveNodeOverrides, useScene, WindowNode, } from '@pascal-app/core';
3
+ import { createDormerDefaultWindow, generateId, useLiveNodeOverrides, usePascalI18n, useScene, WindowNode, } from '@pascal-app/core';
4
4
  import { cn, duplicateNodeAndPickUp, PanelSection, PanelWrapper, SliderControl, triggerSFX, useEditor, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { useCallback, useState } from 'react';
@@ -10,23 +10,27 @@ import { DormerPositionSection } from './panel-position-section.js';
10
10
  import { DormerWindowsSection } from './panel-windows-section.js';
11
11
  import { planDormerWindowRow } from './window-layout.js';
12
12
  const ROOF_TYPE_OPTIONS = [
13
- { label: 'Gable', value: 'gable' },
14
- { label: 'Hip', value: 'hip' },
15
- { label: 'Shed', value: 'shed' },
16
- { label: 'Gambrel', value: 'gambrel' },
17
- { label: 'Dutch', value: 'dutch' },
18
- { label: 'Mansard', value: 'mansard' },
19
- { label: 'Flat', value: 'flat' },
13
+ { label: /* i18n */ { id: 'node.dormer.panel.gable', message: 'Gable' }, value: 'gable' },
14
+ { label: /* i18n */ { id: 'node.dormer.panel.hip', message: 'Hip' }, value: 'hip' },
15
+ { label: /* i18n */ { id: 'node.dormer.panel.shed', message: 'Shed' }, value: 'shed' },
16
+ { label: /* i18n */ { id: 'node.dormer.panel.gambrel', message: 'Gambrel' }, value: 'gambrel' },
17
+ { label: /* i18n */ { id: 'node.dormer.panel.dutch', message: 'Dutch' }, value: 'dutch' },
18
+ { label: /* i18n */ { id: 'node.dormer.panel.mansard', message: 'Mansard' }, value: 'mansard' },
19
+ { label: /* i18n */ { id: 'node.dormer.panel.flat', message: 'Flat' }, value: 'flat' },
20
20
  ];
21
21
  const SHED_HIGH_SIDE_OPTIONS = [
22
- { label: 'Rise Back', value: 'back' },
23
- { label: 'Rise Front', value: 'front' },
22
+ { label: /* i18n */ { id: 'node.dormer.panel.riseBack', message: 'Rise Back' }, value: 'back' },
23
+ {
24
+ label: /* i18n */ { id: 'node.dormer.panel.riseFront', message: 'Rise Front' },
25
+ value: 'front',
26
+ },
24
27
  ];
25
28
  const SECTION_OPTIONS = [
26
- { label: 'Dormer', value: 'dormer' },
27
- { label: 'Windows', value: 'window' },
29
+ { label: /* i18n */ { id: 'node.dormer.panel.dormer', message: 'Dormer' }, value: 'dormer' },
30
+ { label: /* i18n */ { id: 'node.dormer.panel.windows', message: 'Windows' }, value: 'window' },
28
31
  ];
29
32
  export default function DormerPanel() {
33
+ const i18n = usePascalI18n();
30
34
  const [section, setSection] = useState('dormer');
31
35
  const selectedId = useViewer((s) => s.selection.selectedIds[0]);
32
36
  const setSelection = useViewer((s) => s.setSelection);
@@ -187,20 +191,22 @@ export default function DormerPanel() {
187
191
  width: templateWindow?.width ?? defaultWindow.width,
188
192
  },
189
193
  ]) !== null;
190
- return (_jsxs(PanelWrapper, { icon: "/icons/roof.webp", onBack: node.roofSegmentId ? handleBack : undefined, onClose: handleClose, title: node.name || 'Dormer', width: 300, children: [_jsx(DormerPositionSection, { commitProp: commitProp, node: node, previewProp: previewProp, roof: roof, segment: segment, selectedId: selectedId }), _jsx(PanelSection, { title: "Section", children: _jsx("div", { className: "grid grid-cols-3 gap-1.5 px-1 pt-1", children: SECTION_OPTIONS.map((option) => {
194
+ return (_jsxs(PanelWrapper, { icon: "/icons/roof.webp", onBack: node.roofSegmentId ? handleBack : undefined, onClose: handleClose, title: node.name || i18n._({ id: 'node.dormer.panel.dormer', message: 'Dormer' }), width: 300, children: [_jsx(DormerPositionSection, { commitProp: commitProp, node: node, previewProp: previewProp, roof: roof, segment: segment, selectedId: selectedId }), _jsx(PanelSection, { title: i18n._({ id: 'node.dormer.panel.section', message: 'Section' }), children: _jsx("div", { className: "grid grid-cols-3 gap-1.5 px-1 pt-1", children: SECTION_OPTIONS.map((option) => {
191
195
  const isSelected = section === option.value;
192
196
  return (_jsx("button", { className: cn('flex min-h-10 items-center justify-center rounded-lg border px-2 py-2 text-center text-xs transition-colors', isSelected
193
197
  ? 'border-orange-400/60 bg-orange-400/10 text-foreground'
194
- : 'border-border/50 bg-black/4 dark:bg-[#2C2C2E] text-muted-foreground hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground'), onClick: () => setSection(option.value), type: "button", children: _jsx("span", { className: "truncate font-medium", children: option.label }) }, option.value));
195
- }) }) }), section === 'dormer' && (_jsxs(_Fragment, { children: [_jsxs(PanelSection, { title: "Dimensions", children: [_jsx(SliderControl, { label: "Width", max: 1000, min: 0.5, onChange: (v) => previewProp({ width: v }), onCommit: (v) => commitProp({ width: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.width }), _jsx(SliderControl, { label: "Depth", max: 1000, min: 0.5, onChange: (v) => previewProp({ depth: v }), onCommit: (v) => commitProp({ depth: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.depth }), _jsx(SliderControl, { label: "Wall Height", max: 1000, min: 0, onChange: (v) => previewProp({ height: v }), onCommit: (v) => commitProp({ height: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.height }), _jsx(SliderControl, { label: node.roofType === 'shed' ? 'Pitch Rise' : 'Roof Height', max: 3, min: 0, onChange: (v) => previewProp({ roofHeight: v }), onCommit: (v) => commitProp({ roofHeight: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.roofHeight })] }), _jsx(PanelSection, { title: "Roof Type", children: _jsx("div", { className: "grid grid-cols-3 gap-1.5 px-1 pt-1", children: ROOF_TYPE_OPTIONS.map((option) => {
198
+ : 'border-border/50 bg-black/4 dark:bg-[#2C2C2E] text-muted-foreground hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground'), onClick: () => setSection(option.value), type: "button", children: _jsx("span", { className: "min-w-0 break-words font-medium", children: i18n._(option.label) }) }, option.value));
199
+ }) }) }), section === 'dormer' && (_jsxs(_Fragment, { children: [_jsxs(PanelSection, { title: i18n._({ id: 'node.dormer.panel.dimensions', message: 'Dimensions' }), children: [_jsx(SliderControl, { label: i18n._({ id: 'node.dormer.panel.width', message: 'Width' }), max: 1000, min: 0.5, onChange: (v) => previewProp({ width: v }), onCommit: (v) => commitProp({ width: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.width }), _jsx(SliderControl, { label: i18n._({ id: 'node.dormer.panel.depth', message: 'Depth' }), max: 1000, min: 0.5, onChange: (v) => previewProp({ depth: v }), onCommit: (v) => commitProp({ depth: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.depth }), _jsx(SliderControl, { label: i18n._({ id: 'node.dormer.panel.wallHeight', message: 'Wall Height' }), max: 1000, min: 0, onChange: (v) => previewProp({ height: v }), onCommit: (v) => commitProp({ height: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.height }), _jsx(SliderControl, { label: node.roofType === 'shed'
200
+ ? i18n._({ id: 'node.dormer.panel.pitchRise', message: 'Pitch Rise' })
201
+ : i18n._({ id: 'node.dormer.panel.roofHeight', message: 'Roof Height' }), max: 3, min: 0, onChange: (v) => previewProp({ roofHeight: v }), onCommit: (v) => commitProp({ roofHeight: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: node.roofHeight })] }), _jsx(PanelSection, { title: i18n._({ id: 'node.dormer.panel.roofType', message: 'Roof Type' }), children: _jsx("div", { className: "grid grid-cols-3 gap-1.5 px-1 pt-1", children: ROOF_TYPE_OPTIONS.map((option) => {
196
202
  const isSelected = node.roofType === option.value;
197
203
  return (_jsx("button", { className: cn('flex min-h-10 items-center justify-center rounded-lg border px-2 py-2 text-xs transition-colors', isSelected
198
204
  ? 'border-orange-400/60 bg-orange-400/10 text-foreground'
199
- : 'border-border/50 bg-black/4 dark:bg-[#2C2C2E] text-muted-foreground hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground'), onClick: () => handleUpdate({ roofType: option.value }), type: "button", children: _jsx("span", { className: "truncate font-medium", children: option.label }) }, option.value));
200
- }) }) }), node.roofType === 'shed' && (_jsx(PanelSection, { title: "Pitch Direction", children: _jsx("div", { className: "grid grid-cols-2 gap-1.5 px-1 pt-1", children: SHED_HIGH_SIDE_OPTIONS.map((option) => {
205
+ : 'border-border/50 bg-black/4 dark:bg-[#2C2C2E] text-muted-foreground hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground'), onClick: () => handleUpdate({ roofType: option.value }), type: "button", children: _jsx("span", { className: "min-w-0 break-words font-medium", children: i18n._(option.label) }) }, option.value));
206
+ }) }) }), node.roofType === 'shed' && (_jsx(PanelSection, { title: i18n._({ id: 'node.dormer.panel.pitchDirection', message: 'Pitch Direction' }), children: _jsx("div", { className: "grid grid-cols-2 gap-1.5 px-1 pt-1", children: SHED_HIGH_SIDE_OPTIONS.map((option) => {
201
207
  const isSelected = node.shedHighSide === option.value;
202
208
  return (_jsx("button", { className: cn('flex min-h-10 items-center justify-center rounded-lg border px-2 py-2 text-xs transition-colors', isSelected
203
209
  ? 'border-orange-400/60 bg-orange-400/10 text-foreground'
204
- : 'border-border/50 bg-black/4 dark:bg-[#2C2C2E] text-muted-foreground hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground'), onClick: () => handleUpdate({ shedHighSide: option.value }), type: "button", children: _jsx("span", { className: "truncate font-medium", children: option.label }) }, option.value));
210
+ : 'border-border/50 bg-black/4 dark:bg-[#2C2C2E] text-muted-foreground hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground'), onClick: () => handleUpdate({ shedHighSide: option.value }), type: "button", children: _jsx("span", { className: "min-w-0 break-words font-medium", children: i18n._(option.label) }) }, option.value));
205
211
  }) }) }))] })), section === 'window' && (_jsx(DormerWindowsSection, { canAdd: canAddWindow, onAdd: handleAddWindow, onEdit: handleEditWindow, onMove: handleMoveWindow, windows: hostedWindows })), _jsx(DormerActionsSection, { onDelete: handleDelete, onDuplicate: handleDuplicate, onMove: handleMove })] }));
206
212
  }
@@ -1 +1 @@
1
- {"version":3,"file":"inspector-editors.d.ts","sourceRoot":"","sources":["../../src/downspout/inspector-editors.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,aAAa,EAKnB,MAAM,kBAAkB,CAAA;AAGzB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,sCAoExE"}
1
+ {"version":3,"file":"inspector-editors.d.ts","sourceRoot":"","sources":["../../src/downspout/inspector-editors.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,aAAa,EAMnB,MAAM,kBAAkB,CAAA;AAGzB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,sCAqExE"}