@pascal-app/nodes 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (566) hide show
  1. package/README.md +1 -0
  2. package/dist/beam/actions/move-endpoint.d.ts +24 -0
  3. package/dist/beam/actions/move-endpoint.d.ts.map +1 -0
  4. package/dist/beam/actions/move-endpoint.js +54 -0
  5. package/dist/beam/definition.d.ts +14 -0
  6. package/dist/beam/definition.d.ts.map +1 -0
  7. package/dist/beam/definition.js +173 -0
  8. package/dist/beam/draft-settings.d.ts +17 -0
  9. package/dist/beam/draft-settings.d.ts.map +1 -0
  10. package/dist/beam/draft-settings.js +81 -0
  11. package/dist/beam/drafting.d.ts +35 -0
  12. package/dist/beam/drafting.d.ts.map +1 -0
  13. package/dist/beam/drafting.js +103 -0
  14. package/dist/beam/floorplan-affordances.d.ts +8 -0
  15. package/dist/beam/floorplan-affordances.d.ts.map +1 -0
  16. package/dist/beam/floorplan-affordances.js +40 -0
  17. package/dist/beam/floorplan-move.d.ts +11 -0
  18. package/dist/beam/floorplan-move.d.ts.map +1 -0
  19. package/dist/beam/floorplan-move.js +54 -0
  20. package/dist/beam/floorplan.d.ts +11 -0
  21. package/dist/beam/floorplan.d.ts.map +1 -0
  22. package/dist/beam/floorplan.js +91 -0
  23. package/dist/beam/geometry.d.ts +19 -0
  24. package/dist/beam/geometry.d.ts.map +1 -0
  25. package/dist/beam/geometry.js +63 -0
  26. package/dist/beam/index.d.ts +3 -0
  27. package/dist/beam/index.d.ts.map +1 -0
  28. package/dist/beam/index.js +2 -0
  29. package/dist/beam/move-endpoint-tool.d.ts +21 -0
  30. package/dist/beam/move-endpoint-tool.d.ts.map +1 -0
  31. package/dist/beam/move-endpoint-tool.js +49 -0
  32. package/dist/beam/move-tool.d.ts +12 -0
  33. package/dist/beam/move-tool.d.ts.map +1 -0
  34. package/dist/beam/move-tool.js +114 -0
  35. package/dist/beam/panel-model.d.ts +28 -0
  36. package/dist/beam/panel-model.d.ts.map +1 -0
  37. package/dist/beam/panel-model.js +123 -0
  38. package/dist/beam/panel.d.ts +13 -0
  39. package/dist/beam/panel.d.ts.map +1 -0
  40. package/dist/beam/panel.js +107 -0
  41. package/dist/beam/parametrics.d.ts +3 -0
  42. package/dist/beam/parametrics.d.ts.map +1 -0
  43. package/dist/beam/parametrics.js +4 -0
  44. package/dist/beam/renderer.d.ts +13 -0
  45. package/dist/beam/renderer.d.ts.map +1 -0
  46. package/dist/beam/renderer.js +36 -0
  47. package/dist/beam/schema.d.ts +2 -0
  48. package/dist/beam/schema.d.ts.map +1 -0
  49. package/dist/beam/schema.js +1 -0
  50. package/dist/beam/tool.d.ts +13 -0
  51. package/dist/beam/tool.d.ts.map +1 -0
  52. package/dist/beam/tool.js +152 -0
  53. package/dist/box-vent/panel.d.ts.map +1 -1
  54. package/dist/box-vent/panel.js +8 -7
  55. package/dist/cabinet/batchable.d.ts +10 -0
  56. package/dist/cabinet/batchable.d.ts.map +1 -0
  57. package/dist/cabinet/batchable.js +12 -0
  58. package/dist/cabinet/compartment-card.d.ts.map +1 -1
  59. package/dist/cabinet/compartment-card.js +142 -46
  60. package/dist/cabinet/countertop-layout.d.ts +5 -0
  61. package/dist/cabinet/countertop-layout.d.ts.map +1 -1
  62. package/dist/cabinet/definition.d.ts.map +1 -1
  63. package/dist/cabinet/definition.js +3 -0
  64. package/dist/cabinet/dimension-input.d.ts +6 -0
  65. package/dist/cabinet/dimension-input.d.ts.map +1 -0
  66. package/dist/cabinet/dimension-input.js +8 -0
  67. package/dist/cabinet/essential-controls.d.ts.map +1 -1
  68. package/dist/cabinet/essential-controls.js +82 -17
  69. package/dist/cabinet/index.d.ts +1 -1
  70. package/dist/cabinet/index.d.ts.map +1 -1
  71. package/dist/cabinet/index.js +1 -1
  72. package/dist/cabinet/kitchen-catalog.d.ts +17 -4
  73. package/dist/cabinet/kitchen-catalog.d.ts.map +1 -1
  74. package/dist/cabinet/kitchen-catalog.js +45 -7
  75. package/dist/cabinet/kitchen-collection.d.ts.map +1 -1
  76. package/dist/cabinet/kitchen-collection.js +21 -5
  77. package/dist/cabinet/kitchen-module-actions.d.ts.map +1 -1
  78. package/dist/cabinet/kitchen-module-actions.js +107 -14
  79. package/dist/cabinet/neighbor-placement.d.ts +10 -0
  80. package/dist/cabinet/neighbor-placement.d.ts.map +1 -1
  81. package/dist/cabinet/panel.d.ts.map +1 -1
  82. package/dist/cabinet/panel.js +127 -50
  83. package/dist/cabinet/run-finishing.d.ts +5 -0
  84. package/dist/cabinet/run-finishing.d.ts.map +1 -1
  85. package/dist/cabinet/run-ops.d.ts +5 -0
  86. package/dist/cabinet/run-ops.d.ts.map +1 -1
  87. package/dist/cabinet/run-panel.d.ts.map +1 -1
  88. package/dist/cabinet/run-panel.js +203 -52
  89. package/dist/cabinet/tool.d.ts.map +1 -1
  90. package/dist/cabinet/tool.js +8 -5
  91. package/dist/ceiling/build-up-section.d.ts +7 -0
  92. package/dist/ceiling/build-up-section.d.ts.map +1 -0
  93. package/dist/ceiling/build-up-section.js +57 -0
  94. package/dist/ceiling/definition.d.ts.map +1 -1
  95. package/dist/ceiling/definition.js +3 -1
  96. package/dist/ceiling/floorplan-affordances.d.ts +112 -0
  97. package/dist/ceiling/floorplan-affordances.d.ts.map +1 -1
  98. package/dist/ceiling/materials.d.ts +5 -0
  99. package/dist/ceiling/materials.d.ts.map +1 -1
  100. package/dist/ceiling/materials.js +17 -0
  101. package/dist/ceiling/panel-model.d.ts +13 -0
  102. package/dist/ceiling/panel-model.d.ts.map +1 -0
  103. package/dist/ceiling/panel-model.js +49 -0
  104. package/dist/ceiling/panel.d.ts.map +1 -1
  105. package/dist/ceiling/panel.js +82 -18
  106. package/dist/ceiling/renderer.d.ts.map +1 -1
  107. package/dist/ceiling/renderer.js +10 -4
  108. package/dist/ceiling/tool.d.ts.map +1 -1
  109. package/dist/ceiling/tool.js +24 -4
  110. package/dist/chimney/panel.d.ts.map +1 -1
  111. package/dist/chimney/panel.js +113 -41
  112. package/dist/column/definition.d.ts.map +1 -1
  113. package/dist/column/definition.js +3 -0
  114. package/dist/column/floorplan.d.ts.map +1 -1
  115. package/dist/column/floorplan.js +17 -0
  116. package/dist/column/hosted-resize.d.ts +28 -1
  117. package/dist/column/hosted-resize.d.ts.map +1 -1
  118. package/dist/column/panel.d.ts.map +1 -1
  119. package/dist/column/panel.js +125 -37
  120. package/dist/column/post-options.d.ts +10 -0
  121. package/dist/column/post-options.d.ts.map +1 -0
  122. package/dist/column/post-options.js +71 -0
  123. package/dist/column/post-placement.d.ts +78 -0
  124. package/dist/column/post-placement.d.ts.map +1 -0
  125. package/dist/column/post-placement.js +157 -0
  126. package/dist/column/post-section.d.ts +17 -0
  127. package/dist/column/post-section.d.ts.map +1 -0
  128. package/dist/column/post-section.js +95 -0
  129. package/dist/column/post-tool.d.ts +11 -0
  130. package/dist/column/post-tool.d.ts.map +1 -0
  131. package/dist/column/post-tool.js +94 -0
  132. package/dist/column/tool.d.ts +3 -10
  133. package/dist/column/tool.d.ts.map +1 -1
  134. package/dist/column/tool.js +13 -1
  135. package/dist/cupola/panel.d.ts.map +1 -1
  136. package/dist/cupola/panel.js +14 -7
  137. package/dist/door/actions.d.ts +7 -0
  138. package/dist/door/actions.d.ts.map +1 -0
  139. package/dist/door/actions.js +32 -0
  140. package/dist/door/contextual-dimensions.d.ts.map +1 -1
  141. package/dist/door/contextual-dimensions.js +11 -1
  142. package/dist/door/definition.d.ts.map +1 -1
  143. package/dist/door/definition.js +34 -7
  144. package/dist/door/floorplan-affordances.d.ts.map +1 -1
  145. package/dist/door/floorplan-affordances.js +5 -2
  146. package/dist/door/floorplan-move.d.ts.map +1 -1
  147. package/dist/door/floorplan-move.js +28 -6
  148. package/dist/door/floorplan.d.ts +2 -0
  149. package/dist/door/floorplan.d.ts.map +1 -1
  150. package/dist/door/floorplan.js +89 -16
  151. package/dist/door/move-tool.d.ts.map +1 -1
  152. package/dist/door/move-tool.js +60 -16
  153. package/dist/door/paint.d.ts +2 -7
  154. package/dist/door/paint.d.ts.map +1 -1
  155. package/dist/door/paint.js +26 -2
  156. package/dist/door/panel.d.ts.map +1 -1
  157. package/dist/door/panel.js +242 -90
  158. package/dist/door/parametrics.js +1 -1
  159. package/dist/door/placement.d.ts.map +1 -1
  160. package/dist/door/placement.js +9 -2
  161. package/dist/door/swing.d.ts +22 -0
  162. package/dist/door/swing.d.ts.map +1 -0
  163. package/dist/door/swing.js +36 -0
  164. package/dist/door/tool.d.ts.map +1 -1
  165. package/dist/door/tool.js +76 -29
  166. package/dist/dormer/panel-actions-section.d.ts.map +1 -1
  167. package/dist/dormer/panel-actions-section.js +3 -1
  168. package/dist/dormer/panel-position-section.d.ts.map +1 -1
  169. package/dist/dormer/panel-position-section.js +4 -3
  170. package/dist/dormer/panel-windows-section.d.ts.map +1 -1
  171. package/dist/dormer/panel-windows-section.js +38 -1
  172. package/dist/dormer/panel.d.ts.map +1 -1
  173. package/dist/dormer/panel.js +24 -18
  174. package/dist/downspout/inspector-editors.d.ts.map +1 -1
  175. package/dist/downspout/inspector-editors.js +3 -2
  176. package/dist/duct-fitting/inspector-editors.d.ts.map +1 -1
  177. package/dist/duct-fitting/inspector-editors.js +6 -1
  178. package/dist/duct-fitting/tool.d.ts.map +1 -1
  179. package/dist/duct-fitting/tool.js +11 -2
  180. package/dist/duct-terminal/tool.d.ts.map +1 -1
  181. package/dist/duct-terminal/tool.js +11 -2
  182. package/dist/elevator/panel.d.ts.map +1 -1
  183. package/dist/elevator/panel.js +41 -18
  184. package/dist/eyebrow-vent/panel.d.ts.map +1 -1
  185. package/dist/eyebrow-vent/panel.js +16 -6
  186. package/dist/fence/drafting.d.ts +2 -3
  187. package/dist/fence/drafting.d.ts.map +1 -1
  188. package/dist/fence/drafting.js +2 -3
  189. package/dist/fence/inspector-editors.d.ts.map +1 -1
  190. package/dist/fence/inspector-editors.js +64 -21
  191. package/dist/fence/move-endpoint-tool.d.ts.map +1 -1
  192. package/dist/fence/move-endpoint-tool.js +11 -2
  193. package/dist/fence/system.d.ts.map +1 -1
  194. package/dist/fence/system.js +13 -0
  195. package/dist/fence-feature/actions.d.ts.map +1 -1
  196. package/dist/fence-feature/actions.js +5 -2
  197. package/dist/fence-feature/inspector.d.ts.map +1 -1
  198. package/dist/fence-feature/inspector.js +150 -34
  199. package/dist/fence-feature/move-session.d.ts +1 -1
  200. package/dist/floor-opening/floorplan.d.ts +29 -6
  201. package/dist/floor-opening/floorplan.d.ts.map +1 -1
  202. package/dist/floor-opening/floorplan.js +172 -14
  203. package/dist/gutter/downspouts-panel.d.ts.map +1 -1
  204. package/dist/gutter/downspouts-panel.js +14 -2
  205. package/dist/hvac-equipment/tool.d.ts.map +1 -1
  206. package/dist/hvac-equipment/tool.js +3 -2
  207. package/dist/i18n/definition-messages.d.ts +5 -0
  208. package/dist/i18n/definition-messages.d.ts.map +1 -0
  209. package/dist/i18n/definition-messages.js +771 -0
  210. package/dist/index.d.ts +4 -1
  211. package/dist/index.d.ts.map +1 -1
  212. package/dist/index.js +6 -1
  213. package/dist/item/authored-params.d.ts.map +1 -1
  214. package/dist/item/authored-params.js +19 -4
  215. package/dist/item/floorplan.d.ts +1 -1
  216. package/dist/item/floorplan.d.ts.map +1 -1
  217. package/dist/item/panel.d.ts.map +1 -1
  218. package/dist/item/panel.js +9 -7
  219. package/dist/liquid-line/tool.d.ts.map +1 -1
  220. package/dist/liquid-line/tool.js +10 -3
  221. package/dist/measurement/tool.d.ts +1 -1
  222. package/dist/measurement/tool.d.ts.map +1 -1
  223. package/dist/measurement/tool.js +8 -8
  224. package/dist/pipe-fitting/tool.d.ts.map +1 -1
  225. package/dist/pipe-fitting/tool.js +3 -2
  226. package/dist/pipe-trap/tool.d.ts.map +1 -1
  227. package/dist/pipe-trap/tool.js +7 -2
  228. package/dist/procedural-item/renderer.d.ts.map +1 -1
  229. package/dist/procedural-item/renderer.js +8 -1
  230. package/dist/ridge-vent/panel.d.ts.map +1 -1
  231. package/dist/ridge-vent/panel.js +22 -9
  232. package/dist/roof/barrel-panel.d.ts.map +1 -1
  233. package/dist/roof/barrel-panel.js +7 -3
  234. package/dist/roof/definition.d.ts.map +1 -1
  235. package/dist/roof/definition.js +33 -3
  236. package/dist/roof/floorplan-overrides.d.ts +22 -0
  237. package/dist/roof/floorplan-overrides.d.ts.map +1 -0
  238. package/dist/roof/floorplan-overrides.js +46 -0
  239. package/dist/roof/floorplan-tool.d.ts +9 -0
  240. package/dist/roof/floorplan-tool.d.ts.map +1 -0
  241. package/dist/roof/floorplan-tool.js +168 -0
  242. package/dist/roof/floorplan.d.ts.map +1 -1
  243. package/dist/roof/floorplan.js +131 -41
  244. package/dist/roof/glazing-controls.d.ts +2 -1
  245. package/dist/roof/glazing-controls.d.ts.map +1 -1
  246. package/dist/roof/glazing-controls.js +51 -13
  247. package/dist/roof/glazing-panel-editor.d.ts.map +1 -1
  248. package/dist/roof/glazing-panel-editor.js +40 -13
  249. package/dist/roof/glazing-panel.d.ts.map +1 -1
  250. package/dist/roof/glazing-panel.js +73 -9
  251. package/dist/roof/paint.d.ts +19 -0
  252. package/dist/roof/paint.d.ts.map +1 -0
  253. package/dist/roof/paint.js +158 -0
  254. package/dist/roof/panel.d.ts.map +1 -1
  255. package/dist/roof/panel.js +90 -22
  256. package/dist/roof/renderer.d.ts.map +1 -1
  257. package/dist/roof/renderer.js +13 -2
  258. package/dist/roof/roof-footprint-source.d.ts +17 -0
  259. package/dist/roof/roof-footprint-source.d.ts.map +1 -1
  260. package/dist/roof/roof-footprint-source.js +14 -0
  261. package/dist/roof/roof-footprint.d.ts +36 -2
  262. package/dist/roof/roof-footprint.d.ts.map +1 -1
  263. package/dist/roof/roof-footprint.js +124 -2
  264. package/dist/roof/roof-materials.d.ts.map +1 -1
  265. package/dist/roof/roof-materials.js +10 -1
  266. package/dist/roof/roof-placement-mode.d.ts +0 -2
  267. package/dist/roof/roof-placement-mode.d.ts.map +1 -1
  268. package/dist/roof/roof-placement-mode.js +8 -6
  269. package/dist/roof/roof-plan-creases.d.ts +50 -0
  270. package/dist/roof/roof-plan-creases.d.ts.map +1 -0
  271. package/dist/roof/roof-plan-creases.js +194 -0
  272. package/dist/roof/roof-ridge-mode.d.ts +20 -0
  273. package/dist/roof/roof-ridge-mode.d.ts.map +1 -0
  274. package/dist/roof/roof-ridge-mode.js +16 -0
  275. package/dist/roof/tool.d.ts +17 -4
  276. package/dist/roof/tool.d.ts.map +1 -1
  277. package/dist/roof/tool.js +211 -113
  278. package/dist/roof/wall-catch.d.ts +106 -0
  279. package/dist/roof/wall-catch.d.ts.map +1 -0
  280. package/dist/roof/wall-catch.js +267 -0
  281. package/dist/roof-segment/build-up-section.d.ts +9 -0
  282. package/dist/roof-segment/build-up-section.d.ts.map +1 -0
  283. package/dist/roof-segment/build-up-section.js +191 -0
  284. package/dist/roof-segment/definition.d.ts.map +1 -1
  285. package/dist/roof-segment/definition.js +50 -5
  286. package/dist/roof-segment/floorplan-affordances.d.ts.map +1 -1
  287. package/dist/roof-segment/floorplan-affordances.js +68 -19
  288. package/dist/roof-segment/floorplan.d.ts.map +1 -1
  289. package/dist/roof-segment/floorplan.js +16 -12
  290. package/dist/roof-segment/paint.d.ts +3 -1
  291. package/dist/roof-segment/paint.d.ts.map +1 -1
  292. package/dist/roof-segment/paint.js +43 -2
  293. package/dist/roof-segment/panel-model.d.ts +23 -0
  294. package/dist/roof-segment/panel-model.d.ts.map +1 -0
  295. package/dist/roof-segment/panel-model.js +64 -0
  296. package/dist/roof-segment/panel.d.ts.map +1 -1
  297. package/dist/roof-segment/panel.js +96 -14
  298. package/dist/roof-segment/parametrics.d.ts.map +1 -1
  299. package/dist/roof-segment/parametrics.js +4 -0
  300. package/dist/roof-segment/renderer.d.ts.map +1 -1
  301. package/dist/roof-segment/renderer.js +26 -5
  302. package/dist/separator/definition.d.ts.map +1 -1
  303. package/dist/separator/definition.js +10 -12
  304. package/dist/separator/floorplan-affordances.d.ts +9 -0
  305. package/dist/separator/floorplan-affordances.d.ts.map +1 -0
  306. package/dist/separator/floorplan-affordances.js +23 -0
  307. package/dist/separator/floorplan.d.ts +9 -0
  308. package/dist/separator/floorplan.d.ts.map +1 -0
  309. package/dist/separator/floorplan.js +54 -0
  310. package/dist/separator/renderer.d.ts +4 -0
  311. package/dist/separator/renderer.d.ts.map +1 -1
  312. package/dist/separator/renderer.js +21 -6
  313. package/dist/separator/selection.d.ts +10 -0
  314. package/dist/separator/selection.d.ts.map +1 -0
  315. package/dist/separator/selection.js +35 -0
  316. package/dist/shared/build-up-controls.d.ts +88 -0
  317. package/dist/shared/build-up-controls.d.ts.map +1 -0
  318. package/dist/shared/build-up-controls.js +139 -0
  319. package/dist/shared/curtain-opening-limits.d.ts.map +1 -1
  320. package/dist/shared/curtain-opening-limits.js +44 -14
  321. package/dist/shared/item-interaction-actions.d.ts.map +1 -1
  322. package/dist/shared/item-interaction-actions.js +11 -2
  323. package/dist/shared/layer-thickness.d.ts +2 -0
  324. package/dist/shared/layer-thickness.d.ts.map +1 -0
  325. package/dist/shared/layer-thickness.js +3 -0
  326. package/dist/shared/move-roof-tool.d.ts.map +1 -1
  327. package/dist/shared/move-roof-tool.js +100 -5
  328. package/dist/shared/node-batch/batchable.d.ts +2 -0
  329. package/dist/shared/node-batch/batchable.d.ts.map +1 -1
  330. package/dist/shared/node-batch/batchable.js +4 -0
  331. package/dist/shared/node-batch/candidates.d.ts +21 -5
  332. package/dist/shared/node-batch/candidates.d.ts.map +1 -1
  333. package/dist/shared/node-batch/candidates.js +85 -50
  334. package/dist/shared/node-batch/system.d.ts.map +1 -1
  335. package/dist/shared/node-batch/system.js +24 -15
  336. package/dist/shared/opening-casing-move.d.ts +16 -0
  337. package/dist/shared/opening-casing-move.d.ts.map +1 -0
  338. package/dist/shared/opening-casing-move.js +33 -0
  339. package/dist/shared/opening-casing-section.d.ts +15 -0
  340. package/dist/shared/opening-casing-section.d.ts.map +1 -0
  341. package/dist/shared/opening-casing-section.js +38 -0
  342. package/dist/shared/opening-casing.d.ts +26 -0
  343. package/dist/shared/opening-casing.d.ts.map +1 -0
  344. package/dist/shared/opening-casing.js +80 -0
  345. package/dist/shared/opening-depth-position.d.ts +13 -0
  346. package/dist/shared/opening-depth-position.d.ts.map +1 -0
  347. package/dist/shared/opening-depth-position.js +34 -0
  348. package/dist/shared/opening-documentation.d.ts.map +1 -1
  349. package/dist/shared/opening-documentation.js +17 -8
  350. package/dist/shared/opening-guides-runtime.d.ts +2 -1
  351. package/dist/shared/opening-guides-runtime.d.ts.map +1 -1
  352. package/dist/shared/opening-guides-runtime.js +11 -7
  353. package/dist/shared/opening-labels.d.ts +11 -0
  354. package/dist/shared/opening-labels.d.ts.map +1 -0
  355. package/dist/shared/opening-labels.js +46 -0
  356. package/dist/shared/opening-placement-dimensions.d.ts.map +1 -1
  357. package/dist/shared/opening-placement-dimensions.js +11 -9
  358. package/dist/shared/opening-plane-offset.d.ts +4 -3
  359. package/dist/shared/opening-plane-offset.d.ts.map +1 -1
  360. package/dist/shared/opening-plane-offset.js +7 -4
  361. package/dist/shared/opening-swap.d.ts +8 -0
  362. package/dist/shared/opening-swap.d.ts.map +1 -0
  363. package/dist/shared/opening-swap.js +18 -0
  364. package/dist/shared/polygon-vertex-affordance.d.ts +19 -0
  365. package/dist/shared/polygon-vertex-affordance.d.ts.map +1 -1
  366. package/dist/shared/polygon-vertex-affordance.js +65 -6
  367. package/dist/shared/roof-opening-host.d.ts +2 -1
  368. package/dist/shared/roof-opening-host.d.ts.map +1 -1
  369. package/dist/shared/roof-opening-host.js +14 -5
  370. package/dist/shared/roof-wall-opening-cut.d.ts.map +1 -1
  371. package/dist/shared/roof-wall-opening-cut.js +14 -6
  372. package/dist/shared/roof-wall-opening-placement.d.ts +2 -1
  373. package/dist/shared/roof-wall-opening-placement.d.ts.map +1 -1
  374. package/dist/shared/roof-wall-opening-placement.js +6 -4
  375. package/dist/shared/run-hanger-inspector.d.ts.map +1 -1
  376. package/dist/shared/run-hanger-inspector.js +39 -5
  377. package/dist/shared/system-check-panel.d.ts.map +1 -1
  378. package/dist/shared/system-check-panel.js +94 -15
  379. package/dist/shared/wall-attach-target.d.ts.map +1 -1
  380. package/dist/shared/wall-attach-target.js +6 -3
  381. package/dist/shelf/definition.d.ts.map +1 -1
  382. package/dist/shelf/definition.js +2 -0
  383. package/dist/site/ground-hole.d.ts +3 -3
  384. package/dist/site/ground-hole.js +3 -3
  385. package/dist/site/ground-veil.d.ts +5 -12
  386. package/dist/site/ground-veil.d.ts.map +1 -1
  387. package/dist/site/ground-veil.js +9 -33
  388. package/dist/site/panel.d.ts.map +1 -1
  389. package/dist/site/panel.js +52 -12
  390. package/dist/site/renderer.d.ts.map +1 -1
  391. package/dist/site/renderer.js +52 -23
  392. package/dist/skylight/panel.d.ts.map +1 -1
  393. package/dist/skylight/panel.js +49 -19
  394. package/dist/slab/deck-geometry.d.ts +28 -0
  395. package/dist/slab/deck-geometry.d.ts.map +1 -0
  396. package/dist/slab/deck-geometry.js +320 -0
  397. package/dist/slab/definition.d.ts +2 -1
  398. package/dist/slab/definition.d.ts.map +1 -1
  399. package/dist/slab/definition.js +6 -1
  400. package/dist/slab/dependency-tracker.d.ts.map +1 -1
  401. package/dist/slab/dependency-tracker.js +3 -0
  402. package/dist/slab/floorplan-affordances.d.ts +500 -0
  403. package/dist/slab/floorplan-affordances.d.ts.map +1 -1
  404. package/dist/slab/geometry.d.ts.map +1 -1
  405. package/dist/slab/geometry.js +46 -9
  406. package/dist/slab/panel.d.ts.map +1 -1
  407. package/dist/slab/panel.js +97 -21
  408. package/dist/slab/renderer.d.ts +11 -0
  409. package/dist/slab/renderer.d.ts.map +1 -0
  410. package/dist/slab/renderer.js +19 -0
  411. package/dist/slab/system.d.ts.map +1 -1
  412. package/dist/slab/system.js +12 -1
  413. package/dist/solar-panel/panel.d.ts.map +1 -1
  414. package/dist/solar-panel/panel.js +49 -14
  415. package/dist/stair/construction-controls.d.ts +3 -1
  416. package/dist/stair/construction-controls.d.ts.map +1 -1
  417. package/dist/stair/construction-controls.js +75 -12
  418. package/dist/stair/paint.d.ts +6 -0
  419. package/dist/stair/paint.d.ts.map +1 -1
  420. package/dist/stair/panel.d.ts.map +1 -1
  421. package/dist/stair/panel.js +243 -51
  422. package/dist/stair/parametrics.d.ts.map +1 -1
  423. package/dist/stair/parametrics.js +7 -0
  424. package/dist/stair/placement-defaults.d.ts +18 -0
  425. package/dist/stair/placement-defaults.d.ts.map +1 -0
  426. package/dist/stair/placement-defaults.js +27 -0
  427. package/dist/stair/railing-controls.d.ts.map +1 -1
  428. package/dist/stair/railing-controls.js +78 -18
  429. package/dist/stair/renderer.d.ts.map +1 -1
  430. package/dist/stair/renderer.js +16 -10
  431. package/dist/stair/structure-controls.d.ts +18 -0
  432. package/dist/stair/structure-controls.d.ts.map +1 -0
  433. package/dist/stair/structure-controls.js +275 -0
  434. package/dist/stair/tool.d.ts.map +1 -1
  435. package/dist/stair/tool.js +13 -9
  436. package/dist/stair/use-stair-render-data.d.ts +41 -0
  437. package/dist/stair/use-stair-render-data.d.ts.map +1 -1
  438. package/dist/stair-segment/panel.d.ts.map +1 -1
  439. package/dist/stair-segment/panel.js +65 -18
  440. package/dist/turbine-vent/panel.d.ts.map +1 -1
  441. package/dist/turbine-vent/panel.js +14 -5
  442. package/dist/unit/unit-panel.d.ts.map +1 -1
  443. package/dist/unit/unit-panel.js +28 -12
  444. package/dist/wall/actions.d.ts +1 -1
  445. package/dist/wall/actions.d.ts.map +1 -1
  446. package/dist/wall/actions.js +17 -13
  447. package/dist/wall/construction-dimensions.d.ts +6 -0
  448. package/dist/wall/construction-dimensions.d.ts.map +1 -1
  449. package/dist/wall/construction-dimensions.js +8 -0
  450. package/dist/wall/contextual-dimensions.d.ts +6 -0
  451. package/dist/wall/contextual-dimensions.d.ts.map +1 -1
  452. package/dist/wall/contextual-dimensions.js +104 -17
  453. package/dist/wall/curtain-opening-frame.d.ts.map +1 -1
  454. package/dist/wall/curtain-opening-frame.js +6 -4
  455. package/dist/wall/curtain-wall-layout.d.ts +1 -1
  456. package/dist/wall/curtain-wall-layout.d.ts.map +1 -1
  457. package/dist/wall/curtain-wall-layout.js +6 -4
  458. package/dist/wall/curtain-wall-materials.d.ts.map +1 -1
  459. package/dist/wall/curtain-wall-materials.js +8 -3
  460. package/dist/wall/curtain-wall-panel.d.ts.map +1 -1
  461. package/dist/wall/curtain-wall-panel.js +241 -37
  462. package/dist/wall/curve-tool.d.ts.map +1 -1
  463. package/dist/wall/curve-tool.js +2 -3
  464. package/dist/wall/definition.d.ts.map +1 -1
  465. package/dist/wall/definition.js +20 -5
  466. package/dist/wall/floorplan-affordances.d.ts.map +1 -1
  467. package/dist/wall/floorplan-affordances.js +9 -6
  468. package/dist/wall/floorplan-move.d.ts.map +1 -1
  469. package/dist/wall/floorplan-move.js +66 -16
  470. package/dist/wall/floorplan.d.ts +4 -5
  471. package/dist/wall/floorplan.d.ts.map +1 -1
  472. package/dist/wall/floorplan.js +62 -46
  473. package/dist/wall/move-endpoint-tool.d.ts.map +1 -1
  474. package/dist/wall/move-endpoint-tool.js +1 -0
  475. package/dist/wall/move-tool.d.ts.map +1 -1
  476. package/dist/wall/move-tool.js +77 -12
  477. package/dist/wall/paint.d.ts +2 -2
  478. package/dist/wall/paint.d.ts.map +1 -1
  479. package/dist/wall/paint.js +11 -4
  480. package/dist/wall/panel-model.d.ts +17 -2
  481. package/dist/wall/panel-model.d.ts.map +1 -1
  482. package/dist/wall/panel-model.js +158 -18
  483. package/dist/wall/panel.d.ts +8 -0
  484. package/dist/wall/panel.d.ts.map +1 -1
  485. package/dist/wall/panel.js +228 -156
  486. package/dist/wall/parametrics.d.ts +1 -1
  487. package/dist/wall/parametrics.d.ts.map +1 -1
  488. package/dist/wall/parametrics.js +14 -1
  489. package/dist/wall/railing-wall-adapter.d.ts +7 -0
  490. package/dist/wall/railing-wall-adapter.d.ts.map +1 -0
  491. package/dist/wall/railing-wall-adapter.js +38 -0
  492. package/dist/wall/railing-wall-floorplan.d.ts +8 -0
  493. package/dist/wall/railing-wall-floorplan.d.ts.map +1 -0
  494. package/dist/wall/railing-wall-floorplan.js +27 -0
  495. package/dist/wall/railing-wall-geometry.d.ts +12 -0
  496. package/dist/wall/railing-wall-geometry.d.ts.map +1 -0
  497. package/dist/wall/railing-wall-geometry.js +51 -0
  498. package/dist/wall/railing-wall-guard.d.ts +81 -0
  499. package/dist/wall/railing-wall-guard.d.ts.map +1 -0
  500. package/dist/wall/railing-wall-guard.js +435 -0
  501. package/dist/wall/railing-wall-materials.d.ts +11 -0
  502. package/dist/wall/railing-wall-materials.d.ts.map +1 -0
  503. package/dist/wall/railing-wall-materials.js +31 -0
  504. package/dist/wall/railing-wall-panel-model.d.ts +30 -0
  505. package/dist/wall/railing-wall-panel-model.d.ts.map +1 -0
  506. package/dist/wall/railing-wall-panel-model.js +117 -0
  507. package/dist/wall/railing-wall-panel.d.ts +17 -0
  508. package/dist/wall/railing-wall-panel.d.ts.map +1 -0
  509. package/dist/wall/railing-wall-panel.js +42 -0
  510. package/dist/wall/rectangle-command.d.ts +79 -1
  511. package/dist/wall/rectangle-command.d.ts.map +1 -1
  512. package/dist/wall/rectangle-tool.d.ts.map +1 -1
  513. package/dist/wall/rectangle-tool.js +2 -0
  514. package/dist/wall/renderer.d.ts.map +1 -1
  515. package/dist/wall/renderer.js +3 -1
  516. package/dist/wall/skirting-floor-gaps.d.ts +8 -0
  517. package/dist/wall/skirting-floor-gaps.d.ts.map +1 -0
  518. package/dist/wall/skirting-floor-gaps.js +36 -0
  519. package/dist/wall/system.d.ts +0 -14
  520. package/dist/wall/system.d.ts.map +1 -1
  521. package/dist/wall/system.js +6 -1
  522. package/dist/wall/tool.d.ts +16 -0
  523. package/dist/wall/tool.d.ts.map +1 -1
  524. package/dist/wall/tool.js +160 -47
  525. package/dist/wall/treatments.d.ts +3 -0
  526. package/dist/wall/treatments.d.ts.map +1 -1
  527. package/dist/wall/treatments.js +30 -7
  528. package/dist/window/actions.d.ts +7 -0
  529. package/dist/window/actions.d.ts.map +1 -0
  530. package/dist/window/actions.js +29 -0
  531. package/dist/window/definition.d.ts.map +1 -1
  532. package/dist/window/definition.js +11 -2
  533. package/dist/window/floorplan-move.d.ts.map +1 -1
  534. package/dist/window/floorplan-move.js +5 -0
  535. package/dist/window/floorplan.d.ts +2 -0
  536. package/dist/window/floorplan.d.ts.map +1 -1
  537. package/dist/window/floorplan.js +58 -1
  538. package/dist/window/mechanism.d.ts.map +1 -1
  539. package/dist/window/mechanism.js +21 -1
  540. package/dist/window/move-tool.d.ts.map +1 -1
  541. package/dist/window/move-tool.js +10 -3
  542. package/dist/window/paint.d.ts +2 -7
  543. package/dist/window/paint.d.ts.map +1 -1
  544. package/dist/window/paint.js +31 -3
  545. package/dist/window/panel.d.ts.map +1 -1
  546. package/dist/window/panel.js +311 -69
  547. package/dist/window/placement.d.ts.map +1 -1
  548. package/dist/window/placement.js +5 -1
  549. package/dist/window/swing.d.ts +13 -0
  550. package/dist/window/swing.d.ts.map +1 -0
  551. package/dist/window/swing.js +16 -0
  552. package/dist/window/tool.d.ts.map +1 -1
  553. package/dist/window/tool.js +19 -14
  554. package/dist/zone/floorplan-affordances.d.ts +136 -0
  555. package/dist/zone/floorplan-affordances.d.ts.map +1 -1
  556. package/dist/zone/quantities-panel.d.ts.map +1 -1
  557. package/dist/zone/quantities-panel.js +34 -9
  558. package/dist/zone/renderer.d.ts.map +1 -1
  559. package/dist/zone/renderer.js +9 -5
  560. package/package.json +14 -14
  561. package/dist/site/generic-foundation-geometry.d.ts +0 -16
  562. package/dist/site/generic-foundation-geometry.d.ts.map +0 -1
  563. package/dist/site/generic-foundation-geometry.js +0 -75
  564. package/dist/site/generic-foundation.d.ts +0 -4
  565. package/dist/site/generic-foundation.d.ts.map +0 -1
  566. package/dist/site/generic-foundation.js +0 -91
@@ -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 { cascadeDirty, createSceneApi, resolveLevelId, runAsSingleSceneHistoryStep, useScene, } from '@pascal-app/core';
3
+ import { cascadeDirty, createSceneApi, resolveLevelId, runAsSingleSceneHistoryStep, usePascalI18n, useScene, } from '@pascal-app/core';
4
4
  import { ActionButton, PanelSection, PanelWrapper, SegmentedControl, SliderControl, ToggleControl, usePlacementNotice, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { Copy, Equal as EqualIcon, Plus, Trash } from 'lucide-react';
@@ -58,35 +58,46 @@ function selectCabinetRunPlanningNodes(nodes, runId) {
58
58
  });
59
59
  }
60
60
  const FRONT_STYLE_OPTIONS = [
61
- { value: 'slab', label: 'Slab' },
62
- { value: 'shaker', label: 'Shaker' },
63
- { value: 'raised-arch', label: 'Raised Arch' },
61
+ { value: 'slab', label: /* i18n */ { id: 'node.cabinet.runPanel.slab', message: 'Slab' } },
62
+ { value: 'shaker', label: /* i18n */ { id: 'node.cabinet.runPanel.shaker', message: 'Shaker' } },
63
+ {
64
+ value: 'raised-arch',
65
+ label: /* i18n */ { id: 'node.cabinet.runPanel.raisedArch', message: 'Raised Arch' },
66
+ },
64
67
  ];
65
68
  const FRONT_OVERLAY_OPTIONS = [
66
- { value: 'full', label: 'Overlay' },
67
- { value: 'inset', label: 'Inset' },
69
+ { value: 'full', label: /* i18n */ { id: 'node.cabinet.runPanel.overlay', message: 'Overlay' } },
70
+ { value: 'inset', label: /* i18n */ { id: 'node.cabinet.runPanel.inset', message: 'Inset' } },
68
71
  ];
69
72
  const HANDLE_STYLE_OPTIONS = [
70
- { value: 'bar', label: 'Bar' },
71
- { value: 'knob', label: 'Knob' },
72
- { value: 'cutout', label: 'Cutout' },
73
- { value: 'hole', label: 'Hole' },
74
- { value: 'none', label: 'None' },
73
+ { value: 'bar', label: /* i18n */ { id: 'node.cabinet.runPanel.bar', message: 'Bar' } },
74
+ { value: 'knob', label: /* i18n */ { id: 'node.cabinet.runPanel.knob', message: 'Knob' } },
75
+ { value: 'cutout', label: /* i18n */ { id: 'node.cabinet.runPanel.cutout', message: 'Cutout' } },
76
+ { value: 'hole', label: /* i18n */ { id: 'node.cabinet.runPanel.hole', message: 'Hole' } },
77
+ { value: 'none', label: /* i18n */ { id: 'node.cabinet.runPanel.none', message: 'None' } },
75
78
  ];
76
79
  const HANDLE_POSITION_OPTIONS = [
77
- { value: 'auto', label: 'Auto' },
78
- { value: 'top', label: 'Top' },
79
- { value: 'center', label: 'Center' },
80
+ { value: 'auto', label: /* i18n */ { id: 'node.cabinet.runPanel.auto', message: 'Auto' } },
81
+ { value: 'top', label: /* i18n */ { id: 'node.cabinet.runPanel.top', message: 'Top' } },
82
+ { value: 'center', label: /* i18n */ { id: 'node.cabinet.runPanel.center', message: 'Center' } },
80
83
  ];
81
- function moduleSummary(module) {
84
+ function moduleSummary(module, i18n) {
82
85
  if ((module.cabinetType ?? 'base') === 'tall')
83
- return 'Tall cabinet';
86
+ return i18n._({ id: 'node.cabinet.runPanel.summaryTall', message: 'Tall cabinet' });
84
87
  const stack = stackForCabinet(module);
85
88
  if (stack.length === 0)
86
- return 'Empty';
89
+ return i18n._({ id: 'node.cabinet.runPanel.summaryEmpty', message: 'Empty' });
87
90
  if (stack.length === 1)
88
- return stack[0].type;
89
- return `${stack.length} compartments`;
91
+ return i18n._({
92
+ id: 'node.cabinet.runPanel.summaryCompartment',
93
+ message: '{type, select, shelf {Shelf} drawer {Drawer} door {Door} oven {Oven} microwave {Microwave} dishwasher {Dishwasher} sink {Sink} cooktop_gas {Gas cooktop} cooktop_induction {Induction cooktop} pull_out_pantry {Pull-out pantry} fridge_single {Fridge} fridge_double {Double fridge} fridge_top_freezer {Top-freezer fridge} fridge_bottom_freezer {Bottom-freezer fridge} hood_pyramid {Pyramid hood} hood_curved_glass {Curved glass hood} other {{raw}}}',
94
+ values: { type: stack[0].type.replaceAll('-', '_'), raw: stack[0].type },
95
+ });
96
+ return i18n._({
97
+ id: 'node.cabinet.runPanel.summaryCompartments',
98
+ message: '{count, plural, one {{number} compartment} other {{number} compartments}}',
99
+ values: { count: stack.length, number: String(stack.length) },
100
+ });
90
101
  }
91
102
  export function bumpRunLayoutRevisionViaStore(scene, run) {
92
103
  bumpCabinetRunLayoutRevision(createSceneApi(useScene), run);
@@ -318,11 +329,18 @@ function writeCabinetRun({ modules, node, patch, }, sceneApi) {
318
329
  }
319
330
  }
320
331
  export function CabinetRunPanel({ node, modules, onClose, }) {
332
+ const i18n = usePascalI18n();
321
333
  const setSelection = useViewer((s) => s.setSelection);
322
334
  const planningNodeList = useScene(useShallow((state) => selectCabinetRunPlanningNodes(state.nodes, node.id)));
323
335
  const planningNodes = useMemo(() => Object.fromEntries(planningNodeList.map((planningNode) => [planningNode.id, planningNode])), [planningNodeList]);
324
336
  const planningNode = planningNodes[node.id] ?? node;
325
337
  const sortedModules = useMemo(() => [...modules].sort((a, b) => a.position[0] - b.position[0]), [modules]);
338
+ const moduleNames = sortedModules.map((module, index) => module.name ||
339
+ i18n._({
340
+ id: 'node.cabinet.runPanel.moduleNumber',
341
+ message: 'Module {number}',
342
+ values: { number: index + 1 },
343
+ }));
326
344
  const [arraySourceId, setArraySourceId] = useState(null);
327
345
  const [arrayCopyCount, setArrayCopyCount] = useState(2);
328
346
  const [arraySpacing, setArraySpacing] = useState(0);
@@ -348,7 +366,12 @@ export function CabinetRunPanel({ node, modules, onClose, }) {
348
366
  .applyNodeChanges(outcome.changes));
349
367
  }
350
368
  catch (error) {
351
- setFinishMessage(error instanceof Error ? error.message : 'Unable to finish this kitchen run.');
369
+ setFinishMessage(error instanceof Error
370
+ ? error.message
371
+ : i18n._({
372
+ id: 'node.cabinet.runPanel.unableToFinish',
373
+ message: 'Unable to finish this kitchen run.',
374
+ }));
352
375
  }
353
376
  };
354
377
  const updateRun = useCallback((patch) => updateCabinetRun({ modules, node, patch }), [modules, node]);
@@ -367,11 +390,23 @@ export function CabinetRunPanel({ node, modules, onClose, }) {
367
390
  }, [node]);
368
391
  const equalizeWidthsTitle = !widthEqualization.ok
369
392
  ? widthEqualization.reason === 'not-enough-modules'
370
- ? 'At least two standard base cabinets are required'
371
- : 'The available run width cannot satisfy the cabinet width limits'
393
+ ? i18n._({
394
+ id: 'node.cabinet.runPanel.equalizeNeedsTwo',
395
+ message: 'At least two standard base cabinets are required',
396
+ })
397
+ : i18n._({
398
+ id: 'node.cabinet.runPanel.equalizeNoFit',
399
+ message: 'The available run width cannot satisfy the cabinet width limits',
400
+ })
372
401
  : widthEqualization.changed
373
- ? 'Equalize all resizeable standard base cabinets in this run'
374
- : 'The resizeable cabinet widths are already equal';
402
+ ? i18n._({
403
+ id: 'node.cabinet.runPanel.equalizeAll',
404
+ message: 'Equalize all resizeable standard base cabinets in this run',
405
+ })
406
+ : i18n._({
407
+ id: 'node.cabinet.runPanel.equalizeAlreadyEqual',
408
+ message: 'The resizeable cabinet widths are already equal',
409
+ });
375
410
  const duplicateAlongRun = useCallback(() => {
376
411
  if (!arraySource)
377
412
  return;
@@ -388,11 +423,30 @@ export function CabinetRunPanel({ node, modules, onClose, }) {
388
423
  }, [arrayCopyCount, arrayDirection, arraySpacing, arraySource, node, setSelection]);
389
424
  const duplicateAlongRunTitle = !arrayPlan.ok
390
425
  ? arrayPlan.reason === 'no-source'
391
- ? 'Choose a standard or appliance module as the source'
426
+ ? i18n._({
427
+ id: 'node.cabinet.runPanel.arrayNoSource',
428
+ message: 'Choose a standard or appliance module as the source',
429
+ })
392
430
  : arrayPlan.reason === 'invalid-options'
393
- ? 'Choose a copy count from 1 to 20 and spacing from 0 to 2 m'
394
- : 'There is not enough room in this run for the requested array'
395
- : `Create ${arrayCopyCount} ${arraySource?.name || 'module'} cop${arrayCopyCount === 1 ? 'y' : 'ies'}`;
431
+ ? i18n._({
432
+ id: 'node.cabinet.runPanel.arrayInvalidOptions',
433
+ message: 'Choose a copy count from 1 to 20 and spacing from 0 to 2 m',
434
+ })
435
+ : i18n._({
436
+ id: 'node.cabinet.runPanel.arrayNoRoom',
437
+ message: 'There is not enough room in this run for the requested array',
438
+ })
439
+ : arraySource?.name
440
+ ? i18n._({
441
+ id: 'node.cabinet.runPanel.arrayCreateNamed',
442
+ message: '{count, plural, one {Create {number} {name} copy} other {Create {number} {name} copies}}',
443
+ values: { count: arrayCopyCount, number: String(arrayCopyCount), name: arraySource.name },
444
+ })
445
+ : i18n._({
446
+ id: 'node.cabinet.runPanel.arrayCreate',
447
+ message: '{count, plural, one {Create {number} module copy} other {Create {number} module copies}}',
448
+ values: { count: arrayCopyCount, number: String(arrayCopyCount) },
449
+ });
396
450
  const dimensionProfile = cabinetDimensionProfileId(node);
397
451
  const wallHeightPreset = cabinetWallHeightPresetId(node);
398
452
  const applyWallHeightPreset = useCallback((presetId) => {
@@ -419,48 +473,145 @@ export function CabinetRunPanel({ node, modules, onClose, }) {
419
473
  setSelection({ selectedIds: [] });
420
474
  }
421
475
  }, [node.id, setSelection]);
422
- return (_jsxs(PanelWrapper, { icon: "/icons/item.webp", onClose: onClose, title: node.name || 'Kitchen run', width: 320, children: [placementNotice && (_jsx("p", { role: "status", className: "px-3 py-2 text-xs text-amber-600", children: placementNotice.line })), _jsx(PanelSection, { title: "Finish & align", children: _jsxs("div", { className: "flex flex-col gap-2 px-1 pb-2", children: [_jsx(ActionButton, { label: "Align cabinets & handles", onClick: () => finishRun('align') }), finishMessage && (_jsx("p", { role: "status", className: "text-xs text-amber-600", children: finishMessage })), _jsx("p", { className: "text-xs text-muted-foreground", children: "Match base heights, backs, reveals and handles. Align upper cabinets; preserve tall appliances and custom compartments." }), _jsx(ToggleControl, { label: "Finished exposed ends", checked: node.withFinishedEnds, onChange: (checked) => updateRun({ withFinishedEnds: checked }) }), _jsx(ActionButton, { label: "Fit wall fillers", disabled: fillerPlan.length === 0, onClick: () => finishRun('fill') }), _jsx("p", { className: "text-xs text-muted-foreground", children: fillerPlan.length
476
+ return (_jsxs(PanelWrapper, { icon: "/icons/item.webp", onClose: onClose, title: node.name || i18n._({ id: 'node.cabinet.runPanel.kitchenRun', message: 'Kitchen run' }), width: 320, children: [placementNotice && (_jsx("p", { role: "status", className: "px-3 py-2 text-xs text-amber-600", children: placementNotice.line })), _jsx(PanelSection, { title: i18n._({ id: 'node.cabinet.runPanel.finishAlign', message: 'Finish & align' }), children: _jsxs("div", { className: "flex flex-col gap-2 px-1 pb-2", children: [_jsx(ActionButton, { label: i18n._({
477
+ id: 'node.cabinet.runPanel.alignCabinetsHandles',
478
+ message: 'Align cabinets & handles',
479
+ }), onClick: () => finishRun('align') }), finishMessage && (_jsx("p", { role: "status", className: "text-xs text-amber-600", children: finishMessage })), _jsx("p", { className: "text-xs text-muted-foreground", children: i18n._({
480
+ id: 'node.cabinet.runPanel.matchBaseHeightsBacksRevealsAnd',
481
+ message: 'Match base heights, backs, reveals and handles. Align upper cabinets; preserve tall appliances and custom compartments.',
482
+ }) }), _jsx(ToggleControl, { label: i18n._({
483
+ id: 'node.cabinet.runPanel.finishedExposedEnds',
484
+ message: 'Finished exposed ends',
485
+ }), checked: node.withFinishedEnds, onChange: (checked) => updateRun({ withFinishedEnds: checked }) }), _jsx(ActionButton, { label: i18n._({
486
+ id: 'node.cabinet.runPanel.fitWallFillers',
487
+ message: 'Fit wall fillers',
488
+ }), disabled: fillerPlan.length === 0, onClick: () => finishRun('fill') }), _jsx("p", { className: "text-xs text-muted-foreground", children: fillerPlan.length
423
489
  ? fillerPlan
424
- .map(({ side, width }) => `${side}: ${Math.round(width * 1000)} mm`)
490
+ .map(({ side, width }) => i18n._({
491
+ id: 'node.cabinet.runPanel.fillerPlanSide',
492
+ message: '{side, select, left {Left: {width} mm} other {Right: {width} mm}}',
493
+ values: { side, width: String(Math.round(width * 1000)) },
494
+ }))
425
495
  .join(' · ')
426
- : 'Fits 50–150 mm gaps at run ends beside perpendicular walls.' })] }) }), _jsxs(PanelSection, { title: "Modules", children: [_jsx("div", { className: "flex flex-col gap-2 px-1 pb-2", children: sortedModules.map((module, index) => (_jsxs("div", { className: "flex items-center justify-between gap-2 rounded-lg border border-border/40 bg-black/3 dark:bg-[#252527] px-2 py-2", children: [_jsxs("button", { className: "min-h-8 min-w-0 flex-1 py-1 text-left", onClick: () => setSelection({ selectedIds: [module.id] }), type: "button", children: [_jsx("div", { className: "truncate text-xs font-medium text-foreground", children: module.name || `Module ${index + 1}` }), _jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: moduleSummary(module) })] }), _jsx("button", { "aria-label": `Use ${module.name || `Module ${index + 1}`} as array source`, className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md border border-border/50 text-muted-foreground transition-colors hover:bg-black/5 dark:hover:bg-white/8 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-30", disabled: module.moduleKind === 'corner-filler', onClick: () => setArraySourceId(module.id), title: module.moduleKind === 'corner-filler'
427
- ? 'Corner fillers cannot be used as array sources'
428
- : 'Use this module as the array source', type: "button", children: _jsx(Copy, { className: "h-3.5 w-3.5" }) }), _jsx("button", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md border border-red-500/20 bg-red-500/8 text-red-700 dark:text-red-300 transition-colors hover:bg-red-500/15 hover:text-red-700 dark:hover:text-red-200 disabled:opacity-30", disabled: modules.length <= 1, onClick: () => deleteModule(module), type: "button", children: _jsx(Trash, { className: "h-3.5 w-3.5" }) })] }, module.id))) }), _jsxs("div", { className: "px-1 pb-1", children: [_jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsx(ActionButton, { icon: _jsx(Plus, { className: "h-4 w-4" }), label: "Add left", onClick: () => addModule('left') }), _jsx(ActionButton, { icon: _jsx(Plus, { className: "h-4 w-4" }), label: "Add right", onClick: () => addModule('right') })] }), _jsx(ActionButton, { className: "mt-2 w-full", disabled: !widthEqualization.ok || !widthEqualization.changed, icon: _jsx(EqualIcon, { className: "h-4 w-4" }), label: "Equalize widths", onClick: equalizeWidths, title: equalizeWidthsTitle }), _jsx("p", { className: "px-1 pt-1 text-[10px] leading-4 text-muted-foreground", children: "Balances standard base cabinets while keeping appliance and corner-filler widths fixed." })] })] }), _jsx(PanelSection, { title: "Duplicate along run", children: _jsxs("div", { className: "space-y-2 px-1 pb-2", children: [_jsxs("div", { className: "rounded-lg border border-border/40 bg-black/3 dark:bg-[#252527] px-2 py-2", children: [_jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "Source module" }), _jsx("div", { className: "truncate pt-1 text-xs font-medium text-foreground", children: arraySource?.name ||
429
- (arraySource ? moduleSummary(arraySource) : 'No eligible module') })] }), _jsx(SliderControl, { label: "Copies", max: 20, min: 1, onChange: (value) => setArrayCopyCount(Math.round(value)), precision: 0, step: 1, value: arrayCopyCount }), _jsx(SliderControl, { label: "Spacing", max: 2, min: 0, onChange: setArraySpacing, precision: 2, step: 0.01, unit: "m", value: arraySpacing }), _jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: "Direction" }), _jsx(SegmentedControl, { onChange: (value) => setArrayDirection(value), options: [
430
- { value: 'left', label: 'Left' },
431
- { value: 'right', label: 'Right' },
432
- ], value: arrayDirection })] }), _jsx(ActionButton, { className: "w-full", disabled: !arrayPlan.ok, icon: _jsx(Copy, { className: "h-4 w-4" }), label: "Create array", onClick: duplicateAlongRun, title: duplicateAlongRunTitle }), _jsx("p", { className: "px-1 pt-1 text-[10px] leading-4 text-muted-foreground", children: "Copies include the source cabinet structure and any attached wall cabinet. Existing modules stay fixed; the requested array must fit in the available run space." })] }) }), _jsx(PanelSection, { title: "Shared Plinth & Countertop", children: _jsxs("div", { className: "space-y-2 px-1 pb-2", children: [node.runTier === 'base' && (_jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: "Standard dimensions" }), _jsx(SegmentedControl, { mixed: dimensionProfile === 'custom', onChange: (value) => applyDimensionProfile(value), options: CABINET_DIMENSION_PROFILES.map((profile) => ({
433
- label: profile.label,
496
+ : i18n._({
497
+ id: 'node.cabinet.runPanel.fits50150MmGapsAt',
498
+ message: 'Fits 50–150 mm gaps at run ends beside perpendicular walls.',
499
+ }) })] }) }), _jsxs(PanelSection, { title: i18n._({ id: 'node.cabinet.runPanel.modules', message: 'Modules' }), children: [_jsx("div", { className: "flex flex-col gap-2 px-1 pb-2", children: sortedModules.map((module, index) => (_jsxs("div", { className: "flex items-center justify-between gap-2 rounded-lg border border-border/40 bg-black/3 dark:bg-[#252527] px-2 py-2", children: [_jsxs("button", { className: "min-h-8 min-w-0 flex-1 py-1 text-left", onClick: () => setSelection({ selectedIds: [module.id] }), type: "button", children: [_jsx("div", { className: "truncate text-xs font-medium text-foreground", children: moduleNames[index] }), _jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: moduleSummary(module, i18n) })] }), _jsx("button", { "aria-label": i18n._({
500
+ id: 'node.cabinet.runPanel.useAsArraySource',
501
+ message: 'Use {name} as array source',
502
+ values: { name: moduleNames[index] },
503
+ }), className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md border border-border/50 text-muted-foreground transition-colors hover:bg-black/5 dark:hover:bg-white/8 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-30", disabled: module.moduleKind === 'corner-filler', onClick: () => setArraySourceId(module.id), title: module.moduleKind === 'corner-filler'
504
+ ? i18n._({
505
+ id: 'node.cabinet.runPanel.cornerFillersCannotBeUsedAs',
506
+ message: 'Corner fillers cannot be used as array sources',
507
+ })
508
+ : i18n._({
509
+ id: 'node.cabinet.runPanel.useThisModuleAsTheArray',
510
+ message: 'Use this module as the array source',
511
+ }), type: "button", children: _jsx(Copy, { className: "h-3.5 w-3.5" }) }), _jsx("button", { "aria-label": i18n._({
512
+ id: 'node.cabinet.runPanel.deleteModule',
513
+ message: 'Delete {name}',
514
+ values: { name: moduleNames[index] },
515
+ }), className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md border border-red-500/20 bg-red-500/8 text-red-700 dark:text-red-300 transition-colors hover:bg-red-500/15 hover:text-red-700 dark:hover:text-red-200 disabled:opacity-30", disabled: modules.length <= 1, onClick: () => deleteModule(module), type: "button", children: _jsx(Trash, { className: "h-3.5 w-3.5" }) })] }, module.id))) }), _jsxs("div", { className: "px-1 pb-1", children: [_jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsx(ActionButton, { icon: _jsx(Plus, { className: "h-4 w-4" }), label: i18n._({ id: 'node.cabinet.runPanel.addLeft', message: 'Add left' }), onClick: () => addModule('left') }), _jsx(ActionButton, { icon: _jsx(Plus, { className: "h-4 w-4" }), label: i18n._({ id: 'node.cabinet.runPanel.addRight', message: 'Add right' }), onClick: () => addModule('right') })] }), _jsx(ActionButton, { className: "mt-2 w-full", disabled: !widthEqualization.ok || !widthEqualization.changed, icon: _jsx(EqualIcon, { className: "h-4 w-4" }), label: i18n._({
516
+ id: 'node.cabinet.runPanel.equalizeWidths',
517
+ message: 'Equalize widths',
518
+ }), onClick: equalizeWidths, title: equalizeWidthsTitle }), _jsx("p", { className: "px-1 pt-1 text-[10px] leading-4 text-muted-foreground", children: i18n._({
519
+ id: 'node.cabinet.runPanel.balancesStandardBaseCabinetsWhileKeeping',
520
+ message: 'Balances standard base cabinets while keeping appliance and corner-filler widths fixed.',
521
+ }) })] })] }), _jsx(PanelSection, { title: i18n._({
522
+ id: 'node.cabinet.runPanel.duplicateAlongRun',
523
+ message: 'Duplicate along run',
524
+ }), children: _jsxs("div", { className: "space-y-2 px-1 pb-2", children: [_jsxs("div", { className: "rounded-lg border border-border/40 bg-black/3 dark:bg-[#252527] px-2 py-2", children: [_jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: i18n._({ id: 'node.cabinet.runPanel.sourceModule', message: 'Source module' }) }), _jsx("div", { className: "truncate pt-1 text-xs font-medium text-foreground", children: arraySource?.name ||
525
+ (arraySource
526
+ ? moduleSummary(arraySource, i18n)
527
+ : i18n._({
528
+ id: 'node.cabinet.runPanel.noEligibleModule',
529
+ message: 'No eligible module',
530
+ })) })] }), _jsx(SliderControl, { label: i18n._({ id: 'node.cabinet.runPanel.copies', message: 'Copies' }), max: 20, min: 1, onChange: (value) => setArrayCopyCount(Math.round(value)), precision: 0, step: 1, value: arrayCopyCount }), _jsx(SliderControl, { label: i18n._({ id: 'node.cabinet.runPanel.spacing', message: 'Spacing' }), max: 2, min: 0, onChange: setArraySpacing, precision: 2, step: 0.01, unit: "m", value: arraySpacing }), _jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: i18n._({ id: 'node.cabinet.runPanel.direction', message: 'Direction' }) }), _jsx(SegmentedControl, { onChange: (value) => setArrayDirection(value), options: [
531
+ {
532
+ value: 'left',
533
+ label: i18n._({ id: 'node.cabinet.runPanel.left', message: 'Left' }),
534
+ },
535
+ {
536
+ value: 'right',
537
+ label: i18n._({ id: 'node.cabinet.runPanel.right', message: 'Right' }),
538
+ },
539
+ ], value: arrayDirection })] }), _jsx(ActionButton, { className: "w-full", disabled: !arrayPlan.ok, icon: _jsx(Copy, { className: "h-4 w-4" }), label: i18n._({ id: 'node.cabinet.runPanel.createArray', message: 'Create array' }), onClick: duplicateAlongRun, title: duplicateAlongRunTitle }), _jsx("p", { className: "px-1 pt-1 text-[10px] leading-4 text-muted-foreground", children: i18n._({
540
+ id: 'node.cabinet.runPanel.copiesIncludeTheSourceCabinetStructure',
541
+ message: 'Copies include the source cabinet structure and any attached wall cabinet. Existing modules stay fixed; the requested array must fit in the available run space.',
542
+ }) })] }) }), _jsx(PanelSection, { title: i18n._({
543
+ id: 'node.cabinet.runPanel.sharedPlinthCountertop',
544
+ message: 'Shared Plinth & Countertop',
545
+ }), children: _jsxs("div", { className: "space-y-2 px-1 pb-2", children: [node.runTier === 'base' && (_jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: i18n._({
546
+ id: 'node.cabinet.runPanel.standardDimensions',
547
+ message: 'Standard dimensions',
548
+ }) }), _jsx(SegmentedControl, { mixed: dimensionProfile === 'custom', onChange: (value) => applyDimensionProfile(value), options: CABINET_DIMENSION_PROFILES.map((profile) => ({
549
+ label: profile.id === 'us-base'
550
+ ? i18n._({ id: 'node.cabinet.runPanel.usProfile', message: 'US · 24 in' })
551
+ : i18n._({
552
+ id: 'node.cabinet.runPanel.metricProfile',
553
+ message: 'Metric · 600 mm',
554
+ }),
434
555
  value: profile.id,
435
- })), value: dimensionProfile === 'us-base' ? 'us-base' : 'metric-base' }), _jsx("p", { className: "px-1 pt-1 text-[10px] leading-4 text-muted-foreground", children: "Applies depth, carcass, plinth, and countertop thickness to this run." })] })), node.runTier === 'wall' && (_jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: "Height preset" }), _jsx(SegmentedControl, { mixed: wallHeightPreset === 'custom', onChange: (value) => applyWallHeightPreset(value), options: CABINET_WALL_HEIGHT_PRESETS.map((preset) => ({
556
+ })), value: dimensionProfile === 'us-base' ? 'us-base' : 'metric-base' }), _jsx("p", { className: "px-1 pt-1 text-[10px] leading-4 text-muted-foreground", children: i18n._({
557
+ id: 'node.cabinet.runPanel.appliesDepthCarcassPlinthAndCountertop',
558
+ message: 'Applies depth, carcass, plinth, and countertop thickness to this run.',
559
+ }) })] })), node.runTier === 'wall' && (_jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: i18n._({ id: 'node.cabinet.runPanel.heightPreset', message: 'Height preset' }) }), _jsx(SegmentedControl, { mixed: wallHeightPreset === 'custom', onChange: (value) => applyWallHeightPreset(value), options: CABINET_WALL_HEIGHT_PRESETS.map((preset) => ({
436
560
  label: (_jsxs("span", { className: "flex flex-col items-center leading-3", children: [_jsx("span", { children: preset.label }), _jsx("span", { className: "text-[9px] text-muted-foreground", children: preset.metricLabel })] })),
437
561
  value: preset.id,
438
- })), value: wallHeightPreset === 'custom' ? '18' : wallHeightPreset }), _jsx("p", { className: "px-1 pt-1 text-[10px] leading-4 text-muted-foreground", children: "Common wall-cabinet heights. Use the slider below for a custom height." })] })), _jsx(SliderControl, { label: "Depth", max: 1.2, min: 0.3, onChange: (value) => updateRun({ depth: value }), precision: 2, step: 0.01, unit: "m", value: node.depth }), _jsx(SliderControl, { label: "Carcass height", max: node.runTier === 'tall' ? 2.4 : 1.4, min: Math.max(0.4, ...modules.map((module) => minCabinetCarcassHeightForStack(module))), onChange: (value) => updateRun({ carcassHeight: value }), precision: 2, step: 0.01, unit: "m", value: node.carcassHeight }), _jsx(ToggleControl, { checked: node.showPlinth, label: "Show plinth", onChange: (checked) => updateRun({ showPlinth: checked }) }), node.showPlinth && (_jsx(SliderControl, { label: "Plinth height", max: 0.3, min: 0.02, onChange: (value) => updateRun({ plinthHeight: value }), precision: 2, step: 0.01, unit: "m", value: node.plinthHeight })), _jsx(ToggleControl, { checked: node.withCountertop, label: "Show countertop", onChange: (checked) => updateRun({ withCountertop: checked }) }), node.withCountertop && (_jsxs(_Fragment, { children: [_jsx(SliderControl, { label: "Countertop height", max: 0.08, min: 0.005, onChange: (value) => updateRun({ countertopThickness: value }), precision: 3, step: 0.005, unit: "m", value: node.countertopThickness }), _jsx(SliderControl, { label: "Countertop depth", max: 0.12, min: 0, onChange: (value) => updateRun({ countertopOverhang: value }), precision: 2, step: 0.005, unit: "m", value: node.countertopOverhang })] }))] }) }), _jsx(PanelSection, { title: "Island & Bar", children: _jsxs("div", { className: "space-y-2 px-1 pb-2", children: [node.withCountertop && node.barLedge?.edge !== 'back' && (_jsx(SliderControl, { label: "Seating overhang", max: 0.45, min: 0, onChange: (value) => updateRun({ countertopBackOverhang: value }), precision: 2, step: 0.05, unit: "m", value: node.countertopBackOverhang })), _jsx(ToggleControl, { checked: node.withFinishedBack, label: "Finished back", onChange: (checked) => updateRun({ withFinishedBack: checked }) }), node.withCountertop && (_jsx(ToggleControl, { checked: node.withWaterfall, label: "Waterfall ends", onChange: (checked) => updateRun({ withWaterfall: checked }) })), _jsx(ToggleControl, { checked: Boolean(node.barLedge), label: "Bar counter", onChange: (checked) => updateRun({
562
+ })), value: wallHeightPreset === 'custom' ? '18' : wallHeightPreset }), _jsx("p", { className: "px-1 pt-1 text-[10px] leading-4 text-muted-foreground", children: i18n._({
563
+ id: 'node.cabinet.runPanel.commonWallCabinetHeightsUseThe',
564
+ message: 'Common wall-cabinet heights. Use the slider below for a custom height.',
565
+ }) })] })), _jsx(SliderControl, { label: i18n._({ id: 'node.cabinet.runPanel.depth', message: 'Depth' }), max: 1.2, min: 0.3, onChange: (value) => updateRun({ depth: value }), precision: 2, step: 0.01, unit: "m", value: node.depth }), _jsx(SliderControl, { label: i18n._({ id: 'node.cabinet.runPanel.carcassHeight', message: 'Carcass height' }), max: node.runTier === 'tall' ? 2.4 : 1.4, min: Math.max(0.4, ...modules.map((module) => minCabinetCarcassHeightForStack(module))), onChange: (value) => updateRun({ carcassHeight: value }), precision: 2, step: 0.01, unit: "m", value: node.carcassHeight }), _jsx(ToggleControl, { checked: node.showPlinth, label: i18n._({ id: 'node.cabinet.runPanel.showPlinth', message: 'Show plinth' }), onChange: (checked) => updateRun({ showPlinth: checked }) }), node.showPlinth && (_jsx(SliderControl, { label: i18n._({ id: 'node.cabinet.runPanel.plinthHeight', message: 'Plinth height' }), max: 0.3, min: 0.02, onChange: (value) => updateRun({ plinthHeight: value }), precision: 2, step: 0.01, unit: "m", value: node.plinthHeight })), _jsx(ToggleControl, { checked: node.withCountertop, label: i18n._({
566
+ id: 'node.cabinet.runPanel.showCountertop',
567
+ message: 'Show countertop',
568
+ }), onChange: (checked) => updateRun({ withCountertop: checked }) }), node.withCountertop && (_jsxs(_Fragment, { children: [_jsx(SliderControl, { label: i18n._({
569
+ id: 'node.cabinet.runPanel.countertopHeight',
570
+ message: 'Countertop height',
571
+ }), max: 0.08, min: 0.005, onChange: (value) => updateRun({ countertopThickness: value }), precision: 3, step: 0.005, unit: "m", value: node.countertopThickness }), _jsx(SliderControl, { label: i18n._({
572
+ id: 'node.cabinet.runPanel.countertopDepth',
573
+ message: 'Countertop depth',
574
+ }), max: 0.12, min: 0, onChange: (value) => updateRun({ countertopOverhang: value }), precision: 2, step: 0.005, unit: "m", value: node.countertopOverhang })] }))] }) }), _jsx(PanelSection, { title: i18n._({ id: 'node.cabinet.runPanel.islandBar', message: 'Island & Bar' }), children: _jsxs("div", { className: "space-y-2 px-1 pb-2", children: [node.withCountertop && node.barLedge?.edge !== 'back' && (_jsx(SliderControl, { label: i18n._({
575
+ id: 'node.cabinet.runPanel.seatingOverhang',
576
+ message: 'Seating overhang',
577
+ }), max: 0.45, min: 0, onChange: (value) => updateRun({ countertopBackOverhang: value }), precision: 2, step: 0.05, unit: "m", value: node.countertopBackOverhang })), _jsx(ToggleControl, { checked: node.withFinishedBack, label: i18n._({ id: 'node.cabinet.runPanel.finishedBack', message: 'Finished back' }), onChange: (checked) => updateRun({ withFinishedBack: checked }) }), node.withCountertop && (_jsx(ToggleControl, { checked: node.withWaterfall, label: i18n._({
578
+ id: 'node.cabinet.runPanel.waterfallEnds',
579
+ message: 'Waterfall ends',
580
+ }), onChange: (checked) => updateRun({ withWaterfall: checked }) })), _jsx(ToggleControl, { checked: Boolean(node.barLedge), label: i18n._({ id: 'node.cabinet.runPanel.barCounter', message: 'Bar counter' }), onChange: (checked) => updateRun({
439
581
  barLedge: checked ? { edge: 'back', height: 1.06, depth: 0.35 } : undefined,
440
582
  }) }), node.barLedge && (_jsxs(_Fragment, { children: [_jsx(SegmentedControl, { onChange: (value) => updateRun({
441
583
  barLedge: { ...node.barLedge, edge: value },
442
584
  }), options: [
443
- { value: 'back', label: 'Back' },
444
- { value: 'left', label: 'Left' },
445
- { value: 'right', label: 'Right' },
446
- ], value: node.barLedge.edge }), _jsx(SliderControl, { label: "Bar height", max: 1.3, min: 0.9, onChange: (value) => updateRun({ barLedge: { ...node.barLedge, height: value } }), precision: 2, step: 0.01, unit: "m", value: node.barLedge.height }), _jsx(SliderControl, { label: "Bar depth", max: 0.5, min: 0.15, onChange: (value) => updateRun({ barLedge: { ...node.barLedge, depth: value } }), precision: 2, step: 0.01, unit: "m", value: node.barLedge.depth })] }))] }) }), _jsx(PanelSection, { title: "Fronts", children: _jsxs("div", { className: "space-y-2 px-1 pb-2", children: [_jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: "Style" }), _jsx(SegmentedControl, { onChange: (value) => updateRun({ frontStyle: value }), options: FRONT_STYLE_OPTIONS.map((option) => ({
585
+ {
586
+ value: 'back',
587
+ label: i18n._({ id: 'node.cabinet.runPanel.back', message: 'Back' }),
588
+ },
589
+ {
590
+ value: 'left',
591
+ label: i18n._({ id: 'node.cabinet.runPanel.left', message: 'Left' }),
592
+ },
593
+ {
594
+ value: 'right',
595
+ label: i18n._({ id: 'node.cabinet.runPanel.right', message: 'Right' }),
596
+ },
597
+ ], value: node.barLedge.edge }), _jsx(SliderControl, { label: i18n._({ id: 'node.cabinet.runPanel.barHeight', message: 'Bar height' }), max: 1.3, min: 0.9, onChange: (value) => updateRun({ barLedge: { ...node.barLedge, height: value } }), precision: 2, step: 0.01, unit: "m", value: node.barLedge.height }), _jsx(SliderControl, { label: i18n._({ id: 'node.cabinet.runPanel.barDepth', message: 'Bar depth' }), max: 0.5, min: 0.15, onChange: (value) => updateRun({ barLedge: { ...node.barLedge, depth: value } }), precision: 2, step: 0.01, unit: "m", value: node.barLedge.depth })] }))] }) }), _jsx(PanelSection, { title: i18n._({ id: 'node.cabinet.runPanel.fronts', message: 'Fronts' }), children: _jsxs("div", { className: "space-y-2 px-1 pb-2", children: [_jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: i18n._({ id: 'node.cabinet.runPanel.style', message: 'Style' }) }), _jsx(SegmentedControl, { onChange: (value) => updateRun({ frontStyle: value }), options: FRONT_STYLE_OPTIONS.map((option) => ({
447
598
  value: option.value,
448
- label: option.label,
449
- })), value: node.frontStyle ?? 'slab' })] }), _jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: "Mounting" }), _jsx(SegmentedControl, { onChange: (value) => updateRun({ frontOverlay: value }), options: FRONT_OVERLAY_OPTIONS.map((option) => ({
599
+ label: i18n._(option.label),
600
+ })), value: node.frontStyle ?? 'slab' })] }), _jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: i18n._({ id: 'node.cabinet.runPanel.mounting', message: 'Mounting' }) }), _jsx(SegmentedControl, { onChange: (value) => updateRun({ frontOverlay: value }), options: FRONT_OVERLAY_OPTIONS.map((option) => ({
450
601
  value: option.value,
451
- label: option.label,
452
- })), value: node.frontOverlay ?? 'full' })] }), _jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: "Reveal gap" }), _jsx(SegmentedControl, { mixed: cabinetRevealGapId(node.frontGap) === 'custom', onChange: (value) => updateRun({
602
+ label: i18n._(option.label),
603
+ })), value: node.frontOverlay ?? 'full' })] }), _jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: i18n._({ id: 'node.cabinet.runPanel.revealGap', message: 'Reveal gap' }) }), _jsx(SegmentedControl, { mixed: cabinetRevealGapId(node.frontGap) === 'custom', onChange: (value) => updateRun({
453
604
  frontGap: cabinetRevealGapById(value).value,
454
605
  }), options: CABINET_REVEAL_GAPS.map((gap) => ({
455
606
  value: gap.id,
456
607
  label: gap.label,
457
608
  })), value: cabinetRevealGapId(node.frontGap) === 'custom'
458
609
  ? '3'
459
- : cabinetRevealGapId(node.frontGap) })] })] }) }), _jsx(PanelSection, { title: "Handles", children: _jsxs("div", { className: "space-y-2 px-1 pb-2", children: [_jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: "Style" }), _jsx(SegmentedControl, { onChange: (value) => updateRun({ handleStyle: value }), options: HANDLE_STYLE_OPTIONS.map((option) => ({
610
+ : cabinetRevealGapId(node.frontGap) })] })] }) }), _jsx(PanelSection, { title: i18n._({ id: 'node.cabinet.runPanel.handles', message: 'Handles' }), children: _jsxs("div", { className: "space-y-2 px-1 pb-2", children: [_jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: i18n._({ id: 'node.cabinet.runPanel.style', message: 'Style' }) }), _jsx(SegmentedControl, { onChange: (value) => updateRun({ handleStyle: value }), options: HANDLE_STYLE_OPTIONS.map((option) => ({
460
611
  value: option.value,
461
- label: option.label,
462
- })), value: node.handleStyle })] }), (node.handleStyle === 'bar' || node.handleStyle === 'knob') && (_jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: "Position" }), _jsx(SegmentedControl, { onChange: (value) => updateRun({ handlePosition: value }), options: HANDLE_POSITION_OPTIONS.map((option) => ({
612
+ label: i18n._(option.label),
613
+ })), value: node.handleStyle })] }), (node.handleStyle === 'bar' || node.handleStyle === 'knob') && (_jsxs("div", { children: [_jsx("div", { className: "px-1 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground", children: i18n._({ id: 'node.cabinet.runPanel.position', message: 'Position' }) }), _jsx(SegmentedControl, { onChange: (value) => updateRun({ handlePosition: value }), options: HANDLE_POSITION_OPTIONS.map((option) => ({
463
614
  value: option.value,
464
- label: option.label,
615
+ label: i18n._(option.label),
465
616
  })), value: node.handlePosition ?? 'auto' })] }))] }) })] }));
466
617
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/cabinet/tool.tsx"],"names":[],"mappings":"AAmiEA,MAAM,CAAC,OAAO,UAAU,WAAW,gCAGlC"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/cabinet/tool.tsx"],"names":[],"mappings":"AAkiEA,MAAM,CAAC,OAAO,UAAU,WAAW,gCAGlC"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { CabinetModuleNode, CabinetNode, collectAlignmentAnchors, createSceneApi, emitter, getFloorPlacedFootprints, getWallLocalFaceZ, isCurvedWall, movingAlignmentAnchors, nodeRegistry, resolveAlignment, resolveSupportSlabPatch, runAsSingleSceneHistoryStep, spatialGridManager, useScene, } from '@pascal-app/core';
4
- import { clearPlacementSurface, EDITOR_LAYER, getFloorStackPreviewPosition, getSideFromNormal, isAlignmentGuideActive, isGridSnapActive, isMagneticSnapActive, isTypingTarget, isValidWallSideFace, markToolCancelConsumed, movementSfxStepKey, PlacementBox, PlacementDimensionGuides, parseMeasurement, publishPlacementSurface, triggerSFX, useAlignmentGuides, useEditor, useFacingPose, usePlacementPreview, } from '@pascal-app/editor';
3
+ import { CabinetModuleNode, CabinetNode, collectAlignmentAnchors, createSceneApi, emitter, getFloorPlacedFootprints, getWallLocalFaceZ, isCurvedWall, movingAlignmentAnchors, nodeRegistry, resolveAlignment, resolveSupportSlabPatch, runAsSingleSceneHistoryStep, spatialGridManager, useLocale, useScene, } from '@pascal-app/core';
4
+ import { clearPlacementSurface, EDITOR_LAYER, getFloorStackPreviewPosition, getSideFromNormal, isAlignmentGuideActive, isGridSnapActive, isMagneticSnapActive, isTypingTarget, isValidWallSideFace, markToolCancelConsumed, movementSfxStepKey, PlacementBox, PlacementDimensionGuides, publishPlacementSurface, triggerSFX, useAlignmentGuides, useEditor, useFacingPose, usePlacementPreview, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { Html } from '@react-three/drei';
7
7
  import { useFrame } from '@react-three/fiber';
@@ -12,6 +12,7 @@ import { LevelOffsetGroup } from '../shared/level-offset-group.js';
12
12
  import { findWallOpeningConflicts } from '../shared/wall-opening-clearance.js';
13
13
  import { cabinetStretchExitSide, chooseCabinetContinuousAnchor, createCabinetContinuousContinuation, isCabinetContinuousFollowUpClick, isForcePlacementEvent, planCabinetContinuousStretch, resolveCabinetContinuousValidity, } from './continuous-placement.js';
14
14
  import { bumpCabinetRunsNear, cabinetDefinition, cabinetModuleDefinition, cabinetRunFootprint, } from './definition.js';
15
+ import { parseCabinetDimensionInput } from './dimension-input.js';
15
16
  import { buildCabinetGeometry } from './geometry.js';
16
17
  import { applyCabinetModuleInsertion, cabinetModuleForRunInsertion } from './insertion.js';
17
18
  import { resolveCabinetNeighborPlacement } from './neighbor-placement.js';
@@ -196,6 +197,7 @@ const CabinetPlacementTool = () => {
196
197
  const activeLevelId = useViewer((s) => s.selection.levelId);
197
198
  const unit = useViewer((s) => s.unit);
198
199
  const metricNotation = useViewer((s) => s.metricNotation);
200
+ const locale = useLocale();
199
201
  const activeDimensionId = usePlacementPreview((s) => s.activeDimensionId);
200
202
  const dimensionInput = usePlacementPreview((s) => s.dimensionInput);
201
203
  const [placement, setPlacement] = useState(null);
@@ -1262,9 +1264,10 @@ const CabinetPlacementTool = () => {
1262
1264
  if (!(editor.activeDimensionId && editor.dimensionInput && current)) {
1263
1265
  return false;
1264
1266
  }
1265
- const value = parseMeasurement(editor.dimensionInput, { kind: 'length', unitId: 'm' }, {
1266
- bareUnit: unit === 'imperial' ? 'in' : metricNotation === 'millimeters' ? 'mm' : 'm',
1267
- system: unit === 'imperial' ? 'imperial' : 'metric',
1267
+ const value = parseCabinetDimensionInput(editor.dimensionInput, {
1268
+ locale,
1269
+ metricNotation,
1270
+ unit,
1268
1271
  });
1269
1272
  if (value === null)
1270
1273
  return false;
@@ -0,0 +1,7 @@
1
+ import { type CeilingNode } from '@pascal-app/core';
2
+ export declare function CeilingBuildUpSection({ node, onUpdate, unit, }: {
3
+ node: CeilingNode;
4
+ onUpdate: (patch: Partial<CeilingNode>) => void;
5
+ unit: 'metric' | 'imperial';
6
+ }): import("react").JSX.Element;
7
+ //# sourceMappingURL=build-up-section.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-up-section.d.ts","sourceRoot":"","sources":["../../src/ceiling/build-up-section.tsx"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,WAAW,EAKjB,MAAM,kBAAkB,CAAA;AA8CzB,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,QAAQ,EACR,IAAI,GACL,EAAE;IACD,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAA;IAC/C,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAA;CAC5B,+BAqFA"}
@@ -0,0 +1,57 @@
1
+ 'use client';
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { ceilingBuildUpThickness, LUMBER_DEPTH, usePascalI18n, } from '@pascal-app/core';
4
+ import { PanelSection, SelectControl } from '@pascal-app/editor';
5
+ import { BuildUpReadout, editedBuildUp, FinishFields, FramingSizeFields, InsulationFields, NONE, PanelFields, } from '../shared/build-up-controls.js';
6
+ import { formatLayerDepth } from '../shared/layer-thickness.js';
7
+ import { ceilingBuildUpPresetOptions, ceilingBuildUpPresetPatch, ceilingBuildUpPresetValue, } from './panel-model.js';
8
+ const INCH = 0.0254;
9
+ const FRAMING_OPTIONS = [
10
+ { label: /* i18n */ { id: 'node.ceiling.buildUpSection.none', message: 'None' }, value: NONE },
11
+ {
12
+ label: /* i18n */ {
13
+ id: 'node.ceiling.buildUpSection.ceilingJoists',
14
+ message: 'Ceiling joists',
15
+ },
16
+ value: 'joists',
17
+ },
18
+ {
19
+ label: /* i18n */ {
20
+ id: 'node.ceiling.buildUpSection.trussBottomChords',
21
+ message: 'Truss bottom chords',
22
+ },
23
+ value: 'truss-chords',
24
+ },
25
+ ];
26
+ const NEW_FRAMING = {
27
+ joists: { system: 'joists', size: '2x6', spacing: 16 * INCH },
28
+ 'truss-chords': { system: 'truss-chords', size: '2x4', spacing: 24 * INCH },
29
+ };
30
+ export function CeilingBuildUpSection({ node, onUpdate, unit, }) {
31
+ const i18n = usePascalI18n();
32
+ const buildUp = node.buildUp;
33
+ const edit = (change) => {
34
+ if (buildUp)
35
+ onUpdate({ buildUp: editedBuildUp(buildUp, change) });
36
+ };
37
+ const framing = buildUp?.framing;
38
+ return (_jsxs(PanelSection, { title: i18n._({ id: 'node.ceiling.buildUpSection.layers', message: 'Layers' }), children: [_jsx(SelectControl, { label: i18n._({ id: 'node.ceiling.buildUpSection.preset', message: 'Preset' }), onChange: (id) => {
39
+ const patch = ceilingBuildUpPresetPatch(id);
40
+ if (patch)
41
+ onUpdate(patch);
42
+ }, options: ceilingBuildUpPresetOptions(ceilingBuildUpPresetValue(buildUp)), value: ceilingBuildUpPresetValue(buildUp) }), buildUp && (_jsxs(_Fragment, { children: [_jsx(FinishFields, { label: i18n._({ id: 'node.ceiling.buildUpSection.finish', message: 'Finish' }), layer: buildUp.finish, onChange: (finish) => edit({ finish }), unit: unit }), _jsx(SelectControl, { label: i18n._({ id: 'node.ceiling.buildUpSection.framing', message: 'Framing' }), onChange: (system) => edit({
43
+ framing: system === NONE
44
+ ? undefined
45
+ : framing
46
+ ? { ...framing, system }
47
+ : NEW_FRAMING[system],
48
+ }), options: FRAMING_OPTIONS.map((option) => ({ ...option, label: i18n._(option.label) })), value: framing?.system ?? NONE }), framing && (_jsx(FramingSizeFields, { framing: framing, onChange: (change) => edit({ framing: { ...framing, ...change } }), sizeLabel: framing.system === 'joists'
49
+ ? i18n._({ id: 'node.ceiling.buildUpSection.joists', message: 'Joists' })
50
+ : i18n._({
51
+ id: 'node.ceiling.buildUpSection.bottomChord',
52
+ message: 'Bottom chord',
53
+ }), unit: unit })), _jsx(PanelFields, { added: 0.75 * INCH, label: i18n._({ id: 'node.ceiling.buildUpSection.decking', message: 'Decking' }), layer: buildUp.decking, onChange: (decking) => edit({ decking }), optional: true, unit: unit }), _jsx(InsulationFields, { framingDepth: LUMBER_DEPTH[framing?.size ?? '2x4'], layer: buildUp.insulation, onChange: (insulation) => edit({ insulation }), unit: unit }), _jsx(BuildUpReadout, { label: i18n._({ id: 'node.ceiling.buildUpSection.thickness', message: 'Thickness' }), value: formatLayerDepth(ceilingBuildUpThickness(buildUp), unit) }), _jsx("div", { className: "px-1 text-[11px] text-muted-foreground", children: i18n._({
54
+ id: 'node.ceiling.buildUpSection.theHeightIsTheFinishedUnderside',
55
+ message: 'The height is the finished underside; the layers rise from it.',
56
+ }) })] }))] }));
57
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/ceiling/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EAIpB,MAAM,kBAAkB,CAAA;AAuBzB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AA+EtC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,EAAE,cAAc,CAAC,OAAO,WAAW,CAyHhE,CAAA"}
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/ceiling/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EAIpB,MAAM,kBAAkB,CAAA;AAyBzB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AA+EtC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,EAAE,cAAc,CAAC,OAAO,WAAW,CA0HhE,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { ceilingSlots, resolveCeilingHeight, useScene, } from '@pascal-app/core';
2
- import { clearStructuralElevationGuide, DRAFTING_SURFACE_EXTENSION_KEY, publishStructuralElevationGuide, resolveStructuralElevationSnap, } from '@pascal-app/editor';
2
+ import { clearStructuralElevationGuide, DRAFTING_SURFACE_EXTENSION_KEY, PANEL_MODEL_EXTENSION, publishStructuralElevationGuide, resolveStructuralElevationSnap, } from '@pascal-app/editor';
3
3
  import { surfaceBatchable } from '../shared/node-batch/batchable.js';
4
4
  import { polygonMeasurementFeatures } from '../shared/polygon-measurement.js';
5
5
  import { sameOutlineSurfaceCounterparts } from '../shared/surface-counterparts.js';
@@ -8,6 +8,7 @@ import { ceilingAddVertexAffordance, ceilingDeleteVertexAffordance, ceilingMoveE
8
8
  import { ceilingFloorplanMoveTarget } from './floorplan-move.js';
9
9
  import { CEILING_HANDLE_MIN_HEIGHT, ceilingHeightRange } from './height-bounds.js';
10
10
  import { ceilingPaint } from './paint.js';
11
+ import { ceilingPanelModel } from './panel-model.js';
11
12
  import { ceilingParametrics } from './parametrics.js';
12
13
  import { CeilingNode } from './schema.js';
13
14
  const HEIGHT_HANDLE_OFFSET = 0.22;
@@ -107,6 +108,7 @@ export const ceilingDefinition = {
107
108
  'pascal:editor/floorplan': {
108
109
  selectionCounterparts: sameOutlineSurfaceCounterparts,
109
110
  },
111
+ [PANEL_MODEL_EXTENSION]: ceilingPanelModel,
110
112
  },
111
113
  // Height-less on purpose: a new ceiling follows the level top until the
112
114
  // user gives it an explicit custom height.