@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 +1 @@
1
- {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/slab/panel.tsx"],"names":[],"mappings":"AAwCA;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,uCA0cxB;eAEc,SAAS"}
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/slab/panel.tsx"],"names":[],"mappings":"AA+CA;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,uCA8hBxB;eA0Bc,SAAS"}
@@ -1,7 +1,8 @@
1
1
  'use client';
2
2
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { isDerivedNode, MIN_SLAB_THICKNESS, useScene, } from '@pascal-app/core';
4
- import { ActionButton, ActionGroup, FloorFoundationPanel, holeEditScope, PanelSection, PanelWrapper, SegmentedControl, ShapeChoice, SliderControl, startOpeningDraft, triggerSFX, useEditingHole, useEditor, useInteractionScope, } from '@pascal-app/editor';
3
+ import { formatFixed, isDerivedNode, MIN_SLAB_THICKNESS, usePascalI18n, useScene, } from '@pascal-app/core';
4
+ import { setSlabSurfaceScript } from '@pascal-app/core/agent-operations';
5
+ import { ActionButton, ActionGroup, FloorFoundationPanel, formatAreaLabel, getAreaUnitLabel, holeEditScope, PanelSection, PanelWrapper, ScriptedFinishRow, SegmentedControl, ShapeChoice, SliderControl, squareMetersToAreaUnit, startOpeningDraft, triggerSFX, useEditingHole, useEditor, useInteractionScope, } from '@pascal-app/editor';
5
6
  import { useViewer } from '@pascal-app/viewer';
6
7
  import { Edit, Move, Plus, Trash2 } from 'lucide-react';
7
8
  import { useCallback, useEffect, useRef } from 'react';
@@ -18,6 +19,7 @@ import { applySlabAnchorElevationChange, applySlabElevationPreset, applySlabRece
18
19
  * into `parametrics.groups`.
19
20
  */
20
21
  export function SlabPanel() {
22
+ const i18n = usePascalI18n();
21
23
  const selectedId = useViewer((s) => s.selection.selectedIds[0]);
22
24
  const unit = useViewer((s) => s.unit);
23
25
  const setSelection = useViewer((s) => s.setSelection);
@@ -202,21 +204,61 @@ export function SlabPanel() {
202
204
  // for whole-inch offsets.
203
205
  const elevationPresets = unit === 'imperial'
204
206
  ? [
205
- { label: 'Sunken (6")', elevation: -0.1524 },
206
- { label: 'Thin (1")', elevation: 0.0254 },
207
- { label: 'Standard (2")', elevation: 0.0508 },
208
- { label: 'Thick (6")', elevation: 0.1524 },
207
+ {
208
+ label: i18n._({ id: 'node.slab.panel.sunken6', message: 'Sunken (6")' }),
209
+ elevation: -0.1524,
210
+ },
211
+ {
212
+ label: i18n._({ id: 'node.slab.panel.thin1', message: 'Thin (1")' }),
213
+ elevation: 0.0254,
214
+ },
215
+ {
216
+ label: i18n._({ id: 'node.slab.panel.standard2', message: 'Standard (2")' }),
217
+ elevation: 0.0508,
218
+ },
219
+ {
220
+ label: i18n._({ id: 'node.slab.panel.thick6', message: 'Thick (6")' }),
221
+ elevation: 0.1524,
222
+ },
209
223
  ]
210
224
  : [
211
- { label: 'Sunken (15cm)', elevation: -0.15 },
212
- { label: 'Thin (2cm)', elevation: 0.02 },
213
- { label: 'Standard (5cm)', elevation: 0.05 },
214
- { label: 'Thick (15cm)', elevation: 0.15 },
225
+ {
226
+ label: i18n._({ id: 'node.slab.panel.sunken15cm', message: 'Sunken (15cm)' }),
227
+ elevation: -0.15,
228
+ },
229
+ {
230
+ label: i18n._({ id: 'node.slab.panel.thin2cm', message: 'Thin (2cm)' }),
231
+ elevation: 0.02,
232
+ },
233
+ {
234
+ label: i18n._({ id: 'node.slab.panel.standard5cm', message: 'Standard (5cm)' }),
235
+ elevation: 0.05,
236
+ },
237
+ {
238
+ label: i18n._({ id: 'node.slab.panel.thick15cm', message: 'Thick (15cm)' }),
239
+ elevation: 0.15,
240
+ },
215
241
  ];
216
- return (_jsxs(PanelWrapper, { icon: "/icons/floor.webp", onClose: handleClose, title: node.name || 'Slab', width: 320, children: [_jsxs(PanelSection, { title: "Elevation", children: [_jsx(SliderControl, { label: node.recessed ? 'Floor' : 'Surface', max: 20, min: -3, onChange: handleElevationChange, precision: 3, step: 0.01, unit: "m", value: node.elevation }), _jsx(SliderControl, { label: node.recessed ? 'Rim' : 'Base', max: 20, min: -3, onChange: handleAnchorChange, precision: 3, step: 0.01, unit: "m", value: getSlabAnchorElevation(node) }), node.recessed ? (_jsx(SliderControl, { label: "Depth", max: 1000, min: MIN_SLAB_THICKNESS, onChange: handleRecessDepthChange, precision: 2, step: 0.01, unit: "m", value: getSlabRecessDepth(node) })) : (_jsx(SliderControl, { label: "Thickness", max: 1000, min: MIN_SLAB_THICKNESS, onChange: handleThicknessChange, precision: 2, step: 0.01, unit: "m", value: node.thickness ?? 0.05 })), !node.recessed && (_jsxs(_Fragment, { children: [_jsx("div", { className: "px-1 font-medium text-[10px] text-muted-foreground/80 uppercase tracking-wider", children: "Foundation" }), _jsx(SegmentedControl, { onChange: handleTerrainModeChange, options: [
217
- { label: 'Fixed', value: 'fixed' },
218
- { label: 'Follows terrain', value: 'terrain' },
219
- ], value: node.fillToTerrain ? 'terrain' : 'fixed' }), node.fillToTerrain && (_jsx("div", { className: "px-1 text-[11px] text-muted-foreground", children: "Extends the perimeter down to terrain. The flat surface, base, and thickness stay unchanged." }))] })), _jsx("div", { className: "mt-2 grid grid-cols-2 gap-1.5 px-1 pb-1", children: elevationPresets.map((preset) => (_jsx(ActionButton, { label: preset.label, onClick: () => handleElevationPreset(preset.elevation) }, preset.label))) })] }), _jsx(PanelSection, { title: "Info", children: _jsxs("div", { className: "flex items-center justify-between px-2 py-1 text-muted-foreground text-sm", children: [_jsx("span", { children: "Area" }), _jsxs("span", { className: "font-mono text-foreground dark:text-white", children: [area.toFixed(2), " m\u00B2"] })] }) }), _jsxs(PanelSection, { title: "Holes", children: [node.holes && node.holes.length > 0 ? (_jsx("div", { className: "flex flex-col gap-1 pb-2", children: node.holes.map((hole, index) => {
242
+ return (_jsxs(PanelWrapper, { icon: "/icons/floor.webp", onClose: handleClose, title: node.name || i18n._({ id: 'node.slab.panel.slab', message: 'Slab' }), width: 320, children: [_jsxs(PanelSection, { title: i18n._({ id: 'node.slab.panel.elevation', message: 'Elevation' }), children: [_jsx(SliderControl, { label: node.recessed
243
+ ? i18n._({ id: 'node.slab.panel.floor', message: 'Floor' })
244
+ : i18n._({ id: 'node.slab.panel.surface', message: 'Surface' }), max: 20, min: -3, onChange: handleElevationChange, precision: 3, step: 0.01, unit: "m", value: node.elevation }), _jsx(SliderControl, { label: node.recessed
245
+ ? i18n._({ id: 'node.slab.panel.rim', message: 'Rim' })
246
+ : i18n._({ id: 'node.slab.panel.base', message: 'Base' }), max: 20, min: -3, onChange: handleAnchorChange, precision: 3, step: 0.01, unit: "m", value: getSlabAnchorElevation(node) }), node.recessed ? (_jsx(SliderControl, { label: i18n._({ id: 'node.slab.panel.depth', message: 'Depth' }), max: 1000, min: MIN_SLAB_THICKNESS, onChange: handleRecessDepthChange, precision: 2, step: 0.01, unit: "m", value: getSlabRecessDepth(node) })) : (_jsx(SliderControl, { label: i18n._({ id: 'node.slab.panel.thickness', message: 'Thickness' }), max: 1000, min: MIN_SLAB_THICKNESS, onChange: handleThicknessChange, precision: 2, step: 0.01, unit: "m", value: node.thickness ?? 0.05 })), !node.recessed && (_jsxs(_Fragment, { children: [_jsx("div", { className: "px-1 font-medium text-[10px] text-muted-foreground/80 uppercase tracking-wider", children: i18n._({ id: 'node.slab.panel.foundation', message: 'Foundation' }) }), _jsx(SegmentedControl, { onChange: handleTerrainModeChange, options: [
247
+ {
248
+ label: i18n._({ id: 'node.slab.panel.fixed', message: 'Fixed' }),
249
+ value: 'fixed',
250
+ },
251
+ {
252
+ label: i18n._({
253
+ id: 'node.slab.panel.followsTerrain',
254
+ message: 'Follows terrain',
255
+ }),
256
+ value: 'terrain',
257
+ },
258
+ ], value: node.fillToTerrain ? 'terrain' : 'fixed' }), node.fillToTerrain && (_jsx("div", { className: "px-1 text-[11px] text-muted-foreground", children: i18n._({
259
+ id: 'node.slab.panel.extendsThePerimeterDownToTerrain',
260
+ message: 'Extends the perimeter down to terrain. The flat surface, base, and thickness stay unchanged.',
261
+ }) }))] })), _jsx("div", { className: "mt-2 grid grid-cols-2 gap-1.5 px-1 pb-1", children: elevationPresets.map((preset) => (_jsx(ActionButton, { label: preset.label, onClick: () => handleElevationPreset(preset.elevation) }, preset.label))) })] }), _jsx(PanelSection, { title: i18n._({ id: 'node.slab.panel.info', message: 'Info' }), children: _jsxs("div", { className: "flex items-center justify-between px-2 py-1 text-muted-foreground text-sm", children: [_jsx("span", { children: i18n._({ id: 'node.slab.panel.area', message: 'Area' }) }), _jsx("span", { className: "font-mono text-foreground dark:text-white", children: formatAreaLabel(area, unit, 2) })] }) }), _jsxs(PanelSection, { title: i18n._({ id: 'node.slab.panel.holes', message: 'Holes' }), children: [node.holes && node.holes.length > 0 ? (_jsx("div", { className: "flex flex-col gap-1 pb-2", children: node.holes.map((hole, index) => {
220
262
  const holeArea = calculateArea(hole);
221
263
  const isEditing = editingHole?.nodeId === selectedId && editingHole?.holeIndex === index;
222
264
  const source = node.holeMetadata?.[index]?.source ?? 'manual';
@@ -225,17 +267,51 @@ export function SlabPanel() {
225
267
  const openingId = derived ? node.holeMetadata?.[index]?.openingId : undefined;
226
268
  const isAutoHole = source !== 'manual' || derived;
227
269
  const autoLabel = source === 'elevator'
228
- ? 'Auto elevator cutout'
270
+ ? i18n._({ id: 'node.cutout.autoElevator', message: 'Auto elevator cutout' })
229
271
  : source === 'stair'
230
- ? 'Auto stair cutout'
272
+ ? i18n._({ id: 'node.cutout.autoStair', message: 'Auto stair cutout' })
231
273
  : source === 'floor-opening'
232
- ? 'Opening'
233
- : 'Room cutout';
274
+ ? i18n._({ id: 'node.cutout.opening', message: 'Opening' })
275
+ : i18n._({ id: 'node.cutout.room', message: 'Room cutout' });
234
276
  return (_jsxs("div", { className: `flex items-center justify-between rounded-lg border p-2 transition-colors ${isEditing
235
277
  ? 'border-primary/50 bg-primary/10'
236
- : 'border-transparent hover:bg-accent/30'}`, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("p", { className: `font-medium text-xs ${isEditing ? 'text-primary' : 'text-foreground dark:text-white'}`, children: ["Hole ", index + 1, " ", isEditing && '(Editing)'] }), _jsxs("p", { className: "text-[10px] text-muted-foreground", children: [holeArea.toFixed(2), " m\u00B2 \u00B7 ", hole.length, " pts \u00B7", ' ', isAutoHole ? autoLabel : 'Manual'] })] }), _jsx("div", { className: "flex items-center gap-1", children: isEditing ? (_jsx(ActionButton, { className: "h-7 bg-primary text-primary-foreground hover:bg-primary/90", label: "Done", onClick: () => useInteractionScope
278
+ : 'border-transparent hover:bg-accent/30'}`, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: `font-medium text-xs ${isEditing ? 'text-primary' : 'text-foreground dark:text-white'}`, children: isEditing
279
+ ? i18n._({
280
+ id: 'node.holeEditing',
281
+ message: 'Hole {number} (Editing)',
282
+ values: { number: index + 1 },
283
+ })
284
+ : i18n._({
285
+ id: 'node.holeNumber',
286
+ message: 'Hole {number}',
287
+ values: { number: index + 1 },
288
+ }) }), _jsx("p", { className: "text-[10px] text-muted-foreground", children: i18n._({
289
+ id: 'node.holeSummary',
290
+ message: '{area} {unit} · {count, plural, one {{points} pt} other {{points} pts}} · {source}',
291
+ values: {
292
+ area: formatFixed(squareMetersToAreaUnit(holeArea, unit), 2, i18n.getLocale()),
293
+ unit: getAreaUnitLabel(unit),
294
+ count: hole.length,
295
+ points: String(hole.length),
296
+ source: isAutoHole
297
+ ? autoLabel
298
+ : i18n._({ id: 'node.hole.manual', message: 'Manual' }),
299
+ },
300
+ }) })] }), _jsx("div", { className: "flex items-center gap-1", children: isEditing ? (_jsx(ActionButton, { className: "h-7 bg-primary text-primary-foreground hover:bg-primary/90", label: i18n._({ id: 'node.slab.panel.done', message: 'Done' }), onClick: () => useInteractionScope
237
301
  .getState()
238
- .endIf((scope) => scope.kind === 'reshaping' && scope.reshape === 'hole') })) : openingId ? (_jsx("button", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-black/4 dark:bg-[#2C2C2E] text-muted-foreground hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground", "data-slab-hole-opening": openingId, onClick: () => setSelection({ selectedIds: [openingId] }), type: "button", children: _jsx(Edit, { className: "h-3.5 w-3.5" }) })) : isAutoHole ? (_jsx("div", { className: "rounded-md bg-black/4 dark:bg-[#2C2C2E] px-2 py-1 text-[10px] text-muted-foreground", children: "Auto" })) : (_jsxs(_Fragment, { children: [_jsx("button", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-black/4 dark:bg-[#2C2C2E] text-muted-foreground hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground", onClick: () => handleEditHole(index), type: "button", children: _jsx(Edit, { className: "h-3.5 w-3.5" }) }), _jsx("button", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-red-500/10 text-red-600 dark:text-red-400 hover:bg-red-500/20 hover:text-red-700 dark:hover:text-red-300", onClick: () => handleDeleteHole(index), type: "button", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) })] })) })] }, index));
239
- }) })) : (_jsx("div", { className: "px-2 py-3 text-center text-muted-foreground text-xs", children: "No holes" })), _jsx("div", { className: "px-1 pt-1 pb-1", children: derived ? (_jsx(ShapeChoice, { className: "px-1 text-muted-foreground text-xs", disabled: !openingZoneId, label: node.support === 'open' ? 'Cut hatch' : 'Cut opening', onPick: (shape) => openingZoneId && startOpeningDraft(openingZoneId, 'floor', shape) })) : (_jsx(ActionButton, { className: "w-full", disabled: editingHole?.nodeId === selectedId, icon: _jsx(Plus, { className: "h-3.5 w-3.5" }), label: "Add Hole", onClick: handleAddHole })) })] }), _jsx(ActionGroup, { children: _jsx(ActionButton, { icon: _jsx(Move, { className: "h-3.5 w-3.5" }), label: "Move", onClick: handleMove }) })] }));
302
+ .endIf((scope) => scope.kind === 'reshaping' && scope.reshape === 'hole') })) : openingId ? (_jsx("button", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-black/4 dark:bg-[#2C2C2E] text-muted-foreground hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground", "data-slab-hole-opening": openingId, onClick: () => setSelection({ selectedIds: [openingId] }), type: "button", children: _jsx(Edit, { className: "h-3.5 w-3.5" }) })) : isAutoHole ? (_jsx("div", { className: "rounded-md bg-black/4 dark:bg-[#2C2C2E] px-2 py-1 text-[10px] text-muted-foreground", children: i18n._({ id: 'node.slab.panel.auto', message: 'Auto' }) })) : (_jsxs(_Fragment, { children: [_jsx("button", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-black/4 dark:bg-[#2C2C2E] text-muted-foreground hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground", onClick: () => handleEditHole(index), type: "button", children: _jsx(Edit, { className: "h-3.5 w-3.5" }) }), _jsx("button", { className: "flex h-7 w-7 items-center justify-center rounded-md bg-red-500/10 text-red-600 dark:text-red-400 hover:bg-red-500/20 hover:text-red-700 dark:hover:text-red-300", onClick: () => handleDeleteHole(index), type: "button", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) })] })) })] }, index));
303
+ }) })) : (_jsx("div", { className: "px-2 py-3 text-center text-muted-foreground text-xs", children: i18n._({ id: 'node.slab.panel.noHoles', message: 'No holes' }) })), _jsx("div", { className: "px-1 pt-1 pb-1", children: derived ? (_jsx(ShapeChoice, { className: "px-1 text-muted-foreground text-xs", disabled: !openingZoneId, label: node.support === 'open'
304
+ ? i18n._({ id: 'node.slab.panel.cutHatch', message: 'Cut hatch' })
305
+ : i18n._({ id: 'node.slab.panel.cutOpening', message: 'Cut opening' }), onPick: (shape) => openingZoneId && startOpeningDraft(openingZoneId, 'floor', shape) })) : (_jsx(ActionButton, { className: "w-full", disabled: editingHole?.nodeId === selectedId, icon: _jsx(Plus, { className: "h-3.5 w-3.5" }), label: i18n._({ id: 'node.slab.panel.addHole', message: 'Add Hole' }), onClick: handleAddHole })) })] }), _jsx(SlabSurfaceScriptRow, { slabId: node.id }), _jsx(ActionGroup, { children: _jsx(ActionButton, { icon: _jsx(Move, { className: "h-3.5 w-3.5" }), label: i18n._({ id: 'node.slab.panel.move', message: 'Move' }), onClick: handleMove }) })] }));
306
+ }
307
+ /** The slab's surface a script builds, with its code to read and a way to take it off. */
308
+ function SlabSurfaceScriptRow({ slabId }) {
309
+ const sha = useScene((scene) => {
310
+ const slab = scene.nodes[slabId];
311
+ return slab?.type === 'slab' ? slab.surfaceScript?.script : undefined;
312
+ });
313
+ if (!sha)
314
+ return null;
315
+ return (_jsx("div", { className: "border-border/50 border-b px-3 pb-3", children: _jsx(ScriptedFinishRow, { "data-slab-surface-script": slabId, remove: () => setSlabSurfaceScript(useScene.getState().nodes, { slabId, remove: true }, { activeLevelId: null }).changes, sha: sha }) }));
240
316
  }
241
317
  export default SlabPanel;
@@ -0,0 +1,11 @@
1
+ import { type SlabNode } from '@pascal-app/core';
2
+ /**
3
+ * The slab its geometry builds, and its surface script's build beside it rather than inside: the
4
+ * slab's group is rebuilt by its geometry and packed into the level's surface batch, which would
5
+ * freeze or drop a model loaded into it.
6
+ */
7
+ declare const SlabRenderer: ({ node }: {
8
+ node: SlabNode;
9
+ }) => import("react").JSX.Element;
10
+ export default SlabRenderer;
11
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/slab/renderer.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,QAAQ,EAId,MAAM,kBAAkB,CAAA;AAIzB;;;;GAIG;AACH,QAAA,MAAM,YAAY,aAAc;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,gCAKjD,CAAA;eAac,YAAY"}
@@ -0,0 +1,19 @@
1
+ 'use client';
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { FLOOR_SCRIPT_LIFT, slabScriptSurface, useScene, } from '@pascal-app/core';
4
+ import { ParametricNodeRenderer } from '@pascal-app/viewer';
5
+ import { FinishScriptModel } from '../shared/finish-script-model.js';
6
+ /**
7
+ * The slab its geometry builds, and its surface script's build beside it rather than inside: the
8
+ * slab's group is rebuilt by its geometry and packed into the level's surface batch, which would
9
+ * freeze or drop a model loaded into it.
10
+ */
11
+ const SlabRenderer = ({ node }) => (_jsxs(_Fragment, { children: [_jsx(ParametricNodeRenderer, { node: node }), node.surfaceScript ? _jsx(SlabSurfaceScriptModel, { node: node, script: node.surfaceScript }) : null] }));
12
+ /** The slab's surface finish its script built: in the level's plan, its y = 0 on the slab's top. */
13
+ function SlabSurfaceScriptModel({ node, script }) {
14
+ const surface = useScene((state) => slabScriptSurface(state.nodes, node.id));
15
+ if (surface === null)
16
+ return null;
17
+ return (_jsx("group", { "position-y": surface + FLOOR_SCRIPT_LIFT, visible: node.visible !== false, children: _jsx(FinishScriptModel, { ownerId: node.id, parentId: node.parentId, script: script }) }));
18
+ }
19
+ export default SlabRenderer;
@@ -1 +1 @@
1
- {"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../src/slab/system.tsx"],"names":[],"mappings":"AAMA,QAAA,MAAM,WAAW,YAUhB,CAAA;eAEc,WAAW"}
1
+ {"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../src/slab/system.tsx"],"names":[],"mappings":"AAOA,QAAA,MAAM,WAAW,YAwBhB,CAAA;eAEc,WAAW"}
@@ -1,5 +1,6 @@
1
1
  'use client';
2
- import { useScene } from '@pascal-app/core';
2
+ import { isDeckSlab, useScene } from '@pascal-app/core';
3
+ import { useViewer } from '@pascal-app/viewer';
3
4
  import { useEffect } from 'react';
4
5
  import { createSlabDependencyTracker } from './dependency-tracker.js';
5
6
  const SlabSystems = () => {
@@ -12,6 +13,16 @@ const SlabSystems = () => {
12
13
  state.markDirty(id);
13
14
  });
14
15
  }, []);
16
+ // "Framing only" hides the shell, a deck's boards and frame with it, and draws the frame on its
17
+ // own: a deck rebuilds when it flips, so no batched copy of it stays drawn over the frame.
18
+ useEffect(() => useViewer.subscribe((state, previous) => {
19
+ if (state.framingOnly === previous.framingOnly)
20
+ return;
21
+ const scene = useScene.getState();
22
+ for (const node of Object.values(scene.nodes))
23
+ if (node.type === 'slab' && isDeckSlab(node, (id) => scene.nodes[id]))
24
+ scene.markDirty(node.id);
25
+ }), []);
15
26
  return null;
16
27
  };
17
28
  export default SlabSystems;
@@ -1 +1 @@
1
- {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/solar-panel/panel.tsx"],"names":[],"mappings":"AAyDA,MAAM,CAAC,OAAO,UAAU,eAAe,uCAqUtC"}
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/solar-panel/panel.tsx"],"names":[],"mappings":"AA2EA,MAAM,CAAC,OAAO,UAAU,eAAe,uCAoWtC"}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { SOLAR_PANEL_PRESET_LABELS, SOLAR_PANEL_PRESETS, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
3
+ import { formatFixed, SOLAR_PANEL_PRESETS, useLiveNodeOverrides, usePascalI18n, useScene, } from '@pascal-app/core';
4
4
  import { ActionButton, ActionGroup, PanelSection, PanelWrapper, SegmentedControl, SliderControl, triggerSFX, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { LayoutGrid, Trash2 } from 'lucide-react';
@@ -15,11 +15,27 @@ const PRESET_OWNED_FIELDS = [
15
15
  'frameThickness',
16
16
  'frameDepth',
17
17
  ];
18
+ // Preset names in the UI language; core's `SOLAR_PANEL_PRESET_LABELS` stay English.
18
19
  const PRESET_CARDS = [
19
- { key: 'residential', label: SOLAR_PANEL_PRESET_LABELS.residential },
20
- { key: 'residential-large', label: SOLAR_PANEL_PRESET_LABELS['residential-large'] },
21
- { key: 'compact', label: SOLAR_PANEL_PRESET_LABELS.compact },
22
- { key: 'frameless', label: SOLAR_PANEL_PRESET_LABELS.frameless },
20
+ {
21
+ key: 'residential',
22
+ label: /* i18n */ { id: 'node.solarPanel.preset.residential', message: 'Residential' },
23
+ },
24
+ {
25
+ key: 'residential-large',
26
+ label: /* i18n */ {
27
+ id: 'node.solarPanel.preset.residentialLarge',
28
+ message: 'Residential Large',
29
+ },
30
+ },
31
+ {
32
+ key: 'compact',
33
+ label: /* i18n */ { id: 'node.solarPanel.preset.compact', message: 'Compact' },
34
+ },
35
+ {
36
+ key: 'frameless',
37
+ label: /* i18n */ { id: 'node.solarPanel.preset.frameless', message: 'Frameless' },
38
+ },
23
39
  ];
24
40
  function dimsTouchedByUpdate(updates) {
25
41
  for (const field of PRESET_OWNED_FIELDS) {
@@ -32,6 +48,7 @@ function num(value, fallback) {
32
48
  return typeof value === 'number' && Number.isFinite(value) ? value : fallback;
33
49
  }
34
50
  export default function SolarPanelPanel() {
51
+ const i18n = usePascalI18n();
35
52
  const selectedId = useViewer((s) => s.selection.selectedIds[0]);
36
53
  const setSelection = useViewer((s) => s.setSelection);
37
54
  const updateNode = useScene((s) => s.updateNode);
@@ -100,12 +117,15 @@ export default function SolarPanelPanel() {
100
117
  return;
101
118
  const fit = computeAutoFit(segment, node);
102
119
  if (!fit) {
103
- setAutoFitMessage('Setbacks too large to fit a panel.');
120
+ setAutoFitMessage(i18n._({
121
+ id: 'node.solarPanel.panel.setbacksTooLarge',
122
+ message: 'Setbacks too large to fit a panel.',
123
+ }));
104
124
  return;
105
125
  }
106
126
  updateNode(selectedId, { rows: fit.rows, columns: fit.columns });
107
127
  setAutoFitMessage(null);
108
- }, [selectedId, node, segment, updateNode]);
128
+ }, [selectedId, node, segment, updateNode, i18n]);
109
129
  const handleDelete = useCallback(() => {
110
130
  if (!(selectedId && node))
111
131
  return;
@@ -132,15 +152,30 @@ export default function SolarPanelPanel() {
132
152
  if (!(node && node.type === 'solar-panel' && selectedId))
133
153
  return null;
134
154
  const activePreset = node.panelTypePreset;
135
- const formatDims = (w, h) => `${w.toFixed(2)} × ${h.toFixed(2)} m`;
136
- return (_jsxs(PanelWrapper, { icon: "/icons/roof.webp", onBack: node.roofSegmentId ? handleBack : undefined, onClose: handleClose, title: node.name || 'Solar Panel', width: 300, children: [_jsxs(PanelSection, { title: "Preset", children: [_jsx("div", { className: "grid grid-cols-2 gap-1.5 px-1 pt-1", children: PRESET_CARDS.map((card) => {
155
+ const formatDims = (w, h) => `${formatFixed(w, 2, i18n.getLocale())} × ${formatFixed(h, 2, i18n.getLocale())} m`;
156
+ return (_jsxs(PanelWrapper, { icon: "/icons/roof.webp", onBack: node.roofSegmentId ? handleBack : undefined, onClose: handleClose, title: node.name || i18n._({ id: 'node.solarPanel.panel.solarPanel', message: 'Solar Panel' }), width: 300, children: [_jsxs(PanelSection, { title: i18n._({ id: 'node.solarPanel.panel.preset', message: 'Preset' }), children: [_jsx("div", { className: "grid grid-cols-2 gap-1.5 px-1 pt-1", children: PRESET_CARDS.map((card) => {
137
157
  const dims = SOLAR_PANEL_PRESETS[card.key];
138
158
  const isSelected = activePreset === card.key;
139
159
  return (_jsxs("button", { className: cn('flex min-h-14 flex-col items-start gap-0.5 rounded-lg border px-2.5 py-2 text-left text-xs transition-colors', isSelected
140
160
  ? 'border-orange-400/60 bg-orange-400/10 text-foreground'
141
- : 'border-border/50 bg-black/4 dark:bg-[#2C2C2E] text-muted-foreground hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground'), onClick: () => handlePresetChange(card.key), type: "button", children: [_jsxs("span", { className: "flex items-center gap-1.5 font-medium", children: [_jsx(LayoutGrid, { className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "truncate", children: card.label })] }), _jsx("span", { className: "pl-[20px] text-[10px] tabular-nums opacity-70", children: formatDims(dims.panelWidth, dims.panelHeight) })] }, card.key));
142
- }) }), !activePreset && (_jsx("p", { className: "px-1 pt-1 text-[11px] text-muted-foreground", children: "Custom \u2014 dimensions don't match any preset" }))] }), _jsxs(PanelSection, { title: "Array", children: [_jsx(SliderControl, { label: "Rows", max: 20, min: 1, onChange: (v) => previewProp({ rows: Math.round(v) }), onCommit: (v) => commitProp({ rows: Math.round(v) }), precision: 0, restoreOnCommit: false, step: 1, value: num(node.rows, 4) }), _jsx(SliderControl, { label: "Columns", max: 20, min: 1, onChange: (v) => previewProp({ columns: Math.round(v) }), onCommit: (v) => commitProp({ columns: Math.round(v) }), precision: 0, restoreOnCommit: false, step: 1, value: num(node.columns, 5) }), _jsx(SliderControl, { label: "Gap X", max: 0.2, min: 0, onChange: (v) => previewProp({ gapX: v }), onCommit: (v) => commitProp({ gapX: v }), precision: 3, restoreOnCommit: false, step: 0.005, unit: "m", value: num(node.gapX, 0.02) }), _jsx(SliderControl, { label: "Gap Y", max: 0.2, min: 0, onChange: (v) => previewProp({ gapY: v }), onCommit: (v) => commitProp({ gapY: v }), precision: 3, restoreOnCommit: false, step: 0.005, unit: "m", value: num(node.gapY, 0.02) }), _jsx(ActionGroup, { children: _jsx(ActionButton, { disabled: !segment, label: "Auto-fit to roof", onClick: handleAutoFit }) }), autoFitMessage ? (_jsx("p", { className: "px-1 text-amber-700 dark:text-amber-400 text-xs", children: autoFitMessage })) : null] }), _jsxs(PanelSection, { title: "Panel", children: [_jsx(SliderControl, { label: "Width", max: 1000, min: 0.3, onChange: (v) => previewProp({ panelWidth: v }), onCommit: (v) => commitProp({ panelWidth: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: num(node.panelWidth, 1) }), _jsx(SliderControl, { label: "Height", max: 1000, min: 0.3, onChange: (v) => previewProp({ panelHeight: v }), onCommit: (v) => commitProp({ panelHeight: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: num(node.panelHeight, 1.65) }), _jsx(ActionGroup, { children: _jsx(ActionButton, { label: "Flip orientation", onClick: handleFlip }) }), _jsx(SliderControl, { label: "Frame thickness", max: 0.1, min: 0.005, onChange: (v) => previewProp({ frameThickness: v }), onCommit: (v) => commitProp({ frameThickness: v }), precision: 3, restoreOnCommit: false, step: 0.005, unit: "m", value: num(node.frameThickness, 0.04) }), _jsx(SliderControl, { label: "Frame depth", max: 0.1, min: 0.005, onChange: (v) => previewProp({ frameDepth: v }), onCommit: (v) => commitProp({ frameDepth: v }), precision: 3, restoreOnCommit: false, step: 0.005, unit: "m", value: num(node.frameDepth, 0.04) })] }), _jsxs(PanelSection, { title: "Mounting", children: [_jsx(SegmentedControl, { onChange: (v) => handleUpdate({ mountingType: v }), options: [
143
- { label: 'Flush', value: 'flush' },
144
- { label: 'Tilted', value: 'tilted' },
145
- ], value: node.mountingType ?? 'flush' }), node.mountingType === 'tilted' && (_jsx(SliderControl, { label: "Tilt angle", max: 45, min: 0, onChange: (v) => previewProp({ tiltAngle: v }), onCommit: (v) => commitProp({ tiltAngle: v }), precision: 0, restoreOnCommit: false, step: 1, unit: "\u00B0", value: Math.round(num(node.tiltAngle, 15)) })), _jsx(SliderControl, { label: "Standoff", max: 0.3, min: 0, onChange: (v) => previewProp({ standoffHeight: v }), onCommit: (v) => commitProp({ standoffHeight: v }), precision: 3, restoreOnCommit: false, step: 0.005, unit: "m", value: num(node.standoffHeight, 0.05) })] }), _jsx(PanelSection, { title: "Actions", children: _jsx(ActionGroup, { children: _jsx(ActionButton, { className: "hover:bg-red-500/20", icon: _jsx(Trash2, { className: "h-3.5 w-3.5 text-red-600 dark:text-red-400" }), label: "Delete", onClick: handleDelete }) }) })] }));
161
+ : 'border-border/50 bg-black/4 dark:bg-[#2C2C2E] text-muted-foreground hover:bg-black/8 dark:hover:bg-[#3e3e3e] hover:text-foreground'), onClick: () => handlePresetChange(card.key), type: "button", children: [_jsxs("span", { className: "flex items-center gap-1.5 font-medium", children: [_jsx(LayoutGrid, { className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "min-w-0 break-words", children: i18n._(card.label) })] }), _jsx("span", { className: "pl-[20px] text-[10px] tabular-nums opacity-70", children: formatDims(dims.panelWidth, dims.panelHeight) })] }, card.key));
162
+ }) }), !activePreset && (_jsx("p", { className: "px-1 pt-1 text-[11px] text-muted-foreground", children: i18n._({
163
+ id: 'node.solarPanel.panel.customDimensionsDonTMatchAny',
164
+ message: "Custom — dimensions don't match any preset",
165
+ }) }))] }), _jsxs(PanelSection, { title: i18n._({ id: 'node.solarPanel.panel.array', message: 'Array' }), children: [_jsx(SliderControl, { label: i18n._({ id: 'node.solarPanel.panel.rows', message: 'Rows' }), max: 20, min: 1, onChange: (v) => previewProp({ rows: Math.round(v) }), onCommit: (v) => commitProp({ rows: Math.round(v) }), precision: 0, restoreOnCommit: false, step: 1, value: num(node.rows, 4) }), _jsx(SliderControl, { label: i18n._({ id: 'node.solarPanel.panel.columns', message: 'Columns' }), max: 20, min: 1, onChange: (v) => previewProp({ columns: Math.round(v) }), onCommit: (v) => commitProp({ columns: Math.round(v) }), precision: 0, restoreOnCommit: false, step: 1, value: num(node.columns, 5) }), _jsx(SliderControl, { label: i18n._({ id: 'node.solarPanel.panel.gapX', message: 'Gap X' }), max: 0.2, min: 0, onChange: (v) => previewProp({ gapX: v }), onCommit: (v) => commitProp({ gapX: v }), precision: 3, restoreOnCommit: false, step: 0.005, unit: "m", value: num(node.gapX, 0.02) }), _jsx(SliderControl, { label: i18n._({ id: 'node.solarPanel.panel.gapY', message: 'Gap Y' }), max: 0.2, min: 0, onChange: (v) => previewProp({ gapY: v }), onCommit: (v) => commitProp({ gapY: v }), precision: 3, restoreOnCommit: false, step: 0.005, unit: "m", value: num(node.gapY, 0.02) }), _jsx(ActionGroup, { children: _jsx(ActionButton, { disabled: !segment, label: i18n._({
166
+ id: 'node.solarPanel.panel.autoFitToRoof',
167
+ message: 'Auto-fit to roof',
168
+ }), onClick: handleAutoFit }) }), autoFitMessage ? (_jsx("p", { className: "px-1 text-amber-700 dark:text-amber-400 text-xs", children: autoFitMessage })) : null] }), _jsxs(PanelSection, { title: i18n._({ id: 'node.solarPanel.panel.panel', message: 'Panel' }), children: [_jsx(SliderControl, { label: i18n._({ id: 'node.solarPanel.panel.width', message: 'Width' }), max: 1000, min: 0.3, onChange: (v) => previewProp({ panelWidth: v }), onCommit: (v) => commitProp({ panelWidth: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: num(node.panelWidth, 1) }), _jsx(SliderControl, { label: i18n._({ id: 'node.solarPanel.panel.height', message: 'Height' }), max: 1000, min: 0.3, onChange: (v) => previewProp({ panelHeight: v }), onCommit: (v) => commitProp({ panelHeight: v }), precision: 2, restoreOnCommit: false, step: 0.05, unit: "m", value: num(node.panelHeight, 1.65) }), _jsx(ActionGroup, { children: _jsx(ActionButton, { label: i18n._({
169
+ id: 'node.solarPanel.panel.flipOrientation',
170
+ message: 'Flip orientation',
171
+ }), onClick: handleFlip }) }), _jsx(SliderControl, { label: i18n._({ id: 'node.solarPanel.panel.frameThickness', message: 'Frame thickness' }), max: 0.1, min: 0.005, onChange: (v) => previewProp({ frameThickness: v }), onCommit: (v) => commitProp({ frameThickness: v }), precision: 3, restoreOnCommit: false, step: 0.005, unit: "m", value: num(node.frameThickness, 0.04) }), _jsx(SliderControl, { label: i18n._({ id: 'node.solarPanel.panel.frameDepth', message: 'Frame depth' }), max: 0.1, min: 0.005, onChange: (v) => previewProp({ frameDepth: v }), onCommit: (v) => commitProp({ frameDepth: v }), precision: 3, restoreOnCommit: false, step: 0.005, unit: "m", value: num(node.frameDepth, 0.04) })] }), _jsxs(PanelSection, { title: i18n._({ id: 'node.solarPanel.panel.mounting', message: 'Mounting' }), children: [_jsx(SegmentedControl, { onChange: (v) => handleUpdate({ mountingType: v }), options: [
172
+ {
173
+ label: i18n._({ id: 'node.solarPanel.panel.flush', message: 'Flush' }),
174
+ value: 'flush',
175
+ },
176
+ {
177
+ label: i18n._({ id: 'node.solarPanel.panel.tilted', message: 'Tilted' }),
178
+ value: 'tilted',
179
+ },
180
+ ], value: node.mountingType ?? 'flush' }), node.mountingType === 'tilted' && (_jsx(SliderControl, { label: i18n._({ id: 'node.solarPanel.panel.tiltAngle', message: 'Tilt angle' }), max: 45, min: 0, onChange: (v) => previewProp({ tiltAngle: v }), onCommit: (v) => commitProp({ tiltAngle: v }), precision: 0, restoreOnCommit: false, step: 1, unit: "\u00B0", value: Math.round(num(node.tiltAngle, 15)) })), _jsx(SliderControl, { label: i18n._({ id: 'node.solarPanel.panel.standoff', message: 'Standoff' }), max: 0.3, min: 0, onChange: (v) => previewProp({ standoffHeight: v }), onCommit: (v) => commitProp({ standoffHeight: v }), precision: 3, restoreOnCommit: false, step: 0.005, unit: "m", value: num(node.standoffHeight, 0.05) })] }), _jsx(PanelSection, { title: i18n._({ id: 'node.solarPanel.panel.actions', message: 'Actions' }), children: _jsx(ActionGroup, { children: _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.solarPanel.panel.delete', message: 'Delete' }), onClick: handleDelete }) }) })] }));
146
181
  }
@@ -1,7 +1,9 @@
1
1
  import { StairConstruction, type StairNode, type StairSegmentNode } from '@pascal-app/core';
2
- export declare function StairConstructionControls({ node, inherited, onChange, }: {
2
+ export declare function StairConstructionControls({ node, inherited, structured, onChange, }: {
3
3
  node: StairNode | StairSegmentNode;
4
4
  inherited?: StairConstruction;
5
+ /** The stair has a structure: without a body of its own it draws the structure's. */
6
+ structured?: boolean;
5
7
  onChange: (construction: StairConstruction | undefined) => void;
6
8
  }): import("react").JSX.Element;
7
9
  export declare function StairConstructionField({ node, onUpdate, }: {
@@ -1 +1 @@
1
- {"version":3,"file":"construction-controls.d.ts","sourceRoot":"","sources":["../../src/stair/construction-controls.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,iBAAiB,EACjB,KAAK,SAAS,EACd,KAAK,gBAAgB,EAEtB,MAAM,kBAAkB,CAAA;AAYzB,wBAAgB,yBAAyB,CAAC,EACxC,IAAI,EACJ,SAAS,EACT,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,SAAS,GAAG,gBAAgB,CAAA;IAClC,SAAS,CAAC,EAAE,iBAAiB,CAAA;IAC7B,QAAQ,EAAE,CAAC,YAAY,EAAE,iBAAiB,GAAG,SAAS,KAAK,IAAI,CAAA;CAChE,+BAwGA;AAED,wBAAgB,sBAAsB,CAAC,EACrC,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,SAAS,CAAA;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,KAAK,IAAI,CAAA;CAC9C,+BAOA;AAED,wBAAgB,6BAA6B,CAAC,EAC5C,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,gBAAgB,CAAA;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAA;CACrD,+BAYA"}
1
+ {"version":3,"file":"construction-controls.d.ts","sourceRoot":"","sources":["../../src/stair/construction-controls.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,iBAAiB,EACjB,KAAK,SAAS,EACd,KAAK,gBAAgB,EAGtB,MAAM,kBAAkB,CAAA;AAoCzB,wBAAgB,yBAAyB,CAAC,EACxC,IAAI,EACJ,SAAS,EACT,UAAkB,EAClB,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,SAAS,GAAG,gBAAgB,CAAA;IAClC,SAAS,CAAC,EAAE,iBAAiB,CAAA;IAC7B,qFAAqF;IACrF,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,CAAC,YAAY,EAAE,iBAAiB,GAAG,SAAS,KAAK,IAAI,CAAA;CAChE,+BA2IA;AAED,wBAAgB,sBAAsB,CAAC,EACrC,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,SAAS,CAAA;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,KAAK,IAAI,CAAA;CAC9C,+BAQA;AAED,wBAAgB,6BAA6B,CAAC,EAC5C,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,gBAAgB,CAAA;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAA;CACrD,+BAiBA"}
@@ -1,29 +1,92 @@
1
1
  'use client';
2
2
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { StairConstruction, useScene, } from '@pascal-app/core';
3
+ import { StairConstruction, usePascalI18n, useScene, } from '@pascal-app/core';
4
4
  import { MetricControl, SelectControl, ToggleControl } from '@pascal-app/editor';
5
5
  const OPTIONS = [
6
- { label: 'Original', value: 'original' },
7
- { label: 'Solid', value: 'solid' },
8
- { label: 'Waist', value: 'waist' },
9
- { label: 'Open', value: 'open' },
10
- { label: 'Side stringers', value: 'side-stringers' },
11
- { label: 'Center stringer', value: 'center-stringer' },
6
+ {
7
+ label: /* i18n */ { id: 'node.stair.constructionControls.original', message: 'Original' },
8
+ value: 'original',
9
+ },
10
+ {
11
+ label: /* i18n */ { id: 'node.stair.constructionControls.solid', message: 'Solid' },
12
+ value: 'solid',
13
+ },
14
+ {
15
+ label: /* i18n */ { id: 'node.stair.constructionControls.waist', message: 'Waist' },
16
+ value: 'waist',
17
+ },
18
+ {
19
+ label: /* i18n */ { id: 'node.stair.constructionControls.open', message: 'Open' },
20
+ value: 'open',
21
+ },
22
+ {
23
+ label: /* i18n */ {
24
+ id: 'node.stair.constructionControls.sideStringers',
25
+ message: 'Side stringers',
26
+ },
27
+ value: 'side-stringers',
28
+ },
29
+ {
30
+ label: /* i18n */ {
31
+ id: 'node.stair.constructionControls.centerStringer',
32
+ message: 'Center stringer',
33
+ },
34
+ value: 'center-stringer',
35
+ },
12
36
  ];
13
- export function StairConstructionControls({ node, inherited, onChange, }) {
37
+ export function StairConstructionControls({ node, inherited, structured = false, onChange, }) {
38
+ const i18n = usePascalI18n();
14
39
  const effective = node.construction ?? inherited;
15
40
  const update = (patch) => onChange(StairConstruction.parse({ ...effective, ...patch }));
16
- return (_jsxs("div", { className: "space-y-3", children: [_jsx(SelectControl, { label: "Body", value: node.construction?.mode ?? 'original', options: OPTIONS.map((option) => option.value === 'original' && inherited ? { ...option, label: 'Inherit' } : option), onChange: (mode) => mode === 'original'
41
+ return (_jsxs("div", { className: "space-y-3", children: [_jsx(SelectControl, { label: i18n._({ id: 'node.stair.constructionControls.body', message: 'Body' }), value: node.construction?.mode ?? 'original', options: OPTIONS.map((option) => option.value === 'original' && (inherited || structured)
42
+ ? {
43
+ ...option,
44
+ label: inherited
45
+ ? i18n._({
46
+ id: 'node.stair.constructionControls.inherit',
47
+ message: 'Inherit',
48
+ })
49
+ : i18n._({
50
+ id: 'node.stair.constructionControls.fromStructure',
51
+ message: 'From structure',
52
+ }),
53
+ }
54
+ : { ...option, label: i18n._(option.label) }), onChange: (mode) => mode === 'original'
17
55
  ? onChange(undefined)
18
- : update({ mode: mode }) }), effective ? (_jsxs(_Fragment, { children: [effective.mode === 'waist' ? (_jsx(MetricControl, { label: "Waist thickness", min: 0.001, value: effective.waistThickness, onChange: (waistThickness) => update({ waistThickness }), unit: "m", step: 0.01, precision: 3 })) : null, _jsx(MetricControl, { label: "Tread thickness", min: 0.001, value: effective.treadThickness, onChange: (treadThickness) => update({ treadThickness }), unit: "m", step: 0.01, precision: 3 }), _jsx(MetricControl, { label: "Nosing", min: 0, value: effective.nosing, onChange: (nosing) => update({ nosing }), unit: "m", step: 0.005, precision: 3 }), _jsx(MetricControl, { label: "Tread finish", min: 0, value: effective.finishThickness, onChange: (finishThickness) => update({ finishThickness }), unit: "m", step: 0.005, precision: 3 }), effective.mode === 'solid' || effective.mode === 'waist' ? null : (_jsxs(_Fragment, { children: [_jsx(ToggleControl, { label: "Closed risers", checked: effective.closedRisers, onChange: (closedRisers) => update({ closedRisers }) }), effective.closedRisers ? (_jsx(MetricControl, { label: "Riser thickness", min: 0.001, value: effective.riserThickness, onChange: (riserThickness) => update({ riserThickness }), unit: "m", step: 0.005, precision: 3 })) : null] })), effective.mode === 'side-stringers' || effective.mode === 'center-stringer' ? (_jsxs(_Fragment, { children: [_jsx(MetricControl, { label: "Stringer width", min: 0.001, value: effective.stringerWidth, onChange: (stringerWidth) => update({ stringerWidth }), unit: "m", step: 0.01, precision: 3 }), _jsx(MetricControl, { label: "Stringer depth", min: 0.001, value: effective.stringerDepth, onChange: (stringerDepth) => update({ stringerDepth }), unit: "m", step: 0.01, precision: 3 })] })) : null] })) : null] }));
56
+ : update({ mode: mode }) }), effective ? (_jsxs(_Fragment, { children: [effective.mode === 'waist' ? (_jsx(MetricControl, { label: i18n._({
57
+ id: 'node.stair.constructionControls.waistThickness',
58
+ message: 'Waist thickness',
59
+ }), min: 0.001, value: effective.waistThickness, onChange: (waistThickness) => update({ waistThickness }), unit: "m", step: 0.01, precision: 3 })) : null, _jsx(MetricControl, { label: i18n._({
60
+ id: 'node.stair.constructionControls.treadThickness',
61
+ message: 'Tread thickness',
62
+ }), min: 0.001, value: effective.treadThickness, onChange: (treadThickness) => update({ treadThickness }), unit: "m", step: 0.01, precision: 3 }), _jsx(MetricControl, { label: i18n._({ id: 'node.stair.constructionControls.nosing', message: 'Nosing' }), min: 0, value: effective.nosing, onChange: (nosing) => update({ nosing }), unit: "m", step: 0.005, precision: 3 }), _jsx(MetricControl, { label: i18n._({
63
+ id: 'node.stair.constructionControls.treadFinish',
64
+ message: 'Tread finish',
65
+ }), min: 0, value: effective.finishThickness, onChange: (finishThickness) => update({ finishThickness }), unit: "m", step: 0.005, precision: 3 }), effective.mode === 'solid' || effective.mode === 'waist' ? null : (_jsxs(_Fragment, { children: [_jsx(ToggleControl, { label: i18n._({
66
+ id: 'node.stair.constructionControls.closedRisers',
67
+ message: 'Closed risers',
68
+ }), checked: effective.closedRisers, onChange: (closedRisers) => update({ closedRisers }) }), effective.closedRisers ? (_jsx(MetricControl, { label: i18n._({
69
+ id: 'node.stair.constructionControls.riserThickness',
70
+ message: 'Riser thickness',
71
+ }), min: 0.001, value: effective.riserThickness, onChange: (riserThickness) => update({ riserThickness }), unit: "m", step: 0.005, precision: 3 })) : null] })), effective.mode === 'side-stringers' || effective.mode === 'center-stringer' ? (_jsxs(_Fragment, { children: [_jsx(MetricControl, { label: i18n._({
72
+ id: 'node.stair.constructionControls.stringerWidth',
73
+ message: 'Stringer width',
74
+ }), min: 0.001, value: effective.stringerWidth, onChange: (stringerWidth) => update({ stringerWidth }), unit: "m", step: 0.01, precision: 3 }), _jsx(MetricControl, { label: i18n._({
75
+ id: 'node.stair.constructionControls.stringerDepth',
76
+ message: 'Stringer depth',
77
+ }), min: 0.001, value: effective.stringerDepth, onChange: (stringerDepth) => update({ stringerDepth }), unit: "m", step: 0.01, precision: 3 })] })) : null] })) : null] }));
19
78
  }
20
79
  export function StairConstructionField({ node, onUpdate, }) {
21
- return (_jsx(StairConstructionControls, { node: node, onChange: (construction) => onUpdate({ construction }) }));
80
+ return (_jsx(StairConstructionControls, { node: node, structured: Boolean(node.structure), onChange: (construction) => onUpdate({ construction }) }));
22
81
  }
23
82
  export function StairSegmentConstructionField({ node, onUpdate, }) {
24
83
  const inherited = useScene((state) => {
25
84
  const parent = node.parentId ? state.nodes[node.parentId] : undefined;
26
85
  return parent?.type === 'stair' ? parent.construction : undefined;
27
86
  });
28
- return (_jsx(StairConstructionControls, { node: node, inherited: inherited, onChange: (construction) => onUpdate({ construction }) }));
87
+ const structured = useScene((state) => {
88
+ const parent = node.parentId ? state.nodes[node.parentId] : undefined;
89
+ return parent?.type === 'stair' && Boolean(parent.structure);
90
+ });
91
+ return (_jsx(StairConstructionControls, { node: node, inherited: inherited, structured: structured, onChange: (construction) => onUpdate({ construction }) }));
29
92
  }
@@ -6,6 +6,7 @@ export declare const stairSegmentPaint: {
6
6
  roomScope?: boolean;
7
7
  resolveRole: (args: PaintResolveArgs) => string | null;
8
8
  roleLabel?: (node: AnyNode, role: string) => string | null;
9
+ scopes?: (node: AnyNode, role: string) => import("@pascal-app/core").PaintSurfaceScopes | null;
9
10
  buildPatch: (args: import("@pascal-app/core").PaintPatchArgs) => Partial<AnyNode>;
10
11
  commit?: (args: import("@pascal-app/core").PaintPatchArgs) => void;
11
12
  applyPreview: (args: PaintPreviewArgs) => (() => void) | null;
@@ -25,6 +26,11 @@ export declare const stairSegmentPaint: {
25
26
  url: string;
26
27
  repeat?: [number, number] | undefined;
27
28
  scale?: number | undefined;
29
+ offset?: [number, number] | undefined;
30
+ normalMap?: string | undefined;
31
+ normalScale?: number | undefined;
32
+ bumpMap?: string | undefined;
33
+ bumpScale?: number | undefined;
28
34
  } | undefined;
29
35
  } | undefined;
30
36
  materialPreset: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"paint.d.ts","sourceRoot":"","sources":["../../src/stair/paint.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAGZ,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EAMtB,MAAM,kBAAkB,CAAA;AAwHzB,eAAO,MAAM,UAAU,4CAKrB,CAAA;AAEF,QAAA,MAAM,YAAY,4CAMhB,CAAA;AACF,eAAO,MAAM,iBAAiB;;;;;;;;iCAGpB,UAAU,CAAC,WAAW,CAAC,OAAO,YAAY,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;CAa7E,CAAA"}
1
+ {"version":3,"file":"paint.d.ts","sourceRoot":"","sources":["../../src/stair/paint.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAGZ,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EAMtB,MAAM,kBAAkB,CAAA;AAwHzB,eAAO,MAAM,UAAU,4CAKrB,CAAA;AAEF,QAAA,MAAM,YAAY,4CAMhB,CAAA;AACF,eAAO,MAAM,iBAAiB;;;;;;;;;iCAGpB,UAAU,CAAC,WAAW,CAAC,OAAO,YAAY,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;CAa7E,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/stair/panel.tsx"],"names":[],"mappings":"AA4FA,MAAM,CAAC,OAAO,UAAU,UAAU,uCAo4BjC"}
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/stair/panel.tsx"],"names":[],"mappings":"AAkKA,MAAM,CAAC,OAAO,UAAU,UAAU,uCA2hCjC"}