@pascal-app/editor 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) 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 +11 -11
  5. package/src/components/editor/editor-layout-v2.tsx +1 -1
  6. package/src/components/editor/elevation-3d-guide-layer.tsx +1 -1
  7. package/src/components/editor/first-person-controls.tsx +20 -1981
  8. package/src/components/editor/floating-action-menu.tsx +1 -1
  9. package/src/components/editor/floating-building-action-menu.tsx +1 -1
  10. package/src/components/editor/floor-region-controls.tsx +6 -2
  11. package/src/components/editor/floorplan-navigation-presentation.test.ts +0 -40
  12. package/src/components/editor/floorplan-navigation-presentation.ts +0 -66
  13. package/src/components/editor/floorplan-panel.tsx +26 -22
  14. package/src/components/editor/floorplan-wall-typing-keys.ts +1 -1
  15. package/src/components/editor/follow-pascal.test.tsx +1 -2
  16. package/src/components/editor/follow-pascal.tsx +1 -1
  17. package/src/components/editor/footprint-height-handle.tsx +1 -1
  18. package/src/components/editor/group-actions.ts +1 -2
  19. package/src/components/editor/group-floating-action-menu.tsx +1 -1
  20. package/src/components/editor/group-move-3d.ts +1 -2
  21. package/src/components/editor/group-rotate-handle.tsx +1 -2
  22. package/src/components/editor/handles/use-handle-drag.ts +1 -2
  23. package/src/components/editor/index.tsx +24 -14
  24. package/src/components/editor/inspector-extension-actions.tsx +1 -1
  25. package/src/components/editor/node-arrow-handles.tsx +1 -1
  26. package/src/components/editor/open-wall-ends-3d-layer.tsx +1 -1
  27. package/src/components/editor/opening-guides-3d-layer.tsx +1 -1
  28. package/src/components/editor/room-controls.tsx +7 -4
  29. package/src/components/editor/room-handles-2d.tsx +2 -3
  30. package/src/components/editor/room-handles.tsx +1 -2
  31. package/src/components/editor/room-highlight.tsx +6 -105
  32. package/src/components/editor/room-labels.test.ts +8 -822
  33. package/src/components/editor/room-labels.tsx +40 -1671
  34. package/src/components/editor/room-webgpu-materials.test.ts +1 -1
  35. package/src/components/editor/selection-manager.tsx +5 -3
  36. package/src/components/editor/site-edge-labels.tsx +1 -1
  37. package/src/components/editor/snapshot-capture-overlay.tsx +2 -5
  38. package/src/components/editor/use-floorplan-background-placement.ts +2 -1
  39. package/src/components/editor/views/plugins-view.tsx +1 -1
  40. package/src/components/editor/views/view-bar.tsx +9 -9
  41. package/src/components/editor/wall-measurement-label.tsx +1 -1
  42. package/src/components/editor/wall-move-side-handles.tsx +1 -1
  43. package/src/components/editor/wall-pull-grip.tsx +2 -2
  44. package/src/components/editor-2d/floorplan-group-move.tsx +2 -3
  45. package/src/components/editor-2d/floorplan-measurement-tool-layer.tsx +1 -1
  46. package/src/components/editor-2d/floorplan-open-wall-ends-layer.tsx +1 -1
  47. package/src/components/editor-2d/floorplan-registry-move-overlay.tsx +1 -2
  48. package/src/components/editor-2d/renderers/floorplan-annotation-layout.test.ts +0 -37
  49. package/src/components/editor-2d/renderers/floorplan-annotation-layout.ts +0 -30
  50. package/src/components/editor-2d/renderers/floorplan-dimension-edit-overlay.tsx +13 -3
  51. package/src/components/editor-2d/renderers/floorplan-placement-preview-layer.tsx +1 -2
  52. package/src/components/editor-2d/renderers/floorplan-registry-layer.test.ts +8 -10
  53. package/src/components/editor-2d/renderers/floorplan-registry-layer.tsx +25 -33
  54. package/src/components/systems/roof/roof-edit-system.tsx +4 -3
  55. package/src/components/tools/distribution/distribution-run-tool.tsx +1 -1
  56. package/src/components/tools/item/placement-history.test.tsx +1 -1
  57. package/src/components/tools/item/use-placement-coordinator.tsx +2 -3
  58. package/src/components/tools/paint-region/wall-paint-region-tool.tsx +6 -2
  59. package/src/components/tools/registry/move-registry-node-tool.tsx +1 -2
  60. package/src/components/tools/shared/cursor-sphere.tsx +1 -1
  61. package/src/components/tools/shared/draft-measurement-label.tsx +1 -1
  62. package/src/components/tools/shared/placement-box.tsx +1 -1
  63. package/src/components/tools/shared/placement-dimension-guides.tsx +1 -1
  64. package/src/components/tools/site/terrain-brush-cursor.tsx +1 -1
  65. package/src/components/ui/action-menu/camera-actions.tsx +2 -2
  66. package/src/components/ui/action-menu/control-modes.tsx +1 -1
  67. package/src/components/ui/action-menu/follow-pascal-pill.tsx +1 -1
  68. package/src/components/ui/action-menu/index.tsx +3 -3
  69. package/src/components/ui/action-menu/measurement-control.tsx +3 -3
  70. package/src/components/ui/action-menu/placement.ts +0 -18
  71. package/src/components/ui/action-menu/point-ask-button.tsx +1 -1
  72. package/src/components/ui/action-menu/view-toggles.tsx +5 -5
  73. package/src/components/ui/controls/finish-swatch.tsx +1 -1
  74. package/src/components/ui/controls/material-paint-panel.tsx +2 -2
  75. package/src/components/ui/controls/scene-material-list.tsx +2 -2
  76. package/src/components/ui/controls/select-control.tsx +1 -1
  77. package/src/components/ui/controls/terrain-sculpt-panel.tsx +1 -1
  78. package/src/components/ui/floating-level-selector.tsx +3 -3
  79. package/src/components/ui/helpers/contextual-helper-panel.tsx +1 -1
  80. package/src/components/ui/helpers/helper-manager.test.tsx +1 -1
  81. package/src/components/ui/helpers/helper-manager.tsx +1 -1
  82. package/src/components/ui/level-duplicate-dialog.tsx +1 -1
  83. package/src/components/ui/node-icon-image.test.tsx +46 -0
  84. package/src/components/ui/node-icon-image.tsx +33 -1
  85. package/src/components/ui/panels/collections/collections-popover.tsx +2 -2
  86. package/src/components/ui/panels/floor-foundation-panel.tsx +2 -2
  87. package/src/components/ui/panels/floor-opening-panel.tsx +4 -4
  88. package/src/components/ui/panels/node-display.ts +1 -1
  89. package/src/components/ui/panels/panel-manager.tsx +1 -1
  90. package/src/components/ui/panels/panel-wrapper.tsx +1 -1
  91. package/src/components/ui/panels/parametric-inspector.tsx +1 -1
  92. package/src/components/ui/panels/room-construction-rows.tsx +6 -6
  93. package/src/components/ui/panels/room-name-options.ts +1 -5
  94. package/src/components/ui/panels/room-panel.tsx +6 -8
  95. package/src/components/ui/primitives/color-dot.tsx +2 -2
  96. package/src/components/ui/primitives/opacity-control.tsx +2 -2
  97. package/src/components/ui/primitives/sidebar.tsx +3 -3
  98. package/src/components/ui/right-stack.tsx +1 -1
  99. package/src/components/ui/sidebar/icon-rail.tsx +1 -1
  100. package/src/components/ui/sidebar/panels/items-panel/function-tree-panel.tsx +1 -1
  101. package/src/components/ui/sidebar/panels/settings-panel/audio-settings-dialog.tsx +2 -2
  102. package/src/components/ui/sidebar/panels/settings-panel/construction-animation-setting.tsx +1 -1
  103. package/src/components/ui/sidebar/panels/settings-panel/index.tsx +2 -2
  104. package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +1 -1
  105. package/src/components/ui/sidebar/panels/settings-panel/load-build-dialog.tsx +1 -1
  106. package/src/components/ui/sidebar/panels/settings-panel/print-export-button.tsx +1 -1
  107. package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +1 -1
  108. package/src/components/ui/sidebar/panels/site-panel/index.tsx +2 -2
  109. package/src/components/ui/sidebar/panels/site-panel/inline-rename-input.tsx +1 -1
  110. package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +1 -1
  111. package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +46 -7
  112. package/src/components/ui/sidebar/panels/site-panel/tree-node-actions.tsx +1 -1
  113. package/src/components/ui/sidebar/panels/site-panel/tree-node-drag.tsx +14 -5
  114. package/src/components/ui/sidebar/panels/site-panel/unit-tree-node.tsx +2 -2
  115. package/src/components/ui/sidebar/panels/zone-panel/index.tsx +3 -3
  116. package/src/components/ui/sidebar/tab-bar.tsx +1 -1
  117. package/src/components/ui/wall-type/wall-type-editor-dialog.tsx +1 -1
  118. package/src/components/ui/wall-type/wall-type-menu.tsx +1 -1
  119. package/src/components/viewer-overlay.tsx +1 -2
  120. package/src/hooks/use-auto-frame.ts +1 -2
  121. package/src/hooks/use-keyboard.ts +1 -2
  122. package/src/hooks/use-selected-room.ts +5 -7
  123. package/src/i18n/floor-footprint-name.ts +1 -1
  124. package/src/i18n/locales/en/messages.po +180 -182
  125. package/src/i18n/locales/es/messages.po +180 -182
  126. package/src/i18n/locales/fr/messages.po +180 -182
  127. package/src/i18n/locales/ja/messages.po +180 -182
  128. package/src/i18n/locales/zh-CN/messages.po +180 -182
  129. package/src/i18n/locales.test.ts +1 -1
  130. package/src/index.tsx +109 -131
  131. package/src/lib/below-grade.test.tsx +4 -4
  132. package/src/lib/camera-facing.test.ts +1 -1
  133. package/src/lib/camera-facing.ts +2 -3
  134. package/src/lib/editor-level-display.ts +1 -1
  135. package/src/lib/floor-footprints.test.ts +2 -2
  136. package/src/lib/floor-opening-draft.ts +1 -1
  137. package/src/lib/floorplan/annotation-visibility.test.ts +1 -1
  138. package/src/lib/floorplan/annotation-visibility.ts +1 -1
  139. package/src/lib/floorplan/floorplan-export.test.ts +1 -1
  140. package/src/lib/floorplan/floorplan-export.tsx +8 -11
  141. package/src/lib/floorplan/floorplan-extension.ts +4 -157
  142. package/src/lib/floorplan/floorplan-mode.ts +2 -1
  143. package/src/lib/floorplan/floorplan-pdfkit-renderer.test.ts +1 -1
  144. package/src/lib/floorplan/floorplan-pdfkit-renderer.ts +8 -6
  145. package/src/lib/floorplan/floorplan-plugin-install.test.tsx +3 -4
  146. package/src/lib/floorplan/geometry.ts +2 -112
  147. package/src/lib/floorplan/index.ts +0 -9
  148. package/src/lib/floorplan/items.ts +2 -1
  149. package/src/lib/floorplan/schedules.ts +6 -3
  150. package/src/lib/floorplan/sheet-export.ts +7 -3
  151. package/src/lib/floorplan/site-plan/site-parts.ts +7 -1
  152. package/src/lib/floorplan/site-plan/site-plan-layer.tsx +1 -1
  153. package/src/lib/follow-pascal-presentation.ts +1 -1
  154. package/src/lib/glb-export.ts +1 -1
  155. package/src/lib/material-paint.ts +1 -1
  156. package/src/lib/measurements.test.ts +2 -1
  157. package/src/lib/mezzanine-selection.test.ts +1 -1
  158. package/src/lib/paint-region-mode.ts +1 -1
  159. package/src/lib/point-ask/session.ts +1 -2
  160. package/src/lib/roof-duplication.test.ts +100 -0
  161. package/src/lib/roof-duplication.ts +30 -5
  162. package/src/lib/room-handle-drag.ts +2 -12
  163. package/src/lib/room-name-catalog.test.ts +2 -1
  164. package/src/lib/room-name-messages.test.ts +2 -1
  165. package/src/lib/room-name-messages.ts +1 -118
  166. package/src/lib/room-name-storage.test.ts +2 -1
  167. package/src/lib/room-selection-commands.ts +2 -2
  168. package/src/lib/room-selection.test.ts +6 -6
  169. package/src/lib/room-transform-session.ts +1 -2
  170. package/src/lib/room-zone-routing.ts +2 -2
  171. package/src/lib/selection-routing.test.ts +0 -28
  172. package/src/lib/selection-routing.ts +1 -40
  173. package/src/lib/sfx-bus.ts +8 -32
  174. package/src/lib/sfx-player.test.ts +72 -1
  175. package/src/lib/sfx-player.ts +49 -337
  176. package/src/lib/viewer-selection.test.ts +38 -10
  177. package/src/lib/wall-pull.test.ts +1 -1
  178. package/src/lib/wall-pull.ts +1 -27
  179. package/src/store/use-editor.tsx +17 -26
  180. package/src/store/use-floorplan-annotation-visibility.ts +5 -5
  181. package/src/store/use-wall-region-handles-selection.ts +1 -2
  182. package/src/components/editor/__bench__/room-label-placement.bench.ts +0 -108
  183. package/src/components/editor/first-person/build-collider-world.test.ts +0 -596
  184. package/src/components/editor/first-person/build-collider-world.ts +0 -549
  185. package/src/components/editor/first-person/ground-holes.test.ts +0 -128
  186. package/src/components/editor/first-person/ground-holes.ts +0 -130
  187. package/src/components/editor/first-person/mechanism-targets.test.ts +0 -162
  188. package/src/components/editor/first-person/mechanism-targets.ts +0 -88
  189. package/src/components/editor/first-person/terrain-collider.test.ts +0 -132
  190. package/src/components/editor/first-person/terrain-collider.ts +0 -212
  191. package/src/components/editor/floorplan-camera-sync.test.ts +0 -249
  192. package/src/components/editor/floorplan-camera-sync.ts +0 -213
  193. package/src/components/editor/localized-html.tsx +0 -22
  194. package/src/components/editor-2d/renderers/floorplan-dimension-renderer.test.tsx +0 -236
  195. package/src/components/editor-2d/renderers/floorplan-dimension-renderer.tsx +0 -708
  196. package/src/components/editor-2d/renderers/floorplan-geometry-renderer.test.tsx +0 -385
  197. package/src/components/editor-2d/renderers/floorplan-geometry-renderer.tsx +0 -670
  198. package/src/components/editor-2d/renderers/floorplan-label-angle.test.ts +0 -89
  199. package/src/components/editor-2d/renderers/floorplan-label-angle.ts +0 -106
  200. package/src/components/editor-2d/svg-paths.ts +0 -124
  201. package/src/components/ui/action-menu/action-button.tsx +0 -89
  202. package/src/components/ui/action-menu/follow-pascal-toggle.tsx +0 -42
  203. package/src/components/ui/primitives/button.tsx +0 -69
  204. package/src/components/ui/primitives/dropdown-menu.tsx +0 -232
  205. package/src/components/ui/primitives/popover.tsx +0 -42
  206. package/src/components/ui/primitives/switch.tsx +0 -29
  207. package/src/components/ui/primitives/tooltip.tsx +0 -57
  208. package/src/components/ui/scene-loader.tsx +0 -73
  209. package/src/components/viewer/floorplan-compass-button.tsx +0 -67
  210. package/src/components/viewer/floorplan-preview-geometry.test.ts +0 -107
  211. package/src/components/viewer/floorplan-preview-geometry.ts +0 -281
  212. package/src/components/viewer/floorplan-preview-navigation.test.ts +0 -43
  213. package/src/components/viewer/floorplan-preview-navigation.ts +0 -62
  214. package/src/components/viewer/floorplan-preview-visibility.test.ts +0 -35
  215. package/src/components/viewer/floorplan-preview-visibility.ts +0 -19
  216. package/src/components/viewer/floorplan-preview.tsx +0 -1065
  217. package/src/components/viewer/render-settings-menu.tsx +0 -294
  218. package/src/components/viewer/sky-control.tsx +0 -710
  219. package/src/components/viewer/use-viewer-camera-navigation-sync.ts +0 -140
  220. package/src/components/viewer/use-viewer-ui-sounds.test.ts +0 -15
  221. package/src/components/viewer/use-viewer-ui-sounds.ts +0 -46
  222. package/src/components/viewer/viewer-controls-bar.tsx +0 -496
  223. package/src/components/viewer/viewer-hover-label.tsx +0 -42
  224. package/src/components/viewer/viewer-rooms.tsx +0 -248
  225. package/src/components/viewer/viewer-scene-header.tsx +0 -286
  226. package/src/components/viewer/viewer-selection-manager.tsx +0 -124
  227. package/src/components/viewer/viewer-stage-modes.test.ts +0 -38
  228. package/src/components/viewer/viewer-stage-modes.ts +0 -49
  229. package/src/components/viewer/viewer-stage-switcher.tsx +0 -97
  230. package/src/components/viewer/viewer-stage.test.tsx +0 -47
  231. package/src/components/viewer/viewer-stage.tsx +0 -221
  232. package/src/components/walkthrough-hud.tsx +0 -193
  233. package/src/hooks/use-mobile.ts +0 -19
  234. package/src/i18n/level-name.ts +0 -39
  235. package/src/i18n/scene-theme-name.ts +0 -16
  236. package/src/lib/below-grade.ts +0 -133
  237. package/src/lib/camera-pose.test.ts +0 -237
  238. package/src/lib/camera-pose.ts +0 -172
  239. package/src/lib/floorplan/floorplan-extension.test.ts +0 -42
  240. package/src/lib/floorplan/floorplan-readonly.test.ts +0 -47
  241. package/src/lib/floorplan/floorplan-readonly.ts +0 -95
  242. package/src/lib/floorplan/marks.test.ts +0 -213
  243. package/src/lib/floorplan/marks.ts +0 -238
  244. package/src/lib/measurements.ts +0 -8
  245. package/src/lib/node-display-label.ts +0 -37
  246. package/src/lib/room-assembly-overlay.test.ts +0 -275
  247. package/src/lib/room-assembly-overlay.ts +0 -265
  248. package/src/lib/room-selection.ts +0 -417
  249. package/src/lib/scene-bounds.test.ts +0 -327
  250. package/src/lib/scene-bounds.ts +0 -233
  251. package/src/lib/typing-target.ts +0 -9
  252. package/src/lib/viewer-selection.ts +0 -595
  253. package/src/lib/zone-content.ts +0 -133
  254. package/src/store/camera-pose-store.test.ts +0 -29
  255. package/src/store/camera-pose-store.ts +0 -27
  256. package/src/store/navigation-sync-pose-store.test.ts +0 -34
  257. package/src/store/navigation-sync-pose-store.ts +0 -27
  258. package/src/store/use-audio.test.ts +0 -146
  259. package/src/store/use-audio.tsx +0 -169
  260. package/src/store/use-first-person-hud.ts +0 -40
  261. package/src/store/use-follow-pascal.test.ts +0 -62
  262. package/src/store/use-follow-pascal.ts +0 -53
@@ -30,7 +30,8 @@ import {
30
30
  useSpatialQuery,
31
31
  type WallEvent,
32
32
  } from '@pascal-app/core'
33
- import { useViewer } from '@pascal-app/viewer'
33
+ import { isTypingTarget, useViewer } from '@pascal-app/viewer'
34
+ import { LocalizedHtml as Html } from '@pascal-app/viewer/ui'
34
35
  import { useFrame, useThree } from '@react-three/fiber'
35
36
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
36
37
  import {
@@ -58,7 +59,6 @@ import {
58
59
  surfaceFramePose,
59
60
  updateSurfaceNode as writeSurfaceNode,
60
61
  } from '../../../lib/surface-attachment'
61
- import { isTypingTarget } from '../../../lib/typing-target'
62
62
  import { createWallPointerTracker } from '../../../lib/wall-placement-pointer'
63
63
  import {
64
64
  projectAlignmentGuidesWorldToActiveBuildingLocal,
@@ -73,7 +73,6 @@ import useEditor, {
73
73
  import useFacingPose from '../../../store/use-facing-pose'
74
74
  import { getMovingNode } from '../../../store/use-interaction-scope'
75
75
  import usePlacementPreview from '../../../store/use-placement-preview'
76
- import { Html } from '../../editor/localized-html'
77
76
  import {
78
77
  createItemSurfaceGridDispatch,
79
78
  createItemSurfacePointerArbitration,
@@ -10,7 +10,12 @@ import {
10
10
  type WallFace,
11
11
  type WallNode,
12
12
  } from '@pascal-app/core'
13
- import { getSceneTheme, setSurfaceRaycastLayers, useViewer } from '@pascal-app/viewer'
13
+ import {
14
+ getSceneTheme,
15
+ isTypingTarget,
16
+ setSurfaceRaycastLayers,
17
+ useViewer,
18
+ } from '@pascal-app/viewer'
14
19
  import { useFrame, useThree } from '@react-three/fiber'
15
20
  import { useEffect, useMemo, useRef } from 'react'
16
21
  import {
@@ -29,7 +34,6 @@ import { LineBasicNodeMaterial, MeshBasicNodeMaterial } from 'three/webgpu'
29
34
  import { markToolCancelConsumed } from '../../../hooks/use-keyboard'
30
35
  import { EDITOR_LAYER } from '../../../lib/constants'
31
36
  import { paintRegionTargets, usePaintRegionMode } from '../../../lib/paint-region-mode'
32
- import { isTypingTarget } from '../../../lib/typing-target'
33
37
  import {
34
38
  activeWallRegionGesture,
35
39
  activeWallRegionTarget,
@@ -38,7 +38,7 @@ import {
38
38
  useLiveTransforms,
39
39
  useScene,
40
40
  } from '@pascal-app/core'
41
- import { useViewer } from '@pascal-app/viewer'
41
+ import { isTypingTarget, useViewer } from '@pascal-app/viewer'
42
42
  import { useFrame, useThree } from '@react-three/fiber'
43
43
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
44
44
  import { type Group, Vector3 } from 'three'
@@ -61,7 +61,6 @@ import {
61
61
  surfaceAttachmentUpdates,
62
62
  updateSurfaceNode,
63
63
  } from '../../../lib/surface-attachment'
64
- import { isTypingTarget } from '../../../lib/typing-target'
65
64
  import useAlignmentGuides from '../../../store/use-alignment-guides'
66
65
  import useEditor, {
67
66
  getActiveSnappingMode,
@@ -1,4 +1,5 @@
1
1
  import { type MessageDescriptor, usePascalI18n } from '@pascal-app/core'
2
+ import { LocalizedHtml as Html } from '@pascal-app/viewer/ui'
2
3
  import type { ThreeElements } from '@react-three/fiber'
3
4
  import { forwardRef } from 'react'
4
5
  import { CircleGeometry, CylinderGeometry, type Group, SphereGeometry } from 'three'
@@ -8,7 +9,6 @@ import { EDITOR_LAYER } from '../../../lib/constants'
8
9
  import { wallCursorIcon } from '../../../lib/tool-cursor-icon'
9
10
  import useEditor from '../../../store/use-editor'
10
11
  import useWallSnapIndicator from '../../../store/use-wall-snap-indicator'
11
- import { Html } from '../../editor/localized-html'
12
12
 
13
13
  interface CursorSphereProps extends Omit<ThreeElements['group'], 'ref'> {
14
14
  color?: string
@@ -1,6 +1,6 @@
1
1
  'use client'
2
2
 
3
- import { Html } from '../../editor/localized-html'
3
+ import { LocalizedHtml as Html } from '@pascal-app/viewer/ui'
4
4
 
5
5
  /** Lift of a draft's readout above the top of what it measures, in metres. */
6
6
  export const DRAFT_LABEL_Y_OFFSET = 0.22
@@ -3,12 +3,12 @@
3
3
  import '../../../three-types'
4
4
 
5
5
  import { formatLinearMeasurement, type LinearUnit, type MetricNotation } from '@pascal-app/core'
6
+ import { LocalizedHtml as Html } from '@pascal-app/viewer/ui'
6
7
  import { useEffect, useMemo } from 'react'
7
8
  import { PlaneGeometry } from 'three'
8
9
  import { distance, smoothstep, uv, vec2 } from 'three/tsl'
9
10
  import { LineBasicNodeMaterial, MeshBasicNodeMaterial } from 'three/webgpu'
10
11
  import { EDITOR_LAYER } from '../../../lib/constants'
11
- import { Html } from '../../editor/localized-html'
12
12
  import { createLineGeometry, getBoxEdgePoints } from './placement-box-geometry'
13
13
 
14
14
  const VALID_COLOR = 0x22_c5_5e // green-500
@@ -1,13 +1,13 @@
1
1
  'use client'
2
2
 
3
3
  import { useViewer } from '@pascal-app/viewer'
4
+ import { LocalizedHtml as Html } from '@pascal-app/viewer/ui'
4
5
  import { useLayoutEffect, useMemo } from 'react'
5
6
  import { BufferGeometry, Float32BufferAttribute, Line as ThreeLine } from 'three'
6
7
  import { LineBasicNodeMaterial } from 'three/webgpu'
7
8
  import { EDITOR_LAYER } from '../../../lib/constants'
8
9
  import type { PlacementPreviewDimension } from '../../../store/use-placement-preview'
9
10
  import usePlacementPreview from '../../../store/use-placement-preview'
10
- import { Html } from '../../editor/localized-html'
11
11
  import { formatMeasurement } from '../../editor/measurement-pill'
12
12
 
13
13
  const DIMENSION_COLOR = 0x63_66_f1
@@ -10,6 +10,7 @@ import {
10
10
  useLiveTerrain,
11
11
  } from '@pascal-app/core'
12
12
  import { useViewer } from '@pascal-app/viewer'
13
+ import { LocalizedHtml as Html } from '@pascal-app/viewer/ui'
13
14
  import { useFrame, useThree } from '@react-three/fiber'
14
15
  import { type MutableRefObject, useEffect, useMemo, useRef } from 'react'
15
16
  import {
@@ -24,7 +25,6 @@ import { EDITOR_LAYER } from '../../../lib/constants'
24
25
  import { sculptFieldForSite, terrainPointInsideSite } from '../../../lib/terrain-sculpt'
25
26
  import { brushRingColor } from '../../../lib/terrain-verb-color'
26
27
  import useEditor from '../../../store/use-editor'
27
- import { Html } from '../../editor/localized-html'
28
28
  import { formatMeasurement } from '../../editor/measurement-pill'
29
29
 
30
30
  /** Segments in the cursor ring. 64 reads as a circle at any usable brush size. */
@@ -4,8 +4,8 @@ import { emitter, usePascalI18n } from '@pascal-app/core'
4
4
  import Image from 'next/image'
5
5
  import useEditor from '../../../store/use-editor'
6
6
  import { visibleScene } from '../../../store/view-layout'
7
- import { ActionButton } from './action-button'
8
- import { FollowPascalToggle } from './follow-pascal-toggle'
7
+ import { ActionButton } from '@pascal-app/viewer/ui'
8
+ import { FollowPascalToggle } from '@pascal-app/viewer/ui'
9
9
 
10
10
  export function CameraActions({ hideOrbit = false }: { hideOrbit?: boolean }) {
11
11
  const i18n = usePascalI18n()
@@ -9,7 +9,7 @@ import Image from 'next/image'
9
9
  import { Fragment } from 'react'
10
10
  import { cn } from './../../../lib/utils'
11
11
  import useEditor from './../../../store/use-editor'
12
- import { ActionButton } from './action-button'
12
+ import { ActionButton } from '@pascal-app/viewer/ui'
13
13
  import { MeasurementControl } from './measurement-control'
14
14
  import { PointAskButton } from './point-ask-button'
15
15
 
@@ -3,7 +3,7 @@
3
3
  import { usePascalI18n } from '@pascal-app/core'
4
4
  import { AnimatePresence, motion } from 'motion/react'
5
5
  import { useReducedMotion } from '../../../hooks/use-reduced-motion'
6
- import useFollowPascal from '../../../store/use-follow-pascal'
6
+ import { useFollowPascal } from '@pascal-app/viewer/ui'
7
7
 
8
8
  /**
9
9
  * Offered while a build plays and the person has the camera: one press and the camera goes back to
@@ -3,8 +3,8 @@
3
3
  import { useScene } from '@pascal-app/core'
4
4
  import { useViewer } from '@pascal-app/viewer'
5
5
  import { motion } from 'motion/react'
6
- import { TooltipProvider } from './../../../components/ui/primitives/tooltip'
7
- import { useIsMobile } from './../../../hooks/use-mobile'
6
+ import { TooltipProvider } from '@pascal-app/viewer/ui'
7
+ import { useIsMobile } from '@pascal-app/viewer/ui'
8
8
  import { useReducedMotion } from './../../../hooks/use-reduced-motion'
9
9
  import { shouldShowEditingControls } from './../../../lib/interaction/overlay-policy'
10
10
  import { cn } from './../../../lib/utils'
@@ -12,7 +12,7 @@ import useEditor from './../../../store/use-editor'
12
12
  import { CameraActions } from './camera-actions'
13
13
  import { ControlModes } from './control-modes'
14
14
  import { FollowPascalPill } from './follow-pascal-pill'
15
- import { type ActionMenuPlacement, ActionMenuPlacementProvider } from './placement'
15
+ import { type ActionMenuPlacement, ActionMenuPlacementProvider } from '@pascal-app/viewer/ui'
16
16
  import { SecondaryToggles } from './view-toggles'
17
17
 
18
18
  // Mobile bottom offset matches the viewer's overlap behind the sheet's
@@ -27,9 +27,9 @@ import { cn } from '../../../lib/utils'
27
27
  import useEditor from '../../../store/use-editor'
28
28
  import { VIEW_2D } from '../../../store/view-layout'
29
29
  import useFloorplanMode from '../../../store/use-floorplan-mode'
30
- import { Popover, PopoverContent, PopoverTrigger } from '../primitives/popover'
31
- import { ActionButton } from './action-button'
32
- import { useActionMenuPopupSide } from './placement'
30
+ import { Popover, PopoverContent, PopoverTrigger } from '@pascal-app/viewer/ui'
31
+ import { ActionButton } from '@pascal-app/viewer/ui'
32
+ import { useActionMenuPopupSide } from '@pascal-app/viewer/ui'
33
33
 
34
34
  const measurementOptions = [
35
35
  { kind: 'distance', label: /* i18n */ { id: 'editor.actionMenu.measurementControl.distance', message: 'Distance' }, icon: Ruler },
@@ -1,20 +1,2 @@
1
- import { createContext, useContext } from 'react'
2
-
3
- /** Viewport edge the action menu docks to. */
4
- export type ActionMenuPlacement = 'bottom' | 'top'
5
-
6
1
  /** Where chrome under a top-docked menu starts: below the host toolbar row and the menu itself. */
7
2
  export const TOP_MENU_CLEARANCE = '7.25rem'
8
-
9
- const ActionMenuPlacementContext = createContext<ActionMenuPlacement>('bottom')
10
-
11
- export const ActionMenuPlacementProvider = ActionMenuPlacementContext.Provider
12
-
13
- export function useActionMenuPlacement(): ActionMenuPlacement {
14
- return useContext(ActionMenuPlacementContext)
15
- }
16
-
17
- /** Side tooltips and popovers open toward, away from the docked edge. */
18
- export function useActionMenuPopupSide(): 'top' | 'bottom' {
19
- return useActionMenuPlacement() === 'top' ? 'bottom' : 'top'
20
- }
@@ -6,7 +6,7 @@ import { cn } from '../../../lib/utils'
6
6
  import useEditor from '../../../store/use-editor'
7
7
  import { usePointAsk } from '../../../store/use-point-ask'
8
8
  import { isViewVisible, VIEW_3D } from '../../../store/view-layout'
9
- import { ActionButton } from './action-button'
9
+ import { ActionButton } from '@pascal-app/viewer/ui'
10
10
 
11
11
  /**
12
12
  * Point and ask (key C): the toolbar's way into the mode where hovering names what Pascal would
@@ -35,11 +35,11 @@ import {
35
35
  useWallsBelowSetting,
36
36
  } from '../../editor-2d/floorplan-adjacent-walls-layer'
37
37
  import { SliderControl } from '../controls/slider-control'
38
- import { Popover, PopoverContent, PopoverTrigger } from '../primitives/popover'
39
- import { Switch } from '../primitives/switch'
40
- import { ActionButton } from './action-button'
41
- import { useActionMenuPopupSide } from './placement'
42
- import { localizedLevelName } from '../../../i18n/level-name'
38
+ import { Popover, PopoverContent, PopoverTrigger } from '@pascal-app/viewer/ui'
39
+ import { Switch } from '@pascal-app/viewer/ui'
40
+ import { ActionButton } from '@pascal-app/viewer/ui'
41
+ import { useActionMenuPopupSide } from '@pascal-app/viewer/ui'
42
+ import { localizedLevelName } from '@pascal-app/viewer/ui'
43
43
 
44
44
  const MAX_FILE_SIZE = 200 * 1024 * 1024 // 200MB
45
45
  const ACCEPTED_FILE_TYPES = '.glb,.gltf,image/jpeg,image/png,image/webp,image/gif'
@@ -13,7 +13,7 @@ import {
13
13
  } from '@pascal-app/core'
14
14
  import { useState } from 'react'
15
15
  import { materialSwatchStyle } from '../../../lib/material-swatch-style'
16
- import { Popover, PopoverContent, PopoverTrigger } from '../primitives/popover'
16
+ import { Popover, PopoverContent, PopoverTrigger } from '@pascal-app/viewer/ui'
17
17
  import { MaterialPicker } from './material-picker'
18
18
 
19
19
  type Swatch = { label: string; color: string | null; image: string | null; tinted?: boolean }
@@ -6,8 +6,8 @@ import { useState } from 'react'
6
6
  import { useMaterialPaintPanelModel } from '../../../lib/material-paint-panel-model'
7
7
  import { type PaintMode, usePaintRegionMode } from '../../../lib/paint-region-mode'
8
8
  import useEditor, { armMaterialPaint } from '../../../store/use-editor'
9
- import { Button } from '../primitives/button'
10
- import { Tooltip, TooltipContent, TooltipTrigger } from '../primitives/tooltip'
9
+ import { Button } from '@pascal-app/viewer/ui'
10
+ import { Tooltip, TooltipContent, TooltipTrigger } from '@pascal-app/viewer/ui'
11
11
  import { MaterialPicker } from './material-picker'
12
12
  import { SceneMaterialList } from './scene-material-list'
13
13
  import { SegmentedControl } from './segmented-control'
@@ -12,9 +12,9 @@ import { Copy, Paintbrush, Pencil, Trash2 } from 'lucide-react'
12
12
  import { useEffect, useMemo, useState } from 'react'
13
13
  import { sceneMaterialUsageCounts } from '../../../lib/scene-material-refs'
14
14
  import useEditor from '../../../store/use-editor'
15
- import { Button } from '../primitives/button'
15
+ import { Button } from '@pascal-app/viewer/ui'
16
16
  import { Input } from '../primitives/input'
17
- import { Tooltip, TooltipContent, TooltipTrigger } from '../primitives/tooltip'
17
+ import { Tooltip, TooltipContent, TooltipTrigger } from '@pascal-app/viewer/ui'
18
18
  import { MaterialPropertiesEditor } from './material-properties-editor'
19
19
 
20
20
  export function SceneMaterialList({ autoEditId }: { autoEditId?: SceneMaterialId | null }) {
@@ -8,7 +8,7 @@ import {
8
8
  DropdownMenuRadioGroup,
9
9
  DropdownMenuRadioItem,
10
10
  DropdownMenuTrigger,
11
- } from '../primitives/dropdown-menu'
11
+ } from '@pascal-app/viewer/ui'
12
12
 
13
13
  interface SelectControlProps<T extends string> {
14
14
  label: string
@@ -10,7 +10,7 @@ import {
10
10
  import { Mountain, Pipette } from 'lucide-react'
11
11
  import { brushRadiusRange, flattenSite, resetSiteTerrain } from '../../../lib/terrain-sculpt'
12
12
  import useEditor from '../../../store/use-editor'
13
- import { Button } from '../primitives/button'
13
+ import { Button } from '@pascal-app/viewer/ui'
14
14
  import { SegmentedControl } from './segmented-control'
15
15
  import { SliderControl } from './slider-control'
16
16
 
@@ -61,14 +61,14 @@ import {
61
61
  useLocale,
62
62
  usePascalI18n,
63
63
  } from '@pascal-app/core'
64
- import { authoredLevelName, localizedLevelName } from '../../i18n/level-name'
64
+ import { authoredLevelName, localizedLevelName } from '@pascal-app/viewer/ui'
65
65
  import { messageWithSlot } from '../../i18n/message-slot'
66
66
  import { addStoreyBelow, addStoreyOnTop, setGroundFloor } from '../../lib/add-storey'
67
67
  import { deleteLevelWithFallbackSelection } from '../../lib/level-selection'
68
68
  import { unitMemberLevels, leaveUnitFocus } from '../../lib/units'
69
69
  import { useLinearDisplay } from '../../lib/use-linear-display'
70
70
  import { cn } from '../../lib/utils'
71
- import { useIsMobile } from '../../hooks/use-mobile'
71
+ import { useIsMobile } from '@pascal-app/viewer/ui'
72
72
  import { ActionButton } from './controls/action-button'
73
73
  import { SliderControl } from './controls/slider-control'
74
74
  import { LevelDuplicateDialog } from './level-duplicate-dialog'
@@ -81,7 +81,7 @@ import {
81
81
  DialogHeader,
82
82
  DialogTitle,
83
83
  } from './primitives/dialog'
84
- import { Popover, PopoverContent, PopoverTrigger } from './primitives/popover'
84
+ import { Popover, PopoverContent, PopoverTrigger } from '@pascal-app/viewer/ui'
85
85
 
86
86
  // ── Inline rename input for a level row ─────────────────────────────────────
87
87
 
@@ -23,7 +23,7 @@ import useEditor, { type GridSnapStep } from '../../../store/use-editor'
23
23
  import useFenceCurveDraft from '../../../store/use-fence-curve-draft'
24
24
  import { IconRefGlyph } from '../icon-ref'
25
25
  import { ShortcutToken } from '../primitives/shortcut-token'
26
- import { Tooltip, TooltipContent, TooltipTrigger } from '../primitives/tooltip'
26
+ import { Tooltip, TooltipContent, TooltipTrigger } from '@pascal-app/viewer/ui'
27
27
  import { useInRightStack } from '../right-stack'
28
28
 
29
29
  // One muted container holds every row — passive key hints and interactive chips
@@ -8,7 +8,7 @@ import {
8
8
  import { SELECT_HUD_TITLE, toolHudTitle } from '../../../lib/hud-title'
9
9
  import { snapContextOf } from '../../../lib/snapping-mode'
10
10
  import { cornerHintRows } from '../../../store/use-corner-snap-hint'
11
- import { TooltipProvider } from '../primitives/tooltip'
11
+ import { TooltipProvider } from '@pascal-app/viewer/ui'
12
12
  import { ContextualHelperPanel } from './contextual-helper-panel'
13
13
  import {
14
14
  mepHandleGesture,
@@ -11,7 +11,7 @@ import {
11
11
  import { useViewer } from '@pascal-app/viewer'
12
12
  import { useEffect, useMemo, useState, useSyncExternalStore } from 'react'
13
13
  import { useShallow } from 'zustand/react/shallow'
14
- import { useIsMobile } from '../../../hooks/use-mobile'
14
+ import { useIsMobile } from '@pascal-app/viewer/ui'
15
15
  import {
16
16
  AXIS_MOVE_DRAG_LABEL,
17
17
  type ContextualShortcutHint,
@@ -4,7 +4,7 @@ import type { LevelNode, MessageDescriptor } from '@pascal-app/core'
4
4
  import { useEffect, useState } from 'react'
5
5
  import type { LevelDuplicatePreset } from '@pascal-app/core/building'
6
6
  import { useLocale, usePascalI18n } from '@pascal-app/core'
7
- import { localizedLevelName } from '../../i18n/level-name'
7
+ import { localizedLevelName } from '@pascal-app/viewer/ui'
8
8
  import { cn } from '../../lib/utils'
9
9
  import {
10
10
  Dialog,
@@ -0,0 +1,46 @@
1
+ import { describe, expect, test } from 'bun:test'
2
+ import { imageConfigDefault } from 'next/dist/shared/lib/image-config'
3
+ import { ImageConfigContext } from 'next/dist/shared/lib/image-config-context.shared-runtime'
4
+ import { renderToStaticMarkup } from 'react-dom/server'
5
+ import { canOptimizeImageSrc, NodeIconImage } from './node-icon-image'
6
+
7
+ const config = {
8
+ ...imageConfigDefault,
9
+ remotePatterns: [{ protocol: 'https' as const, hostname: 'assets.example.com' }],
10
+ }
11
+
12
+ const render = (src: string) =>
13
+ renderToStaticMarkup(
14
+ <ImageConfigContext.Provider value={config}>
15
+ <NodeIconImage alt="" height={16} src={src} width={16} />
16
+ </ImageConfigContext.Provider>,
17
+ )
18
+
19
+ describe('canOptimizeImageSrc', () => {
20
+ test('optimizes site-relative paths and configured hosts', () => {
21
+ expect(canOptimizeImageSrc('/icons/item.png', config)).toBe(true)
22
+ expect(canOptimizeImageSrc('https://assets.example.com/thumb.webp', config)).toBe(true)
23
+ })
24
+
25
+ test('does not optimize hosts missing from remotePatterns', () => {
26
+ expect(canOptimizeImageSrc('https://prod.supabase.co/storage/thumb.webp', config)).toBe(false)
27
+ expect(canOptimizeImageSrc('//prod.supabase.co/thumb.webp', config)).toBe(false)
28
+ })
29
+
30
+ test('keeps optimizing when the config carries no host lists, as in production builds', () => {
31
+ expect(canOptimizeImageSrc('https://prod.supabase.co/storage/thumb.webp', {})).toBe(true)
32
+ })
33
+ })
34
+
35
+ describe('NodeIconImage', () => {
36
+ test('renders an unconfigured host straight from its URL', () => {
37
+ const src = 'https://prod.supabase.co/storage/v1/object/public/items/thumb.webp'
38
+ const html = render(src)
39
+ expect(html).toContain(`src="${src}"`)
40
+ expect(html).not.toContain('/_next/image')
41
+ })
42
+
43
+ test('still optimizes a configured host', () => {
44
+ expect(render('https://assets.example.com/thumb.webp')).toContain('/_next/image?url=')
45
+ })
46
+ })
@@ -1,7 +1,35 @@
1
1
  'use client'
2
2
 
3
3
  import { ARTIFACT_URL_PREFIX, resolveArtifactUrl } from '@pascal-app/core'
4
+ import { type ImageConfigComplete, imageConfigDefault } from 'next/dist/shared/lib/image-config'
5
+ import { ImageConfigContext } from 'next/dist/shared/lib/image-config-context.shared-runtime'
6
+ import { hasRemoteMatch } from 'next/dist/shared/lib/match-remote-pattern'
4
7
  import Image, { type ImageProps } from 'next/image'
8
+ import { useContext } from 'react'
9
+
10
+ type ImageHostConfig = Partial<Pick<ImageConfigComplete, 'domains' | 'remotePatterns'>>
11
+
12
+ // Inlined by Next's bundler define, as next/image itself reads it.
13
+ const configEnv = process.env.__NEXT_IMAGE_OPTS as unknown as ImageHostConfig | undefined
14
+
15
+ /**
16
+ * Whether next/image can optimize `src`. An absolute URL on a host missing
17
+ * from `images.remotePatterns` makes next/image throw during render (e.g. a
18
+ * catalog thumbnail on production storage while running against local
19
+ * Supabase), so those render unoptimized, straight from their host.
20
+ */
21
+ export function canOptimizeImageSrc(src: string, config: ImageHostConfig): boolean {
22
+ if (src.startsWith('/') && !src.startsWith('//')) return true
23
+ // Production builds inline no host lists, and next/image validates none then.
24
+ if (!config.domains && !config.remotePatterns) return true
25
+ let url: URL
26
+ try {
27
+ url = new URL(src)
28
+ } catch {
29
+ return false
30
+ }
31
+ return hasRemoteMatch(config.domains ?? [], config.remotePatterns ?? [], url)
32
+ }
5
33
 
6
34
  /**
7
35
  * A node's icon or thumbnail. A scripted object's thumbnail is an
@@ -10,7 +38,11 @@ import Image, { type ImageProps } from 'next/image'
10
38
  * private project's artifact with.
11
39
  */
12
40
  export function NodeIconImage({ src, ...props }: Omit<ImageProps, 'src'> & { src: string }) {
13
- if (!src.startsWith(ARTIFACT_URL_PREFIX)) return <Image src={src} {...props} />
41
+ const configContext = useContext(ImageConfigContext)
42
+ const config = configEnv || configContext || imageConfigDefault
43
+ if (!src.startsWith(ARTIFACT_URL_PREFIX)) {
44
+ return <Image src={src} unoptimized={!canOptimizeImageSrc(src, config)} {...props} />
45
+ }
14
46
  const url = resolveArtifactUrl(src)
15
47
  return url ? <Image src={url} unoptimized {...props} /> : null
16
48
  }
@@ -21,12 +21,12 @@ import {
21
21
  DropdownMenuContent,
22
22
  DropdownMenuItem,
23
23
  DropdownMenuTrigger,
24
- } from '../../../../components/ui/primitives/dropdown-menu'
24
+ } from '@pascal-app/viewer/ui'
25
25
  import {
26
26
  Popover,
27
27
  PopoverContent,
28
28
  PopoverTrigger,
29
- } from '../../../../components/ui/primitives/popover'
29
+ } from '@pascal-app/viewer/ui'
30
30
  import { cn } from '../../../../lib/utils'
31
31
 
32
32
  interface CollectionsPopoverProps {
@@ -19,7 +19,7 @@ import {
19
19
  } from '@pascal-app/core'
20
20
  import { useViewer } from '@pascal-app/viewer'
21
21
  import { localizedFloorFootprintName } from '../../../i18n/floor-footprint-name'
22
- import { localizedLevelName } from '../../../i18n/level-name'
22
+ import { localizedLevelName } from '@pascal-app/viewer/ui'
23
23
  import { useRef, useState } from 'react'
24
24
  import {
25
25
  applyFloorFoundation,
@@ -40,7 +40,7 @@ import { formatLinearMeasurement } from '@pascal-app/core'
40
40
  import { FinishSwatch } from '../controls/finish-swatch'
41
41
  import { MetricControl } from '../controls/metric-control'
42
42
  import { SegmentedControl } from '../controls/segmented-control'
43
- import { Button } from '../primitives/button'
43
+ import { Button } from '@pascal-app/viewer/ui'
44
44
  import { PanelWrapper } from './panel-wrapper'
45
45
 
46
46
  /** Unpainted finishes, as the plate renders them (nodes' slab slot defaults). */
@@ -15,12 +15,12 @@ import {
15
15
  openingRoom,
16
16
  } from '../../../lib/floor-edit-session'
17
17
  import { formatAreaLabel } from '@pascal-app/core'
18
- import { Button } from '../primitives/button'
19
- import { Switch } from '../primitives/switch'
18
+ import { Button } from '@pascal-app/viewer/ui'
19
+ import { Switch } from '@pascal-app/viewer/ui'
20
20
  import { PanelWrapper } from './panel-wrapper'
21
- import { localizedLevelName } from '../../../i18n/level-name'
21
+ import { localizedLevelName } from '@pascal-app/viewer/ui'
22
22
  import { nodeLabel } from '../../../i18n/node-messages'
23
- import { displayRoomName } from '../../../lib/room-name-messages'
23
+ import { displayRoomName } from '@pascal-app/viewer/ui'
24
24
 
25
25
  /**
26
26
  * A floor (or ceiling) opening: where it is, what it cuts, and the switch for
@@ -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
@@ -28,7 +28,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'
28
28
  import { useSelectedRoom, useZoneRoom } from '../../../hooks/use-selected-room'
29
29
  import { FloorOpeningPanel } from './floor-opening-panel'
30
30
  import { OpenRoomPanel, RoomPanel } from './room-panel'
31
- import { useIsMobile } from '../../../hooks/use-mobile'
31
+ import { useIsMobile } from '@pascal-app/viewer/ui'
32
32
  import { shouldShowEditingControls } from '../../../lib/interaction/overlay-policy'
33
33
  import { captureElementActionOrigin, completeElementAction } from '../../../lib/room-zone-routing'
34
34
  import { sfxEmitter } from '../../../lib/sfx-bus'
@@ -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'
@@ -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'
@@ -36,7 +36,7 @@ import {
36
36
  } from '../../../lib/floor-footprints'
37
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) {