@pascal-app/nodes 1.0.0 → 1.0.3

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 (439) hide show
  1. package/dist/block/definition.d.ts.map +1 -1
  2. package/dist/block/definition.js +4 -1
  3. package/dist/block/face-host.d.ts.map +1 -1
  4. package/dist/block/face-host.js +19 -2
  5. package/dist/block/hosted-edit.d.ts +13 -0
  6. package/dist/block/hosted-edit.d.ts.map +1 -0
  7. package/dist/block/hosted-edit.js +205 -0
  8. package/dist/block/last-operation.d.ts +1 -1
  9. package/dist/block/last-operation.d.ts.map +1 -1
  10. package/dist/block/last-operation.js +6 -4
  11. package/dist/block/modal-session.d.ts +2 -1
  12. package/dist/block/modal-session.d.ts.map +1 -1
  13. package/dist/block/modal-session.js +2 -2
  14. package/dist/block/selection.d.ts.map +1 -1
  15. package/dist/block/selection.js +82 -24
  16. package/dist/block/surface.d.ts +4 -0
  17. package/dist/block/surface.d.ts.map +1 -0
  18. package/dist/block/surface.js +54 -0
  19. package/dist/block/use-block-face-operation.d.ts +2 -2
  20. package/dist/block/use-block-face-operation.d.ts.map +1 -1
  21. package/dist/block/use-block-face-operation.js +25 -11
  22. package/dist/box-vent/definition.d.ts.map +1 -1
  23. package/dist/box-vent/definition.js +1 -0
  24. package/dist/box-vent/panel.js +4 -4
  25. package/dist/building/renderer.d.ts.map +1 -1
  26. package/dist/building/renderer.js +1 -1
  27. package/dist/cabinet/appliance-layout.d.ts +26 -0
  28. package/dist/cabinet/appliance-layout.d.ts.map +1 -0
  29. package/dist/cabinet/appliance-layout.js +52 -0
  30. package/dist/cabinet/countertop-layout.d.ts +173 -0
  31. package/dist/cabinet/countertop-layout.d.ts.map +1 -0
  32. package/dist/cabinet/countertop-layout.js +80 -0
  33. package/dist/cabinet/definition.d.ts.map +1 -1
  34. package/dist/cabinet/definition.js +17 -8
  35. package/dist/cabinet/geometry/cooktop.d.ts.map +1 -1
  36. package/dist/cabinet/geometry/cooktop.js +2 -2
  37. package/dist/cabinet/geometry/run.d.ts.map +1 -1
  38. package/dist/cabinet/geometry/run.js +10 -71
  39. package/dist/cabinet/geometry/sink.d.ts +2 -12
  40. package/dist/cabinet/geometry/sink.d.ts.map +1 -1
  41. package/dist/cabinet/geometry/sink.js +8 -39
  42. package/dist/cabinet/hosted-resize.d.ts +5 -0
  43. package/dist/cabinet/hosted-resize.d.ts.map +1 -0
  44. package/dist/cabinet/hosted-resize.js +14 -0
  45. package/dist/cabinet/placement-snap.d.ts.map +1 -1
  46. package/dist/cabinet/placement-snap.js +4 -2
  47. package/dist/cabinet/run-layout.d.ts +8 -1
  48. package/dist/cabinet/run-layout.d.ts.map +1 -1
  49. package/dist/cabinet/run-layout.js +22 -14
  50. package/dist/cabinet/run-ops.d.ts +3 -3
  51. package/dist/cabinet/run-ops.js +3 -3
  52. package/dist/cabinet/run-panel.d.ts +1 -1
  53. package/dist/cabinet/run-panel.d.ts.map +1 -1
  54. package/dist/cabinet/run-panel.js +16 -7
  55. package/dist/cabinet/surfaces.d.ts +5 -0
  56. package/dist/cabinet/surfaces.d.ts.map +1 -0
  57. package/dist/cabinet/surfaces.js +113 -0
  58. package/dist/cabinet/tool.d.ts.map +1 -1
  59. package/dist/cabinet/tool.js +8 -4
  60. package/dist/cabinet/tree-structure.d.ts.map +1 -1
  61. package/dist/cabinet/tree-structure.js +10 -9
  62. package/dist/ceiling/definition.d.ts.map +1 -1
  63. package/dist/ceiling/definition.js +6 -1
  64. package/dist/ceiling/floorplan-affordances.d.ts +4 -4
  65. package/dist/ceiling/panel.js +1 -1
  66. package/dist/ceiling/renderer.d.ts.map +1 -1
  67. package/dist/ceiling/renderer.js +3 -2
  68. package/dist/chimney/definition.d.ts.map +1 -1
  69. package/dist/chimney/definition.js +1 -0
  70. package/dist/chimney/panel.js +9 -9
  71. package/dist/column/definition.d.ts.map +1 -1
  72. package/dist/column/definition.js +10 -3
  73. package/dist/column/floorplan-affordances.d.ts.map +1 -1
  74. package/dist/column/floorplan-affordances.js +6 -1
  75. package/dist/column/floorplan.d.ts.map +1 -1
  76. package/dist/column/floorplan.js +23 -11
  77. package/dist/column/hosted-resize.d.ts +116 -0
  78. package/dist/column/hosted-resize.d.ts.map +1 -0
  79. package/dist/column/hosted-resize.js +9 -0
  80. package/dist/column/panel.d.ts.map +1 -1
  81. package/dist/column/panel.js +6 -3
  82. package/dist/column/renderer.d.ts.map +1 -1
  83. package/dist/column/renderer.js +25 -103
  84. package/dist/column/shape.d.ts +22 -0
  85. package/dist/column/shape.d.ts.map +1 -0
  86. package/dist/column/shape.js +120 -0
  87. package/dist/column/surface.d.ts +4 -0
  88. package/dist/column/surface.d.ts.map +1 -0
  89. package/dist/column/surface.js +66 -0
  90. package/dist/cupola/definition.d.ts.map +1 -1
  91. package/dist/cupola/definition.js +1 -0
  92. package/dist/cupola/panel.js +1 -1
  93. package/dist/door/definition.d.ts.map +1 -1
  94. package/dist/door/definition.js +40 -1
  95. package/dist/door/door-math.d.ts +1 -1
  96. package/dist/door/door-math.d.ts.map +1 -1
  97. package/dist/door/door-math.js +7 -10
  98. package/dist/door/floorplan-affordances.d.ts.map +1 -1
  99. package/dist/door/floorplan-affordances.js +8 -12
  100. package/dist/door/move-tool.d.ts.map +1 -1
  101. package/dist/door/move-tool.js +3 -4
  102. package/dist/door/panel.d.ts.map +1 -1
  103. package/dist/door/panel.js +28 -57
  104. package/dist/door/tool.d.ts.map +1 -1
  105. package/dist/door/tool.js +20 -2
  106. package/dist/dormer/definition.d.ts.map +1 -1
  107. package/dist/dormer/definition.js +1 -0
  108. package/dist/dormer/panel-position-section.js +2 -2
  109. package/dist/dormer/panel.js +1 -1
  110. package/dist/downspout/definition.d.ts.map +1 -1
  111. package/dist/downspout/definition.js +1 -0
  112. package/dist/duct-segment/parametrics.d.ts.map +1 -1
  113. package/dist/duct-segment/parametrics.js +5 -1
  114. package/dist/duct-segment/tool.d.ts +1 -0
  115. package/dist/duct-segment/tool.d.ts.map +1 -1
  116. package/dist/duct-segment/tool.js +21 -8
  117. package/dist/duct-terminal/tool.d.ts.map +1 -1
  118. package/dist/duct-terminal/tool.js +77 -8
  119. package/dist/elevator/definition.d.ts.map +1 -1
  120. package/dist/elevator/definition.js +2 -0
  121. package/dist/elevator/parametrics.d.ts.map +1 -1
  122. package/dist/elevator/parametrics.js +98 -1
  123. package/dist/eyebrow-vent/definition.d.ts.map +1 -1
  124. package/dist/eyebrow-vent/definition.js +1 -0
  125. package/dist/eyebrow-vent/panel.js +1 -1
  126. package/dist/fence/definition.d.ts.map +1 -1
  127. package/dist/fence/definition.js +1 -0
  128. package/dist/fence/inspector-editors.js +1 -1
  129. package/dist/fence/tool.js +2 -2
  130. package/dist/guide/definition.d.ts.map +1 -1
  131. package/dist/guide/definition.js +1 -0
  132. package/dist/gutter/definition.d.ts.map +1 -1
  133. package/dist/gutter/definition.js +1 -0
  134. package/dist/hvac-equipment/tool.d.ts.map +1 -1
  135. package/dist/hvac-equipment/tool.js +8 -2
  136. package/dist/imported-mesh/definition.d.ts +5 -0
  137. package/dist/imported-mesh/definition.d.ts.map +1 -0
  138. package/dist/imported-mesh/definition.js +38 -0
  139. package/dist/imported-mesh/floorplan.d.ts +4 -0
  140. package/dist/imported-mesh/floorplan.d.ts.map +1 -0
  141. package/dist/imported-mesh/floorplan.js +34 -0
  142. package/dist/imported-mesh/geometry.d.ts +5 -0
  143. package/dist/imported-mesh/geometry.d.ts.map +1 -0
  144. package/dist/imported-mesh/geometry.js +34 -0
  145. package/dist/imported-mesh/index.d.ts +4 -0
  146. package/dist/imported-mesh/index.d.ts.map +1 -0
  147. package/dist/imported-mesh/index.js +3 -0
  148. package/dist/imported-mesh/schema.d.ts +2 -0
  149. package/dist/imported-mesh/schema.d.ts.map +1 -0
  150. package/dist/imported-mesh/schema.js +1 -0
  151. package/dist/index.d.ts +2 -0
  152. package/dist/index.d.ts.map +1 -1
  153. package/dist/index.js +8 -0
  154. package/dist/item/__fixtures__/main-floorplan.d.ts +26 -0
  155. package/dist/item/__fixtures__/main-floorplan.d.ts.map +1 -0
  156. package/dist/item/__fixtures__/main-floorplan.js +297 -0
  157. package/dist/item/definition.d.ts.map +1 -1
  158. package/dist/item/definition.js +3 -1
  159. package/dist/item/floorplan-move.d.ts +9 -1
  160. package/dist/item/floorplan-move.d.ts.map +1 -1
  161. package/dist/item/floorplan-move.js +231 -99
  162. package/dist/item/floorplan.d.ts +22 -0
  163. package/dist/item/floorplan.d.ts.map +1 -1
  164. package/dist/item/floorplan.js +72 -2
  165. package/dist/item/move-tool.d.ts +1 -1
  166. package/dist/item/move-tool.d.ts.map +1 -1
  167. package/dist/item/move-tool.js +15 -7
  168. package/dist/item/panel.js +1 -1
  169. package/dist/item/renderer.d.ts.map +1 -1
  170. package/dist/item/renderer.js +8 -2
  171. package/dist/level/renderer.js +1 -1
  172. package/dist/lineset/tool.d.ts.map +1 -1
  173. package/dist/lineset/tool.js +1 -0
  174. package/dist/liquid-line/tool.d.ts.map +1 -1
  175. package/dist/liquid-line/tool.js +5 -1
  176. package/dist/measurement/definition.d.ts.map +1 -1
  177. package/dist/measurement/definition.js +1 -0
  178. package/dist/pipe-segment/parametrics.d.ts.map +1 -1
  179. package/dist/pipe-segment/parametrics.js +5 -1
  180. package/dist/pipe-segment/tool.d.ts.map +1 -1
  181. package/dist/pipe-segment/tool.js +14 -3
  182. package/dist/pipe-trap/tool.d.ts.map +1 -1
  183. package/dist/pipe-trap/tool.js +7 -8
  184. package/dist/procedural-item/definition.d.ts +4 -0
  185. package/dist/procedural-item/definition.d.ts.map +1 -0
  186. package/dist/procedural-item/definition.js +257 -0
  187. package/dist/procedural-item/geometry.d.ts +31 -0
  188. package/dist/procedural-item/geometry.d.ts.map +1 -0
  189. package/dist/procedural-item/geometry.js +88 -0
  190. package/dist/procedural-item/index.d.ts +3 -0
  191. package/dist/procedural-item/index.d.ts.map +1 -0
  192. package/dist/procedural-item/index.js +2 -0
  193. package/dist/procedural-item/move-session.d.ts +15 -0
  194. package/dist/procedural-item/move-session.d.ts.map +1 -0
  195. package/dist/procedural-item/move-session.js +197 -0
  196. package/dist/procedural-item/move-tool.d.ts +5 -0
  197. package/dist/procedural-item/move-tool.d.ts.map +1 -0
  198. package/dist/procedural-item/move-tool.js +193 -0
  199. package/dist/procedural-item/renderer.d.ts +5 -0
  200. package/dist/procedural-item/renderer.d.ts.map +1 -0
  201. package/dist/procedural-item/renderer.js +66 -0
  202. package/dist/ridge-vent/definition.d.ts.map +1 -1
  203. package/dist/ridge-vent/definition.js +1 -0
  204. package/dist/ridge-vent/panel.js +4 -4
  205. package/dist/roof/definition.d.ts.map +1 -1
  206. package/dist/roof/definition.js +4 -1
  207. package/dist/roof/panel-model.d.ts +4 -0
  208. package/dist/roof/panel-model.d.ts.map +1 -0
  209. package/dist/roof/panel-model.js +151 -0
  210. package/dist/roof/panel.d.ts.map +1 -1
  211. package/dist/roof/panel.js +9 -8
  212. package/dist/roof/parametrics.d.ts.map +1 -1
  213. package/dist/roof/parametrics.js +16 -1
  214. package/dist/roof-segment/definition.d.ts.map +1 -1
  215. package/dist/roof-segment/definition.js +1 -0
  216. package/dist/roof-segment/panel.d.ts.map +1 -1
  217. package/dist/roof-segment/panel.js +5 -5
  218. package/dist/roof-segment/parametrics.d.ts.map +1 -1
  219. package/dist/roof-segment/parametrics.js +176 -1
  220. package/dist/scan/definition.d.ts.map +1 -1
  221. package/dist/scan/definition.js +1 -0
  222. package/dist/shared/automatic-run-end-cap.d.ts +1 -0
  223. package/dist/shared/automatic-run-end-cap.d.ts.map +1 -1
  224. package/dist/shared/automatic-run-end-cap.js +10 -0
  225. package/dist/shared/commit-opening-move.d.ts +4 -0
  226. package/dist/shared/commit-opening-move.d.ts.map +1 -0
  227. package/dist/shared/commit-opening-move.js +9 -0
  228. package/dist/shared/curtain-opening-limits.d.ts +14 -0
  229. package/dist/shared/curtain-opening-limits.d.ts.map +1 -0
  230. package/dist/shared/curtain-opening-limits.js +53 -0
  231. package/dist/shared/distribution-run-tool.d.ts +10 -0
  232. package/dist/shared/distribution-run-tool.d.ts.map +1 -1
  233. package/dist/shared/distribution-run-tool.js +56 -11
  234. package/dist/shared/draft-axis-guides.d.ts +0 -6
  235. package/dist/shared/draft-axis-guides.d.ts.map +1 -1
  236. package/dist/shared/draft-axis-guides.js +1 -8
  237. package/dist/shared/hosted-resize.d.ts +12 -0
  238. package/dist/shared/hosted-resize.d.ts.map +1 -0
  239. package/dist/shared/hosted-resize.js +166 -0
  240. package/dist/shared/opening-grid-follow.d.ts +8 -0
  241. package/dist/shared/opening-grid-follow.d.ts.map +1 -0
  242. package/dist/shared/opening-grid-follow.js +12 -0
  243. package/dist/shared/opening-property-preview-host.d.ts +3 -0
  244. package/dist/shared/opening-property-preview-host.d.ts.map +1 -0
  245. package/dist/shared/opening-property-preview-host.js +21 -0
  246. package/dist/shared/opening-property-preview.d.ts +19 -0
  247. package/dist/shared/opening-property-preview.d.ts.map +1 -0
  248. package/dist/shared/opening-property-preview.js +99 -0
  249. package/dist/shared/panel-fields.d.ts +15 -0
  250. package/dist/shared/panel-fields.d.ts.map +1 -0
  251. package/dist/shared/panel-fields.js +31 -0
  252. package/dist/shared/resting-surface-plan.d.ts +4 -0
  253. package/dist/shared/resting-surface-plan.d.ts.map +1 -0
  254. package/dist/shared/resting-surface-plan.js +53 -0
  255. package/dist/shared/surface-counterparts.d.ts +12 -0
  256. package/dist/shared/surface-counterparts.d.ts.map +1 -0
  257. package/dist/shared/surface-counterparts.js +27 -0
  258. package/dist/shared/wall-attach-target.d.ts +1 -0
  259. package/dist/shared/wall-attach-target.d.ts.map +1 -1
  260. package/dist/shared/wall-attach-target.js +4 -1
  261. package/dist/shared/wall-event-from-grid.d.ts +5 -0
  262. package/dist/shared/wall-event-from-grid.d.ts.map +1 -0
  263. package/dist/shared/wall-event-from-grid.js +36 -0
  264. package/dist/shelf/definition.d.ts.map +1 -1
  265. package/dist/shelf/definition.js +5 -2
  266. package/dist/shelf/floorplan-affordances.d.ts.map +1 -1
  267. package/dist/shelf/floorplan-affordances.js +5 -3
  268. package/dist/shelf/floorplan-move.d.ts.map +1 -1
  269. package/dist/shelf/floorplan-move.js +3 -2
  270. package/dist/shelf/floorplan.d.ts.map +1 -1
  271. package/dist/shelf/floorplan.js +9 -2
  272. package/dist/shelf/geometry.d.ts.map +1 -1
  273. package/dist/shelf/geometry.js +2 -10
  274. package/dist/site/renderer.d.ts.map +1 -1
  275. package/dist/site/renderer.js +9 -2
  276. package/dist/skylight/definition.d.ts.map +1 -1
  277. package/dist/skylight/definition.js +1 -0
  278. package/dist/skylight/panel.js +6 -6
  279. package/dist/slab/definition.d.ts.map +1 -1
  280. package/dist/slab/definition.js +4 -0
  281. package/dist/slab/panel.js +1 -1
  282. package/dist/solar-panel/definition.d.ts.map +1 -1
  283. package/dist/solar-panel/definition.js +1 -0
  284. package/dist/solar-panel/panel.js +2 -2
  285. package/dist/spawn/definition.d.ts.map +1 -1
  286. package/dist/spawn/definition.js +1 -0
  287. package/dist/spawn/panel.js +1 -1
  288. package/dist/stair/definition.d.ts.map +1 -1
  289. package/dist/stair/definition.js +2 -0
  290. package/dist/stair/panel.d.ts.map +1 -1
  291. package/dist/stair/panel.js +9 -7
  292. package/dist/stair/parametrics.d.ts.map +1 -1
  293. package/dist/stair/parametrics.js +164 -1
  294. package/dist/stair-segment/definition.d.ts.map +1 -1
  295. package/dist/stair-segment/definition.js +1 -0
  296. package/dist/stair-segment/panel.js +4 -4
  297. package/dist/stair-segment/parametrics.d.ts.map +1 -1
  298. package/dist/stair-segment/parametrics.js +81 -1
  299. package/dist/turbine-vent/definition.d.ts.map +1 -1
  300. package/dist/turbine-vent/definition.js +1 -0
  301. package/dist/turbine-vent/panel.js +1 -1
  302. package/dist/unit/definition.d.ts +10 -0
  303. package/dist/unit/definition.d.ts.map +1 -0
  304. package/dist/unit/definition.js +38 -0
  305. package/dist/unit/index.d.ts +2 -0
  306. package/dist/unit/index.d.ts.map +1 -0
  307. package/dist/unit/index.js +1 -0
  308. package/dist/unit/parametrics.d.ts +3 -0
  309. package/dist/unit/parametrics.d.ts.map +1 -0
  310. package/dist/unit/parametrics.js +4 -0
  311. package/dist/unit/schema.d.ts +2 -0
  312. package/dist/unit/schema.d.ts.map +1 -0
  313. package/dist/unit/schema.js +1 -0
  314. package/dist/unit/unit-panel.d.ts +5 -0
  315. package/dist/unit/unit-panel.d.ts.map +1 -0
  316. package/dist/unit/unit-panel.js +61 -0
  317. package/dist/wall/actions.d.ts +3 -0
  318. package/dist/wall/actions.d.ts.map +1 -0
  319. package/dist/wall/actions.js +56 -0
  320. package/dist/wall/curtain-opening-frame.d.ts +14 -0
  321. package/dist/wall/curtain-opening-frame.d.ts.map +1 -0
  322. package/dist/wall/curtain-opening-frame.js +111 -0
  323. package/dist/wall/curtain-panel-highlight.d.ts +3 -0
  324. package/dist/wall/curtain-panel-highlight.d.ts.map +1 -0
  325. package/dist/wall/curtain-panel-highlight.js +113 -0
  326. package/dist/wall/curtain-wall-adapter.d.ts +3 -0
  327. package/dist/wall/curtain-wall-adapter.d.ts.map +1 -0
  328. package/dist/wall/curtain-wall-adapter.js +55 -0
  329. package/dist/wall/curtain-wall-floorplan.d.ts +3 -0
  330. package/dist/wall/curtain-wall-floorplan.d.ts.map +1 -0
  331. package/dist/wall/curtain-wall-floorplan.js +91 -0
  332. package/dist/wall/curtain-wall-geometry.d.ts +4 -0
  333. package/dist/wall/curtain-wall-geometry.d.ts.map +1 -0
  334. package/dist/wall/curtain-wall-geometry.js +226 -0
  335. package/dist/wall/curtain-wall-layout.d.ts +16 -0
  336. package/dist/wall/curtain-wall-layout.d.ts.map +1 -0
  337. package/dist/wall/curtain-wall-layout.js +176 -0
  338. package/dist/wall/curtain-wall-materials.d.ts +5 -0
  339. package/dist/wall/curtain-wall-materials.d.ts.map +1 -0
  340. package/dist/wall/curtain-wall-materials.js +55 -0
  341. package/dist/wall/curtain-wall-panel.d.ts +14 -0
  342. package/dist/wall/curtain-wall-panel.d.ts.map +1 -0
  343. package/dist/wall/curtain-wall-panel.js +167 -0
  344. package/dist/wall/curtain-wall-piece-geometry.d.ts +5 -0
  345. package/dist/wall/curtain-wall-piece-geometry.d.ts.map +1 -0
  346. package/dist/wall/curtain-wall-piece-geometry.js +220 -0
  347. package/dist/wall/curtain-wall-shadow.d.ts +4 -0
  348. package/dist/wall/curtain-wall-shadow.d.ts.map +1 -0
  349. package/dist/wall/curtain-wall-shadow.js +15 -0
  350. package/dist/wall/definition.d.ts +0 -15
  351. package/dist/wall/definition.d.ts.map +1 -1
  352. package/dist/wall/definition.js +65 -4
  353. package/dist/wall/drawing-mode.d.ts +12 -0
  354. package/dist/wall/drawing-mode.d.ts.map +1 -0
  355. package/dist/wall/drawing-mode.js +38 -0
  356. package/dist/wall/floorplan-tool.d.ts +4 -0
  357. package/dist/wall/floorplan-tool.d.ts.map +1 -0
  358. package/dist/wall/floorplan-tool.js +107 -0
  359. package/dist/wall/floorplan.d.ts.map +1 -1
  360. package/dist/wall/floorplan.js +6 -2
  361. package/dist/wall/length-patch.d.ts +3 -0
  362. package/dist/wall/length-patch.d.ts.map +1 -0
  363. package/dist/wall/length-patch.js +14 -0
  364. package/dist/wall/move-tool.d.ts.map +1 -1
  365. package/dist/wall/move-tool.js +23 -1
  366. package/dist/wall/paint.d.ts.map +1 -1
  367. package/dist/wall/paint.js +39 -4
  368. package/dist/wall/panel-model.d.ts +4 -0
  369. package/dist/wall/panel-model.d.ts.map +1 -0
  370. package/dist/wall/panel-model.js +117 -0
  371. package/dist/wall/panel.d.ts.map +1 -1
  372. package/dist/wall/panel.js +20 -24
  373. package/dist/wall/property-preview.d.ts +7 -0
  374. package/dist/wall/property-preview.d.ts.map +1 -0
  375. package/dist/wall/property-preview.js +31 -0
  376. package/dist/wall/rectangle-command.d.ts +149 -0
  377. package/dist/wall/rectangle-command.d.ts.map +1 -0
  378. package/dist/wall/rectangle-command.js +22 -0
  379. package/dist/wall/rectangle-tool.d.ts +2 -0
  380. package/dist/wall/rectangle-tool.d.ts.map +1 -0
  381. package/dist/wall/rectangle-tool.js +147 -0
  382. package/dist/wall/renderer.d.ts.map +1 -1
  383. package/dist/wall/renderer.js +7 -4
  384. package/dist/wall/slots.d.ts +2 -2
  385. package/dist/wall/slots.d.ts.map +1 -1
  386. package/dist/wall/slots.js +10 -2
  387. package/dist/wall/split-floorplan-layer.d.ts +4 -0
  388. package/dist/wall/split-floorplan-layer.d.ts.map +1 -0
  389. package/dist/wall/split-floorplan-layer.js +71 -0
  390. package/dist/wall/split-pointer.d.ts +3 -0
  391. package/dist/wall/split-pointer.d.ts.map +1 -0
  392. package/dist/wall/split-pointer.js +95 -0
  393. package/dist/wall/split-preview.d.ts +55 -0
  394. package/dist/wall/split-preview.d.ts.map +1 -0
  395. package/dist/wall/split-preview.js +106 -0
  396. package/dist/wall/split-session.d.ts +16 -0
  397. package/dist/wall/split-session.d.ts.map +1 -0
  398. package/dist/wall/split-session.js +138 -0
  399. package/dist/wall/split-store.d.ts +16 -0
  400. package/dist/wall/split-store.d.ts.map +1 -0
  401. package/dist/wall/split-store.js +6 -0
  402. package/dist/wall/split-tool.d.ts +10 -0
  403. package/dist/wall/split-tool.d.ts.map +1 -0
  404. package/dist/wall/split-tool.js +95 -0
  405. package/dist/wall/system.d.ts.map +1 -1
  406. package/dist/wall/system.js +3 -1
  407. package/dist/wall/tool.d.ts.map +1 -1
  408. package/dist/wall/tool.js +14 -6
  409. package/dist/wall/wall-batch-system.d.ts.map +1 -1
  410. package/dist/wall/wall-batch-system.js +3 -0
  411. package/dist/window/definition.d.ts.map +1 -1
  412. package/dist/window/definition.js +48 -1
  413. package/dist/window/floorplan-affordances.d.ts.map +1 -1
  414. package/dist/window/floorplan-affordances.js +8 -10
  415. package/dist/window/move-tool.d.ts.map +1 -1
  416. package/dist/window/move-tool.js +4 -6
  417. package/dist/window/panel.d.ts.map +1 -1
  418. package/dist/window/panel.js +22 -60
  419. package/dist/window/tool.d.ts.map +1 -1
  420. package/dist/window/tool.js +34 -2
  421. package/dist/window/window-math.d.ts +1 -1
  422. package/dist/window/window-math.d.ts.map +1 -1
  423. package/dist/window/window-math.js +8 -11
  424. package/dist/zone/definition.d.ts.map +1 -1
  425. package/dist/zone/definition.js +8 -1
  426. package/dist/zone/floorplan.d.ts +1 -3
  427. package/dist/zone/floorplan.d.ts.map +1 -1
  428. package/dist/zone/floorplan.js +43 -28
  429. package/dist/zone/quantities-panel.d.ts.map +1 -1
  430. package/dist/zone/quantities-panel.js +32 -44
  431. package/dist/zone/renderer.d.ts.map +1 -1
  432. package/dist/zone/renderer.js +21 -7
  433. package/dist/zone/unit-membership.d.ts +12 -0
  434. package/dist/zone/unit-membership.d.ts.map +1 -0
  435. package/dist/zone/unit-membership.js +22 -0
  436. package/package.json +15 -9
  437. package/dist/shared/opening-documentation-fields.d.ts +0 -16
  438. package/dist/shared/opening-documentation-fields.d.ts.map +0 -1
  439. package/dist/shared/opening-documentation-fields.js +0 -54
@@ -0,0 +1,38 @@
1
+ import { emitter } from '@pascal-app/core';
2
+ import { isEditableKeyboardTarget } from '@pascal-app/editor';
3
+ import { useEffect } from 'react';
4
+ import { create } from 'zustand';
5
+ export const useWallDrawingMode = create((set, get) => ({
6
+ mode: 'line',
7
+ toggle: () => {
8
+ emitter.emit('tool:cancel');
9
+ set({ mode: get().mode === 'rectangle' ? 'line' : 'rectangle' });
10
+ },
11
+ }));
12
+ const onKeyDown = (e) => {
13
+ if (e.repeat || e.metaKey || e.ctrlKey || e.altKey)
14
+ return;
15
+ if (e.key !== 'r' && e.key !== 'R')
16
+ return;
17
+ if (isEditableKeyboardTarget(e.target))
18
+ return;
19
+ e.preventDefault();
20
+ useWallDrawingMode.getState().toggle();
21
+ };
22
+ let owners = 0;
23
+ /**
24
+ * R toggles line / rectangle drawing (the HUD's Shape chip cycles the same
25
+ * store). Both wall tools mount this: the 3D tool only exists once the canvas
26
+ * does, and split view mounts both, so one listener serves whichever is up.
27
+ * The mode outlives the tool: re-arming walls resumes the last shape used.
28
+ */
29
+ export function useWallDrawingModeKeys() {
30
+ useEffect(() => {
31
+ if (owners++ === 0)
32
+ window.addEventListener('keydown', onKeyDown);
33
+ return () => {
34
+ if (--owners === 0)
35
+ window.removeEventListener('keydown', onKeyDown);
36
+ };
37
+ }, []);
38
+ }
@@ -0,0 +1,4 @@
1
+ import { type FloorplanToolContext } from '@pascal-app/editor';
2
+ /** The wall's plan tool: line drafting stays with the panel; rectangle mode mounts its own tool. */
3
+ export default function WallFloorplanTool(props: FloorplanToolContext): import("react").JSX.Element | null;
4
+ //# sourceMappingURL=floorplan-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"floorplan-tool.d.ts","sourceRoot":"","sources":["../../src/wall/floorplan-tool.tsx"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,oBAAoB,EAO1B,MAAM,oBAAoB,CAAA;AAK3B,oGAAoG;AACpG,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,KAAK,EAAE,oBAAoB,sCAIpE"}
@@ -0,0 +1,107 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { emitter, resolveTerrainWallConstructionOptions, useScene, } from '@pascal-app/core';
4
+ import { markToolCancelConsumed, triggerSFX, useEditor, useFloorplanDraftPreview, useFloorplanRender, useInteractionScope, } from '@pascal-app/editor';
5
+ import { useEffect, useRef, useState } from 'react';
6
+ import { useWallDrawingMode, useWallDrawingModeKeys } from './drawing-mode';
7
+ import { createWallRectangle } from './rectangle-command';
8
+ /** The wall's plan tool: line drafting stays with the panel; rectangle mode mounts its own tool. */
9
+ export default function WallFloorplanTool(props) {
10
+ useWallDrawingModeKeys();
11
+ const mode = useWallDrawingMode((s) => s.mode);
12
+ return mode === 'rectangle' ? _jsx(RectangleFloorplanTool, { ...props }) : null;
13
+ }
14
+ /**
15
+ * Rectangle mode in the floor plan. Pointer moves stay with the panel, so the
16
+ * cursor, snapping, alignment guides and snap beacon are the line wall's own;
17
+ * this tool only claims clicks and publishes the first corner, and the panel's
18
+ * linear draft layer draws the four draft walls from it.
19
+ */
20
+ function RectangleFloorplanTool({ activeLevelId }) {
21
+ const group = useRef(null);
22
+ const renderContext = useFloorplanRender();
23
+ const [error, setError] = useState(null);
24
+ useEffect(() => {
25
+ const svg = group.current?.ownerSVGElement;
26
+ if (!svg || !activeLevelId)
27
+ return;
28
+ const draft = useFloorplanDraftPreview.getState;
29
+ let down = null;
30
+ let construction;
31
+ useInteractionScope.getState().begin({ kind: 'drafting', tool: 'wall' });
32
+ const claim = (e) => {
33
+ e.preventDefault();
34
+ e.stopImmediatePropagation();
35
+ };
36
+ const onDown = (e) => {
37
+ if (e.button !== 0 || e.metaKey || e.ctrlKey)
38
+ return;
39
+ claim(e);
40
+ down = [e.clientX, e.clientY];
41
+ };
42
+ const cancel = () => {
43
+ if (draft().wallRectangleDraftStart)
44
+ markToolCancelConsumed();
45
+ draft().setWallRectangleDraftStart(null);
46
+ down = null;
47
+ setError(null);
48
+ };
49
+ const onClick = (e) => {
50
+ if (e.button !== 0 || e.metaKey || e.ctrlKey)
51
+ return;
52
+ claim(e);
53
+ if (!down || Math.hypot(e.clientX - down[0], e.clientY - down[1]) > 5) {
54
+ down = null;
55
+ return;
56
+ }
57
+ down = null;
58
+ // The panel's snapped cursor, exactly where a line wall would land.
59
+ const point = draft().cursorPoint;
60
+ if (!point)
61
+ return;
62
+ const start = draft().wallRectangleDraftStart;
63
+ if (!start) {
64
+ construction = resolveTerrainWallConstructionOptions(useScene.getState().nodes, activeLevelId, point, useEditor.getState().toolDefaults.wall);
65
+ draft().setWallRectangleDraftStart(point);
66
+ setError(null);
67
+ triggerSFX('sfx:structure-build-start');
68
+ return;
69
+ }
70
+ try {
71
+ createWallRectangle(activeLevelId, start, point, useEditor.getState().toolDefaults.wall ?? {}, construction);
72
+ cancel();
73
+ triggerSFX('sfx:structure-build');
74
+ }
75
+ catch (e) {
76
+ setError({ message: e.message, at: point });
77
+ }
78
+ };
79
+ const stopDouble = (e) => {
80
+ if (e.button === 0)
81
+ claim(e);
82
+ };
83
+ // The panel publishes the snapped cursor only when it moves to a new
84
+ // point, so each change while a corner is down is the line draft's tick.
85
+ const stopTick = useFloorplanDraftPreview.subscribe((state, previous) => {
86
+ if (state.wallRectangleDraftStart &&
87
+ state.cursorPoint &&
88
+ state.cursorPoint !== previous.cursorPoint)
89
+ triggerSFX('sfx:grid-snap');
90
+ });
91
+ svg.addEventListener('pointerdown', onDown, true);
92
+ svg.addEventListener('click', onClick, true);
93
+ svg.addEventListener('dblclick', stopDouble, true);
94
+ emitter.on('tool:cancel', cancel);
95
+ return () => {
96
+ stopTick();
97
+ svg.removeEventListener('pointerdown', onDown, true);
98
+ svg.removeEventListener('click', onClick, true);
99
+ svg.removeEventListener('dblclick', stopDouble, true);
100
+ emitter.off('tool:cancel', cancel);
101
+ draft().setWallRectangleDraftStart(null);
102
+ useInteractionScope.getState().endIf((s) => s.kind === 'drafting' && s.tool === 'wall');
103
+ };
104
+ }, [activeLevelId]);
105
+ const unitsPerPixel = renderContext?.unitsPerPixel ?? 0.01;
106
+ return (_jsx("g", { ref: group, pointerEvents: "none", children: error && (_jsx("text", { x: error.at[0], y: error.at[1] - 0.2, fill: "#ef4444", fontSize: 12 * unitsPerPixel, children: error.message })) }));
107
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"floorplan.d.ts","sourceRoot":"","sources":["../../src/wall/floorplan.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAEZ,KAAK,iBAAiB,EAEtB,KAAK,eAAe,EAOpB,KAAK,aAAa,EAClB,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAKL,KAAK,6BAA6B,EACnC,MAAM,2BAA2B,CAAA;AAYlC,QAAA,MAAM,yBAAyB,yDAA0D,CAAA;AAEzF,KAAK,sBAAsB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAA;AAexE,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,aAAa,CAAA;IACrB,cAAc,EAAE,aAAa,CAAA;IAC7B,iCAAiC,EAAE,MAAM,CAAC,sBAAsB,EAAE,6BAA6B,CAAC,CAAA;CACjG,CAAA;AAED,wBAAgB,6BAA6B,CAAC,EAC5C,QAAQ,EACR,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B,GAAG,sBAAsB,CAqCzB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,eAAe,GAAG,iBAAiB,GAAG,IAAI,CAkNjG"}
1
+ {"version":3,"file":"floorplan.d.ts","sourceRoot":"","sources":["../../src/wall/floorplan.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAEZ,KAAK,iBAAiB,EAEtB,KAAK,eAAe,EAQpB,KAAK,aAAa,EAClB,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAKL,KAAK,6BAA6B,EACnC,MAAM,2BAA2B,CAAA;AAalC,QAAA,MAAM,yBAAyB,yDAA0D,CAAA;AAEzF,KAAK,sBAAsB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAA;AAexE,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,aAAa,CAAA;IACrB,cAAc,EAAE,aAAa,CAAA;IAC7B,iCAAiC,EAAE,MAAM,CAAC,sBAAsB,EAAE,6BAA6B,CAAC,CAAA;CACjG,CAAA;AAED,wBAAgB,6BAA6B,CAAC,EAC5C,QAAQ,EACR,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B,GAAG,sBAAsB,CAqCzB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,eAAe,GAAG,iBAAiB,GAAG,IAAI,CA8NjG"}
@@ -1,7 +1,8 @@
1
- import { calculateLevelMiters, getWallCurveFrameAt, getWallCurveLength, getWallMidpointHandlePoint, getWallPlanFootprint, getWallThickness, isCurvedWall, } from '@pascal-app/core';
1
+ import { calculateLevelMiters, getWallCurveFrameAt, getWallCurveLength, getWallEffectiveHeightForNodes, getWallMidpointHandlePoint, getWallPlanFootprint, getWallThickness, isCurvedWall, } from '@pascal-app/core';
2
2
  import { floorplanGeometryMetadata, readFloorplanContext } from '@pascal-app/editor';
3
3
  import { constructionDimensionStandard } from '../shared/construction-dimension-standards';
4
4
  import { buildCurvedWallConstructionDimensions, buildLevelWallConstructionDimensionPlan, buildWallConstructionDimensions, renderPlannedConstructionDimensions, } from './construction-dimensions';
5
+ import { buildCurtainWallFloorplan } from './curtain-wall-floorplan';
5
6
  import { hasWallCurveBlockingChildren } from './curve-eligibility';
6
7
  // Same constants the legacy `getFloorplanWall` uses (editor/lib/floorplan/walls.ts).
7
8
  // Slightly exaggerates thin walls so the 2D plan stays legible without
@@ -103,7 +104,7 @@ export function buildWallFloorplan(node, ctx) {
103
104
  : isHovered && palette
104
105
  ? palette.wallHoverStroke
105
106
  : '#1f2937';
106
- const fill = showSelectedChrome ? '#ffffff' : '#374151';
107
+ const fill = node.wallType === 'curtain' ? 'transparent' : showSelectedChrome ? '#ffffff' : '#374151';
107
108
  const children = [
108
109
  {
109
110
  kind: 'polygon',
@@ -121,6 +122,9 @@ export function buildWallFloorplan(node, ctx) {
121
122
  cursor: isSelected ? 'default' : undefined,
122
123
  },
123
124
  ];
125
+ if (node.wallType === 'curtain') {
126
+ children.push(...buildCurtainWallFloorplan(node, getWallEffectiveHeightForNodes(node, ctx.sceneNodes ?? {}), stroke, ctx.children));
127
+ }
124
128
  if (automaticDimensions) {
125
129
  const dimensionStroke = isSelected && palette ? palette.selectedStroke : (palette?.measurementStroke ?? '#334155');
126
130
  const dimensionStandard = constructionDimensionStandard({
@@ -0,0 +1,3 @@
1
+ import { type WallNode } from '@pascal-app/core';
2
+ export declare function buildWallLengthPatch(node: WallNode, nextLength: number): Partial<WallNode>;
3
+ //# sourceMappingURL=length-patch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"length-patch.d.ts","sourceRoot":"","sources":["../../src/wall/length-patch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiD,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAE/F,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAW1F"}
@@ -0,0 +1,14 @@
1
+ import { getClampedWallCurveOffset, getWallCurveLength } from '@pascal-app/core';
2
+ export function buildWallLengthPatch(node, nextLength) {
3
+ const length = getWallCurveLength(node);
4
+ if (!length || !Number.isFinite(nextLength) || nextLength <= 0)
5
+ return {};
6
+ const ratio = nextLength / length;
7
+ return {
8
+ end: [
9
+ node.start[0] + (node.end[0] - node.start[0]) * ratio,
10
+ node.start[1] + (node.end[1] - node.start[1]) * ratio,
11
+ ],
12
+ ...(node.curveOffset ? { curveOffset: getClampedWallCurveOffset(node) * ratio } : {}),
13
+ };
14
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"move-tool.d.ts","sourceRoot":"","sources":["../../src/wall/move-tool.tsx"],"names":[],"mappings":"AAEA,OAAO,EAwBL,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AAqIzB,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CA4iBrD,CAAA;AAED,eAAe,YAAY,CAAA"}
1
+ {"version":3,"file":"move-tool.d.ts","sourceRoot":"","sources":["../../src/wall/move-tool.tsx"],"names":[],"mappings":"AAEA,OAAO,EAwBL,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AAqIzB,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CA+jBrD,CAAA;AAED,eAAe,YAAY,CAAA"}
@@ -121,6 +121,7 @@ export const MoveWallTool = ({ node }) => {
121
121
  const levelId = node.parentId ?? null;
122
122
  pauseSceneHistory(useScene);
123
123
  let shouldRestoreOnCleanup = true;
124
+ let active = true;
124
125
  // Wall ids that currently carry a live position override. Cleared on commit
125
126
  // (after the final store write lands) and on cancel / external unmount.
126
127
  const touchedWallIds = new Set();
@@ -284,6 +285,13 @@ export const MoveWallTool = ({ node }) => {
284
285
  return linkedOriginalsRef.current.map((wall) => movedById.get(wall.id) ?? { id: wall.id, start: wall.start, end: wall.end });
285
286
  };
286
287
  const applyPreview = (nextStart, nextEnd) => {
288
+ const previous = previewRef.current ?? { start: originalStart, end: originalEnd };
289
+ if (nextStart[0] === previous.start[0] &&
290
+ nextStart[1] === previous.start[1] &&
291
+ nextEnd[0] === previous.end[0] &&
292
+ nextEnd[1] === previous.end[1])
293
+ return;
294
+ hasDraggedRef.current = true;
287
295
  previewRef.current = { start: nextStart, end: nextEnd };
288
296
  const centerX = (nextStart[0] + nextEnd[0]) / 2;
289
297
  const centerZ = (nextStart[1] + nextEnd[1]) / 2;
@@ -324,15 +332,24 @@ export const MoveWallTool = ({ node }) => {
324
332
  clearSurfaceOverrides();
325
333
  };
326
334
  const onGridMove = (event) => {
335
+ if (!active)
336
+ return;
327
337
  const rawX = event.localPosition[0];
328
338
  const rawZ = event.localPosition[2];
329
339
  const snapStep = getSegmentGridStep();
330
340
  // Anchor at the raw cursor so the displacement is measured in
331
341
  // continuous space.
332
342
  const anchor = dragAnchorRef.current ?? [rawX, rawZ];
343
+ const firstMove = dragAnchorRef.current === null;
333
344
  dragAnchorRef.current = anchor;
345
+ // Seeding a controller grab is not movement; don't snap an off-grid wall
346
+ // to the lattice before the user has moved their hand.
347
+ if (firstMove)
348
+ return;
334
349
  const rawDeltaX = rawX - anchor[0];
335
350
  const rawDeltaZ = rawZ - anchor[1];
351
+ if (!hasDraggedRef.current && Math.hypot(rawDeltaX, rawDeltaZ) < 1e-6)
352
+ return;
336
353
  // When the move is axis-locked (side-handle drag), snap the wall
337
354
  // center's absolute perpendicular offset to a multiple of
338
355
  // `snapStep`. For axis-aligned walls this puts the wall on grid
@@ -378,7 +395,6 @@ export const MoveWallTool = ({ node }) => {
378
395
  previousGridPosRef.current = constrainedGridPos;
379
396
  const nextCenter = [originalCenter[0] + deltaX, originalCenter[1] + deltaZ];
380
397
  const nextWall = buildWallFromCenter(nextCenter);
381
- hasDraggedRef.current = true;
382
398
  applyPreview(nextWall.start, nextWall.end);
383
399
  };
384
400
  const commitPreview = () => {
@@ -459,6 +475,9 @@ export const MoveWallTool = ({ node }) => {
459
475
  exitMoveMode();
460
476
  };
461
477
  const onPointerUp = () => {
478
+ if (!active)
479
+ return;
480
+ active = false;
462
481
  // Press-release without drag: dismiss the tool without committing.
463
482
  // This is the same UX as MoveWallEndpointTool / WallHeightArrowHandle
464
483
  // — pointer-down on the affordance starts the move, drag updates the
@@ -496,6 +515,9 @@ export const MoveWallTool = ({ node }) => {
496
515
  applyPreview(nextWall.start, nextWall.end);
497
516
  };
498
517
  const onCancel = () => {
518
+ if (!active)
519
+ return;
520
+ active = false;
499
521
  shouldRestoreOnCleanup = false;
500
522
  restoreOriginal();
501
523
  useViewer.getState().setSelection({ selectedIds: [nodeId] });
@@ -1 +1 @@
1
- {"version":3,"file":"paint.d.ts","sourceRoot":"","sources":["../../src/wall/paint.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,eAAe,EAOpB,KAAK,QAAQ,EAGd,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAA2C,KAAK,GAAG,EAAa,MAAM,OAAO,CAAA;AAqDpF;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,IAAI,EAAE,QAAQ,CAAA;IACd,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;KAAE,CAAA;IAC/C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;IACrD,aAAa,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;IAC5D,GAAG,CAAC,EAAE,GAAG,CAAA;CACV,GAAG,MAAM,GAAG,IAAI,CA+DhB;AAqCD;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,eAoCtB,CAAA"}
1
+ {"version":3,"file":"paint.d.ts","sourceRoot":"","sources":["../../src/wall/paint.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,eAAe,EAOpB,KAAK,QAAQ,EAGd,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAA2C,KAAK,GAAG,EAAa,MAAM,OAAO,CAAA;AAqDpF;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,IAAI,EAAE,QAAQ,CAAA;IACd,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;KAAE,CAAA;IAC/C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;IACrD,aAAa,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;IAC5D,GAAG,CAAC,EAAE,GAAG,CAAA;CACV,GAAG,MAAM,GAAG,IAAI,CAwEhB;AAsCD;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,eA8DtB,CAAA"}
@@ -1,4 +1,4 @@
1
- import { getEffectiveWallSurfaceMaterial, getWallBandSlotId, getWallFaceBandConfig, getWallFaceBandForHeight, getWallSurfaceSideFromBandSlot, parseMaterialRef, sceneRegistry, useScene, WALL_SURFACE_SLOT_DEFAULTS, } from '@pascal-app/core';
1
+ import { getCurtainWallConfig, getEffectiveWallSurfaceMaterial, getWallBandSlotId, getWallFaceBandConfig, getWallFaceBandForHeight, getWallSurfaceSideFromBandSlot, parseMaterialRef, sceneRegistry, useScene, WALL_SURFACE_SLOT_DEFAULTS, } from '@pascal-app/core';
2
2
  import { setSurfaceRaycastLayers } from '@pascal-app/viewer';
3
3
  import { Raycaster } from 'three';
4
4
  import { buildSlotPreviewMaterial, createSlotPaintCapability, previewSlotByUserData, } from '../shared/slot-paint';
@@ -57,6 +57,14 @@ function resolveWallSlotByRay(node, ray) {
57
57
  */
58
58
  export function resolveWallRole(args) {
59
59
  const { node, hitObject, materialIndex, normal, localPosition, ray } = args;
60
+ if (node.wallType === 'curtain') {
61
+ const root = sceneRegistry.nodes.get(node.id);
62
+ if (!(root && ray))
63
+ return null;
64
+ wallSlotRaycaster.ray.copy(ray);
65
+ const hit = wallSlotRaycaster.intersectObject(root, false)[0];
66
+ return (['curtain-frame', 'curtain-glass', 'curtain-solid'][hit?.face?.materialIndex ?? -1] ?? null);
67
+ }
60
68
  const directSlotId = hitObject?.userData?.slotId;
61
69
  if (typeof directSlotId === 'string' && WALL_SLOT_IDS.has(directSlotId)) {
62
70
  return directSlotId;
@@ -113,11 +121,12 @@ export function resolveWallRole(args) {
113
121
  */
114
122
  function applyWallPreview(args) {
115
123
  const { role, material, materialPreset } = args;
116
- if (!(role in WALL_ARRAY_SLOT_INDEX)) {
124
+ const curtainIndex = ['curtain-frame', 'curtain-glass', 'curtain-solid'].indexOf(role);
125
+ if (curtainIndex < 0 && !(role in WALL_ARRAY_SLOT_INDEX)) {
117
126
  return previewSlotByUserData(args);
118
127
  }
119
- const index = WALL_ARRAY_SLOT_INDEX[role];
120
- if (!index)
128
+ const index = curtainIndex >= 0 ? curtainIndex : WALL_ARRAY_SLOT_INDEX[role];
129
+ if (index === undefined)
121
130
  return previewSlotByUserData(args);
122
131
  const mesh = sceneRegistry.nodes.get(args.node.id);
123
132
  if (!(mesh && mesh.isMesh))
@@ -155,6 +164,32 @@ export const wallPaint = createSlotPaintCapability({
155
164
  }),
156
165
  applyPreview: applyWallPreview,
157
166
  legacyEffective: (node, role) => {
167
+ if (node.type === 'wall' && node.wallType === 'curtain') {
168
+ const config = getCurtainWallConfig(node);
169
+ const color = role === 'curtain-frame'
170
+ ? config.frameColor
171
+ : role === 'curtain-glass'
172
+ ? config.glassColor
173
+ : role === 'curtain-solid'
174
+ ? config.solidColor
175
+ : undefined;
176
+ if (!color)
177
+ return null;
178
+ return {
179
+ materialPreset: undefined,
180
+ material: {
181
+ preset: 'custom',
182
+ properties: {
183
+ color,
184
+ roughness: role === 'curtain-glass' ? config.glassRoughness : 0.4,
185
+ metalness: role === 'curtain-frame' ? 0.65 : 0,
186
+ opacity: role === 'curtain-glass' ? config.glassOpacity : 1,
187
+ transparent: role === 'curtain-glass',
188
+ side: 'front',
189
+ },
190
+ },
191
+ };
192
+ }
158
193
  const side = getWallSurfaceSideFromBandSlot(role);
159
194
  if (!side && role in WALL_SURFACE_SLOT_DEFAULTS) {
160
195
  return {
@@ -0,0 +1,4 @@
1
+ import { type AnyNode, type AnyNodeId, type WallNode } from '@pascal-app/core';
2
+ import { type PanelRow } from '@pascal-app/editor';
3
+ export declare function wallSettings(node: WallNode, nodes: Record<AnyNodeId, AnyNode>, update: (patch: Partial<WallNode>) => void, reshape?: () => void): PanelRow[];
4
+ //# sourceMappingURL=panel-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel-model.d.ts","sourceRoot":"","sources":["../../src/wall/panel-model.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,SAAS,EAad,KAAK,QAAQ,EAEd,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAEL,KAAK,QAAQ,EAGd,MAAM,oBAAoB,CAAA;AAiB3B,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EACjC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,IAAI,EAC1C,OAAO,GAAE,MAAM,IAId,GACA,QAAQ,EAAE,CAmNZ"}
@@ -0,0 +1,117 @@
1
+ import { buildWallFaceBandCountPatch, GROUND_SUPPORT_ID, getClampedWallCurveOffset, getMaxWallCurveOffset, getWallCurveLength, getWallFaceBandConfig, normalizeWallCurveOffset, terrainSupportLift, WALL_CHAIR_RAIL_DEFAULT, WALL_CROWN_DEFAULT, WALL_FACE_BAND_DEFAULT, WALL_SKIRTING_DEFAULT, } from '@pascal-app/core';
2
+ import { curveReshapeScope, triggerSFX, useInteractionScope, } from '@pascal-app/editor';
3
+ import { useViewer } from '@pascal-app/viewer';
4
+ import { resolveWallOpeningCeiling } from '../shared/wall-opening-ceiling';
5
+ import { hasWallCurveBlockingChildren } from './curve-eligibility';
6
+ import { buildWallLengthPatch } from './length-patch';
7
+ const profiles = {
8
+ skirting: ['flat', 'base-modern', 'base-colonial', 'base-shoe', 'base-ogee'],
9
+ crown: ['flat', 'crown-cove', 'crown-ogee', 'crown-craftsman', 'crown-layered'],
10
+ chairRail: ['flat', 'rail-rounded', 'rail-ogee', 'rail-picture', 'rail-stepped'],
11
+ };
12
+ const pretty = (value) => value
13
+ .replace(/^(base|crown|rail)-/, '')
14
+ .replace(/(^|[- ])\w/g, (s) => s.replace('-', ' ').toUpperCase());
15
+ export function wallSettings(node, nodes, update, reshape = () => {
16
+ triggerSFX('sfx:item-pick');
17
+ useInteractionScope.getState().begin(curveReshapeScope(node.id));
18
+ useViewer.getState().setSelection({ selectedIds: [] });
19
+ }) {
20
+ const rows = [];
21
+ const height = resolveWallOpeningCeiling(node, nodes);
22
+ const repairBase = () => ({
23
+ supportOffset: undefined,
24
+ ...(node.supportSlabId === GROUND_SUPPORT_ID &&
25
+ !(node.parentId && terrainSupportLift(nodes, node.parentId, ...node.start) != null)
26
+ ? { supportSlabId: undefined }
27
+ : {}),
28
+ });
29
+ const number = (section, id, label, value, min, max, step, onChange, unit = 'm') => rows.push({
30
+ section,
31
+ id,
32
+ kind: 'stepper',
33
+ label,
34
+ value,
35
+ min,
36
+ max,
37
+ step,
38
+ unit,
39
+ onChange: (next) => onChange(Math.max(min, Math.min(max, next))),
40
+ });
41
+ const choice = (section, id, label, value, onSelect) => rows.push({ section, id, kind: 'choice', label, value, onSelect });
42
+ const cycle = (section, id, label, value, values, onChange) => {
43
+ const change = (direction) => onChange(values[(Math.max(0, values.indexOf(value)) + direction + values.length) % values.length]);
44
+ rows.push({
45
+ section,
46
+ id,
47
+ kind: 'cycle',
48
+ label,
49
+ value: pretty(value),
50
+ next: () => change(1),
51
+ previous: () => change(-1),
52
+ });
53
+ };
54
+ const length = getWallCurveLength(node);
55
+ number('Dimensions', 'wall-length', 'Length', length, 0.1, 1000, 0.05, (next) => {
56
+ update(buildWallLengthPatch(node, next));
57
+ });
58
+ choice('Dimensions', 'wall-top', 'Top', node.height == null ? 'Follows level' : 'Custom height', () => update(node.height == null
59
+ ? { height: Math.max(0.1, height) }
60
+ : { height: undefined, ...repairBase() }));
61
+ if (node.height == null)
62
+ choice('Dimensions', 'wall-height-auto', 'Current height', `${Number(height.toFixed(3))} m`);
63
+ else
64
+ number('Dimensions', 'height', 'Height', node.height, 0.1, 1000, 0.05, (height) => update({ height }));
65
+ choice('Dimensions', 'wall-bottom', 'Bottom', node.fillToTerrain ? 'Fill to terrain' : 'Auto', () => update(node.fillToTerrain
66
+ ? { fillToTerrain: undefined, ...repairBase() }
67
+ : { fillToTerrain: true }));
68
+ number('Dimensions', 'thickness', 'Thickness', node.thickness ?? 0.1, 0.05, 1000, 0.01, (thickness) => update({ thickness }));
69
+ const blockedCurve = hasWallCurveBlockingChildren((node.children ?? []).flatMap((id) => nodes[id] ? [nodes[id]] : []));
70
+ if (!blockedCurve) {
71
+ const limit = Math.max(0.01, getMaxWallCurveOffset(node));
72
+ number('Dimensions', 'curveOffset', 'Curve', getClampedWallCurveOffset(node), -limit, limit, 0.05, (next) => update({ curveOffset: normalizeWallCurveOffset(node, next) }));
73
+ if (reshape)
74
+ rows.push({
75
+ section: 'Dimensions',
76
+ id: 'wall-reshape',
77
+ kind: 'action',
78
+ label: 'Reshape curve in scene',
79
+ onSelect: reshape,
80
+ });
81
+ }
82
+ const bands = getWallFaceBandConfig(node, height);
83
+ number('Wall bands', 'wall-band-count', 'Bands', bands.count, 1, 4, 1, (count) => update(buildWallFaceBandCountPatch(node, Math.round(count))), '');
84
+ const band = (key, label, max) => number('Wall bands', `wall-band-${key}`, label, bands[key], 0, Math.max(0, max), 0.01, (value) => update({
85
+ faceBands: {
86
+ ...WALL_FACE_BAND_DEFAULT,
87
+ ...node.faceBands,
88
+ enabled: bands.count > 1,
89
+ count: bands.count,
90
+ [key]: value,
91
+ },
92
+ }));
93
+ if (bands.count >= 2)
94
+ band('lowerHeight', 'Lower', height);
95
+ if (bands.count >= 3)
96
+ band('middleHeight', 'Middle', height - bands.lowerHeight);
97
+ if (bands.count >= 4)
98
+ band('upperHeight', 'Upper', height - bands.lowerHeight - bands.middleHeight);
99
+ for (const [key, title, defaults] of [
100
+ ['skirting', 'Skirting', WALL_SKIRTING_DEFAULT],
101
+ ['crown', 'Crown molding', WALL_CROWN_DEFAULT],
102
+ ['chairRail', 'Chair rail', WALL_CHAIR_RAIL_DEFAULT],
103
+ ]) {
104
+ const trim = { ...defaults, ...node[key] };
105
+ const patch = (value) => update({ [key]: { ...trim, ...value } });
106
+ choice(title, `${key}-enabled`, title, trim.enabled ? 'On' : 'Off', () => patch({ enabled: !trim.enabled }));
107
+ if (!trim.enabled)
108
+ continue;
109
+ cycle(title, `${key}-sides`, 'Sides', trim.sides, ['interior', 'exterior', 'both'], (sides) => patch({ sides: sides }));
110
+ cycle(title, `${key}-profile`, 'Profile', trim.profile, profiles[key], (profile) => patch({ profile: profile }));
111
+ number(title, `${key}-height`, 'Height', trim.height, 0.01, Math.max(0.05, height), 0.01, (height) => patch({ height }));
112
+ number(title, `${key}-proud`, 'Projection', trim.proud, 0.001, 0.2, 0.005, (proud) => patch({ proud }));
113
+ if (key === 'chairRail')
114
+ number(title, `${key}-offset`, 'Offset', trim.offsetY ?? 0, 0, Math.max(0.05, height - trim.height), 0.01, (offsetY) => patch({ offsetY }));
115
+ }
116
+ return rows;
117
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/wall/panel.tsx"],"names":[],"mappings":"AA0FA,MAAM,CAAC,OAAO,UAAU,SAAS,uCA8ThC"}
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/wall/panel.tsx"],"names":[],"mappings":"AA6FA,MAAM,CAAC,OAAO,UAAU,SAAS,uCAiWhC"}
@@ -4,9 +4,12 @@ import { buildWallFaceBandCountPatch, GROUND_SUPPORT_ID, getClampedWallCurveOffs
4
4
  import { ActionButton, ActionGroup, curveReshapeScope, formatLinearMeasurement, getLinearUnitLabel, linearControlValueToMeters, metersToLinearUnit, PanelSection, PanelWrapper, SegmentedControl, SliderControl, triggerSFX, useInteractionScope, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { Spline } from 'lucide-react';
7
- import { useCallback, useMemo, useRef } from 'react';
7
+ import { useCallback, useEffect, useMemo, useRef } from 'react';
8
8
  import { resolveWallOpeningCeiling } from '../shared/wall-opening-ceiling';
9
+ import { CurtainWallPanel } from './curtain-wall-panel';
9
10
  import { hasWallCurveBlockingChildren } from './curve-eligibility';
11
+ import { buildWallLengthPatch } from './length-patch';
12
+ import { createWallPropertyPreview } from './property-preview';
10
13
  /**
11
14
  * Base half of the plane-bound repair: a stamped draft offset goes, and a
12
15
  * ground host is dropped unless sculpted terrain actually supports it — a
@@ -90,28 +93,18 @@ export default function WallPanel() {
90
93
  // "Maximum update depth exceeded" cascade. Same fix in fence-panel.tsx.
91
94
  const nodeRef = useRef(node);
92
95
  nodeRef.current = node;
93
- const handleUpdate = useCallback((updates) => {
94
- if (!selectedId)
95
- return;
96
- useScene.getState().updateNode(selectedId, updates);
97
- }, [selectedId]);
96
+ const propertyPreview = useMemo(() => (selectedId ? createWallPropertyPreview(selectedId) : undefined), [selectedId]);
97
+ useEffect(() => () => propertyPreview?.cancel(), [propertyPreview]);
98
+ const handleUpdate = useCallback((updates) => propertyPreview?.commit(updates), [propertyPreview]);
99
+ const handlePreview = useCallback((updates) => propertyPreview?.preview(updates), [propertyPreview]);
100
+ const handleCommit = useCallback(() => propertyPreview?.commit(), [propertyPreview]);
101
+ const handleCancel = useCallback(() => propertyPreview?.cancel(), [propertyPreview]);
98
102
  const handleUpdateLength = useCallback((newLength) => {
99
103
  const n = nodeRef.current;
100
104
  if (!n || newLength <= 0)
101
105
  return;
102
- const dx = n.end[0] - n.start[0];
103
- const dz = n.end[1] - n.start[1];
104
- const currentLength = Math.sqrt(dx * dx + dz * dz);
105
- if (currentLength === 0)
106
- return;
107
- const dirX = dx / currentLength;
108
- const dirZ = dz / currentLength;
109
- const newEnd = [
110
- n.start[0] + dirX * newLength,
111
- n.start[1] + dirZ * newLength,
112
- ];
113
- handleUpdate({ end: newEnd });
114
- }, [handleUpdate]);
106
+ handlePreview(buildWallLengthPatch(n, newLength));
107
+ }, [handlePreview]);
115
108
  const handleTopModeChange = useCallback((mode) => {
116
109
  const n = nodeRef.current;
117
110
  if (!n)
@@ -174,25 +167,28 @@ export default function WallPanel() {
174
167
  const skirting = { ...WALL_SKIRTING_DEFAULT, ...(node.skirting ?? {}) };
175
168
  const crown = { ...WALL_CROWN_DEFAULT, ...(node.crown ?? {}) };
176
169
  const chairRail = { ...WALL_CHAIR_RAIL_DEFAULT, ...(node.chairRail ?? {}) };
177
- return (_jsxs(PanelWrapper, { icon: "/icons/wall.webp", onClose: handleClose, title: node.name || 'Wall', width: 280, children: [_jsxs(PanelSection, { title: "Dimensions", children: [_jsx(SliderControl, { label: "Length", max: metersToLinearUnit(1000, unit), min: metersToLinearUnit(0.1, unit), onChange: (value) => handleUpdateLength(linearControlValueToMeters(value, unit, { maxMeters: 1000, minMeters: 0.1 })), precision: 2, step: unit === 'imperial' ? 0.1 : 0.01, unit: unitLabel, value: displayLength }), _jsx("div", { className: "px-1 font-medium text-[10px] text-muted-foreground/80 uppercase tracking-wider", children: "Top" }), _jsx(SegmentedControl, { onChange: handleTopModeChange, options: [
170
+ return (_jsxs(PanelWrapper, { icon: "/icons/wall.webp", onClose: handleClose, title: node.name || 'Wall', width: 280, children: [_jsx(PanelSection, { title: "Wall type", children: _jsx(SegmentedControl, { onChange: (wallType) => handleUpdate({ wallType }), options: [
171
+ { label: 'Standard', value: 'standard' },
172
+ { label: 'Curtain wall', value: 'curtain' },
173
+ ], value: node.wallType ?? 'standard' }) }), _jsxs(PanelSection, { title: "Dimensions", children: [_jsx(SliderControl, { onCommit: handleCommit, onCancel: handleCancel, restoreOnCommit: false, previewWhileTyping: true, label: "Length", max: metersToLinearUnit(1000, unit), min: metersToLinearUnit(0.1, unit), onChange: (value) => handleUpdateLength(linearControlValueToMeters(value, unit, { maxMeters: 1000, minMeters: 0.1 })), precision: 2, step: unit === 'imperial' ? 0.1 : 0.01, unit: unitLabel, value: displayLength }), _jsx("div", { className: "px-1 font-medium text-[10px] text-muted-foreground/80 uppercase tracking-wider", children: "Top" }), _jsx(SegmentedControl, { onChange: handleTopModeChange, options: [
178
174
  { label: 'Follows level', value: 'storey' },
179
175
  { label: 'Custom height', value: 'custom' },
180
- ], value: isPlaneBound ? 'storey' : 'custom' }), isPlaneBound ? (_jsxs("div", { className: "px-1 text-[11px] text-muted-foreground", children: ["Currently ", formatLinearMeasurement(height, unit)] })) : (_jsx(SliderControl, { label: "Height", max: metersToLinearUnit(1000, unit), min: metersToLinearUnit(0.1, unit), onChange: (v) => handleUpdate({
176
+ ], value: isPlaneBound ? 'storey' : 'custom' }), isPlaneBound ? (_jsxs("div", { className: "px-1 text-[11px] text-muted-foreground", children: ["Currently ", formatLinearMeasurement(height, unit)] })) : (_jsx(SliderControl, { onCommit: handleCommit, onCancel: handleCancel, restoreOnCommit: false, previewWhileTyping: true, label: "Height", max: metersToLinearUnit(1000, unit), min: metersToLinearUnit(0.1, unit), onChange: (v) => handlePreview({
181
177
  height: linearControlValueToMeters(v, unit, { maxMeters: 1000, minMeters: 0.1 }),
182
178
  }), precision: 2, step: 0.1, unit: unitLabel, value: Math.round(displayHeight * 100) / 100 })), _jsx("div", { className: "px-1 font-medium text-[10px] text-muted-foreground/80 uppercase tracking-wider", children: "Bottom" }), _jsx(SegmentedControl, { onChange: handleInfillChange, options: [
183
179
  { label: 'Auto', value: 'auto' },
184
180
  { label: 'Fill to terrain', value: 'terrain' },
185
- ], value: followsTerrain ? 'terrain' : 'auto' }), followsTerrain && (_jsx("div", { className: "px-1 text-[11px] text-muted-foreground", children: "Extends downward to meet the terrain. Height and top stay unchanged." })), _jsx(SliderControl, { label: "Thickness", max: metersToLinearUnit(1000, unit), min: metersToLinearUnit(0.05, unit), onChange: (v) => handleUpdate({
181
+ ], value: followsTerrain ? 'terrain' : 'auto' }), followsTerrain && (_jsx("div", { className: "px-1 text-[11px] text-muted-foreground", children: "Extends downward to meet the terrain. Height and top stay unchanged." })), _jsx(SliderControl, { onCommit: handleCommit, onCancel: handleCancel, restoreOnCommit: false, previewWhileTyping: true, label: node.wallType === 'curtain' ? 'Frame depth' : 'Thickness', max: metersToLinearUnit(1000, unit), min: metersToLinearUnit(0.05, unit), onChange: (v) => handlePreview({
186
182
  thickness: linearControlValueToMeters(v, unit, {
187
183
  maxMeters: 1000,
188
184
  minMeters: 0.05,
189
185
  }),
190
- }), precision: 3, step: 0.01, unit: unitLabel, value: Math.round(displayThickness * 1000) / 1000 }), !hasWallChildrenBlockingCurve && (_jsx(SliderControl, { label: "Curve", max: Math.max(metersToLinearUnit(0.01, unit), displayMaxCurveOffset), min: -Math.max(metersToLinearUnit(0.01, unit), displayMaxCurveOffset), onChange: (v) => handleUpdate({
186
+ }), precision: 3, step: 0.01, unit: unitLabel, value: Math.round(displayThickness * 1000) / 1000 }), !hasWallChildrenBlockingCurve && (_jsx(SliderControl, { onCommit: handleCommit, onCancel: handleCancel, restoreOnCommit: false, previewWhileTyping: true, label: "Curve", max: Math.max(metersToLinearUnit(0.01, unit), displayMaxCurveOffset), min: -Math.max(metersToLinearUnit(0.01, unit), displayMaxCurveOffset), onChange: (v) => handlePreview({
191
187
  curveOffset: normalizeWallCurveOffset(node, linearControlValueToMeters(v, unit, {
192
188
  maxMeters: curveOffsetLimit,
193
189
  minMeters: -curveOffsetLimit,
194
190
  })),
195
- }), precision: 2, step: 0.1, unit: unitLabel, value: Math.round(displayCurveOffset * 100) / 100 }))] }), _jsx(WallFaceBandSection, { node: node, onUpdate: handleUpdate, unit: unit, unitLabel: unitLabel, wallHeightMeters: wallHeightMeters }), _jsx(WallTrimSection, { node: node, onUpdate: handleUpdate, title: "Skirting", trimKey: "skirting", trimValue: skirting, unit: unit, unitLabel: unitLabel, wallHeightMeters: wallHeightMeters }), _jsx(WallTrimSection, { node: node, onUpdate: handleUpdate, title: "Crown molding", trimKey: "crown", trimValue: crown, unit: unit, unitLabel: unitLabel, wallHeightMeters: wallHeightMeters }), _jsx(WallTrimSection, { node: node, onUpdate: handleUpdate, title: "Chair rail", trimKey: "chairRail", trimValue: chairRail, unit: unit, unitLabel: unitLabel, wallHeightMeters: wallHeightMeters }), !hasWallChildrenBlockingCurve && (_jsx(PanelSection, { title: "Actions", children: _jsx(ActionGroup, { children: _jsx(ActionButton, { icon: _jsx(Spline, { className: "h-3.5 w-3.5" }), label: "Curve", onClick: handleCurve }) }) }))] }));
191
+ }), precision: 2, step: 0.1, unit: unitLabel, value: Math.round(displayCurveOffset * 100) / 100 }))] }), node.wallType === 'curtain' ? (_jsx(CurtainWallPanel, { height: height, node: node, onUpdate: handleUpdate, onPreview: handlePreview, onCommit: handleCommit, onCancel: handleCancel, unit: unit }, node.id)) : (_jsxs(_Fragment, { children: [_jsx(WallFaceBandSection, { node: node, onUpdate: handleUpdate, unit: unit, unitLabel: unitLabel, wallHeightMeters: wallHeightMeters }), _jsx(WallTrimSection, { node: node, onUpdate: handleUpdate, title: "Skirting", trimKey: "skirting", trimValue: skirting, unit: unit, unitLabel: unitLabel, wallHeightMeters: wallHeightMeters }), _jsx(WallTrimSection, { node: node, onUpdate: handleUpdate, title: "Crown molding", trimKey: "crown", trimValue: crown, unit: unit, unitLabel: unitLabel, wallHeightMeters: wallHeightMeters }), _jsx(WallTrimSection, { node: node, onUpdate: handleUpdate, title: "Chair rail", trimKey: "chairRail", trimValue: chairRail, unit: unit, unitLabel: unitLabel, wallHeightMeters: wallHeightMeters })] })), !hasWallChildrenBlockingCurve && (_jsx(PanelSection, { title: "Actions", children: _jsx(ActionGroup, { children: _jsx(ActionButton, { icon: _jsx(Spline, { className: "h-3.5 w-3.5" }), label: "Curve", onClick: handleCurve }) }) }))] }));
196
192
  }
197
193
  function WallFaceBandSection({ node, onUpdate, unit, unitLabel, wallHeightMeters, }) {
198
194
  const bandConfig = getWallFaceBandConfig(node, wallHeightMeters);
@@ -0,0 +1,7 @@
1
+ import { type AnyNodeId, type WallNode } from '@pascal-app/core';
2
+ export declare function createWallPropertyPreview(id: AnyNodeId): {
3
+ preview(patch: Partial<WallNode>): void;
4
+ commit(patch?: Partial<WallNode>): void;
5
+ cancel: () => void;
6
+ };
7
+ //# sourceMappingURL=property-preview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property-preview.d.ts","sourceRoot":"","sources":["../../src/wall/property-preview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAkC,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEhG,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,SAAS;mBASpC,OAAO,CAAC,QAAQ,CAAC;mBAKjB,OAAO,CAAC,QAAQ,CAAC;;EAiBnC"}