@pascal-app/editor 1.0.3 → 1.0.5
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.
- package/README.md +106 -0
- package/package.json +42 -38
- package/src/components/editor/__bench__/room-label-placement.bench.ts +108 -0
- package/src/components/editor/action-menu-button.tsx +83 -0
- package/src/components/editor/bake-thumbnail.tsx +307 -5
- package/src/components/editor/capture-level-picker.tsx +72 -0
- package/src/components/editor/construction-reveal-audio.test.tsx +150 -0
- package/src/components/editor/construction-reveal-audio.tsx +40 -0
- package/src/components/editor/custom-camera-controls.tsx +275 -57
- package/src/components/editor/delete-confirmation-dialog.tsx +297 -7
- package/src/components/editor/duplicate-node.ts +244 -0
- package/src/components/editor/editor-layout-mobile.tsx +37 -26
- package/src/components/editor/editor-layout-v2.tsx +132 -59
- package/src/components/editor/export-manager.tsx +47 -26
- package/src/components/editor/first-person/build-collider-world.test.ts +320 -0
- package/src/components/editor/first-person/build-collider-world.ts +28 -7
- package/src/components/editor/first-person/ground-holes.test.ts +128 -0
- package/src/components/editor/first-person/ground-holes.ts +130 -0
- package/src/components/editor/first-person/mechanism-targets.test.ts +162 -0
- package/src/components/editor/first-person/mechanism-targets.ts +88 -0
- package/src/components/editor/first-person-controls.tsx +220 -9
- package/src/components/editor/floating-action-menu.tsx +63 -207
- package/src/components/editor/floor-aware-camera-controls.test.ts +466 -0
- package/src/components/editor/floor-aware-camera-controls.ts +324 -0
- package/src/components/editor/floor-openings-overlay.tsx +243 -0
- package/src/components/editor/floor-region-controls.tsx +846 -0
- package/src/components/editor/floor-region-webgpu-materials.test.ts +12 -0
- package/src/components/editor/floor-surface.test.ts +165 -0
- package/src/components/editor/floor-surface.ts +182 -0
- package/src/components/editor/floorplan-background-selection.test.ts +11 -2
- package/src/components/editor/floorplan-background-selection.ts +1 -3
- package/src/components/editor/floorplan-mode-coordinator.tsx +2 -2
- package/src/components/editor/floorplan-panel.tsx +414 -363
- package/src/components/editor/follow-pascal.test.tsx +912 -0
- package/src/components/editor/follow-pascal.tsx +354 -0
- package/src/components/editor/footprint-height-handle.tsx +204 -0
- package/src/components/editor/group-actions.ts +56 -2
- package/src/components/editor/group-move-3d.ts +2 -0
- package/src/components/editor/group-rotate-handle.tsx +2 -0
- package/src/components/editor/group-transform-shared.test.ts +460 -0
- package/src/components/editor/handles/handle-hit-priority.test.tsx +63 -0
- package/src/components/editor/handles/handle-hit-priority.tsx +37 -0
- package/src/components/editor/handles/swallow-next-click.test.ts +28 -0
- package/src/components/editor/handles/use-handle-drag.ts +269 -197
- package/src/components/editor/index.tsx +409 -197
- package/src/components/editor/join-walls-pill.tsx +44 -0
- package/src/components/editor/node-action-menu.tsx +68 -70
- package/src/components/editor/node-arrow-handles.tsx +25 -6
- package/src/components/editor/open-wall-ends-3d-layer.tsx +273 -0
- package/src/components/editor/open-wall-ends-hint.tsx +89 -0
- package/src/components/editor/quick-measurement-hud.tsx +3 -2
- package/src/components/editor/registry-action-contributions.test.tsx +63 -0
- package/src/components/editor/registry-action-contributions.tsx +80 -1
- package/src/components/editor/riser-diagram-panel.tsx +14 -7
- package/src/components/editor/room-controls.tsx +847 -0
- package/src/components/editor/room-floor-highlight.tsx +128 -0
- package/src/components/editor/room-handles-2d.tsx +354 -0
- package/src/components/editor/room-handles.tsx +675 -0
- package/src/components/editor/room-highlight.tsx +233 -0
- package/src/components/editor/room-labels.test.ts +850 -0
- package/src/components/editor/room-labels.tsx +1890 -0
- package/src/components/editor/room-transform-ghost.tsx +256 -0
- package/src/components/editor/room-webgpu-materials.test.ts +27 -0
- package/src/components/editor/selection-manager.tsx +474 -419
- package/src/components/editor/slab-hole-highlights.tsx +5 -2
- package/src/components/editor/snapshot-capture-overlay.tsx +7 -2
- package/src/components/editor/snapshot-capture.test.ts +119 -60
- package/src/components/editor/snapshot-capture.ts +36 -5
- package/src/components/editor/thumbnail-generator.test.ts +654 -0
- package/src/components/editor/thumbnail-generator.tsx +1103 -223
- package/src/components/editor/use-floorplan-background-placement.ts +34 -12
- package/src/components/editor/vector-edge-extractor.tsx +121 -0
- package/src/components/editor/views/host-view.tsx +61 -0
- package/src/components/editor/views/plugins-view.tsx +663 -0
- package/src/components/editor/views/scene-region.tsx +59 -0
- package/src/components/editor/views/use-editor-views.ts +57 -0
- package/src/components/editor/views/view-bar.test.tsx +54 -0
- package/src/components/editor/views/view-bar.tsx +343 -0
- package/src/components/editor/wall-justification.test.ts +140 -0
- package/src/components/editor/wall-move-side-handles.tsx +43 -142
- package/src/components/editor/wall-push-arrow.tsx +92 -0
- package/src/components/editor/wall-region-handles.tsx +509 -0
- package/src/components/editor/wall-snap-beacon-layer.tsx +8 -4
- package/src/components/editor-2d/floorplan-cursor-indicator-overlay.tsx +8 -4
- package/src/components/editor-2d/floorplan-group-move.tsx +3 -0
- package/src/components/editor-2d/floorplan-open-wall-ends-layer.test.tsx +86 -0
- package/src/components/editor-2d/floorplan-open-wall-ends-layer.tsx +290 -0
- package/src/components/editor-2d/floorplan-registered-tool-layer.tsx +2 -2
- package/src/components/editor-2d/floorplan-registry-action-menu.tsx +11 -1
- package/src/components/editor-2d/floorplan-registry-move-overlay.tsx +116 -106
- package/src/components/editor-2d/renderers/floorplan-dimension-edit-overlay.test.ts +156 -0
- package/src/components/editor-2d/renderers/floorplan-dimension-edit-overlay.tsx +278 -0
- package/src/components/editor-2d/renderers/floorplan-dimension-renderer.tsx +77 -0
- package/src/components/editor-2d/renderers/{floorplan-draft-wall-measurement.tsx → floorplan-draft-measurement.tsx} +8 -8
- package/src/components/editor-2d/renderers/floorplan-geometry-renderer.tsx +4 -1
- package/src/components/editor-2d/renderers/floorplan-registry-layer.test.ts +38 -8
- package/src/components/editor-2d/renderers/floorplan-registry-layer.tsx +319 -233
- package/src/components/editor-2d/renderers/floorplan-reveal.test.tsx +254 -0
- package/src/components/editor-2d/renderers/floorplan-reveal.ts +141 -0
- package/src/components/editor-2d/svg-paths.ts +12 -15
- package/src/components/point-ask/bubble.tsx +538 -0
- package/src/components/point-ask/hover-chip.tsx +91 -0
- package/src/components/point-ask/mode-pill.tsx +92 -0
- package/src/components/point-ask/optional-motion.ts +22 -0
- package/src/components/point-ask/outline-corners.tsx +93 -0
- package/src/components/point-ask/pins.tsx +711 -0
- package/src/components/point-ask/point-ask-layer.tsx +83 -0
- package/src/components/point-ask/point-ask-styles.ts +105 -0
- package/src/components/point-ask/region-marquee-styles.ts +15 -0
- package/src/components/point-ask/region-marquee.tsx +64 -0
- package/src/components/procedural-items/inspector.tsx +40 -15
- package/src/components/systems/ceiling/ceiling-bracket-batch.test.ts +12 -2
- package/src/components/systems/ceiling/ceiling-selection-affordance-system.test.ts +97 -14
- package/src/components/systems/ceiling/ceiling-selection-affordance-system.tsx +18 -18
- package/src/components/systems/roof/roof-edit-system.tsx +1 -0
- package/src/components/systems/zone/zone-system.test.ts +47 -0
- package/src/components/systems/zone/zone-system.tsx +29 -68
- package/src/components/tools/distribution/connection-compatibility.test.ts +34 -0
- package/src/components/tools/distribution/connection-compatibility.ts +43 -0
- package/src/components/tools/distribution/distribution-public.ts +9 -0
- package/src/components/tools/distribution/distribution-run-contract.test.ts +26 -0
- package/src/components/tools/distribution/distribution-run-contract.ts +94 -0
- package/src/components/tools/distribution/distribution-run-tool.test.ts +241 -0
- package/src/components/tools/distribution/distribution-run-tool.test.tsx +125 -0
- package/src/components/tools/distribution/distribution-run-tool.tsx +1323 -0
- package/src/components/tools/distribution/draw-alignment.ts +35 -0
- package/src/components/tools/distribution/ports.test.ts +56 -0
- package/src/components/tools/distribution/ports.ts +378 -0
- package/src/components/tools/distribution/run-cursor.test.ts +135 -0
- package/src/components/tools/distribution/run-cursor.ts +36 -0
- package/src/components/tools/distribution/run-direction-feedback.test.ts +60 -0
- package/src/components/tools/distribution/run-direction-feedback.tsx +251 -0
- package/src/components/tools/distribution/run-port-snap.test.ts +79 -0
- package/src/components/tools/distribution/run-port-snap.ts +25 -0
- package/src/components/tools/distribution/run-screen-direction.test.ts +23 -0
- package/src/components/tools/distribution/run-screen-direction.ts +30 -0
- package/src/components/tools/elevator/elevator-tool.tsx +3 -6
- package/src/components/tools/elevator/move-elevator-tool.tsx +2 -3
- package/src/components/tools/item/item-surface-strategy-resolver.test.ts +67 -68
- package/src/components/tools/item/placement-history.test.tsx +512 -0
- package/src/components/tools/item/placement-strategies.test.ts +46 -1
- package/src/components/tools/item/placement-strategies.ts +11 -10
- package/src/components/tools/item/shelf-surface-strategy-resolver.test.ts +56 -56
- package/src/components/tools/item/use-draft-node.test.tsx +432 -1
- package/src/components/tools/item/use-draft-node.ts +166 -95
- package/src/components/tools/item/use-placement-coordinator.tsx +148 -95
- package/src/components/tools/paint-region/use-paint-tint.ts +37 -0
- package/src/components/tools/paint-region/wall-paint-region-tool.tsx +466 -0
- package/src/components/tools/registry/item-surface-move.test.ts +62 -63
- package/src/components/tools/registry/item-surface-move.ts +2 -0
- package/src/components/tools/registry/item-surface-resolver.test.ts +26 -26
- package/src/components/tools/registry/move-registry-node-tool.test.ts +268 -1
- package/src/components/tools/registry/move-registry-node-tool.tsx +66 -30
- package/src/components/tools/select/box-select-tool.tsx +2 -12
- package/src/components/tools/select/plane-box-select-tool.test.tsx +79 -0
- package/src/components/tools/select/plane-box-select-tool.tsx +35 -22
- package/src/components/tools/select/select-candidates.test.ts +37 -4
- package/src/components/tools/select/select-candidates.ts +15 -11
- package/src/components/tools/shared/cursor-sphere.tsx +36 -12
- package/src/components/tools/site/site-boundary-editor.tsx +1 -2
- package/src/components/tools/tool-manager.tsx +59 -24
- package/src/components/tools/wall/wall-drafting.test.ts +175 -47
- package/src/components/tools/zone/zone-tool.tsx +4 -12
- package/src/components/ui/action-menu/action-button.tsx +9 -1
- package/src/components/ui/action-menu/camera-actions.tsx +9 -4
- package/src/components/ui/action-menu/control-modes.tsx +15 -42
- package/src/components/ui/action-menu/follow-pascal-pill.tsx +32 -0
- package/src/components/ui/action-menu/follow-pascal-toggle.tsx +36 -0
- package/src/components/ui/action-menu/index.tsx +56 -33
- package/src/components/ui/action-menu/measurement-control.tsx +14 -19
- package/src/components/ui/action-menu/placement.ts +20 -0
- package/src/components/ui/action-menu/point-ask-button.tsx +52 -0
- package/src/components/ui/action-menu/view-toggles.tsx +47 -42
- package/src/components/ui/build-panel/build-panel.tsx +242 -0
- package/src/components/ui/command-palette/editor-commands.tsx +7 -42
- package/src/components/ui/command-palette/index.tsx +50 -39
- package/src/components/ui/command-palette/ranked-groups.test.ts +31 -0
- package/src/components/ui/controls/action-button.tsx +5 -2
- package/src/components/ui/controls/finish-swatch.tsx +110 -0
- package/src/components/ui/controls/material-paint-panel.tsx +97 -26
- package/src/components/ui/controls/material-picker.tsx +4 -1
- package/src/components/ui/controls/metric-control.tsx +1 -1
- package/src/components/ui/controls/scene-material-list.tsx +4 -32
- package/src/components/ui/controls/segmented-control.tsx +21 -8
- package/src/components/ui/controls/select-control.tsx +65 -0
- package/src/components/ui/controls/slider-control.tsx +1 -1
- package/src/components/ui/controls/toggle-control.tsx +3 -3
- package/src/components/ui/controls/tool-options-panel.tsx +1 -1
- package/src/components/ui/floating-level-selector.tsx +159 -59
- package/src/components/ui/helpers/building-helper.tsx +4 -1
- package/src/components/ui/helpers/contextual-helper-panel.tsx +181 -72
- package/src/components/ui/helpers/helper-manager.test.tsx +121 -0
- package/src/components/ui/helpers/helper-manager.tsx +331 -14
- package/src/components/ui/helpers/item-helper.tsx +17 -1
- package/src/components/ui/helpers/registered-tool-helper.tsx +8 -1
- package/src/components/ui/icon-ref.tsx +45 -1
- package/src/components/ui/level-duplicate-dialog.tsx +1 -1
- package/src/components/ui/node-icon-image.tsx +16 -0
- package/src/components/ui/panels/collections/collections-popover.tsx +28 -22
- package/src/components/ui/panels/floor-foundation-panel.tsx +551 -0
- package/src/components/ui/panels/floor-opening-panel.tsx +143 -0
- package/src/components/ui/panels/mobile-panel-sheet.tsx +4 -4
- package/src/components/ui/panels/mobile-selection-bar.tsx +8 -5
- package/src/components/ui/panels/multi-field-value.test.ts +26 -3
- package/src/components/ui/panels/multi-field-value.ts +6 -3
- package/src/components/ui/panels/multi-parametric-inspector.tsx +52 -2
- package/src/components/ui/panels/multi-selection-panel.tsx +161 -5
- package/src/components/ui/panels/node-display.ts +8 -3
- package/src/components/ui/panels/panel-manager.tsx +103 -68
- package/src/components/ui/panels/panel-wrapper.tsx +130 -62
- package/src/components/ui/panels/parametric-field-control.tsx +3 -3
- package/src/components/ui/panels/parametric-inspector.tsx +7 -7
- package/src/components/ui/panels/reference-panel.tsx +2 -3
- package/src/components/ui/panels/room-construction-rows.tsx +774 -0
- package/src/components/ui/panels/room-name-options.test.ts +55 -0
- package/src/components/ui/panels/room-name-options.ts +47 -0
- package/src/components/ui/panels/room-openings-field.tsx +110 -0
- package/src/components/ui/panels/room-panel.tsx +790 -0
- package/src/components/ui/panels/shape-choice.tsx +58 -0
- package/src/components/ui/panels/wall-region-list.tsx +109 -0
- package/src/components/ui/primitives/badge.tsx +8 -0
- package/src/components/ui/primitives/color-dot.tsx +36 -24
- package/src/components/ui/primitives/sidebar.tsx +3 -1
- package/src/components/ui/right-stack.test.ts +29 -0
- package/src/components/ui/right-stack.tsx +164 -0
- package/src/components/ui/sidebar/app-sidebar.tsx +1 -1
- package/src/components/ui/sidebar/icon-rail.tsx +8 -3
- package/src/components/ui/sidebar/panels/items-panel/function-tree-panel.tsx +1 -1
- package/src/components/ui/sidebar/panels/items-panel/index.tsx +6 -6
- package/src/components/ui/sidebar/panels/settings-panel/animation-speed-setting.tsx +40 -0
- package/src/components/ui/sidebar/panels/settings-panel/audio-settings-dialog.tsx +7 -8
- package/src/components/ui/sidebar/panels/settings-panel/construction-animation-setting.test.tsx +170 -0
- package/src/components/ui/sidebar/panels/settings-panel/construction-animation-setting.tsx +92 -0
- package/src/components/ui/sidebar/panels/settings-panel/index.tsx +138 -27
- package/src/components/ui/sidebar/panels/settings-panel/interface-theme.test.tsx +20 -0
- package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +5 -5
- package/src/components/ui/sidebar/panels/settings-panel/print-export-button.tsx +4 -10
- package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +3 -11
- package/src/components/ui/sidebar/panels/site-panel/ceiling-tree-node.tsx +4 -4
- package/src/components/ui/sidebar/panels/site-panel/chimney-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/collection-tree-node.tsx +197 -0
- package/src/components/ui/sidebar/panels/site-panel/column-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/door-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/dormer-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/elevator-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/fence-tree-node.tsx +24 -11
- package/src/components/ui/sidebar/panels/site-panel/gutter-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/index.tsx +181 -223
- package/src/components/ui/sidebar/panels/site-panel/inline-rename-input.tsx +30 -8
- package/src/components/ui/sidebar/panels/site-panel/item-tree-node.tsx +1 -3
- package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +4 -1
- package/src/components/ui/sidebar/panels/site-panel/registry-tree-node.tsx +1 -3
- package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +1 -4
- package/src/components/ui/sidebar/panels/site-panel/shelf-tree-node.tsx +1 -3
- package/src/components/ui/sidebar/panels/site-panel/slab-tree-node.tsx +21 -13
- package/src/components/ui/sidebar/panels/site-panel/solar-panel-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/spawn-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/stair-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/tree-node.tsx +13 -37
- package/src/components/ui/sidebar/panels/site-panel/unit-tree-node.tsx +2 -3
- package/src/components/ui/sidebar/panels/site-panel/wall-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/window-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/zone-tree-node.tsx +9 -4
- package/src/components/ui/sidebar/panels/zone-panel/index.tsx +2 -4
- package/src/components/ui/sidebar/tab-bar.tsx +14 -4
- package/src/components/ui/sidebar/use-plugin-panels.tsx +15 -5
- package/src/components/viewer/floorplan-compass-button.tsx +9 -1
- package/src/components/viewer/floorplan-preview.tsx +5 -6
- package/src/components/viewer/viewer-controls-bar.tsx +18 -6
- package/src/components/viewer/viewer-hover-label.tsx +34 -0
- package/src/components/viewer/viewer-rooms.tsx +191 -0
- package/src/components/viewer/viewer-scene-header.tsx +181 -145
- package/src/components/viewer/viewer-selection-manager.tsx +124 -0
- package/src/components/viewer/viewer-stage.tsx +2 -2
- package/src/components/viewer-zone-system.tsx +3 -8
- package/src/hooks/use-auto-save.integration.test.tsx +215 -43
- package/src/hooks/use-auto-save.ts +60 -9
- package/src/hooks/use-ceiling-events.test.ts +123 -118
- package/src/hooks/use-grid-events.test.ts +105 -105
- package/src/hooks/use-keyboard.test.ts +243 -19
- package/src/hooks/use-keyboard.ts +118 -83
- package/src/hooks/use-open-wall-ends.test.ts +99 -0
- package/src/hooks/use-open-wall-ends.ts +238 -0
- package/src/hooks/use-placement-notice.test.ts +71 -0
- package/src/hooks/use-placement-notice.ts +73 -0
- package/src/hooks/use-selected-room.ts +143 -0
- package/src/index.tsx +312 -58
- package/src/lib/__fixtures__/owner-victor-seattle-parking.json +1 -0
- package/src/lib/__fixtures__/owner-villa-aurelia-basement.json +1 -0
- package/src/lib/add-storey.test.ts +177 -0
- package/src/lib/add-storey.ts +59 -0
- package/src/lib/below-grade.test.tsx +171 -0
- package/src/lib/below-grade.ts +133 -0
- package/src/lib/camera-facing.test.ts +24 -0
- package/src/lib/camera-facing.ts +24 -0
- package/src/lib/ceiling-edit-session.test.ts +321 -0
- package/src/lib/ceiling-edit-session.ts +206 -0
- package/src/lib/ceiling-region-session.test.ts +179 -0
- package/src/lib/continuation.test.ts +19 -1
- package/src/lib/continuation.ts +25 -4
- package/src/lib/direct-manipulation.ts +2 -0
- package/src/lib/door-interaction.ts +14 -0
- package/src/lib/download-project-file.ts +17 -0
- package/src/lib/editor-level-display.test.ts +96 -0
- package/src/lib/editor-level-display.ts +55 -0
- package/src/lib/editor-views.ts +178 -0
- package/src/lib/export-geometry-wait.test.ts +90 -0
- package/src/lib/export-texture-utils.ts +2 -4
- package/src/lib/floor-edit-session.ts +153 -0
- package/src/lib/floor-footprints.test.ts +563 -0
- package/src/lib/floor-footprints.ts +395 -0
- package/src/lib/floor-foundation-support.test.ts +284 -0
- package/src/lib/floor-opening-draft.ts +218 -0
- package/src/lib/floor-openings.test.ts +216 -0
- package/src/lib/floor-region-geometry.ts +191 -0
- package/src/lib/floor-region-session.test.ts +485 -0
- package/src/lib/floor-region-session.ts +589 -0
- package/src/lib/floor-region-snap.ts +101 -0
- package/src/lib/floor-step-hover.test.ts +32 -0
- package/src/lib/floorplan/annotation-visibility.ts +17 -0
- package/src/lib/floorplan/dimension-drive.test.ts +360 -0
- package/src/lib/floorplan/dimension-drive.ts +479 -0
- package/src/lib/floorplan/floorplan-export.test.ts +12 -8
- package/src/lib/floorplan/floorplan-export.tsx +32 -8
- package/src/lib/floorplan/floorplan-extension.ts +32 -0
- package/src/lib/floorplan/floorplan-mode.test.ts +4 -0
- package/src/lib/floorplan/floorplan-mode.ts +2 -0
- package/src/lib/floorplan/floorplan-pdfkit-document.ts +363 -27
- package/src/lib/floorplan/floorplan-pdfkit-renderer.test.ts +177 -8
- package/src/lib/floorplan/floorplan-pdfkit-renderer.ts +60 -25
- package/src/lib/floorplan/floorplan-plugin-install.test.tsx +138 -0
- package/src/lib/floorplan/floorplan-readonly.ts +6 -0
- package/src/lib/floorplan/geometry.ts +13 -6
- package/src/lib/floorplan/index.ts +0 -9
- package/src/lib/floorplan/items.ts +5 -2
- package/src/lib/floorplan/marks.test.ts +213 -0
- package/src/lib/floorplan/marks.ts +238 -0
- package/src/lib/floorplan/open-wall-ends.test.ts +268 -0
- package/src/lib/floorplan/open-wall-ends.ts +162 -0
- package/src/lib/floorplan/pdf-fonts/GeistMono-Bold.ttf +0 -0
- package/src/lib/floorplan/pdf-fonts/GeistMono-Regular.ttf +0 -0
- package/src/lib/floorplan/pdf-fonts/LICENSE-GeistMono.txt +92 -0
- package/src/lib/floorplan/pdf-fonts/LICENSE-LiberationSans.txt +102 -0
- package/src/lib/floorplan/pdf-fonts/LiberationSans-Bold.ttf +0 -0
- package/src/lib/floorplan/pdf-fonts/LiberationSans-Regular.ttf +0 -0
- package/src/lib/floorplan/pdfkit-standard-fonts.d.ts +5 -0
- package/src/lib/floorplan/schedules.test.ts +189 -0
- package/src/lib/floorplan/schedules.ts +339 -0
- package/src/lib/floorplan/sheet-export.test.ts +124 -0
- package/src/lib/floorplan/sheet-export.ts +318 -0
- package/src/lib/floorplan/site-plan/build-site-plan-drawing.ts +768 -0
- package/src/lib/floorplan/site-plan/contours.test.ts +43 -0
- package/src/lib/floorplan/site-plan/contributors.ts +97 -0
- package/src/lib/floorplan/site-plan/coverage.ts +230 -0
- package/src/lib/floorplan/site-plan/drawing-type-switch.test.ts +15 -0
- package/src/lib/floorplan/site-plan/drawing-type-switch.tsx +86 -0
- package/src/lib/floorplan/site-plan/front-edge.test.ts +103 -0
- package/src/lib/floorplan/site-plan/front-edge.ts +157 -0
- package/src/lib/floorplan/site-plan/geometry.test.ts +269 -0
- package/src/lib/floorplan/site-plan/geometry.ts +142 -0
- package/src/lib/floorplan/site-plan/index.ts +55 -0
- package/src/lib/floorplan/site-plan/site-annotations.test.ts +483 -0
- package/src/lib/floorplan/site-plan/site-annotations.ts +1084 -0
- package/src/lib/floorplan/site-plan/site-parts.ts +287 -0
- package/src/lib/floorplan/site-plan/site-plan-layer.tsx +138 -0
- package/src/lib/floorplan/site-plan/street-name.test.ts +69 -0
- package/src/lib/floorplan/site-plan/street-name.ts +302 -0
- package/src/lib/floorplan/site-plan/yards.test.ts +70 -0
- package/src/lib/floorplan/types.ts +1 -27
- package/src/lib/follow-pascal-exterior.test-fixture.ts +17 -0
- package/src/lib/follow-pascal-exterior.test.ts +171 -0
- package/src/lib/follow-pascal-exterior.ts +39 -0
- package/src/lib/follow-pascal-presentation.test.ts +203 -0
- package/src/lib/follow-pascal-presentation.ts +129 -0
- package/src/lib/follow-pascal-sight.ts +84 -0
- package/src/lib/follow-pascal-targets.test.ts +406 -0
- package/src/lib/follow-pascal-targets.ts +198 -0
- package/src/lib/follow-pascal.test.ts +350 -0
- package/src/lib/follow-pascal.ts +284 -0
- package/src/lib/fresh-planar-placement.test.ts +148 -0
- package/src/lib/fresh-planar-placement.ts +114 -37
- package/src/lib/geometry-script/author.ts +157 -0
- package/src/lib/geometry-script/client.ts +159 -0
- package/src/lib/geometry-script/finish-scripts.ts +127 -0
- package/src/lib/geometry-script/protocol.ts +13 -0
- package/src/lib/gesture-lifecycle.test.ts +595 -0
- package/src/lib/gesture-lifecycle.ts +290 -0
- package/src/lib/glb-export-zone-holes.test.ts +41 -0
- package/src/lib/glb-export.test.ts +636 -126
- package/src/lib/glb-export.ts +241 -120
- package/src/lib/history.test.ts +18 -7
- package/src/lib/history.ts +7 -0
- package/src/lib/hud-title.ts +109 -0
- package/src/lib/hydration-gated-storage.ts +49 -0
- package/src/lib/ifc-export.test.ts +174 -0
- package/src/lib/ifc-export.ts +201 -0
- package/src/lib/ifc-parts.ts +15 -0
- package/src/lib/inspector-expanded.test.ts +44 -0
- package/src/lib/inspector-expanded.ts +36 -0
- package/src/lib/interaction/scope.ts +22 -0
- package/src/lib/keyboard-pan.test.ts +129 -7
- package/src/lib/keyboard-pan.ts +161 -12
- package/src/lib/level-selection.test.ts +57 -0
- package/src/lib/level-selection.ts +16 -1
- package/src/lib/live-gesture-round-trip.test.ts +360 -0
- package/src/lib/lot/__fixtures__/map-dossier-miami-shores.json +1 -0
- package/src/lib/lot/__fixtures__/map-dossier-stpete.json +1 -0
- package/src/lib/lot/clean-ring.test.ts +187 -0
- package/src/lib/lot/clean-ring.ts +217 -0
- package/src/lib/lot/dossier.test.ts +202 -0
- package/src/lib/lot/dossier.ts +498 -0
- package/src/lib/lot/drop-in.test.ts +326 -0
- package/src/lib/lot/drop-in.ts +392 -0
- package/src/lib/lot/index.ts +43 -0
- package/src/lib/lot/lot-patch.test.ts +340 -0
- package/src/lib/lot/lot-patch.ts +394 -0
- package/src/lib/lot/parcel-provider.ts +43 -0
- package/src/lib/lot/terrain.test.ts +161 -0
- package/src/lib/lot/terrain.ts +266 -0
- package/src/lib/material-catalog-model.ts +3 -1
- package/src/lib/material-paint-panel-model.ts +9 -5
- package/src/lib/material-paint.ts +4 -0
- package/src/lib/measurement-kind.test.ts +6 -8
- package/src/lib/measurements.test.ts +23 -0
- package/src/lib/mezzanine-actions.test.ts +342 -0
- package/src/lib/mezzanine-draft.test.ts +501 -0
- package/src/lib/mezzanine-draft.ts +278 -0
- package/src/lib/mezzanine-messages.ts +26 -0
- package/src/lib/mezzanine-selection.test.ts +207 -0
- package/src/lib/mezzanine-stairs.ts +46 -0
- package/src/lib/model-export.ts +3 -1
- package/src/lib/node-action-movement.ts +17 -6
- package/src/lib/node-display-label.ts +37 -0
- package/src/lib/orbit-floor-clearance.test.ts +201 -0
- package/src/lib/orbit-floor-clearance.ts +154 -0
- package/src/lib/paint-commit-route.test.ts +37 -0
- package/src/lib/paint-commit-route.ts +17 -0
- package/src/lib/paint-eyedropper.test.tsx +165 -0
- package/src/lib/paint-eyedropper.ts +99 -0
- package/src/lib/paint-pass-through.test.ts +122 -0
- package/src/lib/paint-pass-through.ts +78 -0
- package/src/lib/paint-region-hover.ts +25 -0
- package/src/lib/paint-region-mode.ts +154 -0
- package/src/lib/paint-regions.test.ts +166 -0
- package/src/lib/paint-regions.ts +192 -0
- package/src/lib/paint-scope.test.ts +317 -35
- package/src/lib/paint-scope.ts +267 -25
- package/src/lib/panel-rows.ts +21 -0
- package/src/lib/parametric-node-update.ts +16 -7
- package/src/lib/plate-paint-affected.test.ts +300 -0
- package/src/lib/plate-paint-affected.ts +177 -0
- package/src/lib/plugin-chat.ts +65 -0
- package/src/lib/plugin-panels.test.ts +25 -0
- package/src/lib/plugin-panels.ts +94 -0
- package/src/lib/point-ask/__fixtures__/consumer-browser.tsx +76 -0
- package/src/lib/point-ask/__fixtures__/house.ts +81 -0
- package/src/lib/point-ask/ask-created.test.ts +195 -0
- package/src/lib/point-ask/ask-flow.test.ts +380 -0
- package/src/lib/point-ask/build-context.test.ts +173 -0
- package/src/lib/point-ask/build-context.ts +94 -0
- package/src/lib/point-ask/capture-crop.ts +129 -0
- package/src/lib/point-ask/choreography.ts +69 -0
- package/src/lib/point-ask/compare.test.ts +145 -0
- package/src/lib/point-ask/compare.ts +73 -0
- package/src/lib/point-ask/describe-target.test.ts +165 -0
- package/src/lib/point-ask/describe-target.ts +234 -0
- package/src/lib/point-ask/dictation.ts +79 -0
- package/src/lib/point-ask/edge-marker.test.ts +61 -0
- package/src/lib/point-ask/edge-marker.ts +27 -0
- package/src/lib/point-ask/frame-loop.ts +25 -0
- package/src/lib/point-ask/history-marks.test.ts +94 -0
- package/src/lib/point-ask/history-marks.ts +39 -0
- package/src/lib/point-ask/host-api.ts +32 -0
- package/src/lib/point-ask/outline-box.test.ts +30 -0
- package/src/lib/point-ask/outline-box.ts +11 -0
- package/src/lib/point-ask/overlay-metrics.ts +6 -0
- package/src/lib/point-ask/pick.test.ts +220 -0
- package/src/lib/point-ask/pick.ts +121 -0
- package/src/lib/point-ask/pin-machine.test.ts +494 -0
- package/src/lib/point-ask/pin-machine.ts +217 -0
- package/src/lib/point-ask/placement.test.ts +203 -0
- package/src/lib/point-ask/placement.ts +141 -0
- package/src/lib/point-ask/pointer-tracker.ts +34 -0
- package/src/lib/point-ask/projector.ts +83 -0
- package/src/lib/point-ask/region.test.ts +157 -0
- package/src/lib/point-ask/region.ts +136 -0
- package/src/lib/point-ask/retry.test.ts +217 -0
- package/src/lib/point-ask/retry.ts +37 -0
- package/src/lib/point-ask/scene-commit.test.ts +312 -0
- package/src/lib/point-ask/scene-commit.ts +32 -0
- package/src/lib/point-ask/session.ts +1391 -0
- package/src/lib/point-ask/spring-keyframes.test.ts +45 -0
- package/src/lib/point-ask/spring-keyframes.ts +38 -0
- package/src/lib/point-ask/spring.test.ts +63 -0
- package/src/lib/point-ask/spring.ts +107 -0
- package/src/lib/point-ask/suggestions.test.ts +80 -0
- package/src/lib/point-ask/suggestions.ts +125 -0
- package/src/lib/point-ask/target-scope.test.ts +622 -0
- package/src/lib/point-ask/target-scope.ts +338 -0
- package/src/lib/point-ask/types.ts +48 -0
- package/src/lib/portable-export.test.ts +34 -1
- package/src/lib/portable-export.ts +119 -53
- package/src/lib/print-feature-thickness.ts +10 -1
- package/src/lib/print-roof-solids.test.ts +39 -1
- package/src/lib/print-roof-solids.ts +43 -10
- package/src/lib/print-shell-compiler-manifold-core.ts +1 -1
- package/src/lib/print-shell-compiler.ts +1 -0
- package/src/lib/registered-draft-snap.ts +12 -0
- package/src/lib/roof-duplication.ts +10 -2
- package/src/lib/room-assembly-overlay.test.ts +275 -0
- package/src/lib/room-assembly-overlay.ts +265 -0
- package/src/lib/room-built-on.test.ts +379 -0
- package/src/lib/room-built-on.ts +138 -0
- package/src/lib/room-construction-commands.ts +712 -0
- package/src/lib/room-construction.test.ts +746 -0
- package/src/lib/room-construction.ts +385 -0
- package/src/lib/room-controls-phase6.test.ts +630 -0
- package/src/lib/room-divide-session.ts +523 -0
- package/src/lib/room-handle-drag.ts +1068 -0
- package/src/lib/room-name-catalog.test.ts +90 -0
- package/src/lib/room-name-catalog.ts +168 -0
- package/src/lib/room-push-dimensions.test.ts +311 -0
- package/src/lib/room-push-dimensions.ts +251 -0
- package/src/lib/room-selection-commands.ts +62 -0
- package/src/lib/room-selection.test.ts +1017 -0
- package/src/lib/room-selection.ts +417 -0
- package/src/lib/room-structure-commands.ts +94 -0
- package/src/lib/room-structure.test.ts +921 -0
- package/src/lib/room-transform-session.ts +570 -0
- package/src/lib/room-zone-routing.test.ts +294 -0
- package/src/lib/room-zone-routing.ts +197 -0
- package/src/lib/scene-clipboard.test.ts +610 -1
- package/src/lib/scene-clipboard.ts +269 -58
- package/src/lib/scene-material-refs.test.ts +79 -0
- package/src/lib/scene-material-refs.ts +79 -0
- package/src/lib/scene.test.ts +24 -36
- package/src/lib/scene.ts +33 -57
- package/src/lib/selection-routing.test.ts +129 -45
- package/src/lib/selection-routing.ts +54 -75
- package/src/lib/session-writes.test.ts +120 -0
- package/src/lib/session-writes.ts +205 -0
- package/src/lib/sfx-bus.ts +13 -0
- package/src/lib/sfx-player.test.ts +70 -9
- package/src/lib/sfx-player.ts +6 -0
- package/src/lib/sidebar-panel.ts +62 -0
- package/src/lib/site-boundary.test.ts +4 -6
- package/src/lib/site-boundary.ts +1 -1
- package/src/lib/snapping-mode.test.ts +4 -0
- package/src/lib/snapping-mode.ts +8 -1
- package/src/lib/stair-levels.test.ts +25 -0
- package/src/lib/stair-levels.ts +22 -3
- package/src/lib/terrace-draft.test.ts +145 -0
- package/src/lib/terrace-draft.ts +214 -0
- package/src/lib/tool-cursor-icon.test.ts +16 -0
- package/src/lib/tool-cursor-icon.ts +11 -0
- package/src/lib/typing-target.ts +9 -0
- package/src/lib/units.ts +77 -39
- package/src/lib/vector-edges.test.ts +58 -0
- package/src/lib/vector-edges.ts +400 -0
- package/src/lib/viewer-selection.test.ts +577 -0
- package/src/lib/viewer-selection.ts +580 -0
- package/src/lib/wall-draw-variant.test.ts +71 -0
- package/src/lib/wall-draw-variant.ts +91 -0
- package/src/lib/wall-paint-region-session.ts +246 -0
- package/src/lib/wall-paint-region.test.ts +373 -0
- package/src/lib/wall-placement-pointer.test.ts +42 -0
- package/src/lib/wall-placement-pointer.ts +57 -0
- package/src/lib/wall-polygon-draft.test.ts +262 -0
- package/src/lib/wall-polygon-draft.ts +286 -0
- package/src/lib/wall-push.test.ts +453 -0
- package/src/lib/wall-region-face.ts +352 -0
- package/src/lib/wall-region-handles.test.ts +304 -0
- package/src/lib/wall-region-handles.ts +368 -0
- package/src/lib/wall-region-list.test.ts +119 -0
- package/src/lib/wall-region-list.ts +136 -0
- package/src/lib/wall-region-snap.ts +110 -0
- package/src/lib/window-changes.ts +35 -0
- package/src/lib/window-interaction.ts +14 -0
- package/src/lib/zone-content.ts +4 -1
- package/src/lib/zone-name.test.ts +17 -0
- package/src/lib/zone-name.ts +17 -0
- package/src/store/opens-in-select-mode.test.ts +223 -0
- package/src/store/paint-mode.test.ts +188 -0
- package/src/store/terrain-sculpt-mode.test.ts +19 -21
- package/src/store/tool-mode.test.ts +137 -6
- package/src/store/use-audio.test.ts +146 -0
- package/src/store/use-audio.tsx +127 -3
- package/src/store/use-construction-reveal.test.ts +173 -0
- package/src/store/use-construction-reveal.ts +145 -0
- package/src/store/use-corner-snap-hint.test.ts +24 -0
- package/src/store/use-corner-snap-hint.ts +47 -0
- package/src/store/use-delete-confirmation.ts +28 -1
- package/src/store/use-drawing-view.test.ts +24 -3
- package/src/store/use-drawing-view.ts +29 -1
- package/src/store/use-editor.tsx +432 -321
- package/src/store/use-floorplan-draft-preview.ts +13 -0
- package/src/store/use-floorplan-marquee.ts +12 -2
- package/src/store/use-follow-pascal.test.ts +62 -0
- package/src/store/use-follow-pascal.ts +53 -0
- package/src/store/use-point-ask.ts +247 -0
- package/src/store/use-quick-measurement-hud.ts +3 -3
- package/src/store/use-stair-build-preview.ts +33 -5
- package/src/store/use-wall-move-ghosts.ts +4 -2
- package/src/store/use-wall-region-handles-selection.test.ts +222 -0
- package/src/store/use-wall-region-handles-selection.ts +139 -0
- package/src/store/view-layout.test.ts +201 -0
- package/src/store/view-layout.ts +199 -0
- package/src/test-utils/immediate-animation-frames.ts +16 -0
- package/src/test-utils/live-gesture-round-trip.ts +224 -0
- package/src/test-utils/render-current-markup.tsx +16 -0
- package/src/test-utils/selection-harness.ts +82 -0
- package/src/components/editor-2d/renderers/floorplan-stair-layer.tsx +0 -499
- package/src/components/systems/zone/zone-label-editor-system.tsx +0 -333
- package/src/components/tools/fence/fence-drafting.test.ts +0 -100
- package/src/components/tools/fence/fence-drafting.ts +0 -266
- package/src/components/tools/stair/stair-click-guard.test.ts +0 -58
- package/src/components/tools/stair/stair-click-guard.ts +0 -72
- package/src/components/tools/stair/stair-defaults.ts +0 -18
- package/src/components/tools/stair/stair-tool.tsx +0 -634
- package/src/components/ui/sidebar/panels/plugins-panel.tsx +0 -218
- package/src/components/viewer/viewer-units-panel.tsx +0 -116
- package/src/lib/floorplan/stairs.ts +0 -489
- package/src/lib/level-duplication.test.ts +0 -144
- package/src/lib/level-duplication.ts +0 -195
|
@@ -11,6 +11,8 @@ import { cn } from './../../../lib/utils'
|
|
|
11
11
|
import useEditor from './../../../store/use-editor'
|
|
12
12
|
import { CameraActions } from './camera-actions'
|
|
13
13
|
import { ControlModes } from './control-modes'
|
|
14
|
+
import { FollowPascalPill } from './follow-pascal-pill'
|
|
15
|
+
import { type ActionMenuPlacement, ActionMenuPlacementProvider } from './placement'
|
|
14
16
|
import { SecondaryToggles } from './view-toggles'
|
|
15
17
|
|
|
16
18
|
// Mobile bottom offset matches the viewer's overlap behind the sheet's
|
|
@@ -18,7 +20,16 @@ import { SecondaryToggles } from './view-toggles'
|
|
|
18
20
|
// just above that strip instead of inside it.
|
|
19
21
|
const MOBILE_BOTTOM_OFFSET = 24
|
|
20
22
|
|
|
21
|
-
export function ActionMenu({
|
|
23
|
+
export function ActionMenu({
|
|
24
|
+
className,
|
|
25
|
+
inline = false,
|
|
26
|
+
placement = 'bottom',
|
|
27
|
+
}: {
|
|
28
|
+
className?: string
|
|
29
|
+
// Rendered in the flow of a layout slot instead of floating over the viewer.
|
|
30
|
+
inline?: boolean
|
|
31
|
+
placement?: ActionMenuPlacement
|
|
32
|
+
}) {
|
|
22
33
|
const isMobile = useIsMobile()
|
|
23
34
|
const readOnly = useScene((s) => s.readOnly)
|
|
24
35
|
const hasSelectionOnMobile = useViewer((s) => isMobile && s.selection.selectedIds.length > 0)
|
|
@@ -47,41 +58,53 @@ export function ActionMenu({ className }: { className?: string }) {
|
|
|
47
58
|
? { duration: 0 }
|
|
48
59
|
: { type: 'spring' as const, bounce: 0.2, duration: 0.4 }
|
|
49
60
|
|
|
61
|
+
// Mobile keeps the bottom rail: the sheet owns the rest of the screen.
|
|
62
|
+
const effectivePlacement = isMobile ? 'bottom' : placement
|
|
63
|
+
|
|
50
64
|
return (
|
|
51
|
-
<
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
<ActionMenuPlacementProvider value={effectivePlacement}>
|
|
66
|
+
<TooltipProvider>
|
|
67
|
+
<FollowPascalPill />
|
|
68
|
+
<motion.div
|
|
69
|
+
className={cn(
|
|
70
|
+
'z-50',
|
|
71
|
+
isMobile
|
|
72
|
+
? 'absolute left-1/2 origin-bottom -translate-x-1/2 scale-90'
|
|
73
|
+
: inline
|
|
74
|
+
? 'relative'
|
|
75
|
+
: effectivePlacement === 'top'
|
|
76
|
+
? 'fixed top-3 left-1/2 -translate-x-1/2'
|
|
77
|
+
: 'fixed bottom-6 left-1/2 -translate-x-1/2',
|
|
78
|
+
'rounded-2xl border border-border bg-background/90 shadow-2xl backdrop-blur-md',
|
|
79
|
+
'transition-colors duration-200 ease-out',
|
|
80
|
+
className,
|
|
81
|
+
)}
|
|
82
|
+
layout
|
|
83
|
+
style={isMobile ? { bottom: MOBILE_BOTTOM_OFFSET } : undefined}
|
|
84
|
+
transition={transition}
|
|
85
|
+
>
|
|
86
|
+
{isMobile ? (
|
|
87
|
+
<div className="flex flex-col items-stretch gap-0.5 px-2 py-1.5">
|
|
88
|
+
{/* Row 1: control modes only */}
|
|
89
|
+
<div className="flex items-center justify-center gap-1">
|
|
90
|
+
<ControlModes />
|
|
91
|
+
</div>
|
|
92
|
+
{/* Row 2: secondary toggles (orbit + top view hidden) */}
|
|
93
|
+
<div className="flex items-center justify-center gap-1 border-border/50 border-t pt-1">
|
|
94
|
+
<SecondaryToggles />
|
|
95
|
+
</div>
|
|
69
96
|
</div>
|
|
70
|
-
|
|
71
|
-
<div className="flex items-center justify-center gap-1
|
|
97
|
+
) : (
|
|
98
|
+
<div className="flex items-center justify-center gap-1 px-2 py-1.5">
|
|
99
|
+
<ControlModes />
|
|
100
|
+
<div className="mx-1 h-5 w-px bg-border" />
|
|
72
101
|
<SecondaryToggles />
|
|
102
|
+
<div className="mx-1 h-5 w-px bg-border" />
|
|
103
|
+
<CameraActions />
|
|
73
104
|
</div>
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
<div className="mx-1 h-5 w-px bg-border" />
|
|
79
|
-
<SecondaryToggles />
|
|
80
|
-
<div className="mx-1 h-5 w-px bg-border" />
|
|
81
|
-
<CameraActions />
|
|
82
|
-
</div>
|
|
83
|
-
)}
|
|
84
|
-
</motion.div>
|
|
85
|
-
</TooltipProvider>
|
|
105
|
+
)}
|
|
106
|
+
</motion.div>
|
|
107
|
+
</TooltipProvider>
|
|
108
|
+
</ActionMenuPlacementProvider>
|
|
86
109
|
)
|
|
87
110
|
}
|
|
@@ -22,9 +22,11 @@ import { useState } from 'react'
|
|
|
22
22
|
import type { CreatableMeasurementKind } from '../../../lib/measurement-kind'
|
|
23
23
|
import { cn } from '../../../lib/utils'
|
|
24
24
|
import useEditor from '../../../store/use-editor'
|
|
25
|
+
import { VIEW_2D } from '../../../store/view-layout'
|
|
25
26
|
import useFloorplanMode from '../../../store/use-floorplan-mode'
|
|
26
27
|
import { Popover, PopoverContent, PopoverTrigger } from '../primitives/popover'
|
|
27
28
|
import { ActionButton } from './action-button'
|
|
29
|
+
import { useActionMenuPopupSide } from './placement'
|
|
28
30
|
|
|
29
31
|
const measurementOptions = [
|
|
30
32
|
{ kind: 'distance', label: 'Distance', icon: Ruler },
|
|
@@ -61,6 +63,7 @@ const constructionDimensionOptions = [
|
|
|
61
63
|
}[]
|
|
62
64
|
|
|
63
65
|
export function MeasurementControl() {
|
|
66
|
+
const popupSide = useActionMenuPopupSide()
|
|
64
67
|
const [isOpen, setIsOpen] = useState(false)
|
|
65
68
|
const mode = useEditor((state) => state.mode)
|
|
66
69
|
const tool = useEditor((state) => state.tool)
|
|
@@ -74,12 +77,10 @@ export function MeasurementControl() {
|
|
|
74
77
|
(state) => state.toolDefaults['construction-dimension']?.mode,
|
|
75
78
|
)
|
|
76
79
|
const setMode = useEditor((state) => state.setMode)
|
|
77
|
-
const setPhase = useEditor((state) => state.setPhase)
|
|
78
80
|
const setLastMeasurementKind = useEditor((state) => state.setLastMeasurementKind)
|
|
79
|
-
const setStructureLayer = useEditor((state) => state.setStructureLayer)
|
|
80
81
|
const setTool = useEditor((state) => state.setTool)
|
|
81
82
|
const setToolDefaults = useEditor((state) => state.setToolDefaults)
|
|
82
|
-
const
|
|
83
|
+
const showView = useEditor((state) => state.showView)
|
|
83
84
|
|
|
84
85
|
const selectedOption =
|
|
85
86
|
measurementOptions.find((option) => option.kind === selectedKind) ?? measurementOptions[0]
|
|
@@ -104,8 +105,6 @@ export function MeasurementControl() {
|
|
|
104
105
|
: selectedOption.label
|
|
105
106
|
|
|
106
107
|
const activateMeasurement = (kind: CreatableMeasurementKind) => {
|
|
107
|
-
setPhase('structure')
|
|
108
|
-
setStructureLayer('elements')
|
|
109
108
|
setLastMeasurementKind(kind)
|
|
110
109
|
setToolDefaults('measurement', { kind })
|
|
111
110
|
setMode('build')
|
|
@@ -121,8 +120,6 @@ export function MeasurementControl() {
|
|
|
121
120
|
}
|
|
122
121
|
|
|
123
122
|
const activateSmartMeasurement = () => {
|
|
124
|
-
setPhase('structure')
|
|
125
|
-
setStructureLayer('elements')
|
|
126
123
|
setToolDefaults('measurement', { kind: 'smart' })
|
|
127
124
|
setMode('build')
|
|
128
125
|
setTool('measurement')
|
|
@@ -136,9 +133,7 @@ export function MeasurementControl() {
|
|
|
136
133
|
useFloorplanMode.getState().showExpertModeNotice('Construction Dimension')
|
|
137
134
|
return
|
|
138
135
|
}
|
|
139
|
-
|
|
140
|
-
setStructureLayer('elements')
|
|
141
|
-
setViewMode('2d')
|
|
136
|
+
showView(VIEW_2D)
|
|
142
137
|
setToolDefaults('construction-dimension', { chainMode, mode: dimensionMode })
|
|
143
138
|
setMode('build')
|
|
144
139
|
setTool('construction-dimension')
|
|
@@ -153,8 +148,8 @@ export function MeasurementControl() {
|
|
|
153
148
|
className={cn(
|
|
154
149
|
'rounded-r-none p-0 text-muted-foreground',
|
|
155
150
|
isControlActive
|
|
156
|
-
? 'bg-cyan-500/20 text-cyan-
|
|
157
|
-
: 'hover:bg-cyan-500/15 hover:text-cyan-400',
|
|
151
|
+
? 'bg-cyan-500/20 text-cyan-700 hover:bg-cyan-500/20 dark:text-cyan-400 dark:hover:text-accent-foreground'
|
|
152
|
+
: 'hover:bg-cyan-500/15 hover:text-cyan-700 dark:hover:text-cyan-400',
|
|
158
153
|
)}
|
|
159
154
|
label={`Measure: ${selectedLabel}`}
|
|
160
155
|
onClick={handlePrimaryClick}
|
|
@@ -173,8 +168,8 @@ export function MeasurementControl() {
|
|
|
173
168
|
className={cn(
|
|
174
169
|
'flex h-11 w-6 items-center justify-center rounded-r-lg text-muted-foreground transition-colors',
|
|
175
170
|
isOpen
|
|
176
|
-
? 'bg-cyan-500/15 text-cyan-400'
|
|
177
|
-
: 'hover:bg-cyan-500/10 hover:text-cyan-400',
|
|
171
|
+
? 'bg-cyan-500/15 text-cyan-700 dark:text-cyan-400'
|
|
172
|
+
: 'hover:bg-cyan-500/10 hover:text-cyan-700 dark:hover:text-cyan-400',
|
|
178
173
|
)}
|
|
179
174
|
type="button"
|
|
180
175
|
>
|
|
@@ -189,7 +184,7 @@ export function MeasurementControl() {
|
|
|
189
184
|
<PopoverContent
|
|
190
185
|
align="center"
|
|
191
186
|
className="max-h-[70vh] w-64 overflow-y-auto rounded-lg border-border/45 bg-background/96 p-2 shadow-elevation-3 backdrop-blur-xl"
|
|
192
|
-
side=
|
|
187
|
+
side={popupSide}
|
|
193
188
|
sideOffset={14}
|
|
194
189
|
>
|
|
195
190
|
<div aria-label="Measurement type" className="space-y-1" role="menu">
|
|
@@ -205,8 +200,8 @@ export function MeasurementControl() {
|
|
|
205
200
|
className={cn(
|
|
206
201
|
'flex h-9 w-full items-center gap-2 rounded-md px-2.5 text-left text-sm transition-colors',
|
|
207
202
|
isSelected
|
|
208
|
-
? 'bg-white/10 text-foreground'
|
|
209
|
-
: 'text-muted-foreground hover:bg-white/8 hover:text-foreground',
|
|
203
|
+
? 'bg-black/6 dark:bg-white/10 text-foreground'
|
|
204
|
+
: 'text-muted-foreground hover:bg-black/5 dark:hover:bg-white/8 hover:text-foreground',
|
|
210
205
|
)}
|
|
211
206
|
key={option.kind}
|
|
212
207
|
onClick={() => {
|
|
@@ -241,8 +236,8 @@ export function MeasurementControl() {
|
|
|
241
236
|
className={cn(
|
|
242
237
|
'flex h-9 w-full items-center gap-2 rounded-md px-2.5 text-left text-sm transition-colors',
|
|
243
238
|
isSelected
|
|
244
|
-
? 'bg-white/10 text-foreground'
|
|
245
|
-
: 'text-muted-foreground hover:bg-white/8 hover:text-foreground',
|
|
239
|
+
? 'bg-black/6 dark:bg-white/10 text-foreground'
|
|
240
|
+
: 'text-muted-foreground hover:bg-black/5 dark:hover:bg-white/8 hover:text-foreground',
|
|
246
241
|
)}
|
|
247
242
|
key={`${option.mode}-${option.chainMode}`}
|
|
248
243
|
onClick={() => {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react'
|
|
2
|
+
|
|
3
|
+
/** Viewport edge the action menu docks to. */
|
|
4
|
+
export type ActionMenuPlacement = 'bottom' | 'top'
|
|
5
|
+
|
|
6
|
+
/** Where chrome under a top-docked menu starts: below the host toolbar row and the menu itself. */
|
|
7
|
+
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
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useHasPointAskHandler } from '@pascal-app/core'
|
|
4
|
+
import { canPoint, enterPointMode, leavePointMode } from '../../../lib/point-ask/session'
|
|
5
|
+
import { cn } from '../../../lib/utils'
|
|
6
|
+
import useEditor from '../../../store/use-editor'
|
|
7
|
+
import { usePointAsk } from '../../../store/use-point-ask'
|
|
8
|
+
import { isViewVisible, VIEW_3D } from '../../../store/view-layout'
|
|
9
|
+
import { ActionButton } from './action-button'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Point and ask (key C): the toolbar's way into the mode where hovering names what Pascal would
|
|
13
|
+
* be told about and a click opens a bubble to ask. Offered only where a host answers asks. In
|
|
14
|
+
* the 2D plan and the walkthrough it is disabled and says so (v1 works in the 3D view).
|
|
15
|
+
*/
|
|
16
|
+
export function PointAskButton() {
|
|
17
|
+
const available = useHasPointAskHandler()
|
|
18
|
+
const active = usePointAsk((s) => s.active)
|
|
19
|
+
const sceneVisible = useEditor((s) => isViewVisible(s, VIEW_3D))
|
|
20
|
+
const firstPerson = useEditor((s) => s.isFirstPersonMode)
|
|
21
|
+
if (!(available || active)) return null
|
|
22
|
+
const unavailable = !active && (!sceneVisible || firstPerson)
|
|
23
|
+
return (
|
|
24
|
+
<ActionButton
|
|
25
|
+
className={cn(
|
|
26
|
+
'group text-muted-foreground',
|
|
27
|
+
active
|
|
28
|
+
? 'bg-[#a99bff]/20 text-[#5d49df] dark:text-[#c9c1ff] dark:hover:text-accent-foreground'
|
|
29
|
+
: 'hover:bg-[#a99bff]/15 hover:text-[#5d49df] dark:hover:text-[#c9c1ff]',
|
|
30
|
+
)}
|
|
31
|
+
data-guide-target="mode-point-ask"
|
|
32
|
+
disabled={unavailable}
|
|
33
|
+
isActive={active}
|
|
34
|
+
label="Point and ask"
|
|
35
|
+
onClick={() => {
|
|
36
|
+
if (active) leavePointMode()
|
|
37
|
+
else if (canPoint()) enterPointMode(true)
|
|
38
|
+
}}
|
|
39
|
+
shortcut="C"
|
|
40
|
+
size="icon"
|
|
41
|
+
tooltipContent={
|
|
42
|
+
unavailable ? <p>Point and ask works in the 3D view</p> : <p>Point and ask (C)</p>
|
|
43
|
+
}
|
|
44
|
+
variant="ghost"
|
|
45
|
+
>
|
|
46
|
+
<svg aria-hidden className="h-5 w-5" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1.6" viewBox="0 0 24 24">
|
|
47
|
+
<path d="M4.5 3.5l8.2 3.7-3.4 1.3-1.3 3.4z" fill="currentColor" fillOpacity="0.25" />
|
|
48
|
+
<path d="M12.5 12.5h6.5a2 2 0 012 2v3a2 2 0 01-2 2h-2.2l-2.3 2v-2h-2a2 2 0 01-2-2v-3a2 2 0 012-2z" />
|
|
49
|
+
</svg>
|
|
50
|
+
</ActionButton>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
@@ -20,6 +20,7 @@ import { useUploadStore } from '../../../store/use-upload'
|
|
|
20
20
|
import { SliderControl } from '../controls/slider-control'
|
|
21
21
|
import { Popover, PopoverContent, PopoverTrigger } from '../primitives/popover'
|
|
22
22
|
import { ActionButton } from './action-button'
|
|
23
|
+
import { useActionMenuPopupSide } from './placement'
|
|
23
24
|
|
|
24
25
|
const MAX_FILE_SIZE = 200 * 1024 * 1024 // 200MB
|
|
25
26
|
const ACCEPTED_FILE_TYPES = '.glb,.gltf,image/jpeg,image/png,image/webp,image/gif'
|
|
@@ -149,7 +150,7 @@ function UploadButton({ onError }: { onError: (message: string | null) => void }
|
|
|
149
150
|
<>
|
|
150
151
|
<button
|
|
151
152
|
aria-label="Upload scan or guide image"
|
|
152
|
-
className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-border/40 text-muted-foreground transition-colors hover:bg-white/10 hover:text-foreground"
|
|
153
|
+
className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-border/40 text-muted-foreground transition-colors hover:bg-black/6 dark:hover:bg-white/10 hover:text-foreground"
|
|
153
154
|
disabled={isAddingGuide}
|
|
154
155
|
onClick={() => fileInputRef.current?.click()}
|
|
155
156
|
type="button"
|
|
@@ -170,6 +171,7 @@ function UploadButton({ onError }: { onError: (message: string | null) => void }
|
|
|
170
171
|
// ── Guides toggle + dropdown ────────────────────────────────────────────────
|
|
171
172
|
|
|
172
173
|
function GuidesControl() {
|
|
174
|
+
const popupSide = useActionMenuPopupSide()
|
|
173
175
|
const showGuides = useViewer((state) => state.showGuides)
|
|
174
176
|
const setShowGuides = useViewer((state) => state.setShowGuides)
|
|
175
177
|
const setSelection = useViewer((state) => state.setSelection)
|
|
@@ -207,8 +209,8 @@ function GuidesControl() {
|
|
|
207
209
|
className={cn(
|
|
208
210
|
'rounded-r-none p-0',
|
|
209
211
|
showGuides
|
|
210
|
-
? 'bg-white/15'
|
|
211
|
-
: 'opacity-60 grayscale hover:bg-
|
|
212
|
+
? 'bg-black/9 hover:bg-black/9 dark:bg-white/15'
|
|
213
|
+
: 'opacity-60 grayscale hover:bg-black/4 hover:opacity-100 hover:grayscale-0',
|
|
212
214
|
)}
|
|
213
215
|
label={`Guides: ${showGuides ? 'Visible' : 'Hidden'}`}
|
|
214
216
|
onClick={() => setShowGuides(!showGuides)}
|
|
@@ -221,7 +223,7 @@ function GuidesControl() {
|
|
|
221
223
|
className="h-[28px] w-[28px] object-contain"
|
|
222
224
|
src="/icons/floorplan.webp"
|
|
223
225
|
/>
|
|
224
|
-
<span className="absolute -right-1.5 -bottom-1 min-w-[14px] rounded-full bg-white/20 px-[3px] text-center font-medium text-[9px] text-white/70 leading-[14px]">
|
|
226
|
+
<span className="absolute -right-1.5 -bottom-1 min-w-[14px] rounded-full bg-black/12 dark:bg-white/20 px-[3px] text-center font-medium text-[9px] text-foreground/70 dark:text-white/70 leading-[14px]">
|
|
225
227
|
{guides.length}
|
|
226
228
|
</span>
|
|
227
229
|
</div>
|
|
@@ -236,11 +238,11 @@ function GuidesControl() {
|
|
|
236
238
|
'flex h-11 w-6 items-center justify-center rounded-r-lg transition-colors',
|
|
237
239
|
showGuides
|
|
238
240
|
? isOpen
|
|
239
|
-
? 'bg-white/10'
|
|
240
|
-
: 'bg-white/5 hover:bg-white/8'
|
|
241
|
+
? 'bg-black/6 dark:bg-white/10'
|
|
242
|
+
: 'bg-black/4 dark:bg-white/5 hover:bg-black/5 dark:hover:bg-white/8'
|
|
241
243
|
: isOpen
|
|
242
|
-
? 'bg-white/8'
|
|
243
|
-
: 'opacity-60 hover:bg-white/5 hover:opacity-100',
|
|
244
|
+
? 'bg-black/5 dark:bg-white/8'
|
|
245
|
+
: 'opacity-60 hover:bg-black/4 dark:hover:bg-white/5 hover:opacity-100',
|
|
244
246
|
)}
|
|
245
247
|
type="button"
|
|
246
248
|
>
|
|
@@ -252,7 +254,7 @@ function GuidesControl() {
|
|
|
252
254
|
<PopoverContent
|
|
253
255
|
align="center"
|
|
254
256
|
className="w-72 rounded-xl border-border/45 bg-background/96 p-3 shadow-elevation-3 backdrop-blur-xl"
|
|
255
|
-
side=
|
|
257
|
+
side={popupSide}
|
|
256
258
|
sideOffset={14}
|
|
257
259
|
>
|
|
258
260
|
<div className="space-y-3">
|
|
@@ -284,7 +286,7 @@ function GuidesControl() {
|
|
|
284
286
|
className={cn(
|
|
285
287
|
'group/item space-y-2 rounded-xl border bg-background/75 p-2.5 transition-colors',
|
|
286
288
|
selectedReferenceId === guide.id
|
|
287
|
-
? 'border-foreground/35 bg-white/10'
|
|
289
|
+
? 'border-foreground/35 bg-black/6 dark:bg-white/10'
|
|
288
290
|
: 'border-border/45',
|
|
289
291
|
)}
|
|
290
292
|
key={guide.id}
|
|
@@ -349,6 +351,7 @@ function GuidesControl() {
|
|
|
349
351
|
// ── Scans toggle + dropdown ─────────────────────────────────────────────────
|
|
350
352
|
|
|
351
353
|
function ScansControl() {
|
|
354
|
+
const popupSide = useActionMenuPopupSide()
|
|
352
355
|
const showScans = useViewer((state) => state.showScans)
|
|
353
356
|
const setShowScans = useViewer((state) => state.setShowScans)
|
|
354
357
|
const setSelection = useViewer((state) => state.setSelection)
|
|
@@ -386,8 +389,8 @@ function ScansControl() {
|
|
|
386
389
|
className={cn(
|
|
387
390
|
'rounded-r-none p-0',
|
|
388
391
|
showScans
|
|
389
|
-
? 'bg-white/15'
|
|
390
|
-
: 'opacity-60 grayscale hover:bg-
|
|
392
|
+
? 'bg-black/9 hover:bg-black/9 dark:bg-white/15'
|
|
393
|
+
: 'opacity-60 grayscale hover:bg-black/4 hover:opacity-100 hover:grayscale-0',
|
|
391
394
|
)}
|
|
392
395
|
label={`Scans: ${showScans ? 'Visible' : 'Hidden'}`}
|
|
393
396
|
onClick={() => setShowScans(!showScans)}
|
|
@@ -396,7 +399,7 @@ function ScansControl() {
|
|
|
396
399
|
>
|
|
397
400
|
<div className="relative">
|
|
398
401
|
<img alt="Scans" className="h-[28px] w-[28px] object-contain" src="/icons/mesh.webp" />
|
|
399
|
-
<span className="absolute -right-1.5 -bottom-1 min-w-[14px] rounded-full bg-white/20 px-[3px] text-center font-medium text-[9px] text-white/70 leading-[14px]">
|
|
402
|
+
<span className="absolute -right-1.5 -bottom-1 min-w-[14px] rounded-full bg-black/12 dark:bg-white/20 px-[3px] text-center font-medium text-[9px] text-foreground/70 dark:text-white/70 leading-[14px]">
|
|
400
403
|
{scans.length}
|
|
401
404
|
</span>
|
|
402
405
|
</div>
|
|
@@ -411,11 +414,11 @@ function ScansControl() {
|
|
|
411
414
|
'flex h-11 w-6 items-center justify-center rounded-r-lg transition-colors',
|
|
412
415
|
showScans
|
|
413
416
|
? isOpen
|
|
414
|
-
? 'bg-white/10'
|
|
415
|
-
: 'bg-white/5 hover:bg-white/8'
|
|
417
|
+
? 'bg-black/6 dark:bg-white/10'
|
|
418
|
+
: 'bg-black/4 dark:bg-white/5 hover:bg-black/5 dark:hover:bg-white/8'
|
|
416
419
|
: isOpen
|
|
417
|
-
? 'bg-white/8'
|
|
418
|
-
: 'opacity-60 hover:bg-white/5 hover:opacity-100',
|
|
420
|
+
? 'bg-black/5 dark:bg-white/8'
|
|
421
|
+
: 'opacity-60 hover:bg-black/4 dark:hover:bg-white/5 hover:opacity-100',
|
|
419
422
|
)}
|
|
420
423
|
type="button"
|
|
421
424
|
>
|
|
@@ -427,7 +430,7 @@ function ScansControl() {
|
|
|
427
430
|
<PopoverContent
|
|
428
431
|
align="center"
|
|
429
432
|
className="w-72 rounded-xl border-border/45 bg-background/96 p-3 shadow-elevation-3 backdrop-blur-xl"
|
|
430
|
-
side=
|
|
433
|
+
side={popupSide}
|
|
431
434
|
sideOffset={14}
|
|
432
435
|
>
|
|
433
436
|
<div className="space-y-3">
|
|
@@ -459,7 +462,7 @@ function ScansControl() {
|
|
|
459
462
|
className={cn(
|
|
460
463
|
'group/item space-y-2 rounded-xl border bg-background/75 p-2.5 transition-colors',
|
|
461
464
|
selectedReferenceId === scan.id
|
|
462
|
-
? 'border-foreground/35 bg-white/10'
|
|
465
|
+
? 'border-foreground/35 bg-black/6 dark:bg-white/10'
|
|
463
466
|
: 'border-border/45',
|
|
464
467
|
)}
|
|
465
468
|
key={scan.id}
|
|
@@ -578,7 +581,7 @@ function ReferenceListSection({
|
|
|
578
581
|
</div>
|
|
579
582
|
<button
|
|
580
583
|
aria-label={show ? `Hide ${title.toLowerCase()}` : `Show ${title.toLowerCase()}`}
|
|
581
|
-
className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-border/40 text-muted-foreground transition-colors hover:bg-white/10 hover:text-foreground"
|
|
584
|
+
className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-border/40 text-muted-foreground transition-colors hover:bg-black/6 dark:hover:bg-white/10 hover:text-foreground"
|
|
582
585
|
onClick={() => setShow(!show)}
|
|
583
586
|
type="button"
|
|
584
587
|
>
|
|
@@ -594,7 +597,7 @@ function ReferenceListSection({
|
|
|
594
597
|
className={cn(
|
|
595
598
|
'group/item space-y-2 rounded-xl border bg-background/75 p-2.5 transition-colors',
|
|
596
599
|
selectedReferenceId === node.id
|
|
597
|
-
? 'border-foreground/35 bg-white/10'
|
|
600
|
+
? 'border-foreground/35 bg-black/6 dark:bg-white/10'
|
|
598
601
|
: 'border-border/45',
|
|
599
602
|
)}
|
|
600
603
|
key={node.id}
|
|
@@ -657,6 +660,7 @@ function ReferenceListSection({
|
|
|
657
660
|
}
|
|
658
661
|
|
|
659
662
|
function ReferencesControl() {
|
|
663
|
+
const popupSide = useActionMenuPopupSide()
|
|
660
664
|
const showScans = useViewer((state) => state.showScans)
|
|
661
665
|
const setShowScans = useViewer((state) => state.setShowScans)
|
|
662
666
|
const showGuides = useViewer((state) => state.showGuides)
|
|
@@ -682,8 +686,8 @@ function ReferencesControl() {
|
|
|
682
686
|
className={cn(
|
|
683
687
|
'rounded-r-none p-0',
|
|
684
688
|
anyVisible
|
|
685
|
-
? 'bg-white/15'
|
|
686
|
-
: 'opacity-60 grayscale hover:bg-
|
|
689
|
+
? 'bg-black/9 hover:bg-black/9 dark:bg-white/15'
|
|
690
|
+
: 'opacity-60 grayscale hover:bg-black/4 hover:opacity-100 hover:grayscale-0',
|
|
687
691
|
)}
|
|
688
692
|
label={`References: ${anyVisible ? 'Visible' : 'Hidden'}`}
|
|
689
693
|
onClick={toggleAll}
|
|
@@ -696,7 +700,7 @@ function ReferencesControl() {
|
|
|
696
700
|
className="h-[28px] w-[28px] object-contain"
|
|
697
701
|
src="/icons/floorplan.webp"
|
|
698
702
|
/>
|
|
699
|
-
<span className="absolute -right-1.5 -bottom-1 min-w-[14px] rounded-full bg-white/20 px-[3px] text-center font-medium text-[9px] text-white/70 leading-[14px]">
|
|
703
|
+
<span className="absolute -right-1.5 -bottom-1 min-w-[14px] rounded-full bg-black/12 dark:bg-white/20 px-[3px] text-center font-medium text-[9px] text-foreground/70 dark:text-white/70 leading-[14px]">
|
|
700
704
|
{total}
|
|
701
705
|
</span>
|
|
702
706
|
</div>
|
|
@@ -710,11 +714,11 @@ function ReferencesControl() {
|
|
|
710
714
|
'flex h-11 w-6 items-center justify-center rounded-r-lg transition-colors',
|
|
711
715
|
anyVisible
|
|
712
716
|
? isOpen
|
|
713
|
-
? 'bg-white/10'
|
|
714
|
-
: 'bg-white/5 hover:bg-white/8'
|
|
717
|
+
? 'bg-black/6 dark:bg-white/10'
|
|
718
|
+
: 'bg-black/4 dark:bg-white/5 hover:bg-black/5 dark:hover:bg-white/8'
|
|
715
719
|
: isOpen
|
|
716
|
-
? 'bg-white/8'
|
|
717
|
-
: 'opacity-60 hover:bg-white/5 hover:opacity-100',
|
|
720
|
+
? 'bg-black/5 dark:bg-white/8'
|
|
721
|
+
: 'opacity-60 hover:bg-black/4 dark:hover:bg-white/5 hover:opacity-100',
|
|
718
722
|
)}
|
|
719
723
|
type="button"
|
|
720
724
|
>
|
|
@@ -726,7 +730,7 @@ function ReferencesControl() {
|
|
|
726
730
|
<PopoverContent
|
|
727
731
|
align="center"
|
|
728
732
|
className="w-72 rounded-xl border-border/45 bg-background/96 p-3 shadow-elevation-3 backdrop-blur-xl"
|
|
729
|
-
side=
|
|
733
|
+
side={popupSide}
|
|
730
734
|
sideOffset={14}
|
|
731
735
|
>
|
|
732
736
|
<div className="space-y-3">
|
|
@@ -765,6 +769,7 @@ function ReferencesControl() {
|
|
|
765
769
|
// ── Reference floor control ────────────────────────────────────────────────────────────────────
|
|
766
770
|
|
|
767
771
|
function ReferenceFloorControl() {
|
|
772
|
+
const popupSide = useActionMenuPopupSide()
|
|
768
773
|
const showReferenceFloor = useEditor((state) => state.showReferenceFloor)
|
|
769
774
|
const toggleReferenceFloor = useEditor((state) => state.toggleReferenceFloor)
|
|
770
775
|
const referenceFloorOffset = useEditor((state) => state.referenceFloorOffset)
|
|
@@ -784,8 +789,8 @@ function ReferenceFloorControl() {
|
|
|
784
789
|
className={cn(
|
|
785
790
|
'rounded-r-none p-0',
|
|
786
791
|
showReferenceFloor && selectedLevel
|
|
787
|
-
? 'bg-white/15'
|
|
788
|
-
: 'opacity-60 grayscale hover:bg-
|
|
792
|
+
? 'bg-black/9 hover:bg-black/9 dark:bg-white/15'
|
|
793
|
+
: 'opacity-60 grayscale hover:bg-black/4 hover:opacity-100 hover:grayscale-0',
|
|
789
794
|
)}
|
|
790
795
|
disabled={!hasLowerLevels}
|
|
791
796
|
label={
|
|
@@ -801,7 +806,7 @@ function ReferenceFloorControl() {
|
|
|
801
806
|
>
|
|
802
807
|
<div className="relative">
|
|
803
808
|
<Layers2 className="h-4 w-4" />
|
|
804
|
-
<span className="absolute -right-1.5 -bottom-1 min-w-[14px] rounded-full bg-white/20 px-[3px] text-center font-medium text-[9px] text-white/70 leading-[14px]">
|
|
809
|
+
<span className="absolute -right-1.5 -bottom-1 min-w-[14px] rounded-full bg-black/12 dark:bg-white/20 px-[3px] text-center font-medium text-[9px] text-foreground/70 dark:text-white/70 leading-[14px]">
|
|
805
810
|
{lowerLevels.length}
|
|
806
811
|
</span>
|
|
807
812
|
</div>
|
|
@@ -815,11 +820,11 @@ function ReferenceFloorControl() {
|
|
|
815
820
|
'flex h-11 w-6 items-center justify-center rounded-r-lg transition-colors',
|
|
816
821
|
showReferenceFloor && selectedLevel
|
|
817
822
|
? isOpen
|
|
818
|
-
? 'bg-white/10'
|
|
819
|
-
: 'bg-white/5 hover:bg-white/8'
|
|
823
|
+
? 'bg-black/6 dark:bg-white/10'
|
|
824
|
+
: 'bg-black/4 dark:bg-white/5 hover:bg-black/5 dark:hover:bg-white/8'
|
|
820
825
|
: isOpen
|
|
821
|
-
? 'bg-white/8'
|
|
822
|
-
: 'opacity-60 hover:bg-white/5 hover:opacity-100',
|
|
826
|
+
? 'bg-black/5 dark:bg-white/8'
|
|
827
|
+
: 'opacity-60 hover:bg-black/4 dark:hover:bg-white/5 hover:opacity-100',
|
|
823
828
|
)}
|
|
824
829
|
disabled={!hasLowerLevels}
|
|
825
830
|
type="button"
|
|
@@ -832,7 +837,7 @@ function ReferenceFloorControl() {
|
|
|
832
837
|
<PopoverContent
|
|
833
838
|
align="center"
|
|
834
839
|
className="w-72 rounded-xl border-border/45 bg-background/96 p-3 shadow-[0_14px_28px_-18px_rgba(15,23,42,0.55),0_6px_16px_-10px_rgba(15,23,42,0.2)] backdrop-blur-xl"
|
|
835
|
-
side=
|
|
840
|
+
side={popupSide}
|
|
836
841
|
sideOffset={14}
|
|
837
842
|
>
|
|
838
843
|
<div className="space-y-3">
|
|
@@ -848,7 +853,7 @@ function ReferenceFloorControl() {
|
|
|
848
853
|
</div>
|
|
849
854
|
<button
|
|
850
855
|
aria-label={showReferenceFloor ? 'Hide reference floor' : 'Show reference floor'}
|
|
851
|
-
className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-border/40 text-muted-foreground transition-colors hover:bg-white/10 hover:text-foreground disabled:pointer-events-none disabled:opacity-40"
|
|
856
|
+
className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-border/40 text-muted-foreground transition-colors hover:bg-black/6 dark:hover:bg-white/10 hover:text-foreground disabled:pointer-events-none disabled:opacity-40"
|
|
852
857
|
disabled={!hasLowerLevels}
|
|
853
858
|
onClick={toggleReferenceFloor}
|
|
854
859
|
type="button"
|
|
@@ -870,8 +875,8 @@ function ReferenceFloorControl() {
|
|
|
870
875
|
return (
|
|
871
876
|
<button
|
|
872
877
|
className={cn(
|
|
873
|
-
'flex w-full items-center gap-2 rounded-lg px-2.5 py-2 text-left text-sm transition-colors hover:bg-white/8',
|
|
874
|
-
isSelected && showReferenceFloor && 'bg-white/10 text-foreground',
|
|
878
|
+
'flex w-full items-center gap-2 rounded-lg px-2.5 py-2 text-left text-sm transition-colors hover:bg-black/5 dark:hover:bg-white/8',
|
|
879
|
+
isSelected && showReferenceFloor && 'bg-black/6 dark:bg-white/10 text-foreground',
|
|
875
880
|
)}
|
|
876
881
|
key={level.id}
|
|
877
882
|
onClick={() => {
|
|
@@ -928,8 +933,8 @@ function RiserControl() {
|
|
|
928
933
|
<ActionButton
|
|
929
934
|
className={cn(
|
|
930
935
|
isRiserOpen
|
|
931
|
-
? 'bg-white/15'
|
|
932
|
-
: 'opacity-60 grayscale hover:bg-
|
|
936
|
+
? 'bg-black/9 hover:bg-black/9 dark:bg-white/15'
|
|
937
|
+
: 'opacity-60 grayscale hover:bg-black/4 hover:opacity-100 hover:grayscale-0',
|
|
933
938
|
)}
|
|
934
939
|
label="Riser diagram"
|
|
935
940
|
onClick={toggleRiserOpen}
|