@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,31 @@
1
+ import { useLiveNodeOverrides, useScene } from '@pascal-app/core';
2
+ export function createWallPropertyPreview(id) {
3
+ let pending;
4
+ const clear = () => {
5
+ if (!pending)
6
+ return;
7
+ useLiveNodeOverrides.getState().clearFields(id, Object.keys(pending));
8
+ pending = undefined;
9
+ useScene.getState().markDirty(id);
10
+ };
11
+ return {
12
+ preview(patch) {
13
+ pending = { ...pending, ...patch };
14
+ useLiveNodeOverrides.getState().set(id, patch);
15
+ useScene.getState().markDirty(id);
16
+ },
17
+ commit(patch) {
18
+ const live = useLiveNodeOverrides.getState().get(id);
19
+ const current = pending && live
20
+ ? Object.fromEntries(Object.keys(pending)
21
+ .filter((key) => key in live)
22
+ .map((key) => [key, live[key]]))
23
+ : undefined;
24
+ const updates = { ...current, ...patch };
25
+ if (Object.keys(updates).length && useScene.getState().nodes[id]?.type === 'wall')
26
+ useScene.getState().updateNode(id, updates);
27
+ clear();
28
+ },
29
+ cancel: clear,
30
+ };
31
+ }
@@ -0,0 +1,149 @@
1
+ import { type AnyNodeId, type WallConstructionOptions, type WallNode, type WallPlanPoint } from '@pascal-app/core';
2
+ export declare function createWallRectangle(levelId: AnyNodeId, start: WallPlanPoint, end: WallPlanPoint, defaults?: Partial<WallNode>, options?: WallConstructionOptions): {
3
+ object: "node";
4
+ parentId: string | null;
5
+ visible: boolean;
6
+ metadata: Record<string, unknown>;
7
+ id: `wall_${string}`;
8
+ type: "wall";
9
+ children: (`item_${string}` | `procedural-item_${string}` | `leanto_${string}` | `door_${string}` | `window_${string}`)[];
10
+ start: [number, number];
11
+ end: [number, number];
12
+ frontSide: "unknown" | "interior" | "exterior";
13
+ backSide: "unknown" | "interior" | "exterior";
14
+ name?: string | undefined;
15
+ camera?: {
16
+ position: [number, number, number];
17
+ target: [number, number, number];
18
+ mode: "perspective" | "orthographic";
19
+ fov?: number | undefined;
20
+ zoom?: number | undefined;
21
+ } | undefined;
22
+ wallType?: "standard" | "curtain" | undefined;
23
+ curtainWall?: {
24
+ construction: "stick" | "unitized";
25
+ framing: "capped" | "vertical-caps" | "horizontal-caps" | "structural-glazing";
26
+ columns: {
27
+ layout: "count" | "maximum-spacing" | "fixed-spacing";
28
+ count: number;
29
+ spacing: number;
30
+ alignment: "center" | "start" | "end";
31
+ };
32
+ rows: {
33
+ layout: "count" | "maximum-spacing" | "fixed-spacing";
34
+ count: number;
35
+ spacing: number;
36
+ alignment: "center" | "start" | "end";
37
+ };
38
+ mullionWidth: number;
39
+ transomWidth: number;
40
+ perimeterWidth: number;
41
+ jointWidth: number;
42
+ glassThickness: number;
43
+ panelType: "glass" | "solid" | "empty";
44
+ spandrel: "top" | "none" | "bottom";
45
+ frameColor: string;
46
+ glassColor: string;
47
+ solidColor: string;
48
+ glassOpacity: number;
49
+ glassRoughness: number;
50
+ panels: {
51
+ column: number;
52
+ row: number;
53
+ type: "glass" | "solid" | "empty";
54
+ }[];
55
+ } | undefined;
56
+ material?: {
57
+ id?: string | undefined;
58
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
59
+ properties?: {
60
+ color: string;
61
+ roughness: number;
62
+ metalness: number;
63
+ opacity: number;
64
+ transparent: boolean;
65
+ side: "front" | "back" | "double";
66
+ } | undefined;
67
+ texture?: {
68
+ url: string;
69
+ repeat?: [number, number] | undefined;
70
+ scale?: number | undefined;
71
+ } | undefined;
72
+ } | undefined;
73
+ materialPreset?: string | undefined;
74
+ interiorMaterial?: {
75
+ id?: string | undefined;
76
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
77
+ properties?: {
78
+ color: string;
79
+ roughness: number;
80
+ metalness: number;
81
+ opacity: number;
82
+ transparent: boolean;
83
+ side: "front" | "back" | "double";
84
+ } | undefined;
85
+ texture?: {
86
+ url: string;
87
+ repeat?: [number, number] | undefined;
88
+ scale?: number | undefined;
89
+ } | undefined;
90
+ } | undefined;
91
+ interiorMaterialPreset?: string | undefined;
92
+ exteriorMaterial?: {
93
+ id?: string | undefined;
94
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
95
+ properties?: {
96
+ color: string;
97
+ roughness: number;
98
+ metalness: number;
99
+ opacity: number;
100
+ transparent: boolean;
101
+ side: "front" | "back" | "double";
102
+ } | undefined;
103
+ texture?: {
104
+ url: string;
105
+ repeat?: [number, number] | undefined;
106
+ scale?: number | undefined;
107
+ } | undefined;
108
+ } | undefined;
109
+ exteriorMaterialPreset?: string | undefined;
110
+ slots?: Record<string, string> | undefined;
111
+ thickness?: number | undefined;
112
+ height?: number | undefined;
113
+ curveOffset?: number | undefined;
114
+ supportSlabId?: string | undefined;
115
+ supportOffset?: number | undefined;
116
+ fillToTerrain?: boolean | undefined;
117
+ faceBands?: {
118
+ enabled: boolean;
119
+ count: number;
120
+ lowerHeight: number;
121
+ middleHeight: number;
122
+ upperHeight: number;
123
+ } | undefined;
124
+ skirting?: {
125
+ enabled: boolean;
126
+ sides: "interior" | "exterior" | "both";
127
+ height: number;
128
+ proud: number;
129
+ profile: "flat" | "bevel" | "triangle" | "cove" | "bullnose" | "base-modern" | "base-colonial" | "base-shoe" | "base-ogee" | "crown-cove" | "crown-ogee" | "crown-craftsman" | "crown-layered" | "rail-rounded" | "rail-ogee" | "rail-picture" | "rail-stepped";
130
+ offsetY?: number | undefined;
131
+ } | undefined;
132
+ crown?: {
133
+ enabled: boolean;
134
+ sides: "interior" | "exterior" | "both";
135
+ height: number;
136
+ proud: number;
137
+ profile: "flat" | "bevel" | "triangle" | "cove" | "bullnose" | "base-modern" | "base-colonial" | "base-shoe" | "base-ogee" | "crown-cove" | "crown-ogee" | "crown-craftsman" | "crown-layered" | "rail-rounded" | "rail-ogee" | "rail-picture" | "rail-stepped";
138
+ offsetY?: number | undefined;
139
+ } | undefined;
140
+ chairRail?: {
141
+ enabled: boolean;
142
+ sides: "interior" | "exterior" | "both";
143
+ height: number;
144
+ proud: number;
145
+ profile: "flat" | "bevel" | "triangle" | "cove" | "bullnose" | "base-modern" | "base-colonial" | "base-shoe" | "base-ogee" | "crown-cove" | "crown-ogee" | "crown-craftsman" | "crown-layered" | "rail-rounded" | "rail-ogee" | "rail-picture" | "rail-stepped";
146
+ offsetY?: number | undefined;
147
+ } | undefined;
148
+ }[];
149
+ //# sourceMappingURL=rectangle-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rectangle-command.d.ts","sourceRoot":"","sources":["../../src/wall/rectangle-command.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAKd,KAAK,uBAAuB,EAC5B,KAAK,QAAQ,EACb,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAA;AAEzB,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,SAAS,EAClB,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,aAAa,EAClB,QAAQ,GAAE,OAAO,CAAC,QAAQ,CAAM,EAChC,OAAO,CAAC,EAAE,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAmBlC"}
@@ -0,0 +1,22 @@
1
+ import { planWallRectangle, resolveWallConstruction, runAsSingleSceneHistoryStep, useScene, } from '@pascal-app/core';
2
+ export function createWallRectangle(levelId, start, end, defaults = {}, options) {
3
+ const scene = useScene.getState();
4
+ if (scene.readOnly)
5
+ throw Error('This scene is read-only.');
6
+ const plan = planWallRectangle(scene.nodes, { levelId, start, end, wallDefaults: defaults });
7
+ if (!plan.changes.create.length && !plan.changes.update.length && !plan.changes.delete.length)
8
+ return [];
9
+ const construction = resolveWallConstruction(scene.nodes, levelId, plan.walls, options);
10
+ const walls = new Map(construction.walls.map((w) => [w.id, w]));
11
+ const changes = {
12
+ ...plan.changes,
13
+ create: plan.changes.create.map((op) => ({
14
+ ...op,
15
+ node: walls.get(op.node.id) ?? op.node,
16
+ })),
17
+ };
18
+ if (construction.sourceSupportUpdate)
19
+ changes.update.push(construction.sourceSupportUpdate);
20
+ runAsSingleSceneHistoryStep(useScene, () => scene.applyNodeChanges(changes));
21
+ return construction.walls;
22
+ }
@@ -0,0 +1,2 @@
1
+ export default function RectangleWallTool(): import("react").JSX.Element;
2
+ //# sourceMappingURL=rectangle-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rectangle-tool.d.ts","sourceRoot":"","sources":["../../src/wall/rectangle-tool.tsx"],"names":[],"mappings":"AAmCA,MAAM,CAAC,OAAO,UAAU,iBAAiB,gCAkMxC"}
@@ -0,0 +1,147 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { emitter, useScene, wallRectangleCorners, } from '@pascal-app/core';
4
+ import { CursorSphere, clearPlacementSurface, DRAFT_LABEL_Y_OFFSET, DraftMeasurementLabel, EDITOR_LAYER, formatLinearMeasurement, isMagneticSnapActive, markToolCancelConsumed, NO_RAYCAST, publishHorizontalConstructionPlane, resolveEventConstructionPlane, snapWallDraftPointDetailed, triggerSFX, useEditor, useInteractionScope, useLinearDisplay, useRegistryToolContext, useWallSnapIndicator, } from '@pascal-app/editor';
5
+ import { getSceneTheme, useViewer } from '@pascal-app/viewer';
6
+ import { useThree } from '@react-three/fiber';
7
+ import { useEffect, useState } from 'react';
8
+ import { DoubleSide } from 'three';
9
+ import { createWallRectangle } from './rectangle-command';
10
+ export default function RectangleWallTool() {
11
+ const { activeLevelId, isCameraDragging } = useRegistryToolContext();
12
+ const canvas = useThree((s) => s.gl.domElement);
13
+ const { isImperial } = useLinearDisplay('m', 2);
14
+ const isDark = useViewer((state) => getSceneTheme(state.sceneTheme).appearance === 'dark');
15
+ const measurementColor = isDark ? '#ffffff' : '#111111';
16
+ const measurementShadowColor = isDark ? '#111111' : '#ffffff';
17
+ const defaults = useEditor((s) => s.toolDefaults.wall);
18
+ const [draft, setDraft] = useState(null);
19
+ const [message, setMessage] = useState('');
20
+ const [cursor, setCursor] = useState(null);
21
+ const levelHeight = useScene((s) => activeLevelId && s.nodes[activeLevelId]?.type === 'level' ? s.nodes[activeLevelId].height : 3);
22
+ const height = typeof defaults?.height === 'number' ? defaults.height : (levelHeight ?? 3);
23
+ const thickness = typeof defaults?.thickness === 'number' ? defaults.thickness : 0.1;
24
+ useEffect(() => {
25
+ if (!activeLevelId)
26
+ return;
27
+ setDraft(null);
28
+ setMessage('');
29
+ let start = null;
30
+ let end = null;
31
+ let plane = null;
32
+ useInteractionScope.getState().begin({ kind: 'drafting', tool: 'wall' });
33
+ const pointFor = (e) => {
34
+ const result = snapWallDraftPointDetailed({
35
+ point: [e.localPosition[0], e.localPosition[2]],
36
+ walls: Object.values(useScene.getState().nodes).filter((n) => n.type === 'wall' && n.parentId === activeLevelId),
37
+ magnetic: isMagneticSnapActive(),
38
+ });
39
+ useWallSnapIndicator.getState().set(result.snap
40
+ ? {
41
+ x: result.point[0],
42
+ z: result.point[1],
43
+ kind: result.snap,
44
+ wallIds: result.targetWallIds,
45
+ }
46
+ : null);
47
+ return result.point;
48
+ };
49
+ const move = (e) => {
50
+ if (e.nativeEvent.target !== canvas || isCameraDragging())
51
+ return;
52
+ const point = pointFor(e);
53
+ const hoverPlane = plane ?? resolveEventConstructionPlane(e, null);
54
+ if (plane)
55
+ publishHorizontalConstructionPlane(e, plane);
56
+ setCursor([point[0], hoverPlane.localY, point[1]]);
57
+ setMessage('');
58
+ if (!start)
59
+ return;
60
+ // The line draft's tick: once per snapped corner position.
61
+ if (end && (end[0] !== point[0] || end[1] !== point[1]))
62
+ triggerSFX('sfx:grid-snap');
63
+ end = point;
64
+ setDraft({ start, end: point, y: hoverPlane.localY });
65
+ };
66
+ const leave = () => {
67
+ setCursor(null);
68
+ useWallSnapIndicator.getState().clear();
69
+ };
70
+ const cancel = () => {
71
+ if (start)
72
+ markToolCancelConsumed();
73
+ start = null;
74
+ end = null;
75
+ plane = null;
76
+ setDraft(null);
77
+ setMessage('');
78
+ leave();
79
+ clearPlacementSurface();
80
+ };
81
+ const click = (e) => {
82
+ if (e.nativeEvent.target !== canvas || e.nativeEvent.button !== 0 || isCameraDragging())
83
+ return;
84
+ const point = pointFor(e);
85
+ if (!start) {
86
+ start = point;
87
+ end = point;
88
+ plane = resolveEventConstructionPlane(e, null);
89
+ publishHorizontalConstructionPlane(e, plane);
90
+ setCursor([point[0], plane.localY, point[1]]);
91
+ setDraft({ start, end: point, y: plane.localY });
92
+ setMessage('');
93
+ triggerSFX('sfx:structure-build-start');
94
+ return;
95
+ }
96
+ try {
97
+ createWallRectangle(activeLevelId, start, point, useEditor.getState().toolDefaults.wall ?? {}, {
98
+ constructionElevation: plane?.elevation,
99
+ preferredSupportSlabId: plane?.supportSlabId,
100
+ constructionHeight: height,
101
+ });
102
+ cancel();
103
+ triggerSFX('sfx:structure-build');
104
+ }
105
+ catch (error) {
106
+ setMessage(error.message);
107
+ }
108
+ };
109
+ emitter.on('grid:move', move);
110
+ emitter.on('grid:click', click);
111
+ emitter.on('tool:cancel', cancel);
112
+ canvas.addEventListener('pointerleave', leave);
113
+ return () => {
114
+ emitter.off('grid:move', move);
115
+ emitter.off('grid:click', click);
116
+ emitter.off('tool:cancel', cancel);
117
+ canvas.removeEventListener('pointerleave', leave);
118
+ useWallSnapIndicator.getState().clear();
119
+ clearPlacementSurface();
120
+ useInteractionScope.getState().endIf((s) => s.kind === 'drafting' && s.tool === 'wall');
121
+ };
122
+ }, [activeLevelId, height, canvas, isCameraDragging]);
123
+ const corners = draft ? wallRectangleCorners(draft.start, draft.end) : [];
124
+ const unit = isImperial ? 'imperial' : 'metric';
125
+ // Label the two sides meeting at the cursor corner, as the floor plan does.
126
+ const cursorIndex = draft
127
+ ? corners.findIndex(([x, z]) => x === draft.end[0] && z === draft.end[1])
128
+ : -1;
129
+ const sideLabels = draft && cursorIndex >= 0
130
+ ? [cursorIndex + 3, cursorIndex].map((side) => {
131
+ const a = corners[side % 4];
132
+ const b = corners[(side + 1) % 4];
133
+ return {
134
+ label: formatLinearMeasurement(Math.hypot(b[0] - a[0], b[1] - a[1]), unit),
135
+ position: [
136
+ (a[0] + b[0]) / 2,
137
+ draft.y + height + DRAFT_LABEL_Y_OFFSET,
138
+ (a[1] + b[1]) / 2,
139
+ ],
140
+ };
141
+ })
142
+ : [];
143
+ return (_jsxs("group", { children: [_jsx(CursorSphere, { name: "rectangle-wall-cursor", height: height, position: cursor ?? [0, 0, 0], visible: !!cursor }), corners.map((a, i) => {
144
+ const b = corners[(i + 1) % 4];
145
+ return (_jsxs("mesh", { layers: EDITOR_LAYER, raycast: NO_RAYCAST, renderOrder: 1, position: [(a[0] + b[0]) / 2, draft.y + height / 2, (a[1] + b[1]) / 2], rotation: [0, -Math.atan2(b[1] - a[1], b[0] - a[0]), 0], children: [_jsx("boxGeometry", { args: [Math.hypot(b[0] - a[0], b[1] - a[1]), height, thickness] }), _jsx("meshBasicMaterial", { color: message ? '#ef4444' : '#818cf8', depthTest: false, depthWrite: false, opacity: 0.5, side: DoubleSide, transparent: true })] }, i));
146
+ }), draft && message ? (_jsx(DraftMeasurementLabel, { color: "#ef4444", label: message, position: [draft.end[0], draft.y + height + DRAFT_LABEL_Y_OFFSET, draft.end[1]], shadowColor: measurementShadowColor })) : (sideLabels.map((side, index) => (_jsx(DraftMeasurementLabel, { color: measurementColor, label: side.label, position: side.position, shadowColor: measurementShadowColor }, index))))] }));
147
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/wall/renderer.tsx"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AAsCzB;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,YAAY,GAAI,UAAU;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,gCA4IjD,CAAA;AAED,eAAe,YAAY,CAAA"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/wall/renderer.tsx"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AAuCzB;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,YAAY,GAAI,UAAU;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,gCAyJjD,CAAA;AAED,eAAe,YAAY,CAAA"}
@@ -1,10 +1,11 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { hiddenWallPointerEventsHeld, useLiveNodeOverrides, useRegistry, useScene, } from '@pascal-app/core';
4
- import { getVisibleWallMaterials, NodeRenderer, useLibraryMaterialsVersion, useNodeEvents, useViewer, } from '@pascal-app/viewer';
4
+ import { NodeRenderer, SHADOW_ONLY_LAYER, useLibraryMaterialsVersion, useNodeEvents, useViewer, } from '@pascal-app/viewer';
5
5
  import { useEffect, useLayoutEffect, useMemo, useRef } from 'react';
6
6
  import { useShallow } from 'zustand/react/shallow';
7
7
  import { createPlaceholderGeometry } from '../shared/placeholder-geometry';
8
+ import { getCurtainAwareWallMaterials } from './curtain-wall-materials';
8
9
  import { extractWallSelectionRay, WALL_COLLISION_MESH_NAME, wallPointerEventsSuppressed, } from './pointer-transparency';
9
10
  import { createWallRayHitClassifier } from './selection-hit-owner';
10
11
  import { createWallTreatmentSelector, useWallTreatmentLevelData } from './treatment-level-data';
@@ -38,6 +39,7 @@ const WallRenderer = ({ node }) => {
38
39
  const ref = useRef(null);
39
40
  const placeholderGeometry = useMemo(() => createPlaceholderGeometry(3), []);
40
41
  const collisionPlaceholderGeometry = useMemo(() => createPlaceholderGeometry(), []);
42
+ const shadowPlaceholderGeometry = useMemo(() => createPlaceholderGeometry(), []);
41
43
  useRegistry(node.id, 'wall', ref);
42
44
  useLayoutEffect(() => {
43
45
  useScene.getState().markDirty(node.id);
@@ -46,8 +48,9 @@ const WallRenderer = ({ node }) => {
46
48
  return () => {
47
49
  placeholderGeometry.dispose();
48
50
  collisionPlaceholderGeometry.dispose();
51
+ shadowPlaceholderGeometry.dispose();
49
52
  };
50
- }, [collisionPlaceholderGeometry, placeholderGeometry]);
53
+ }, [collisionPlaceholderGeometry, placeholderGeometry, shadowPlaceholderGeometry]);
51
54
  const rawHandlers = useNodeEvents(node, 'wall');
52
55
  // Hidden walls participate in hover/selection NEAREST-FIRST: when the
53
56
  // wall-mode pass hides this wall (`WallCutout` stamps `userData.wallHidden`
@@ -110,7 +113,7 @@ const WallRenderer = ({ node }) => {
110
113
  // register after mount, and a dangling ref cached as the slot default must
111
114
  // re-resolve when they land.
112
115
  const libraryMaterialsVersion = useLibraryMaterialsVersion();
113
- const baseMaterials = getVisibleWallMaterials(node, shading, textures, colorPreset, sceneTheme, sceneMaterials);
116
+ const baseMaterials = getCurtainAwareWallMaterials(treatmentNode, shading, textures, colorPreset, sceneTheme, sceneMaterials).visible;
114
117
  // biome-ignore lint/correctness/useExhaustiveDependencies: libraryMaterialsVersion invalidates the ref resolution inside createWallExtraSlotMaterials
115
118
  const extraMaterials = useMemo(() => createWallExtraSlotMaterials(node, shading, sceneMaterials), [node, sceneMaterials, shading, libraryMaterialsVersion]);
116
119
  useEffect(() => () => {
@@ -119,6 +122,6 @@ const WallRenderer = ({ node }) => {
119
122
  for (const entry of owned)
120
123
  entry.dispose();
121
124
  }, [baseMaterials, extraMaterials]);
122
- return (_jsxs("mesh", { castShadow: true, geometry: placeholderGeometry, material: baseMaterials, receiveShadow: true, ref: ref, visible: node.visible, children: [_jsx("mesh", { geometry: collisionPlaceholderGeometry, name: WALL_COLLISION_MESH_NAME, visible: false, ...handlers }), hasWallTreatments(treatmentNode) && (_jsx(WallTreatmentSubscription, { childrenNodes: childNodes, materials: extraMaterials, node: treatmentNode })), (node.children ?? []).map((childId) => (_jsx(NodeRenderer, { nodeId: childId }, `${node.id}:${childId}`)))] }));
125
+ return (_jsxs("mesh", { castShadow: node.wallType !== 'curtain', geometry: placeholderGeometry, material: baseMaterials, receiveShadow: true, ref: ref, visible: node.visible, children: [_jsx("mesh", { name: "curtain-wall-shadow", userData: { pascalExport: 'strip' }, geometry: shadowPlaceholderGeometry, layers: SHADOW_ONLY_LAYER, castShadow: true, visible: node.wallType === 'curtain', raycast: () => { }, children: _jsx("meshBasicMaterial", {}) }), _jsx("mesh", { geometry: collisionPlaceholderGeometry, name: WALL_COLLISION_MESH_NAME, visible: false, ...handlers }), node.wallType !== 'curtain' && hasWallTreatments(treatmentNode) && (_jsx(WallTreatmentSubscription, { childrenNodes: childNodes, materials: extraMaterials, node: treatmentNode })), (node.children ?? []).map((childId) => (_jsx(NodeRenderer, { nodeId: childId }, `${node.id}:${childId}`)))] }));
123
126
  };
124
127
  export default WallRenderer;
@@ -1,4 +1,4 @@
1
- import { type SlotDeclaration } from '@pascal-app/core';
1
+ import { type SlotDeclaration, type WallNode } from '@pascal-app/core';
2
2
  /**
3
3
  * A wall exposes two paintable faces — interior + exterior. Painting writes
4
4
  * `node.slots[interior|exterior]` via `wallPaint` like every other kind; this
@@ -6,5 +6,5 @@ import { type SlotDeclaration } from '@pascal-app/core';
6
6
  * keeps walls on the same `{ slotId, label, default }` contract. The defaults
7
7
  * come from core so the viewer's material resolver renders the identical value.
8
8
  */
9
- export declare function wallSlots(): SlotDeclaration[];
9
+ export declare function wallSlots(node?: WallNode): SlotDeclaration[];
10
10
  //# sourceMappingURL=slots.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"slots.d.ts","sourceRoot":"","sources":["../../src/wall/slots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAA8B,MAAM,kBAAkB,CAAA;AAEnF;;;;;;GAMG;AACH,wBAAgB,SAAS,IAAI,eAAe,EAAE,CA2E7C"}
1
+ {"version":3,"file":"slots.d.ts","sourceRoot":"","sources":["../../src/wall/slots.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EAEpB,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AAEzB;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,eAAe,EAAE,CAmF5D"}
@@ -1,4 +1,4 @@
1
- import { WALL_SURFACE_SLOT_DEFAULTS } from '@pascal-app/core';
1
+ import { getCurtainWallConfig, WALL_SURFACE_SLOT_DEFAULTS, } from '@pascal-app/core';
2
2
  /**
3
3
  * A wall exposes two paintable faces — interior + exterior. Painting writes
4
4
  * `node.slots[interior|exterior]` via `wallPaint` like every other kind; this
@@ -6,7 +6,15 @@ import { WALL_SURFACE_SLOT_DEFAULTS } from '@pascal-app/core';
6
6
  * keeps walls on the same `{ slotId, label, default }` contract. The defaults
7
7
  * come from core so the viewer's material resolver renders the identical value.
8
8
  */
9
- export function wallSlots() {
9
+ export function wallSlots(node) {
10
+ if (node?.wallType === 'curtain') {
11
+ const config = getCurtainWallConfig(node);
12
+ return [
13
+ { slotId: 'curtain-frame', label: 'Frame', default: config.frameColor },
14
+ { slotId: 'curtain-glass', label: 'Glass', default: config.glassColor },
15
+ { slotId: 'curtain-solid', label: 'Solid panels', default: config.solidColor },
16
+ ];
17
+ }
10
18
  return [
11
19
  { slotId: 'interior', label: 'Interior', default: WALL_SURFACE_SLOT_DEFAULTS.interior },
12
20
  { slotId: 'exterior', label: 'Exterior', default: WALL_SURFACE_SLOT_DEFAULTS.exterior },
@@ -0,0 +1,4 @@
1
+ import { type FloorplanToolContext } from '@pascal-app/editor';
2
+ /** The plan side of the wall's `split` reshape (`reshapeLayers.split`): the same draft as 3D. */
3
+ export default function WallSplitFloorplanLayer(_props: FloorplanToolContext): import("react").JSX.Element | null;
4
+ //# sourceMappingURL=split-floorplan-layer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split-floorplan-layer.d.ts","sourceRoot":"","sources":["../../src/wall/split-floorplan-layer.tsx"],"names":[],"mappings":"AAQA,OAAO,EAGL,KAAK,oBAAoB,EAG1B,MAAM,oBAAoB,CAAA;AAO3B,iGAAiG;AACjG,MAAM,CAAC,OAAO,UAAU,uBAAuB,CAAC,MAAM,EAAE,oBAAoB,sCAgG3E"}
@@ -0,0 +1,71 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { getWallCurveFrameAt, getWallCurveLength, getWallThickness, useScene, } from '@pascal-app/core';
4
+ import { clientToPlan, FloorplanDraftWallMeasurement, formatLinearMeasurement, useFloorplanRender, } from '@pascal-app/editor';
5
+ import { getSceneTheme, useViewer } from '@pascal-app/viewer';
6
+ import { useEffect } from 'react';
7
+ import { bindWallSplitPointer } from './split-pointer';
8
+ import { wallSplitDistance, wallSplitMarkerColor, wallSplitSegmentLabels } from './split-preview';
9
+ import { useWallSplit } from './split-store';
10
+ /** The plan side of the wall's `split` reshape (`reshapeLayers.split`): the same draft as 3D. */
11
+ export default function WallSplitFloorplanLayer(_props) {
12
+ const draft = useWallSplit((s) => s.draft);
13
+ const wallId = draft?.wallId;
14
+ const wall = useScene((s) => (draft ? s.nodes[draft.wallId] : undefined));
15
+ const levelId = useViewer((s) => s.selection.levelId);
16
+ const unit = useViewer((s) => s.unit);
17
+ const metricNotation = useViewer((s) => s.metricNotation);
18
+ const isDark = useViewer((s) => getSceneTheme(s.sceneTheme).appearance === 'dark');
19
+ const context = useFloorplanRender();
20
+ const upp = context?.unitsPerPixel ?? 0.01;
21
+ useEffect(() => {
22
+ if (!wallId || useScene.getState().nodes[wallId]?.parentId !== levelId)
23
+ return;
24
+ const scene = document.querySelector('g[data-floorplan-scene]');
25
+ const surface = scene?.ownerSVGElement;
26
+ if (!surface)
27
+ return;
28
+ return bindWallSplitPointer(surface, (event) => {
29
+ if (!(event.target instanceof Node) || !surface.contains(event.target))
30
+ return null;
31
+ const point = clientToPlan(event.clientX, event.clientY);
32
+ const current = useScene.getState().nodes[wallId];
33
+ if (!point || current?.type !== 'wall')
34
+ return null;
35
+ const distance = wallSplitDistance(current, point);
36
+ // Only the wall's own stroke is a target, including its endpoint exclusion zones.
37
+ const frame = frameAt(current, distance);
38
+ if (Math.hypot(frame.point.x - point[0], frame.point.y - point[1]) > hitHalfWidth(current, upp))
39
+ return null;
40
+ return distance;
41
+ });
42
+ }, [wallId, levelId, upp]);
43
+ if (!draft || wall?.type !== 'wall' || wall.parentId !== levelId)
44
+ return null;
45
+ const { preview, snap } = draft;
46
+ const half = hitHalfWidth(wall, upp);
47
+ const color = wallSplitMarkerColor(preview.valid);
48
+ const cut = preview.frames[0]?.point;
49
+ return (_jsxs("g", { pointerEvents: "none", "data-testid": "pascal-split-marker-2d", children: [snap?.kind === 'alignment' && cut && (_jsx("line", { stroke: "#818cf8", strokeDasharray: `${4 * upp} ${3 * upp}`, strokeOpacity: 0.8, strokeWidth: upp, x1: snap.anchor[0], x2: cut.x, y1: snap.anchor[1], y2: cut.y })), preview.frames.map(({ point, normal }, index) => {
50
+ const line = {
51
+ x1: point.x - normal.x * half,
52
+ y1: point.y - normal.y * half,
53
+ x2: point.x + normal.x * half,
54
+ y2: point.y + normal.y * half,
55
+ };
56
+ return (_jsxs("g", { children: [_jsx("line", { ...line, stroke: "#f7f3ed", strokeWidth: 7 * upp, strokeLinecap: "round" }), _jsx("line", { ...line, stroke: color, strokeWidth: 3 * upp, strokeLinecap: "round" })] }, index));
57
+ }), !preview.valid && cut ? (_jsx("text", { fill: color, fontSize: 12 * upp, paintOrder: "stroke", stroke: isDark ? '#0f172a' : '#ffffff', strokeWidth: 3 * upp, textAnchor: "middle", x: cut.x, y: cut.y - half - 6 * upp, children: preview.message })) : (wallSplitSegmentLabels(wall, preview).map((segment, index) => (_jsx(FloorplanDraftWallMeasurement, { labelBackground: isDark ? '#0f172a' : '#ffffff', labelText: isDark ? '#e2e8f0' : '#171717', measurement: {
58
+ lengthLabel: `${formatLinearMeasurement(segment.length, unit, metricNotation)}${segment.count > 1 ? ` × ${segment.count}` : ''}`,
59
+ midpoint: segment.midpoint,
60
+ direction: segment.direction,
61
+ angleLabels: [],
62
+ }, measurementStroke: context?.palette.measurementStroke ?? color, sceneRotationDeg: context?.sceneRotationDeg ?? 0, unitsPerPixel: upp }, index))))] }));
63
+ }
64
+ /** The wall's stroke plus a finger's width, so the cut can be grabbed at any zoom. */
65
+ function hitHalfWidth(wall, upp) {
66
+ return getWallThickness(wall) / 2 + 8 * upp;
67
+ }
68
+ function frameAt(wall, distance) {
69
+ const length = getWallCurveLength(wall);
70
+ return getWallCurveFrameAt(wall, length > 0 ? distance / length : 0);
71
+ }
@@ -0,0 +1,3 @@
1
+ /** Both viewports feed a wall distance; neither writes scene nodes while hovering. */
2
+ export declare function bindWallSplitPointer(surface: Element, distanceAt: (event: PointerEvent) => number | null): () => void;
3
+ //# sourceMappingURL=split-pointer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split-pointer.d.ts","sourceRoot":"","sources":["../../src/wall/split-pointer.ts"],"names":[],"mappings":"AAUA,sFAAsF;AACtF,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,MAAM,GAAG,IAAI,cA2EnD"}
@@ -0,0 +1,95 @@
1
+ import { commitWallSplit, hoverWallSplit, setWallSplitCuts } from './split-session';
2
+ import { useWallSplit } from './split-store';
3
+ // Pixels of continuous wheel travel per cut: a short trackpad swipe.
4
+ const WHEEL_STEP_PX = 60;
5
+ // A wheel event after this pause is a new notch or gesture and steps at once,
6
+ // so each notch of a notched wheel is one cut whatever pixels the OS reports
7
+ // for it; a continuous stream (trackpad, fast spin) steps by travel.
8
+ const WHEEL_GESTURE_GAP_MS = 80;
9
+ /** Both viewports feed a wall distance; neither writes scene nodes while hovering. */
10
+ export function bindWallSplitPointer(surface, distanceAt) {
11
+ let pressed = null;
12
+ let wheelTravel = 0;
13
+ let lastWheelAt = Number.NEGATIVE_INFINITY;
14
+ const move = (event) => {
15
+ if (event.buttons && pressed !== event.pointerId)
16
+ return;
17
+ const distance = distanceAt(event);
18
+ if (distance !== null)
19
+ hoverWallSplit(distance, event.altKey);
20
+ };
21
+ const down = (event) => {
22
+ if (event.button !== 0)
23
+ return;
24
+ const distance = distanceAt(event);
25
+ if (distance === null)
26
+ return;
27
+ pressed = event.pointerId;
28
+ event.preventDefault();
29
+ event.stopImmediatePropagation();
30
+ hoverWallSplit(distance, event.altKey);
31
+ };
32
+ const up = (event) => {
33
+ if (pressed !== event.pointerId)
34
+ return;
35
+ pressed = null;
36
+ event.preventDefault();
37
+ event.stopImmediatePropagation();
38
+ const distance = distanceAt(event);
39
+ if (distance === null)
40
+ return;
41
+ hoverWallSplit(distance, event.altKey);
42
+ // Retain ownership through the click dispatched after pointerup, so normal
43
+ // selection cannot consume that same click after the cut closes its session.
44
+ const swallow = (click) => {
45
+ click.preventDefault();
46
+ click.stopImmediatePropagation();
47
+ };
48
+ surface.addEventListener('click', swallow, { capture: true, once: true });
49
+ setTimeout(() => surface.removeEventListener('click', swallow, true), 0);
50
+ commitWallSplit();
51
+ };
52
+ const cancel = () => {
53
+ pressed = null;
54
+ };
55
+ // Scrolling over the viewport changes the cut count, as in a loop cut;
56
+ // pinch (Ctrl + wheel) still zooms.
57
+ const wheel = (event) => {
58
+ if (event.ctrlKey || !(event.target instanceof Node) || !surface.contains(event.target))
59
+ return;
60
+ event.preventDefault();
61
+ event.stopImmediatePropagation();
62
+ if (!event.deltaY)
63
+ return;
64
+ const fresh = event.timeStamp - lastWheelAt > WHEEL_GESTURE_GAP_MS;
65
+ lastWheelAt = event.timeStamp;
66
+ let steps;
67
+ // Line-mode deltas only come from a notched wheel: one line event, one notch.
68
+ if (fresh || event.deltaMode !== 0) {
69
+ wheelTravel = 0;
70
+ steps = Math.sign(event.deltaY);
71
+ }
72
+ else {
73
+ wheelTravel += event.deltaY;
74
+ steps = Math.trunc(wheelTravel / WHEEL_STEP_PX);
75
+ wheelTravel -= steps * WHEEL_STEP_PX;
76
+ }
77
+ if (!steps)
78
+ return;
79
+ const draft = useWallSplit.getState().draft;
80
+ if (draft)
81
+ setWallSplitCuts(draft.cuts - steps);
82
+ };
83
+ window.addEventListener('pointermove', move, true);
84
+ window.addEventListener('pointerdown', down, true);
85
+ window.addEventListener('pointerup', up, true);
86
+ window.addEventListener('pointercancel', cancel, true);
87
+ window.addEventListener('wheel', wheel, { capture: true, passive: false });
88
+ return () => {
89
+ window.removeEventListener('pointermove', move, true);
90
+ window.removeEventListener('pointerdown', down, true);
91
+ window.removeEventListener('pointerup', up, true);
92
+ window.removeEventListener('pointercancel', cancel, true);
93
+ window.removeEventListener('wheel', wheel, true);
94
+ };
95
+ }