@pascal-app/editor 1.0.6 → 1.1.0
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/package.json +18 -15
- package/src/components/editor/action-menu-button.tsx +4 -1
- package/src/components/editor/alignment-3d-guide-layer.tsx +102 -11
- package/src/components/editor/bake-thumbnail.tsx +3 -2
- package/src/components/editor/custom-camera-controls.tsx +110 -42
- package/src/components/editor/duplicate-node.ts +2 -1
- package/src/components/editor/elevation-3d-guide-layer.tsx +1 -1
- package/src/components/editor/first-person-controls.tsx +77 -68
- package/src/components/editor/fit-scene-framing.test.ts +318 -0
- package/src/components/editor/fit-scene-framing.ts +142 -0
- package/src/components/editor/floating-action-menu.tsx +31 -11
- package/src/components/editor/floating-building-action-menu.tsx +1 -1
- package/src/components/editor/floor-openings-overlay.tsx +1 -1
- package/src/components/editor/floor-region-controls.tsx +2 -2
- package/src/components/editor/floorplan-panel.test.ts +220 -0
- package/src/components/editor/floorplan-panel.tsx +458 -140
- package/src/components/editor/floorplan-wall-typing-keys.test.tsx +152 -0
- package/src/components/editor/floorplan-wall-typing-keys.ts +79 -0
- package/src/components/editor/footprint-height-handle.tsx +2 -2
- package/src/components/editor/grid.tsx +24 -15
- package/src/components/editor/group-actions.ts +19 -1
- package/src/components/editor/group-floating-action-menu.tsx +1 -1
- package/src/components/editor/group-move-3d.ts +27 -2
- package/src/components/editor/group-selection-box-3d.tsx +4 -1
- package/src/components/editor/group-transform-shared.ts +23 -1
- package/src/components/editor/index.tsx +150 -20
- package/src/components/editor/inspector-extension-actions.tsx +36 -0
- package/src/components/editor/localized-html.tsx +22 -0
- package/src/components/editor/measurement-pill.tsx +1 -1
- package/src/components/editor/node-action-menu.tsx +46 -12
- package/src/components/editor/node-arrow-handles.tsx +2 -3
- package/src/components/editor/open-wall-ends-3d-layer.tsx +2 -3
- package/src/components/editor/open-wall-ends-hint.tsx +1 -1
- package/src/components/editor/opening-guides-3d-layer.tsx +1 -1
- package/src/components/editor/quick-measurement-card.tsx +1 -1
- package/src/components/editor/registry-action-contributions.test.tsx +67 -6
- package/src/components/editor/registry-action-contributions.tsx +115 -15
- package/src/components/editor/riser-diagram-panel.tsx +59 -9
- package/src/components/editor/room-controls.tsx +4 -3
- package/src/components/editor/room-handles-2d.tsx +158 -7
- package/src/components/editor/room-handles.tsx +244 -54
- package/src/components/editor/room-highlight.tsx +2 -0
- package/src/components/editor/room-labels.tsx +33 -17
- package/src/components/editor/selection-manager.tsx +15 -102
- package/src/components/editor/separator-end-grip.tsx +74 -0
- package/src/components/editor/site-edge-labels.tsx +7 -3
- package/src/components/editor/thumbnail-generator.test.ts +15 -6
- package/src/components/editor/thumbnail-generator.tsx +26 -1
- package/src/components/editor/use-floorplan-background-placement.ts +55 -52
- package/src/components/editor/views/view-bar.tsx +111 -26
- package/src/components/editor/wall-measurement-label.tsx +31 -15
- package/src/components/editor/wall-move-side-handles.tsx +15 -7
- package/src/components/editor/wall-pull-grip.tsx +193 -0
- package/src/components/editor/wall-region-handles.tsx +2 -2
- package/src/components/editor/wall-snap-beacon-layer.tsx +134 -33
- package/src/components/editor-2d/floorplan-adjacent-walls-layer.test.ts +76 -0
- package/src/components/editor-2d/floorplan-adjacent-walls-layer.tsx +186 -0
- package/src/components/editor-2d/floorplan-alignment-guide-layer.tsx +63 -3
- package/src/components/editor-2d/floorplan-group-move.tsx +32 -4
- package/src/components/editor-2d/floorplan-measurement-tool-layer.test.ts +6 -0
- package/src/components/editor-2d/floorplan-measurement-tool-layer.tsx +33 -24
- package/src/components/editor-2d/floorplan-open-wall-ends-layer.tsx +12 -5
- package/src/components/editor-2d/floorplan-registry-action-menu.tsx +2 -1
- package/src/components/editor-2d/floorplan-registry-move-overlay.tsx +29 -5
- package/src/components/editor-2d/floorplan-snap-beacon-layer.tsx +96 -4
- package/src/components/editor-2d/renderers/floorplan-dimension-edit-overlay.tsx +52 -12
- package/src/components/editor-2d/renderers/floorplan-draft-measurement.tsx +7 -1
- package/src/components/editor-2d/renderers/floorplan-placement-preview-layer.tsx +13 -1
- package/src/components/editor-2d/renderers/floorplan-placement-typing-hud.test.tsx +35 -0
- package/src/components/editor-2d/renderers/floorplan-placement-typing-hud.tsx +65 -0
- package/src/components/editor-2d/renderers/floorplan-registry-layer.test.ts +34 -1
- package/src/components/editor-2d/renderers/floorplan-registry-layer.tsx +211 -39
- package/src/components/procedural-items/inspector.tsx +59 -12
- package/src/components/systems/ceiling/ceiling-bracket-batch.test.ts +2 -0
- package/src/components/systems/ceiling/ceiling-system.test.ts +141 -0
- package/src/components/systems/ceiling/ceiling-system.tsx +53 -18
- package/src/components/systems/roof/roof-edit-system.test.tsx +15 -1
- package/src/components/systems/roof/roof-edit-system.tsx +30 -19
- package/src/components/tools/distribution/distribution-run-tool.test.tsx +371 -3
- package/src/components/tools/distribution/distribution-run-tool.tsx +200 -58
- package/src/components/tools/item/move-tool.tsx +1 -6
- package/src/components/tools/item/placement-history.test.tsx +1 -1
- package/src/components/tools/item/placement-strategies.test.ts +64 -1
- package/src/components/tools/item/placement-strategies.ts +5 -9
- package/src/components/tools/item/use-placement-coordinator.tsx +31 -35
- package/src/components/tools/paint-region/wall-paint-region-tool.tsx +1 -1
- package/src/components/tools/registry/item-surface-move.test.ts +11 -0
- package/src/components/tools/registry/move-registry-node-tool.test.ts +42 -1
- package/src/components/tools/registry/move-registry-node-tool.tsx +38 -14
- package/src/components/tools/select/select-candidates.test.ts +45 -0
- package/src/components/tools/select/select-candidates.ts +13 -2
- package/src/components/tools/shared/cursor-sphere.tsx +10 -3
- package/src/components/tools/shared/draft-measurement-label.tsx +1 -1
- package/src/components/tools/shared/placement-box.tsx +2 -6
- package/src/components/tools/shared/placement-coordinate-input.tsx +94 -0
- package/src/components/tools/shared/placement-dimension-guides.tsx +1 -1
- package/src/components/tools/shared/segment-angle.ts +0 -4
- package/src/components/tools/site/terrain-brush-cursor.tsx +1 -1
- package/src/components/tools/tool-manager.tsx +1 -24
- package/src/components/tools/wall/wall-drafting.test.ts +299 -23
- package/src/components/tools/wall/wall-drafting.ts +132 -24
- package/src/components/tools/wall/wall-pull-snap.test.ts +274 -0
- package/src/components/tools/wall/wall-pull-snap.ts +563 -0
- package/src/components/tools/wall/wall-snap-geometry.test.ts +113 -1
- package/src/components/tools/wall/wall-snap-geometry.ts +137 -0
- package/src/components/tools/wall/wall-typed-entry.test.ts +99 -0
- package/src/components/tools/wall/wall-typed-entry.ts +70 -0
- package/src/components/tools/zone/zone-tool.tsx +3 -3
- package/src/components/ui/action-menu/action-button.tsx +2 -0
- package/src/components/ui/action-menu/camera-actions.tsx +8 -7
- package/src/components/ui/action-menu/control-modes.tsx +9 -5
- package/src/components/ui/action-menu/follow-pascal-pill.tsx +3 -1
- package/src/components/ui/action-menu/follow-pascal-toggle.tsx +7 -1
- package/src/components/ui/action-menu/furnish-tools.tsx +7 -6
- package/src/components/ui/action-menu/index.tsx +1 -0
- package/src/components/ui/action-menu/measurement-control.tsx +35 -29
- package/src/components/ui/action-menu/point-ask-button.tsx +4 -3
- package/src/components/ui/action-menu/structure-tools.tsx +25 -23
- package/src/components/ui/action-menu/view-toggles.test.ts +18 -0
- package/src/components/ui/action-menu/view-toggles.tsx +256 -51
- package/src/components/ui/build-panel/build-panel.tsx +163 -25
- package/src/components/ui/command-palette/editor-commands.tsx +38 -11
- package/src/components/ui/controls/finish-swatch.tsx +45 -19
- package/src/components/ui/controls/material-picker.tsx +24 -17
- package/src/components/ui/controls/metric-control.test.ts +52 -0
- package/src/components/ui/controls/metric-control.tsx +62 -24
- package/src/components/ui/controls/segmented-control.tsx +5 -2
- package/src/components/ui/controls/slider-control.test.tsx +23 -0
- package/src/components/ui/controls/slider-control.tsx +47 -19
- package/src/components/ui/controls/tool-options-panel.tsx +74 -44
- package/src/components/ui/floating-level-selector.tsx +100 -48
- package/src/components/ui/helpers/building-helper.tsx +5 -3
- package/src/components/ui/helpers/contextual-helper-panel.tsx +97 -37
- package/src/components/ui/helpers/helper-manager.test.tsx +106 -3
- package/src/components/ui/helpers/helper-manager.tsx +136 -57
- package/src/components/ui/helpers/item-helper.tsx +6 -4
- package/src/components/ui/helpers/registered-tool-helper.tsx +3 -1
- package/src/components/ui/level-duplicate-dialog.tsx +32 -23
- package/src/components/ui/level-wall-copy-prompt.tsx +124 -0
- package/src/components/ui/panels/collections/collections-popover.tsx +11 -11
- package/src/components/ui/panels/deck-boards-fields.tsx +136 -0
- package/src/components/ui/panels/floor-foundation-panel.tsx +114 -39
- package/src/components/ui/panels/floor-opening-panel.tsx +74 -26
- package/src/components/ui/panels/inspector-extensions.tsx +66 -0
- package/src/components/ui/panels/mobile-panel-sheet.tsx +3 -1
- package/src/components/ui/panels/mobile-selection-bar.tsx +34 -28
- package/src/components/ui/panels/multi-field-value.test.ts +27 -0
- package/src/components/ui/panels/multi-field-value.ts +20 -1
- package/src/components/ui/panels/multi-height-mode.tsx +11 -10
- package/src/components/ui/panels/multi-parametric-inspector.tsx +122 -34
- package/src/components/ui/panels/multi-selection-panel.tsx +76 -36
- package/src/components/ui/panels/node-display.ts +35 -24
- package/src/components/ui/panels/panel-manager.tsx +9 -5
- package/src/components/ui/panels/panel-wrapper.tsx +63 -127
- package/src/components/ui/panels/parametric-field-control.tsx +13 -10
- package/src/components/ui/panels/parametric-inspector.tsx +18 -12
- package/src/components/ui/panels/reference-panel.tsx +51 -35
- package/src/components/ui/panels/room-construction-rows.tsx +465 -66
- package/src/components/ui/panels/room-name-options.test.ts +36 -3
- package/src/components/ui/panels/room-name-options.ts +110 -11
- package/src/components/ui/panels/room-openings-field.tsx +22 -13
- package/src/components/ui/panels/room-panel.tsx +207 -100
- package/src/components/ui/panels/shape-choice.tsx +7 -5
- package/src/components/ui/panels/wall-region-list.tsx +7 -7
- package/src/components/ui/primitives/shortcut-token.tsx +10 -6
- package/src/components/ui/right-stack.test.ts +13 -6
- package/src/components/ui/right-stack.tsx +21 -10
- package/src/components/ui/sidebar/icon-rail.tsx +11 -9
- package/src/components/ui/sidebar/panels/items-panel/function-tree-panel.tsx +10 -10
- package/src/components/ui/sidebar/panels/items-panel/index.tsx +10 -9
- package/src/components/ui/sidebar/panels/settings-panel/index.tsx +3 -0
- package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +102 -32
- package/src/components/ui/sidebar/panels/settings-panel/load-build-dialog.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +4 -3
- package/src/components/ui/sidebar/panels/site-panel/ceiling-tree-node.tsx +5 -3
- package/src/components/ui/sidebar/panels/site-panel/chimney-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/collection-tree-node.tsx +7 -5
- package/src/components/ui/sidebar/panels/site-panel/column-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/default-names.ts +75 -0
- package/src/components/ui/sidebar/panels/site-panel/door-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/dormer-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/elevator-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/fence-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/gutter-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/index.tsx +118 -72
- package/src/components/ui/sidebar/panels/site-panel/inline-rename-input.tsx +36 -3
- package/src/components/ui/sidebar/panels/site-panel/item-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +7 -4
- package/src/components/ui/sidebar/panels/site-panel/registry-tree-node.tsx +8 -2
- package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +8 -5
- package/src/components/ui/sidebar/panels/site-panel/shelf-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/slab-tree-node.tsx +9 -4
- package/src/components/ui/sidebar/panels/site-panel/solar-panel-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/spawn-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/stair-tree-node.tsx +8 -7
- package/src/components/ui/sidebar/panels/site-panel/tree-node-actions.tsx +7 -6
- package/src/components/ui/sidebar/panels/site-panel/tree-node.tsx +16 -1
- package/src/components/ui/sidebar/panels/site-panel/unit-tree-node.tsx +15 -8
- package/src/components/ui/sidebar/panels/site-panel/wall-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/window-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/zone-membership-checkbox.tsx +3 -1
- package/src/components/ui/sidebar/panels/site-panel/zone-tree-node.tsx +19 -9
- package/src/components/ui/sidebar/panels/zone-panel/index.tsx +25 -14
- package/src/components/ui/sidebar/tab-bar.tsx +4 -1
- package/src/components/ui/sidebar/use-plugin-panels.tsx +19 -10
- package/src/components/ui/snap-target-badge.tsx +7 -6
- package/src/components/ui/wall-type/wall-type-editor-dialog.tsx +721 -0
- package/src/components/ui/wall-type/wall-type-menu.tsx +167 -0
- package/src/components/viewer/floorplan-compass-button.tsx +12 -3
- package/src/components/viewer/floorplan-preview.tsx +27 -19
- package/src/components/viewer/render-settings-menu.tsx +294 -0
- package/src/components/viewer/sky-control.tsx +710 -0
- package/src/components/viewer/use-viewer-ui-sounds.test.ts +15 -0
- package/src/components/viewer/use-viewer-ui-sounds.ts +46 -0
- package/src/components/viewer/viewer-controls-bar.tsx +278 -260
- package/src/components/viewer/viewer-hover-label.tsx +12 -4
- package/src/components/viewer/viewer-rooms.tsx +62 -5
- package/src/components/viewer/viewer-scene-header.tsx +28 -17
- package/src/components/viewer/viewer-stage-switcher.tsx +4 -2
- package/src/components/viewer-overlay.tsx +8 -0
- package/src/components/walkthrough-hud.tsx +75 -2
- package/src/hooks/use-keyboard.test.ts +85 -4
- package/src/hooks/use-keyboard.ts +65 -7
- package/src/hooks/use-selected-room.ts +12 -1
- package/src/i18n/floor-footprint-name.ts +30 -0
- package/src/i18n/level-name.ts +39 -0
- package/src/i18n/locales/en/messages.po +15849 -0
- package/src/i18n/locales/en/messages.ts +1 -0
- package/src/i18n/locales/en-XA/messages.ts +1 -0
- package/src/i18n/locales/es/messages.po +39331 -0
- package/src/i18n/locales/es/messages.ts +1 -0
- package/src/i18n/locales/fr/messages.po +39331 -0
- package/src/i18n/locales/fr/messages.ts +1 -0
- package/src/i18n/locales/ja/messages.po +39331 -0
- package/src/i18n/locales/ja/messages.ts +1 -0
- package/src/i18n/locales/zh-CN/messages.po +39331 -0
- package/src/i18n/locales/zh-CN/messages.ts +1 -0
- package/src/i18n/locales.test.ts +63 -0
- package/src/i18n/locales.ts +32 -0
- package/src/i18n/message-slot.tsx +25 -0
- package/src/i18n/node-messages.ts +169 -0
- package/src/i18n/pseudo-locale.ts +17 -0
- package/src/i18n/published-entry.test.ts +17 -0
- package/src/i18n/scene-theme-name.ts +16 -0
- package/src/index.tsx +224 -45
- package/src/lib/add-storey.test.ts +3 -3
- package/src/lib/contextual-help.test.ts +20 -1
- package/src/lib/contextual-help.ts +101 -19
- package/src/lib/continuation.ts +38 -11
- package/src/lib/elevation-guides.ts +21 -6
- package/src/lib/elevator-support.ts +1 -72
- package/src/lib/floor-footprints.test.ts +3 -2
- package/src/lib/floor-footprints.ts +1 -9
- package/src/lib/floor-foundation-support.test.ts +15 -6
- package/src/lib/floor-opening-draft.ts +1 -1
- package/src/lib/floor-region-session.ts +1 -1
- package/src/lib/floorplan/dimension-drive.test.ts +36 -2
- package/src/lib/floorplan/dimension-drive.ts +68 -3
- package/src/lib/floorplan/floorplan-export.test.ts +16 -5
- package/src/lib/floorplan/floorplan-export.tsx +13 -16
- package/src/lib/floorplan/floorplan-extension.test.ts +11 -12
- package/src/lib/floorplan/floorplan-extension.ts +37 -18
- package/src/lib/floorplan/floorplan-mode.test.ts +13 -6
- package/src/lib/floorplan/floorplan-mode.ts +14 -12
- package/src/lib/floorplan/floorplan-plugin-install.test.tsx +1 -1
- package/src/lib/floorplan/floorplan-readonly.ts +3 -3
- package/src/lib/floorplan/open-wall-ends.ts +2 -1
- package/src/lib/floorplan/schedules.ts +10 -6
- package/src/lib/floorplan/site-plan/site-annotations.test.ts +46 -1
- package/src/lib/floorplan/site-plan/site-annotations.ts +3 -0
- package/src/lib/floorplan/site-plan/site-parts.ts +6 -3
- package/src/lib/geometry-script/author.test.ts +114 -0
- package/src/lib/geometry-script/author.ts +55 -23
- package/src/lib/geometry-script/client.ts +3 -0
- package/src/lib/geometry-script/finish-scripts.ts +7 -7
- package/src/lib/gesture-lifecycle.ts +3 -1
- package/src/lib/glb-export.test.ts +327 -0
- package/src/lib/glb-export.ts +70 -2
- package/src/lib/grid-frame.test.ts +56 -3
- package/src/lib/grid-frame.ts +28 -1
- package/src/lib/history.test.ts +2 -1
- package/src/lib/hud-title.ts +48 -24
- package/src/lib/ifc-export.test.ts +41 -1
- package/src/lib/inspector-card-mode.test.ts +3 -31
- package/src/lib/inspector-card-mode.ts +5 -10
- package/src/lib/inspector-expanded.test.ts +13 -0
- package/src/lib/inspector-expanded.ts +13 -1
- package/src/lib/interaction/scope.ts +1 -0
- package/src/lib/keyboard-pan.test.ts +7 -0
- package/src/lib/keyboard-pan.ts +9 -2
- package/src/lib/layer-thickness.test.ts +22 -0
- package/src/lib/layer-thickness.ts +79 -0
- package/src/lib/level-selection.test.ts +18 -2
- package/src/lib/level-selection.ts +31 -8
- package/src/lib/linear-display.ts +1 -1
- package/src/lib/live-gesture-round-trip.test.ts +1 -1
- package/src/lib/lot/drop-in.test.ts +59 -1
- package/src/lib/lot/drop-in.ts +42 -50
- package/src/lib/material-swatch-style.ts +24 -0
- package/src/lib/measurement-label.test.ts +1 -1
- package/src/lib/measurement-parser.ts +7 -3
- package/src/lib/measurements.test.ts +24 -6
- package/src/lib/measurements.ts +1 -203
- package/src/lib/mezzanine-selection.test.ts +3 -1
- package/src/lib/node-action-movement.test.tsx +115 -0
- package/src/lib/node-action-movement.ts +2 -0
- package/src/lib/orbit-near-plane.test.ts +12 -0
- package/src/lib/orbit-near-plane.ts +13 -0
- package/src/lib/paint-regions.test.ts +8 -5
- package/src/lib/paint-scope.test.ts +53 -0
- package/src/lib/paint-scope.ts +18 -4
- package/src/lib/panel-rows.ts +17 -8
- package/src/lib/placement-metadata.ts +4 -0
- package/src/lib/point-ask/describe-target.ts +6 -8
- package/src/lib/point-ask/region.ts +1 -1
- package/src/lib/print-shell-compiler.ts +12 -1
- package/src/lib/print-wall-solids.test.ts +11 -0
- package/src/lib/print-wall-solids.ts +9 -0
- package/src/lib/reference-scale.ts +83 -0
- package/src/lib/room-assembly-overlay.ts +1 -1
- package/src/lib/room-built-on.test.ts +28 -17
- package/src/lib/room-built-on.ts +21 -17
- package/src/lib/room-construction-commands.ts +3 -2
- package/src/lib/room-construction.test.ts +28 -1
- package/src/lib/room-construction.ts +14 -0
- package/src/lib/room-controls-phase6.test.ts +141 -1
- package/src/lib/room-handle-drag.ts +554 -58
- package/src/lib/room-name-catalog.test.ts +8 -0
- package/src/lib/room-name-catalog.ts +8 -1
- package/src/lib/room-name-messages.test.ts +132 -0
- package/src/lib/room-name-messages.ts +147 -0
- package/src/lib/room-name-storage.test.ts +334 -0
- package/src/lib/room-push-dimensions.test.ts +38 -1
- package/src/lib/room-push-dimensions.ts +226 -2
- package/src/lib/room-selection.test.ts +23 -6
- package/src/lib/scene-bounds.test.ts +144 -0
- package/src/lib/scene-bounds.ts +79 -15
- package/src/lib/scene-clipboard.test.ts +70 -49
- package/src/lib/scene-clipboard.ts +11 -5
- package/src/lib/selection-cycle.ts +63 -0
- package/src/lib/separator-edit.test.ts +431 -0
- package/src/lib/separator-edit.ts +179 -0
- package/src/lib/separator-lines.ts +38 -0
- package/src/lib/sfx-bus.ts +27 -1
- package/src/lib/sfx-player.ts +16 -0
- package/src/lib/snapping-mode.test.ts +23 -1
- package/src/lib/tool-cursor-icon.ts +5 -1
- package/src/lib/tool-shortcuts.ts +130 -0
- package/src/lib/viewer-selection.test.ts +28 -24
- package/src/lib/viewer-selection.ts +21 -6
- package/src/lib/wall-draw-variant.test.ts +7 -6
- package/src/lib/wall-draw-variant.ts +107 -6
- package/src/lib/wall-nudge.test.ts +44 -0
- package/src/lib/wall-nudge.ts +131 -0
- package/src/lib/wall-parallel-snap.test.ts +83 -0
- package/src/lib/wall-parallel-snap.ts +176 -0
- package/src/lib/wall-placement-pointer.test.ts +23 -0
- package/src/lib/wall-placement-pointer.ts +18 -0
- package/src/lib/wall-pull.test.ts +245 -0
- package/src/lib/wall-pull.ts +209 -0
- package/src/lib/wall-push-line-up.test.ts +132 -0
- package/src/lib/wall-region-list.ts +17 -6
- package/src/lib/wall-run-snap.test.ts +188 -0
- package/src/lib/wall-run-snap.ts +83 -0
- package/src/lib/wall-type.test.ts +125 -0
- package/src/lib/wall-type.ts +119 -0
- package/src/lib/window-interaction.test.ts +44 -0
- package/src/lib/world-grid-snap.test.ts +139 -2
- package/src/lib/world-grid-snap.ts +102 -105
- package/src/store/use-alignment-guides.ts +27 -1
- package/src/store/use-editor.tsx +53 -0
- package/src/store/use-floorplan-annotation-visibility.test.ts +64 -0
- package/src/store/use-floorplan-annotation-visibility.ts +47 -22
- package/src/store/use-placement-typing.test.ts +165 -0
- package/src/store/use-placement-typing.ts +186 -0
- package/src/store/use-wall-snap-indicator.ts +15 -2
- package/src/components/tools/elevator/elevator-defaults.ts +0 -8
- package/src/components/tools/elevator/elevator-tool.tsx +0 -372
- package/src/components/tools/elevator/move-elevator-tool.tsx +0 -262
- package/src/lib/door-interaction.ts +0 -102
- package/src/lib/measurement-label.ts +0 -68
- package/src/lib/window-interaction.ts +0 -100
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"core.level.basement\":[\"地下层\"],\"core.level.basementNumber\":[\"地下 \",[\"number\"],\" 层\"],\"core.level.floorNumber\":[[\"number\"],\" 层\"],\"core.level.groundFloor\":[\"首层\"],\"editor.buildPanel.advanced\":[\"高级\"],\"editor.buildPanel.rooms.hint\":[\"墙体 · 楼板 · 天花板\"],\"editor.buildPanel.rooms.idle\":[\"选择一种形状开始绘制。每个房间都会同时创建墙体、楼板和天花板。\"],\"editor.buildPanel.rooms.polygon.caption\":[[\"lead\"],\"然后再次点击起点闭合。适用于 L 形和斜角房间。\"],\"editor.buildPanel.rooms.polygon.label\":[\"多边形\"],\"editor.buildPanel.rooms.polygon.lead\":[\"依次点击各个角点,\"],\"editor.buildPanel.rooms.polygon.title\":[\"多边形房间\"],\"editor.buildPanel.rooms.rectangle.caption\":[\"在网格上\",[\"lead\"],\"。墙体、楼板和天花板将一并创建。\"],\"editor.buildPanel.rooms.rectangle.label\":[\"矩形\"],\"editor.buildPanel.rooms.rectangle.lead\":[\"点击两个对角点\"],\"editor.buildPanel.rooms.rectangle.title\":[\"矩形房间\"],\"editor.buildPanel.rooms.title\":[\"房间\"],\"editor.buildPanel.rooms.walls.label\":[\"墙体\"],\"editor.buildPanel.rooms.walls.title\":[\"墙体\"],\"viewer.camera.orbitLeft\":[\"向左旋转\"],\"viewer.camera.orbitRight\":[\"向右旋转\"],\"viewer.camera.topView\":[\"俯视图\"],\"viewer.common.off\":[\"关闭\"],\"viewer.common.on\":[\"开启\"],\"viewer.display.camera\":[\"相机\"],\"viewer.display.colored\":[\"彩色\"],\"viewer.display.colors\":[\"颜色\"],\"viewer.display.edges.title\":[\"边线\"],\"viewer.display.monochrome\":[\"单色\"],\"viewer.display.orthographic\":[\"正交\"],\"viewer.display.perspective\":[\"透视\"],\"viewer.display.shadows\":[\"阴影\"],\"viewer.display.title\":[\"显示设置\"],\"viewer.floorplan.alignNorth\":[\"视图对齐北向\"],\"viewer.floorplan.empty\":[\"此场景没有可用的平面图。\"],\"viewer.floorplan.fit\":[\"适合窗口\"],\"viewer.floorplan.floor\":[\"楼层\"],\"viewer.floorplan.floorPlan\":[\"平面图\"],\"viewer.floorplan.viewLabel\":[[\"floor\"],\"二维视图\"],\"viewer.floorplan.zoomIn\":[\"放大\"],\"viewer.floorplan.zoomOut\":[\"缩小\"],\"viewer.header.back\":[\"返回\"],\"viewer.header.levels\":[\"楼层\"],\"viewer.header.rooms\":[\"房间\"],\"viewer.header.selection\":[\"当前选择\"],\"viewer.header.units\":[\"单元\"],\"viewer.header.untitled\":[\"未命名\"],\"viewer.header.zones\":[\"分区\"],\"viewer.levels.exploded\":[\"分解\"],\"viewer.levels.label\":[\"楼层:\",[\"mode\"]],\"viewer.levels.manual\":[\"手动\"],\"viewer.levels.solo\":[\"单层\"],\"viewer.levels.stacked\":[\"叠层\"],\"viewer.stage.layout\":[\"视图布局\"],\"viewer.stage.split\":[\"分屏\"],\"viewer.theme.blueprint\":[\"蓝图\"],\"viewer.theme.mediterranean\":[\"地中海\"],\"viewer.theme.night\":[\"夜景\"],\"viewer.theme.overcast\":[\"阴天\"],\"viewer.theme.paper\":[\"纸面\"],\"viewer.theme.studio\":[\"影棚\"],\"viewer.theme.sunset\":[\"日落\"],\"viewer.theme.title\":[\"场景主题\"],\"viewer.theme.twilight\":[\"暮色\"],\"viewer.theme.verdant\":[\"绿意\"],\"viewer.visibility.guides\":[\"参考图\"],\"viewer.visibility.scans\":[\"扫描模型\"],\"viewer.visibility.title\":[\"可见性\"],\"viewer.walkthrough.label\":[\"漫游:\",[\"state\"]],\"viewer.walls.cutaway\":[\"剖切墙\"],\"viewer.walls.fullHeight\":[\"全高墙\"],\"viewer.walls.label\":[\"墙体:\",[\"mode\"]],\"viewer.walls.low\":[\"矮墙\"]}")as Messages;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { afterEach, expect, test } from 'bun:test'
|
|
2
|
+
import { createI18n, setLocale, translate } from '@pascal-app/core'
|
|
3
|
+
import { authoredLevelName, localizedLevelName } from './level-name'
|
|
4
|
+
import { registerBundledLocales } from './locales'
|
|
5
|
+
|
|
6
|
+
afterEach(() => setLocale('en'))
|
|
7
|
+
|
|
8
|
+
test('bundled locale packs cover the converted viewer and editor surfaces', () => {
|
|
9
|
+
registerBundledLocales()
|
|
10
|
+
|
|
11
|
+
const expectations = {
|
|
12
|
+
'zh-CN': ['显示设置', '房间'],
|
|
13
|
+
fr: ['Paramètres d’affichage', 'Pièces'],
|
|
14
|
+
es: ['Ajustes de visualización', 'Estancias'],
|
|
15
|
+
ja: ['表示設定', '部屋'],
|
|
16
|
+
} as const
|
|
17
|
+
|
|
18
|
+
for (const [locale, [display, rooms]] of Object.entries(expectations)) {
|
|
19
|
+
setLocale(locale)
|
|
20
|
+
expect(translate('viewer.display.title', 'Display settings')).toBe(display)
|
|
21
|
+
expect(translate('editor.buildPanel.rooms.title', 'Rooms')).toBe(rooms)
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test('Simplified Chinese aliases use zh-CN without affecting Traditional Chinese', () => {
|
|
26
|
+
registerBundledLocales()
|
|
27
|
+
|
|
28
|
+
setLocale('zh-Hans')
|
|
29
|
+
expect(translate('viewer.display.title', 'Display settings')).toBe('显示设置')
|
|
30
|
+
|
|
31
|
+
setLocale('zh-Hans-CN')
|
|
32
|
+
expect(translate('viewer.display.title', 'Display settings')).toBe('显示设置')
|
|
33
|
+
|
|
34
|
+
setLocale('zh-Hant')
|
|
35
|
+
expect(translate('viewer.display.title', 'Display settings')).toBe('Display settings')
|
|
36
|
+
|
|
37
|
+
setLocale('zh-TW')
|
|
38
|
+
expect(translate('viewer.display.title', 'Display settings')).toBe('Display settings')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test('generated stored level names localize while authored names remain unchanged', () => {
|
|
42
|
+
registerBundledLocales()
|
|
43
|
+
const french = createI18n({ locale: 'fr' })
|
|
44
|
+
const japanese = createI18n({ locale: 'ja' })
|
|
45
|
+
try {
|
|
46
|
+
expect(localizedLevelName({ level: 0, name: 'Ground floor' }, french, 'fr')).toBe(
|
|
47
|
+
'Rez-de-chaussée',
|
|
48
|
+
)
|
|
49
|
+
expect(localizedLevelName({ level: 1, name: 'Floor 1' }, french, 'fr')).toBe('Étage 1')
|
|
50
|
+
expect(localizedLevelName({ level: 1, name: 'Floor 1' }, japanese, 'ja')).toBe('2階')
|
|
51
|
+
expect(localizedLevelName({ level: 1, name: 'Mezzanine' }, french, 'fr')).toBe('Mezzanine')
|
|
52
|
+
} finally {
|
|
53
|
+
french.destroy()
|
|
54
|
+
japanese.destroy()
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('a stored default level name is not an authored name, so renaming starts empty', () => {
|
|
59
|
+
expect(authoredLevelName({ level: 0, name: 'Ground floor' })).toBeUndefined()
|
|
60
|
+
expect(authoredLevelName({ level: 1, name: 'Level 1' })).toBeUndefined()
|
|
61
|
+
expect(authoredLevelName({ level: 1 })).toBeUndefined()
|
|
62
|
+
expect(authoredLevelName({ level: 1, name: ' Mezzanine ' })).toBe('Mezzanine')
|
|
63
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type CompiledTranslationMessages, registerCompiledMessages } from '@pascal-app/core'
|
|
2
|
+
import { messages as en } from './locales/en/messages'
|
|
3
|
+
import { messages as es } from './locales/es/messages'
|
|
4
|
+
import { messages as fr } from './locales/fr/messages'
|
|
5
|
+
import { messages as ja } from './locales/ja/messages'
|
|
6
|
+
import { messages as zhCN } from './locales/zh-CN/messages'
|
|
7
|
+
|
|
8
|
+
export type BundledLocale = 'en' | 'zh-CN' | 'fr' | 'es' | 'ja'
|
|
9
|
+
|
|
10
|
+
type LocaleCatalog = {
|
|
11
|
+
locale: BundledLocale
|
|
12
|
+
messages: CompiledTranslationMessages
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const bundledLocalePacks: Record<BundledLocale, LocaleCatalog> = {
|
|
16
|
+
en: { locale: 'en', messages: en },
|
|
17
|
+
'zh-CN': { locale: 'zh-CN', messages: zhCN },
|
|
18
|
+
fr: { locale: 'fr', messages: fr },
|
|
19
|
+
es: { locale: 'es', messages: es },
|
|
20
|
+
ja: { locale: 'ja', messages: ja },
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let registered = false
|
|
24
|
+
|
|
25
|
+
export function registerBundledLocales(): void {
|
|
26
|
+
if (registered) return
|
|
27
|
+
registered = true
|
|
28
|
+
|
|
29
|
+
for (const catalog of Object.values(bundledLocalePacks)) {
|
|
30
|
+
registerCompiledMessages(catalog.locale, '', catalog.messages)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { MessageDescriptor, PascalI18n } from '@pascal-app/core'
|
|
2
|
+
import { Fragment, type ReactNode } from 'react'
|
|
3
|
+
|
|
4
|
+
const SLOT = '\uE000'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Renders a whole translated sentence with one React element (a bold name, a
|
|
8
|
+
* link) where the message has `{slot}`, so translators can move it anywhere.
|
|
9
|
+
*/
|
|
10
|
+
export function messageWithSlot(
|
|
11
|
+
i18n: PascalI18n,
|
|
12
|
+
descriptor: MessageDescriptor,
|
|
13
|
+
slot: string,
|
|
14
|
+
element: ReactNode,
|
|
15
|
+
): ReactNode {
|
|
16
|
+
const values = { ...descriptor.values, [slot]: SLOT }
|
|
17
|
+
const text = i18n._(descriptor.id, values, { message: descriptor.message })
|
|
18
|
+
const parts = text.split(SLOT)
|
|
19
|
+
return parts.map((part, index) => (
|
|
20
|
+
<Fragment key={index}>
|
|
21
|
+
{index > 0 && element}
|
|
22
|
+
{part}
|
|
23
|
+
</Fragment>
|
|
24
|
+
))
|
|
25
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import type { MessageDescriptor, PascalI18n } from '@pascal-app/core'
|
|
2
|
+
import { prettifyEnumValue, prettifyKey } from '../components/ui/panels/parametric-field-utils'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Display copy that node definitions carry (presentation labels, tool hints)
|
|
6
|
+
* stays English in the definition, because MCP, agents and exports read it.
|
|
7
|
+
* The editor translates it at display time through IDs derived from the kind
|
|
8
|
+
* and the English text. `scripts/i18n-node-messages.ts` generates the matching
|
|
9
|
+
* descriptors for every built-in kind so they are extracted and translated; a
|
|
10
|
+
* plugin kind can ship the same IDs with `registerMessages`, and otherwise
|
|
11
|
+
* shows its own English.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** Lower-camel slug of up to six words, used in generated message IDs. */
|
|
15
|
+
export function messageSlug(text: string): string {
|
|
16
|
+
const words = text
|
|
17
|
+
.replace(/\{(\w+)[^}]*\}/g, ' $1 ')
|
|
18
|
+
.normalize('NFKD')
|
|
19
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
20
|
+
.match(/[A-Za-z0-9]+/g)
|
|
21
|
+
if (!words?.length) return 'symbol'
|
|
22
|
+
const slug = words
|
|
23
|
+
.slice(0, 6)
|
|
24
|
+
.map((word, index) => {
|
|
25
|
+
const lower = word.toLowerCase()
|
|
26
|
+
return index === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1)
|
|
27
|
+
})
|
|
28
|
+
.join('')
|
|
29
|
+
return /^[0-9]/.test(slug) ? `n${slug}` : slug
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Definition copy is literal text; braces must not read as ICU arguments. */
|
|
33
|
+
function literal(text: string): string {
|
|
34
|
+
return text.replace(/[{}]/g, (brace) => `'${brace}'`)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** `roof-segment` → `roofSegment`. */
|
|
38
|
+
export function nodeKindKey(kind: string): string {
|
|
39
|
+
return kind.replace(/[-_](\w)/g, (_, letter: string) => letter.toUpperCase())
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function nodeLabelDescriptor(kind: string, english: string): MessageDescriptor {
|
|
43
|
+
return { id: `node.${nodeKindKey(kind)}.label`, message: literal(english) }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function nodeDescriptionDescriptor(kind: string, english: string): MessageDescriptor {
|
|
47
|
+
return { id: `node.${nodeKindKey(kind)}.description`, message: literal(english) }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Short FNV-1a hash of the whole message. Hint IDs end with it, so two hints
|
|
52
|
+
* whose first six words agree (a plugin's and a built-in's) never share an ID
|
|
53
|
+
* and so never share a translation.
|
|
54
|
+
*/
|
|
55
|
+
function messageHash(message: string): string {
|
|
56
|
+
let hash = 0x811c9dc5
|
|
57
|
+
for (let index = 0; index < message.length; index += 1) {
|
|
58
|
+
hash ^= message.charCodeAt(index)
|
|
59
|
+
hash = Math.imul(hash, 0x01000193)
|
|
60
|
+
}
|
|
61
|
+
return (hash >>> 0).toString(36)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function hintMessage(message: string): MessageDescriptor {
|
|
65
|
+
return { id: `editor.toolHint.${messageSlug(message)}.${messageHash(message)}`, message }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function toolHintDescriptor(english: string): MessageDescriptor {
|
|
69
|
+
return hintMessage(literal(english))
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* A chip label for one chip value. Labels that spell out a numeric value
|
|
74
|
+
* ("Cuts: 3, even") share one message with the number as `{value}`.
|
|
75
|
+
*/
|
|
76
|
+
export function toolHintChipDescriptor(
|
|
77
|
+
value: string,
|
|
78
|
+
label: string,
|
|
79
|
+
): { descriptor: MessageDescriptor; values?: { value: string } } {
|
|
80
|
+
if (/^\d+$/.test(value) && new RegExp(`\\b${value}\\b`).test(label)) {
|
|
81
|
+
const message = literal(label).replace(new RegExp(`\\b${value}\\b`), '{value}')
|
|
82
|
+
return { descriptor: hintMessage(message), values: { value } }
|
|
83
|
+
}
|
|
84
|
+
return { descriptor: toolHintDescriptor(label) }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function toolHintChipLabel(value: string, label: string, i18n: PascalI18n): string {
|
|
88
|
+
const { descriptor, values } = toolHintChipDescriptor(value, label)
|
|
89
|
+
return i18n._({ ...descriptor, values })
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Gesture and key names the HUD and shortcut tokens print, beyond those the
|
|
94
|
+
* built-in definitions name themselves.
|
|
95
|
+
*/
|
|
96
|
+
export const HINT_KEY_NAMES = [
|
|
97
|
+
'Backspace',
|
|
98
|
+
'Click',
|
|
99
|
+
'Command',
|
|
100
|
+
'Control',
|
|
101
|
+
'Delete',
|
|
102
|
+
'Double click',
|
|
103
|
+
'Drag',
|
|
104
|
+
'Enter',
|
|
105
|
+
'Hover',
|
|
106
|
+
'Left click',
|
|
107
|
+
'Middle click',
|
|
108
|
+
'Right click',
|
|
109
|
+
'Scroll',
|
|
110
|
+
'Scroll wheel',
|
|
111
|
+
'Space',
|
|
112
|
+
'Tab',
|
|
113
|
+
] as const
|
|
114
|
+
|
|
115
|
+
/** Key or gesture names with words in them ("Left click", "Scroll"); bare keys stay as written. */
|
|
116
|
+
export function toolHintKeyDescriptor(key: string): MessageDescriptor | undefined {
|
|
117
|
+
if (!/\p{L}{2}/u.test(key) || /^(?:Alt|Ctrl|Cmd|Esc|Shift)$/.test(key)) {
|
|
118
|
+
return undefined
|
|
119
|
+
}
|
|
120
|
+
const message = literal(key)
|
|
121
|
+
return { id: `editor.toolHint.key.${messageSlug(key)}.${messageHash(message)}`, message }
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Auto-inspector copy (`def.parametrics`): group and action labels, and the
|
|
126
|
+
* field names and enum options it prettifies from keys. Shared across kinds,
|
|
127
|
+
* so "Dimensions" or "Height" is translated once.
|
|
128
|
+
*/
|
|
129
|
+
function inspectorMessage(scope: 'action' | 'field' | 'group' | 'option', english: string) {
|
|
130
|
+
const message = literal(english)
|
|
131
|
+
return {
|
|
132
|
+
id: `editor.inspector.${scope}.${messageSlug(english)}.${messageHash(message)}`,
|
|
133
|
+
message,
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function inspectorGroupDescriptor(label: string): MessageDescriptor {
|
|
138
|
+
return inspectorMessage('group', label)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function inspectorActionDescriptor(label: string): MessageDescriptor {
|
|
142
|
+
return inspectorMessage('action', label)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function inspectorFieldDescriptor(key: string): MessageDescriptor {
|
|
146
|
+
return inspectorMessage('field', prettifyKey(key))
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function inspectorOptionDescriptor(value: string): MessageDescriptor {
|
|
150
|
+
return inspectorMessage('option', prettifyEnumValue(value))
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function nodeLabel(kind: string, english: string, i18n: PascalI18n): string {
|
|
154
|
+
return i18n._(nodeLabelDescriptor(kind, english))
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function toolHintLabel(english: string, i18n: PascalI18n): string {
|
|
158
|
+
return i18n._(toolHintDescriptor(english))
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function toolHintKey(key: string, i18n: PascalI18n): string {
|
|
162
|
+
const descriptor = toolHintKeyDescriptor(key)
|
|
163
|
+
return descriptor ? i18n._(descriptor) : key
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Hint text from a descriptor (editor copy) or English definition copy. */
|
|
167
|
+
export function hintText(value: MessageDescriptor | string, i18n: PascalI18n): string {
|
|
168
|
+
return typeof value === 'string' ? toolHintLabel(value, i18n) : i18n._(value)
|
|
169
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { registerCompiledMessages } from '@pascal-app/core'
|
|
2
|
+
import { messages } from './locales/en-XA/messages'
|
|
3
|
+
|
|
4
|
+
export const PSEUDO_LOCALE = 'en-XA'
|
|
5
|
+
|
|
6
|
+
let registered = false
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Registers `en-XA`, the accented and ~30 % longer pseudo-locale generated
|
|
10
|
+
* from English. It finds untranslated copy and clipping; it is not a language,
|
|
11
|
+
* so hosts enable it only in development or test builds.
|
|
12
|
+
*/
|
|
13
|
+
export function registerPseudoLocale(): void {
|
|
14
|
+
if (registered) return
|
|
15
|
+
registered = true
|
|
16
|
+
registerCompiledMessages(PSEUDO_LOCALE, '', messages)
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { expect, test } from 'bun:test'
|
|
2
|
+
import { createI18n } from '@pascal-app/editor'
|
|
3
|
+
|
|
4
|
+
test('the published editor entry registers compiled English messages', () => {
|
|
5
|
+
const i18n = createI18n({ locale: 'en' })
|
|
6
|
+
try {
|
|
7
|
+
expect(
|
|
8
|
+
i18n._({
|
|
9
|
+
id: 'viewer.levels.label',
|
|
10
|
+
message: 'Levels: {mode}',
|
|
11
|
+
values: { mode: 'Stacked' },
|
|
12
|
+
}),
|
|
13
|
+
).toBe('Levels: Stacked')
|
|
14
|
+
} finally {
|
|
15
|
+
i18n.destroy()
|
|
16
|
+
}
|
|
17
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PascalI18n } from '@pascal-app/core'
|
|
2
|
+
|
|
3
|
+
/** Display name of a built-in scene theme; unknown (plugin) themes keep their own name. */
|
|
4
|
+
export function sceneThemeName(id: string, fallback: string, i18n: PascalI18n): string {
|
|
5
|
+
if (id === 'studio') return i18n._({ id: 'viewer.theme.studio', message: 'Studio' })
|
|
6
|
+
if (id === 'paper') return i18n._({ id: 'viewer.theme.paper', message: 'Paper' })
|
|
7
|
+
if (id === 'sunset') return i18n._({ id: 'viewer.theme.sunset', message: 'Sunset' })
|
|
8
|
+
if (id === 'overcast') return i18n._({ id: 'viewer.theme.overcast', message: 'Overcast' })
|
|
9
|
+
if (id === 'blueprint') return i18n._({ id: 'viewer.theme.blueprint', message: 'Blueprint' })
|
|
10
|
+
if (id === 'mediterranean')
|
|
11
|
+
return i18n._({ id: 'viewer.theme.mediterranean', message: 'Mediterranean' })
|
|
12
|
+
if (id === 'twilight') return i18n._({ id: 'viewer.theme.twilight', message: 'Twilight' })
|
|
13
|
+
if (id === 'night') return i18n._({ id: 'viewer.theme.night', message: 'Night' })
|
|
14
|
+
if (id === 'verdant') return i18n._({ id: 'viewer.theme.verdant', message: 'Verdant' })
|
|
15
|
+
return fallback
|
|
16
|
+
}
|