@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
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
type AnyNodeId,
|
|
7
7
|
bboxAnchors,
|
|
8
8
|
bboxCornerAnchors,
|
|
9
|
+
beginSceneHistoryDraft,
|
|
10
|
+
beginSceneHistoryPauseSession,
|
|
9
11
|
cascadeDirty,
|
|
10
12
|
collectDescendants,
|
|
11
13
|
createSceneApi,
|
|
@@ -15,8 +17,10 @@ import {
|
|
|
15
17
|
getEffectiveNode,
|
|
16
18
|
type MovableConfig,
|
|
17
19
|
nodeRegistry,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
runAsSingleSceneHistoryStep,
|
|
21
|
+
runSceneHistoryDraftWrite,
|
|
22
|
+
sceneHistoryDraftRevertUpdates,
|
|
23
|
+
settleSceneHistoryDrafts,
|
|
20
24
|
useLiveNodeOverrides,
|
|
21
25
|
useLiveTransforms,
|
|
22
26
|
useScene,
|
|
@@ -35,6 +39,7 @@ import {
|
|
|
35
39
|
import { movementSfxStepKey } from '../../lib/sfx/movement-tick'
|
|
36
40
|
import { sfxEmitter } from '../../lib/sfx-bus'
|
|
37
41
|
import { surfaceAttachmentId } from '../../lib/surface-attachment'
|
|
42
|
+
import { isTypingTarget } from '../../lib/typing-target'
|
|
38
43
|
import { resolveAlignmentForFloorplanView } from '../../lib/world-grid-snap'
|
|
39
44
|
import useAlignmentGuides from '../../store/use-alignment-guides'
|
|
40
45
|
import useEditor, {
|
|
@@ -146,15 +151,55 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
146
151
|
}) => FloorplanMoveTargetSession
|
|
147
152
|
)({ node: movingNode, nodes: sceneNodes, sceneApi })
|
|
148
153
|
|
|
149
|
-
|
|
150
|
-
// so the single-undo dance has a clean baseline to revert to.
|
|
151
|
-
const snapshots = session.affectedIds
|
|
152
|
-
.map((id) => sceneNodes[id])
|
|
153
|
-
.filter((n): n is AnyNode => !!n)
|
|
154
|
-
.map((n) => snapshotNode(n))
|
|
154
|
+
const initialAffectedIds = session.affectedIds.filter((id) => sceneNodes[id])
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
// History is paused only around this overlay's own writes (`ownWrite`): every affected
|
|
157
|
+
// node is a carried draft (core's history-drafts), so writes others make mid-move record
|
|
158
|
+
// as their own steps and space detection reconciles them. The drop writes through a
|
|
159
|
+
// session keyed by the moving node, which the 3D mover shares in split view.
|
|
160
|
+
const draftEnds = initialAffectedIds.map((id) =>
|
|
161
|
+
beginSceneHistoryDraft(
|
|
162
|
+
id,
|
|
163
|
+
isFreshPlacementMetadata(sceneNodes[id]!.metadata) ? null : sceneNodes[id]!,
|
|
164
|
+
),
|
|
165
|
+
)
|
|
157
166
|
let historyPaused = true
|
|
167
|
+
const endDrafts = () => {
|
|
168
|
+
for (const end of draftEnds) end()
|
|
169
|
+
historyPaused = false
|
|
170
|
+
}
|
|
171
|
+
const ownWrite = runSceneHistoryDraftWrite
|
|
172
|
+
// Puts back only the fields this move wrote and still holds; a rename or any other write
|
|
173
|
+
// someone made mid-move stays.
|
|
174
|
+
// The drop ends the carry: a transient marker (the 3D mover's, in split view) goes even
|
|
175
|
+
// when someone else edited the metadata meanwhile and the move no longer holds it.
|
|
176
|
+
const endTransientMarkers = () => {
|
|
177
|
+
const nodes = useScene.getState().nodes
|
|
178
|
+
const updates = session.affectedIds.flatMap((id) => {
|
|
179
|
+
const metadata = nodes[id]?.metadata as Record<string, unknown> | undefined
|
|
180
|
+
if (!metadata?.isTransient) return []
|
|
181
|
+
const { isTransient: _transient, ...rest } = metadata
|
|
182
|
+
return [{ id, data: { metadata: rest } }]
|
|
183
|
+
})
|
|
184
|
+
if (updates.length > 0) useScene.getState().updateNodes(updates)
|
|
185
|
+
}
|
|
186
|
+
const revertOwnWrites = () =>
|
|
187
|
+
ownWrite(() => {
|
|
188
|
+
const updates = sceneHistoryDraftRevertUpdates(session.affectedIds)
|
|
189
|
+
if (updates.length > 0) useScene.getState().updateNodes(updates)
|
|
190
|
+
})
|
|
191
|
+
const recordDrop = (write: () => void) => {
|
|
192
|
+
const drop = beginSceneHistoryPauseSession(useScene, { gesture: movingNode.id })
|
|
193
|
+
try {
|
|
194
|
+
// The move's write and its transient cleanup are one undo entry and one commit.
|
|
195
|
+
drop.commitStep(() => runAsSingleSceneHistoryStep(useScene, write))
|
|
196
|
+
// Only a successful drop ends ownership; a rejected write can still be retried.
|
|
197
|
+
settleSceneHistoryDrafts(session.affectedIds)
|
|
198
|
+
endDrafts()
|
|
199
|
+
} finally {
|
|
200
|
+
drop.end()
|
|
201
|
+
}
|
|
202
|
+
}
|
|
158
203
|
|
|
159
204
|
const clearLivePreviews = () => {
|
|
160
205
|
const liveTransforms = useLiveTransforms.getState()
|
|
@@ -229,15 +274,17 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
229
274
|
hasMovedSinceStart = true
|
|
230
275
|
lastPlanPoint = planPoint
|
|
231
276
|
clearRejection()
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
277
|
+
ownWrite(() =>
|
|
278
|
+
session.apply({
|
|
279
|
+
planPoint,
|
|
280
|
+
modifiers: {
|
|
281
|
+
shiftKey: event.shiftKey,
|
|
282
|
+
altKey: event.altKey,
|
|
283
|
+
ctrlKey: event.ctrlKey,
|
|
284
|
+
metaKey: event.metaKey,
|
|
285
|
+
},
|
|
286
|
+
}),
|
|
287
|
+
)
|
|
241
288
|
// Move "tick" — same feedback the 3D move gives, which fires whenever the
|
|
242
289
|
// resolved position changes (any snapping mode, not just grid), so it
|
|
243
290
|
// ticks as the item lands on each new snapped/free position.
|
|
@@ -265,7 +312,14 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
265
312
|
}
|
|
266
313
|
|
|
267
314
|
const commitFinalStateOrRevert = () => {
|
|
268
|
-
|
|
315
|
+
if (!useScene.getState().nodes[movingNode.id]) {
|
|
316
|
+
revertOwnWrites()
|
|
317
|
+
endDrafts()
|
|
318
|
+
clearLivePreviews()
|
|
319
|
+
return
|
|
320
|
+
}
|
|
321
|
+
// Some registered sessions stage their final polygon from canCommit.
|
|
322
|
+
const commitValid = ownWrite(() => session.canCommit())
|
|
269
323
|
const freshPlacement = isFreshPlacementMetadata(
|
|
270
324
|
(useScene.getState().nodes[movingNode.id] as { metadata?: unknown } | undefined)
|
|
271
325
|
?.metadata,
|
|
@@ -283,7 +337,7 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
283
337
|
|
|
284
338
|
// Keep ordinary teardown order. Validated replacements can refuse, so they
|
|
285
339
|
// claim teardown only after success, before clearing the moving node.
|
|
286
|
-
if (!
|
|
340
|
+
if (!freshPlacement) setMovingNodeOrigin('2d')
|
|
287
341
|
|
|
288
342
|
// Sessions with a `commit` hook own their atomic write (e.g.
|
|
289
343
|
// wall move emits creates + deletes + updates via the junction
|
|
@@ -293,7 +347,7 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
293
347
|
if (commitValid && freshPlacement) {
|
|
294
348
|
// Subtrees finalize from the preview. Staging a session commit would publish
|
|
295
349
|
// an unvalidated graph, including for presets created outside our factory.
|
|
296
|
-
if (!atomicPreview) session.commit?.()
|
|
350
|
+
if (!atomicPreview) ownWrite(() => session.commit?.())
|
|
297
351
|
const stagedNode = useScene.getState().nodes[movingNode.id]
|
|
298
352
|
const preview = usePlacementPreview.getState().node
|
|
299
353
|
const effective = stagedNode ? getEffectiveNode(stagedNode) : null
|
|
@@ -310,67 +364,66 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
310
364
|
showRejection,
|
|
311
365
|
)
|
|
312
366
|
: null
|
|
313
|
-
if (!committedId
|
|
367
|
+
if (!committedId) return false
|
|
368
|
+
setMovingNodeOrigin('2d')
|
|
314
369
|
if (atomicPreview) {
|
|
315
|
-
setMovingNodeOrigin('2d')
|
|
316
370
|
for (const id of session.affectedIds) {
|
|
317
371
|
useLiveTransforms.getState().clear(id)
|
|
318
372
|
useLiveNodeOverrides.getState().clear(id)
|
|
319
373
|
}
|
|
320
374
|
}
|
|
321
|
-
if (historyPaused) {
|
|
322
|
-
resumeSceneHistory(useScene)
|
|
323
|
-
historyPaused = false
|
|
324
|
-
}
|
|
325
375
|
if (committedId) {
|
|
376
|
+
settleSceneHistoryDrafts(session.affectedIds)
|
|
326
377
|
sfxEmitter.emit('sfx:item-place')
|
|
327
378
|
useViewer.getState().setSelection({ selectedIds: [committedId] })
|
|
328
379
|
}
|
|
380
|
+
endDrafts()
|
|
329
381
|
return
|
|
330
382
|
}
|
|
331
383
|
|
|
332
384
|
if (commitValid && session.commit) {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}
|
|
338
|
-
session.commit()
|
|
385
|
+
revertOwnWrites()
|
|
386
|
+
recordDrop(() => {
|
|
387
|
+
session.commit?.()
|
|
388
|
+
endTransientMarkers()
|
|
389
|
+
})
|
|
339
390
|
sfxEmitter.emit('sfx:item-place')
|
|
340
|
-
useViewer.getState().setSelection({ selectedIds:
|
|
391
|
+
useViewer.getState().setSelection({ selectedIds: initialAffectedIds })
|
|
341
392
|
return
|
|
342
393
|
}
|
|
343
394
|
|
|
344
395
|
const sceneState = useScene.getState().nodes
|
|
345
396
|
const finalUpdates: Array<{ id: AnyNodeId; data: Record<string, unknown> }> = []
|
|
346
|
-
|
|
347
|
-
|
|
397
|
+
// Reapply everything the revert removes, including newly introduced fields and
|
|
398
|
+
// attachment entries held on hosts outside affectedIds. Foreign writes stay recorded.
|
|
399
|
+
for (const update of sceneHistoryDraftRevertUpdates(session.affectedIds)) {
|
|
400
|
+
const current = sceneState[update.id]
|
|
348
401
|
if (!current) continue
|
|
349
402
|
const data: Record<string, unknown> = {}
|
|
350
403
|
let changed = false
|
|
351
|
-
for (const [key, before] of Object.entries(
|
|
404
|
+
for (const [key, before] of Object.entries(update.data)) {
|
|
352
405
|
const after = (current as unknown as Record<string, unknown>)[key]
|
|
353
406
|
if (!deepEqual(before, after)) {
|
|
354
407
|
data[key] = Array.isArray(after) ? [...(after as unknown[])] : after
|
|
355
408
|
changed = true
|
|
356
409
|
}
|
|
357
410
|
}
|
|
358
|
-
if (changed) finalUpdates.push({ id:
|
|
411
|
+
if (changed) finalUpdates.push({ id: update.id, data })
|
|
359
412
|
}
|
|
360
413
|
|
|
361
|
-
for (const
|
|
362
|
-
const current = sceneState[
|
|
414
|
+
for (const id of initialAffectedIds) {
|
|
415
|
+
const current = sceneState[id]
|
|
363
416
|
if (!current || !isFreshPlacementMetadata((current as { metadata?: unknown }).metadata)) {
|
|
364
417
|
continue
|
|
365
418
|
}
|
|
366
|
-
const existing = finalUpdates.find((update) => update.id ===
|
|
419
|
+
const existing = finalUpdates.find((update) => update.id === id)
|
|
367
420
|
const metadata = stripPlacementMetadataFlags((current as { metadata?: unknown }).metadata)
|
|
368
421
|
if (existing) {
|
|
369
422
|
existing.data.metadata = metadata
|
|
370
423
|
existing.data.visible = true
|
|
371
424
|
} else {
|
|
372
425
|
finalUpdates.push({
|
|
373
|
-
id
|
|
426
|
+
id,
|
|
374
427
|
data: { metadata, visible: true },
|
|
375
428
|
})
|
|
376
429
|
}
|
|
@@ -381,25 +434,21 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
381
434
|
// 1. Revert to baseline while history is still paused.
|
|
382
435
|
// 2. Resume history.
|
|
383
436
|
// 3. Re-apply the final state — recorded as one tracked change.
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}
|
|
389
|
-
useScene.getState().updateNodes(finalUpdates)
|
|
437
|
+
revertOwnWrites()
|
|
438
|
+
recordDrop(() => {
|
|
439
|
+
useScene.getState().updateNodes(finalUpdates)
|
|
440
|
+
endTransientMarkers()
|
|
441
|
+
})
|
|
390
442
|
sfxEmitter.emit('sfx:item-place')
|
|
391
443
|
// Re-select the moved node(s) — mirrors the legacy 3D move
|
|
392
444
|
// tool. The action menu cleared selection on Move click so
|
|
393
445
|
// selection-gated affordances (slab/ceiling boundary editor,
|
|
394
446
|
// etc.) would unmount during the drag; restoring it here
|
|
395
447
|
// brings them back at the new position.
|
|
396
|
-
useViewer.getState().setSelection({ selectedIds:
|
|
448
|
+
useViewer.getState().setSelection({ selectedIds: initialAffectedIds })
|
|
397
449
|
} else {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
resumeSceneHistory(useScene)
|
|
401
|
-
historyPaused = false
|
|
402
|
-
}
|
|
450
|
+
revertOwnWrites()
|
|
451
|
+
endDrafts()
|
|
403
452
|
}
|
|
404
453
|
}
|
|
405
454
|
|
|
@@ -449,6 +498,7 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
449
498
|
}
|
|
450
499
|
|
|
451
500
|
const onKey = (event: KeyboardEvent) => {
|
|
501
|
+
if (isTypingTarget(event.target)) return
|
|
452
502
|
// R flips a directional kind's facing mid-placement (door / window:
|
|
453
503
|
// front ↔ back). The session records the flip and re-runs its last
|
|
454
504
|
// apply so the 2D symbol updates immediately; kinds without a facing
|
|
@@ -468,13 +518,9 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
468
518
|
if (event.metaKey || event.ctrlKey) return
|
|
469
519
|
if (!(session.flipSide && hasMovedSinceStart && pointerOverFloorplan)) return
|
|
470
520
|
if (event.repeat) return
|
|
471
|
-
const t = event.target as HTMLElement | null
|
|
472
|
-
if (t && (t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.isContentEditable)) {
|
|
473
|
-
return
|
|
474
|
-
}
|
|
475
521
|
event.preventDefault()
|
|
476
522
|
event.stopImmediatePropagation()
|
|
477
|
-
session.flipSide()
|
|
523
|
+
ownWrite(() => session.flipSide?.())
|
|
478
524
|
sfxEmitter.emit('sfx:item-rotate')
|
|
479
525
|
return
|
|
480
526
|
}
|
|
@@ -492,22 +538,16 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
492
538
|
if (isFreshPlacementMetadata((movingNode as { metadata?: unknown }).metadata)) {
|
|
493
539
|
emitter.emit('tool:cancel')
|
|
494
540
|
if (!ownsSubtree && !isInteractionSubtreeDraft(movingNode.id))
|
|
495
|
-
useScene.getState().deleteNode(movingNode.id)
|
|
496
|
-
|
|
497
|
-
resumeSceneHistory(useScene)
|
|
498
|
-
historyPaused = false
|
|
499
|
-
}
|
|
541
|
+
ownWrite(() => useScene.getState().deleteNode(movingNode.id))
|
|
542
|
+
endDrafts()
|
|
500
543
|
clearLivePreviews()
|
|
501
544
|
useAlignmentGuides.getState().clear()
|
|
502
545
|
setMovingNode(null)
|
|
503
546
|
return
|
|
504
547
|
}
|
|
505
|
-
// Revert
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
resumeSceneHistory(useScene)
|
|
509
|
-
historyPaused = false
|
|
510
|
-
}
|
|
548
|
+
// Revert as the overlay's own write: no history entry.
|
|
549
|
+
revertOwnWrites()
|
|
550
|
+
endDrafts()
|
|
511
551
|
// Clear any live previews the session wrote. Slab / ceiling
|
|
512
552
|
// 2D move stages a translation delta in `useLiveTransforms`;
|
|
513
553
|
// wall move publishes `{ start, end, ... }` to
|
|
@@ -516,7 +556,7 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
516
556
|
// position.
|
|
517
557
|
clearLivePreviews()
|
|
518
558
|
// Restore selection cleared by the action menu's Move click.
|
|
519
|
-
useViewer.getState().setSelection({ selectedIds:
|
|
559
|
+
useViewer.getState().setSelection({ selectedIds: initialAffectedIds })
|
|
520
560
|
setMovingNode(null)
|
|
521
561
|
}
|
|
522
562
|
|
|
@@ -535,7 +575,7 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
535
575
|
window.removeEventListener('keydown', onKey, true)
|
|
536
576
|
// Unmount cleanup. `historyPaused === true` here means none of
|
|
537
577
|
// our terminal paths (commit, Esc) ran in this overlay — they
|
|
538
|
-
// each
|
|
578
|
+
// each end the drafts and flip the flag.
|
|
539
579
|
//
|
|
540
580
|
// If `movingNodeOrigin === '3d'`, a 3D move tool finalised
|
|
541
581
|
// while our overlay was still mounted (split view); the live
|
|
@@ -554,10 +594,10 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
554
594
|
const finalisedBy3D = useEditor.getState().movingNodeOrigin === '3d'
|
|
555
595
|
if (!finalisedBy3D && !freshPlacement) {
|
|
556
596
|
if (hasMovedSinceStart) {
|
|
557
|
-
|
|
597
|
+
revertOwnWrites()
|
|
558
598
|
}
|
|
559
599
|
}
|
|
560
|
-
|
|
600
|
+
endDrafts()
|
|
561
601
|
}
|
|
562
602
|
// Belt-and-suspenders: clear any live previews on abnormal
|
|
563
603
|
// unmount paths too. Slab / ceiling sessions write to
|
|
@@ -922,6 +962,7 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
922
962
|
}
|
|
923
963
|
|
|
924
964
|
const onKey = (event: KeyboardEvent) => {
|
|
965
|
+
if (isTypingTarget(event.target)) return
|
|
925
966
|
if (event.key !== 'Escape' && !isHistoryShortcut(event)) return
|
|
926
967
|
if (isHistoryShortcut(event)) {
|
|
927
968
|
// ⌘Z mid-move cancels like Escape — keep it from reaching the
|
|
@@ -933,11 +974,7 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
933
974
|
if (isFreshPlacement) {
|
|
934
975
|
emitter.emit('tool:cancel')
|
|
935
976
|
if (!ownsSubtree && !isInteractionSubtreeDraft(movingNode.id)) {
|
|
936
|
-
|
|
937
|
-
const wasTracking = (temporal as { isTracking?: boolean }).isTracking !== false
|
|
938
|
-
if (wasTracking) temporal.pause()
|
|
939
|
-
useScene.getState().deleteNode(movingNode.id)
|
|
940
|
-
if (wasTracking) temporal.resume()
|
|
977
|
+
runSceneHistoryDraftWrite(() => useScene.getState().deleteNode(movingNode.id))
|
|
941
978
|
}
|
|
942
979
|
}
|
|
943
980
|
for (const relatedEntry of relatedEntries) {
|
|
@@ -970,33 +1007,6 @@ export function FloorplanRegistryMoveOverlay() {
|
|
|
970
1007
|
return null
|
|
971
1008
|
}
|
|
972
1009
|
|
|
973
|
-
// ── Snapshot helpers (shared shape with floorplan-registry-layer) ───
|
|
974
|
-
//
|
|
975
|
-
// Kept inline here to avoid a circular dependency through a shared
|
|
976
|
-
// utility module. If a third call site shows up, extract.
|
|
977
|
-
|
|
978
|
-
type NodeSnapshot = { id: AnyNodeId; data: Record<string, unknown> }
|
|
979
|
-
|
|
980
|
-
function snapshotNode(node: AnyNode): NodeSnapshot {
|
|
981
|
-
const data: Record<string, unknown> = {}
|
|
982
|
-
for (const [key, value] of Object.entries(node)) {
|
|
983
|
-
if (key === 'id' || key === 'type' || key === 'object') continue
|
|
984
|
-
data[key] = Array.isArray(value) ? [...(value as unknown[])] : value
|
|
985
|
-
}
|
|
986
|
-
return { id: node.id, data }
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
function restoreSnapshots(snapshots: NodeSnapshot[]) {
|
|
990
|
-
const updates = snapshots
|
|
991
|
-
.filter(
|
|
992
|
-
(s) =>
|
|
993
|
-
!useScene.getState().nodes[s.id] ||
|
|
994
|
-
!deepEqual(s.data, snapshotNode(useScene.getState().nodes[s.id]!).data),
|
|
995
|
-
)
|
|
996
|
-
.map((s) => ({ id: s.id, data: s.data }))
|
|
997
|
-
if (updates.length) useScene.getState().updateNodes(updates)
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
1010
|
function deepEqual(a: unknown, b: unknown): boolean {
|
|
1001
1011
|
if (a === b) return true
|
|
1002
1012
|
if (Array.isArray(a) && Array.isArray(b)) {
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
|
|
2
|
+
import type { AnyNode, AnyNodeId } from '@pascal-app/core'
|
|
3
|
+
import { useScene } from '@pascal-app/core'
|
|
4
|
+
import { commitDimensionValue, isDimensionEditAllowed } from './floorplan-dimension-edit-overlay'
|
|
5
|
+
|
|
6
|
+
type Change = { id: AnyNodeId; data: Partial<AnyNode> }
|
|
7
|
+
|
|
8
|
+
function wall(id: string, start: [number, number], end: [number, number]): AnyNode {
|
|
9
|
+
return {
|
|
10
|
+
object: 'node',
|
|
11
|
+
id,
|
|
12
|
+
type: 'wall',
|
|
13
|
+
parentId: 'level_1',
|
|
14
|
+
visible: true,
|
|
15
|
+
metadata: {},
|
|
16
|
+
start,
|
|
17
|
+
end,
|
|
18
|
+
thickness: 0.15,
|
|
19
|
+
children: [],
|
|
20
|
+
} as unknown as AnyNode
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function nodes(): Record<string, AnyNode> {
|
|
24
|
+
return {
|
|
25
|
+
level_1: {
|
|
26
|
+
object: 'node',
|
|
27
|
+
id: 'level_1',
|
|
28
|
+
type: 'level',
|
|
29
|
+
parentId: null,
|
|
30
|
+
visible: true,
|
|
31
|
+
metadata: {},
|
|
32
|
+
level: 0,
|
|
33
|
+
children: ['wall_a', 'wall_b', 'dim_1'],
|
|
34
|
+
} as unknown as AnyNode,
|
|
35
|
+
wall_a: wall('wall_a', [0, 0], [3, 0]),
|
|
36
|
+
wall_b: wall('wall_b', [3, 0], [3, 4]),
|
|
37
|
+
dim_1: {
|
|
38
|
+
object: 'node',
|
|
39
|
+
id: 'dim_1',
|
|
40
|
+
type: 'construction-dimension',
|
|
41
|
+
parentId: 'level_1',
|
|
42
|
+
visible: true,
|
|
43
|
+
metadata: {},
|
|
44
|
+
children: [],
|
|
45
|
+
} as unknown as AnyNode,
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let initial: ReturnType<typeof useScene.getState>
|
|
50
|
+
let applied: Change[]
|
|
51
|
+
let updated: Change[]
|
|
52
|
+
let dirty: AnyNodeId[]
|
|
53
|
+
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
initial = useScene.getState()
|
|
56
|
+
applied = []
|
|
57
|
+
updated = []
|
|
58
|
+
dirty = []
|
|
59
|
+
useScene.setState({
|
|
60
|
+
nodes: nodes() as ReturnType<typeof useScene.getState>['nodes'],
|
|
61
|
+
applyNodeChanges: ((changes: { update?: Change[] }) => {
|
|
62
|
+
applied.push(...(changes.update ?? []))
|
|
63
|
+
}) as ReturnType<typeof useScene.getState>['applyNodeChanges'],
|
|
64
|
+
updateNode: ((id: AnyNodeId, data: Partial<AnyNode>) => {
|
|
65
|
+
updated.push({ id, data })
|
|
66
|
+
}) as ReturnType<typeof useScene.getState>['updateNode'],
|
|
67
|
+
markDirty: ((id: AnyNodeId) => {
|
|
68
|
+
dirty.push(id)
|
|
69
|
+
}) as ReturnType<typeof useScene.getState>['markDirty'],
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
afterEach(() => {
|
|
74
|
+
useScene.setState(initial, true)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
describe('commitDimensionValue', () => {
|
|
78
|
+
test('a wall dimension drives the wall end and the wall sharing that corner', () => {
|
|
79
|
+
const outcome = commitDimensionValue({
|
|
80
|
+
target: {
|
|
81
|
+
ownerNodeId: 'wall_a' as AnyNodeId,
|
|
82
|
+
witnessStart: [0, 0],
|
|
83
|
+
witnessEnd: [3, 0],
|
|
84
|
+
value: 3,
|
|
85
|
+
},
|
|
86
|
+
nextLength: 3.5,
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
expect(outcome).toEqual({ ok: true })
|
|
90
|
+
const byId = new Map(applied.map((change) => [change.id, change.data]))
|
|
91
|
+
expect(byId.get('wall_a' as AnyNodeId)).toEqual({ start: [0, 0], end: [3.5, 0] })
|
|
92
|
+
expect(byId.get('wall_b' as AnyNodeId)).toEqual({ start: [3.5, 0], end: [3, 4] })
|
|
93
|
+
expect(dirty.sort()).toEqual(['wall_a', 'wall_b'] as AnyNodeId[])
|
|
94
|
+
expect(updated).toEqual([])
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
test('an undrivable wall dimension is refused and nothing is written', () => {
|
|
98
|
+
const outcome = commitDimensionValue({
|
|
99
|
+
target: {
|
|
100
|
+
ownerNodeId: 'wall_a' as AnyNodeId,
|
|
101
|
+
witnessStart: [1.5, -1],
|
|
102
|
+
witnessEnd: [1.5, 1],
|
|
103
|
+
value: 2,
|
|
104
|
+
},
|
|
105
|
+
nextLength: 2.5,
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
expect(outcome.ok).toBe(false)
|
|
109
|
+
expect(applied).toEqual([])
|
|
110
|
+
expect(updated).toEqual([])
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
test('an undrivable construction dimension keeps the typed text as an override', () => {
|
|
114
|
+
const outcome = commitDimensionValue({
|
|
115
|
+
target: {
|
|
116
|
+
ownerNodeId: 'dim_1' as AnyNodeId,
|
|
117
|
+
witnessStart: [10, 10],
|
|
118
|
+
witnessEnd: [12, 10],
|
|
119
|
+
value: 2,
|
|
120
|
+
},
|
|
121
|
+
nextLength: 3,
|
|
122
|
+
unit: 'metric',
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
expect(outcome).toEqual({ ok: true })
|
|
126
|
+
expect(applied).toEqual([])
|
|
127
|
+
expect(updated).toHaveLength(1)
|
|
128
|
+
expect(updated[0]?.id).toBe('dim_1' as AnyNodeId)
|
|
129
|
+
expect(typeof (updated[0]!.data as { textOverride?: unknown }).textOverride).toBe('string')
|
|
130
|
+
})
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
describe('isDimensionEditAllowed', () => {
|
|
134
|
+
const idle = {
|
|
135
|
+
workspaceMode: 'edit',
|
|
136
|
+
mode: 'select',
|
|
137
|
+
isPreviewMode: false,
|
|
138
|
+
isCaptureMode: false,
|
|
139
|
+
isFirstPersonMode: false,
|
|
140
|
+
} as const
|
|
141
|
+
|
|
142
|
+
test('only an editable scene in select mode of the edit workspace', () => {
|
|
143
|
+
expect(isDimensionEditAllowed(idle, { readOnly: false })).toBe(true)
|
|
144
|
+
expect(isDimensionEditAllowed(idle, { readOnly: true })).toBe(false)
|
|
145
|
+
expect(isDimensionEditAllowed({ ...idle, workspaceMode: 'studio' }, { readOnly: false })).toBe(
|
|
146
|
+
false,
|
|
147
|
+
)
|
|
148
|
+
expect(isDimensionEditAllowed({ ...idle, workspaceMode: 'sheets' }, { readOnly: false })).toBe(
|
|
149
|
+
false,
|
|
150
|
+
)
|
|
151
|
+
expect(isDimensionEditAllowed({ ...idle, mode: 'delete' }, { readOnly: false })).toBe(false)
|
|
152
|
+
expect(isDimensionEditAllowed({ ...idle, isPreviewMode: true }, { readOnly: false })).toBe(
|
|
153
|
+
false,
|
|
154
|
+
)
|
|
155
|
+
})
|
|
156
|
+
})
|