@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,5 +1,5 @@
1
1
  import { type AnyNode, type MessageDescriptor, type PascalI18n, scriptImages } from '@pascal-app/core'
2
- import { displayRoomName } from '../../../lib/room-name-messages'
2
+ import { displayRoomName } from '@pascal-app/viewer/ui'
3
3
 
4
4
  export type NodeDisplay = {
5
5
  icon: string
@@ -11,6 +11,8 @@ import {
11
11
  type DormerNode,
12
12
  type ElevatorNode,
13
13
  type FenceNode,
14
+ isMoveLocked,
15
+ isNodeDuplicable,
14
16
  type ItemNode,
15
17
  type RoofNode,
16
18
  type RoofSegmentNode,
@@ -26,7 +28,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'
26
28
  import { useSelectedRoom, useZoneRoom } from '../../../hooks/use-selected-room'
27
29
  import { FloorOpeningPanel } from './floor-opening-panel'
28
30
  import { OpenRoomPanel, RoomPanel } from './room-panel'
29
- import { useIsMobile } from '../../../hooks/use-mobile'
31
+ import { useIsMobile } from '@pascal-app/viewer/ui'
30
32
  import { shouldShowEditingControls } from '../../../lib/interaction/overlay-policy'
31
33
  import { captureElementActionOrigin, completeElementAction } from '../../../lib/room-zone-routing'
32
34
  import { sfxEmitter } from '../../../lib/sfx-bus'
@@ -155,9 +157,9 @@ function MobilePanelLayer({
155
157
  <MobileSelectionBar
156
158
  node={node}
157
159
  onDelete={handleDelete}
158
- onDuplicate={handleDuplicate}
160
+ onDuplicate={isNodeDuplicable(node) ? handleDuplicate : undefined}
159
161
  onEdit={() => setIsSheetOpen((v) => !v)}
160
- onMove={handleMove}
162
+ onMove={isMoveLocked(node) ? undefined : handleMove}
161
163
  />
162
164
  )}
163
165
  <MobilePanelSheet
@@ -19,7 +19,7 @@ import {
19
19
  useRef,
20
20
  useState,
21
21
  } from 'react'
22
- import { useIsMobile } from '../../../hooks/use-mobile'
22
+ import { useIsMobile } from '@pascal-app/viewer/ui'
23
23
  import { NodeIconImage } from '../node-icon-image'
24
24
  import { resolveActiveExtension, toggleCard } from '../../../lib/inspector-card-mode'
25
25
  import { cn } from '../../../lib/utils'
@@ -45,7 +45,7 @@ function clamp(value: number, min: number, max: number): number {
45
45
  * `data-viewer-bounds`) so it can't slide under the sidebar or top bar.
46
46
  * Falls back to the viewport when the marker isn't found.
47
47
  */
48
- function getDragBounds(el: HTMLElement | null): {
48
+ function getDragBounds(el: HTMLElement | null, inStack = false): {
49
49
  left: number
50
50
  top: number
51
51
  right: number
@@ -56,7 +56,15 @@ function getDragBounds(el: HTMLElement | null): {
56
56
  if (!rect) {
57
57
  return { left: 0, top: 0, right: window.innerWidth, bottom: window.innerHeight }
58
58
  }
59
- return { left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom }
59
+ const stack = inStack ? el?.closest('[data-right-stack]') : null
60
+ const stackRect = stack?.getBoundingClientRect()
61
+ const cardRect = stack?.querySelector('[data-right-stack-card]')?.getBoundingClientRect()
62
+ return {
63
+ left: rect.left,
64
+ top: stackRect ? stackRect.top - DRAG_MARGIN : rect.top,
65
+ right: rect.right,
66
+ bottom: cardRect && cardRect.height > 0 ? cardRect.top : rect.bottom,
67
+ }
60
68
  }
61
69
 
62
70
  /**
@@ -187,7 +195,7 @@ export function PanelWrapper({
187
195
  if ((e.target as HTMLElement).closest('button, input, label')) return
188
196
  const rect = panelRef.current?.getBoundingClientRect()
189
197
  if (!rect) return
190
- const bounds = getDragBounds(panelRef.current)
198
+ const bounds = getDragBounds(panelRef.current, inStack)
191
199
  const base = offset ?? { x: 0, y: 0 }
192
200
  dragRef.current = {
193
201
  startX: e.clientX,
@@ -207,7 +215,7 @@ export function PanelWrapper({
207
215
  setIsDragging(true)
208
216
  e.currentTarget.setPointerCapture(e.pointerId)
209
217
  },
210
- [offset],
218
+ [offset, inStack],
211
219
  )
212
220
 
213
221
  const handleHeaderPointerMove = useCallback((e: React.PointerEvent<HTMLDivElement>) => {
@@ -238,22 +246,37 @@ export function PanelWrapper({
238
246
  [handleCardToggle],
239
247
  )
240
248
 
241
- // Expanding can grow the panel past an edge if it was dragged there while
242
- // collapsed — nudge it back inside the viewer bounds.
249
+ // Keep repositioned panels inside the available space as the card or viewer resizes.
243
250
  useLayoutEffect(() => {
244
- if (isMobile || collapsed) return
251
+ if (isMobile) return
245
252
  const el = panelRef.current
246
253
  if (!el) return
247
- const rect = el.getBoundingClientRect()
248
- const bounds = getDragBounds(el)
249
- const left = clamp(rect.left, bounds.left + DRAG_MARGIN, bounds.right - rect.width - DRAG_MARGIN)
250
- const top = clamp(rect.top, bounds.top + DRAG_MARGIN, bounds.bottom - rect.height - DRAG_MARGIN)
251
- const dx = left - rect.left
252
- const dy = top - rect.top
253
- if (Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5) {
254
- setOffset((prev) => ({ x: (prev?.x ?? 0) + dx, y: (prev?.y ?? 0) + dy }))
254
+ const fit = () => {
255
+ const rect = el.getBoundingClientRect()
256
+ const bounds = getDragBounds(el, inStack)
257
+ const left = clamp(rect.left, bounds.left + DRAG_MARGIN, bounds.right - rect.width - DRAG_MARGIN)
258
+ const top = clamp(rect.top, bounds.top + DRAG_MARGIN, bounds.bottom - rect.height - DRAG_MARGIN)
259
+ const dx = left - rect.left
260
+ const dy = top - rect.top
261
+ if (Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5) {
262
+ setOffset((prev) => ({ x: (prev?.x ?? 0) + dx, y: (prev?.y ?? 0) + dy }))
263
+ }
264
+ }
265
+ fit()
266
+ const resize = new ResizeObserver(fit)
267
+ resize.observe(el)
268
+ const stack = el.closest('[data-right-stack]')
269
+ if (stack) {
270
+ resize.observe(stack)
271
+ const card = stack.querySelector('[data-right-stack-card]')
272
+ if (card) resize.observe(card)
273
+ }
274
+ window.addEventListener('resize', fit)
275
+ return () => {
276
+ resize.disconnect()
277
+ window.removeEventListener('resize', fit)
255
278
  }
256
- }, [collapsed, isMobile])
279
+ }, [collapsed, isMobile, inStack])
257
280
 
258
281
  return (
259
282
  <div
@@ -264,7 +287,7 @@ export function PanelWrapper({
264
287
  : inStack
265
288
  ? // In the shared right column: it grows down and scrolls on itself,
266
289
  // leaving the shortcuts card below it its room (`right-stack.tsx`).
267
- 'pointer-events-auto flex max-h-full min-h-0 flex-[0_1_auto] flex-col overflow-hidden rounded-xl border border-border/50 bg-sidebar/95 shadow-2xl backdrop-blur-xl dark:text-foreground'
290
+ 'pointer-events-auto flex max-h-[var(--inspector-available-height)] min-h-0 flex-[0_1_auto] flex-col overflow-hidden rounded-xl border border-border/50 bg-sidebar/95 shadow-2xl backdrop-blur-xl dark:text-foreground'
268
291
  // Cap height at `100dvh - 154px` so a tall panel's bottom edge
269
292
  // aligns flush with the top of the floating bottom action bar.
270
293
  // Combined with `top-20` (80px), the panel's bottom sits at
@@ -291,7 +314,7 @@ export function PanelWrapper({
291
314
  {!isMobile && (
292
315
  <div
293
316
  className={cn(
294
- 'relative flex select-none items-center justify-between px-3 py-3',
317
+ 'relative flex shrink-0 select-none items-center justify-between px-3 py-3',
295
318
  !collapsed && 'border-border/50 border-b',
296
319
  isDragging ? 'cursor-grabbing' : 'cursor-grab',
297
320
  )}
@@ -17,7 +17,7 @@ import { type ComponentType, lazy, Suspense, useCallback } from 'react'
17
17
  import { resolveMoveActionNode } from '../../../lib/direct-manipulation'
18
18
  import { commitParametricNodeFields } from '../../../lib/parametric-node-update'
19
19
  import { sfxEmitter } from '../../../lib/sfx-bus'
20
- import { collectZoneContentIds } from '../../../lib/zone-content'
20
+ import { collectZoneContentIds } from '@pascal-app/viewer/ui'
21
21
  import useEditor from '../../../store/use-editor'
22
22
  import { IconRefImage } from '../icon-ref'
23
23
  import { ActionButton, ActionGroup } from '../controls/action-button'
@@ -34,9 +34,9 @@ import {
34
34
  roomFloorOwner,
35
35
  roomFootprint,
36
36
  } from '../../../lib/floor-footprints'
37
- import { formatLinearMeasurement } from '../../../lib/measurements'
37
+ import { formatLinearMeasurement } from '@pascal-app/core'
38
38
  import { startMezzanineDraft } from '../../../lib/mezzanine-draft'
39
- import { resolveRoomAssemblyHeights } from '../../../lib/room-assembly-overlay'
39
+ import { resolveRoomAssemblyHeights } from '@pascal-app/viewer/ui'
40
40
  import { type FloorChoice, roomBuiltOn, separateFloorSummary } from '../../../lib/room-built-on'
41
41
  import type { RoomConstructionState } from '../../../lib/room-construction'
42
42
  import { roomConstructionState } from '../../../lib/room-construction'
@@ -58,7 +58,7 @@ import {
58
58
  unlockRoomOutsideFaces,
59
59
  } from '../../../lib/room-construction-commands'
60
60
  import { ownFloorElevationBounds } from '../../../lib/room-handle-drag'
61
- import type { RoomSelectionRecord } from '../../../lib/room-selection'
61
+ import type { RoomSelectionRecord } from '@pascal-app/viewer/ui'
62
62
  import { cn } from '../../../lib/utils'
63
63
  import { roomPorchFramingCounts } from '../../../lib/room-construction'
64
64
  import { applyRoomPlan } from '../../../lib/room-structure-commands'
@@ -70,16 +70,16 @@ import {
70
70
  DropdownMenuItem,
71
71
  DropdownMenuSeparator,
72
72
  DropdownMenuTrigger,
73
- } from '../primitives/dropdown-menu'
74
- import { Switch } from '../primitives/switch'
75
- import { Tooltip, TooltipContent, TooltipTrigger } from '../primitives/tooltip'
73
+ } from '@pascal-app/viewer/ui'
74
+ import { Switch } from '@pascal-app/viewer/ui'
75
+ import { Tooltip, TooltipContent, TooltipTrigger } from '@pascal-app/viewer/ui'
76
76
  import { localizedFloorFootprintName } from '../../../i18n/floor-footprint-name'
77
77
  import { messageWithSlot } from '../../../i18n/message-slot'
78
78
  import { nodeLabel } from '../../../i18n/node-messages'
79
79
  import { DeckBoardsFields } from './deck-boards-fields'
80
80
  import { RoomOpeningsField } from './room-openings-field'
81
81
  import { ShapeChoice } from './shape-choice'
82
- import { displayRoomName } from '../../../lib/room-name-messages'
82
+ import { displayRoomName } from '@pascal-app/viewer/ui'
83
83
 
84
84
  /** The buttons a row offers — derived together with its presence. */
85
85
  export function constructionActions(state: RoomConstructionState, part: RoomConstructionPart) {
@@ -4,11 +4,7 @@ import {
4
4
  numberedRoomName,
5
5
  type RoomNameSection,
6
6
  } from '../../../lib/room-name-catalog'
7
- import {
8
- type DescriptorTranslator,
9
- displayRoomName,
10
- editedRoomName,
11
- } from '../../../lib/room-name-messages'
7
+ import { type DescriptorTranslator, displayRoomName, editedRoomName } from '@pascal-app/viewer/ui'
12
8
  import { renameRoom } from '../../../lib/room-structure-commands'
13
9
 
14
10
  export type RoomNameOption = {
@@ -11,7 +11,7 @@ import {
11
11
  useFloorEditSession,
12
12
  } from '../../../lib/floor-edit-session'
13
13
  import { type OpeningSurface, startOpeningDraft } from '../../../lib/floor-opening-draft'
14
- import { formatAreaLabel } from '../../../lib/measurements'
14
+ import { formatAreaLabel } from '@pascal-app/core'
15
15
  import { pill } from './room-construction-rows'
16
16
  import { ShapeChoice } from './shape-choice'
17
17
 
@@ -17,11 +17,11 @@ import { type KeyboardEvent, useEffect, useId, useMemo, useRef, useState } from
17
17
  import { startCeilingEdit } from '../../../lib/ceiling-edit-session'
18
18
  import { resolveOverlayPolicy } from '../../../lib/interaction/overlay-policy'
19
19
  import { finishScriptCode } from '../../../lib/geometry-script/finish-scripts'
20
- import { formatAreaLabel, formatLinearMeasurement } from '../../../lib/measurements'
20
+ import { formatAreaLabel, formatLinearMeasurement } from '@pascal-app/core'
21
21
  import { addMezzanineStairs } from '../../../lib/mezzanine-stairs'
22
22
  import { roomFloorBase, roomRelativeFloorHeight } from '../../../lib/room-construction-commands'
23
23
  import { mezzanineElevationBounds } from '../../../lib/room-handle-drag'
24
- import type { RoomSelectionRecord } from '../../../lib/room-selection'
24
+ import type { RoomSelectionRecord } from '@pascal-app/viewer/ui'
25
25
  import {
26
26
  baseRoomName,
27
27
  type RoomNameSection,
@@ -39,9 +39,9 @@ import {
39
39
  DropdownMenuItem,
40
40
  DropdownMenuSeparator,
41
41
  DropdownMenuTrigger,
42
- } from '../primitives/dropdown-menu'
42
+ } from '@pascal-app/viewer/ui'
43
43
  import { ColorDot } from '../primitives/color-dot'
44
- import { Popover, PopoverAnchor, PopoverContent } from '../primitives/popover'
44
+ import { Popover, PopoverAnchor, PopoverContent } from '@pascal-app/viewer/ui'
45
45
  import { ShortcutToken } from '../primitives/shortcut-token'
46
46
  import { PanelWrapper } from './panel-wrapper'
47
47
  import { RoomOpeningsField } from './room-openings-field'
@@ -59,12 +59,10 @@ import {
59
59
  type RoomNameOption,
60
60
  roomNameOptions,
61
61
  } from './room-name-options'
62
- import { localizedLevelName } from '../../../i18n/level-name'
62
+ import { localizedLevelName } from '@pascal-app/viewer/ui'
63
63
  import { messageWithSlot } from '../../../i18n/message-slot'
64
- import {
65
- displayRoomName,
66
- localizedRoomNameSections,
67
- } from '../../../lib/room-name-messages'
64
+ import { displayRoomName } from '@pascal-app/viewer/ui'
65
+ import { localizedRoomNameSections } from '../../../lib/room-name-messages'
68
66
 
69
67
  /** "Room · Ground floor", "Mezzanine · in Kitchen", "Room · not enclosed". */
70
68
  export function roomKicker(
@@ -3,8 +3,8 @@
3
3
  import { ZONE_COLOR_PALETTE } from '@pascal-app/core'
4
4
  import { useState } from 'react'
5
5
  import { cn } from '../../../lib/utils'
6
- import { Popover, PopoverContent, PopoverTrigger } from './popover'
7
- import { Tooltip, TooltipContent, TooltipTrigger } from './tooltip'
6
+ import { Popover, PopoverContent, PopoverTrigger } from '@pascal-app/viewer/ui'
7
+ import { Tooltip, TooltipContent, TooltipTrigger } from '@pascal-app/viewer/ui'
8
8
 
9
9
  export const PALETTE_COLORS = ZONE_COLOR_PALETTE
10
10
 
@@ -2,8 +2,8 @@
2
2
 
3
3
  import { Eye, EyeOff } from 'lucide-react'
4
4
  import { useState } from 'react'
5
- import { Button } from '../../../components/ui/primitives/button'
6
- import { Popover, PopoverContent, PopoverTrigger } from '../../../components/ui/primitives/popover'
5
+ import { Button } from '@pascal-app/viewer/ui'
6
+ import { Popover, PopoverContent, PopoverTrigger } from '@pascal-app/viewer/ui'
7
7
  import { Slider } from '../../../components/ui/primitives/slider'
8
8
  import { cn } from '../../../lib/utils'
9
9
 
@@ -6,7 +6,7 @@ import { PanelLeftIcon } from 'lucide-react'
6
6
  import * as React from 'react'
7
7
  import { create } from 'zustand'
8
8
  import { persist } from 'zustand/middleware'
9
- import { Button } from './../../../components/ui/primitives/button'
9
+ import { Button } from '@pascal-app/viewer/ui'
10
10
  import { Input } from './../../../components/ui/primitives/input'
11
11
  import { Separator } from './../../../components/ui/primitives/separator'
12
12
  import {
@@ -22,8 +22,8 @@ import {
22
22
  TooltipContent,
23
23
  TooltipProvider,
24
24
  TooltipTrigger,
25
- } from './../../../components/ui/primitives/tooltip'
26
- import { useIsMobile } from './../../../hooks/use-mobile'
25
+ } from '@pascal-app/viewer/ui'
26
+ import { useIsMobile } from '@pascal-app/viewer/ui'
27
27
  import { hydrationGatedStorage } from './../../../lib/hydration-gated-storage'
28
28
  import { cn } from './../../../lib/utils'
29
29
 
@@ -14,16 +14,23 @@ test('the inspector keeps 180 px, or its own height if shorter, above the full c
14
14
  ).toEqual({ inspector: 0, card: 240 })
15
15
  })
16
16
 
17
- test('on a short window the inspector gives way first, down to its header', () => {
17
+ test('on a short window the help card scrolls to preserve editing space', () => {
18
18
  expect(rightStackFloors({ ...tall, naturalHeight: 500, stackHeight: 400 })).toEqual({
19
- inspector: 152,
20
- card: 240,
19
+ inspector: 180,
20
+ card: 212,
21
21
  })
22
22
  })
23
23
 
24
- test('on a very short window the inspector keeps its header and the card scrolls', () => {
24
+ test('expanded hints cannot squeeze the inspector down to just its header', () => {
25
25
  expect(rightStackFloors({ ...tall, naturalHeight: 500, stackHeight: 258 })).toEqual({
26
- inspector: 52,
27
- card: 198,
26
+ inspector: 180,
27
+ card: 70,
28
+ })
29
+ })
30
+
31
+ test('a column shorter than the inspector minimum still bounds both cards', () => {
32
+ expect(rightStackFloors({ ...tall, naturalHeight: 500, stackHeight: 100 })).toEqual({
33
+ inspector: 92,
34
+ card: 0,
28
35
  })
29
36
  })
@@ -1,7 +1,7 @@
1
1
  'use client'
2
2
 
3
- import { createContext, type ReactNode, useContext, useEffect, useRef } from 'react'
4
- import { useIsMobile } from '../../hooks/use-mobile'
3
+ import { createContext, type ReactNode, useContext, useLayoutEffect, useRef } from 'react'
4
+ import { useIsMobile } from '@pascal-app/viewer/ui'
5
5
  import { cn } from '../../lib/utils'
6
6
  import { TOP_MENU_CLEARANCE } from './action-menu/placement'
7
7
 
@@ -20,9 +20,8 @@ const GAP = 8
20
20
 
21
21
  /**
22
22
  * The heights neither panel shrinks below. The inspector keeps 180 px (or its
23
- * own height, if shorter) while the full card fits under it, and never less
24
- * than its header row. The card shows in full whenever the column allows; on a
25
- * very short window it gives way and scrolls on itself — both stay usable.
23
+ * own height, if shorter) and never less than its header row when the column allows.
24
+ * The card uses the remaining room and scrolls on itself on a short window — both stay usable.
26
25
  */
27
26
  export function rightStackFloors(args: {
28
27
  naturalHeight: number
@@ -33,9 +32,10 @@ export function rightStackFloors(args: {
33
32
  const { naturalHeight, headerHeight, cardHeight, stackHeight } = args
34
33
  const gap = naturalHeight > 0 && cardHeight > 0 ? GAP : 0
35
34
  const header = Math.min(headerHeight, naturalHeight)
36
- const inspector = Math.max(
37
- header,
38
- Math.min(INSPECTOR_MIN_HEIGHT, naturalHeight, stackHeight - cardHeight - gap),
35
+ const inspector = Math.min(
36
+ naturalHeight,
37
+ stackHeight,
38
+ Math.max(header, Math.min(INSPECTOR_MIN_HEIGHT, stackHeight - gap)),
39
39
  )
40
40
  const card = Math.max(0, Math.min(cardHeight, stackHeight - gap - inspector))
41
41
  return { inspector, card }
@@ -78,7 +78,7 @@ export function RightStack({
78
78
 
79
79
  // `min(180px, its own height)` has no CSS form for a flex item that scrolls,
80
80
  // so both floors are measured (`rightStackFloors`).
81
- useEffect(() => {
81
+ useLayoutEffect(() => {
82
82
  if (isMobile) return
83
83
  const stack = stackRef.current
84
84
  const slot = inspectorRef.current
@@ -88,18 +88,29 @@ export function RightStack({
88
88
  const fit = () => {
89
89
  frame = 0
90
90
  const { natural, header } = inspectorHeights(slot)
91
+ const cardHeight = Array.from(card.children).reduce(
92
+ (height, child) => height + child.scrollHeight + (child instanceof HTMLElement ? child.offsetHeight - child.clientHeight : 0),
93
+ 0,
94
+ )
91
95
  const floors = rightStackFloors({
92
96
  naturalHeight: natural,
93
97
  headerHeight: header,
94
- cardHeight: card.scrollHeight,
98
+ cardHeight,
95
99
  stackHeight: stack.clientHeight,
96
100
  })
97
101
  const inspectorMin = `${floors.inspector}px`
98
102
  const cardMin = `${floors.card}px`
103
+ // Custom panels may wrap PanelWrapper in a non-flex element. Give the
104
+ // card an explicit inherited limit so those wrappers cannot bypass it.
105
+ const available = Math.max(0, stack.clientHeight - floors.card - (natural > 0 && floors.card > 0 ? GAP : 0))
106
+ const limit = `${available}px`
107
+ if (slot.style.getPropertyValue('--inspector-available-height') !== limit) {
108
+ slot.style.setProperty('--inspector-available-height', limit)
109
+ }
99
110
  if (slot.style.minHeight !== inspectorMin) slot.style.minHeight = inspectorMin
100
111
  if (card.style.minHeight !== cardMin) card.style.minHeight = cardMin
101
112
  // The card is click-through; it takes the pointer only when it has to scroll.
102
- const pointer = floors.card < card.scrollHeight ? 'auto' : ''
113
+ const pointer = floors.card < cardHeight ? 'auto' : ''
103
114
  if (card.style.pointerEvents !== pointer) card.style.pointerEvents = pointer
104
115
  }
105
116
  const schedule = () => {
@@ -7,7 +7,7 @@ import {
7
7
  Tooltip,
8
8
  TooltipContent,
9
9
  TooltipTrigger,
10
- } from './../../../components/ui/primitives/tooltip'
10
+ } from '@pascal-app/viewer/ui'
11
11
  import { cn } from './../../../lib/utils'
12
12
 
13
13
  export type PanelId = string
@@ -11,7 +11,7 @@ import {
11
11
  TooltipContent,
12
12
  TooltipProvider,
13
13
  TooltipTrigger,
14
- } from '../../../../../components/ui/primitives/tooltip'
14
+ } from '@pascal-app/viewer/ui'
15
15
 
16
16
  /** A function-axis taxonomy node, assembled into a tree by the embedder. */
17
17
  export type FunctionTreeNode = {
@@ -1,5 +1,5 @@
1
1
  import { Volume2, VolumeX } from 'lucide-react'
2
- import { Button } from '../../../../../components/ui/primitives/button'
2
+ import { Button } from '@pascal-app/viewer/ui'
3
3
  import {
4
4
  Dialog,
5
5
  DialogContent,
@@ -9,7 +9,7 @@ import {
9
9
  DialogTrigger,
10
10
  } from '../../../../../components/ui/primitives/dialog'
11
11
  import { Slider } from '../../../../../components/ui/slider'
12
- import useAudio from '../../../../../store/use-audio'
12
+ import { useAudioSettings as useAudio } from '@pascal-app/viewer/sfx'
13
13
 
14
14
  export function AudioSettingsDialog() {
15
15
  const {
@@ -8,7 +8,7 @@ import {
8
8
  } from '../../../../../store/use-construction-reveal'
9
9
  import { SegmentedControl } from '../../../controls/segmented-control'
10
10
  import { Badge } from '../../../primitives/badge'
11
- import { Tooltip, TooltipContent, TooltipTrigger } from '../../../primitives/tooltip'
11
+ import { Tooltip, TooltipContent, TooltipTrigger } from '@pascal-app/viewer/ui'
12
12
 
13
13
  /** Why Framing is greyed out. */
14
14
  export const FRAMING_NEEDS_ARCHITECT = 'Framing needs the Architect plugin.'
@@ -61,7 +61,7 @@ import {
61
61
  waitForLocalImport,
62
62
  } from '../../../../../lib/send-to-app'
63
63
  import { SegmentedControl } from './../../../../../components/ui/controls/segmented-control'
64
- import { Button } from './../../../../../components/ui/primitives/button'
64
+ import { Button } from '@pascal-app/viewer/ui'
65
65
  import {
66
66
  Dialog,
67
67
  DialogContent,
@@ -69,7 +69,7 @@ import {
69
69
  DialogTrigger,
70
70
  } from './../../../../../components/ui/primitives/dialog'
71
71
  import { Input } from './../../../../../components/ui/primitives/input'
72
- import { Switch } from './../../../../../components/ui/primitives/switch'
72
+ import { Switch } from '@pascal-app/viewer/ui'
73
73
  import { cn } from './../../../../../lib/utils'
74
74
  import { refusedObjectsNotice } from './../../../../../components/editor/group-actions'
75
75
  import { addStoreyBelow, addStoreyOnTop } from './../../../../../lib/add-storey'
@@ -1,6 +1,6 @@
1
1
  import { type MessageDescriptor, usePascalI18n } from '@pascal-app/core'
2
2
  import { Keyboard } from 'lucide-react'
3
- import { Button } from './../../../../../components/ui/primitives/button'
3
+ import { Button } from '@pascal-app/viewer/ui'
4
4
  import {
5
5
  Dialog,
6
6
  DialogContent,
@@ -14,7 +14,7 @@ import {
14
14
  XCircle,
15
15
  } from 'lucide-react'
16
16
  import { useState } from 'react'
17
- import { Button } from '../../../../../components/ui/primitives/button'
17
+ import { Button } from '@pascal-app/viewer/ui'
18
18
  import {
19
19
  Dialog,
20
20
  DialogContent,
@@ -23,11 +23,7 @@ import {
23
23
  DialogHeader,
24
24
  DialogTitle,
25
25
  } from '../../../../../components/ui/primitives/dialog'
26
- import {
27
- getAreaUnitLabel,
28
- type LinearUnit,
29
- squareMetersToAreaUnit,
30
- } from '../../../../../lib/measurements'
26
+ import { getAreaUnitLabel, type LinearUnit, squareMetersToAreaUnit } from '@pascal-app/core'
31
27
 
32
28
  export type PendingImport = {
33
29
  fileName: string
@@ -2,7 +2,7 @@ import { getProjectFileSink } from '@pascal-app/core'
2
2
  import { downloadProjectFile } from '../../../../../lib/download-project-file'
3
3
  import { AlertTriangle, Printer } from 'lucide-react'
4
4
  import { useState } from 'react'
5
- import { Button } from '../../../../../components/ui/primitives/button'
5
+ import { Button } from '@pascal-app/viewer/ui'
6
6
  import {
7
7
  isPrintLevelBundleReport,
8
8
  type PrintLevelBundleReport,
@@ -8,7 +8,7 @@ import {
8
8
  Tooltip,
9
9
  TooltipContent,
10
10
  TooltipTrigger,
11
- } from './../../../../../components/ui/primitives/tooltip'
11
+ } from '@pascal-app/viewer/ui'
12
12
  import { focusTreeNode, TreeNode, TreeNodeWrapper } from './tree-node'
13
13
  import { TreeNodeActions } from './tree-node-actions'
14
14
 
@@ -4,7 +4,7 @@ import Image from 'next/image'
4
4
  import { memo, useCallback, useEffect, useState } from 'react'
5
5
  import { useShallow } from 'zustand/react/shallow'
6
6
  import { startCeilingEditFromTreeSelection } from './../../../../../lib/ceiling-edit-session'
7
- import { formatAreaLabel } from './../../../../../lib/measurements'
7
+ import { formatAreaLabel } from '@pascal-app/core'
8
8
  import { InlineRenameInput } from './inline-rename-input'
9
9
  import { focusTreeNode, handleTreeSelection, TreeNode, TreeNodeWrapper } from './tree-node'
10
10
  import { TreeNodeActions } from './tree-node-actions'
@@ -52,7 +52,7 @@ import {
52
52
  Popover,
53
53
  PopoverContent,
54
54
  PopoverTrigger,
55
- } from './../../../../../components/ui/primitives/popover'
55
+ } from '@pascal-app/viewer/ui'
56
56
  import {
57
57
  buildLevelDuplicateCreateOps,
58
58
  type LevelDuplicatePreset,
@@ -60,14 +60,7 @@ import {
60
60
  import { addStoreyOnTop } from './../../../../../lib/add-storey'
61
61
  import { offerExteriorWallCopy } from './../../../../../components/ui/level-wall-copy-prompt'
62
62
  import { deleteLevelWithFallbackSelection } from './../../../../../lib/level-selection'
63
- import {
64
- formatAreaLabel,
65
- getAreaUnitLabel,
66
- getLinearUnitLabel,
67
- linearUnitToMeters,
68
- metersToLinearUnit,
69
- squareMetersToAreaUnit,
70
- } from './../../../../../lib/measurements'
63
+ import { formatAreaLabel, getAreaUnitLabel, getLinearUnitLabel, linearUnitToMeters, metersToLinearUnit, squareMetersToAreaUnit } from '@pascal-app/core'
71
64
  import { createLocalGuideImage, createLocalScan } from './../../../../../lib/local-guide-image'
72
65
  import { editorHostTreeChildrenRegistry } from './../../../../../lib/host-tree-children'
73
66
  import { requestRoomDeletion } from './../../../../../lib/room-structure-commands'
@@ -88,7 +81,7 @@ import { focusTreeNode, TreeNode, TreeNodeWrapper } from './tree-node'
88
81
  import { TreeNodeDragProvider } from './tree-node-drag'
89
82
  import { zoneDefaultName } from './default-names'
90
83
  import { nodeLabelDescriptor } from '../../../../../i18n/node-messages'
91
- import { authoredLevelName, localizedLevelName } from '../../../../../i18n/level-name'
84
+ import { authoredLevelName, localizedLevelName } from '@pascal-app/viewer/ui'
92
85
 
93
86
  // ============================================================================
94
87
  // PROPERTY LINE SECTION
@@ -1,7 +1,7 @@
1
1
  import { type AnyNodeId, usePascalI18n, useScene } from '@pascal-app/core'
2
2
  import { Pencil } from 'lucide-react'
3
3
  import { memo, useCallback, useEffect, useRef, useState } from 'react'
4
- import { displayRoomName } from './../../../../../lib/room-name-messages'
4
+ import { displayRoomName } from '@pascal-app/viewer/ui'
5
5
  import { cn } from './../../../../../lib/utils'
6
6
  import { commitTreeRoomRename } from './../../../panels/room-name-options'
7
7
 
@@ -6,7 +6,7 @@ import { useShallow } from 'zustand/react/shallow'
6
6
  import { InlineRenameInput } from './inline-rename-input'
7
7
  import { focusTreeNode, TreeNode, TreeNodeWrapper } from './tree-node'
8
8
  import { TreeNodeActions } from './tree-node-actions'
9
- import { authoredLevelName, localizedLevelName } from '../../../../../i18n/level-name'
9
+ import { authoredLevelName, localizedLevelName } from '@pascal-app/viewer/ui'
10
10
 
11
11
  interface LevelTreeNodeProps {
12
12
  nodeId: LevelNode['id']