@pascal-app/editor 0.8.0 → 0.9.2

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 (350) hide show
  1. package/package.json +15 -13
  2. package/src/components/editor/alignment-3d-guide-layer.tsx +168 -0
  3. package/src/components/editor/bake-exporter.tsx +47 -0
  4. package/src/components/editor/custom-camera-controls.tsx +795 -28
  5. package/src/components/editor/editor-layout-mobile.tsx +8 -3
  6. package/src/components/editor/editor-layout-v2.tsx +76 -51
  7. package/src/components/editor/export-manager.tsx +69 -32
  8. package/src/components/editor/fence-tangent-lines-3d.tsx +87 -0
  9. package/src/components/editor/first-person/build-collider-world.test.ts +182 -0
  10. package/src/components/editor/first-person/build-collider-world.ts +228 -83
  11. package/src/components/editor/first-person-controls.tsx +943 -27
  12. package/src/components/editor/floating-action-menu.tsx +676 -208
  13. package/src/components/editor/floating-building-action-menu.tsx +2 -2
  14. package/src/components/editor/floorplan-background-selection.test.ts +58 -0
  15. package/src/components/editor/floorplan-background-selection.ts +3 -2
  16. package/src/components/editor/floorplan-panel.tsx +6916 -12137
  17. package/src/components/editor/grid.tsx +197 -36
  18. package/src/components/editor/group-actions.ts +457 -0
  19. package/src/components/editor/group-floating-action-menu.tsx +130 -0
  20. package/src/components/editor/group-move-3d.ts +397 -0
  21. package/src/components/editor/group-rotate-handle.tsx +420 -0
  22. package/src/components/editor/group-selection-box-3d.tsx +173 -0
  23. package/src/components/editor/group-transform-shared.test.ts +396 -0
  24. package/src/components/editor/group-transform-shared.ts +489 -0
  25. package/src/components/editor/handles/handle-arrow.tsx +581 -0
  26. package/src/components/editor/handles/use-handle-drag.ts +246 -0
  27. package/src/components/editor/index.tsx +412 -162
  28. package/src/components/editor/measurement-pill.tsx +115 -0
  29. package/src/components/editor/node-action-menu.tsx +14 -1
  30. package/src/components/editor/node-arrow-handles.tsx +1646 -0
  31. package/src/components/editor/opening-guides-3d-layer.tsx +144 -0
  32. package/src/components/editor/quick-measurement-card.tsx +70 -0
  33. package/src/components/editor/quick-measurement-hud.tsx +28 -0
  34. package/src/components/editor/riser-diagram-panel.tsx +137 -0
  35. package/src/components/editor/selection-manager.tsx +1106 -483
  36. package/src/components/editor/site-edge-labels.tsx +45 -21
  37. package/src/components/editor/slab-hole-highlights.tsx +474 -0
  38. package/src/components/editor/snapshot-capture-overlay.tsx +369 -155
  39. package/src/components/editor/three-context-bridge.ts +22 -0
  40. package/src/components/editor/thumbnail-generator.tsx +140 -41
  41. package/src/components/editor/use-floorplan-background-placement.ts +190 -35
  42. package/src/components/editor/use-floorplan-hit-testing.ts +24 -0
  43. package/src/components/editor/use-floorplan-scene-data.ts +19 -7
  44. package/src/components/editor/use-mesh-settle-epoch.ts +26 -0
  45. package/src/components/editor/wall-measurement-label.tsx +14 -19
  46. package/src/components/editor/wall-move-side-handles.tsx +870 -0
  47. package/src/components/editor/wall-opening-highlights.tsx +181 -0
  48. package/src/components/editor/wall-snap-beacon-layer.tsx +304 -0
  49. package/src/components/editor-2d/floorplan-action-menu-layer.tsx +15 -6
  50. package/src/components/editor-2d/floorplan-alignment-guide-layer.tsx +142 -0
  51. package/src/components/editor-2d/floorplan-cursor-indicator-overlay.tsx +5 -3
  52. package/src/components/editor-2d/floorplan-group-action-menu.tsx +87 -0
  53. package/src/components/editor-2d/floorplan-group-move.tsx +701 -0
  54. package/src/components/editor-2d/floorplan-measurement-tool-layer.test.ts +113 -0
  55. package/src/components/editor-2d/floorplan-measurement-tool-layer.tsx +1656 -0
  56. package/src/components/editor-2d/floorplan-quick-measure-layer.tsx +212 -0
  57. package/src/components/editor-2d/floorplan-registry-action-menu.tsx +392 -0
  58. package/src/components/editor-2d/floorplan-registry-move-overlay.tsx +857 -0
  59. package/src/components/editor-2d/floorplan-render-context.tsx +62 -0
  60. package/src/components/editor-2d/floorplan-snap-beacon-layer.tsx +77 -0
  61. package/src/components/editor-2d/floorplan-wall-move-ghost-layer.tsx +47 -0
  62. package/src/components/editor-2d/renderers/floorplan-geometry-renderer.tsx +266 -0
  63. package/src/components/editor-2d/renderers/floorplan-label-angle.test.ts +15 -0
  64. package/src/components/editor-2d/renderers/floorplan-label-angle.ts +14 -0
  65. package/src/components/editor-2d/renderers/floorplan-measurements-layer.tsx +108 -66
  66. package/src/components/editor-2d/renderers/floorplan-placement-preview-layer.tsx +62 -0
  67. package/src/components/editor-2d/renderers/floorplan-registry-layer.test.ts +308 -0
  68. package/src/components/editor-2d/renderers/floorplan-registry-layer.tsx +3325 -0
  69. package/src/components/editor-2d/renderers/floorplan-stair-layer.tsx +24 -9
  70. package/src/components/editor-2d/renderers/floorplan-voronoi-layer.tsx +128 -0
  71. package/src/components/editor-2d/svg-paths.ts +10 -2
  72. package/src/components/systems/ceiling/ceiling-selection-affordance-system.tsx +439 -57
  73. package/src/components/systems/ceiling/ceiling-system.tsx +109 -12
  74. package/src/components/systems/roof/roof-edit-system.tsx +1851 -22
  75. package/src/components/systems/selection-affordance-manager.tsx +38 -0
  76. package/src/components/systems/stair/stair-edit-system.tsx +1 -1
  77. package/src/components/systems/zone/zone-label-editor-system.tsx +14 -1
  78. package/src/components/systems/zone/zone-system.tsx +42 -13
  79. package/src/components/tools/elevator/elevator-defaults.ts +8 -0
  80. package/src/components/tools/elevator/elevator-tool.tsx +375 -0
  81. package/src/components/tools/elevator/move-elevator-tool.tsx +263 -0
  82. package/src/components/tools/fence/fence-drafting.ts +141 -27
  83. package/src/components/tools/item/move-tool.tsx +45 -105
  84. package/src/components/tools/item/placement-math.test.ts +22 -0
  85. package/src/components/tools/item/placement-math.ts +59 -7
  86. package/src/components/tools/item/placement-strategies.ts +432 -16
  87. package/src/components/tools/item/placement-types.ts +22 -1
  88. package/src/components/tools/item/use-draft-node.ts +51 -2
  89. package/src/components/tools/item/use-placement-coordinator.tsx +1399 -256
  90. package/src/components/tools/registry/move-registry-node-tool.tsx +1064 -0
  91. package/src/components/tools/roof/roof-tool.tsx +350 -28
  92. package/src/components/tools/select/box-select-state.ts +88 -0
  93. package/src/components/tools/select/box-select-tool.tsx +442 -520
  94. package/src/components/tools/select/marquee-geometry.test.ts +161 -0
  95. package/src/components/tools/select/marquee-geometry.ts +155 -0
  96. package/src/components/tools/select/plane-box-select-tool.tsx +570 -0
  97. package/src/components/tools/select/screen-rectangle-selection.ts +84 -0
  98. package/src/components/tools/select/select-candidates.test.ts +109 -0
  99. package/src/components/tools/select/select-candidates.ts +85 -0
  100. package/src/components/tools/shared/affordance-dispatch.ts +30 -0
  101. package/src/components/tools/shared/cursor-sphere.tsx +62 -26
  102. package/src/components/tools/shared/drag-bounding-box.tsx +195 -0
  103. package/src/components/tools/shared/facing-indicator.tsx +87 -0
  104. package/src/components/tools/shared/facing-pose-indicator.tsx +54 -0
  105. package/src/components/tools/shared/floor-stack-preview.ts +25 -0
  106. package/src/components/tools/shared/fresh-placement-visibility.ts +61 -0
  107. package/src/components/tools/shared/placement-box-geometry.ts +123 -0
  108. package/src/components/tools/shared/placement-box.tsx +305 -0
  109. package/src/components/tools/shared/polygon-editor.tsx +866 -175
  110. package/src/components/tools/shared/segment-angle.ts +56 -0
  111. package/src/components/tools/site/site-boundary-editor.tsx +520 -16
  112. package/src/components/tools/site/site-flag-model.ts +18 -0
  113. package/src/components/tools/stair/stair-defaults.ts +2 -1
  114. package/src/components/tools/stair/stair-tool.tsx +342 -37
  115. package/src/components/tools/tool-manager.tsx +239 -62
  116. package/src/components/tools/wall/wall-drafting.test.ts +330 -0
  117. package/src/components/tools/wall/wall-drafting.ts +248 -171
  118. package/src/components/tools/wall/wall-snap-geometry.test.ts +123 -0
  119. package/src/components/tools/wall/wall-snap-geometry.ts +331 -0
  120. package/src/components/tools/zone/zone-boundary-editor.tsx +5 -1
  121. package/src/components/tools/zone/zone-tool.tsx +86 -82
  122. package/src/components/ui/action-menu/action-button.tsx +21 -1
  123. package/src/components/ui/action-menu/camera-actions.tsx +24 -17
  124. package/src/components/ui/action-menu/control-modes.tsx +40 -170
  125. package/src/components/ui/action-menu/furnish-tools.tsx +5 -5
  126. package/src/components/ui/action-menu/index.tsx +3 -117
  127. package/src/components/ui/action-menu/measurement-control.tsx +188 -0
  128. package/src/components/ui/action-menu/structure-tools.tsx +27 -93
  129. package/src/components/ui/action-menu/view-toggles.tsx +279 -90
  130. package/src/components/ui/command-palette/editor-commands.tsx +20 -15
  131. package/src/components/ui/command-palette/index.tsx +5 -3
  132. package/src/components/ui/controls/material-paint-panel.tsx +152 -0
  133. package/src/components/ui/controls/material-picker.tsx +87 -177
  134. package/src/components/ui/controls/material-properties-editor.tsx +108 -0
  135. package/src/components/ui/controls/metric-control.tsx +142 -46
  136. package/src/components/ui/controls/scene-material-list.tsx +247 -0
  137. package/src/components/ui/controls/slider-control.tsx +88 -38
  138. package/src/components/ui/floating-level-selector.tsx +47 -10
  139. package/src/components/ui/helpers/building-helper.tsx +10 -23
  140. package/src/components/ui/helpers/contextual-helper-panel.tsx +428 -0
  141. package/src/components/ui/helpers/helper-manager.tsx +235 -23
  142. package/src/components/ui/helpers/item-helper.tsx +28 -32
  143. package/src/components/ui/helpers/registered-tool-helper.tsx +59 -0
  144. package/src/components/ui/helpers/roof-helper.tsx +10 -12
  145. package/src/components/ui/icon-ref.tsx +47 -0
  146. package/src/components/ui/item-catalog/catalog-items.tsx +40 -1
  147. package/src/components/ui/item-catalog/item-catalog.tsx +16 -36
  148. package/src/components/ui/level-duplicate-dialog.tsx +2 -1
  149. package/src/components/ui/panels/node-display.ts +17 -16
  150. package/src/components/ui/panels/panel-manager.tsx +55 -58
  151. package/src/components/ui/panels/panel-wrapper.tsx +238 -12
  152. package/src/components/ui/panels/parametric-inspector.tsx +482 -0
  153. package/src/components/ui/panels/reference-panel.tsx +54 -19
  154. package/src/components/ui/primitives/dropdown-menu.tsx +12 -8
  155. package/src/components/ui/primitives/shortcut-token.tsx +39 -3
  156. package/src/components/ui/primitives/sidebar.tsx +1 -0
  157. package/src/components/ui/scene-loader.tsx +1 -3
  158. package/src/components/ui/sidebar/app-sidebar.tsx +5 -1
  159. package/src/components/ui/sidebar/icon-rail.tsx +50 -31
  160. package/src/components/ui/sidebar/panels/items-panel/function-tree-panel.tsx +263 -0
  161. package/src/components/ui/sidebar/panels/items-panel/index.tsx +82 -8
  162. package/src/components/ui/sidebar/panels/plugins-panel.tsx +218 -0
  163. package/src/components/ui/sidebar/panels/settings-panel/index.tsx +122 -41
  164. package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +66 -7
  165. package/src/components/ui/sidebar/panels/settings-panel/load-build-dialog.tsx +267 -0
  166. package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +3 -1
  167. package/src/components/ui/sidebar/panels/site-panel/ceiling-tree-node.tsx +9 -5
  168. package/src/components/ui/sidebar/panels/site-panel/chimney-tree-node.tsx +86 -0
  169. package/src/components/ui/sidebar/panels/site-panel/column-tree-node.tsx +1 -1
  170. package/src/components/ui/sidebar/panels/site-panel/door-tree-node.tsx +7 -2
  171. package/src/components/ui/sidebar/panels/site-panel/dormer-tree-node.tsx +92 -0
  172. package/src/components/ui/sidebar/panels/site-panel/elevator-tree-node.tsx +75 -0
  173. package/src/components/ui/sidebar/panels/site-panel/fence-tree-node.tsx +3 -3
  174. package/src/components/ui/sidebar/panels/site-panel/gutter-tree-node.tsx +86 -0
  175. package/src/components/ui/sidebar/panels/site-panel/index.tsx +42 -21
  176. package/src/components/ui/sidebar/panels/site-panel/item-tree-node.tsx +31 -17
  177. package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +2 -1
  178. package/src/components/ui/sidebar/panels/site-panel/registry-tree-node.tsx +140 -0
  179. package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +48 -8
  180. package/src/components/ui/sidebar/panels/site-panel/shelf-tree-node.tsx +132 -0
  181. package/src/components/ui/sidebar/panels/site-panel/slab-tree-node.tsx +9 -5
  182. package/src/components/ui/sidebar/panels/site-panel/solar-panel-tree-node.tsx +86 -0
  183. package/src/components/ui/sidebar/panels/site-panel/spawn-tree-node.tsx +7 -1
  184. package/src/components/ui/sidebar/panels/site-panel/stair-tree-node.tsx +2 -2
  185. package/src/components/ui/sidebar/panels/site-panel/tree-node.tsx +112 -39
  186. package/src/components/ui/sidebar/panels/site-panel/tree-structure.ts +36 -0
  187. package/src/components/ui/sidebar/panels/site-panel/wall-tree-node.tsx +1 -1
  188. package/src/components/ui/sidebar/panels/site-panel/window-tree-node.tsx +7 -2
  189. package/src/components/ui/sidebar/panels/site-panel/zone-tree-node.tsx +3 -3
  190. package/src/components/ui/sidebar/panels/zone-panel/index.tsx +51 -2
  191. package/src/components/ui/sidebar/tab-bar.tsx +75 -1
  192. package/src/components/ui/sidebar/use-plugin-panels.tsx +132 -0
  193. package/src/components/ui/snap-target-badge.test.tsx +40 -0
  194. package/src/components/ui/snap-target-badge.tsx +88 -0
  195. package/src/components/viewer-overlay.tsx +253 -61
  196. package/src/components/viewer-zone-system.tsx +7 -2
  197. package/src/hooks/use-auto-save.test.ts +14 -0
  198. package/src/hooks/use-auto-save.ts +64 -10
  199. package/src/hooks/use-ceiling-events.ts +176 -0
  200. package/src/hooks/use-drag-action.ts +127 -0
  201. package/src/hooks/use-keyboard.ts +493 -95
  202. package/src/hooks/use-selection.ts +64 -0
  203. package/src/index.tsx +451 -6
  204. package/src/lib/active-placement-surface.ts +35 -0
  205. package/src/lib/ceiling-plan-snap.ts +24 -0
  206. package/src/lib/constants.ts +6 -2
  207. package/src/lib/contextual-help.test.ts +112 -0
  208. package/src/lib/contextual-help.ts +144 -0
  209. package/src/lib/continuation.ts +64 -0
  210. package/src/lib/direct-manipulation.test.ts +192 -0
  211. package/src/lib/direct-manipulation.ts +109 -0
  212. package/src/lib/editor-api.ts +50 -0
  213. package/src/lib/elevator-support.ts +96 -0
  214. package/src/lib/floorplan/apply-alignment.test.ts +25 -0
  215. package/src/lib/floorplan/apply-alignment.ts +117 -0
  216. package/src/lib/floorplan/floorplan-export.tsx +364 -0
  217. package/src/lib/floorplan/geometry.ts +53 -0
  218. package/src/lib/floorplan/index.ts +10 -0
  219. package/src/lib/floorplan/items.ts +5 -2
  220. package/src/lib/floorplan/plan-coords.ts +21 -0
  221. package/src/lib/floorplan/selection-tool.ts +40 -0
  222. package/src/lib/floorplan/stairs.ts +12 -1
  223. package/src/lib/fresh-planar-placement.test.ts +339 -0
  224. package/src/lib/fresh-planar-placement.ts +130 -0
  225. package/src/lib/glb-export.test.ts +441 -0
  226. package/src/lib/glb-export.ts +874 -0
  227. package/src/lib/history.ts +11 -1
  228. package/src/lib/interaction/hot-set.test.ts +133 -0
  229. package/src/lib/interaction/hot-set.ts +67 -0
  230. package/src/lib/interaction/overlay-policy.test.ts +51 -0
  231. package/src/lib/interaction/overlay-policy.ts +59 -0
  232. package/src/lib/interaction/scope.ts +211 -0
  233. package/src/lib/level-duplication.ts +54 -42
  234. package/src/lib/level-selection.ts +2 -2
  235. package/src/lib/material-paint.ts +227 -48
  236. package/src/lib/measurement-kind.test.ts +30 -0
  237. package/src/lib/measurement-kind.ts +19 -0
  238. package/src/lib/measurement-label.test.ts +47 -0
  239. package/src/lib/measurement-label.ts +68 -0
  240. package/src/lib/measurement-parser.ts +116 -0
  241. package/src/lib/measurements.test.ts +183 -0
  242. package/src/lib/measurements.ts +199 -0
  243. package/src/lib/paint-scope.test.ts +454 -0
  244. package/src/lib/paint-scope.ts +461 -0
  245. package/src/lib/placement-drag-release.ts +23 -0
  246. package/src/lib/placement-metadata.ts +29 -0
  247. package/src/lib/planar-cursor-placement.test.ts +100 -0
  248. package/src/lib/planar-cursor-placement.ts +42 -0
  249. package/src/lib/plugin-panels.test.ts +19 -0
  250. package/src/lib/plugin-panels.ts +91 -0
  251. package/src/lib/quick-measurement.test.ts +77 -0
  252. package/src/lib/quick-measurement.ts +109 -0
  253. package/src/lib/roof-duplication.ts +7 -7
  254. package/src/lib/roof-hover-outline-proxy.ts +22 -0
  255. package/src/lib/roof-wall-hit.ts +164 -0
  256. package/src/lib/scene-clipboard.test.ts +196 -0
  257. package/src/lib/scene-clipboard.ts +332 -0
  258. package/src/lib/scene.ts +40 -8
  259. package/src/lib/selection-routing.test.ts +298 -0
  260. package/src/lib/selection-routing.ts +175 -0
  261. package/src/lib/sfx/index.ts +1 -0
  262. package/src/lib/sfx/movement-tick.test.ts +65 -0
  263. package/src/lib/sfx/movement-tick.ts +18 -0
  264. package/src/lib/sfx-bus.ts +69 -10
  265. package/src/lib/sfx-player.test.ts +124 -0
  266. package/src/lib/sfx-player.ts +148 -55
  267. package/src/lib/site-boundary.ts +1 -0
  268. package/src/lib/slab-plan-snap.test.ts +93 -0
  269. package/src/lib/slab-plan-snap.ts +108 -0
  270. package/src/lib/snapping-mode.test.ts +138 -0
  271. package/src/lib/snapping-mode.ts +179 -0
  272. package/src/lib/stair-duplication.ts +4 -4
  273. package/src/lib/stair-levels.test.ts +146 -0
  274. package/src/lib/stair-levels.ts +177 -0
  275. package/src/lib/surface-plan-snap.test.ts +71 -0
  276. package/src/lib/surface-plan-snap.ts +256 -0
  277. package/src/lib/use-linear-display.ts +40 -0
  278. package/src/lib/world-grid-snap.ts +231 -0
  279. package/src/lib/zone-content.ts +130 -0
  280. package/src/store/use-alignment-guides.ts +21 -0
  281. package/src/store/use-direct-manipulation-feedback.ts +20 -0
  282. package/src/store/use-editor.tsx +767 -114
  283. package/src/store/use-facing-pose.ts +44 -0
  284. package/src/store/use-fence-curve-draft.ts +21 -0
  285. package/src/store/use-floorplan-draft-preview.ts +101 -0
  286. package/src/store/use-floorplan-marquee.ts +50 -0
  287. package/src/store/use-interaction-scope.test.ts +186 -0
  288. package/src/store/use-interaction-scope.ts +132 -0
  289. package/src/store/use-measurement-draft.test.ts +530 -0
  290. package/src/store/use-measurement-draft.ts +543 -0
  291. package/src/store/use-opening-guides.ts +41 -0
  292. package/src/store/use-placement-preview.ts +39 -0
  293. package/src/store/use-quick-measurement-hud.test.ts +53 -0
  294. package/src/store/use-quick-measurement-hud.ts +77 -0
  295. package/src/store/use-segment-draft-chain.ts +28 -0
  296. package/src/store/use-stair-build-preview.ts +43 -0
  297. package/src/store/use-wall-move-ghosts.ts +36 -0
  298. package/src/store/use-wall-snap-indicator.ts +34 -0
  299. package/src/components/editor/first-person/bvh-ecctrl.tsx +0 -860
  300. package/src/components/editor/preset-thumbnail-generator.tsx +0 -125
  301. package/src/components/editor-2d/renderers/floorplan-roof-layer.tsx +0 -113
  302. package/src/components/tools/building/move-building-tool.tsx +0 -157
  303. package/src/components/tools/ceiling/ceiling-boundary-editor.tsx +0 -43
  304. package/src/components/tools/ceiling/ceiling-hole-editor.tsx +0 -49
  305. package/src/components/tools/ceiling/ceiling-tool.tsx +0 -465
  306. package/src/components/tools/ceiling/move-ceiling-tool.tsx +0 -264
  307. package/src/components/tools/column/column-tool.tsx +0 -97
  308. package/src/components/tools/column/move-column-tool.tsx +0 -105
  309. package/src/components/tools/door/door-math.ts +0 -110
  310. package/src/components/tools/door/door-tool.tsx +0 -324
  311. package/src/components/tools/door/move-door-tool.tsx +0 -412
  312. package/src/components/tools/fence/curve-fence-tool.tsx +0 -178
  313. package/src/components/tools/fence/fence-tool.tsx +0 -346
  314. package/src/components/tools/fence/move-fence-endpoint-tool.tsx +0 -441
  315. package/src/components/tools/fence/move-fence-tool.tsx +0 -302
  316. package/src/components/tools/item/item-tool.tsx +0 -26
  317. package/src/components/tools/roof/move-roof-tool.tsx +0 -364
  318. package/src/components/tools/slab/move-slab-tool.tsx +0 -182
  319. package/src/components/tools/slab/slab-boundary-editor.tsx +0 -43
  320. package/src/components/tools/slab/slab-hole-editor.tsx +0 -49
  321. package/src/components/tools/slab/slab-tool.tsx +0 -322
  322. package/src/components/tools/spawn/move-spawn-tool.tsx +0 -101
  323. package/src/components/tools/spawn/spawn-tool.tsx +0 -130
  324. package/src/components/tools/wall/curve-wall-tool.tsx +0 -178
  325. package/src/components/tools/wall/move-wall-endpoint-tool.tsx +0 -426
  326. package/src/components/tools/wall/move-wall-tool.tsx +0 -358
  327. package/src/components/tools/wall/wall-tool.tsx +0 -332
  328. package/src/components/tools/window/move-window-tool.tsx +0 -447
  329. package/src/components/tools/window/window-math.ts +0 -117
  330. package/src/components/tools/window/window-tool.tsx +0 -332
  331. package/src/components/ui/helpers/ceiling-helper.tsx +0 -20
  332. package/src/components/ui/helpers/slab-helper.tsx +0 -20
  333. package/src/components/ui/helpers/wall-helper.tsx +0 -20
  334. package/src/components/ui/panels/ceiling-panel.tsx +0 -249
  335. package/src/components/ui/panels/column-panel.tsx +0 -759
  336. package/src/components/ui/panels/door-panel.tsx +0 -1299
  337. package/src/components/ui/panels/fence-panel.tsx +0 -222
  338. package/src/components/ui/panels/item-panel.tsx +0 -306
  339. package/src/components/ui/panels/paint-panel.tsx +0 -163
  340. package/src/components/ui/panels/presets/presets-popover.tsx +0 -511
  341. package/src/components/ui/panels/roof-panel.tsx +0 -280
  342. package/src/components/ui/panels/roof-segment-panel.tsx +0 -311
  343. package/src/components/ui/panels/slab-panel.tsx +0 -250
  344. package/src/components/ui/panels/spawn-panel.tsx +0 -161
  345. package/src/components/ui/panels/stair-panel.tsx +0 -577
  346. package/src/components/ui/panels/stair-segment-panel.tsx +0 -325
  347. package/src/components/ui/panels/wall-panel.tsx +0 -273
  348. package/src/components/ui/panels/window-panel.tsx +0 -968
  349. package/src/contexts/presets-context.tsx +0 -121
  350. package/src/hooks/use-contextual-tools.ts +0 -61
@@ -0,0 +1,64 @@
1
+ 'use client'
2
+
3
+ import type { AnyNode, AnyNodeId } from '@pascal-app/core'
4
+ import { useScene } from '@pascal-app/core'
5
+ import { useViewer } from '@pascal-app/viewer'
6
+
7
+ /**
8
+ * Resolved current selection — selected node IDs plus a convenience
9
+ * lookup into the live scene store. Returned shape is intentionally
10
+ * narrow: hosts that need richer per-node state can compose this with
11
+ * `useScene()` themselves.
12
+ */
13
+ export type Selection = {
14
+ /** Multi-select node IDs (drives the rest of the editor's UI). */
15
+ selectedIds: AnyNodeId[]
16
+ /** Currently active building context — surfaces / palettes filter on this. */
17
+ buildingId: AnyNodeId | null
18
+ /** Currently active level context. */
19
+ levelId: AnyNodeId | null
20
+ /** Currently active zone context. */
21
+ zoneId: AnyNodeId | null
22
+ /**
23
+ * Resolved nodes for `selectedIds`. Missing entries (deleted nodes) are
24
+ * filtered out, so the array length may be ≤ `selectedIds.length`.
25
+ */
26
+ selectedNodes: AnyNode[]
27
+ /**
28
+ * The single selected node, or `null` when zero or multiple nodes are
29
+ * selected. Useful for "save as preset" / inspector gating where the
30
+ * UI only makes sense for a unique selection.
31
+ */
32
+ selectedNode: AnyNode | null
33
+ }
34
+
35
+ /**
36
+ * Subscribe to the current selection. Equivalent to reading from
37
+ * `useViewer().selection` plus a live `useScene()` lookup, packaged as
38
+ * a single hook so consumers building their own shells (community,
39
+ * standalone editor app, embedders) don't have to learn the two
40
+ * separate stores.
41
+ *
42
+ * Selection state intentionally lives in `useViewer` (it tracks the
43
+ * camera / visibility hierarchy: building → level → zone → nodes), not
44
+ * `useScene` — see `wiki/architecture/scene-registry.md`.
45
+ */
46
+ export function useSelection(): Selection {
47
+ const selection = useViewer((s) => s.selection)
48
+ const nodes = useScene((s) => s.nodes)
49
+
50
+ const selectedIds = selection.selectedIds as AnyNodeId[]
51
+ const selectedNodes = selectedIds
52
+ .map((id) => nodes[id])
53
+ .filter((n): n is AnyNode => n !== undefined)
54
+ const selectedNode = selectedNodes.length === 1 ? (selectedNodes[0] ?? null) : null
55
+
56
+ return {
57
+ selectedIds,
58
+ buildingId: (selection.buildingId ?? null) as AnyNodeId | null,
59
+ levelId: (selection.levelId ?? null) as AnyNodeId | null,
60
+ zoneId: (selection.zoneId ?? null) as AnyNodeId | null,
61
+ selectedNodes,
62
+ selectedNode,
63
+ }
64
+ }
package/src/index.tsx CHANGED
@@ -1,21 +1,220 @@
1
+ // Re-exports of the scene / viewer hooks so consumers composing their
2
+ // own shells on top of `@pascal-app/editor` (community-app, embedders)
3
+ // don't have to learn three separate package imports. The canonical
4
+ // definitions still live in `@pascal-app/core` / `@pascal-app/viewer`.
5
+ export { useScene } from '@pascal-app/core'
6
+ export { useViewer } from '@pascal-app/viewer'
1
7
  export type { EditorProps } from './components/editor'
2
8
  export { default as Editor } from './components/editor'
9
+ // Headless component aliases: the implementation files keep their
10
+ // internal names (`ParametricInspector`, `FloatingActionMenu`) because
11
+ // they're referenced throughout the editor's own internals; the public
12
+ // surface uses the shorter, shell-friendly names from the unified
13
+ // preset-system spec.
14
+ export { BakeExporter } from './components/editor/bake-exporter'
15
+ export { FloatingActionMenu as FloatingMenu } from './components/editor/floating-action-menu'
16
+ // Embed surface — the editor's real in-canvas affordances, so a host can mount
17
+ // authentic selection handles, interactive build tools, and the mover on top
18
+ // of a bare `<Viewer>` without the full `<Editor>` shell.
19
+ // - `NodeArrowHandles` renders the selected node's registry resize/rotate/move
20
+ // handles.
21
+ // - `MoveTool` runs the kind-owned mover once a translate handle arms
22
+ // `useEditor.movingNode`.
23
+ // - `ToolManager` mounts the active registry build tool (wall / door / window /
24
+ // …) for interactive placement when `useEditor` is in build mode with a
25
+ // tool, plus the snap/alignment guide layers. Mount it only while a tool is
26
+ // active to avoid its select-mode boundary editors.
27
+ // - `Grid` is the interactive drafting plane: it raycasts the pointer and
28
+ // emits the `grid:move` / `grid:click` events the build tools consume (the
29
+ // wall tool is driven entirely by them; door/window use them for free-follow
30
+ // alongside the viewer's `wall:*` mesh events). Without it the tools mount
31
+ // but their cursor never tracks the pointer. Mount it while a tool is active.
32
+ // All read `useViewer` selection + `useEditor` state, and cooperate with host
33
+ // camera controls via the `useViewer.inputDragging` / `useEditor.movingNode`
34
+ // flags. Tools place onto `useViewer.selection.levelId`, so the host must set a
35
+ // building + level selection first.
36
+ export { Grid } from './components/editor/grid'
37
+ export {
38
+ DimensionPill,
39
+ type DimensionPillPart,
40
+ formatMeasurement,
41
+ MeasurementPill,
42
+ } from './components/editor/measurement-pill'
43
+ // In-world arrow handle primitives (chevron geometry, invisible hit area,
44
+ // shared material, palette + scale constants). Re-exported so kind-owned
45
+ // 3D selection affordances in `@pascal-app/nodes` (duct side-move / height /
46
+ // extend arrows) reuse the same UI family as the wall / fence side handles.
47
+ export {
48
+ ARROW_COLOR,
49
+ ARROW_HOVER_COLOR,
50
+ ARROW_SCALE,
51
+ createArrowHandleGeometry,
52
+ createArrowHitAreaGeometry,
53
+ HandleArrow,
54
+ type HandleArrowInputShape,
55
+ type HandleArrowPlacement,
56
+ type HandleArrowProps,
57
+ InvisibleHandleHitArea,
58
+ NO_RAYCAST,
59
+ NodeArrowHandles,
60
+ swallowNextClick,
61
+ useArrowMaterial,
62
+ useInvisibleHitAreaMaterial,
63
+ } from './components/editor/node-arrow-handles'
64
+ export { QuickMeasurementCard } from './components/editor/quick-measurement-card'
3
65
  export {
4
66
  type SnapshotCameraData,
5
67
  ThumbnailGenerator,
6
68
  } from './components/editor/thumbnail-generator'
7
- export { CameraActions as ViewerToolbarRight } from './components/ui/action-menu/camera-actions'
8
- export { ViewToggles as ViewerToolbarLeft } from './components/ui/action-menu/view-toggles'
69
+ // SVG path builders for arc / annular-sector / arrow-head shapes —
70
+ // inlined into `kind: 'path'` / `kind: 'polygon'` primitives by curved
71
+ // stair rendering in `nodes/src/stair/floorplan.ts`.
72
+ export {
73
+ buildSvgAnnularSectorPath,
74
+ buildSvgArcPath,
75
+ buildSvgArrowHeadPoints,
76
+ getArcPlanPoint,
77
+ } from './components/editor-2d/svg-paths'
78
+ // Phase 5 Stage D transitional exports — pure drafting / angle helpers
79
+ // consumed by kind-owned drag actions in @pascal-app/nodes. Stage F
80
+ // cleanup moves these into @pascal-app/nodes (fence/drafting.ts +
81
+ // shared/segment-angle.ts) once every Stage D port is in.
82
+ export {
83
+ createFenceOnCurrentLevel,
84
+ createSplineFenceOnCurrentLevel,
85
+ type FencePlanPoint,
86
+ snapFenceDraftPoint,
87
+ } from './components/tools/fence/fence-drafting'
88
+ export { MoveTool } from './components/tools/item/move-tool'
89
+ // Placement-math helpers — shared by kind-owned placement tools in
90
+ // `@pascal-app/nodes` (wall curve sagitta snap, door / window placement,
91
+ // item drop) so kinds don't reach into editor internals.
92
+ export {
93
+ calculateCursorRotation,
94
+ calculateItemRotation,
95
+ getSideFromNormal,
96
+ isValidWallSideFace,
97
+ snapToGrid,
98
+ snapToHalf,
99
+ snapUpToGridStep,
100
+ stripTransient,
101
+ } from './components/tools/item/placement-math'
102
+ export type { PlacementState } from './components/tools/item/placement-types'
103
+ // Item placement / move primitives. Re-exported here so the registry-driven
104
+ // item move-tool in `@pascal-app/nodes` can compose them — same hooks the
105
+ // legacy `MoveItemContent` + `ItemTool` use. Once item placement is fully
106
+ // owned by `nodes`, these can be inlined there and dropped from editor.
107
+ export { type DraftNodeHandle, useDraftNode } from './components/tools/item/use-draft-node'
108
+ export {
109
+ type PlacementCoordinatorConfig,
110
+ usePlacementCoordinator,
111
+ } from './components/tools/item/use-placement-coordinator'
112
+ export { CursorSphere } from './components/tools/shared/cursor-sphere'
113
+ export { DragBoundingBox } from './components/tools/shared/drag-bounding-box'
114
+ export { getFloorStackPreviewPosition } from './components/tools/shared/floor-stack-preview'
115
+ export { useFreshPlacementVisibility } from './components/tools/shared/fresh-placement-visibility'
116
+ export { PlacementBox } from './components/tools/shared/placement-box'
117
+ // Phase 5 Stage D — PolygonEditor for slab/ceiling boundary + hole editors.
118
+ export {
119
+ PolygonEditor,
120
+ type PolygonEditorPlanPointSnapContext,
121
+ type PolygonEditorProps,
122
+ } from './components/tools/shared/polygon-editor'
123
+ export {
124
+ formatAngleRadians,
125
+ getAngleArcToSegmentReference,
126
+ getAngleToSegmentReference,
127
+ getSegmentAngleReferenceAtPoint,
128
+ type SegmentAngleReference,
129
+ } from './components/tools/shared/segment-angle'
130
+ // Stair placement defaults — used by the kind-owned stair / stair-segment
131
+ // panels. Re-exported from `components/tools/stair/stair-defaults.ts`.
132
+ export {
133
+ DEFAULT_CURVED_STAIR_INNER_RADIUS,
134
+ DEFAULT_CURVED_STAIR_SWEEP_ANGLE,
135
+ DEFAULT_SPIRAL_SHOW_CENTER_COLUMN,
136
+ DEFAULT_SPIRAL_SHOW_STEP_SUPPORTS,
137
+ DEFAULT_SPIRAL_STAIR_SWEEP_ANGLE,
138
+ DEFAULT_SPIRAL_TOP_LANDING_DEPTH,
139
+ DEFAULT_SPIRAL_TOP_LANDING_MODE,
140
+ DEFAULT_STAIR_ATTACHMENT_SIDE,
141
+ DEFAULT_STAIR_FILL_TO_FLOOR,
142
+ DEFAULT_STAIR_HEIGHT,
143
+ DEFAULT_STAIR_LENGTH,
144
+ DEFAULT_STAIR_RAILING_HEIGHT,
145
+ DEFAULT_STAIR_RAILING_MODE,
146
+ DEFAULT_STAIR_STEP_COUNT,
147
+ DEFAULT_STAIR_THICKNESS,
148
+ DEFAULT_STAIR_TYPE,
149
+ DEFAULT_STAIR_WIDTH,
150
+ } from './components/tools/stair/stair-defaults'
151
+ export { ToolManager } from './components/tools/tool-manager'
152
+ export {
153
+ chainEndJoinsExistingWall,
154
+ createWallOnCurrentLevel,
155
+ getSegmentGridStep,
156
+ isSegmentLongEnough,
157
+ resolveEndpointWallSplit,
158
+ snapPointToGrid,
159
+ snapScalarToGrid,
160
+ snapWallDraftPoint,
161
+ snapWallDraftPointDetailed,
162
+ WALL_CONNECT_SNAP_RADIUS,
163
+ WALL_GRID_STEP,
164
+ WALL_JOIN_SNAP_RADIUS,
165
+ type WallDraftSnapKind,
166
+ type WallDraftSnapResult,
167
+ type WallPlanPoint,
168
+ type WallSnapRadii,
169
+ } from './components/tools/wall/wall-drafting'
170
+ // `ToolbarLeft` / `ToolbarRight` are the headless-spec aliases for the
171
+ // existing `ViewerToolbarLeft` / `ViewerToolbarRight` exports — the
172
+ // underlying components are the same; the alias just matches the names
173
+ // used in `pascalorg/private-editor:plans/community-preset-system.md`
174
+ // so consumer code stays close to the spec vocabulary.
175
+ export {
176
+ CameraActions as ToolbarRight,
177
+ CameraActions as ViewerToolbarRight,
178
+ } from './components/ui/action-menu/camera-actions'
179
+ export {
180
+ ViewToggles as ToolbarLeft,
181
+ ViewToggles as ViewerToolbarLeft,
182
+ } from './components/ui/action-menu/view-toggles'
9
183
  export { useCommandPalette } from './components/ui/command-palette'
184
+ export { ActionButton, ActionGroup } from './components/ui/controls/action-button'
185
+ export { MaterialPaintPanel } from './components/ui/controls/material-paint-panel'
186
+ export { MaterialPicker } from './components/ui/controls/material-picker'
187
+ export { MetricControl } from './components/ui/controls/metric-control'
188
+ export { PanelSection } from './components/ui/controls/panel-section'
189
+ export { SegmentedControl } from './components/ui/controls/segmented-control'
10
190
  export { SliderControl } from './components/ui/controls/slider-control'
191
+ export { ToggleControl } from './components/ui/controls/toggle-control'
11
192
  export { FloatingLevelSelector } from './components/ui/floating-level-selector'
12
193
  export { CATALOG_ITEMS } from './components/ui/item-catalog/catalog-items'
194
+ // Item collections UI — used by the kind-owned ItemPanel in nodes/.
195
+ export { CollectionsPopover } from './components/ui/panels/collections/collections-popover'
196
+ // Phase 5 Stage E — kinds with bespoke editors (slab holes list,
197
+ // ceiling height presets, etc.) use `parametrics.customPanel` to mount
198
+ // a kind-owned panel and need PanelWrapper for the chrome.
199
+ export { PanelWrapper } from './components/ui/panels/panel-wrapper'
200
+ export { ParametricInspector as Inspector } from './components/ui/panels/parametric-inspector'
13
201
  export { PALETTE_COLORS } from './components/ui/primitives/color-dot'
202
+ export {
203
+ DropdownMenu,
204
+ DropdownMenuContent,
205
+ DropdownMenuItem,
206
+ DropdownMenuSeparator,
207
+ DropdownMenuSub,
208
+ DropdownMenuSubContent,
209
+ DropdownMenuSubTrigger,
210
+ DropdownMenuTrigger,
211
+ } from './components/ui/primitives/dropdown-menu'
14
212
  export { useSidebarStore } from './components/ui/primitives/sidebar'
15
213
  export { Slider } from './components/ui/primitives/slider'
16
214
  export { SceneLoader } from './components/ui/scene-loader'
17
215
  export type { ExtraPanel } from './components/ui/sidebar/icon-rail'
18
216
  export { ItemsPanel } from './components/ui/sidebar/panels/items-panel'
217
+ export type { FunctionTreeNode } from './components/ui/sidebar/panels/items-panel/function-tree-panel'
19
218
  export {
20
219
  type ProjectVisibility,
21
220
  SettingsPanel,
@@ -23,19 +222,265 @@ export {
23
222
  } from './components/ui/sidebar/panels/settings-panel'
24
223
  export type { SitePanelProps } from './components/ui/sidebar/panels/site-panel'
25
224
  export type { SidebarTab } from './components/ui/sidebar/tab-bar'
26
- export type { PresetsAdapter, PresetsTab } from './contexts/presets-context'
27
- export { PresetsProvider } from './contexts/presets-context'
225
+ export {
226
+ resolveAssetSnapTarget,
227
+ resolveNodeSnapTarget,
228
+ type SnapTarget,
229
+ SnapTargetBadge,
230
+ SnapTargetIcon,
231
+ } from './components/ui/snap-target-badge'
28
232
  export type { SaveStatus } from './hooks/use-auto-save'
233
+ // useDragAction is the React-side glue for the registry's DragAction
234
+ // primitive. Public so registry-driven kinds (Phase 5+ Stage D ports)
235
+ // can express their affordances declaratively in their own folder.
236
+ export { type UseDragActionArgs, useDragAction } from './hooks/use-drag-action'
237
+ // Phase 5 Stage D — extras for kind-owned placement tools (FenceTool etc.).
238
+ export { markToolCancelConsumed } from './hooks/use-keyboard'
239
+ export { type Selection, useSelection } from './hooks/use-selection'
240
+ export {
241
+ clearPlacementSurface,
242
+ getPlacementSurface,
243
+ type PlacementSurface,
244
+ publishPlacementSurface,
245
+ } from './lib/active-placement-surface'
246
+ export {
247
+ CEILING_ALIGNMENT_THRESHOLD_M,
248
+ type CeilingPlanSnapInput,
249
+ type CeilingPlanSnapResult,
250
+ clearCeilingSnapFeedback,
251
+ resolveCeilingPlanPointSnap,
252
+ } from './lib/ceiling-plan-snap'
253
+ export { EDITOR_LAYER } from './lib/constants'
254
+ // Helper libs used by the kind-owned roof / stair / elevator panels.
255
+ export {
256
+ CONTINUATION_PROFILES,
257
+ type ContinuationContext,
258
+ type ContinuationMode,
259
+ continuationContextOf,
260
+ nextContinuation,
261
+ } from './lib/continuation'
262
+ export {
263
+ resolveCurrentBuildingId,
264
+ resolveElevatorNodeSupportY,
265
+ resolveElevatorSupportLevelId,
266
+ resolveElevatorSupportY,
267
+ } from './lib/elevator-support'
268
+ // Floor-plan stair helpers — the cumulative-transform walk
269
+ // (`computeFloorplanStairSegmentTransforms`) and the rich segment-entry
270
+ // builder (`buildFloorplanStairEntry`) used by the kind-owned stair
271
+ // floor-plan emitter in `@pascal-app/nodes/src/stair/floorplan.ts`.
272
+ // Each flight's transform depends on every prior sibling's length /
273
+ // height / `attachmentSide`, so individual stair-segments can't compute
274
+ // their own polygon in isolation — the stair (parent) owns the
275
+ // computation and emits the whole stack as one registry entry.
276
+ export {
277
+ alignFloorplanDraftPoint,
278
+ applyFloorplanAlignment,
279
+ buildFloorplanStairEntry,
280
+ FLOORPLAN_ALIGNMENT_THRESHOLD_M,
281
+ FLOORPLAN_DRAFT_ALIGN_ID,
282
+ type FloorplanAlignmentResult,
283
+ type FloorplanStairArrowEntry,
284
+ type FloorplanStairEntry,
285
+ type FloorplanStairSegmentEntry,
286
+ getFloorplanWallThickness,
287
+ } from './lib/floorplan'
288
+ export { commitFreshPlacementSubtree } from './lib/fresh-planar-placement'
289
+ export { exportSceneToGlb } from './lib/glb-export'
290
+ export {
291
+ boundaryReshapeScope,
292
+ curveReshapeScope,
293
+ endpointReshapeScope,
294
+ holeEditScope,
295
+ movingNodeOf,
296
+ } from './lib/interaction/scope'
297
+ export {
298
+ buildResetSurfaceMaterialUpdates,
299
+ buildRoofSurfaceMaterialPatch,
300
+ buildSingleSurfaceMaterialPatch,
301
+ buildStairSurfaceMaterialPatch,
302
+ getActivePaintMaterialLabel,
303
+ hasActivePaintMaterial,
304
+ } from './lib/material-paint'
305
+ export {
306
+ CREATABLE_MEASUREMENT_KINDS,
307
+ type CreatableMeasurementKind,
308
+ DEFAULT_CREATABLE_MEASUREMENT_KIND,
309
+ isCreatableMeasurementKind,
310
+ normalizeCreatableMeasurementKind,
311
+ } from './lib/measurement-kind'
312
+ export {
313
+ measurementPolygonLabelAnchor,
314
+ triangulateMeasurementPolygon,
315
+ } from './lib/measurement-label'
316
+ export {
317
+ buildMeasurementAngleArcPoints,
318
+ cubicMetersToVolumeUnit,
319
+ formatAreaLabel,
320
+ formatLinearMeasurement,
321
+ formatVolumeLabel,
322
+ getAreaUnitLabel,
323
+ getLinearUnitLabel,
324
+ getVolumeUnitLabel,
325
+ type LinearUnit,
326
+ linearControlValueToMeters,
327
+ linearUnitToMeters,
328
+ MEASUREMENT_ACTIVE_COLOR,
329
+ MEASUREMENT_DANGLING_COLOR,
330
+ MEASUREMENT_FLOORPLAN_COLOR,
331
+ MEASUREMENT_PERSISTENT_COLOR,
332
+ measurementFloorplanPresentationColor,
333
+ measurementPresentationColor,
334
+ metersToLinearUnit,
335
+ squareMetersToAreaUnit,
336
+ } from './lib/measurements'
337
+ export { consumePlacementDragRelease } from './lib/placement-drag-release'
338
+ export {
339
+ addFreshPlacementMetadata,
340
+ getPlacementMetadataRecord,
341
+ isFreshPlacementMetadata,
342
+ stripPlacementMetadataFlags,
343
+ } from './lib/placement-metadata'
344
+ export {
345
+ type PlanarCursorPlacementMode,
346
+ type PlanarPoint,
347
+ resolvePlanarCursorPosition,
348
+ } from './lib/planar-cursor-placement'
349
+ export {
350
+ type EditorHostPanel,
351
+ type EditorHostPanelWorkspace,
352
+ editorHostPanelRegistry,
353
+ registerEditorHostPanel,
354
+ } from './lib/plugin-panels'
355
+ export {
356
+ createQuickMeasurementPointerScheduler,
357
+ quickMeasurementContext,
358
+ resolveQuickMeasurementReport,
359
+ } from './lib/quick-measurement'
360
+ export { clearRoofDuplicateMetadata, duplicateRoofSubtree } from './lib/roof-duplication'
361
+ // Roof wall-face hit resolution + overlap guard — shared by the
362
+ // kind-owned door / window tools in `@pascal-app/nodes` and the item
363
+ // placement coordinator's roof-wall strategy.
364
+ export { hasRoofFaceChildOverlap, type RoofWallHit, resolveRoofWallHit } from './lib/roof-wall-hit'
29
365
  export type { SceneGraph } from './lib/scene'
30
366
  export { applySceneGraphToEditor } from './lib/scene'
367
+ export { movementSfxStepKey } from './lib/sfx/movement-tick'
31
368
  export { triggerSFX } from './lib/sfx-bus'
369
+ export {
370
+ clearSlabSnapFeedback,
371
+ resolveSlabEdgeBandSnap,
372
+ resolveSlabPlanPointSnap,
373
+ SLAB_ALIGNMENT_THRESHOLD_M,
374
+ type SlabEdgeBandSnapInput,
375
+ type SlabEdgeBandSnapResult,
376
+ type SlabPlanSnapInput,
377
+ type SlabPlanSnapResult,
378
+ } from './lib/slab-plan-snap'
379
+ export { duplicateStairSubtree } from './lib/stair-duplication'
380
+ export {
381
+ getBuildingLevelsForLevel,
382
+ getStairLevelOptions,
383
+ resolveStairDestinationLevel,
384
+ resolveStairFromLevelId,
385
+ resolveStairPlacementLevelId,
386
+ resolveStairToLevelId,
387
+ } from './lib/stair-levels'
388
+ export {
389
+ clearSurfacePlanSnapFeedback,
390
+ resolveSurfacePlanPointSnap,
391
+ SURFACE_ALIGNMENT_THRESHOLD_M,
392
+ type SurfacePlanSnapInput,
393
+ type SurfacePlanSnapResult,
394
+ } from './lib/surface-plan-snap'
395
+ // `cn` (twMerge + clsx) — used by kind-owned panels in `@pascal-app/
396
+ // nodes` so they don't need their own copy / their own tailwind-merge
397
+ // dependency.
398
+ export { cn } from './lib/utils'
399
+ export {
400
+ getActiveBuildingPose,
401
+ projectAlignmentGuidesWorldToActiveBuildingLocal,
402
+ resolveAlignmentForActiveBuilding,
403
+ resolveAlignmentForFloorplanView,
404
+ snapBuildingLocalToWorldGrid,
405
+ snapWorldXZForActiveBuilding,
406
+ } from './lib/world-grid-snap'
407
+ export { default as useAlignmentGuides } from './store/use-alignment-guides'
32
408
  export { default as useAudio } from './store/use-audio'
33
409
  export { type CommandAction, useCommandRegistry } from './store/use-command-registry'
34
- export type { FloorplanSelectionTool, SplitOrientation, ViewMode } from './store/use-editor'
35
- export { default as useEditor } from './store/use-editor'
410
+ export type {
411
+ CaptureMode,
412
+ FloorplanSelectionTool,
413
+ SnapshotCropMode,
414
+ SnapshotStandardAspect,
415
+ SplitOrientation,
416
+ Tool,
417
+ ToolDefaults,
418
+ ViewMode,
419
+ WorkspaceMode,
420
+ } from './store/use-editor'
421
+ export {
422
+ default as useEditor,
423
+ getActiveContinuationContext,
424
+ getContinuation,
425
+ isAlignmentGuideActive,
426
+ isAngleSnapActive,
427
+ isGridSnapActive,
428
+ isMagneticSnapActive,
429
+ } from './store/use-editor'
430
+ export { default as useFacingPose, type FacingPose } from './store/use-facing-pose'
431
+ export { default as useFenceCurveDraft } from './store/use-fence-curve-draft'
432
+ export {
433
+ default as useInteractionScope,
434
+ getEditingHole,
435
+ getIsCurveReshape,
436
+ getMovingNode,
437
+ useActiveHandleDrag,
438
+ useEditingHole,
439
+ useEndpointReshape,
440
+ useIsCurveReshape,
441
+ useMovingNode,
442
+ useReshapingNode,
443
+ } from './store/use-interaction-scope'
444
+ export {
445
+ commitMeasurementDraft,
446
+ finishMeasurementDraft,
447
+ handleMeasurementDraftEscape,
448
+ type MeasurementAxis,
449
+ type MeasurementAxisGuide,
450
+ type MeasurementDraftOwner,
451
+ type MeasurementDraftPayload,
452
+ type MeasurementDraftStage,
453
+ type MeasurementKind,
454
+ type MeasurementPoint,
455
+ type MeasurementSurfacePoint,
456
+ measurementPolygonMidpoints,
457
+ useMeasurementDraft,
458
+ } from './store/use-measurement-draft'
459
+ export {
460
+ default as useOpeningGuides,
461
+ type OpeningGuide3D,
462
+ type OpeningGuideVec3,
463
+ } from './store/use-opening-guides'
36
464
  export {
37
465
  type PaletteView,
38
466
  type PaletteViewProps,
39
467
  usePaletteViewRegistry,
40
468
  } from './store/use-palette-view-registry'
469
+ export { default as usePlacementPreview } from './store/use-placement-preview'
470
+ export {
471
+ activateQuickMeasurementHudSource,
472
+ clearQuickMeasurementHudSource,
473
+ publishQuickMeasurementHudSource,
474
+ type QuickMeasurementHudEntry,
475
+ type QuickMeasurementHudSource,
476
+ selectQuickMeasurementHudEntry,
477
+ useQuickMeasurementHud,
478
+ } from './store/use-quick-measurement-hud'
479
+ export { default as useSegmentDraftChain } from './store/use-segment-draft-chain'
41
480
  export { useUploadStore } from './store/use-upload'
481
+ export { useWallMoveGhosts, type WallMoveGhostBridge } from './store/use-wall-move-ghosts'
482
+ export {
483
+ default as useWallSnapIndicator,
484
+ type WallSnapKind,
485
+ type WallSnapPoint,
486
+ } from './store/use-wall-snap-indicator'
@@ -0,0 +1,35 @@
1
+ import { Vector3 } from 'three'
2
+
3
+ // The surface the active placement/move ghost is currently snapped to: a contact
4
+ // point (world space) and the surface's outward unit normal. Published each frame
5
+ // by the placement tools (the item coordinator + the drawn-kind tools) and read
6
+ // by the grid so its snap patch sits at the ghost's height AND orients to the
7
+ // surface — horizontal on a floor / shelf top, vertical in a wall plane.
8
+ //
9
+ // A plain module singleton (not a store): both writer and reader run inside
10
+ // `useFrame`, so reactivity would only add overhead. The vectors are reused, so
11
+ // readers must consume them within the same frame.
12
+ export type PlacementSurface = {
13
+ point: Vector3
14
+ normal: Vector3
15
+ }
16
+
17
+ const surface: PlacementSurface = {
18
+ point: new Vector3(),
19
+ normal: new Vector3(0, 1, 0),
20
+ }
21
+ let active = false
22
+
23
+ export function publishPlacementSurface(point: Vector3, normal: Vector3): void {
24
+ surface.point.copy(point)
25
+ surface.normal.copy(normal)
26
+ active = true
27
+ }
28
+
29
+ export function clearPlacementSurface(): void {
30
+ active = false
31
+ }
32
+
33
+ export function getPlacementSurface(): PlacementSurface | null {
34
+ return active ? surface : null
35
+ }
@@ -0,0 +1,24 @@
1
+ import {
2
+ clearSurfacePlanSnapFeedback,
3
+ resolveSurfacePlanPointSnap,
4
+ SURFACE_ALIGNMENT_THRESHOLD_M,
5
+ type SurfacePlanSnapInput,
6
+ type SurfacePlanSnapResult,
7
+ } from './surface-plan-snap'
8
+
9
+ const CEILING_SNAP_MOVING_ID = '__ceiling_snap__'
10
+
11
+ export const CEILING_ALIGNMENT_THRESHOLD_M = SURFACE_ALIGNMENT_THRESHOLD_M
12
+ export type CeilingPlanSnapInput = SurfacePlanSnapInput
13
+ export type CeilingPlanSnapResult = SurfacePlanSnapResult
14
+
15
+ export function clearCeilingSnapFeedback() {
16
+ clearSurfacePlanSnapFeedback()
17
+ }
18
+
19
+ export function resolveCeilingPlanPointSnap(input: CeilingPlanSnapInput): CeilingPlanSnapResult {
20
+ return resolveSurfacePlanPointSnap({
21
+ ...input,
22
+ movingId: input.movingId ?? CEILING_SNAP_MOVING_ID,
23
+ })
24
+ }
@@ -1,3 +1,7 @@
1
+ import { OVERLAY_LAYER } from '@pascal-app/viewer'
2
+
1
3
  /** Three.js layer used for editor-only objects (helpers, grid, polygon editors).
2
- * The thumbnail camera renders only layer 0, so these are excluded from thumbnails. */
3
- export const EDITOR_LAYER = 1
4
+ * The thumbnail camera renders only layer 0, so these are excluded from thumbnails.
5
+ * Aliased to viewer's `OVERLAY_LAYER` so the post-processing overlay pass and the
6
+ * editor's overlay meshes stay on the same layer. */
7
+ export const EDITOR_LAYER = OVERLAY_LAYER