@pascal-app/editor 1.0.7 → 1.1.1

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 (336) hide show
  1. package/package.json +9 -15
  2. package/src/components/editor/action-menu-button.tsx +1 -1
  3. package/src/components/editor/alignment-3d-guide-layer.tsx +1 -1
  4. package/src/components/editor/custom-camera-controls.tsx +101 -45
  5. package/src/components/editor/duplicate-node.ts +2 -1
  6. package/src/components/editor/editor-layout-v2.tsx +1 -1
  7. package/src/components/editor/elevation-3d-guide-layer.tsx +1 -1
  8. package/src/components/editor/first-person-controls.tsx +20 -1983
  9. package/src/components/editor/fit-scene-framing.test.ts +318 -0
  10. package/src/components/editor/fit-scene-framing.ts +142 -0
  11. package/src/components/editor/floating-action-menu.tsx +5 -3
  12. package/src/components/editor/floating-building-action-menu.tsx +1 -1
  13. package/src/components/editor/floor-openings-overlay.tsx +1 -1
  14. package/src/components/editor/floor-region-controls.tsx +8 -4
  15. package/src/components/editor/floorplan-navigation-presentation.test.ts +0 -40
  16. package/src/components/editor/floorplan-navigation-presentation.ts +0 -66
  17. package/src/components/editor/floorplan-panel.tsx +199 -30
  18. package/src/components/editor/floorplan-wall-typing-keys.test.tsx +152 -0
  19. package/src/components/editor/floorplan-wall-typing-keys.ts +79 -0
  20. package/src/components/editor/follow-pascal.test.tsx +1 -2
  21. package/src/components/editor/follow-pascal.tsx +1 -1
  22. package/src/components/editor/footprint-height-handle.tsx +2 -2
  23. package/src/components/editor/group-actions.ts +1 -2
  24. package/src/components/editor/group-floating-action-menu.tsx +1 -1
  25. package/src/components/editor/group-move-3d.ts +1 -2
  26. package/src/components/editor/group-rotate-handle.tsx +1 -2
  27. package/src/components/editor/group-transform-shared.ts +3 -1
  28. package/src/components/editor/handles/use-handle-drag.ts +1 -2
  29. package/src/components/editor/index.tsx +43 -13
  30. package/src/components/editor/inspector-extension-actions.tsx +1 -1
  31. package/src/components/editor/measurement-pill.tsx +1 -1
  32. package/src/components/editor/node-arrow-handles.tsx +2 -2
  33. package/src/components/editor/open-wall-ends-3d-layer.tsx +2 -3
  34. package/src/components/editor/open-wall-ends-hint.tsx +1 -1
  35. package/src/components/editor/opening-guides-3d-layer.tsx +1 -1
  36. package/src/components/editor/quick-measurement-card.tsx +1 -1
  37. package/src/components/editor/room-controls.tsx +10 -6
  38. package/src/components/editor/room-handles-2d.tsx +3 -3
  39. package/src/components/editor/room-handles.tsx +4 -5
  40. package/src/components/editor/room-highlight.tsx +6 -105
  41. package/src/components/editor/room-labels.test.ts +8 -822
  42. package/src/components/editor/room-labels.tsx +41 -1670
  43. package/src/components/editor/room-webgpu-materials.test.ts +1 -1
  44. package/src/components/editor/selection-manager.tsx +5 -3
  45. package/src/components/editor/site-edge-labels.tsx +7 -3
  46. package/src/components/editor/snapshot-capture-overlay.tsx +2 -5
  47. package/src/components/editor/use-floorplan-background-placement.ts +2 -1
  48. package/src/components/editor/views/plugins-view.tsx +1 -1
  49. package/src/components/editor/views/view-bar.tsx +9 -9
  50. package/src/components/editor/wall-measurement-label.tsx +31 -15
  51. package/src/components/editor/wall-move-side-handles.tsx +11 -7
  52. package/src/components/editor/wall-pull-grip.tsx +2 -2
  53. package/src/components/editor/wall-region-handles.tsx +2 -2
  54. package/src/components/editor/wall-snap-beacon-layer.tsx +53 -32
  55. package/src/components/editor-2d/floorplan-group-move.tsx +3 -4
  56. package/src/components/editor-2d/floorplan-measurement-tool-layer.tsx +13 -13
  57. package/src/components/editor-2d/floorplan-open-wall-ends-layer.tsx +2 -3
  58. package/src/components/editor-2d/floorplan-registry-action-menu.tsx +2 -1
  59. package/src/components/editor-2d/floorplan-registry-move-overlay.tsx +23 -6
  60. package/src/components/editor-2d/renderers/floorplan-annotation-layout.test.ts +0 -37
  61. package/src/components/editor-2d/renderers/floorplan-annotation-layout.ts +0 -30
  62. package/src/components/editor-2d/renderers/floorplan-dimension-edit-overlay.tsx +13 -3
  63. package/src/components/editor-2d/renderers/floorplan-draft-measurement.tsx +7 -1
  64. package/src/components/editor-2d/renderers/floorplan-placement-preview-layer.tsx +14 -3
  65. package/src/components/editor-2d/renderers/floorplan-placement-typing-hud.test.tsx +35 -0
  66. package/src/components/editor-2d/renderers/floorplan-placement-typing-hud.tsx +65 -0
  67. package/src/components/editor-2d/renderers/floorplan-registry-layer.test.ts +30 -10
  68. package/src/components/editor-2d/renderers/floorplan-registry-layer.tsx +39 -35
  69. package/src/components/systems/roof/roof-edit-system.test.tsx +15 -1
  70. package/src/components/systems/roof/roof-edit-system.tsx +33 -21
  71. package/src/components/tools/distribution/distribution-run-tool.test.tsx +371 -3
  72. package/src/components/tools/distribution/distribution-run-tool.tsx +151 -33
  73. package/src/components/tools/item/move-tool.tsx +1 -6
  74. package/src/components/tools/item/placement-history.test.tsx +1 -1
  75. package/src/components/tools/item/use-placement-coordinator.tsx +3 -4
  76. package/src/components/tools/paint-region/wall-paint-region-tool.tsx +7 -3
  77. package/src/components/tools/registry/move-registry-node-tool.test.ts +42 -1
  78. package/src/components/tools/registry/move-registry-node-tool.tsx +39 -16
  79. package/src/components/tools/shared/cursor-sphere.tsx +1 -1
  80. package/src/components/tools/shared/draft-measurement-label.tsx +1 -1
  81. package/src/components/tools/shared/placement-box.tsx +2 -6
  82. package/src/components/tools/shared/placement-coordinate-input.tsx +94 -0
  83. package/src/components/tools/shared/placement-dimension-guides.tsx +1 -1
  84. package/src/components/tools/shared/segment-angle.ts +0 -4
  85. package/src/components/tools/site/terrain-brush-cursor.tsx +1 -1
  86. package/src/components/tools/tool-manager.tsx +1 -24
  87. package/src/components/tools/wall/wall-typed-entry.test.ts +99 -0
  88. package/src/components/tools/wall/wall-typed-entry.ts +70 -0
  89. package/src/components/ui/action-menu/camera-actions.tsx +2 -2
  90. package/src/components/ui/action-menu/control-modes.tsx +1 -1
  91. package/src/components/ui/action-menu/follow-pascal-pill.tsx +1 -1
  92. package/src/components/ui/action-menu/index.tsx +3 -3
  93. package/src/components/ui/action-menu/measurement-control.tsx +3 -3
  94. package/src/components/ui/action-menu/placement.ts +0 -18
  95. package/src/components/ui/action-menu/point-ask-button.tsx +1 -1
  96. package/src/components/ui/action-menu/view-toggles.tsx +5 -5
  97. package/src/components/ui/controls/finish-swatch.tsx +1 -1
  98. package/src/components/ui/controls/material-paint-panel.tsx +2 -2
  99. package/src/components/ui/controls/scene-material-list.tsx +2 -2
  100. package/src/components/ui/controls/select-control.tsx +1 -1
  101. package/src/components/ui/controls/slider-control.tsx +18 -6
  102. package/src/components/ui/controls/terrain-sculpt-panel.tsx +1 -1
  103. package/src/components/ui/controls/tool-options-panel.tsx +74 -44
  104. package/src/components/ui/floating-level-selector.tsx +3 -3
  105. package/src/components/ui/helpers/contextual-helper-panel.tsx +1 -1
  106. package/src/components/ui/helpers/helper-manager.test.tsx +54 -1
  107. package/src/components/ui/helpers/helper-manager.tsx +55 -1
  108. package/src/components/ui/level-duplicate-dialog.tsx +1 -1
  109. package/src/components/ui/panels/collections/collections-popover.tsx +2 -2
  110. package/src/components/ui/panels/floor-foundation-panel.tsx +3 -3
  111. package/src/components/ui/panels/floor-opening-panel.tsx +5 -5
  112. package/src/components/ui/panels/mobile-selection-bar.tsx +28 -24
  113. package/src/components/ui/panels/multi-height-mode.tsx +3 -3
  114. package/src/components/ui/panels/multi-selection-panel.tsx +1 -1
  115. package/src/components/ui/panels/node-display.ts +1 -1
  116. package/src/components/ui/panels/panel-manager.tsx +5 -3
  117. package/src/components/ui/panels/panel-wrapper.tsx +42 -19
  118. package/src/components/ui/panels/parametric-inspector.tsx +1 -1
  119. package/src/components/ui/panels/room-construction-rows.tsx +7 -7
  120. package/src/components/ui/panels/room-name-options.ts +1 -5
  121. package/src/components/ui/panels/room-openings-field.tsx +1 -1
  122. package/src/components/ui/panels/room-panel.tsx +7 -9
  123. package/src/components/ui/primitives/color-dot.tsx +2 -2
  124. package/src/components/ui/primitives/opacity-control.tsx +2 -2
  125. package/src/components/ui/primitives/sidebar.tsx +3 -3
  126. package/src/components/ui/right-stack.test.ts +13 -6
  127. package/src/components/ui/right-stack.tsx +22 -11
  128. package/src/components/ui/sidebar/icon-rail.tsx +1 -1
  129. package/src/components/ui/sidebar/panels/items-panel/function-tree-panel.tsx +1 -1
  130. package/src/components/ui/sidebar/panels/settings-panel/audio-settings-dialog.tsx +2 -2
  131. package/src/components/ui/sidebar/panels/settings-panel/construction-animation-setting.tsx +1 -1
  132. package/src/components/ui/sidebar/panels/settings-panel/index.tsx +2 -2
  133. package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +1 -1
  134. package/src/components/ui/sidebar/panels/settings-panel/load-build-dialog.tsx +2 -6
  135. package/src/components/ui/sidebar/panels/settings-panel/print-export-button.tsx +1 -1
  136. package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +1 -1
  137. package/src/components/ui/sidebar/panels/site-panel/ceiling-tree-node.tsx +1 -1
  138. package/src/components/ui/sidebar/panels/site-panel/index.tsx +3 -10
  139. package/src/components/ui/sidebar/panels/site-panel/inline-rename-input.tsx +1 -1
  140. package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +1 -1
  141. package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +46 -7
  142. package/src/components/ui/sidebar/panels/site-panel/slab-tree-node.tsx +1 -1
  143. package/src/components/ui/sidebar/panels/site-panel/tree-node-actions.tsx +1 -1
  144. package/src/components/ui/sidebar/panels/site-panel/tree-node-drag.tsx +14 -5
  145. package/src/components/ui/sidebar/panels/site-panel/unit-tree-node.tsx +2 -2
  146. package/src/components/ui/sidebar/panels/site-panel/zone-tree-node.tsx +1 -1
  147. package/src/components/ui/sidebar/panels/zone-panel/index.tsx +3 -3
  148. package/src/components/ui/sidebar/tab-bar.tsx +1 -1
  149. package/src/components/ui/wall-type/wall-type-editor-dialog.tsx +2 -2
  150. package/src/components/ui/wall-type/wall-type-menu.tsx +1 -1
  151. package/src/components/viewer-overlay.tsx +1 -2
  152. package/src/hooks/use-auto-frame.ts +1 -2
  153. package/src/hooks/use-keyboard.ts +1 -2
  154. package/src/hooks/use-selected-room.ts +5 -7
  155. package/src/i18n/floor-footprint-name.ts +1 -1
  156. package/src/i18n/locales/en/messages.po +1036 -306
  157. package/src/i18n/locales/en/messages.ts +1 -1
  158. package/src/i18n/locales/en-XA/messages.ts +1 -1
  159. package/src/i18n/locales/es/messages.po +2267 -439
  160. package/src/i18n/locales/fr/messages.po +2267 -439
  161. package/src/i18n/locales/ja/messages.po +2267 -439
  162. package/src/i18n/locales/zh-CN/messages.po +2267 -439
  163. package/src/i18n/locales.test.ts +1 -1
  164. package/src/index.tsx +183 -178
  165. package/src/lib/below-grade.test.tsx +4 -4
  166. package/src/lib/camera-facing.test.ts +1 -1
  167. package/src/lib/camera-facing.ts +2 -3
  168. package/src/lib/contextual-help.ts +6 -0
  169. package/src/lib/editor-level-display.ts +1 -1
  170. package/src/lib/elevation-guides.ts +21 -6
  171. package/src/lib/elevator-support.ts +1 -72
  172. package/src/lib/floor-footprints.test.ts +3 -3
  173. package/src/lib/floor-footprints.ts +1 -9
  174. package/src/lib/floor-foundation-support.test.ts +8 -3
  175. package/src/lib/floor-opening-draft.ts +2 -2
  176. package/src/lib/floor-region-session.ts +1 -1
  177. package/src/lib/floorplan/annotation-visibility.test.ts +1 -1
  178. package/src/lib/floorplan/annotation-visibility.ts +1 -1
  179. package/src/lib/floorplan/floorplan-export.test.ts +1 -1
  180. package/src/lib/floorplan/floorplan-export.tsx +8 -11
  181. package/src/lib/floorplan/floorplan-extension.ts +4 -157
  182. package/src/lib/floorplan/floorplan-mode.ts +2 -1
  183. package/src/lib/floorplan/floorplan-pdfkit-renderer.test.ts +1 -1
  184. package/src/lib/floorplan/floorplan-pdfkit-renderer.ts +8 -6
  185. package/src/lib/floorplan/floorplan-plugin-install.test.tsx +3 -4
  186. package/src/lib/floorplan/geometry.ts +2 -112
  187. package/src/lib/floorplan/index.ts +0 -9
  188. package/src/lib/floorplan/items.ts +2 -1
  189. package/src/lib/floorplan/open-wall-ends.ts +2 -1
  190. package/src/lib/floorplan/schedules.ts +6 -3
  191. package/src/lib/floorplan/sheet-export.ts +7 -3
  192. package/src/lib/floorplan/site-plan/site-parts.ts +7 -1
  193. package/src/lib/floorplan/site-plan/site-plan-layer.tsx +1 -1
  194. package/src/lib/follow-pascal-presentation.ts +1 -1
  195. package/src/lib/gesture-lifecycle.ts +3 -1
  196. package/src/lib/glb-export.ts +1 -1
  197. package/src/lib/interaction/scope.ts +1 -0
  198. package/src/lib/layer-thickness.ts +1 -1
  199. package/src/lib/level-selection.test.ts +18 -2
  200. package/src/lib/level-selection.ts +31 -8
  201. package/src/lib/linear-display.ts +1 -1
  202. package/src/lib/live-gesture-round-trip.test.ts +1 -1
  203. package/src/lib/material-paint.ts +1 -1
  204. package/src/lib/measurement-label.test.ts +1 -1
  205. package/src/lib/measurements.test.ts +7 -5
  206. package/src/lib/mezzanine-selection.test.ts +1 -1
  207. package/src/lib/node-action-movement.test.tsx +115 -0
  208. package/src/lib/node-action-movement.ts +2 -0
  209. package/src/lib/paint-region-mode.ts +1 -1
  210. package/src/lib/placement-metadata.ts +4 -0
  211. package/src/lib/point-ask/describe-target.ts +6 -8
  212. package/src/lib/point-ask/region.ts +1 -1
  213. package/src/lib/point-ask/session.ts +1 -2
  214. package/src/lib/print-shell-compiler.ts +12 -1
  215. package/src/lib/print-wall-solids.test.ts +11 -0
  216. package/src/lib/print-wall-solids.ts +9 -0
  217. package/src/lib/roof-duplication.test.ts +100 -0
  218. package/src/lib/roof-duplication.ts +30 -5
  219. package/src/lib/room-built-on.test.ts +2 -5
  220. package/src/lib/room-built-on.ts +1 -15
  221. package/src/lib/room-construction-commands.ts +3 -2
  222. package/src/lib/room-controls-phase6.test.ts +1 -1
  223. package/src/lib/room-handle-drag.ts +8 -37
  224. package/src/lib/room-name-catalog.test.ts +2 -1
  225. package/src/lib/room-name-messages.test.ts +2 -1
  226. package/src/lib/room-name-messages.ts +1 -118
  227. package/src/lib/room-name-storage.test.ts +2 -1
  228. package/src/lib/room-push-dimensions.test.ts +1 -1
  229. package/src/lib/room-selection-commands.ts +2 -2
  230. package/src/lib/room-selection.test.ts +6 -6
  231. package/src/lib/room-transform-session.ts +1 -2
  232. package/src/lib/room-zone-routing.ts +2 -2
  233. package/src/lib/scene-clipboard.ts +2 -1
  234. package/src/lib/selection-routing.test.ts +0 -28
  235. package/src/lib/selection-routing.ts +1 -40
  236. package/src/lib/sfx-bus.ts +8 -32
  237. package/src/lib/sfx-player.test.ts +72 -1
  238. package/src/lib/sfx-player.ts +49 -337
  239. package/src/lib/snapping-mode.test.ts +23 -1
  240. package/src/lib/viewer-selection.test.ts +38 -10
  241. package/src/lib/wall-pull.test.ts +1 -1
  242. package/src/lib/wall-pull.ts +1 -27
  243. package/src/lib/wall-region-list.ts +3 -1
  244. package/src/lib/window-interaction.test.ts +4 -2
  245. package/src/store/use-editor.tsx +22 -26
  246. package/src/store/use-floorplan-annotation-visibility.ts +5 -5
  247. package/src/store/use-placement-typing.test.ts +165 -0
  248. package/src/store/use-placement-typing.ts +186 -0
  249. package/src/store/use-wall-region-handles-selection.ts +1 -2
  250. package/src/components/editor/__bench__/room-label-placement.bench.ts +0 -108
  251. package/src/components/editor/first-person/build-collider-world.test.ts +0 -596
  252. package/src/components/editor/first-person/build-collider-world.ts +0 -549
  253. package/src/components/editor/first-person/ground-holes.test.ts +0 -128
  254. package/src/components/editor/first-person/ground-holes.ts +0 -130
  255. package/src/components/editor/first-person/mechanism-targets.test.ts +0 -162
  256. package/src/components/editor/first-person/mechanism-targets.ts +0 -88
  257. package/src/components/editor/first-person/terrain-collider.test.ts +0 -132
  258. package/src/components/editor/first-person/terrain-collider.ts +0 -212
  259. package/src/components/editor/floorplan-camera-sync.test.ts +0 -249
  260. package/src/components/editor/floorplan-camera-sync.ts +0 -213
  261. package/src/components/editor/localized-html.tsx +0 -22
  262. package/src/components/editor-2d/renderers/floorplan-dimension-renderer.test.tsx +0 -236
  263. package/src/components/editor-2d/renderers/floorplan-dimension-renderer.tsx +0 -708
  264. package/src/components/editor-2d/renderers/floorplan-geometry-renderer.test.tsx +0 -385
  265. package/src/components/editor-2d/renderers/floorplan-geometry-renderer.tsx +0 -670
  266. package/src/components/editor-2d/renderers/floorplan-label-angle.test.ts +0 -89
  267. package/src/components/editor-2d/renderers/floorplan-label-angle.ts +0 -106
  268. package/src/components/editor-2d/svg-paths.ts +0 -124
  269. package/src/components/tools/elevator/elevator-defaults.ts +0 -8
  270. package/src/components/tools/elevator/elevator-tool.tsx +0 -372
  271. package/src/components/tools/elevator/move-elevator-tool.tsx +0 -262
  272. package/src/components/ui/action-menu/action-button.tsx +0 -89
  273. package/src/components/ui/action-menu/follow-pascal-toggle.tsx +0 -42
  274. package/src/components/ui/primitives/button.tsx +0 -69
  275. package/src/components/ui/primitives/dropdown-menu.tsx +0 -232
  276. package/src/components/ui/primitives/popover.tsx +0 -42
  277. package/src/components/ui/primitives/switch.tsx +0 -29
  278. package/src/components/ui/primitives/tooltip.tsx +0 -57
  279. package/src/components/ui/scene-loader.tsx +0 -73
  280. package/src/components/viewer/floorplan-compass-button.tsx +0 -67
  281. package/src/components/viewer/floorplan-preview-geometry.test.ts +0 -107
  282. package/src/components/viewer/floorplan-preview-geometry.ts +0 -281
  283. package/src/components/viewer/floorplan-preview-navigation.test.ts +0 -43
  284. package/src/components/viewer/floorplan-preview-navigation.ts +0 -62
  285. package/src/components/viewer/floorplan-preview-visibility.test.ts +0 -35
  286. package/src/components/viewer/floorplan-preview-visibility.ts +0 -19
  287. package/src/components/viewer/floorplan-preview.tsx +0 -1065
  288. package/src/components/viewer/render-settings-menu.tsx +0 -294
  289. package/src/components/viewer/sky-control.tsx +0 -710
  290. package/src/components/viewer/use-viewer-camera-navigation-sync.ts +0 -140
  291. package/src/components/viewer/use-viewer-ui-sounds.test.ts +0 -15
  292. package/src/components/viewer/use-viewer-ui-sounds.ts +0 -46
  293. package/src/components/viewer/viewer-controls-bar.tsx +0 -496
  294. package/src/components/viewer/viewer-hover-label.tsx +0 -42
  295. package/src/components/viewer/viewer-rooms.tsx +0 -248
  296. package/src/components/viewer/viewer-scene-header.tsx +0 -286
  297. package/src/components/viewer/viewer-selection-manager.tsx +0 -124
  298. package/src/components/viewer/viewer-stage-modes.test.ts +0 -38
  299. package/src/components/viewer/viewer-stage-modes.ts +0 -49
  300. package/src/components/viewer/viewer-stage-switcher.tsx +0 -97
  301. package/src/components/viewer/viewer-stage.test.tsx +0 -47
  302. package/src/components/viewer/viewer-stage.tsx +0 -221
  303. package/src/components/walkthrough-hud.tsx +0 -193
  304. package/src/hooks/use-mobile.ts +0 -19
  305. package/src/i18n/level-name.ts +0 -39
  306. package/src/i18n/scene-theme-name.ts +0 -16
  307. package/src/lib/below-grade.ts +0 -133
  308. package/src/lib/camera-pose.test.ts +0 -237
  309. package/src/lib/camera-pose.ts +0 -172
  310. package/src/lib/door-interaction.ts +0 -102
  311. package/src/lib/floorplan/floorplan-extension.test.ts +0 -42
  312. package/src/lib/floorplan/floorplan-readonly.test.ts +0 -47
  313. package/src/lib/floorplan/floorplan-readonly.ts +0 -95
  314. package/src/lib/floorplan/marks.test.ts +0 -213
  315. package/src/lib/floorplan/marks.ts +0 -238
  316. package/src/lib/measurement-label.ts +0 -68
  317. package/src/lib/measurements.ts +0 -225
  318. package/src/lib/node-display-label.ts +0 -37
  319. package/src/lib/room-assembly-overlay.test.ts +0 -275
  320. package/src/lib/room-assembly-overlay.ts +0 -265
  321. package/src/lib/room-selection.ts +0 -417
  322. package/src/lib/scene-bounds.test.ts +0 -183
  323. package/src/lib/scene-bounds.ts +0 -169
  324. package/src/lib/typing-target.ts +0 -9
  325. package/src/lib/viewer-selection.ts +0 -595
  326. package/src/lib/window-interaction.ts +0 -142
  327. package/src/lib/zone-content.ts +0 -133
  328. package/src/store/camera-pose-store.test.ts +0 -29
  329. package/src/store/camera-pose-store.ts +0 -27
  330. package/src/store/navigation-sync-pose-store.test.ts +0 -34
  331. package/src/store/navigation-sync-pose-store.ts +0 -27
  332. package/src/store/use-audio.test.ts +0 -146
  333. package/src/store/use-audio.tsx +0 -169
  334. package/src/store/use-first-person-hud.ts +0 -40
  335. package/src/store/use-follow-pascal.test.ts +0 -62
  336. package/src/store/use-follow-pascal.ts +0 -53
@@ -1,7 +1,7 @@
1
1
  import { useViewer } from '@pascal-app/viewer'
2
+ import { useBelowGrade, useGroundWindowBox } from '@pascal-app/viewer/ui'
2
3
  import { useEffect } from 'react'
3
4
  import useEditor, { type CaptureMode } from '../store/use-editor'
4
- import { useBelowGrade, useGroundWindowBox } from './below-grade'
5
5
 
6
6
  /**
7
7
  * Whether the editor shows every level. Preview and the walkthrough show the
@@ -154,12 +154,27 @@ export function collectElevationSnapTargets(
154
154
  anchor: center,
155
155
  label: 'Wall base',
156
156
  })
157
- targets.push({
158
- id: `${node.id}:top`,
159
- elevation: base + getWallEffectiveHeightForNodes(node, nodes),
160
- anchor: center,
161
- label: 'Wall top',
162
- })
157
+ if (node.endHeightOffset) {
158
+ targets.push({
159
+ id: `${node.id}:top-start`,
160
+ elevation: base + getWallEffectiveHeightForNodes(node, nodes, 0),
161
+ anchor: node.start,
162
+ label: 'Wall top start',
163
+ })
164
+ targets.push({
165
+ id: `${node.id}:top-end`,
166
+ elevation: base + getWallEffectiveHeightForNodes(node, nodes, 1),
167
+ anchor: node.end,
168
+ label: 'Wall top end',
169
+ })
170
+ } else {
171
+ targets.push({
172
+ id: `${node.id}:top`,
173
+ elevation: base + getWallEffectiveHeightForNodes(node, nodes, 0.5),
174
+ anchor: center,
175
+ label: 'Wall top',
176
+ })
177
+ }
163
178
  continue
164
179
  }
165
180
 
@@ -1,26 +1,4 @@
1
- import {
2
- type AnyNode,
3
- type AnyNodeId,
4
- type BuildingNode,
5
- type ElevatorNode,
6
- type LevelNode,
7
- spatialGridManager,
8
- useScene,
9
- } from '@pascal-app/core'
10
-
11
- function getBuildingLevels(
12
- buildingId: string | null | undefined,
13
- nodes: Record<string, AnyNode>,
14
- ): LevelNode[] {
15
- if (!buildingId) return []
16
- const building = nodes[buildingId as AnyNodeId]
17
- if (building?.type !== 'building') return []
18
-
19
- return building.children
20
- .map((childId) => nodes[childId as AnyNodeId])
21
- .filter((entry): entry is LevelNode => entry?.type === 'level')
22
- .sort((left, right) => left.level - right.level)
23
- }
1
+ import type { AnyNode, AnyNodeId, BuildingNode, LevelNode } from '@pascal-app/core'
24
2
 
25
3
  export function resolveCurrentBuildingId({
26
4
  buildingId,
@@ -45,52 +23,3 @@ export function resolveCurrentBuildingId({
45
23
 
46
24
  return null
47
25
  }
48
-
49
- export function resolveElevatorSupportLevelId({
50
- buildingId,
51
- preferredLevelId,
52
- }: {
53
- buildingId: string | null | undefined
54
- preferredLevelId?: string | null
55
- }): LevelNode['id'] | null {
56
- const nodes = useScene.getState().nodes
57
- const preferred = preferredLevelId ? nodes[preferredLevelId as AnyNodeId] : undefined
58
- const levels = getBuildingLevels(buildingId, nodes)
59
- const preferredInBuilding = preferredLevelId
60
- ? levels.find((level) => level.id === preferredLevelId)
61
- : undefined
62
-
63
- if (preferredInBuilding) return preferredInBuilding.id
64
- if (levels.length === 0) return preferred?.type === 'level' ? preferred.id : null
65
-
66
- return levels[0]?.id ?? null
67
- }
68
-
69
- export function resolveElevatorSupportY({
70
- buildingId,
71
- preferredLevelId,
72
- x,
73
- z,
74
- }: {
75
- buildingId: string | null | undefined
76
- preferredLevelId?: string | null
77
- x: number
78
- z: number
79
- }): number {
80
- const levelId = resolveElevatorSupportLevelId({ buildingId, preferredLevelId })
81
- if (!levelId) return 0
82
-
83
- return Math.max(0, spatialGridManager.getSlabElevationAt(levelId, x, z))
84
- }
85
-
86
- export function resolveElevatorNodeSupportY(
87
- node: ElevatorNode,
88
- position: [number, number, number] = node.position,
89
- ): number {
90
- return resolveElevatorSupportY({
91
- buildingId: node.parentId,
92
- preferredLevelId: node.fromLevelId ?? node.defaultLevelId,
93
- x: position[0],
94
- z: position[2],
95
- })
96
- }
@@ -11,6 +11,7 @@ import {
11
11
  ItemNode,
12
12
  initSpaceDetectionSync,
13
13
  LevelNode,
14
+ levelFootprints,
14
15
  type SceneCommit,
15
16
  type SlabNode,
16
17
  SlabNode as SlabSchema,
@@ -18,6 +19,8 @@ import {
18
19
  useScene,
19
20
  ZoneNode,
20
21
  } from '@pascal-app/core'
22
+ import type { RoomSelectionRecord } from '@pascal-app/viewer/ui'
23
+ import { resolveRoomAssemblyHeights } from '@pascal-app/viewer/ui'
21
24
  import { moveTogetherLabel } from '../components/ui/panels/floor-foundation-panel'
22
25
  import {
23
26
  applyFloorFoundation,
@@ -29,13 +32,11 @@ import {
29
32
  footprintsToMoveTogether,
30
33
  foundationHeight,
31
34
  isFootprintConstructionHit,
32
- levelFootprints,
33
35
  presetPatch,
34
36
  roomFloorOwner,
35
37
  roomFootprint,
36
38
  roomOwnedPlateDrillTarget,
37
39
  } from './floor-footprints'
38
- import { resolveRoomAssemblyHeights } from './room-assembly-overlay'
39
40
  import { roomConstructionState } from './room-construction'
40
41
  import {
41
42
  addRoomConstruction,
@@ -43,7 +44,6 @@ import {
43
44
  roomRelativeFloorHeight,
44
45
  setRoomRelativeFloorHeight,
45
46
  } from './room-construction-commands'
46
- import type { RoomSelectionRecord } from './room-selection'
47
47
  import { applyRoomPlan } from './room-structure-commands'
48
48
 
49
49
  const LEVEL = 'level_footprints'
@@ -10,6 +10,7 @@ import {
10
10
  getRoomBaseElevation,
11
11
  groundFloorConstruction,
12
12
  intersection,
13
+ levelFootprints,
13
14
  roomDrawnFloor,
14
15
  type SlabNode,
15
16
  setFloorFoundation,
@@ -39,15 +40,6 @@ const ON_GROUND = 0.0005
39
40
  const isBase = (node: AnyNode | undefined): node is SlabNode =>
40
41
  node?.type === 'slab' && node.plateRole === 'base'
41
42
 
42
- const footprintArea = (plate: SlabNode) => area([{ outer: plate.polygon, holes: plate.holes }])
43
-
44
- /** The level's footprints, largest first (ties by id, so the order is stable). */
45
- export function levelFootprints(nodes: Record<string, AnyNode>, levelId: string): SlabNode[] {
46
- return Object.values(nodes)
47
- .filter((node): node is SlabNode => isBase(node) && node.parentId === levelId)
48
- .sort((a, b) => footprintArea(b) - footprintArea(a) || a.id.localeCompare(b.id))
49
- }
50
-
51
43
  /**
52
44
  * The drawn slab a room's floor is: the one it visibly stands on (a legacy
53
45
  * floor can show a hand-drawn slab over the one it was taken from), else the
@@ -11,6 +11,7 @@ import {
11
11
  getLevelElevations,
12
12
  initSpaceDetectionSync,
13
13
  LevelNode,
14
+ levelFootprints,
14
15
  type SlabNode,
15
16
  upperFloorHeightControl,
16
17
  useScene,
@@ -30,7 +31,6 @@ import {
30
31
  footprintHeightMinimum,
31
32
  footprintHeightPatch,
32
33
  footprintHeightValue,
33
- levelFootprints,
34
34
  presetPatch,
35
35
  setFootprintHeight,
36
36
  thickFloorAdvice,
@@ -169,7 +169,6 @@ describe('Upper-floor height drag release (round-final item 6)', () => {
169
169
  test(`a drag of ${delta} m lands on release`, () => {
170
170
  const bedroom = plateOf(UPPER, 'Bedroom')
171
171
  const start = footprintHeightValue(nodes(), bedroom)
172
- const past = useScene.temporal.getState().pastStates.length
173
172
  const preview = beginFootprintHeightPreview(bedroom.id)
174
173
  expect(preview.preview(start + delta / 2)).toBeNull()
175
174
  expect(preview.preview(start + delta)).toBeNull()
@@ -177,7 +176,13 @@ describe('Upper-floor height drag release (round-final item 6)', () => {
177
176
  const after = nodes()[bedroom.id] as SlabNode
178
177
  expect(after.thickness).toBeCloseTo(bedroom.thickness + delta, 6)
179
178
  expect(footprintHeightValue(nodes(), after)).toBeCloseTo(start + delta, 6)
180
- expect(useScene.temporal.getState().pastStates.length).toBe(past + 1)
179
+ useScene.temporal.getState().undo()
180
+ expect(footprintHeightValue(nodes(), nodes()[bedroom.id] as SlabNode)).toBeCloseTo(start, 6)
181
+ useScene.temporal.getState().redo()
182
+ expect(footprintHeightValue(nodes(), nodes()[bedroom.id] as SlabNode)).toBeCloseTo(
183
+ start + delta,
184
+ 6,
185
+ )
181
186
  })
182
187
  }
183
188
  })
@@ -7,11 +7,13 @@ import {
7
7
  generateId,
8
8
  type LevelNode,
9
9
  type MultiPolygon,
10
+ roomFloorElevation,
10
11
  type StructurePlan,
11
12
  structureChangeBatch,
12
13
  useScene,
13
14
  } from '@pascal-app/core'
14
15
  import { useViewer } from '@pascal-app/viewer'
16
+ import { resolveRoomAssemblyHeights } from '@pascal-app/viewer/ui'
15
17
  import { create } from 'zustand'
16
18
  import { getRoomSelectionIndex } from '../hooks/use-selected-room'
17
19
  import useEditor from '../store/use-editor'
@@ -30,8 +32,6 @@ import {
30
32
  } from './floor-region-session'
31
33
  import { type FloorRegionPoint, floorRegionSnapTargets } from './floor-region-snap'
32
34
  import { beginGesture, type GestureHandle } from './gesture-lifecycle'
33
- import { resolveRoomAssemblyHeights } from './room-assembly-overlay'
34
- import { roomFloorElevation } from './room-handle-drag'
35
35
  import { sfxEmitter } from './sfx-bus'
36
36
 
37
37
  // "Cut opening": draws an opening on a room's floor (or its ceiling) with the
@@ -7,6 +7,7 @@ import {
7
7
  ceilingRegionsOwner,
8
8
  type MultiPolygon,
9
9
  resolveCeilingHeight,
10
+ roomFloorElevation,
10
11
  union,
11
12
  useScene,
12
13
  } from '@pascal-app/core'
@@ -32,7 +33,6 @@ import { beginGesture, type GestureHandle } from './gesture-lifecycle'
32
33
  import { hasActivePaintMaterial } from './material-paint'
33
34
  import { isPaintErasing, usePaintRegionMode } from './paint-region-mode'
34
35
  import { addCeilingRegion, addFloorRegion } from './paint-regions'
35
- import { roomFloorElevation } from './room-handle-drag'
36
36
 
37
37
  // An outline drawn on one room's floor: a rectangle (press, drag, release; a
38
38
  // persistent tool also takes two clicks) or a polygon (click points, close on
@@ -1,11 +1,11 @@
1
1
  import { describe, expect, test } from 'bun:test'
2
2
  import type { FloorplanGeometry } from '@pascal-app/core'
3
+ import { floorplanGeometryMetadata, withFloorplanGeometryMetadata } from '@pascal-app/core'
3
4
  import {
4
5
  DEFAULT_FLOORPLAN_ANNOTATION_VISIBILITY,
5
6
  filterFloorplanAnnotationGeometry,
6
7
  normalizeFloorplanAnnotationVisibility,
7
8
  } from './annotation-visibility'
8
- import { floorplanGeometryMetadata, withFloorplanGeometryMetadata } from './floorplan-extension'
9
9
 
10
10
  describe('floor-plan annotation visibility', () => {
11
11
  test('fills missing persisted categories with visible defaults', () => {
@@ -1,5 +1,5 @@
1
1
  import type { FloorplanGeometry } from '@pascal-app/core'
2
- import { type FloorplanAnnotationRole, readFloorplanGeometryMetadata } from './floorplan-extension'
2
+ import { type FloorplanAnnotationRole, readFloorplanGeometryMetadata } from '@pascal-app/core'
3
3
 
4
4
  export type FloorplanAnnotationCategory =
5
5
  | 'automaticDimensions'
@@ -4,6 +4,7 @@ import {
4
4
  type AnyNodeDefinition,
5
5
  BuildingNode,
6
6
  type FloorplanGeometry,
7
+ floorplanGeometryMetadata,
7
8
  type GeometryContext,
8
9
  LevelNode,
9
10
  loadPlugin,
@@ -36,7 +37,6 @@ import {
36
37
  resolveFloorplanScreenUnitsPerPixel,
37
38
  rotateFloorplanExportBounds,
38
39
  } from './floorplan-export'
39
- import { floorplanGeometryMetadata } from './floorplan-extension'
40
40
  import { FloorplanPdfDocument, loadFloorplanPdfFonts } from './floorplan-pdfkit-document'
41
41
  import { renderFloorplanGeometryToPdfKit } from './floorplan-pdfkit-renderer'
42
42
 
@@ -4,23 +4,28 @@ import {
4
4
  type AnyNode,
5
5
  type AnyNodeId,
6
6
  type ConstructionDrawingType,
7
+ FLOORPLAN_VIEW_ROTATION_DEG,
7
8
  type FloorplanGeometry,
9
+ type FloorplanMetricNotation,
8
10
  type FloorplanPalette,
9
11
  type FloorplanPoint,
12
+ type FloorplanSchedule,
13
+ type FloorplanWallDimensionFaces,
10
14
  getLevelDisplayName,
11
15
  isNodeKindEnabled,
12
16
  type LiveNodeOverrides,
13
17
  type NodeCategory,
14
18
  nodeRegistry,
19
+ readFloorplanGeometryMetadata,
15
20
  resolveBuildingForLevel,
16
21
  useScene,
17
22
  } from '@pascal-app/core'
18
23
  import { useViewer } from '@pascal-app/viewer'
24
+ import { FloorplanGeometryRenderer, navigationSyncPoseStore } from '@pascal-app/viewer/ui'
19
25
  import { createElement } from 'react'
20
26
  import { flushSync } from 'react-dom'
21
27
  import { createRoot } from 'react-dom/client'
22
28
  import { resolveSvgAnnotationCollisions } from '../../components/editor-2d/renderers/floorplan-annotation-layout'
23
- import { FloorplanGeometryRenderer } from '../../components/editor-2d/renderers/floorplan-geometry-renderer'
24
29
  import {
25
30
  buildContext,
26
31
  collectDirectFloorplanScopeNodes,
@@ -33,7 +38,6 @@ import {
33
38
  splitFloorplanOverlay,
34
39
  } from '../../components/editor-2d/renderers/floorplan-registry-layer'
35
40
  import useDrawingView, { DRAWING_TYPE_OPTIONS } from '../../store/use-drawing-view'
36
- import useEditor from '../../store/use-editor'
37
41
  import useFloorplanAnnotationVisibility from '../../store/use-floorplan-annotation-visibility'
38
42
  import useFloorplanMode from '../../store/use-floorplan-mode'
39
43
  import {
@@ -41,17 +45,10 @@ import {
41
45
  filterFloorplanAnnotationGeometry,
42
46
  } from './annotation-visibility'
43
47
  import { resolveNodeForDrawingType } from './drawing-coordination'
44
- import {
45
- type FloorplanMetricNotation,
46
- type FloorplanSchedule,
47
- type FloorplanWallDimensionFaces,
48
- getFloorplanNodeExtension,
49
- readFloorplanGeometryMetadata,
50
- } from './floorplan-extension'
48
+ import { getFloorplanNodeExtension } from './floorplan-extension'
51
49
  import { type FloorplanMode, resolveFloorplanAnnotationVisibility } from './floorplan-mode'
52
50
  import { createFloorplanPdfDocument, type FloorplanPdfDocument } from './floorplan-pdfkit-document'
53
51
  import { renderFloorplanGeometryToPdfKit } from './floorplan-pdfkit-renderer'
54
- import { FLOORPLAN_VIEW_ROTATION_DEG } from './geometry'
55
52
 
56
53
  /**
57
54
  * Floorplan PDF export.
@@ -193,7 +190,7 @@ export async function exportFloorplanPdf(scope: FloorplanExportScope): Promise<v
193
190
  expertAnnotationState.visibility,
194
191
  expertAnnotationState.showDimensions,
195
192
  )
196
- const navigationAzimuth = useEditor.getState().navigationSyncPose?.azimuth
193
+ const navigationAzimuth = navigationSyncPoseStore.getState().pose?.azimuth
197
194
  const drawingType = useDrawingView.getState().drawingType
198
195
  const annotationLayoutOverrides = useDrawingView.getState().annotationLayoutOverrides
199
196
  const drawingLabel =
@@ -2,7 +2,11 @@ import type {
2
2
  AnyNode,
3
3
  AnyNodeId,
4
4
  ConstructionDrawingType,
5
+ FloorplanAnnotationRole,
5
6
  FloorplanGeometry,
7
+ FloorplanMetricNotation,
8
+ FloorplanSchedule,
9
+ FloorplanWallDimensionFaces,
6
10
  GeometryContext,
7
11
  NodeDefinition,
8
12
  SceneApi,
@@ -11,57 +15,8 @@ import type { ComponentType } from 'react'
11
15
  import type { WallSelectionDimension } from '../room-push-dimensions'
12
16
 
13
17
  export const FLOORPLAN_NODE_EXTENSION_KEY = 'pascal:editor/floorplan'
14
- export const FLOORPLAN_GEOMETRY_METADATA_KEY = 'pascal:editor/floorplan'
15
- export const FLOORPLAN_CONTEXT_EXTENSION_KEY = 'pascal:editor/floorplan'
16
18
 
17
- export type FloorplanRenderPurpose = 'edit' | 'document'
18
- export type FloorplanMetricNotation = 'meters' | 'millimeters'
19
19
  export type FloorplanToolMode = 'default' | 'expert'
20
- /**
21
- * Display → Measure walls: which finished faces wall dimensions measure to —
22
- * the interior faces (ID, the room sizes), the exterior faces (OD, the
23
- * outside size) or both. Read by a selected wall's temporary dimensions in 2D
24
- * and 3D and by the Expert plan's automatic dimension strings.
25
- */
26
- export type FloorplanWallDimensionFaces = 'interior' | 'exterior' | 'both'
27
- export const DEFAULT_FLOORPLAN_WALL_DIMENSION_FACES: FloorplanWallDimensionFaces = 'both'
28
-
29
- export function normalizeFloorplanWallDimensionFaces(value: unknown): FloorplanWallDimensionFaces {
30
- return value === 'interior' || value === 'exterior'
31
- ? value
32
- : DEFAULT_FLOORPLAN_WALL_DIMENSION_FACES
33
- }
34
- export type FloorplanAnnotationRole =
35
- | 'automatic-dimension'
36
- | 'contextual-dimension'
37
- | 'manual-dimension'
38
- | 'measurement'
39
- | 'opening-mark'
40
- | 'structural-grid'
41
- | 'column-center'
42
- | 'room-label'
43
- /** A room's finish / ceiling-height lines — detail under the name, off in the clean plan. */
44
- | 'room-detail'
45
- /** The roof plan proper: outline, ridges, hips, slope arrows. Off over a floor plan unless asked. */
46
- | 'roof-plan'
47
- | 'roof-pitch'
48
- | 'stair-annotation'
49
-
50
- export type FloorplanSchedule = {
51
- id: string
52
- title: string
53
- columns: ReadonlyArray<{
54
- key: string
55
- label: string
56
- weight?: number
57
- }>
58
- rows: ReadonlyArray<{
59
- id: string
60
- cells: Readonly<Record<string, string>>
61
- }>
62
- issues?: readonly string[]
63
- }
64
-
65
20
  export type FloorplanToolContext = {
66
21
  sceneApi: SceneApi
67
22
  activeLevelId: AnyNodeId | null
@@ -124,7 +79,6 @@ export type FloorplanNodeExtension<N extends AnyNode = AnyNode> = {
124
79
  /** A drafted sheet's schedule: marks match the sheet's tags. */
125
80
  drafting?: boolean
126
81
  }) => FloorplanSchedule | null
127
- linkedLevelIds?: (node: N) => readonly AnyNodeId[]
128
82
  resolveForDrawing?: (args: {
129
83
  node: N
130
84
  nodes: Record<string, AnyNode>
@@ -132,38 +86,6 @@ export type FloorplanNodeExtension<N extends AnyNode = AnyNode> = {
132
86
  }) => AnyNode | null
133
87
  }
134
88
 
135
- type FloorplanGeometryMetadata = {
136
- annotationRole?: FloorplanAnnotationRole
137
- annotationObstacle?: 'bounds' | 'outline'
138
- renderPass?: 'overlay'
139
- /**
140
- * Annotation text only: the size to print at, in paper points, instead of
141
- * the size its role implies. Lets a sheet set a room tag's name larger than
142
- * its number without inventing a role per size.
143
- */
144
- textSizePt?: number
145
- }
146
-
147
- type FloorplanContextExtension = {
148
- automaticDimensions: boolean
149
- purpose: FloorplanRenderPurpose
150
- /**
151
- * Sheet drafting (the Sheets plan viewports): kinds draw the permit-set
152
- * convention — fixtures as labelled linework, furniture as light outlines,
153
- * no raster sprites. Only `collectSheetGeometry` sets it; the editor and the
154
- * read-only viewer never do, so their plans keep today's look.
155
- */
156
- drafting: boolean
157
- /**
158
- * The editor canvas draws room labels as screen pills over the plan
159
- * (`RoomLabels2D`), so zones skip their drawn tags and wash there. Exports,
160
- * sheets and the read-only viewer keep the drawn tags.
161
- */
162
- roomLabelOverlay: boolean
163
- metricNotation: FloorplanMetricNotation
164
- wallDimensionFaces: FloorplanWallDimensionFaces
165
- }
166
-
167
89
  export function getFloorplanNodeExtension(
168
90
  definition: NodeDefinition<any> | undefined,
169
91
  ): FloorplanNodeExtension | undefined {
@@ -171,78 +93,3 @@ export function getFloorplanNodeExtension(
171
93
  | FloorplanNodeExtension
172
94
  | undefined
173
95
  }
174
-
175
- export function floorplanGeometryMetadata(
176
- values: FloorplanGeometryMetadata,
177
- ): Readonly<Record<string, unknown>> {
178
- return { [FLOORPLAN_GEOMETRY_METADATA_KEY]: values }
179
- }
180
-
181
- export function withFloorplanGeometryMetadata<T extends FloorplanGeometry | null>(
182
- geometry: T,
183
- values: FloorplanGeometryMetadata,
184
- ): T {
185
- if (!geometry) return geometry
186
- const existing = readFloorplanGeometryMetadata(geometry)
187
- return {
188
- ...geometry,
189
- metadata: floorplanGeometryMetadata({ ...existing, ...values }),
190
- } as T
191
- }
192
-
193
- export function readFloorplanGeometryMetadata(geometry: unknown): FloorplanGeometryMetadata {
194
- const metadata = (geometry as { metadata?: Readonly<Record<string, unknown>> } | null)?.metadata
195
- const value = metadata?.[FLOORPLAN_GEOMETRY_METADATA_KEY]
196
- return value && typeof value === 'object' && !Array.isArray(value)
197
- ? (value as FloorplanGeometryMetadata)
198
- : {}
199
- }
200
-
201
- export function createFloorplanContextExtensions(
202
- values: Partial<FloorplanContextExtension>,
203
- ): Readonly<Record<string, unknown>> {
204
- return {
205
- [FLOORPLAN_CONTEXT_EXTENSION_KEY]: {
206
- automaticDimensions: values.automaticDimensions !== false,
207
- purpose: values.purpose === 'document' ? 'document' : 'edit',
208
- drafting: values.drafting === true,
209
- roomLabelOverlay: values.roomLabelOverlay === true,
210
- metricNotation: values.metricNotation === 'millimeters' ? 'millimeters' : 'meters',
211
- wallDimensionFaces: normalizeFloorplanWallDimensionFaces(values.wallDimensionFaces),
212
- } satisfies FloorplanContextExtension,
213
- }
214
- }
215
-
216
- export function readFloorplanContext(ctx: GeometryContext): FloorplanContextExtension {
217
- const value = ctx.extensions?.[FLOORPLAN_CONTEXT_EXTENSION_KEY]
218
- if (value && typeof value === 'object' && !Array.isArray(value)) {
219
- const extension = value as Partial<FloorplanContextExtension>
220
- return {
221
- automaticDimensions: extension.automaticDimensions !== false,
222
- purpose: extension.purpose === 'document' ? 'document' : 'edit',
223
- drafting: extension.drafting === true,
224
- roomLabelOverlay: extension.roomLabelOverlay === true,
225
- metricNotation: extension.metricNotation === 'millimeters' ? 'millimeters' : 'meters',
226
- wallDimensionFaces: normalizeFloorplanWallDimensionFaces(extension.wallDimensionFaces),
227
- }
228
- }
229
- return {
230
- automaticDimensions: true,
231
- purpose: 'edit',
232
- drafting: false,
233
- roomLabelOverlay: false,
234
- metricNotation: 'meters',
235
- wallDimensionFaces: DEFAULT_FLOORPLAN_WALL_DIMENSION_FACES,
236
- }
237
- }
238
-
239
- export function readFloorplanMetricNotationOverride(
240
- ctx: GeometryContext,
241
- ): FloorplanMetricNotation | undefined {
242
- const value = ctx.extensions?.[FLOORPLAN_CONTEXT_EXTENSION_KEY]
243
- if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined
244
- const metricNotation = (value as { metricNotation?: unknown }).metricNotation
245
- return metricNotation === 'meters' || metricNotation === 'millimeters'
246
- ? metricNotation
247
- : undefined
248
- }
@@ -1,8 +1,9 @@
1
+ import type { FloorplanAnnotationRole } from '@pascal-app/core'
1
2
  import {
2
3
  type FloorplanAnnotationVisibility,
3
4
  revealFloorplanAnnotationRole,
4
5
  } from './annotation-visibility'
5
- import type { FloorplanAnnotationRole, FloorplanToolMode } from './floorplan-extension'
6
+ import type { FloorplanToolMode } from './floorplan-extension'
6
7
 
7
8
  export const FLOORPLAN_MODES = ['default', 'expert'] as const
8
9
 
@@ -1,7 +1,7 @@
1
1
  import { describe, expect, test } from 'bun:test'
2
2
  import type { FloorplanGeometry } from '@pascal-app/core'
3
+ import { floorplanGeometryMetadata } from '@pascal-app/core'
3
4
  import PDFDocument from 'pdfkit'
4
- import { floorplanGeometryMetadata } from './floorplan-extension'
5
5
  import { FloorplanPdfDocument, loadFloorplanPdfFonts } from './floorplan-pdfkit-document'
6
6
  import { renderFloorplanGeometryToPdfKit } from './floorplan-pdfkit-renderer'
7
7
 
@@ -1,16 +1,18 @@
1
- import { type FloorplanGeometry, type FloorplanPoint, loadAssetUrl } from '@pascal-app/core'
1
+ import {
2
+ type FloorplanGeometry,
3
+ type FloorplanPoint,
4
+ loadAssetUrl,
5
+ readFloorplanGeometryMetadata,
6
+ } from '@pascal-app/core'
2
7
  import {
3
8
  type ArchitecturalDimensionLayout,
4
9
  computeArchitecturalDimensionLayout,
5
- } from '../../components/editor-2d/renderers/floorplan-dimension-renderer'
6
- import {
7
10
  documentCircleGeometryAttrs,
8
11
  documentRectGeometryAttrs,
9
12
  resolveDocumentAnnotationGroupChildren,
10
- } from '../../components/editor-2d/renderers/floorplan-geometry-renderer'
11
- import { resolveFloorplanLabelAngle } from '../../components/editor-2d/renderers/floorplan-label-angle'
13
+ resolveFloorplanLabelAngle,
14
+ } from '@pascal-app/viewer/ui'
12
15
  import type { FloorplanExportBounds } from './floorplan-export'
13
- import { readFloorplanGeometryMetadata } from './floorplan-extension'
14
16
  import type { FloorplanPdfBaseline, FloorplanPdfDocument } from './floorplan-pdfkit-document'
15
17
 
16
18
  const DIMENSION_LINE_WIDTH_PT = 0.5
@@ -6,12 +6,11 @@ import {
6
6
  loadPlugin,
7
7
  nodeRegistry,
8
8
  } from '@pascal-app/core'
9
+ import { FloorplanPreview } from '@pascal-app/viewer/ui'
9
10
  import { renderToStaticMarkup } from 'react-dom/server'
10
11
  import { z } from 'zod'
11
- import { FloorplanPreview } from '../../components/viewer/floorplan-preview'
12
12
  import { DEFAULT_FLOORPLAN_ANNOTATION_VISIBILITY } from './annotation-visibility'
13
13
  import { collectFloorplanGeometry, floorplanExportInstalledPlugins } from './floorplan-export'
14
- import { FLOORPLAN_NODE_EXTENSION_KEY } from './floorplan-extension'
15
14
 
16
15
  // Plugin API v1, no-install case: a plugin kind's floor-plan output appears in
17
16
  // the read-only preview and the PDF export only while the project has the
@@ -31,7 +30,7 @@ const bed = {
31
30
  visible: true,
32
31
  metadata: {},
33
32
  } as unknown as AnyNode
34
- // Lives on the upper level but draws on this one through `linkedLevelIds`.
33
+ // Lives on the upper level but draws on this one through `floorplanLinkedLevelIds`.
35
34
  const upper = LevelNode.parse({ id: 'level_plugin_upper', level: 1, children: ['fxshaft_plan'] })
36
35
  const shaft = {
37
36
  object: 'node',
@@ -70,7 +69,7 @@ beforeEach(async () => {
70
69
  category: 'structure',
71
70
  defaults: () => ({}),
72
71
  capabilities: {},
73
- extensions: { [FLOORPLAN_NODE_EXTENSION_KEY]: { linkedLevelIds: () => [level.id] } },
72
+ floorplanLinkedLevelIds: () => [level.id],
74
73
  floorplan: () => ({ kind: 'rect', x: 3, y: 0, width: 1, height: 1 }),
75
74
  } as unknown as AnyNodeDefinition,
76
75
  ],