@pascal-app/editor 1.1.0 → 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 (260) 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/panels/collections/collections-popover.tsx +2 -2
  84. package/src/components/ui/panels/floor-foundation-panel.tsx +2 -2
  85. package/src/components/ui/panels/floor-opening-panel.tsx +4 -4
  86. package/src/components/ui/panels/node-display.ts +1 -1
  87. package/src/components/ui/panels/panel-manager.tsx +1 -1
  88. package/src/components/ui/panels/panel-wrapper.tsx +1 -1
  89. package/src/components/ui/panels/parametric-inspector.tsx +1 -1
  90. package/src/components/ui/panels/room-construction-rows.tsx +6 -6
  91. package/src/components/ui/panels/room-name-options.ts +1 -5
  92. package/src/components/ui/panels/room-panel.tsx +6 -8
  93. package/src/components/ui/primitives/color-dot.tsx +2 -2
  94. package/src/components/ui/primitives/opacity-control.tsx +2 -2
  95. package/src/components/ui/primitives/sidebar.tsx +3 -3
  96. package/src/components/ui/right-stack.tsx +1 -1
  97. package/src/components/ui/sidebar/icon-rail.tsx +1 -1
  98. package/src/components/ui/sidebar/panels/items-panel/function-tree-panel.tsx +1 -1
  99. package/src/components/ui/sidebar/panels/settings-panel/audio-settings-dialog.tsx +2 -2
  100. package/src/components/ui/sidebar/panels/settings-panel/construction-animation-setting.tsx +1 -1
  101. package/src/components/ui/sidebar/panels/settings-panel/index.tsx +2 -2
  102. package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +1 -1
  103. package/src/components/ui/sidebar/panels/settings-panel/load-build-dialog.tsx +1 -1
  104. package/src/components/ui/sidebar/panels/settings-panel/print-export-button.tsx +1 -1
  105. package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +1 -1
  106. package/src/components/ui/sidebar/panels/site-panel/index.tsx +2 -2
  107. package/src/components/ui/sidebar/panels/site-panel/inline-rename-input.tsx +1 -1
  108. package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +1 -1
  109. package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +46 -7
  110. package/src/components/ui/sidebar/panels/site-panel/tree-node-actions.tsx +1 -1
  111. package/src/components/ui/sidebar/panels/site-panel/tree-node-drag.tsx +14 -5
  112. package/src/components/ui/sidebar/panels/site-panel/unit-tree-node.tsx +2 -2
  113. package/src/components/ui/sidebar/panels/zone-panel/index.tsx +3 -3
  114. package/src/components/ui/sidebar/tab-bar.tsx +1 -1
  115. package/src/components/ui/wall-type/wall-type-editor-dialog.tsx +1 -1
  116. package/src/components/ui/wall-type/wall-type-menu.tsx +1 -1
  117. package/src/components/viewer-overlay.tsx +1 -2
  118. package/src/hooks/use-auto-frame.ts +1 -2
  119. package/src/hooks/use-keyboard.ts +1 -2
  120. package/src/hooks/use-selected-room.ts +5 -7
  121. package/src/i18n/floor-footprint-name.ts +1 -1
  122. package/src/i18n/locales/en/messages.po +180 -182
  123. package/src/i18n/locales/es/messages.po +180 -182
  124. package/src/i18n/locales/fr/messages.po +180 -182
  125. package/src/i18n/locales/ja/messages.po +180 -182
  126. package/src/i18n/locales/zh-CN/messages.po +180 -182
  127. package/src/i18n/locales.test.ts +1 -1
  128. package/src/index.tsx +109 -131
  129. package/src/lib/below-grade.test.tsx +4 -4
  130. package/src/lib/camera-facing.test.ts +1 -1
  131. package/src/lib/camera-facing.ts +2 -3
  132. package/src/lib/editor-level-display.ts +1 -1
  133. package/src/lib/floor-footprints.test.ts +2 -2
  134. package/src/lib/floor-opening-draft.ts +1 -1
  135. package/src/lib/floorplan/annotation-visibility.test.ts +1 -1
  136. package/src/lib/floorplan/annotation-visibility.ts +1 -1
  137. package/src/lib/floorplan/floorplan-export.test.ts +1 -1
  138. package/src/lib/floorplan/floorplan-export.tsx +8 -11
  139. package/src/lib/floorplan/floorplan-extension.ts +4 -157
  140. package/src/lib/floorplan/floorplan-mode.ts +2 -1
  141. package/src/lib/floorplan/floorplan-pdfkit-renderer.test.ts +1 -1
  142. package/src/lib/floorplan/floorplan-pdfkit-renderer.ts +8 -6
  143. package/src/lib/floorplan/floorplan-plugin-install.test.tsx +3 -4
  144. package/src/lib/floorplan/geometry.ts +2 -112
  145. package/src/lib/floorplan/index.ts +0 -9
  146. package/src/lib/floorplan/items.ts +2 -1
  147. package/src/lib/floorplan/schedules.ts +6 -3
  148. package/src/lib/floorplan/sheet-export.ts +7 -3
  149. package/src/lib/floorplan/site-plan/site-parts.ts +7 -1
  150. package/src/lib/floorplan/site-plan/site-plan-layer.tsx +1 -1
  151. package/src/lib/follow-pascal-presentation.ts +1 -1
  152. package/src/lib/glb-export.ts +1 -1
  153. package/src/lib/material-paint.ts +1 -1
  154. package/src/lib/measurements.test.ts +2 -1
  155. package/src/lib/mezzanine-selection.test.ts +1 -1
  156. package/src/lib/paint-region-mode.ts +1 -1
  157. package/src/lib/point-ask/session.ts +1 -2
  158. package/src/lib/roof-duplication.test.ts +100 -0
  159. package/src/lib/roof-duplication.ts +30 -5
  160. package/src/lib/room-handle-drag.ts +2 -12
  161. package/src/lib/room-name-catalog.test.ts +2 -1
  162. package/src/lib/room-name-messages.test.ts +2 -1
  163. package/src/lib/room-name-messages.ts +1 -118
  164. package/src/lib/room-name-storage.test.ts +2 -1
  165. package/src/lib/room-selection-commands.ts +2 -2
  166. package/src/lib/room-selection.test.ts +6 -6
  167. package/src/lib/room-transform-session.ts +1 -2
  168. package/src/lib/room-zone-routing.ts +2 -2
  169. package/src/lib/selection-routing.test.ts +0 -28
  170. package/src/lib/selection-routing.ts +1 -40
  171. package/src/lib/sfx-bus.ts +8 -32
  172. package/src/lib/sfx-player.test.ts +72 -1
  173. package/src/lib/sfx-player.ts +49 -337
  174. package/src/lib/viewer-selection.test.ts +38 -10
  175. package/src/lib/wall-pull.test.ts +1 -1
  176. package/src/lib/wall-pull.ts +1 -27
  177. package/src/store/use-editor.tsx +17 -26
  178. package/src/store/use-floorplan-annotation-visibility.ts +5 -5
  179. package/src/store/use-wall-region-handles-selection.ts +1 -2
  180. package/src/components/editor/__bench__/room-label-placement.bench.ts +0 -108
  181. package/src/components/editor/first-person/build-collider-world.test.ts +0 -596
  182. package/src/components/editor/first-person/build-collider-world.ts +0 -549
  183. package/src/components/editor/first-person/ground-holes.test.ts +0 -128
  184. package/src/components/editor/first-person/ground-holes.ts +0 -130
  185. package/src/components/editor/first-person/mechanism-targets.test.ts +0 -162
  186. package/src/components/editor/first-person/mechanism-targets.ts +0 -88
  187. package/src/components/editor/first-person/terrain-collider.test.ts +0 -132
  188. package/src/components/editor/first-person/terrain-collider.ts +0 -212
  189. package/src/components/editor/floorplan-camera-sync.test.ts +0 -249
  190. package/src/components/editor/floorplan-camera-sync.ts +0 -213
  191. package/src/components/editor/localized-html.tsx +0 -22
  192. package/src/components/editor-2d/renderers/floorplan-dimension-renderer.test.tsx +0 -236
  193. package/src/components/editor-2d/renderers/floorplan-dimension-renderer.tsx +0 -708
  194. package/src/components/editor-2d/renderers/floorplan-geometry-renderer.test.tsx +0 -385
  195. package/src/components/editor-2d/renderers/floorplan-geometry-renderer.tsx +0 -670
  196. package/src/components/editor-2d/renderers/floorplan-label-angle.test.ts +0 -89
  197. package/src/components/editor-2d/renderers/floorplan-label-angle.ts +0 -106
  198. package/src/components/editor-2d/svg-paths.ts +0 -124
  199. package/src/components/ui/action-menu/action-button.tsx +0 -89
  200. package/src/components/ui/action-menu/follow-pascal-toggle.tsx +0 -42
  201. package/src/components/ui/primitives/button.tsx +0 -69
  202. package/src/components/ui/primitives/dropdown-menu.tsx +0 -232
  203. package/src/components/ui/primitives/popover.tsx +0 -42
  204. package/src/components/ui/primitives/switch.tsx +0 -29
  205. package/src/components/ui/primitives/tooltip.tsx +0 -57
  206. package/src/components/ui/scene-loader.tsx +0 -73
  207. package/src/components/viewer/floorplan-compass-button.tsx +0 -67
  208. package/src/components/viewer/floorplan-preview-geometry.test.ts +0 -107
  209. package/src/components/viewer/floorplan-preview-geometry.ts +0 -281
  210. package/src/components/viewer/floorplan-preview-navigation.test.ts +0 -43
  211. package/src/components/viewer/floorplan-preview-navigation.ts +0 -62
  212. package/src/components/viewer/floorplan-preview-visibility.test.ts +0 -35
  213. package/src/components/viewer/floorplan-preview-visibility.ts +0 -19
  214. package/src/components/viewer/floorplan-preview.tsx +0 -1065
  215. package/src/components/viewer/render-settings-menu.tsx +0 -294
  216. package/src/components/viewer/sky-control.tsx +0 -710
  217. package/src/components/viewer/use-viewer-camera-navigation-sync.ts +0 -140
  218. package/src/components/viewer/use-viewer-ui-sounds.test.ts +0 -15
  219. package/src/components/viewer/use-viewer-ui-sounds.ts +0 -46
  220. package/src/components/viewer/viewer-controls-bar.tsx +0 -496
  221. package/src/components/viewer/viewer-hover-label.tsx +0 -42
  222. package/src/components/viewer/viewer-rooms.tsx +0 -248
  223. package/src/components/viewer/viewer-scene-header.tsx +0 -286
  224. package/src/components/viewer/viewer-selection-manager.tsx +0 -124
  225. package/src/components/viewer/viewer-stage-modes.test.ts +0 -38
  226. package/src/components/viewer/viewer-stage-modes.ts +0 -49
  227. package/src/components/viewer/viewer-stage-switcher.tsx +0 -97
  228. package/src/components/viewer/viewer-stage.test.tsx +0 -47
  229. package/src/components/viewer/viewer-stage.tsx +0 -221
  230. package/src/components/walkthrough-hud.tsx +0 -193
  231. package/src/hooks/use-mobile.ts +0 -19
  232. package/src/i18n/level-name.ts +0 -39
  233. package/src/i18n/scene-theme-name.ts +0 -16
  234. package/src/lib/below-grade.ts +0 -133
  235. package/src/lib/camera-pose.test.ts +0 -237
  236. package/src/lib/camera-pose.ts +0 -172
  237. package/src/lib/floorplan/floorplan-extension.test.ts +0 -42
  238. package/src/lib/floorplan/floorplan-readonly.test.ts +0 -47
  239. package/src/lib/floorplan/floorplan-readonly.ts +0 -95
  240. package/src/lib/floorplan/marks.test.ts +0 -213
  241. package/src/lib/floorplan/marks.ts +0 -238
  242. package/src/lib/measurements.ts +0 -8
  243. package/src/lib/node-display-label.ts +0 -37
  244. package/src/lib/room-assembly-overlay.test.ts +0 -275
  245. package/src/lib/room-assembly-overlay.ts +0 -265
  246. package/src/lib/room-selection.ts +0 -417
  247. package/src/lib/scene-bounds.test.ts +0 -327
  248. package/src/lib/scene-bounds.ts +0 -233
  249. package/src/lib/typing-target.ts +0 -9
  250. package/src/lib/viewer-selection.ts +0 -595
  251. package/src/lib/zone-content.ts +0 -133
  252. package/src/store/camera-pose-store.test.ts +0 -29
  253. package/src/store/camera-pose-store.ts +0 -27
  254. package/src/store/navigation-sync-pose-store.test.ts +0 -34
  255. package/src/store/navigation-sync-pose-store.ts +0 -27
  256. package/src/store/use-audio.test.ts +0 -146
  257. package/src/store/use-audio.tsx +0 -169
  258. package/src/store/use-first-person-hud.ts +0 -40
  259. package/src/store/use-follow-pascal.test.ts +0 -62
  260. package/src/store/use-follow-pascal.ts +0 -53
@@ -6,7 +6,7 @@ import { readFileSync } from 'node:fs'
6
6
  // draft instead, so it only has to stay clear of drei fat lines.
7
7
  for (const [file, drawsLines] of [
8
8
  ['./room-controls.tsx', false],
9
- ['./room-highlight.tsx', true],
9
+ ['../../../../viewer/src/ui/components/rooms/room-highlight.tsx', true],
10
10
  ['../../../../nodes/src/separator/renderer.tsx', true],
11
11
  ] as const) {
12
12
  test(`${file} uses WebGPU node materials instead of drei fat lines`, () => {
@@ -35,6 +35,11 @@ import {
35
35
  tintEmissive,
36
36
  useViewer,
37
37
  } from '@pascal-app/viewer'
38
+ import {
39
+ type SelectionModifierKeys,
40
+ sameRoom,
41
+ selectionModifiersFromEvent,
42
+ } from '@pascal-app/viewer/ui'
38
43
  import { useThree } from '@react-three/fiber'
39
44
  import { useCallback, useEffect, useRef } from 'react'
40
45
  import { type BufferGeometry, Color, type Material, type Mesh, type Object3D, Vector3 } from 'three'
@@ -105,7 +110,6 @@ import {
105
110
  usePaintOutline,
106
111
  } from '../../lib/plate-paint-affected'
107
112
  import { getHoveredRoofSegmentOutlineProxy } from '../../lib/roof-hover-outline-proxy'
108
- import { sameRoom } from '../../lib/room-selection'
109
113
  import { selectRoom, shouldInterceptRoom } from '../../lib/room-selection-commands'
110
114
  import { roomKeyForZone } from '../../lib/room-zone-routing'
111
115
  import {
@@ -114,8 +118,6 @@ import {
114
118
  resolveCanvasBuildingId,
115
119
  resolveCanvasSelectionNode,
116
120
  resolveSelectedIdsForNodeClick,
117
- type SelectionModifierKeys,
118
- selectionModifiersFromEvent,
119
121
  shouldPreserveSelectedRoofHostTarget,
120
122
  } from '../../lib/selection-routing'
121
123
  import { emitDeleteSFX, sfxEmitter } from '../../lib/sfx-bus'
@@ -8,13 +8,13 @@ import {
8
8
  useScene,
9
9
  } from '@pascal-app/core'
10
10
  import { getSceneTheme, useViewer } from '@pascal-app/viewer'
11
+ import { LocalizedHtml as Html } from '@pascal-app/viewer/ui'
11
12
  import { createPortal, useFrame, useThree } from '@react-three/fiber'
12
13
  import { useCallback, useMemo, useRef, useState } from 'react'
13
14
  import { type Camera, type Object3D, Vector3 } from 'three'
14
15
  import { groundHeightAt } from '../../lib/ground-surface'
15
16
  import { SITE_BOUNDARY_DRAG_LABEL } from '../../lib/site-boundary'
16
17
  import { useActiveHandleDrag } from '../../store/use-interaction-scope'
17
- import { Html } from './localized-html'
18
18
 
19
19
  type ViewportSize = {
20
20
  width: number
@@ -1,7 +1,8 @@
1
1
  'use client'
2
2
 
3
3
  import { emitter, type SnapshotSavedEvent } from '@pascal-app/core'
4
- import { SNAPSHOT_MAX_EDGE } from '@pascal-app/viewer'
4
+ import { isTypingTarget, SNAPSHOT_MAX_EDGE } from '@pascal-app/viewer'
5
+ import { useFirstPersonHud, useIsMobile, WalkthroughCrosshair } from '@pascal-app/viewer/ui'
5
6
  import {
6
7
  Check,
7
8
  Crop,
@@ -16,9 +17,7 @@ import {
16
17
  } from 'lucide-react'
17
18
  import { useCallback, useEffect, useRef, useState } from 'react'
18
19
  import { flushSync } from 'react-dom'
19
- import { useIsMobile } from '../../hooks/use-mobile'
20
20
  import { triggerSFX } from '../../lib/sfx-bus'
21
- import { isTypingTarget } from '../../lib/typing-target'
22
21
  import { requestWalkthroughPointerLock } from '../../lib/walkthrough-pointer-lock'
23
22
  import useEditor, {
24
23
  CAPTURE_FOV_MAX,
@@ -27,9 +26,7 @@ import useEditor, {
27
26
  type SnapshotCropMode,
28
27
  type SnapshotStandardAspect,
29
28
  } from '../../store/use-editor'
30
- import { useFirstPersonHud } from '../../store/use-first-person-hud'
31
29
  import { Slider } from '../ui/slider'
32
- import { WalkthroughCrosshair } from '../walkthrough-hud'
33
30
  import { CaptureLevelPicker } from './capture-level-picker'
34
31
  import { isOverlaySnapshotSave } from './snapshot-capture'
35
32
 
@@ -3,6 +3,7 @@
3
3
  import {
4
4
  emitter,
5
5
  type FenceNode,
6
+ getPlanPointDistance,
6
7
  isCurvedWall,
7
8
  nodeRegistry,
8
9
  type WallNode,
@@ -14,7 +15,7 @@ import {
14
15
  useSyncExternalStore,
15
16
  } from 'react'
16
17
  import { resolveCeilingPlanPointSnap } from '../../lib/ceiling-plan-snap'
17
- import { alignFloorplanDraftPoint, getPlanPointDistance } from '../../lib/floorplan'
18
+ import { alignFloorplanDraftPoint } from '../../lib/floorplan'
18
19
  import { resolveGenericFloorplanGridEventPoint } from '../../lib/floorplan-grid-event-point'
19
20
  import { snapRegisteredDraftPoint } from '../../lib/registered-draft-snap'
20
21
  import { resolveSlabPlanPointSnap } from '../../lib/slab-plan-snap'
@@ -1,6 +1,7 @@
1
1
  'use client'
2
2
 
3
3
  import { useScene } from '@pascal-app/core'
4
+ import { Button } from '@pascal-app/viewer/ui'
4
5
  import {
5
6
  Check,
6
7
  ChevronRight,
@@ -31,7 +32,6 @@ import { cn } from '../../../lib/utils'
31
32
  import useEditor from '../../../store/use-editor'
32
33
  import { IconRefGlyph } from '../../ui/icon-ref'
33
34
  import { Badge } from '../../ui/primitives/badge'
34
- import { Button } from '../../ui/primitives/button'
35
35
  import { PLUGINS_VIEW_ID } from './use-editor-views'
36
36
 
37
37
  const PLUGIN_AUTHORING_URL = 'https://editor.pascal.app/docs/developers/plugins'
@@ -2,14 +2,6 @@
2
2
 
3
3
  import { type MessageDescriptor, type PascalI18n, usePascalI18n } from '@pascal-app/core'
4
4
  import { type GroundMode, useViewer } from '@pascal-app/viewer'
5
- import { ArrowLeftRight, Check, Columns2, MoreHorizontal, Pin, PinOff, X } from 'lucide-react'
6
- import { type ReactNode, useEffect, useRef } from 'react'
7
- import { useIsMobile } from '../../../hooks/use-mobile'
8
- import { type EditorViewDescriptor, isSceneView, isViewPinned } from '../../../lib/editor-views'
9
- import { cn } from '../../../lib/utils'
10
- import useEditor from '../../../store/use-editor'
11
- import { VIEW_2D, VIEW_3D, type ViewPaneIndex } from '../../../store/view-layout'
12
- import { IconRefGlyph } from '../../ui/icon-ref'
13
5
  import {
14
6
  DropdownMenu,
15
7
  DropdownMenuContent,
@@ -17,7 +9,15 @@ import {
17
9
  DropdownMenuLabel,
18
10
  DropdownMenuSeparator,
19
11
  DropdownMenuTrigger,
20
- } from '../../ui/primitives/dropdown-menu'
12
+ useIsMobile,
13
+ } from '@pascal-app/viewer/ui'
14
+ import { ArrowLeftRight, Check, Columns2, MoreHorizontal, Pin, PinOff, X } from 'lucide-react'
15
+ import { type ReactNode, useEffect, useRef } from 'react'
16
+ import { type EditorViewDescriptor, isSceneView, isViewPinned } from '../../../lib/editor-views'
17
+ import { cn } from '../../../lib/utils'
18
+ import useEditor from '../../../store/use-editor'
19
+ import { VIEW_2D, VIEW_3D, type ViewPaneIndex } from '../../../store/view-layout'
20
+ import { IconRefGlyph } from '../../ui/icon-ref'
21
21
  import { PLUGINS_VIEW_ID, useActiveViewLayout, useEditorViews } from './use-editor-views'
22
22
 
23
23
  const GROUP = cn(
@@ -21,10 +21,10 @@ import {
21
21
  type WallNode,
22
22
  } from '@pascal-app/core'
23
23
  import { getSceneTheme, useViewer } from '@pascal-app/viewer'
24
+ import { LocalizedHtml as Html } from '@pascal-app/viewer/ui'
24
25
  import { createPortal, useFrame } from '@react-three/fiber'
25
26
  import { useMemo, useState } from 'react'
26
27
  import * as THREE from 'three'
27
- import { Html } from './localized-html'
28
28
 
29
29
  const GUIDE_Y_OFFSET = 0.08
30
30
  const LABEL_LIFT = 0.08
@@ -19,6 +19,7 @@ import {
19
19
  type WallNode,
20
20
  } from '@pascal-app/core'
21
21
  import { useViewer } from '@pascal-app/viewer'
22
+ import { LocalizedHtml as Html } from '@pascal-app/viewer/ui'
22
23
  import { createPortal, type ThreeEvent, useFrame, useThree } from '@react-three/fiber'
23
24
  import { useEffect, useMemo, useRef, useState } from 'react'
24
25
  import {
@@ -60,7 +61,6 @@ import useInteractionScope, {
60
61
  import { suppressBoxSelectForPointer } from '../tools/select/box-select-state'
61
62
  import { resolveResizeSnapValue } from './handles/resize-snap'
62
63
  import { type HandleDragControls, useHandleDrag } from './handles/use-handle-drag'
63
- import { Html } from './localized-html'
64
64
  import { MeasurementPill } from './measurement-pill'
65
65
  import {
66
66
  createArrowHitAreaGeometry,
@@ -1,13 +1,13 @@
1
1
  'use client'
2
2
 
3
- import { nodeRegistry, type WallNode } from '@pascal-app/core'
3
+ import { nodeRegistry, WALL_PULL_GRIP_TITLE, type WallNode, wallPullSeed } from '@pascal-app/core'
4
4
  import { type ThreeEvent, useThree } from '@react-three/fiber'
5
5
  import { useEffect, useMemo, useState } from 'react'
6
6
  import { Color, DoubleSide, ExtrudeGeometry, OrthographicCamera, Shape } from 'three'
7
7
  import { MeshBasicNodeMaterial } from 'three/webgpu'
8
8
  import { EDITOR_LAYER } from '../../lib/constants'
9
9
  import { sfxEmitter } from '../../lib/sfx-bus'
10
- import { startWallPull, WALL_PULL_GRIP_TITLE, wallPullSeed } from '../../lib/wall-pull'
10
+ import { startWallPull } from '../../lib/wall-pull'
11
11
  import { suppressBoxSelectForPointer } from '../tools/select/box-select-state'
12
12
  import {
13
13
  createEndpointHitAreaGeometry,
@@ -17,7 +17,8 @@ import {
17
17
  useLiveTransforms,
18
18
  useScene,
19
19
  } from '@pascal-app/core'
20
- import { useViewer } from '@pascal-app/viewer'
20
+ import { isTypingTarget, useViewer } from '@pascal-app/viewer'
21
+ import { FloorplanDimensionRenderer } from '@pascal-app/viewer/ui'
21
22
  import { memo, type PointerEvent as ReactPointerEvent, useEffect, useMemo, useState } from 'react'
22
23
  import { create } from 'zustand'
23
24
  import { GROUP_MOVE_DRAG_LABEL, GROUP_ROTATE_DRAG_LABEL } from '../../lib/contextual-help'
@@ -27,7 +28,6 @@ import { isHistoryShortcut } from '../../lib/history'
27
28
  import type { WallGroupPush } from '../../lib/room-handle-drag'
28
29
  import { useRoomHandleDrag } from '../../lib/room-handle-drag'
29
30
  import { sfxEmitter } from '../../lib/sfx-bus'
30
- import { isTypingTarget } from '../../lib/typing-target'
31
31
  import useAlignmentGuides from '../../store/use-alignment-guides'
32
32
  import useEditor, {
33
33
  isAlignmentGuideActive,
@@ -55,7 +55,6 @@ import {
55
55
  import { swallowNextClick } from '../editor/handles/use-handle-drag'
56
56
  import { useMeshSettleEpoch } from '../editor/use-mesh-settle-epoch'
57
57
  import { useFloorplanSceneRotation } from './floorplan-render-context'
58
- import { FloorplanDimensionRenderer } from './renderers/floorplan-dimension-renderer'
59
58
 
60
59
  // 2D sibling of the 3D body-drag group move (`group-move-3d.ts`): dragging
61
60
  // any selected element of a multi-selection slides the whole selection
@@ -33,6 +33,7 @@ import {
33
33
  measurementPolygonLabelAnchor,
34
34
  useViewer,
35
35
  } from '@pascal-app/viewer'
36
+ import { resolveFloorplanLabelAngle } from '@pascal-app/viewer/ui'
36
37
  import { useEffect, useMemo, useRef, useState } from 'react'
37
38
  import {
38
39
  clearSurfacePlanSnapFeedback,
@@ -48,7 +49,6 @@ import {
48
49
  } from '../../store/use-measurement-draft'
49
50
  import { FloorplanQuickMeasureLayer } from './floorplan-quick-measure-layer'
50
51
  import { useFloorplanRender } from './floorplan-render-context'
51
- import { resolveFloorplanLabelAngle } from './renderers/floorplan-label-angle'
52
52
 
53
53
  const DRAFT_COLOR = MEASUREMENT_ACTIVE_COLOR
54
54
  const X_AXIS_COLOR = '#ef4444'
@@ -2,6 +2,7 @@
2
2
 
3
3
  import type { AnyNodeId, OpenWallEnd } from '@pascal-app/core'
4
4
  import { MEASUREMENT_DANGLING_COLOR, useViewer } from '@pascal-app/viewer'
5
+ import { resolveFloorplanLabelAngle } from '@pascal-app/viewer/ui'
5
6
  import { memo, useEffect, useState } from 'react'
6
7
  import { createPortal } from 'react-dom'
7
8
  import {
@@ -15,7 +16,6 @@ import { isViewVisible, VIEW_2D } from '../../store/view-layout'
15
16
  import { JoinWallsPill } from '../editor/join-walls-pill'
16
17
  import { OpenWallEndsHint } from '../editor/open-wall-ends-hint'
17
18
  import { useFloorplanRender } from './floorplan-render-context'
18
- import { resolveFloorplanLabelAngle } from './renderers/floorplan-label-angle'
19
19
 
20
20
  function sceneScreenPoint(point: [number, number]): { left: number; top: number } | null {
21
21
  const scene = document.querySelector<SVGGElement>('[data-floorplan-scene]')
@@ -26,7 +26,7 @@ import {
26
26
  useScene,
27
27
  } from '@pascal-app/core'
28
28
  import { nodeLevelFrame } from '@pascal-app/core/procedural-items'
29
- import { useViewer } from '@pascal-app/viewer'
29
+ import { isTypingTarget, useViewer } from '@pascal-app/viewer'
30
30
  import { useEffect, useMemo } from 'react'
31
31
  import { commitFreshPlacementSubtree } from '../../lib/fresh-planar-placement'
32
32
  import { isHistoryShortcut } from '../../lib/history'
@@ -39,7 +39,6 @@ import {
39
39
  import { movementSfxStepKey } from '../../lib/sfx/movement-tick'
40
40
  import { sfxEmitter } from '../../lib/sfx-bus'
41
41
  import { surfaceAttachmentId } from '../../lib/surface-attachment'
42
- import { isTypingTarget } from '../../lib/typing-target'
43
42
  import { resolveAlignmentForFloorplanView } from '../../lib/world-grid-snap'
44
43
  import useAlignmentGuides from '../../store/use-alignment-guides'
45
44
  import useEditor, {
@@ -1,47 +1,10 @@
1
1
  import { describe, expect, test } from 'bun:test'
2
- import { floorplanGeometryMetadata } from '../../../lib/floorplan/floorplan-extension'
3
2
  import {
4
- floorplanAnnotationObstacleMode,
5
3
  polylineObstacleRectangles,
6
4
  resolveAnnotationLabelRectangles,
7
5
  resolveSvgAnnotationCollisions,
8
6
  } from './floorplan-annotation-layout'
9
7
 
10
- describe('floorplanAnnotationObstacleMode', () => {
11
- test('treats fixed annotation categories as layout obstacles', () => {
12
- expect(
13
- floorplanAnnotationObstacleMode({
14
- kind: 'text',
15
- x: 0,
16
- y: 0,
17
- text: 'BEDROOM',
18
- fontSize: 0.18,
19
- metadata: floorplanGeometryMetadata({ annotationRole: 'room-label' }),
20
- }),
21
- ).toBe('bounds')
22
- expect(
23
- floorplanAnnotationObstacleMode({
24
- kind: 'line',
25
- x1: 0,
26
- y1: 0,
27
- x2: 1,
28
- y2: 0,
29
- metadata: floorplanGeometryMetadata({ annotationRole: 'column-center' }),
30
- }),
31
- ).toBe('bounds')
32
- expect(
33
- floorplanAnnotationObstacleMode({
34
- kind: 'polyline',
35
- points: [
36
- [0, 0],
37
- [1, 0],
38
- ],
39
- metadata: floorplanGeometryMetadata({ annotationRole: 'stair-annotation' }),
40
- }),
41
- ).toBe('outline')
42
- })
43
- })
44
-
45
8
  describe('resolveAnnotationLabelRectangles', () => {
46
9
  test('keeps the higher-priority label and moves the conflicting label', () => {
47
10
  const shifts = resolveAnnotationLabelRectangles([
@@ -1,6 +1,3 @@
1
- import type { FloorplanGeometry } from '@pascal-app/core'
2
- import { readFloorplanGeometryMetadata } from '../../../lib/floorplan/floorplan-extension'
3
-
4
1
  export type AnnotationLabelRectangle = {
5
2
  id: string
6
3
  x: number
@@ -467,33 +464,6 @@ function candidateCost(
467
464
  return preference + distance + perpendicularMovement * 4
468
465
  }
469
466
 
470
- export function isFloorplanAnnotationObstacleGeometry(geometry: FloorplanGeometry): boolean {
471
- if (floorplanAnnotationObstacleMode(geometry)) return true
472
- if (geometry.kind !== 'group') return false
473
- const hasPlate = geometry.children.some(
474
- (child) => child.kind === 'rect' || child.kind === 'circle',
475
- )
476
- const hasUprightText = geometry.children.some((child) => child.kind === 'text' && child.upright)
477
- return hasPlate && hasUprightText
478
- }
479
-
480
- export function floorplanAnnotationObstacleMode(
481
- geometry: FloorplanGeometry,
482
- ): 'bounds' | 'outline' | '' | undefined {
483
- const metadata = readFloorplanGeometryMetadata(geometry)
484
- if (metadata.annotationObstacle) return metadata.annotationObstacle
485
- switch (metadata.annotationRole) {
486
- case 'room-label':
487
- return geometry.kind === 'text' ? 'bounds' : undefined
488
- case 'column-center':
489
- return geometry.kind === 'line' || geometry.kind === 'text' ? 'bounds' : undefined
490
- case 'stair-annotation':
491
- return geometry.kind === 'polyline' || geometry.kind === 'line' ? 'outline' : 'bounds'
492
- default:
493
- return undefined
494
- }
495
- }
496
-
497
467
  function rectanglesOverlap(
498
468
  left: Pick<AnnotationLabelRectangle, 'x' | 'y' | 'width' | 'height'>,
499
469
  right: Pick<AnnotationLabelRectangle, 'x' | 'y' | 'width' | 'height'>,
@@ -3,7 +3,8 @@
3
3
  import type { AnyNode, AnyNodeId } from '@pascal-app/core'
4
4
  import { useLocale, useScene } from '@pascal-app/core'
5
5
  import { useViewer } from '@pascal-app/viewer'
6
- import { useCallback, useEffect, useRef, useState } from 'react'
6
+ import { FloorplanDimensionHitsProvider } from '@pascal-app/viewer/ui'
7
+ import { type ReactNode, useCallback, useEffect, useRef, useState } from 'react'
7
8
  import { createPortal } from 'react-dom'
8
9
  import {
9
10
  parseDimensionInput,
@@ -26,8 +27,8 @@ import useEditor from '../../../store/use-editor'
26
27
  * anchor the value is written as `textOverride` on a construction-dimension
27
28
  * node instead, and the label renders an "override" badge.
28
29
  *
29
- * The label is found by DOM delegation on the attributes
30
- * `floorplan-dimension-renderer.tsx` emits, so this works identically for
30
+ * The label is found by DOM delegation on the attributes the viewer's
31
+ * dimension renderer emits under `FloorplanDimensionHitsGate`, so this works identically for
31
32
  * `dimension` and `dimension-string` geometry, for automatic wall dimensions,
32
33
  * contextual dimensions and manual construction-dimension nodes — and on
33
34
  * sheets, which mount the same renderer.
@@ -62,6 +63,15 @@ export function useDimensionEditAllowed(): boolean {
62
63
  return useEditor((state) => isDimensionEditAllowed(state, { readOnly }))
63
64
  }
64
65
 
66
+ /** Plan dimension labels under the editor carry their typeable hit rects while typing is allowed. */
67
+ export function FloorplanDimensionHitsGate({ children }: { children: ReactNode }) {
68
+ return (
69
+ <FloorplanDimensionHitsProvider value={useDimensionEditAllowed()}>
70
+ {children}
71
+ </FloorplanDimensionHitsProvider>
72
+ )
73
+ }
74
+
65
75
  /**
66
76
  * The typeable dimension value under a press, with the node typing it drives:
67
77
  * the pressed element's or, when the plan's dashed group box lies over it, the
@@ -10,12 +10,11 @@ import {
10
10
  useScene,
11
11
  } from '@pascal-app/core'
12
12
  import { useViewer } from '@pascal-app/viewer'
13
+ import { FloorplanDimensionRenderer, FloorplanGeometryRenderer } from '@pascal-app/viewer/ui'
13
14
  import { memo, useMemo } from 'react'
14
15
  import usePlacementPreview from '../../../store/use-placement-preview'
15
16
  import { usePlacementTyping } from '../../../store/use-placement-typing'
16
17
  import { useFloorplanRender, useFloorplanSceneRotation } from '../floorplan-render-context'
17
- import { FloorplanDimensionRenderer } from './floorplan-dimension-renderer'
18
- import { FloorplanGeometryRenderer } from './floorplan-geometry-renderer'
19
18
  import { FloorplanPlacementTypingHud } from './floorplan-placement-typing-hud'
20
19
 
21
20
  export interface FloorplanNodePreviewProps {
@@ -7,15 +7,17 @@ import type {
7
7
  FloorplanPalette,
8
8
  LiveNodeOverrides,
9
9
  } from '@pascal-app/core'
10
- import { type AnyNodeDefinition, emitter, nodeRegistry, registerNode } from '@pascal-app/core'
10
+ import {
11
+ type AnyNodeDefinition,
12
+ emitter,
13
+ floorplanGeometryMetadata,
14
+ nodeRegistry,
15
+ registerNode,
16
+ } from '@pascal-app/core'
11
17
  import { createElement } from 'react'
12
18
  import { renderToStaticMarkup } from 'react-dom/server'
13
19
  import { z } from 'zod'
14
20
  import { AXIS_MOVE_DRAG_LABEL, PATH_POINT_DRAG_LABEL } from '../../../lib/contextual-help'
15
- import {
16
- FLOORPLAN_NODE_EXTENSION_KEY,
17
- floorplanGeometryMetadata,
18
- } from '../../../lib/floorplan/floorplan-extension'
19
21
  import type { SessionWrites } from '../../../lib/session-writes'
20
22
  import { snapContextOf } from '../../../lib/snapping-mode'
21
23
  import {
@@ -776,11 +778,7 @@ describe('collectFloorplanLinkedLevelNodes', () => {
776
778
  category: 'structure',
777
779
  defaults: () => ({}) as never,
778
780
  floorplan: () => null,
779
- extensions: {
780
- [FLOORPLAN_NODE_EXTENSION_KEY]: {
781
- linkedLevelIds: () => ['level_upper' as AnyNodeId],
782
- },
783
- },
781
+ floorplanLinkedLevelIds: () => ['level_upper' as AnyNodeId],
784
782
  } as unknown as AnyNodeDefinition)
785
783
  const child = {
786
784
  id: 'linked_child',
@@ -4,15 +4,22 @@ import {
4
4
  type AnyNode,
5
5
  type AnyNodeDefinition,
6
6
  type AnyNodeId,
7
+ buildFloorplanContext,
8
+ createFloorplanContextExtensions,
7
9
  createSceneApi,
8
10
  emitter,
9
11
  type FloorplanAffordanceSession,
12
+ type FloorplanAnnotationRole,
10
13
  type FloorplanGeometry,
11
14
  type FloorplanPalette,
12
15
  type FloorplanPoint,
13
16
  type FloorplanScope,
17
+ type FloorplanWallDimensionFaces,
18
+ floorplanAnnotationObstacleMode,
19
+ floorplanLayerRank,
14
20
  type GeometryContext,
15
21
  hidesDescendants,
22
+ isFloorplanAnnotationObstacleGeometry,
16
23
  isNodeKindEnabled,
17
24
  isRegistryMovable,
18
25
  kindsWithFloorplanScope,
@@ -20,6 +27,7 @@ import {
20
27
  type LiveTransform,
21
28
  nodeRegistry,
22
29
  pauseSceneHistory,
30
+ readFloorplanGeometryMetadata,
23
31
  resolveBuildingForLevel,
24
32
  resolveSelectionProxyId,
25
33
  resumeSceneHistory,
@@ -28,6 +36,10 @@ import {
28
36
  useLiveNodeOverrides,
29
37
  useLiveTransforms,
30
38
  useScene,
39
+ WALL_PULL_AFFORDANCE,
40
+ WALL_PUSH_AFFORDANCE,
41
+ type WallPullGripPayload,
42
+ withFloorplanGeometryMetadata,
31
43
  } from '@pascal-app/core'
32
44
  import {
33
45
  beginPerfAction,
@@ -37,6 +49,14 @@ import {
37
49
  useRevealWaiting,
38
50
  useViewer,
39
51
  } from '@pascal-app/viewer'
52
+ import {
53
+ FloorplanDimensionRenderer,
54
+ FloorplanGeometryRenderer,
55
+ resolveFloorplanAnnotationUpdate,
56
+ resolveFloorplanLabelAngle,
57
+ selectionModifiersFromEvent,
58
+ updateSvgFloorplanLabelOrientations,
59
+ } from '@pascal-app/viewer/ui'
40
60
  import {
41
61
  type ComponentProps,
42
62
  memo,
@@ -55,7 +75,6 @@ import {
55
75
  hoverRoomFromHit,
56
76
  resolvePlanRoomHit,
57
77
  roomPickingEnabled,
58
- selectionModifiersFromEvent,
59
78
  useRoomRecords,
60
79
  } from '../../../hooks/use-selected-room'
61
80
  import { useCeilingEditSession } from '../../../lib/ceiling-edit-session'
@@ -79,22 +98,11 @@ import {
79
98
  filterFloorplanAnnotationGeometry,
80
99
  } from '../../../lib/floorplan/annotation-visibility'
81
100
  import { resolveNodeForDrawingType } from '../../../lib/floorplan/drawing-coordination'
82
- import {
83
- createFloorplanContextExtensions,
84
- type FloorplanAnnotationRole,
85
- type FloorplanWallDimensionFaces,
86
- getFloorplanNodeExtension,
87
- readFloorplanGeometryMetadata,
88
- withFloorplanGeometryMetadata,
89
- } from '../../../lib/floorplan/floorplan-extension'
101
+ import { getFloorplanNodeExtension } from '../../../lib/floorplan/floorplan-extension'
90
102
  import {
91
103
  type FloorplanMode,
92
104
  resolveFloorplanAnnotationVisibility,
93
105
  } from '../../../lib/floorplan/floorplan-mode'
94
- import {
95
- buildFloorplanContext,
96
- floorplanLayerRank,
97
- } from '../../../lib/floorplan/floorplan-readonly'
98
106
  import { clientToPlan } from '../../../lib/floorplan/plan-coords'
99
107
  import {
100
108
  type ActiveInteractionScope,
@@ -106,7 +114,7 @@ import {
106
114
  isIdle,
107
115
  tangentReshapeScope,
108
116
  } from '../../../lib/interaction/scope'
109
- import { runFloorplanWallPush, WALL_PUSH_AFFORDANCE } from '../../../lib/room-handle-drag'
117
+ import { runFloorplanWallPush } from '../../../lib/room-handle-drag'
110
118
  import { selectRoom, selectRoomFromHit } from '../../../lib/room-selection-commands'
111
119
  import { clickZoneArea, hoverZoneArea } from '../../../lib/room-zone-routing'
112
120
  import {
@@ -118,11 +126,7 @@ import { createSessionWrites, type SessionWrites } from '../../../lib/session-wr
118
126
  import { sfxEmitter } from '../../../lib/sfx-bus'
119
127
  import { clearSurfacePlanSnapFeedback } from '../../../lib/surface-plan-snap'
120
128
  import { paintZoneMembership } from '../../../lib/units'
121
- import {
122
- startWallPull,
123
- WALL_PULL_AFFORDANCE,
124
- type WallPullGripPayload,
125
- } from '../../../lib/wall-pull'
129
+ import { startWallPull } from '../../../lib/wall-pull'
126
130
  import useDirectManipulationFeedback from '../../../store/use-direct-manipulation-feedback'
127
131
  import useDrawingView from '../../../store/use-drawing-view'
128
132
  import useEditor, { isAngleSnapActive, type Mode } from '../../../store/use-editor'
@@ -157,23 +161,11 @@ import {
157
161
  useFloorplanStaticRender,
158
162
  useFloorplanStaticUnitsPerPixel,
159
163
  } from '../floorplan-render-context'
160
- import {
161
- floorplanAnnotationObstacleMode,
162
- isFloorplanAnnotationObstacleGeometry,
163
- resolveSvgAnnotationCollisions,
164
- svgAnnotationLabelId,
165
- } from './floorplan-annotation-layout'
164
+ import { resolveSvgAnnotationCollisions, svgAnnotationLabelId } from './floorplan-annotation-layout'
166
165
  import {
167
166
  FloorplanDimensionEditOverlay,
168
167
  typeableDimensionAt,
169
168
  } from './floorplan-dimension-edit-overlay'
170
- import { FloorplanDimensionRenderer } from './floorplan-dimension-renderer'
171
- import { FloorplanGeometryRenderer } from './floorplan-geometry-renderer'
172
- import {
173
- resolveFloorplanAnnotationUpdate,
174
- resolveFloorplanLabelAngle,
175
- updateSvgFloorplanLabelOrientations,
176
- } from './floorplan-label-angle'
177
169
  import { useFloorplanReveal } from './floorplan-reveal'
178
170
 
179
171
  /**
@@ -3645,7 +3637,7 @@ export function collectFloorplanLinkedLevelNodes(
3645
3637
  for (const [rawId, node] of Object.entries(nodes)) {
3646
3638
  if (!node) continue
3647
3639
  const definition = nodeRegistry.get(node.type)
3648
- const linkedLevelIds = getFloorplanNodeExtension(definition)?.linkedLevelIds
3640
+ const linkedLevelIds = definition?.floorplanLinkedLevelIds
3649
3641
  if (!definition?.floorplan || !linkedLevelIds) continue
3650
3642
  const id = rawId as AnyNodeId
3651
3643
  if (excludedIds.has(id)) continue
@@ -22,6 +22,7 @@ import {
22
22
  csgEvaluator,
23
23
  generateRoofSegmentGeometry,
24
24
  INTERSECTION,
25
+ isTypingTarget,
25
26
  markPureRaycast,
26
27
  prepareBrushForCSG,
27
28
  useViewer,
@@ -34,7 +35,6 @@ import { LineBasicNodeMaterial, MeshBasicNodeMaterial } from 'three/webgpu'
34
35
  import { EDITOR_LAYER } from '../../../lib/constants'
35
36
  import { isHistoryShortcut } from '../../../lib/history'
36
37
  import { getHoveredRoofSegmentOutlineProxyName } from '../../../lib/roof-hover-outline-proxy'
37
- import { isTypingTarget } from '../../../lib/typing-target'
38
38
  import useInteractionScope, { useMovingNode } from '../../../store/use-interaction-scope'
39
39
  import { swallowNextClick } from '../../editor/handles/use-handle-drag'
40
40
 
@@ -1863,10 +1863,11 @@ export const RoofEditSystem = () => {
1863
1863
  const wasReveal = prevRevealRoofIds.current.has(roofId)
1864
1864
  if (isActive !== wasActive || isMoving !== wasMoving) {
1865
1865
  // Entering or exiting edit and move modes rebuilds the merged shell
1866
- // from the current segment values.
1866
+ // from the current segment values (its faces of other kinds are no part of it).
1867
1867
  const { markDirty } = useScene.getState()
1868
1868
  for (const childId of roofNode.children) {
1869
- markDirty(childId as AnyNodeId)
1869
+ if (nodes[childId as AnyNodeId]?.type === 'roof-segment')
1870
+ markDirty(childId as AnyNodeId)
1870
1871
  }
1871
1872
  }
1872
1873
  // Entering reveal mode (and NOT also full-edit, which already
@@ -26,12 +26,12 @@ import {
26
26
  useEditor,
27
27
  useInteractionScope,
28
28
  } from '@pascal-app/editor'
29
+ import { LocalizedHtml as Html } from '@pascal-app/viewer/ui'
29
30
  import { useThree } from '@react-three/fiber'
30
31
  import { type RefObject, useCallback, useEffect, useRef, useState } from 'react'
31
32
  import { createPortal } from 'react-dom'
32
33
  import { type Group, Vector3 } from 'three'
33
34
  import { messageWithSlot } from '../../../i18n/message-slot'
34
- import { Html } from '../../editor/localized-html'
35
35
  import type { RunSurfaceBounds, RunSurfaceTarget } from './distribution-run-contract'
36
36
  import { clearDrawAlignment } from './draw-alignment'
37
37
  import type { RunBodyHit, ScenePort } from './ports'
@@ -22,12 +22,12 @@ import {
22
22
  WallNode,
23
23
  } from '@pascal-app/core'
24
24
  import { useViewer } from '@pascal-app/viewer'
25
+ import { LocalizedHtml as Html } from '@pascal-app/viewer/ui'
25
26
  import { act, create } from '@react-three/test-renderer'
26
27
  import { Children, Component, cloneElement, isValidElement, type ReactNode } from 'react'
27
28
  import { Group } from 'three'
28
29
  import useEditor from '../../../store/use-editor'
29
30
  import useInteractionScope from '../../../store/use-interaction-scope'
30
- import { Html } from '../../editor/localized-html'
31
31
  import { useDraftNode } from './use-draft-node'
32
32
  import { usePlacementCoordinator } from './use-placement-coordinator'
33
33