@pascal-app/nodes 1.0.0-beta.5 → 1.0.0

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 (831) hide show
  1. package/LICENSE +21 -0
  2. package/dist/block/commands.d.ts +68 -0
  3. package/dist/block/commands.d.ts.map +1 -0
  4. package/dist/block/commands.js +1144 -0
  5. package/dist/block/contextual-help.d.ts +3 -0
  6. package/dist/block/contextual-help.d.ts.map +1 -0
  7. package/dist/block/contextual-help.js +38 -0
  8. package/dist/block/definition.d.ts +8 -0
  9. package/dist/block/definition.d.ts.map +1 -0
  10. package/dist/block/definition.js +126 -0
  11. package/dist/block/edit-session.d.ts +16 -0
  12. package/dist/block/edit-session.d.ts.map +1 -0
  13. package/dist/block/edit-session.js +32 -0
  14. package/dist/block/face-host.d.ts +3 -0
  15. package/dist/block/face-host.d.ts.map +1 -0
  16. package/dist/block/face-host.js +178 -0
  17. package/dist/block/floorplan.d.ts +3 -0
  18. package/dist/block/floorplan.d.ts.map +1 -0
  19. package/dist/block/floorplan.js +43 -0
  20. package/dist/block/geometry-snap.d.ts +18 -0
  21. package/dist/block/geometry-snap.d.ts.map +1 -0
  22. package/dist/block/geometry-snap.js +137 -0
  23. package/dist/block/geometry.d.ts +11 -0
  24. package/dist/block/geometry.d.ts.map +1 -0
  25. package/dist/block/geometry.js +146 -0
  26. package/dist/block/gesture-wheel.d.ts +8 -0
  27. package/dist/block/gesture-wheel.d.ts.map +1 -0
  28. package/dist/block/gesture-wheel.js +7 -0
  29. package/dist/block/interaction-sfx.d.ts +3 -0
  30. package/dist/block/interaction-sfx.d.ts.map +1 -0
  31. package/dist/block/interaction-sfx.js +16 -0
  32. package/dist/block/last-operation.d.ts +48 -0
  33. package/dist/block/last-operation.d.ts.map +1 -0
  34. package/dist/block/last-operation.js +120 -0
  35. package/dist/block/loop-cut-interaction.d.ts +5 -0
  36. package/dist/block/loop-cut-interaction.d.ts.map +1 -0
  37. package/dist/block/loop-cut-interaction.js +13 -0
  38. package/dist/block/material-slots.d.ts +61 -0
  39. package/dist/block/material-slots.d.ts.map +1 -0
  40. package/dist/block/material-slots.js +131 -0
  41. package/dist/block/modal-face-operation.d.ts +13 -0
  42. package/dist/block/modal-face-operation.d.ts.map +1 -0
  43. package/dist/block/modal-face-operation.js +40 -0
  44. package/dist/block/modal-session.d.ts +15 -0
  45. package/dist/block/modal-session.d.ts.map +1 -0
  46. package/dist/block/modal-session.js +40 -0
  47. package/dist/block/modal-transform.d.ts +30 -0
  48. package/dist/block/modal-transform.d.ts.map +1 -0
  49. package/dist/block/modal-transform.js +144 -0
  50. package/dist/block/paint.d.ts +3 -0
  51. package/dist/block/paint.d.ts.map +1 -0
  52. package/dist/block/paint.js +136 -0
  53. package/dist/block/panel.d.ts +2 -0
  54. package/dist/block/panel.d.ts.map +1 -0
  55. package/dist/block/panel.js +234 -0
  56. package/dist/block/parametrics.d.ts +4 -0
  57. package/dist/block/parametrics.d.ts.map +1 -0
  58. package/dist/block/parametrics.js +9 -0
  59. package/dist/block/preview.d.ts +6 -0
  60. package/dist/block/preview.d.ts.map +1 -0
  61. package/dist/block/preview.js +46 -0
  62. package/dist/block/rotation-drag.d.ts +5 -0
  63. package/dist/block/rotation-drag.d.ts.map +1 -0
  64. package/dist/block/rotation-drag.js +18 -0
  65. package/dist/block/schema.d.ts +2 -0
  66. package/dist/block/schema.d.ts.map +1 -0
  67. package/dist/block/schema.js +1 -0
  68. package/dist/block/selection-geometry.d.ts +9 -0
  69. package/dist/block/selection-geometry.d.ts.map +1 -0
  70. package/dist/block/selection-geometry.js +31 -0
  71. package/dist/block/selection-model.d.ts +17 -0
  72. package/dist/block/selection-model.d.ts.map +1 -0
  73. package/dist/block/selection-model.js +84 -0
  74. package/dist/block/selection.d.ts +4 -0
  75. package/dist/block/selection.d.ts.map +1 -0
  76. package/dist/block/selection.js +2570 -0
  77. package/dist/block/slots.d.ts +4 -0
  78. package/dist/block/slots.d.ts.map +1 -0
  79. package/dist/block/slots.js +17 -0
  80. package/dist/block/tool.d.ts +3 -0
  81. package/dist/block/tool.d.ts.map +1 -0
  82. package/dist/block/tool.js +174 -0
  83. package/dist/block/toolbar-state.d.ts +46 -0
  84. package/dist/block/toolbar-state.d.ts.map +1 -0
  85. package/dist/block/toolbar-state.js +67 -0
  86. package/dist/block/use-block-face-operation.d.ts +39 -0
  87. package/dist/block/use-block-face-operation.d.ts.map +1 -0
  88. package/dist/block/use-block-face-operation.js +218 -0
  89. package/dist/box-vent/definition.d.ts.map +1 -1
  90. package/dist/box-vent/definition.js +8 -5
  91. package/dist/box-vent/geometry.d.ts +4 -0
  92. package/dist/box-vent/geometry.d.ts.map +1 -1
  93. package/dist/box-vent/geometry.js +76 -44
  94. package/dist/box-vent/paint.d.ts +4 -0
  95. package/dist/box-vent/paint.d.ts.map +1 -0
  96. package/dist/box-vent/paint.js +40 -0
  97. package/dist/box-vent/panel.js +1 -1
  98. package/dist/box-vent/parametrics.js +3 -3
  99. package/dist/box-vent/renderer.d.ts.map +1 -1
  100. package/dist/box-vent/renderer.js +29 -10
  101. package/dist/cabinet/compartment-card.d.ts.map +1 -1
  102. package/dist/cabinet/compartment-card.js +11 -3
  103. package/dist/cabinet/continuous-placement.d.ts +3 -0
  104. package/dist/cabinet/continuous-placement.d.ts.map +1 -1
  105. package/dist/cabinet/continuous-placement.js +6 -0
  106. package/dist/cabinet/definition.d.ts.map +1 -1
  107. package/dist/cabinet/definition.js +400 -54
  108. package/dist/cabinet/floorplan-move.d.ts.map +1 -1
  109. package/dist/cabinet/floorplan-move.js +91 -22
  110. package/dist/cabinet/geometry/fridge.d.ts.map +1 -1
  111. package/dist/cabinet/geometry/fridge.js +25 -1
  112. package/dist/cabinet/geometry/fronts.d.ts +4 -0
  113. package/dist/cabinet/geometry/fronts.d.ts.map +1 -1
  114. package/dist/cabinet/geometry/fronts.js +1 -1
  115. package/dist/cabinet/geometry/run.d.ts.map +1 -1
  116. package/dist/cabinet/geometry/run.js +19 -1
  117. package/dist/cabinet/geometry.d.ts.map +1 -1
  118. package/dist/cabinet/geometry.js +63 -1
  119. package/dist/cabinet/index.d.ts +1 -0
  120. package/dist/cabinet/index.d.ts.map +1 -1
  121. package/dist/cabinet/index.js +1 -0
  122. package/dist/cabinet/insertion.d.ts +19 -0
  123. package/dist/cabinet/insertion.d.ts.map +1 -0
  124. package/dist/cabinet/insertion.js +49 -0
  125. package/dist/cabinet/move-frame.d.ts.map +1 -1
  126. package/dist/cabinet/move-frame.js +68 -2
  127. package/dist/cabinet/panel-context.d.ts +7 -0
  128. package/dist/cabinet/panel-context.d.ts.map +1 -0
  129. package/dist/cabinet/panel-context.js +16 -0
  130. package/dist/cabinet/panel-visibility.d.ts +9 -0
  131. package/dist/cabinet/panel-visibility.d.ts.map +1 -0
  132. package/dist/cabinet/panel-visibility.js +26 -0
  133. package/dist/cabinet/panel.d.ts.map +1 -1
  134. package/dist/cabinet/panel.js +221 -37
  135. package/dist/cabinet/placement-dimensions.d.ts +42 -0
  136. package/dist/cabinet/placement-dimensions.d.ts.map +1 -0
  137. package/dist/cabinet/placement-dimensions.js +227 -0
  138. package/dist/cabinet/placement-snap.d.ts +21 -1
  139. package/dist/cabinet/placement-snap.d.ts.map +1 -1
  140. package/dist/cabinet/placement-snap.js +48 -6
  141. package/dist/cabinet/preset-width-debt.d.ts +7 -0
  142. package/dist/cabinet/preset-width-debt.d.ts.map +1 -0
  143. package/dist/cabinet/preset-width-debt.js +45 -0
  144. package/dist/cabinet/presets.d.ts.map +1 -1
  145. package/dist/cabinet/presets.js +14 -13
  146. package/dist/cabinet/profiles.d.ts +14 -0
  147. package/dist/cabinet/profiles.d.ts.map +1 -0
  148. package/dist/cabinet/profiles.js +30 -0
  149. package/dist/cabinet/quick-actions.d.ts.map +1 -1
  150. package/dist/cabinet/quick-actions.js +8 -24
  151. package/dist/cabinet/reveals.d.ts +37 -0
  152. package/dist/cabinet/reveals.d.ts.map +1 -0
  153. package/dist/cabinet/reveals.js +13 -0
  154. package/dist/cabinet/run-layout.d.ts +90 -4
  155. package/dist/cabinet/run-layout.d.ts.map +1 -1
  156. package/dist/cabinet/run-layout.js +408 -23
  157. package/dist/cabinet/run-ops.d.ts +202 -10
  158. package/dist/cabinet/run-ops.d.ts.map +1 -1
  159. package/dist/cabinet/run-ops.js +520 -33
  160. package/dist/cabinet/run-panel.d.ts +6 -2
  161. package/dist/cabinet/run-panel.d.ts.map +1 -1
  162. package/dist/cabinet/run-panel.js +285 -108
  163. package/dist/cabinet/stack-transitions.d.ts.map +1 -1
  164. package/dist/cabinet/stack-transitions.js +35 -24
  165. package/dist/cabinet/stack.d.ts +169 -1
  166. package/dist/cabinet/stack.d.ts.map +1 -1
  167. package/dist/cabinet/stack.js +57 -18
  168. package/dist/cabinet/tool.d.ts.map +1 -1
  169. package/dist/cabinet/tool.js +615 -91
  170. package/dist/cabinet/validation.d.ts +27 -0
  171. package/dist/cabinet/validation.d.ts.map +1 -0
  172. package/dist/cabinet/validation.js +56 -0
  173. package/dist/cabinet/wall-height-presets.d.ts +12 -0
  174. package/dist/cabinet/wall-height-presets.d.ts.map +1 -0
  175. package/dist/cabinet/wall-height-presets.js +15 -0
  176. package/dist/cabinet/wall-snap.d.ts +27 -3
  177. package/dist/cabinet/wall-snap.d.ts.map +1 -1
  178. package/dist/cabinet/wall-snap.js +278 -62
  179. package/dist/cabinet/widths.d.ts +10 -0
  180. package/dist/cabinet/widths.d.ts.map +1 -0
  181. package/dist/cabinet/widths.js +13 -0
  182. package/dist/ceiling/definition.d.ts.map +1 -1
  183. package/dist/ceiling/definition.js +7 -1
  184. package/dist/ceiling/floorplan-affordances.d.ts +8 -8
  185. package/dist/ceiling/materials.d.ts.map +1 -1
  186. package/dist/ceiling/materials.js +0 -1
  187. package/dist/ceiling/panel.js +1 -1
  188. package/dist/ceiling/parametrics.js +1 -1
  189. package/dist/chimney/definition.js +1 -1
  190. package/dist/chimney/panel.js +1 -1
  191. package/dist/chimney/parametrics.js +3 -3
  192. package/dist/column/definition.d.ts.map +1 -1
  193. package/dist/column/definition.js +22 -4
  194. package/dist/column/panel.d.ts.map +1 -1
  195. package/dist/column/panel.js +37 -7
  196. package/dist/column/parametrics.d.ts.map +1 -1
  197. package/dist/column/parametrics.js +5 -3
  198. package/dist/column/tool.d.ts.map +1 -1
  199. package/dist/column/tool.js +50 -14
  200. package/dist/cupola/definition.d.ts.map +1 -1
  201. package/dist/cupola/definition.js +15 -6
  202. package/dist/cupola/geometry.d.ts +6 -0
  203. package/dist/cupola/geometry.d.ts.map +1 -1
  204. package/dist/cupola/geometry.js +60 -13
  205. package/dist/cupola/paint.d.ts +4 -0
  206. package/dist/cupola/paint.d.ts.map +1 -0
  207. package/dist/cupola/paint.js +39 -0
  208. package/dist/cupola/panel.js +1 -1
  209. package/dist/cupola/parametrics.js +3 -3
  210. package/dist/cupola/renderer.d.ts.map +1 -1
  211. package/dist/cupola/renderer.js +27 -8
  212. package/dist/door/floorplan-move.d.ts.map +1 -1
  213. package/dist/door/floorplan-move.js +1 -1
  214. package/dist/door/move-tool.d.ts.map +1 -1
  215. package/dist/door/move-tool.js +86 -32
  216. package/dist/door/panel.d.ts.map +1 -1
  217. package/dist/door/panel.js +1 -1
  218. package/dist/door/parametrics.js +2 -2
  219. package/dist/door/tool.d.ts.map +1 -1
  220. package/dist/door/tool.js +16 -4
  221. package/dist/dormer/csg-geometry.d.ts +6 -42
  222. package/dist/dormer/csg-geometry.d.ts.map +1 -1
  223. package/dist/dormer/csg-geometry.js +38 -209
  224. package/dist/dormer/definition.d.ts +4 -12
  225. package/dist/dormer/definition.d.ts.map +1 -1
  226. package/dist/dormer/definition.js +18 -193
  227. package/dist/dormer/floorplan.d.ts +3 -3
  228. package/dist/dormer/floorplan.d.ts.map +1 -1
  229. package/dist/dormer/floorplan.js +6 -17
  230. package/dist/dormer/geometry.d.ts +5 -24
  231. package/dist/dormer/geometry.d.ts.map +1 -1
  232. package/dist/dormer/geometry.js +64 -41
  233. package/dist/dormer/index.d.ts +1 -1
  234. package/dist/dormer/index.d.ts.map +1 -1
  235. package/dist/dormer/index.js +1 -1
  236. package/dist/dormer/move-tool.d.ts.map +1 -1
  237. package/dist/dormer/move-tool.js +31 -3
  238. package/dist/dormer/panel-windows-section.d.ts +9 -0
  239. package/dist/dormer/panel-windows-section.d.ts.map +1 -0
  240. package/dist/dormer/panel-windows-section.js +7 -0
  241. package/dist/dormer/panel.d.ts.map +1 -1
  242. package/dist/dormer/panel.js +100 -18
  243. package/dist/dormer/parametrics.d.ts.map +1 -1
  244. package/dist/dormer/parametrics.js +8 -77
  245. package/dist/dormer/preview.d.ts.map +1 -1
  246. package/dist/dormer/preview.js +9 -1
  247. package/dist/dormer/renderer.d.ts.map +1 -1
  248. package/dist/dormer/renderer.js +24 -26
  249. package/dist/dormer/tool.d.ts.map +1 -1
  250. package/dist/dormer/tool.js +3 -1
  251. package/dist/dormer/window-layout.d.ts +15 -0
  252. package/dist/dormer/window-layout.d.ts.map +1 -0
  253. package/dist/dormer/window-layout.js +59 -0
  254. package/dist/downspout/definition.d.ts.map +1 -1
  255. package/dist/downspout/definition.js +17 -4
  256. package/dist/downspout/geometry.d.ts.map +1 -1
  257. package/dist/downspout/geometry.js +10 -0
  258. package/dist/downspout/inspector-editors.d.ts.map +1 -1
  259. package/dist/downspout/inspector-editors.js +9 -1
  260. package/dist/downspout/parametrics.d.ts.map +1 -1
  261. package/dist/downspout/parametrics.js +2 -1
  262. package/dist/downspout/renderer.d.ts.map +1 -1
  263. package/dist/downspout/renderer.js +19 -3
  264. package/dist/downspout/system.d.ts +7 -0
  265. package/dist/downspout/system.d.ts.map +1 -0
  266. package/dist/downspout/system.js +114 -0
  267. package/dist/duct-fitting/accessory-geometry.d.ts +4 -0
  268. package/dist/duct-fitting/accessory-geometry.d.ts.map +1 -0
  269. package/dist/duct-fitting/accessory-geometry.js +47 -0
  270. package/dist/duct-fitting/definition.d.ts.map +1 -1
  271. package/dist/duct-fitting/definition.js +11 -1
  272. package/dist/duct-fitting/floorplan.d.ts.map +1 -1
  273. package/dist/duct-fitting/floorplan.js +8 -0
  274. package/dist/duct-fitting/geometry.d.ts.map +1 -1
  275. package/dist/duct-fitting/geometry.js +52 -38
  276. package/dist/duct-fitting/parametrics.d.ts.map +1 -1
  277. package/dist/duct-fitting/parametrics.js +78 -15
  278. package/dist/duct-fitting/ports.d.ts +1 -0
  279. package/dist/duct-fitting/ports.d.ts.map +1 -1
  280. package/dist/duct-fitting/ports.js +46 -0
  281. package/dist/duct-fitting/tool.d.ts +19 -0
  282. package/dist/duct-fitting/tool.d.ts.map +1 -1
  283. package/dist/duct-fitting/tool.js +126 -34
  284. package/dist/duct-segment/continuation.d.ts +21 -0
  285. package/dist/duct-segment/continuation.d.ts.map +1 -0
  286. package/dist/duct-segment/continuation.js +167 -0
  287. package/dist/duct-segment/definition.d.ts.map +1 -1
  288. package/dist/duct-segment/definition.js +19 -18
  289. package/dist/duct-segment/floorplan.d.ts.map +1 -1
  290. package/dist/duct-segment/floorplan.js +43 -0
  291. package/dist/duct-segment/geometry.d.ts.map +1 -1
  292. package/dist/duct-segment/geometry.js +3 -0
  293. package/dist/duct-segment/move-tool.d.ts.map +1 -1
  294. package/dist/duct-segment/move-tool.js +33 -6
  295. package/dist/duct-segment/parametrics.d.ts.map +1 -1
  296. package/dist/duct-segment/parametrics.js +45 -1
  297. package/dist/duct-segment/selection.d.ts +3 -4
  298. package/dist/duct-segment/selection.d.ts.map +1 -1
  299. package/dist/duct-segment/selection.js +186 -158
  300. package/dist/duct-segment/tool.d.ts +37 -0
  301. package/dist/duct-segment/tool.d.ts.map +1 -1
  302. package/dist/duct-segment/tool.js +305 -678
  303. package/dist/duct-terminal/parametrics.js +2 -2
  304. package/dist/duct-terminal/tool.d.ts.map +1 -1
  305. package/dist/duct-terminal/tool.js +37 -7
  306. package/dist/elevator/panel.d.ts.map +1 -1
  307. package/dist/elevator/panel.js +7 -7
  308. package/dist/elevator/system.d.ts.map +1 -1
  309. package/dist/elevator/system.js +10 -1
  310. package/dist/eyebrow-vent/definition.d.ts.map +1 -1
  311. package/dist/eyebrow-vent/definition.js +8 -5
  312. package/dist/eyebrow-vent/geometry.d.ts +4 -0
  313. package/dist/eyebrow-vent/geometry.d.ts.map +1 -1
  314. package/dist/eyebrow-vent/geometry.js +60 -15
  315. package/dist/eyebrow-vent/paint.d.ts +4 -0
  316. package/dist/eyebrow-vent/paint.d.ts.map +1 -0
  317. package/dist/eyebrow-vent/paint.js +33 -0
  318. package/dist/eyebrow-vent/panel.js +1 -1
  319. package/dist/eyebrow-vent/parametrics.js +3 -3
  320. package/dist/eyebrow-vent/renderer.d.ts.map +1 -1
  321. package/dist/eyebrow-vent/renderer.js +27 -8
  322. package/dist/fence/definition.d.ts.map +1 -1
  323. package/dist/fence/definition.js +2 -1
  324. package/dist/fence/floorplan-affordances.d.ts +1 -0
  325. package/dist/fence/floorplan-affordances.d.ts.map +1 -1
  326. package/dist/fence/floorplan-affordances.js +30 -1
  327. package/dist/fence/floorplan.d.ts.map +1 -1
  328. package/dist/fence/floorplan.js +14 -0
  329. package/dist/fence/parametrics.js +3 -3
  330. package/dist/fence/tool.d.ts.map +1 -1
  331. package/dist/fence/tool.js +47 -20
  332. package/dist/gutter/corner-mitre.d.ts.map +1 -1
  333. package/dist/gutter/corner-mitre.js +47 -7
  334. package/dist/gutter/definition.d.ts.map +1 -1
  335. package/dist/gutter/definition.js +23 -13
  336. package/dist/gutter/eave-align.d.ts.map +1 -1
  337. package/dist/gutter/eave-align.js +10 -0
  338. package/dist/gutter/eave-snap.d.ts +1 -1
  339. package/dist/gutter/eave-snap.d.ts.map +1 -1
  340. package/dist/gutter/eave-snap.js +10 -23
  341. package/dist/gutter/geometry.d.ts.map +1 -1
  342. package/dist/gutter/geometry.js +126 -8
  343. package/dist/gutter/outlet-lookup.d.ts.map +1 -1
  344. package/dist/gutter/outlet-lookup.js +22 -1
  345. package/dist/gutter/paint.d.ts +3 -0
  346. package/dist/gutter/paint.d.ts.map +1 -0
  347. package/dist/gutter/paint.js +6 -0
  348. package/dist/gutter/parametrics.d.ts.map +1 -1
  349. package/dist/gutter/parametrics.js +4 -1
  350. package/dist/gutter/renderer.d.ts.map +1 -1
  351. package/dist/gutter/renderer.js +63 -7
  352. package/dist/gutter/trim-clip.d.ts +3 -0
  353. package/dist/gutter/trim-clip.d.ts.map +1 -0
  354. package/dist/gutter/trim-clip.js +5 -0
  355. package/dist/hvac-equipment/parametrics.js +3 -3
  356. package/dist/hvac-equipment/tool.d.ts.map +1 -1
  357. package/dist/hvac-equipment/tool.js +12 -2
  358. package/dist/index.d.ts +5 -2
  359. package/dist/index.d.ts.map +1 -1
  360. package/dist/index.js +9 -2
  361. package/dist/item/definition.d.ts.map +1 -1
  362. package/dist/item/definition.js +10 -2
  363. package/dist/item/floorplan-move.d.ts.map +1 -1
  364. package/dist/item/floorplan-move.js +20 -1
  365. package/dist/item/floorplan.d.ts.map +1 -1
  366. package/dist/item/floorplan.js +22 -1
  367. package/dist/item/move-tool.d.ts +28 -1
  368. package/dist/item/move-tool.d.ts.map +1 -1
  369. package/dist/item/move-tool.js +14 -2
  370. package/dist/item/renderer.d.ts.map +1 -1
  371. package/dist/item/renderer.js +16 -6
  372. package/dist/item/system.d.ts +5 -0
  373. package/dist/item/system.d.ts.map +1 -1
  374. package/dist/item/system.js +7 -1
  375. package/dist/lean-to-extension/arc.d.ts +14 -0
  376. package/dist/lean-to-extension/arc.d.ts.map +1 -0
  377. package/dist/lean-to-extension/arc.js +56 -0
  378. package/dist/lean-to-extension/assembly.d.ts +61 -0
  379. package/dist/lean-to-extension/assembly.d.ts.map +1 -0
  380. package/dist/lean-to-extension/assembly.js +761 -0
  381. package/dist/lean-to-extension/canopy-joint.d.ts +35 -0
  382. package/dist/lean-to-extension/canopy-joint.d.ts.map +1 -0
  383. package/dist/lean-to-extension/canopy-joint.js +234 -0
  384. package/dist/lean-to-extension/conical-host.d.ts +15 -0
  385. package/dist/lean-to-extension/conical-host.d.ts.map +1 -0
  386. package/dist/lean-to-extension/conical-host.js +113 -0
  387. package/dist/lean-to-extension/corner-joint.d.ts +29 -0
  388. package/dist/lean-to-extension/corner-joint.d.ts.map +1 -0
  389. package/dist/lean-to-extension/corner-joint.js +1202 -0
  390. package/dist/lean-to-extension/definition.d.ts +4 -0
  391. package/dist/lean-to-extension/definition.d.ts.map +1 -0
  392. package/dist/lean-to-extension/definition.js +433 -0
  393. package/dist/lean-to-extension/floorplan-affordances.d.ts +4 -0
  394. package/dist/lean-to-extension/floorplan-affordances.d.ts.map +1 -0
  395. package/dist/lean-to-extension/floorplan-affordances.js +144 -0
  396. package/dist/lean-to-extension/floorplan-move.d.ts +3 -0
  397. package/dist/lean-to-extension/floorplan-move.d.ts.map +1 -0
  398. package/dist/lean-to-extension/floorplan-move.js +157 -0
  399. package/dist/lean-to-extension/floorplan-tool.d.ts +4 -0
  400. package/dist/lean-to-extension/floorplan-tool.d.ts.map +1 -0
  401. package/dist/lean-to-extension/floorplan-tool.js +385 -0
  402. package/dist/lean-to-extension/floorplan.d.ts +3 -0
  403. package/dist/lean-to-extension/floorplan.d.ts.map +1 -0
  404. package/dist/lean-to-extension/floorplan.js +373 -0
  405. package/dist/lean-to-extension/geometry.d.ts +7 -0
  406. package/dist/lean-to-extension/geometry.d.ts.map +1 -0
  407. package/dist/lean-to-extension/geometry.js +662 -0
  408. package/dist/lean-to-extension/index.d.ts +8 -0
  409. package/dist/lean-to-extension/index.d.ts.map +1 -0
  410. package/dist/lean-to-extension/index.js +7 -0
  411. package/dist/lean-to-extension/layout.d.ts +108 -0
  412. package/dist/lean-to-extension/layout.d.ts.map +1 -0
  413. package/dist/lean-to-extension/layout.js +477 -0
  414. package/dist/lean-to-extension/managed-preview.d.ts +3 -0
  415. package/dist/lean-to-extension/managed-preview.d.ts.map +1 -0
  416. package/dist/lean-to-extension/managed-preview.js +93 -0
  417. package/dist/lean-to-extension/move-tool.d.ts +8 -0
  418. package/dist/lean-to-extension/move-tool.d.ts.map +1 -0
  419. package/dist/lean-to-extension/move-tool.js +202 -0
  420. package/dist/lean-to-extension/paint.d.ts +2 -0
  421. package/dist/lean-to-extension/paint.d.ts.map +1 -0
  422. package/dist/lean-to-extension/paint.js +16 -0
  423. package/dist/lean-to-extension/parametrics.d.ts +4 -0
  424. package/dist/lean-to-extension/parametrics.d.ts.map +1 -0
  425. package/dist/lean-to-extension/parametrics.js +570 -0
  426. package/dist/lean-to-extension/placement-scope.d.ts +3 -0
  427. package/dist/lean-to-extension/placement-scope.d.ts.map +1 -0
  428. package/dist/lean-to-extension/placement-scope.js +4 -0
  429. package/dist/lean-to-extension/placement-validation.d.ts +4 -0
  430. package/dist/lean-to-extension/placement-validation.d.ts.map +1 -0
  431. package/dist/lean-to-extension/placement-validation.js +324 -0
  432. package/dist/lean-to-extension/placement.d.ts +59 -0
  433. package/dist/lean-to-extension/placement.d.ts.map +1 -0
  434. package/dist/lean-to-extension/placement.js +331 -0
  435. package/dist/lean-to-extension/plan-footprint.d.ts +10 -0
  436. package/dist/lean-to-extension/plan-footprint.d.ts.map +1 -0
  437. package/dist/lean-to-extension/plan-footprint.js +27 -0
  438. package/dist/lean-to-extension/preview-geometry.d.ts +7 -0
  439. package/dist/lean-to-extension/preview-geometry.d.ts.map +1 -0
  440. package/dist/lean-to-extension/preview-geometry.js +40 -0
  441. package/dist/lean-to-extension/preview.d.ts +7 -0
  442. package/dist/lean-to-extension/preview.d.ts.map +1 -0
  443. package/dist/lean-to-extension/preview.js +20 -0
  444. package/dist/lean-to-extension/renderer.d.ts +6 -0
  445. package/dist/lean-to-extension/renderer.d.ts.map +1 -0
  446. package/dist/lean-to-extension/renderer.js +34 -0
  447. package/dist/lean-to-extension/roof-attachment.d.ts +28 -0
  448. package/dist/lean-to-extension/roof-attachment.d.ts.map +1 -0
  449. package/dist/lean-to-extension/roof-attachment.js +376 -0
  450. package/dist/lean-to-extension/schema.d.ts +2 -0
  451. package/dist/lean-to-extension/schema.d.ts.map +1 -0
  452. package/dist/lean-to-extension/schema.js +1 -0
  453. package/dist/lean-to-extension/slots.d.ts +5 -0
  454. package/dist/lean-to-extension/slots.d.ts.map +1 -0
  455. package/dist/lean-to-extension/slots.js +15 -0
  456. package/dist/lean-to-extension/system.d.ts +7 -0
  457. package/dist/lean-to-extension/system.d.ts.map +1 -0
  458. package/dist/lean-to-extension/system.js +726 -0
  459. package/dist/lean-to-extension/tool.d.ts +3 -0
  460. package/dist/lean-to-extension/tool.d.ts.map +1 -0
  461. package/dist/lean-to-extension/tool.js +580 -0
  462. package/dist/lean-to-extension/wall-target.d.ts +10 -0
  463. package/dist/lean-to-extension/wall-target.d.ts.map +1 -0
  464. package/dist/lean-to-extension/wall-target.js +29 -0
  465. package/dist/lineset/definition.d.ts.map +1 -1
  466. package/dist/lineset/definition.js +1 -0
  467. package/dist/liquid-line/definition.d.ts.map +1 -1
  468. package/dist/liquid-line/definition.js +1 -0
  469. package/dist/pipe-fitting/definition.d.ts.map +1 -1
  470. package/dist/pipe-fitting/definition.js +16 -2
  471. package/dist/pipe-fitting/floorplan.d.ts.map +1 -1
  472. package/dist/pipe-fitting/floorplan.js +4 -0
  473. package/dist/pipe-fitting/geometry.d.ts +3 -5
  474. package/dist/pipe-fitting/geometry.d.ts.map +1 -1
  475. package/dist/pipe-fitting/geometry.js +154 -21
  476. package/dist/pipe-fitting/inline-insertion.d.ts +13 -0
  477. package/dist/pipe-fitting/inline-insertion.d.ts.map +1 -0
  478. package/dist/pipe-fitting/inline-insertion.js +96 -0
  479. package/dist/pipe-fitting/parametrics.d.ts.map +1 -1
  480. package/dist/pipe-fitting/parametrics.js +17 -3
  481. package/dist/pipe-fitting/ports.d.ts.map +1 -1
  482. package/dist/pipe-fitting/ports.js +8 -1
  483. package/dist/pipe-fitting/tool.d.ts +26 -0
  484. package/dist/pipe-fitting/tool.d.ts.map +1 -1
  485. package/dist/pipe-fitting/tool.js +182 -37
  486. package/dist/pipe-segment/continuation.d.ts +22 -0
  487. package/dist/pipe-segment/continuation.d.ts.map +1 -0
  488. package/dist/pipe-segment/continuation.js +146 -0
  489. package/dist/pipe-segment/definition.d.ts.map +1 -1
  490. package/dist/pipe-segment/definition.js +23 -7
  491. package/dist/pipe-segment/floorplan.d.ts.map +1 -1
  492. package/dist/pipe-segment/floorplan.js +42 -0
  493. package/dist/pipe-segment/geometry.d.ts +2 -1
  494. package/dist/pipe-segment/geometry.d.ts.map +1 -1
  495. package/dist/pipe-segment/geometry.js +4 -1
  496. package/dist/pipe-segment/move-tool.d.ts.map +1 -1
  497. package/dist/pipe-segment/move-tool.js +25 -5
  498. package/dist/pipe-segment/parametrics.d.ts.map +1 -1
  499. package/dist/pipe-segment/parametrics.js +45 -0
  500. package/dist/pipe-segment/selection.d.ts +3 -4
  501. package/dist/pipe-segment/selection.d.ts.map +1 -1
  502. package/dist/pipe-segment/selection.js +169 -105
  503. package/dist/pipe-segment/slope.d.ts +5 -0
  504. package/dist/pipe-segment/slope.d.ts.map +1 -0
  505. package/dist/pipe-segment/slope.js +10 -0
  506. package/dist/pipe-segment/tool.d.ts.map +1 -1
  507. package/dist/pipe-segment/tool.js +325 -545
  508. package/dist/pipe-trap/tool.d.ts.map +1 -1
  509. package/dist/pipe-trap/tool.js +15 -2
  510. package/dist/ridge-vent/definition.js +1 -1
  511. package/dist/ridge-vent/panel.d.ts.map +1 -1
  512. package/dist/ridge-vent/panel.js +2 -2
  513. package/dist/ridge-vent/parametrics.js +1 -1
  514. package/dist/roof/conical-roof-placement.d.ts +36 -0
  515. package/dist/roof/conical-roof-placement.d.ts.map +1 -0
  516. package/dist/roof/conical-roof-placement.js +134 -0
  517. package/dist/roof/conical-roof.d.ts +3 -0
  518. package/dist/roof/conical-roof.d.ts.map +1 -0
  519. package/dist/roof/conical-roof.js +53 -0
  520. package/dist/roof/definition.d.ts +3 -10
  521. package/dist/roof/definition.d.ts.map +1 -1
  522. package/dist/roof/definition.js +83 -13
  523. package/dist/roof/floorplan.d.ts +3 -10
  524. package/dist/roof/floorplan.d.ts.map +1 -1
  525. package/dist/roof/floorplan.js +139 -165
  526. package/dist/roof/index.d.ts +1 -0
  527. package/dist/roof/index.d.ts.map +1 -1
  528. package/dist/roof/index.js +1 -0
  529. package/dist/roof/panel.d.ts.map +1 -1
  530. package/dist/roof/panel.js +22 -23
  531. package/dist/roof/renderer.d.ts.map +1 -1
  532. package/dist/roof/roof-footprint-source.d.ts +16 -0
  533. package/dist/roof/roof-footprint-source.d.ts.map +1 -0
  534. package/dist/roof/roof-footprint-source.js +14 -0
  535. package/dist/roof/roof-footprint.d.ts +25 -0
  536. package/dist/roof/roof-footprint.d.ts.map +1 -0
  537. package/dist/roof/roof-footprint.js +94 -0
  538. package/dist/roof/roof-placement-mode.d.ts +18 -0
  539. package/dist/roof/roof-placement-mode.d.ts.map +1 -0
  540. package/dist/roof/roof-placement-mode.js +24 -0
  541. package/dist/roof/tool.d.ts +10 -0
  542. package/dist/roof/tool.d.ts.map +1 -0
  543. package/dist/roof/tool.js +922 -0
  544. package/dist/roof-segment/definition.d.ts.map +1 -1
  545. package/dist/roof-segment/definition.js +52 -8
  546. package/dist/roof-segment/floorplan-affordances.d.ts +5 -6
  547. package/dist/roof-segment/floorplan-affordances.d.ts.map +1 -1
  548. package/dist/roof-segment/floorplan-affordances.js +64 -18
  549. package/dist/roof-segment/floorplan.d.ts +3 -2
  550. package/dist/roof-segment/floorplan.d.ts.map +1 -1
  551. package/dist/roof-segment/floorplan.js +95 -46
  552. package/dist/roof-segment/panel.d.ts.map +1 -1
  553. package/dist/roof-segment/panel.js +122 -27
  554. package/dist/scan/definition.d.ts +2 -3
  555. package/dist/scan/definition.d.ts.map +1 -1
  556. package/dist/scan/definition.js +9 -7
  557. package/dist/scan/parametrics.d.ts.map +1 -1
  558. package/dist/scan/parametrics.js +13 -1
  559. package/dist/scan/renderer.d.ts.map +1 -1
  560. package/dist/scan/renderer.js +8 -2
  561. package/dist/shared/accessory-cursor.d.ts +7 -0
  562. package/dist/shared/accessory-cursor.d.ts.map +1 -0
  563. package/dist/shared/accessory-cursor.js +83 -0
  564. package/dist/shared/accessory-floorplan.d.ts +4 -0
  565. package/dist/shared/accessory-floorplan.d.ts.map +1 -0
  566. package/dist/shared/accessory-floorplan.js +51 -0
  567. package/dist/shared/accessory-geometry.d.ts +7 -0
  568. package/dist/shared/accessory-geometry.d.ts.map +1 -0
  569. package/dist/shared/accessory-geometry.js +79 -0
  570. package/dist/shared/accessory-placement.d.ts +10 -0
  571. package/dist/shared/accessory-placement.d.ts.map +1 -0
  572. package/dist/shared/accessory-placement.js +126 -0
  573. package/dist/shared/accessory-snapping.d.ts +5 -0
  574. package/dist/shared/accessory-snapping.d.ts.map +1 -0
  575. package/dist/shared/accessory-snapping.js +40 -0
  576. package/dist/shared/automatic-run-end-cap.d.ts +11 -0
  577. package/dist/shared/automatic-run-end-cap.d.ts.map +1 -0
  578. package/dist/shared/automatic-run-end-cap.js +159 -0
  579. package/dist/shared/block-face-host.d.ts +15 -0
  580. package/dist/shared/block-face-host.d.ts.map +1 -0
  581. package/dist/shared/block-face-host.js +36 -0
  582. package/dist/shared/connection-compatibility.d.ts +8 -0
  583. package/dist/shared/connection-compatibility.d.ts.map +1 -0
  584. package/dist/shared/connection-compatibility.js +28 -0
  585. package/dist/shared/connection-feedback.d.ts +10 -0
  586. package/dist/shared/connection-feedback.d.ts.map +1 -0
  587. package/dist/shared/connection-feedback.js +17 -0
  588. package/dist/shared/distribution-run-contract.d.ts +49 -0
  589. package/dist/shared/distribution-run-contract.d.ts.map +1 -0
  590. package/dist/shared/distribution-run-contract.js +30 -0
  591. package/dist/shared/distribution-run-tool.d.ts +107 -0
  592. package/dist/shared/distribution-run-tool.d.ts.map +1 -0
  593. package/dist/shared/distribution-run-tool.js +941 -0
  594. package/dist/shared/dormer-wall-opening-placement.d.ts +21 -0
  595. package/dist/shared/dormer-wall-opening-placement.d.ts.map +1 -0
  596. package/dist/shared/dormer-wall-opening-placement.js +101 -0
  597. package/dist/shared/duct-adapter.d.ts +10 -0
  598. package/dist/shared/duct-adapter.d.ts.map +1 -0
  599. package/dist/shared/duct-adapter.js +43 -0
  600. package/dist/shared/elbow-branch-continuation.d.ts +20 -0
  601. package/dist/shared/elbow-branch-continuation.d.ts.map +1 -0
  602. package/dist/shared/elbow-branch-continuation.js +200 -0
  603. package/dist/shared/fitting-clearance.d.ts +5 -0
  604. package/dist/shared/fitting-clearance.d.ts.map +1 -0
  605. package/dist/shared/fitting-clearance.js +11 -0
  606. package/dist/shared/fitting-deletion-cleanup.d.ts +14 -0
  607. package/dist/shared/fitting-deletion-cleanup.d.ts.map +1 -0
  608. package/dist/shared/fitting-deletion-cleanup.js +297 -0
  609. package/dist/shared/fitting-surface-support.d.ts +5 -0
  610. package/dist/shared/fitting-surface-support.d.ts.map +1 -0
  611. package/dist/shared/fitting-surface-support.js +42 -0
  612. package/dist/shared/fitting-tool-options.d.ts +4 -0
  613. package/dist/shared/fitting-tool-options.d.ts.map +1 -0
  614. package/dist/shared/fitting-tool-options.js +175 -0
  615. package/dist/shared/floor-placement.d.ts +1 -1
  616. package/dist/shared/floor-placement.d.ts.map +1 -1
  617. package/dist/shared/floor-placement.js +13 -33
  618. package/dist/shared/ghost-materials.d.ts.map +1 -1
  619. package/dist/shared/ghost-materials.js +2 -1
  620. package/dist/shared/lean-to-post-omissions.d.ts +8 -0
  621. package/dist/shared/lean-to-post-omissions.d.ts.map +1 -0
  622. package/dist/shared/lean-to-post-omissions.js +51 -0
  623. package/dist/shared/mep-fitting-actions.d.ts +5 -0
  624. package/dist/shared/mep-fitting-actions.d.ts.map +1 -0
  625. package/dist/shared/mep-fitting-actions.js +16 -0
  626. package/dist/shared/mep-presets.d.ts +11 -0
  627. package/dist/shared/mep-presets.d.ts.map +1 -0
  628. package/dist/shared/mep-presets.js +34 -0
  629. package/dist/shared/node-batch/candidates.d.ts +29 -0
  630. package/dist/shared/node-batch/candidates.d.ts.map +1 -0
  631. package/dist/shared/node-batch/candidates.js +260 -0
  632. package/dist/shared/node-batch/store.d.ts +26 -0
  633. package/dist/shared/node-batch/store.d.ts.map +1 -0
  634. package/dist/shared/node-batch/store.js +319 -0
  635. package/dist/shared/node-batch/system.d.ts +8 -0
  636. package/dist/shared/node-batch/system.d.ts.map +1 -0
  637. package/dist/shared/node-batch/system.js +569 -0
  638. package/dist/shared/node-batch/types.d.ts +99 -0
  639. package/dist/shared/node-batch/types.d.ts.map +1 -0
  640. package/dist/shared/node-batch/types.js +4 -0
  641. package/dist/shared/opening-move-history.d.ts +47 -0
  642. package/dist/shared/opening-move-history.d.ts.map +1 -0
  643. package/dist/shared/opening-move-history.js +18 -0
  644. package/dist/shared/opening-move-wall-gate.d.ts +55 -0
  645. package/dist/shared/opening-move-wall-gate.d.ts.map +1 -0
  646. package/dist/shared/opening-move-wall-gate.js +44 -0
  647. package/dist/shared/path-point-affordance.d.ts +2 -2
  648. package/dist/shared/path-point-affordance.d.ts.map +1 -1
  649. package/dist/shared/path-point-affordance.js +30 -6
  650. package/dist/shared/placeholder-geometry.d.ts.map +1 -1
  651. package/dist/shared/placeholder-geometry.js +4 -0
  652. package/dist/shared/ports.d.ts +20 -3
  653. package/dist/shared/ports.d.ts.map +1 -1
  654. package/dist/shared/ports.js +148 -7
  655. package/dist/shared/primitive-uv.d.ts +17 -0
  656. package/dist/shared/primitive-uv.d.ts.map +1 -0
  657. package/dist/shared/primitive-uv.js +107 -0
  658. package/dist/shared/reducer-size.d.ts +2 -0
  659. package/dist/shared/reducer-size.d.ts.map +1 -0
  660. package/dist/shared/reducer-size.js +12 -0
  661. package/dist/shared/ridge-snap.js +1 -1
  662. package/dist/shared/roof-surface.d.ts.map +1 -1
  663. package/dist/shared/roof-surface.js +17 -2
  664. package/dist/shared/run-cursor.d.ts +22 -0
  665. package/dist/shared/run-cursor.d.ts.map +1 -0
  666. package/dist/shared/run-cursor.js +19 -0
  667. package/dist/shared/run-direction-feedback.d.ts +20 -0
  668. package/dist/shared/run-direction-feedback.d.ts.map +1 -0
  669. package/dist/shared/run-direction-feedback.js +139 -0
  670. package/dist/shared/run-hanger-controls.d.ts +7 -0
  671. package/dist/shared/run-hanger-controls.d.ts.map +1 -0
  672. package/dist/shared/run-hanger-controls.js +44 -0
  673. package/dist/shared/run-hanger-inspector.d.ts +5 -0
  674. package/dist/shared/run-hanger-inspector.d.ts.map +1 -0
  675. package/dist/shared/run-hanger-inspector.js +43 -0
  676. package/dist/shared/run-hanger-mode.d.ts +11 -0
  677. package/dist/shared/run-hanger-mode.d.ts.map +1 -0
  678. package/dist/shared/run-hanger-mode.js +32 -0
  679. package/dist/shared/run-hanger-system.d.ts +3 -0
  680. package/dist/shared/run-hanger-system.d.ts.map +1 -0
  681. package/dist/shared/run-hanger-system.js +39 -0
  682. package/dist/shared/run-hangers.d.ts +25 -0
  683. package/dist/shared/run-hangers.d.ts.map +1 -0
  684. package/dist/shared/run-hangers.js +261 -0
  685. package/dist/shared/run-port-snap.d.ts +11 -0
  686. package/dist/shared/run-port-snap.d.ts.map +1 -0
  687. package/dist/shared/run-port-snap.js +19 -0
  688. package/dist/shared/run-screen-direction.d.ts +5 -0
  689. package/dist/shared/run-screen-direction.d.ts.map +1 -0
  690. package/dist/shared/run-screen-direction.js +24 -0
  691. package/dist/shared/selection-handles.d.ts +4 -0
  692. package/dist/shared/selection-handles.d.ts.map +1 -1
  693. package/dist/shared/selection-handles.js +10 -0
  694. package/dist/shared/slot-paint.d.ts +8 -1
  695. package/dist/shared/slot-paint.d.ts.map +1 -1
  696. package/dist/shared/slot-paint.js +120 -27
  697. package/dist/shared/surface-paint.d.ts +1 -2
  698. package/dist/shared/surface-paint.d.ts.map +1 -1
  699. package/dist/shared/surface-paint.js +9 -20
  700. package/dist/shared/system-check-panel.d.ts +6 -0
  701. package/dist/shared/system-check-panel.d.ts.map +1 -0
  702. package/dist/shared/system-check-panel.js +62 -0
  703. package/dist/shared/system-checks.d.ts +9 -0
  704. package/dist/shared/system-checks.d.ts.map +1 -0
  705. package/dist/shared/system-checks.js +131 -0
  706. package/dist/shared/wall-attach-target.d.ts +14 -2
  707. package/dist/shared/wall-attach-target.d.ts.map +1 -1
  708. package/dist/shared/wall-attach-target.js +108 -4
  709. package/dist/shared/wall-opening-clearance.d.ts +19 -0
  710. package/dist/shared/wall-opening-clearance.d.ts.map +1 -0
  711. package/dist/shared/wall-opening-clearance.js +28 -0
  712. package/dist/shared/wall-run-move.d.ts +17 -0
  713. package/dist/shared/wall-run-move.d.ts.map +1 -0
  714. package/dist/shared/wall-run-move.js +56 -0
  715. package/dist/shelf/parametrics.js +4 -4
  716. package/dist/site/renderer.d.ts.map +1 -1
  717. package/dist/site/renderer.js +40 -28
  718. package/dist/site/terrain-geometry.d.ts +1 -1
  719. package/dist/site/terrain-geometry.d.ts.map +1 -1
  720. package/dist/site/terrain-geometry.js +35 -9
  721. package/dist/site/terrain-mesh.d.ts +5 -0
  722. package/dist/site/terrain-mesh.d.ts.map +1 -1
  723. package/dist/site/terrain-mesh.js +63 -34
  724. package/dist/skylight/definition.js +1 -1
  725. package/dist/skylight/panel.js +1 -1
  726. package/dist/skylight/parametrics.js +2 -2
  727. package/dist/slab/definition.d.ts.map +1 -1
  728. package/dist/slab/definition.js +6 -1
  729. package/dist/slab/dependency-tracker.d.ts +3 -0
  730. package/dist/slab/dependency-tracker.d.ts.map +1 -0
  731. package/dist/slab/dependency-tracker.js +104 -0
  732. package/dist/slab/floorplan-affordances.d.ts +8 -8
  733. package/dist/slab/geometry.d.ts.map +1 -1
  734. package/dist/slab/geometry.js +16 -2
  735. package/dist/slab/panel.js +1 -1
  736. package/dist/slab/parametrics.js +1 -1
  737. package/dist/slab/system.d.ts.map +1 -1
  738. package/dist/slab/system.js +8 -64
  739. package/dist/solar-panel/definition.js +1 -1
  740. package/dist/solar-panel/panel.js +1 -1
  741. package/dist/solar-panel/parametrics.js +2 -2
  742. package/dist/stair/panel.d.ts.map +1 -1
  743. package/dist/stair/panel.js +18 -13
  744. package/dist/stair/stair-type.d.ts +18 -0
  745. package/dist/stair/stair-type.d.ts.map +1 -0
  746. package/dist/stair/stair-type.js +25 -0
  747. package/dist/stair-segment/panel.d.ts.map +1 -1
  748. package/dist/stair-segment/panel.js +44 -5
  749. package/dist/turbine-vent/definition.d.ts.map +1 -1
  750. package/dist/turbine-vent/definition.js +8 -5
  751. package/dist/turbine-vent/geometry.d.ts.map +1 -1
  752. package/dist/turbine-vent/geometry.js +48 -18
  753. package/dist/turbine-vent/paint.d.ts +4 -0
  754. package/dist/turbine-vent/paint.d.ts.map +1 -0
  755. package/dist/turbine-vent/paint.js +35 -0
  756. package/dist/turbine-vent/panel.js +1 -1
  757. package/dist/turbine-vent/parametrics.js +2 -2
  758. package/dist/turbine-vent/renderer.d.ts.map +1 -1
  759. package/dist/turbine-vent/renderer.js +31 -9
  760. package/dist/wall/curve-eligibility.d.ts +3 -0
  761. package/dist/wall/curve-eligibility.d.ts.map +1 -0
  762. package/dist/wall/curve-eligibility.js +10 -0
  763. package/dist/wall/curve-tool.d.ts.map +1 -1
  764. package/dist/wall/curve-tool.js +8 -11
  765. package/dist/wall/definition.d.ts +1 -1
  766. package/dist/wall/definition.d.ts.map +1 -1
  767. package/dist/wall/definition.js +36 -13
  768. package/dist/wall/floorplan-affordances.d.ts +1 -0
  769. package/dist/wall/floorplan-affordances.d.ts.map +1 -1
  770. package/dist/wall/floorplan-affordances.js +46 -7
  771. package/dist/wall/floorplan-move.d.ts +3 -4
  772. package/dist/wall/floorplan-move.d.ts.map +1 -1
  773. package/dist/wall/floorplan-move.js +122 -9
  774. package/dist/wall/floorplan.d.ts.map +1 -1
  775. package/dist/wall/floorplan.js +19 -23
  776. package/dist/wall/move-shared.d.ts.map +1 -1
  777. package/dist/wall/move-shared.js +10 -7
  778. package/dist/wall/paint.d.ts.map +1 -1
  779. package/dist/wall/paint.js +2 -0
  780. package/dist/wall/panel.d.ts.map +1 -1
  781. package/dist/wall/panel.js +10 -17
  782. package/dist/wall/parametrics.js +2 -2
  783. package/dist/wall/pointer-transparency.d.ts +128 -0
  784. package/dist/wall/pointer-transparency.d.ts.map +1 -0
  785. package/dist/wall/pointer-transparency.js +147 -0
  786. package/dist/wall/renderer.d.ts.map +1 -1
  787. package/dist/wall/renderer.js +65 -8
  788. package/dist/wall/selection-hit-owner.d.ts +53 -0
  789. package/dist/wall/selection-hit-owner.d.ts.map +1 -0
  790. package/dist/wall/selection-hit-owner.js +79 -0
  791. package/dist/wall/system.d.ts +2 -0
  792. package/dist/wall/system.d.ts.map +1 -1
  793. package/dist/wall/system.js +66 -25
  794. package/dist/wall/tool.d.ts.map +1 -1
  795. package/dist/wall/tool.js +5 -0
  796. package/dist/wall/treatment-level-data.d.ts +6 -1
  797. package/dist/wall/treatment-level-data.d.ts.map +1 -1
  798. package/dist/wall/treatment-level-data.js +82 -5
  799. package/dist/wall/treatments.d.ts +1 -0
  800. package/dist/wall/treatments.d.ts.map +1 -1
  801. package/dist/wall/treatments.js +5 -0
  802. package/dist/wall/wall-batch-system.d.ts +38 -6
  803. package/dist/wall/wall-batch-system.d.ts.map +1 -1
  804. package/dist/wall/wall-batch-system.js +122 -25
  805. package/dist/wall/wall-batch.js +2 -2
  806. package/dist/window/definition.d.ts +2 -1
  807. package/dist/window/definition.d.ts.map +1 -1
  808. package/dist/window/definition.js +51 -24
  809. package/dist/window/floorplan-move.d.ts.map +1 -1
  810. package/dist/window/floorplan-move.js +1 -1
  811. package/dist/window/move-tool.d.ts +7 -5
  812. package/dist/window/move-tool.d.ts.map +1 -1
  813. package/dist/window/move-tool.js +344 -58
  814. package/dist/window/panel.d.ts.map +1 -1
  815. package/dist/window/panel.js +2 -0
  816. package/dist/window/parametrics.js +2 -2
  817. package/dist/window/renderer.d.ts.map +1 -1
  818. package/dist/window/renderer.js +5 -7
  819. package/dist/window/tool.d.ts.map +1 -1
  820. package/dist/window/tool.js +227 -13
  821. package/dist/zone/floorplan-affordances.d.ts +12 -12
  822. package/package.json +11 -9
  823. package/dist/dormer/panel-window-section.d.ts +0 -14
  824. package/dist/dormer/panel-window-section.d.ts.map +0 -1
  825. package/dist/dormer/panel-window-section.js +0 -59
  826. package/dist/dormer/window-assembly.d.ts +0 -22
  827. package/dist/dormer/window-assembly.d.ts.map +0 -1
  828. package/dist/dormer/window-assembly.js +0 -111
  829. package/dist/dormer/window-frame.d.ts +0 -24
  830. package/dist/dormer/window-frame.d.ts.map +0 -1
  831. package/dist/dormer/window-frame.js +0 -100
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { CabinetModuleNode, CabinetNode, collectAlignmentAnchors, createSceneApi, emitter, getFloorPlacedFootprints, getWallThickness, isCurvedWall, movingFootprintAnchors, nodeRegistry, resolveAlignment, resolveSupportSlabPatch, spatialGridManager, useScene, } from '@pascal-app/core';
4
- import { clearPlacementSurface, getFloorStackPreviewPosition, getSideFromNormal, isAlignmentGuideActive, isGridSnapActive, isMagneticSnapActive, isValidWallSideFace, markToolCancelConsumed, movementSfxStepKey, PlacementBox, publishPlacementSurface, triggerSFX, useAlignmentGuides, useEditor, useFacingPose, usePlacementPreview, } from '@pascal-app/editor';
4
+ import { clearPlacementSurface, EDITOR_LAYER, getFloorStackPreviewPosition, getSideFromNormal, isAlignmentGuideActive, isGridSnapActive, isMagneticSnapActive, isValidWallSideFace, markToolCancelConsumed, movementSfxStepKey, PlacementBox, PlacementDimensionGuides, parseMeasurement, publishPlacementSurface, triggerSFX, useAlignmentGuides, useEditor, useFacingPose, usePlacementPreview, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { Html } from '@react-three/drei';
7
7
  import { useFrame } from '@react-three/fiber';
@@ -9,21 +9,93 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
9
9
  import { Mesh, Quaternion, Vector3 } from 'three';
10
10
  import { FLOOR_PLACEMENT_ALIGNMENT_THRESHOLD_M, getLevelLocalSnappedPosition, stopPlacementCommitPropagation, subscribeFloorPlacementClicks, subscribeFloorPlacementDoubleClicks, } from '../shared/floor-placement';
11
11
  import { LevelOffsetGroup } from '../shared/level-offset-group';
12
- import { findClosestWallInPlan } from '../shared/wall-attach-target';
12
+ import { findWallOpeningConflicts } from '../shared/wall-opening-clearance';
13
13
  import { cabinetStretchExitSide, chooseCabinetContinuousAnchor, createCabinetContinuousContinuation, isCabinetContinuousFollowUpClick, isForcePlacementEvent, planCabinetContinuousStretch, resolveCabinetContinuousValidity, } from './continuous-placement';
14
14
  import { bumpCabinetRunsNear, cabinetDefinition, cabinetModuleDefinition, cabinetRunFootprint, } from './definition';
15
15
  import { buildCabinetGeometry } from './geometry';
16
- import { resolveCabinetGridPosition } from './placement-snap';
16
+ import { applyCabinetModuleInsertion, cabinetModuleForRunInsertion } from './insertion';
17
+ import { buildCabinetPlacementSizeDimensions, resolveCabinetPlacementDimensionPosition, resolveCabinetPlacementDimensions, } from './placement-dimensions';
18
+ import { resolveCabinetGridPosition, resolveCabinetGridPositionInFrame, resolveCabinetLevelPlanFrame, } from './placement-snap';
17
19
  import useCabinetPlacementStatus from './placement-status';
18
20
  import useCabinetPlacementType from './placement-type';
19
21
  import { cabinetPresetById } from './presets';
20
- import { runLocalToPlan } from './run-layout';
21
- import { addCabinetModuleSide, addCornerRun, previewCornerAdditionLayout } from './run-ops';
22
- import { collectCabinetWallSnapNeighbors, resolveCabinetWallFaceOffset, resolveCabinetWallSnapPlacement, } from './wall-snap';
22
+ import { moduleMaxX, planRunModuleInsertion, planToRunLocal, runLocalToPlan, runWallConstraints, sortRunModules, } from './run-layout';
23
+ import { addCabinetModuleSide, addCornerRun, cabinetModulesForRun, cornerPinnedEndsForRun, previewCornerAdditionLayout, syncCornerRunsFromRunSources, } from './run-ops';
24
+ import { findClosestCabinetWallInPlan, resolveCabinetWallSnapPlacementInScene, } from './wall-snap';
23
25
  const PREVIEW_OPACITY = 0.55;
24
26
  const ROTATE_STEP_RAD = Math.PI / 4;
25
27
  const DEFAULT_PLACEMENT_PRESET = cabinetPresetById('base-door');
26
28
  const ISLAND_SEATING_OVERHANG = 0.3;
29
+ function angleDelta(a, b) {
30
+ return Math.atan2(Math.sin(a - b), Math.cos(a - b));
31
+ }
32
+ function resolveCabinetRunInsertion({ hit, insertionId, nodes, placement, parentLevelId, width, }) {
33
+ if (isCurvedWall(hit.wall))
34
+ return null;
35
+ const candidates = Object.values(nodes).filter((node) => node?.type === 'cabinet' && node.parentId === parentLevelId && node.rotation != null);
36
+ let best;
37
+ for (const run of candidates) {
38
+ if (Math.abs(angleDelta(run.rotation, placement.yaw)) > 0.08)
39
+ continue;
40
+ const modules = cabinetModulesForRun(run, nodes);
41
+ if (modules.length < 2)
42
+ continue;
43
+ const local = planToRunLocal(run, placement.position[0], 0, placement.position[2]);
44
+ const sorted = sortRunModules(modules);
45
+ const insertionIndex = sorted.findIndex((module) => moduleMaxX(module) > local[0] + 1e-4);
46
+ if (insertionIndex <= 0 || insertionIndex >= sorted.length)
47
+ continue;
48
+ const left = sorted[insertionIndex - 1];
49
+ const right = sorted[insertionIndex];
50
+ if (local[0] < moduleMaxX(left) - 0.15 ||
51
+ local[0] > right.position[0] - right.width / 2 + 0.15) {
52
+ continue;
53
+ }
54
+ const distance = Math.abs(local[2] - (left.position[2] + right.position[2]) / 2);
55
+ if (!best || distance < best.distance)
56
+ best = { distance, run, modules, localX: local[0] };
57
+ }
58
+ if (!best)
59
+ return null;
60
+ const { run, modules, localX } = best;
61
+ const sorted = sortRunModules(modules);
62
+ const insertionModule = sorted.find((module) => moduleMaxX(module) > localX + 1e-4);
63
+ const insertionY = insertionModule?.position[1] ?? sorted[0].position[1];
64
+ const insertionZ = insertionModule?.position[2] ?? sorted[0].position[2];
65
+ const preserveEnds = cornerPinnedEndsForRun(modules);
66
+ const result = planRunModuleInsertion({
67
+ modules,
68
+ insertion: {
69
+ id: insertionId,
70
+ position: [localX, insertionY, insertionZ],
71
+ width,
72
+ },
73
+ wallConstraints: runWallConstraints(run, modules, nodes),
74
+ fillerIds: new Set(modules.filter((module) => module.moduleKind === 'corner-filler').map((module) => module.id)),
75
+ preserveEnds,
76
+ anchorInsertionSide: preserveEnds.right ? 'right' : 'left',
77
+ });
78
+ if (!result.ok)
79
+ return { kind: 'blocked', reason: 'no-space', runId: run.id };
80
+ return {
81
+ kind: 'preview',
82
+ runId: run.id,
83
+ plan: {
84
+ runId: run.id,
85
+ runPosition: [...run.position],
86
+ runYaw: run.rotation,
87
+ modules: result.modules.map((module) => ({
88
+ id: module.id,
89
+ position: [...module.position],
90
+ width: module.width,
91
+ })),
92
+ inserted: {
93
+ position: [...result.inserted.position],
94
+ width: result.inserted.width,
95
+ },
96
+ },
97
+ };
98
+ }
27
99
  function isStretchContinuation(anchor) {
28
100
  return 'straightAnchor' in anchor;
29
101
  }
@@ -123,6 +195,8 @@ const CabinetTool = () => {
123
195
  const activeLevelId = useViewer((s) => s.selection.levelId);
124
196
  const unit = useViewer((s) => s.unit);
125
197
  const metricNotation = useViewer((s) => s.metricNotation);
198
+ const activeDimensionId = usePlacementPreview((s) => s.activeDimensionId);
199
+ const dimensionInput = usePlacementPreview((s) => s.dimensionInput);
126
200
  const [placement, setPlacement] = useState(null);
127
201
  const [draftSegments, setDraftSegments] = useState([]);
128
202
  const [yaw, setYaw] = useState(0);
@@ -147,7 +221,7 @@ const CabinetTool = () => {
147
221
  const surfaceQuatRef = useRef(new Quaternion());
148
222
  const surfaceForwardRef = useRef(new Vector3(0, 0, 1));
149
223
  const facingPointRef = useRef(new Vector3());
150
- const previewNode = useMemo(() => {
224
+ const previewNodeTemplate = useMemo(() => {
151
225
  const runDefaults = cabinetDefinition.defaults();
152
226
  return CabinetModuleNode.parse({
153
227
  ...cabinetModuleDefinition.defaults(),
@@ -161,6 +235,19 @@ const CabinetTool = () => {
161
235
  countertopBackOverhang: runDefaults.countertopBackOverhang,
162
236
  });
163
237
  }, []);
238
+ const [previewSize, setPreviewSize] = useState(() => ({
239
+ depth: previewNodeTemplate.depth,
240
+ height: previewNodeTemplate.carcassHeight,
241
+ width: previewNodeTemplate.width,
242
+ }));
243
+ const previewNode = useMemo(() => CabinetModuleNode.parse({
244
+ ...previewNodeTemplate,
245
+ carcassHeight: previewSize.height,
246
+ depth: previewSize.depth,
247
+ width: previewSize.width,
248
+ }), [previewNodeTemplate, previewSize]);
249
+ const previewNodeRef = useRef(previewNode);
250
+ previewNodeRef.current = previewNode;
164
251
  const placementDimensions = useMemo(() => {
165
252
  const defaults = cabinetDefinition.defaults();
166
253
  return [
@@ -171,6 +258,22 @@ const CabinetTool = () => {
171
258
  previewNode.depth + (islandMode ? ISLAND_SEATING_OVERHANG : 0),
172
259
  ];
173
260
  }, [previewNode, islandMode]);
261
+ const placementDimensionsRef = useRef(placementDimensions);
262
+ placementDimensionsRef.current = placementDimensions;
263
+ const placementSnapFootprint = useMemo(() => {
264
+ const sideAndFrontOverhang = previewNode.withCountertop ? previewNode.countertopOverhang : 0;
265
+ const backOverhang = islandMode ? ISLAND_SEATING_OVERHANG : 0;
266
+ return {
267
+ dimensions: [
268
+ previewNode.width + sideAndFrontOverhang * 2,
269
+ placementDimensions[1],
270
+ previewNode.depth + sideAndFrontOverhang + backOverhang,
271
+ ],
272
+ offset: [0, (sideAndFrontOverhang - backOverhang) / 2],
273
+ };
274
+ }, [islandMode, placementDimensions, previewNode]);
275
+ const placementSnapFootprintRef = useRef(placementSnapFootprint);
276
+ placementSnapFootprintRef.current = placementSnapFootprint;
174
277
  const ghost = useMemo(() => {
175
278
  const group = buildCabinetGeometry(previewNode);
176
279
  group.traverse((child) => {
@@ -183,6 +286,26 @@ const CabinetTool = () => {
183
286
  });
184
287
  return group;
185
288
  }, [previewNode]);
289
+ const insertionGhost = useMemo(() => {
290
+ const node = CabinetModuleNode.parse({
291
+ ...previewNode,
292
+ plinthHeight: 0,
293
+ showPlinth: false,
294
+ countertopThickness: 0,
295
+ withCountertop: false,
296
+ });
297
+ const group = buildCabinetGeometry(node);
298
+ group.traverse((child) => {
299
+ child.layers.set(EDITOR_LAYER);
300
+ if (child instanceof Mesh) {
301
+ child.material = child.material.clone();
302
+ child.material.transparent = true;
303
+ child.material.opacity = PREVIEW_OPACITY;
304
+ child.raycast = () => { };
305
+ }
306
+ });
307
+ return group;
308
+ }, [previewNode]);
186
309
  // The stretched span renders one ghost per module — the same Object3D can't
187
310
  // appear twice in the scene, so extra modules reuse pooled clones (geometry
188
311
  // and materials stay shared) instead of cloning on every pointer move.
@@ -195,23 +318,87 @@ const CabinetTool = () => {
195
318
  pool.push(ghost.clone());
196
319
  return pool[index - 1];
197
320
  }, [ghost]);
321
+ const insertionGhostPoolRef = useRef([]);
322
+ const insertionGhostForIndex = useCallback((index) => {
323
+ if (index === 0)
324
+ return insertionGhost;
325
+ const pool = insertionGhostPoolRef.current;
326
+ while (pool.length < index)
327
+ pool.push(insertionGhost.clone());
328
+ return pool[index - 1];
329
+ }, [insertionGhost]);
198
330
  const publishFloorplanPreview = useCallback((next, island = islandModeRef.current) => {
199
331
  const stretch = next.stretch;
332
+ const previewPosition = stretch
333
+ ? runLocalToPlan({ position: next.position, rotation: next.yaw }, [
334
+ stretch.centerLocalX,
335
+ 0,
336
+ 0,
337
+ ])
338
+ : next.position;
339
+ const livePreviewNode = previewNodeRef.current;
200
340
  const node = buildCabinetPlacementPreviewNode({
201
341
  island,
202
- position: stretch
203
- ? runLocalToPlan({ position: next.position, rotation: next.yaw }, [
204
- stretch.centerLocalX,
205
- 0,
206
- 0,
207
- ])
208
- : next.position,
209
- previewModule: previewNode,
342
+ position: previewPosition,
343
+ previewModule: livePreviewNode,
210
344
  yaw: next.yaw,
211
345
  });
346
+ let floorplanNode = stretch ? { ...node, width: stretch.length } : node;
347
+ let floorplanContextNodes = [];
348
+ if (next.insertionPreview) {
349
+ const liveRun = useScene.getState().nodes[next.insertionPreview.runId];
350
+ if (liveRun?.type === 'cabinet') {
351
+ const insertedId = livePreviewNode.id;
352
+ const previewModules = [
353
+ ...next.insertionPreview.modules.map((planned) => {
354
+ const liveModule = useScene.getState().nodes[planned.id];
355
+ return liveModule?.type === 'cabinet-module'
356
+ ? {
357
+ ...liveModule,
358
+ position: planned.position,
359
+ width: planned.width,
360
+ }
361
+ : null;
362
+ }),
363
+ CabinetModuleNode.parse({
364
+ ...cabinetModuleForRunInsertion(livePreviewNode, liveRun),
365
+ id: insertedId,
366
+ position: next.insertionPreview.inserted.position,
367
+ width: next.insertionPreview.inserted.width,
368
+ }),
369
+ ].filter((previewModule) => previewModule != null);
370
+ floorplanNode = CabinetNode.parse({
371
+ ...liveRun,
372
+ children: previewModules.map((previewModule) => previewModule.id),
373
+ });
374
+ floorplanContextNodes = previewModules;
375
+ }
376
+ }
377
+ const placementDimensions = activeLevelId && !island
378
+ ? resolveCabinetPlacementDimensions({
379
+ depth: livePreviewNode.depth,
380
+ levelId: activeLevelId,
381
+ nodes: useScene.getState().nodes,
382
+ position: previewPosition,
383
+ rotation: next.yaw,
384
+ wallId: next.wallId,
385
+ width: stretch?.length ?? livePreviewNode.width,
386
+ })
387
+ : [];
388
+ const sizeDimensions = !stretch && !island
389
+ ? buildCabinetPlacementSizeDimensions({
390
+ depth: livePreviewNode.depth,
391
+ height: livePreviewNode.carcassHeight,
392
+ position: previewPosition,
393
+ rotation: next.yaw,
394
+ width: livePreviewNode.width,
395
+ })
396
+ : [];
212
397
  // A stretched span can exceed the schema's width cap — override post-parse.
213
- usePlacementPreview.getState().set(stretch ? { ...node, width: stretch.length } : node);
214
- }, [previewNode]);
398
+ usePlacementPreview
399
+ .getState()
400
+ .set(floorplanNode, null, [...placementDimensions, ...sizeDimensions], floorplanContextNodes);
401
+ }, [activeLevelId]);
215
402
  useFrame(() => {
216
403
  const ghostGroup = activeGhostRef.current;
217
404
  const current = placementRef.current;
@@ -260,7 +447,7 @@ const CabinetTool = () => {
260
447
  previousWasWallSnapRef.current = false;
261
448
  previousTickFrameRef.current = -1;
262
449
  draftAnchorRef.current = null;
263
- let alignmentCandidates = collectAlignmentAnchors(useScene.getState().nodes, previewNode.id, activeLevelId);
450
+ let alignmentCandidates = collectAlignmentAnchors(useScene.getState().nodes, previewNodeRef.current.id, activeLevelId);
264
451
  let lastWallEventTime = -1;
265
452
  let wallOwnedPointerAt = Number.NEGATIVE_INFINITY;
266
453
  const WALL_OWNS_POINTER_MS = 64;
@@ -323,9 +510,21 @@ const CabinetTool = () => {
323
510
  };
324
511
  const resolveGridPosition = (raw, bypassGrid = false) => {
325
512
  const step = !bypassGrid && isGridSnapActive() ? useEditor.getState().gridSnapStep : 0;
513
+ if (step > 0) {
514
+ const frame = resolveCabinetLevelPlanFrame(activeLevelId, useScene.getState().nodes);
515
+ return resolveCabinetGridPositionInFrame({
516
+ raw,
517
+ dimensions: placementSnapFootprintRef.current.dimensions,
518
+ footprintOffset: placementSnapFootprintRef.current.offset,
519
+ yaw: yawRef.current,
520
+ step,
521
+ frame,
522
+ });
523
+ }
326
524
  return resolveCabinetGridPosition({
327
525
  raw,
328
- dimensions: placementDimensions,
526
+ dimensions: placementSnapFootprintRef.current.dimensions,
527
+ footprintOffset: placementSnapFootprintRef.current.offset,
329
528
  yaw: yawRef.current,
330
529
  step,
331
530
  });
@@ -338,7 +537,7 @@ const CabinetTool = () => {
338
537
  const alignmentNode = buildCabinetPlacementPreviewNode({
339
538
  island: islandModeRef.current,
340
539
  position,
341
- previewModule: previewNode,
540
+ previewModule: previewNodeRef.current,
342
541
  yaw,
343
542
  });
344
543
  const moving = movingFootprintAnchors({
@@ -360,60 +559,83 @@ const CabinetTool = () => {
360
559
  return [position[0] + result.snap.dx, position[1], position[2] + result.snap.dz];
361
560
  };
362
561
  const withPlacementValidity = (next, bypassCollision) => {
363
- if (bypassCollision)
364
- return { ...next, conflictIds: [], valid: true };
365
- const floorPlaced = nodeRegistry.get(previewNode.type)?.capabilities?.floorPlaced;
562
+ if (bypassCollision) {
563
+ return { ...next, conflictIds: [], valid: !next.insertionFailure };
564
+ }
565
+ const livePreviewNode = previewNodeRef.current;
566
+ const livePlacementDimensions = placementDimensionsRef.current;
567
+ const floorPlaced = nodeRegistry.get(livePreviewNode.type)?.capabilities?.floorPlaced;
366
568
  const effectiveNode = {
367
- ...previewNode,
569
+ ...livePreviewNode,
368
570
  position: next.position,
369
571
  rotation: next.yaw,
370
572
  };
573
+ const ignoreIds = next.insertionPreview ? [next.insertionPreview.runId] : undefined;
371
574
  const footprints = floorPlaced
372
575
  ? getFloorPlacedFootprints(floorPlaced, effectiveNode, {
373
576
  nodes: useScene.getState().nodes,
374
577
  }).filter((footprint) => footprint.position != null)
375
578
  : [];
376
579
  const result = footprints.length > 0
377
- ? spatialGridManager.canPlaceOnFloorFootprints(activeLevelId, footprints)
378
- : spatialGridManager.canPlaceOnFloor(activeLevelId, next.position, placementDimensions, [
379
- 0,
380
- next.yaw,
381
- 0,
382
- ]);
383
- return { ...next, conflictIds: result.conflictIds, valid: result.valid };
580
+ ? spatialGridManager.canPlaceOnFloorFootprints(activeLevelId, footprints, ignoreIds)
581
+ : spatialGridManager.canPlaceOnFloor(activeLevelId, next.position, livePlacementDimensions, [0, next.yaw, 0], ignoreIds);
582
+ const wall = next.wallId ? useScene.getState().nodes[next.wallId] : undefined;
583
+ const openingConflictIds = wall?.type === 'wall' && next.wallLocalX != null
584
+ ? findWallOpeningConflicts({
585
+ bottom: 0,
586
+ height: livePlacementDimensions[1],
587
+ localX: next.wallLocalX,
588
+ nodes: useScene.getState().nodes,
589
+ wall,
590
+ width: livePreviewNode.width,
591
+ })
592
+ : [];
593
+ const conflictIds = [...new Set([...result.conflictIds, ...openingConflictIds])];
594
+ return {
595
+ ...next,
596
+ conflictIds,
597
+ valid: !next.insertionFailure && result.valid && openingConflictIds.length === 0,
598
+ };
384
599
  };
385
600
  const resolveWallHitPlacement = (hit) => {
386
601
  if (!isWallSnapEligible())
387
602
  return null;
388
603
  const nodes = useScene.getState().nodes;
389
- const neighbors = collectCabinetWallSnapNeighbors({
604
+ const wallPlacement = resolveCabinetWallSnapPlacementInScene({
605
+ depth: previewNodeRef.current.depth,
606
+ gridStep: isGridSnapActive() ? useEditor.getState().gridSnapStep : 0,
390
607
  hit,
391
608
  nodes,
392
609
  parentLevelId: activeLevelId,
393
- width: previewNode.width,
610
+ width: previewNodeRef.current.width,
394
611
  });
395
- const faceOffset = resolveCabinetWallFaceOffset({
612
+ if (!wallPlacement)
613
+ return null;
614
+ const wallSurfaceNormal = [Math.sin(wallPlacement.yaw), 0, Math.cos(wallPlacement.yaw)];
615
+ const insertion = resolveCabinetRunInsertion({
396
616
  hit,
617
+ insertionId: previewNodeRef.current.id,
397
618
  nodes,
619
+ placement: wallPlacement,
398
620
  parentLevelId: activeLevelId,
621
+ width: previewNodeRef.current.width,
399
622
  });
400
- const wallPlacement = resolveCabinetWallSnapPlacement({
401
- depth: previewNode.depth,
402
- faceOffset,
403
- gridStep: isGridSnapActive() ? useEditor.getState().gridSnapStep : 0,
404
- hit,
405
- neighbors,
406
- width: previewNode.width,
407
- });
408
- if (!wallPlacement)
409
- return null;
410
- const wallSurfaceNormal = [Math.sin(wallPlacement.yaw), 0, Math.cos(wallPlacement.yaw)];
623
+ const insertionPreview = insertion?.kind === 'preview' ? insertion.plan : undefined;
624
+ const insertionFailure = insertion?.kind === 'blocked'
625
+ ? { runId: insertion.runId, reason: insertion.reason }
626
+ : undefined;
627
+ const insertionPosition = insertionPreview
628
+ ? runLocalToPlan({ position: insertionPreview.runPosition, rotation: insertionPreview.runYaw }, insertionPreview.inserted.position)
629
+ : wallPlacement.position;
411
630
  return {
412
631
  conflictIds: [],
413
632
  guide: wallPlacement.guide,
414
- position: wallPlacement.position,
633
+ ...(insertionFailure ? { insertionFailure } : {}),
634
+ ...(insertionPreview ? { insertionPreview } : {}),
635
+ position: insertionPosition,
415
636
  snapReason: wallPlacement.snapReason,
416
637
  valid: true,
638
+ wallId: hit.wall.id,
417
639
  wallLocalX: wallPlacement.localX,
418
640
  wallSurfaceNormal,
419
641
  yaw: wallPlacement.yaw,
@@ -424,7 +646,12 @@ const CabinetTool = () => {
424
646
  if (!isWallSnapEligible())
425
647
  return null;
426
648
  const nodes = useScene.getState().nodes;
427
- const hit = findClosestWallInPlan([raw[0], raw[2]], nodes, activeLevelId);
649
+ const hit = findClosestCabinetWallInPlan({
650
+ excludeIds: [],
651
+ nodes,
652
+ parentLevelId: activeLevelId,
653
+ planPoint: [raw[0], raw[2]],
654
+ });
428
655
  if (!hit)
429
656
  return null;
430
657
  return resolveWallHitPlacement(hit);
@@ -455,6 +682,44 @@ const CabinetTool = () => {
455
682
  snappedToWall: false,
456
683
  }, forcePlacement);
457
684
  };
685
+ const resolveStretchedValidity = (anchor, stretch, forcePlace) => {
686
+ const spanCenter = runLocalToPlan({ position: anchor.position, rotation: anchor.yaw }, [
687
+ stretch.centerLocalX,
688
+ 0,
689
+ 0,
690
+ ]);
691
+ const ignoreIds = chainRootRunRef.current
692
+ ? [chainRootRunRef.current.id]
693
+ : undefined;
694
+ return resolveCabinetContinuousValidity((() => {
695
+ const floorResult = spatialGridManager.canPlaceOnFloor(activeLevelId, spanCenter, [stretch.length, placementDimensionsRef.current[1], placementDimensionsRef.current[2]], [0, anchor.yaw, 0], ignoreIds);
696
+ const nodes = useScene.getState().nodes;
697
+ const wall = anchor.wallId ? nodes[anchor.wallId] : undefined;
698
+ const wallHit = wall?.type === 'wall' && anchor.wallLocalX != null
699
+ ? { wall, localX: anchor.wallLocalX + stretch.centerLocalX }
700
+ : findClosestCabinetWallInPlan({
701
+ excludeIds: [],
702
+ nodes,
703
+ parentLevelId: activeLevelId,
704
+ planPoint: [spanCenter[0], spanCenter[2]],
705
+ yaw: anchor.yaw,
706
+ });
707
+ const openingConflictIds = wallHit && (wallHit.localX ?? null) != null
708
+ ? findWallOpeningConflicts({
709
+ bottom: 0,
710
+ height: placementDimensionsRef.current[1],
711
+ localX: wallHit.localX,
712
+ nodes,
713
+ wall: wallHit.wall,
714
+ width: stretch.length,
715
+ })
716
+ : [];
717
+ return {
718
+ conflictIds: [...new Set([...floorResult.conflictIds, ...openingConflictIds])],
719
+ valid: floorResult.valid && openingConflictIds.length === 0,
720
+ };
721
+ })(), forcePlace);
722
+ };
458
723
  // While stretching, the run is pinned at the anchored first module and
459
724
  // grows toward the cursor — the far end tracks the pointer smoothly.
460
725
  const resolveStretchedPlacement = (anchor, event) => {
@@ -462,7 +727,7 @@ const CabinetTool = () => {
462
727
  const raw = resolveRawPosition(event);
463
728
  let stretch = planCabinetContinuousStretch({
464
729
  anchor,
465
- previewWidth: previewNode.width,
730
+ previewWidth: previewNodeRef.current.width,
466
731
  rawPlanPosition: raw,
467
732
  });
468
733
  if (anchor.leadingWidth != null &&
@@ -480,6 +745,8 @@ const CabinetTool = () => {
480
745
  position: anchor.position,
481
746
  yaw: anchor.yaw,
482
747
  snappedToWall: anchor.snappedToWall,
748
+ wallId: anchor.wallId,
749
+ wallLocalX: anchor.wallLocalX,
483
750
  wallSurfaceNormal: anchor.wallSurfaceNormal,
484
751
  valid: false,
485
752
  conflictIds: [],
@@ -489,19 +756,13 @@ const CabinetTool = () => {
489
756
  }
490
757
  stretch = stretchWithAdjustedConnectedWidth(stretch, preview.connectedWidth);
491
758
  }
492
- const spanCenter = runLocalToPlan({ position: anchor.position, rotation: anchor.yaw }, [
493
- stretch.centerLocalX,
494
- 0,
495
- 0,
496
- ]);
497
- const ignoreIds = chainRootRunRef.current
498
- ? [chainRootRunRef.current.id]
499
- : undefined;
500
- const result = resolveCabinetContinuousValidity(spatialGridManager.canPlaceOnFloor(activeLevelId, spanCenter, [stretch.length, placementDimensions[1], placementDimensions[2]], [0, anchor.yaw, 0], ignoreIds), isForcePlacementEvent(event));
759
+ const result = resolveStretchedValidity(anchor, stretch, isForcePlacementEvent(event));
501
760
  return {
502
761
  position: anchor.position,
503
762
  yaw: anchor.yaw,
504
763
  snappedToWall: anchor.snappedToWall,
764
+ wallId: anchor.wallId,
765
+ wallLocalX: anchor.wallLocalX,
505
766
  wallSurfaceNormal: anchor.wallSurfaceNormal,
506
767
  valid: result.valid,
507
768
  conflictIds: result.conflictIds,
@@ -693,6 +954,86 @@ const CabinetTool = () => {
693
954
  }
694
955
  return { anchor: currentPlacement.stretchAnchor, stretch: currentPlacement.stretch };
695
956
  };
957
+ const commitInsertion = (next) => {
958
+ const insertionPreview = next.insertionPreview;
959
+ if (!insertionPreview)
960
+ return null;
961
+ const sceneApi = createSceneApi(useScene);
962
+ const run = sceneApi.get(insertionPreview.runId);
963
+ if (!run)
964
+ return null;
965
+ const module = cabinetModuleForRunInsertion(CabinetModuleNode.parse({
966
+ ...previewNodeRef.current,
967
+ position: insertionPreview.inserted.position,
968
+ width: insertionPreview.inserted.width,
969
+ }), run);
970
+ sceneApi.pauseHistory();
971
+ try {
972
+ const id = applyCabinetModuleInsertion({
973
+ module,
974
+ plan: insertionPreview,
975
+ run,
976
+ sceneApi,
977
+ });
978
+ if (!id)
979
+ throw new Error('Unable to apply cabinet insertion');
980
+ const liveRun = sceneApi.get(run.id);
981
+ if (!liveRun)
982
+ throw new Error('Unable to resolve inserted cabinet run');
983
+ sceneApi.update(liveRun.id, resolveSupportSlabPatch(liveRun, sceneApi.nodes()));
984
+ syncCornerRunsFromRunSources({
985
+ run: sceneApi.get(liveRun.id) ?? liveRun,
986
+ sceneApi,
987
+ });
988
+ const updatedRun = sceneApi.get(liveRun.id) ?? liveRun;
989
+ bumpCabinetRunsNear(sceneApi, [cabinetRunFootprint(updatedRun, sceneApi.nodes())], new Set([updatedRun.id]));
990
+ sceneApi.resumeHistory();
991
+ return id;
992
+ }
993
+ catch {
994
+ sceneApi.restoreAll();
995
+ sceneApi.resumeHistory();
996
+ return null;
997
+ }
998
+ };
999
+ const updatePreviewSize = (field, value) => {
1000
+ const nextPreviewNode = CabinetModuleNode.parse({
1001
+ ...previewNodeRef.current,
1002
+ carcassHeight: field === 'height' ? value : previewNodeRef.current.carcassHeight,
1003
+ depth: field === 'depth' ? value : previewNodeRef.current.depth,
1004
+ width: field === 'width' ? value : previewNodeRef.current.width,
1005
+ });
1006
+ previewNodeRef.current = nextPreviewNode;
1007
+ setPreviewSize({
1008
+ depth: nextPreviewNode.depth,
1009
+ height: nextPreviewNode.carcassHeight,
1010
+ width: nextPreviewNode.width,
1011
+ });
1012
+ const nextPlacementDimensions = [
1013
+ nextPreviewNode.width,
1014
+ (nextPreviewNode.showPlinth ? nextPreviewNode.plinthHeight : 0) +
1015
+ nextPreviewNode.carcassHeight +
1016
+ (nextPreviewNode.withCountertop ? nextPreviewNode.countertopThickness : 0),
1017
+ nextPreviewNode.depth + (islandModeRef.current ? ISLAND_SEATING_OVERHANG : 0),
1018
+ ];
1019
+ placementDimensionsRef.current = nextPlacementDimensions;
1020
+ const sideAndFrontOverhang = nextPreviewNode.withCountertop
1021
+ ? nextPreviewNode.countertopOverhang
1022
+ : 0;
1023
+ placementSnapFootprintRef.current = {
1024
+ dimensions: [
1025
+ nextPreviewNode.width + sideAndFrontOverhang * 2,
1026
+ nextPlacementDimensions[1],
1027
+ nextPreviewNode.depth +
1028
+ sideAndFrontOverhang +
1029
+ (islandModeRef.current ? ISLAND_SEATING_OVERHANG : 0),
1030
+ ],
1031
+ offset: [
1032
+ 0,
1033
+ (sideAndFrontOverhang - (islandModeRef.current ? ISLAND_SEATING_OVERHANG : 0)) / 2,
1034
+ ],
1035
+ };
1036
+ };
696
1037
  const onDoubleClick = (event) => {
697
1038
  const anchor = resolveDraftAnchor();
698
1039
  if (!anchor)
@@ -735,8 +1076,8 @@ const CabinetTool = () => {
735
1076
  chainCornerSideRef.current = cabinetStretchExitSide(segment.stretch);
736
1077
  draftAnchorRef.current = createCabinetContinuousContinuation({
737
1078
  anchor: segment.anchor,
738
- previewDepth: previewNode.depth,
739
- previewWidth: previewNode.width,
1079
+ previewDepth: previewNodeRef.current.depth,
1080
+ previewWidth: previewNodeRef.current.width,
740
1081
  stretch: segment.stretch,
741
1082
  });
742
1083
  publishPlacement(resolveActiveStretchPlacement(draftAnchorRef.current, event));
@@ -751,6 +1092,22 @@ const CabinetTool = () => {
751
1092
  stopPlacementCommitPropagation(event);
752
1093
  return;
753
1094
  }
1095
+ if (next.insertionPreview) {
1096
+ const insertedId = commitInsertion(next);
1097
+ if (!insertedId) {
1098
+ stopPlacementCommitPropagation(event);
1099
+ return;
1100
+ }
1101
+ useViewer.getState().setSelection({ selectedIds: [insertedId] });
1102
+ useEditor.getState().setMode('select');
1103
+ triggerSFX('sfx:item-place');
1104
+ useAlignmentGuides.getState().clear();
1105
+ usePlacementPreview.getState().clear();
1106
+ clearPlacementSurface();
1107
+ useFacingPose.getState().clear();
1108
+ stopPlacementCommitPropagation(event);
1109
+ return;
1110
+ }
754
1111
  if (useEditor.getState().getContinuation('cabinet') === 'continuous') {
755
1112
  draftSegmentsRef.current = [];
756
1113
  setDraftSegments([]);
@@ -762,6 +1119,8 @@ const CabinetTool = () => {
762
1119
  position: next.position,
763
1120
  yaw: next.yaw,
764
1121
  snappedToWall: next.snappedToWall,
1122
+ wallId: next.wallId,
1123
+ wallLocalX: next.wallLocalX,
765
1124
  wallSurfaceNormal: next.wallSurfaceNormal,
766
1125
  };
767
1126
  publishPlacement(resolveStretchedPlacement(draftAnchorRef.current, event));
@@ -770,7 +1129,7 @@ const CabinetTool = () => {
770
1129
  return;
771
1130
  }
772
1131
  const { cabinet, buildModule } = buildRunNodes(next.position, next.yaw);
773
- const module = buildModule(0, previewNode.width, 0);
1132
+ const module = buildModule(0, previewNodeRef.current.width, 0);
774
1133
  const nodes = { ...useScene.getState().nodes, [cabinet.id]: cabinet, [module.id]: module };
775
1134
  const committedCabinet = CabinetNode.parse({
776
1135
  ...cabinet,
@@ -790,10 +1149,182 @@ const CabinetTool = () => {
790
1149
  useFacingPose.getState().clear();
791
1150
  stopPlacementCommitPropagation(event);
792
1151
  };
1152
+ const applyTypedDimension = () => {
1153
+ const editor = usePlacementPreview.getState();
1154
+ const current = placementRef.current;
1155
+ if (!editor.activeDimensionId || !editor.dimensionInput || !current) {
1156
+ return false;
1157
+ }
1158
+ const value = parseMeasurement(editor.dimensionInput, { kind: 'length', unitId: 'm' }, {
1159
+ bareUnit: unit === 'imperial' ? 'in' : metricNotation === 'millimeters' ? 'mm' : 'm',
1160
+ system: unit === 'imperial' ? 'imperial' : 'metric',
1161
+ });
1162
+ if (value === null)
1163
+ return false;
1164
+ if (!current.stretch) {
1165
+ const sizeField = editor.activeDimensionId === 'cabinet-width'
1166
+ ? 'width'
1167
+ : editor.activeDimensionId === 'cabinet-depth'
1168
+ ? 'depth'
1169
+ : editor.activeDimensionId === 'cabinet-height'
1170
+ ? 'height'
1171
+ : null;
1172
+ if (sizeField) {
1173
+ const limits = sizeField === 'width'
1174
+ ? { max: 3, min: 0.3 }
1175
+ : sizeField === 'depth'
1176
+ ? { max: 1.2, min: 0.3 }
1177
+ : { max: 1.4, min: 0.4 };
1178
+ const nextValue = Math.min(limits.max, Math.max(limits.min, value));
1179
+ updatePreviewSize(sizeField, nextValue);
1180
+ let position = current.position;
1181
+ let wallLocalX = current.wallLocalX;
1182
+ if (current.snappedToWall && current.wallId) {
1183
+ const resolvedWallPosition = resolveCabinetPlacementDimensionPosition({
1184
+ depth: previewNodeRef.current.depth,
1185
+ dimensionId: 'wall-clearance',
1186
+ levelId: activeLevelId,
1187
+ nodes: useScene.getState().nodes,
1188
+ position: current.position,
1189
+ rotation: current.yaw,
1190
+ wallId: current.wallId,
1191
+ value: 0,
1192
+ width: previewNodeRef.current.width,
1193
+ });
1194
+ if (resolvedWallPosition) {
1195
+ position = resolvedWallPosition.position;
1196
+ wallLocalX = resolvedWallPosition.wallLocalX;
1197
+ }
1198
+ }
1199
+ const { conflictIds: _conflictIds, valid: _valid, ...placementBase } = current;
1200
+ const next = withPlacementValidity({
1201
+ ...placementBase,
1202
+ position,
1203
+ ...(wallLocalX != null ? { wallLocalX } : {}),
1204
+ }, false);
1205
+ placementRef.current = next;
1206
+ setPlacement(next);
1207
+ publishFloorplanPreview(next);
1208
+ editor.clearDimensionEditor();
1209
+ return true;
1210
+ }
1211
+ }
1212
+ if (current.stretch && current.stretchAnchor) {
1213
+ const spanPosition = runLocalToPlan({ position: current.position, rotation: current.yaw }, [
1214
+ current.stretch.centerLocalX,
1215
+ 0,
1216
+ 0,
1217
+ ]);
1218
+ const resolved = resolveCabinetPlacementDimensionPosition({
1219
+ depth: previewNodeRef.current.depth,
1220
+ dimensionId: editor.activeDimensionId,
1221
+ levelId: activeLevelId,
1222
+ nodes: useScene.getState().nodes,
1223
+ position: spanPosition,
1224
+ rotation: current.yaw,
1225
+ wallId: current.wallId,
1226
+ value,
1227
+ width: current.stretch.length,
1228
+ });
1229
+ if (!resolved)
1230
+ return false;
1231
+ const anchorPosition = runLocalToPlan({ position: resolved.position, rotation: current.yaw }, [-current.stretch.centerLocalX, 0, 0]);
1232
+ const nextAnchor = {
1233
+ ...current.stretchAnchor,
1234
+ position: anchorPosition,
1235
+ ...(current.wallId && current.wallLocalX != null
1236
+ ? { wallLocalX: resolved.wallLocalX - current.stretch.centerLocalX }
1237
+ : {}),
1238
+ };
1239
+ const validity = resolveStretchedValidity(nextAnchor, current.stretch, false);
1240
+ const next = {
1241
+ ...current,
1242
+ conflictIds: validity.conflictIds,
1243
+ position: anchorPosition,
1244
+ stretchAnchor: nextAnchor,
1245
+ valid: validity.valid,
1246
+ ...(current.wallId && current.wallLocalX != null
1247
+ ? { wallLocalX: resolved.wallLocalX - current.stretch.centerLocalX }
1248
+ : {}),
1249
+ };
1250
+ placementRef.current = next;
1251
+ setPlacement(next);
1252
+ publishFloorplanPreview(next);
1253
+ editor.clearDimensionEditor();
1254
+ return true;
1255
+ }
1256
+ const resolved = resolveCabinetPlacementDimensionPosition({
1257
+ depth: previewNodeRef.current.depth,
1258
+ dimensionId: editor.activeDimensionId,
1259
+ levelId: activeLevelId,
1260
+ nodes: useScene.getState().nodes,
1261
+ position: current.position,
1262
+ rotation: current.yaw,
1263
+ wallId: current.wallId,
1264
+ value,
1265
+ width: previewNodeRef.current.width,
1266
+ });
1267
+ if (!resolved)
1268
+ return false;
1269
+ const { conflictIds: _conflictIds, valid: _valid, ...placementBase } = current;
1270
+ const next = withPlacementValidity({
1271
+ ...placementBase,
1272
+ position: resolved.position,
1273
+ wallLocalX: resolved.wallLocalX,
1274
+ }, false);
1275
+ placementRef.current = next;
1276
+ setPlacement(next);
1277
+ publishFloorplanPreview(next);
1278
+ editor.clearDimensionEditor();
1279
+ return true;
1280
+ };
793
1281
  const onKeyDown = (event) => {
794
1282
  const tag = event.target?.tagName;
795
1283
  if (tag === 'INPUT' || tag === 'TEXTAREA')
796
1284
  return;
1285
+ const dimensionEditor = usePlacementPreview.getState();
1286
+ if (event.key === 'Tab' && dimensionEditor.dimensions.length > 0) {
1287
+ const currentIndex = dimensionEditor.dimensions.findIndex((dimension) => dimension.id === dimensionEditor.activeDimensionId);
1288
+ const direction = event.shiftKey ? -1 : 1;
1289
+ const nextIndex = (currentIndex + direction + dimensionEditor.dimensions.length) %
1290
+ dimensionEditor.dimensions.length;
1291
+ dimensionEditor.selectDimension(dimensionEditor.dimensions[nextIndex].id);
1292
+ event.preventDefault();
1293
+ event.stopPropagation();
1294
+ return;
1295
+ }
1296
+ if (dimensionEditor.activeDimensionId && placementRef.current) {
1297
+ if (event.key === 'Enter') {
1298
+ applyTypedDimension();
1299
+ event.preventDefault();
1300
+ event.stopPropagation();
1301
+ return;
1302
+ }
1303
+ if (event.key === 'Escape') {
1304
+ dimensionEditor.clearDimensionEditor();
1305
+ event.preventDefault();
1306
+ event.stopPropagation();
1307
+ return;
1308
+ }
1309
+ if (event.key === 'Backspace' || event.key === 'Delete') {
1310
+ dimensionEditor.setDimensionInput(event.key === 'Delete'
1311
+ ? ''
1312
+ : dimensionEditor.dimensionInput.slice(0, Math.max(0, dimensionEditor.dimensionInput.length - 1)));
1313
+ event.preventDefault();
1314
+ event.stopPropagation();
1315
+ return;
1316
+ }
1317
+ if (event.key.length === 1 &&
1318
+ !event.metaKey &&
1319
+ !event.ctrlKey &&
1320
+ !event.altKey &&
1321
+ /^[0-9a-zA-Z.'"+\- ]$/.test(event.key)) {
1322
+ dimensionEditor.setDimensionInput(dimensionEditor.dimensionInput + event.key);
1323
+ event.preventDefault();
1324
+ event.stopPropagation();
1325
+ return;
1326
+ }
1327
+ }
797
1328
  if (event.key === 'i' || event.key === 'I') {
798
1329
  event.preventDefault();
799
1330
  event.stopPropagation();
@@ -816,12 +1347,7 @@ const CabinetTool = () => {
816
1347
  const raw = lastRawPositionRef.current ?? current.position;
817
1348
  const position = resolveAlignedCabinetPosition({
818
1349
  applyAlignmentSnap: isMagneticSnapActive(),
819
- position: resolveCabinetGridPosition({
820
- raw,
821
- dimensions: placementDimensions,
822
- yaw: yawRef.current,
823
- step: isGridSnapActive() ? useEditor.getState().gridSnapStep : 0,
824
- }),
1350
+ position: resolveGridPosition(raw),
825
1351
  yaw: yawRef.current,
826
1352
  });
827
1353
  const next = withPlacementValidity({ ...placementBase, position, yaw: yawRef.current }, false);
@@ -861,7 +1387,7 @@ const CabinetTool = () => {
861
1387
  useAlignmentGuides.getState().clear();
862
1388
  useCabinetPlacementStatus.getState().setBlocked(false);
863
1389
  };
864
- }, [activeLevelId, placementDimensions, previewNode, publishFloorplanPreview]);
1390
+ }, [activeLevelId, metricNotation, publishFloorplanPreview, unit]);
865
1391
  if (!activeLevelId || !placement)
866
1392
  return null;
867
1393
  const stretch = placement.stretch;
@@ -869,19 +1395,21 @@ const CabinetTool = () => {
869
1395
  .slice(0, segmentIndex)
870
1396
  .reduce((sum, previous) => sum + previous.stretch.modules.length, 0));
871
1397
  const activeStretchGhostOffset = draftSegments.reduce((sum, segment) => sum + segment.stretch.modules.length, 0);
872
- const placementLabel = stretch
873
- ? placement.valid
874
- ? `${draftSegments.length + 1} leg${draftSegments.length + 1 === 1 ? '' : 's'} · ${stretch.modules.length} module${stretch.modules.length === 1 ? '' : 's'} · Click to continue · Double-click/Esc to finish`
875
- : null
876
- : !placement.valid
877
- ? null
878
- : placement.snappedToWall
879
- ? placement.snapReason === 'cabinet-edge'
880
- ? 'Edge snap'
881
- : placement.snapReason === 'corner'
882
- ? 'Corner snap'
883
- : 'Wall snap'
884
- : null;
1398
+ const placementLabel = placement.insertionFailure
1399
+ ? 'No space in this run to insert this cabinet'
1400
+ : stretch
1401
+ ? placement.valid
1402
+ ? `${draftSegments.length + 1} leg${draftSegments.length + 1 === 1 ? '' : 's'} · ${stretch.modules.length} module${stretch.modules.length === 1 ? '' : 's'} · Click to continue · Double-click/Esc to finish`
1403
+ : null
1404
+ : !placement.valid
1405
+ ? null
1406
+ : placement.snappedToWall
1407
+ ? placement.snapReason === 'cabinet-edge'
1408
+ ? 'Edge snap'
1409
+ : placement.snapReason === 'corner'
1410
+ ? 'Corner snap'
1411
+ : 'Wall snap'
1412
+ : null;
885
1413
  const labelPosition = stretch
886
1414
  ? runLocalToPlan({ position: placement.position, rotation: placement.yaw }, [
887
1415
  stretch.centerLocalX,
@@ -902,23 +1430,19 @@ const CabinetTool = () => {
902
1430
  });
903
1431
  const placementRotationY = placement.snappedToWall || stretch ? placement.yaw : yaw;
904
1432
  const placementBoxDimensions = [
905
- stretch ? stretch.length : placementDimensions[0],
906
- placementDimensions[1],
907
- placementDimensions[2],
1433
+ stretch
1434
+ ? stretch.length + (previewNode.withCountertop ? previewNode.countertopOverhang * 2 : 0)
1435
+ : placementSnapFootprint.dimensions[0],
1436
+ placementSnapFootprint.dimensions[1],
1437
+ placementSnapFootprint.dimensions[2],
908
1438
  ];
909
- const placementBoxPlanPosition = stretch
910
- ? runLocalToPlan({ position: placement.position, rotation: placement.yaw }, [
911
- stretch.centerLocalX,
912
- 0,
913
- 0,
914
- ])
915
- : placement.position;
1439
+ const placementBoxPlanPosition = runLocalToPlan({ position: placement.position, rotation: placement.yaw }, [stretch?.centerLocalX ?? 0, 0, placementSnapFootprint.offset[1]]);
916
1440
  const placementBoxPosition = [
917
1441
  placementBoxPlanPosition[0],
918
1442
  visualPosition[1],
919
1443
  placementBoxPlanPosition[2],
920
1444
  ];
921
- return (_jsxs(LevelOffsetGroup, { children: [placement.guide && _jsx(WallSnapGuide, { blocked: !placement.valid, guide: placement.guide }), _jsx(PlacementBox, { dimensions: placementBoxDimensions, measurements: { unit, metricNotation }, position: placementBoxPosition, rotationY: placementRotationY, valid: placement.valid }), draftSegments.map((segment, segmentIndex) => (_jsx("group", { position: segment.anchor.position, rotation: [0, segment.anchor.yaw, 0], children: segment.stretch.modules.map((module, index) => (_jsx("group", { position: [module.x, 0, 0], scale: [module.width / previewNode.width, 1, 1], children: _jsx("primitive", { object: ghostForIndex(draftModuleOffsets[segmentIndex] + index) }) }, `${segmentIndex}-${index}`))) }, `draft-${segmentIndex}`))), _jsx("group", { ref: activeGhostRef, position: visualPosition, rotation: [0, placementRotationY, 0], children: stretch ? (stretch.modules.map((module, index) => (_jsx("group", { position: [module.x, 0, 0], scale: [module.width / previewNode.width, 1, 1], children: _jsx("primitive", { object: ghostForIndex(activeStretchGhostOffset + index) }) }, index)))) : (_jsx("primitive", { object: ghost })) }), placementLabel ? (_jsx(Html, { center: true, position: [
1445
+ return (_jsxs(LevelOffsetGroup, { children: [placement.guide && _jsx(WallSnapGuide, { blocked: !placement.valid, guide: placement.guide }), _jsx(PlacementBox, { activeDimensionId: stretch ? null : activeDimensionId, dimensions: placementBoxDimensions, dimensionInput: dimensionInput, measurements: { unit, metricNotation }, measurementValues: stretch ? undefined : [previewNode.width, previewNode.carcassHeight, previewNode.depth], onDimensionSelect: stretch ? undefined : (id) => usePlacementPreview.getState().selectDimension(id), position: placementBoxPosition, rotationY: placementRotationY, valid: placement.valid }), _jsx(PlacementDimensionGuides, {}), draftSegments.map((segment, segmentIndex) => (_jsx("group", { position: segment.anchor.position, rotation: [0, segment.anchor.yaw, 0], children: segment.stretch.modules.map((module, index) => (_jsx("group", { position: [module.x, 0, 0], scale: [module.width / previewNode.width, 1, 1], children: _jsx("primitive", { object: ghostForIndex(draftModuleOffsets[segmentIndex] + index) }) }, `${segmentIndex}-${index}`))) }, `draft-${segmentIndex}`))), _jsx("group", { ref: activeGhostRef, position: visualPosition, rotation: [0, placementRotationY, 0], children: placement.insertionPreview ? (_jsx("primitive", { object: insertionGhost })) : stretch ? (stretch.modules.map((module, index) => (_jsx("group", { position: [module.x, 0, 0], scale: [module.width / previewNode.width, 1, 1], children: _jsx("primitive", { object: ghostForIndex(activeStretchGhostOffset + index) }) }, index)))) : (_jsx("primitive", { object: ghost })) }), placement.insertionPreview ? (_jsx("group", { position: placement.insertionPreview.runPosition, rotation: [0, placement.insertionPreview.runYaw, 0], children: placement.insertionPreview.modules.map((module, index) => (_jsx("group", { position: module.position, scale: [module.width / previewNode.width, 1, 1], children: _jsx("primitive", { object: insertionGhostForIndex(index + 1) }) }, module.id))) })) : null, placementLabel ? (_jsx(Html, { center: true, position: [
922
1446
  labelPosition[0],
923
1447
  previewNode.plinthHeight + previewNode.carcassHeight + 0.35,
924
1448
  labelPosition[2],