pixelweaver 0.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/.env.development +1 -0
- package/.github/workflows/ci.yml +22 -0
- package/.github/workflows/publish.yml +18 -0
- package/.prettierignore +5 -0
- package/.prettierrc +16 -0
- package/.python-version +1 -0
- package/.rlsbl/bases/.github/workflows/ci.yml +21 -0
- package/.rlsbl/bases/.github/workflows/publish.yml +18 -0
- package/.rlsbl/bases/.rlsbl/changes/unreleased.jsonl +0 -0
- package/.rlsbl/bases/.rlsbl/hooks/post-release.sh +8 -0
- package/.rlsbl/bases/.rlsbl/hooks/pre-checks.sh +5 -0
- package/.rlsbl/bases/.rlsbl/hooks/pre-release.sh +8 -0
- package/.rlsbl/bases/.rlsbl/lint/go.toml +17 -0
- package/.rlsbl/bases/.rlsbl/lint/npm.toml +19 -0
- package/.rlsbl/bases/.rlsbl/lint/python.toml +25 -0
- package/.rlsbl/bases/CHANGELOG.md +5 -0
- package/.rlsbl/bases/LICENSE +21 -0
- package/.rlsbl/changes/.validated +1 -0
- package/.rlsbl/changes/0.1.0.jsonl +85 -0
- package/.rlsbl/changes/0.1.0.md +13 -0
- package/.rlsbl/changes/unreleased.jsonl +0 -0
- package/.rlsbl/config.json +6 -0
- package/.rlsbl/hashes.json +14 -0
- package/.rlsbl/hooks/post-release.sh +8 -0
- package/.rlsbl/hooks/pre-checks.sh +5 -0
- package/.rlsbl/hooks/pre-release.sh +8 -0
- package/.rlsbl/lint/go.toml +17 -0
- package/.rlsbl/lint/npm.toml +19 -0
- package/.rlsbl/lint/python.toml +25 -0
- package/.rlsbl/releases/unreleased.toml +0 -0
- package/.rlsbl/releases/v0.1.0.toml +3 -0
- package/.rlsbl/version +1 -0
- package/.selfdoc/hashes/hashes.json +146 -0
- package/.strictcli/schema.json +227 -0
- package/CHANGELOG.md +17 -0
- package/CLAUDE.md +100 -0
- package/LICENSE +21 -0
- package/README.md +116 -0
- package/assets/icon.png +0 -0
- package/docs/_README.md +117 -0
- package/docs/cli-config.md +35 -0
- package/docs/cli-dev.md +21 -0
- package/docs/cli-diagnose.md +12 -0
- package/docs/cli-index.md +30 -0
- package/docs/cli-list.md +18 -0
- package/docs/cli-mcp.md +18 -0
- package/docs/cli-new.md +26 -0
- package/docs/cli-open.md +21 -0
- package/docs/cli-serve.md +21 -0
- package/docs/cli-stop.md +12 -0
- package/docs/gen-index.md +36 -0
- package/docs/index.md +13 -0
- package/docs/server-src-pixelweaver-__main__.md +12 -0
- package/docs/server-src-pixelweaver-autosave.md +12 -0
- package/docs/server-src-pixelweaver-bridge.md +12 -0
- package/docs/server-src-pixelweaver-cli.md +12 -0
- package/docs/server-src-pixelweaver-config.md +12 -0
- package/docs/server-src-pixelweaver-connections.md +12 -0
- package/docs/server-src-pixelweaver-main.md +12 -0
- package/docs/server-src-pixelweaver-mcp_bridge.md +12 -0
- package/docs/server-src-pixelweaver-mcp_drawing_tools.md +12 -0
- package/docs/server-src-pixelweaver-mcp_export_tools.md +12 -0
- package/docs/server-src-pixelweaver-mcp_frame_tools.md +12 -0
- package/docs/server-src-pixelweaver-mcp_history_tools.md +12 -0
- package/docs/server-src-pixelweaver-mcp_layer_tools.md +12 -0
- package/docs/server-src-pixelweaver-mcp_lock.md +12 -0
- package/docs/server-src-pixelweaver-mcp_project_tools.md +12 -0
- package/docs/server-src-pixelweaver-mcp_read_tools.md +12 -0
- package/docs/server-src-pixelweaver-mcp_registry.md +12 -0
- package/docs/server-src-pixelweaver-mcp_resources.md +12 -0
- package/docs/server-src-pixelweaver-mcp_server.md +12 -0
- package/docs/server-src-pixelweaver-protocol.md +12 -0
- package/docs/server-src-pixelweaver-state.md +12 -0
- package/docs/server-src-pixelweaver-storage.md +12 -0
- package/docs/server-src-pixelweaver-websocket.md +12 -0
- package/docs/server-src-pixelweaver.md +12 -0
- package/e2e/app-launch.test.ts +35 -0
- package/e2e/menus.test.ts +26 -0
- package/e2e/tools.test.ts +27 -0
- package/e2e/undo-redo.test.ts +11 -0
- package/eslint.config.js +62 -0
- package/index.html +13 -0
- package/package.json +48 -0
- package/playwright.config.ts +19 -0
- package/plugins/builtin/.gitkeep +0 -0
- package/plugins/builtin/advanced-fill-tool.ts +146 -0
- package/plugins/builtin/circle-tool.ts +186 -0
- package/plugins/builtin/diamond-tool.ts +182 -0
- package/plugins/builtin/dither-tool.ts +186 -0
- package/plugins/builtin/drawing-primitives-plugin.ts +362 -0
- package/plugins/builtin/drawing-utils.test.ts +495 -0
- package/plugins/builtin/drawing-utils.ts +431 -0
- package/plugins/builtin/effects/blur.ts +97 -0
- package/plugins/builtin/effects/color-effects.ts +278 -0
- package/plugins/builtin/effects/flip.ts +83 -0
- package/plugins/builtin/effects/glow.ts +118 -0
- package/plugins/builtin/effects/outline.ts +110 -0
- package/plugins/builtin/effects/rotate.ts +357 -0
- package/plugins/builtin/effects/scale.ts +258 -0
- package/plugins/builtin/effects/shadow.ts +111 -0
- package/plugins/builtin/effects/sharpen.ts +102 -0
- package/plugins/builtin/effects.test.ts +715 -0
- package/plugins/builtin/eraser-tool.ts +23 -0
- package/plugins/builtin/eyedropper-tool.ts +83 -0
- package/plugins/builtin/fill-tool.ts +93 -0
- package/plugins/builtin/gradient-tool.ts +204 -0
- package/plugins/builtin/gradient.test.ts +142 -0
- package/plugins/builtin/importers/aseprite-importer-plugin.ts +174 -0
- package/plugins/builtin/importers/aseprite-parser.ts +497 -0
- package/plugins/builtin/importers/piskel-importer-plugin.ts +222 -0
- package/plugins/builtin/importers/sky-spec-plugin.ts +409 -0
- package/plugins/builtin/line-tool.ts +267 -0
- package/plugins/builtin/make-stroke-tool.ts +271 -0
- package/plugins/builtin/noise-dither.test.ts +151 -0
- package/plugins/builtin/noise-tool.ts +131 -0
- package/plugins/builtin/pattern-stamp-tool.ts +162 -0
- package/plugins/builtin/pencil-tool.ts +25 -0
- package/plugins/builtin/rect-tool.ts +179 -0
- package/plugins/builtin/selection-tool.ts +388 -0
- package/plugins/builtin/selection.test.ts +195 -0
- package/plugins/builtin/tool-plugins.test.ts +529 -0
- package/public/favicon.svg +7 -0
- package/public/sw.js +91 -0
- package/pyproject.toml +49 -0
- package/scripts/eslint-wave-a-list.sh +24 -0
- package/scripts/eslint-wave-a-status.sh +25 -0
- package/scripts/fix-index-signature-access.py +127 -0
- package/scripts/fix-unchecked-index.py +128 -0
- package/scripts/fix-unchecked-vars.py +127 -0
- package/scripts/fix-wave-a-bangs.py +36 -0
- package/scripts/fix-wave-a-templates.py +108 -0
- package/scripts/fix-wave-b-void-expr.py +167 -0
- package/scripts/generate-command-params.py +540 -0
- package/scripts/migrate-single-frame-to-multi.py +171 -0
- package/scripts/smoke-test.sh +77 -0
- package/selfdoc.json +10 -0
- package/server/README.md +0 -0
- package/server/src/pixelweaver/__init__.py +1 -0
- package/server/src/pixelweaver/__main__.py +4 -0
- package/server/src/pixelweaver/autosave.py +114 -0
- package/server/src/pixelweaver/bridge.py +127 -0
- package/server/src/pixelweaver/cli.py +199 -0
- package/server/src/pixelweaver/config.py +24 -0
- package/server/src/pixelweaver/connections.py +54 -0
- package/server/src/pixelweaver/main.py +271 -0
- package/server/src/pixelweaver/mcp_bridge.py +189 -0
- package/server/src/pixelweaver/mcp_drawing_tools.py +178 -0
- package/server/src/pixelweaver/mcp_export_tools.py +291 -0
- package/server/src/pixelweaver/mcp_frame_tools.py +423 -0
- package/server/src/pixelweaver/mcp_history_tools.py +106 -0
- package/server/src/pixelweaver/mcp_layer_tools.py +64 -0
- package/server/src/pixelweaver/mcp_lock.py +37 -0
- package/server/src/pixelweaver/mcp_project_tools.py +302 -0
- package/server/src/pixelweaver/mcp_read_tools.py +163 -0
- package/server/src/pixelweaver/mcp_registry.py +247 -0
- package/server/src/pixelweaver/mcp_resources.py +312 -0
- package/server/src/pixelweaver/mcp_server.py +234 -0
- package/server/src/pixelweaver/protocol.py +219 -0
- package/server/src/pixelweaver/state.py +267 -0
- package/server/src/pixelweaver/storage.py +293 -0
- package/server/src/pixelweaver/websocket.py +282 -0
- package/server/tests/__init__.py +0 -0
- package/server/tests/conftest.py +17 -0
- package/server/tests/test_api.py +96 -0
- package/server/tests/test_bridge.py +161 -0
- package/server/tests/test_health.py +9 -0
- package/server/tests/test_integration.py +86 -0
- package/server/tests/test_mcp_bridge.py +293 -0
- package/server/tests/test_mcp_lock.py +34 -0
- package/server/tests/test_mcp_registry.py +679 -0
- package/server/tests/test_mcp_resources.py +648 -0
- package/server/tests/test_protocol.py +125 -0
- package/server/tests/test_state.py +87 -0
- package/server/tests/test_storage.py +306 -0
- package/server/tests/test_websocket.py +275 -0
- package/src/App.svelte +107 -0
- package/src/app.css +215 -0
- package/src/lib/animation/AnimationPreviewPanel.svelte +667 -0
- package/src/lib/animation/animation-commands.test.ts +228 -0
- package/src/lib/animation/animation-commands.ts +540 -0
- package/src/lib/animation/animation-preview-panel-plugin.ts +25 -0
- package/src/lib/animation/animation-preview.svelte.ts +151 -0
- package/src/lib/animation/clipboard.ts +134 -0
- package/src/lib/animation/frame-model.svelte.ts +437 -0
- package/src/lib/animation/frame-model.test.ts +314 -0
- package/src/lib/animation/frame-selection.svelte.ts +77 -0
- package/src/lib/animation/frame-tags.svelte.ts +238 -0
- package/src/lib/animation/frame-tags.test.ts +136 -0
- package/src/lib/animation/import.test.ts +141 -0
- package/src/lib/animation/import.ts +112 -0
- package/src/lib/animation/spritesheet-export.test.ts +239 -0
- package/src/lib/animation/spritesheet-export.ts +314 -0
- package/src/lib/canvas/CanvasViewport.svelte +216 -0
- package/src/lib/canvas/canvas-init-plugin.ts +178 -0
- package/src/lib/canvas/canvas-renderer.ts +408 -0
- package/src/lib/canvas/canvas-state.svelte.ts +232 -0
- package/src/lib/canvas/canvas-state.test.ts +139 -0
- package/src/lib/canvas/input-handler.ts +221 -0
- package/src/lib/canvas/input-plugin.ts +150 -0
- package/src/lib/canvas/onion-skin.ts +94 -0
- package/src/lib/canvas/pixel-buffer.test.ts +249 -0
- package/src/lib/canvas/pixel-buffer.ts +151 -0
- package/src/lib/canvas/render-state.svelte.ts +18 -0
- package/src/lib/canvas/shape-preview-state.svelte.ts +36 -0
- package/src/lib/canvas/tile-mode.test.ts +53 -0
- package/src/lib/canvas/tile-mode.ts +92 -0
- package/src/lib/canvas/viewport-utils.ts +24 -0
- package/src/lib/canvas/zoom-utils.ts +31 -0
- package/src/lib/color/.gitkeep +0 -0
- package/src/lib/color/color-commands.ts +87 -0
- package/src/lib/color/color-state.svelte.ts +98 -0
- package/src/lib/color/color-state.test.ts +91 -0
- package/src/lib/color/color-utils.test.ts +220 -0
- package/src/lib/color/color-utils.ts +243 -0
- package/src/lib/color/palette-state.svelte.ts +127 -0
- package/src/lib/color/palette-state.test.ts +154 -0
- package/src/lib/color/palette.ts +79 -0
- package/src/lib/core/bootstrap.ts +66 -0
- package/src/lib/core/command-params.generated.ts +1549 -0
- package/src/lib/core/command-params.ts +20 -0
- package/src/lib/core/command-runner.ts +79 -0
- package/src/lib/core/commands.ts +134 -0
- package/src/lib/core/dispatcher.test.ts +548 -0
- package/src/lib/core/dispatcher.ts +361 -0
- package/src/lib/core/index.test.ts +7 -0
- package/src/lib/core/notification-state.svelte.ts +119 -0
- package/src/lib/core/plugin-api.ts +210 -0
- package/src/lib/core/plugin-discovery.test.ts +53 -0
- package/src/lib/core/plugin-discovery.ts +65 -0
- package/src/lib/core/plugin-loader.test.ts +159 -0
- package/src/lib/core/plugin-loader.ts +240 -0
- package/src/lib/core/plugin-types.ts +286 -0
- package/src/lib/core/registries.svelte.ts +74 -0
- package/src/lib/core/tool-options-state.svelte.ts +61 -0
- package/src/lib/dock/DockLayout.svelte +375 -0
- package/src/lib/dock/TabAddMenu.svelte +90 -0
- package/src/lib/dock/dock-persistence.ts +46 -0
- package/src/lib/dock/dock-plugin.ts +49 -0
- package/src/lib/dock/dock-presets.ts +156 -0
- package/src/lib/dock/dock-state.svelte.ts +77 -0
- package/src/lib/dock/dock-types.ts +2 -0
- package/src/lib/dock/dockview-theme.css +226 -0
- package/src/lib/dock/dockview-theme.ts +17 -0
- package/src/lib/dock/header-action-renderer.ts +77 -0
- package/src/lib/edit/clipboard-state.ts +34 -0
- package/src/lib/export/download.ts +201 -0
- package/src/lib/export/png-metadata.ts +181 -0
- package/src/lib/history/ActionLogPanel.svelte +418 -0
- package/src/lib/history/action-log-panel-plugin.ts +24 -0
- package/src/lib/history/action-log.svelte.ts +172 -0
- package/src/lib/history/action-log.test.ts +168 -0
- package/src/lib/history/history-commands.ts +403 -0
- package/src/lib/history/macros.svelte.ts +320 -0
- package/src/lib/history/macros.test.ts +224 -0
- package/src/lib/history/replay-engine.test.ts +241 -0
- package/src/lib/history/replay-engine.ts +149 -0
- package/src/lib/history/spec-format.test.ts +250 -0
- package/src/lib/history/spec-format.ts +210 -0
- package/src/lib/iso/SeamCheckerPanel.svelte +251 -0
- package/src/lib/iso/iso-math.test.ts +77 -0
- package/src/lib/iso/iso-math.ts +77 -0
- package/src/lib/iso/seam-checker-panel-plugin.ts +25 -0
- package/src/lib/iso/seam-checker.test.ts +126 -0
- package/src/lib/iso/seam-checker.ts +93 -0
- package/src/lib/iso/tessellation.ts +67 -0
- package/src/lib/layers/compositor.test.ts +193 -0
- package/src/lib/layers/compositor.ts +175 -0
- package/src/lib/layers/layer-commands.test.ts +263 -0
- package/src/lib/layers/layer-commands.ts +429 -0
- package/src/lib/layers/layer-tree.svelte.ts +516 -0
- package/src/lib/layers/layer-tree.test.ts +383 -0
- package/src/lib/layers/layer-types.ts +56 -0
- package/src/lib/leveleditor/LevelEditorViewport.svelte +1808 -0
- package/src/lib/leveleditor/MapPropertiesPanel.svelte +266 -0
- package/src/lib/leveleditor/TilePickerPanel.svelte +324 -0
- package/src/lib/leveleditor/depth-sort.test.ts +70 -0
- package/src/lib/leveleditor/depth-sort.ts +39 -0
- package/src/lib/leveleditor/level-editor-commands.ts +353 -0
- package/src/lib/leveleditor/level-editor-viewport-plugin.ts +25 -0
- package/src/lib/leveleditor/map-properties-panel-plugin.ts +25 -0
- package/src/lib/leveleditor/map-state.svelte.ts +372 -0
- package/src/lib/leveleditor/map-state.test.ts +243 -0
- package/src/lib/leveleditor/tile-picker-panel-plugin.ts +25 -0
- package/src/lib/leveleditor/tile-source-registry.svelte.ts +91 -0
- package/src/lib/leveleditor/tiled-export.test.ts +144 -0
- package/src/lib/leveleditor/tiled-export.ts +374 -0
- package/src/lib/pywebview.d.ts +15 -0
- package/src/lib/recovery/.gitkeep +0 -0
- package/src/lib/recovery/idb-store.ts +118 -0
- package/src/lib/recovery/recovery-manager.test.ts +321 -0
- package/src/lib/recovery/recovery-manager.ts +115 -0
- package/src/lib/recovery/recovery-plugin.ts +55 -0
- package/src/lib/recovery/recovery-state.svelte.ts +21 -0
- package/src/lib/recovery/sw-plugin.ts +18 -0
- package/src/lib/recovery/sw-register.ts +17 -0
- package/src/lib/save/directory-format.ts +42 -0
- package/src/lib/save/project-snapshot.ts +139 -0
- package/src/lib/save/recent-projects.ts +56 -0
- package/src/lib/save/save-state.svelte.ts +35 -0
- package/src/lib/save/storage.ts +167 -0
- package/src/lib/save/zip-format.ts +45 -0
- package/src/lib/shortcuts/.gitkeep +0 -0
- package/src/lib/shortcuts/ShortcutEditorPanel.svelte +690 -0
- package/src/lib/shortcuts/default-bindings.ts +61 -0
- package/src/lib/shortcuts/shortcut-editor-panel-plugin.ts +25 -0
- package/src/lib/shortcuts/shortcut-init.ts +380 -0
- package/src/lib/shortcuts/shortcut-manager.test.ts +466 -0
- package/src/lib/shortcuts/shortcut-manager.ts +281 -0
- package/src/lib/shortcuts/shortcut-state.svelte.ts +78 -0
- package/src/lib/shortcuts/shortcuts-plugin.ts +17 -0
- package/src/lib/sync/patch-applicator.ts +300 -0
- package/src/lib/sync/patch-types.ts +65 -0
- package/src/lib/sync/project-manager.ts +108 -0
- package/src/lib/sync/sync-init.ts +152 -0
- package/src/lib/sync/sync-plugin.ts +19 -0
- package/src/lib/sync/sync-state.svelte.ts +56 -0
- package/src/lib/sync/ws-client.test.ts +604 -0
- package/src/lib/sync/ws-client.ts +574 -0
- package/src/lib/tools/.gitkeep +0 -0
- package/src/lib/ui/.gitkeep +0 -0
- package/src/lib/ui/AboutDialog.svelte +113 -0
- package/src/lib/ui/ColorPicker.svelte +761 -0
- package/src/lib/ui/ContextMenu.svelte +216 -0
- package/src/lib/ui/ExportDialog.svelte +747 -0
- package/src/lib/ui/FrameStrip.svelte +854 -0
- package/src/lib/ui/LayerPanel.svelte +810 -0
- package/src/lib/ui/MenuBar.svelte +590 -0
- package/src/lib/ui/NewProjectDialog.svelte +803 -0
- package/src/lib/ui/PluginManagerPanel.svelte +475 -0
- package/src/lib/ui/PromptDialog.svelte +252 -0
- package/src/lib/ui/RecoveryDialog.svelte +295 -0
- package/src/lib/ui/ResizeDialog.svelte +416 -0
- package/src/lib/ui/StatusBar.svelte +145 -0
- package/src/lib/ui/ToolbarPanel.svelte +488 -0
- package/src/lib/ui/animation-menu-commands.ts +194 -0
- package/src/lib/ui/command-palette/CommandPalette.svelte +232 -0
- package/src/lib/ui/command-palette/command-palette-plugin.ts +30 -0
- package/src/lib/ui/command-palette/command-palette-state.svelte.ts +190 -0
- package/src/lib/ui/command-palette/command-palette.test.ts +129 -0
- package/src/lib/ui/dialog-state.svelte.ts +70 -0
- package/src/lib/ui/edit-commands.ts +271 -0
- package/src/lib/ui/file-commands.ts +275 -0
- package/src/lib/ui/file-open.ts +99 -0
- package/src/lib/ui/help-commands.ts +93 -0
- package/src/lib/ui/image-commands.ts +181 -0
- package/src/lib/ui/layer-menu-commands.ts +420 -0
- package/src/lib/ui/menu-builder.ts +224 -0
- package/src/lib/ui/notifications/NotificationBanner.svelte +137 -0
- package/src/lib/ui/notifications/notification-plugin.ts +29 -0
- package/src/lib/ui/notifications/notification-state.svelte.ts +9 -0
- package/src/lib/ui/plugin-manager-panel-plugin.ts +26 -0
- package/src/lib/ui/plugin-state.svelte.ts +62 -0
- package/src/lib/ui/select-commands.ts +75 -0
- package/src/lib/ui/theme-plugin.ts +18 -0
- package/src/lib/ui/theme.svelte.ts +45 -0
- package/src/lib/ui/theme.test.ts +51 -0
- package/src/lib/ui/toolbar-config.ts +90 -0
- package/src/lib/ui/toolbar-plugin.ts +39 -0
- package/src/lib/ui/view-commands.ts +629 -0
- package/src/lib/variants/BisectionExportDialog.svelte +500 -0
- package/src/lib/variants/VariantPanel.svelte +822 -0
- package/src/lib/variants/bisection-export.test.ts +113 -0
- package/src/lib/variants/bisection-export.ts +148 -0
- package/src/lib/variants/palette-extraction.test.ts +111 -0
- package/src/lib/variants/palette-extraction.ts +84 -0
- package/src/lib/variants/palette-interpolation.test.ts +113 -0
- package/src/lib/variants/palette-interpolation.ts +87 -0
- package/src/lib/variants/palette-swap.test.ts +101 -0
- package/src/lib/variants/palette-swap.ts +114 -0
- package/src/lib/variants/variant-commands.ts +594 -0
- package/src/lib/variants/variant-panel-plugin.ts +27 -0
- package/src/lib/variants/variant-randomizer.ts +101 -0
- package/src/lib/variants/variant-state.svelte.ts +166 -0
- package/src/lib/variants/variant-state.test.ts +138 -0
- package/src/main.ts +14 -0
- package/src/vite-env.d.ts +3 -0
- package/svelte.config.js +2 -0
- package/todo/.done/audit-design-decisions.md +812 -0
- package/todo/.done/audit-implementation-plan.md +1235 -0
- package/todo/.done/happy-path-polish.md +177 -0
- package/todo/.done/pixelweaver-full-build.md +937 -0
- package/todo/.done/server-multi-frame-design.md +405 -0
- package/todo/.done/typed-dispatcher-design.md +435 -0
- package/todo/.done/unified-toolbar-and-action-system.md +323 -0
- package/todo/.obsolete/comprehensive-audit-obsolete-items.md +33 -0
- package/todo/.obsolete/tauri-desktop-bundle.md +424 -0
- package/todo/comprehensive-audit.md +1085 -0
- package/tsconfig.app.json +26 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +20 -0
- package/uv.lock +1167 -0
- package/vite.config.ts +32 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { dockState } from './dock-state.svelte.js';
|
|
2
|
+
import type { DockviewApi } from 'dockview-core';
|
|
3
|
+
|
|
4
|
+
export interface LayoutPreset {
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
apply: () => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** Clear all panels and rebuild using the given builder function */
|
|
11
|
+
function clearAndRebuild(builder: (api: DockviewApi) => void): void {
|
|
12
|
+
const api = dockState.api;
|
|
13
|
+
if (!api) return;
|
|
14
|
+
api.clear();
|
|
15
|
+
builder(api);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const presets: LayoutPreset[] = [
|
|
19
|
+
{
|
|
20
|
+
name: 'Default',
|
|
21
|
+
description: 'Canvas center, Colors/Layers/Seam Checker right, Animation bottom',
|
|
22
|
+
apply() {
|
|
23
|
+
clearAndRebuild((api) => {
|
|
24
|
+
// Center: Canvas
|
|
25
|
+
api.addPanel({ id: 'canvas', title: 'Canvas', component: 'canvas' });
|
|
26
|
+
// Left: Drawing Tools (own split, fixed width toolbar)
|
|
27
|
+
api.addPanel({
|
|
28
|
+
id: 'toolbar-drawing-tools',
|
|
29
|
+
title: 'Drawing Tools',
|
|
30
|
+
component: 'toolbar-drawing-tools',
|
|
31
|
+
position: { direction: 'left' },
|
|
32
|
+
initialWidth: 50,
|
|
33
|
+
minimumWidth: 50,
|
|
34
|
+
maximumWidth: 50,
|
|
35
|
+
});
|
|
36
|
+
// Top: View Controls (own split, fixed height toolbar)
|
|
37
|
+
api.addPanel({
|
|
38
|
+
id: 'toolbar-view-controls',
|
|
39
|
+
title: 'View Controls',
|
|
40
|
+
component: 'toolbar-view-controls',
|
|
41
|
+
position: { direction: 'above' },
|
|
42
|
+
initialHeight: 48,
|
|
43
|
+
minimumHeight: 48,
|
|
44
|
+
maximumHeight: 48,
|
|
45
|
+
});
|
|
46
|
+
// Right: Colors + Layers tabbed
|
|
47
|
+
api.addPanel({
|
|
48
|
+
id: 'colors',
|
|
49
|
+
title: 'Colors',
|
|
50
|
+
component: 'colors',
|
|
51
|
+
position: { direction: 'right' },
|
|
52
|
+
initialWidth: 280,
|
|
53
|
+
});
|
|
54
|
+
api.addPanel({
|
|
55
|
+
id: 'layers',
|
|
56
|
+
title: 'Layers',
|
|
57
|
+
component: 'layers',
|
|
58
|
+
position: { referencePanel: 'colors', direction: 'within' },
|
|
59
|
+
});
|
|
60
|
+
api.addPanel({
|
|
61
|
+
id: 'seam-checker',
|
|
62
|
+
title: 'Seam Checker',
|
|
63
|
+
component: 'seam-checker',
|
|
64
|
+
position: { referencePanel: 'colors', direction: 'within' },
|
|
65
|
+
});
|
|
66
|
+
// Bottom: Animation
|
|
67
|
+
api.addPanel({
|
|
68
|
+
id: 'frames',
|
|
69
|
+
title: 'Animation',
|
|
70
|
+
component: 'frames',
|
|
71
|
+
position: { direction: 'below' },
|
|
72
|
+
initialHeight: 120,
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'Compact',
|
|
79
|
+
description: 'Canvas only, all panels hidden',
|
|
80
|
+
apply() {
|
|
81
|
+
clearAndRebuild((api) => {
|
|
82
|
+
api.addPanel({ id: 'canvas', title: 'Canvas', component: 'canvas' });
|
|
83
|
+
// Left: Drawing Tools only (minimal setup)
|
|
84
|
+
api.addPanel({
|
|
85
|
+
id: 'toolbar-drawing-tools',
|
|
86
|
+
title: 'Drawing Tools',
|
|
87
|
+
component: 'toolbar-drawing-tools',
|
|
88
|
+
position: { direction: 'left' },
|
|
89
|
+
initialWidth: 50,
|
|
90
|
+
minimumWidth: 50,
|
|
91
|
+
maximumWidth: 50,
|
|
92
|
+
});
|
|
93
|
+
// Top: View Controls
|
|
94
|
+
api.addPanel({
|
|
95
|
+
id: 'toolbar-view-controls',
|
|
96
|
+
title: 'View Controls',
|
|
97
|
+
component: 'toolbar-view-controls',
|
|
98
|
+
position: { direction: 'above' },
|
|
99
|
+
initialHeight: 48,
|
|
100
|
+
minimumHeight: 48,
|
|
101
|
+
maximumHeight: 48,
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'Animation',
|
|
108
|
+
description: 'Larger animation strip, canvas center, panels right',
|
|
109
|
+
apply() {
|
|
110
|
+
clearAndRebuild((api) => {
|
|
111
|
+
api.addPanel({ id: 'canvas', title: 'Canvas', component: 'canvas' });
|
|
112
|
+
// Left: Drawing Tools (own split)
|
|
113
|
+
api.addPanel({
|
|
114
|
+
id: 'toolbar-drawing-tools',
|
|
115
|
+
title: 'Drawing Tools',
|
|
116
|
+
component: 'toolbar-drawing-tools',
|
|
117
|
+
position: { direction: 'left' },
|
|
118
|
+
initialWidth: 50,
|
|
119
|
+
minimumWidth: 50,
|
|
120
|
+
maximumWidth: 50,
|
|
121
|
+
});
|
|
122
|
+
// Top: View Controls (own split)
|
|
123
|
+
api.addPanel({
|
|
124
|
+
id: 'toolbar-view-controls',
|
|
125
|
+
title: 'View Controls',
|
|
126
|
+
component: 'toolbar-view-controls',
|
|
127
|
+
position: { direction: 'above' },
|
|
128
|
+
initialHeight: 48,
|
|
129
|
+
minimumHeight: 48,
|
|
130
|
+
maximumHeight: 48,
|
|
131
|
+
});
|
|
132
|
+
api.addPanel({
|
|
133
|
+
id: 'colors',
|
|
134
|
+
title: 'Colors',
|
|
135
|
+
component: 'colors',
|
|
136
|
+
position: { direction: 'right' },
|
|
137
|
+
initialWidth: 280,
|
|
138
|
+
});
|
|
139
|
+
api.addPanel({
|
|
140
|
+
id: 'layers',
|
|
141
|
+
title: 'Layers',
|
|
142
|
+
component: 'layers',
|
|
143
|
+
position: { referencePanel: 'colors', direction: 'within' },
|
|
144
|
+
});
|
|
145
|
+
// Bottom takes more space for animation workflow
|
|
146
|
+
api.addPanel({
|
|
147
|
+
id: 'frames',
|
|
148
|
+
title: 'Animation',
|
|
149
|
+
component: 'frames',
|
|
150
|
+
position: { direction: 'below' },
|
|
151
|
+
initialHeight: 200,
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
];
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { PanelConfig } from '../core/plugin-types.js';
|
|
2
|
+
import { panelRegistry } from '../core/registries.svelte.js';
|
|
3
|
+
import type { DockviewApi } from 'dockview-core';
|
|
4
|
+
|
|
5
|
+
// Reference to the active dockview API (set by DockLayout on mount)
|
|
6
|
+
let api: DockviewApi | null = $state(null);
|
|
7
|
+
|
|
8
|
+
export const dockState = {
|
|
9
|
+
/** Get all registered panels (reads from the central panelRegistry) */
|
|
10
|
+
get panels(): ReadonlyMap<string, PanelConfig> {
|
|
11
|
+
return panelRegistry.getAll();
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
/** Get a specific panel config */
|
|
15
|
+
getPanel(id: string): PanelConfig | undefined {
|
|
16
|
+
return panelRegistry.get(id);
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
/** Set the dockview API reference (called by DockLayout on mount) */
|
|
20
|
+
setApi(dockApi: DockviewApi): void {
|
|
21
|
+
api = dockApi;
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
/** Get the dockview API */
|
|
25
|
+
get api(): DockviewApi | null {
|
|
26
|
+
return api;
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
/** Add a panel to the dock layout at runtime */
|
|
30
|
+
addPanel(id: string): void {
|
|
31
|
+
if (!api) return;
|
|
32
|
+
const config = panelRegistry.get(id);
|
|
33
|
+
if (!config) return;
|
|
34
|
+
api.addPanel({
|
|
35
|
+
id,
|
|
36
|
+
title: config.title,
|
|
37
|
+
// The component key matches the panel id in our createComponent factory
|
|
38
|
+
component: id,
|
|
39
|
+
});
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
/** Remove a panel from the dock layout */
|
|
43
|
+
removePanel(id: string): void {
|
|
44
|
+
if (!api) return;
|
|
45
|
+
const panel = api.getPanel(id);
|
|
46
|
+
if (panel) {
|
|
47
|
+
api.removePanel(panel);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
/** Show/focus a panel (if it's already added) */
|
|
52
|
+
focusPanel(id: string): void {
|
|
53
|
+
if (!api) return;
|
|
54
|
+
const panel = api.getPanel(id);
|
|
55
|
+
if (panel) {
|
|
56
|
+
panel.api.setActive();
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
/** Check if a panel is visible in the layout */
|
|
61
|
+
isPanelVisible(id: string): boolean {
|
|
62
|
+
if (!api) return false;
|
|
63
|
+
return api.getPanel(id) !== undefined;
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
/** Serialize layout to JSON */
|
|
67
|
+
serializeLayout(): object | null {
|
|
68
|
+
if (!api) return null;
|
|
69
|
+
return api.toJSON();
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
/** Restore layout from JSON */
|
|
73
|
+
restoreLayout(layout: object): void {
|
|
74
|
+
if (!api) return;
|
|
75
|
+
api.fromJSON(layout as Parameters<DockviewApi['fromJSON']>[0]);
|
|
76
|
+
},
|
|
77
|
+
};
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* PixelWeaver dockview theme
|
|
3
|
+
*
|
|
4
|
+
* Custom dockview-core theme that maps all dockview CSS variables to
|
|
5
|
+
* PixelWeaver's design tokens (defined in app.css). Because every color
|
|
6
|
+
* references a CSS custom property, the theme automatically adapts when
|
|
7
|
+
* the user switches between dark and light mode.
|
|
8
|
+
*
|
|
9
|
+
* Apply by passing the exported `themePixelWeaver` DockviewTheme object
|
|
10
|
+
* to the DockviewComponent constructor options.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
.dockview-theme-pixelweaver {
|
|
14
|
+
|
|
15
|
+
/* --- Tab bar (the strip that holds tabs + action buttons) --- */
|
|
16
|
+
--dv-tabs-and-actions-container-background-color: var(--bg-toolbar);
|
|
17
|
+
--dv-tabs-and-actions-container-height: 28px;
|
|
18
|
+
--dv-tabs-and-actions-container-font-size: var(--text-sm);
|
|
19
|
+
|
|
20
|
+
/* --- Panel / group background --- */
|
|
21
|
+
--dv-group-view-background-color: var(--bg-panel);
|
|
22
|
+
|
|
23
|
+
/* --- Active group, visible (selected) tab --- */
|
|
24
|
+
--dv-activegroup-visiblepanel-tab-background-color: var(--bg-panel);
|
|
25
|
+
--dv-activegroup-visiblepanel-tab-color: var(--text-primary);
|
|
26
|
+
|
|
27
|
+
/* --- Active group, hidden (inactive) tabs --- */
|
|
28
|
+
--dv-activegroup-hiddenpanel-tab-background-color: var(--bg-toolbar);
|
|
29
|
+
--dv-activegroup-hiddenpanel-tab-color: var(--text-secondary);
|
|
30
|
+
|
|
31
|
+
/* --- Inactive group, visible tab --- */
|
|
32
|
+
--dv-inactivegroup-visiblepanel-tab-background-color: var(--bg-secondary);
|
|
33
|
+
--dv-inactivegroup-visiblepanel-tab-color: var(--text-secondary);
|
|
34
|
+
|
|
35
|
+
/* --- Inactive group, hidden tabs --- */
|
|
36
|
+
--dv-inactivegroup-hiddenpanel-tab-background-color: var(--bg-toolbar);
|
|
37
|
+
--dv-inactivegroup-hiddenpanel-tab-color: var(--text-muted);
|
|
38
|
+
|
|
39
|
+
/* --- Tab dividers and borders --- */
|
|
40
|
+
--dv-tab-divider-color: var(--border);
|
|
41
|
+
--dv-separator-border: var(--border);
|
|
42
|
+
|
|
43
|
+
/* --- Tab sizing --- */
|
|
44
|
+
--dv-tab-font-size: var(--text-sm);
|
|
45
|
+
--dv-tab-margin: 0;
|
|
46
|
+
--dv-border-radius: 0px;
|
|
47
|
+
|
|
48
|
+
/* --- Sash (resize handle between panels) --- */
|
|
49
|
+
--dv-sash-color: transparent;
|
|
50
|
+
--dv-active-sash-color: var(--border);
|
|
51
|
+
--dv-active-sash-transition-duration: var(--transition-fast);
|
|
52
|
+
--dv-active-sash-transition-delay: 0.3s;
|
|
53
|
+
|
|
54
|
+
/* --- Drag-and-drop overlay --- */
|
|
55
|
+
--dv-drag-over-background-color: rgba(74, 158, 255, 0.12);
|
|
56
|
+
--dv-drag-over-border-color: var(--accent);
|
|
57
|
+
|
|
58
|
+
/* --- Floating panels --- */
|
|
59
|
+
--dv-floating-box-shadow: var(--shadow-md);
|
|
60
|
+
--dv-overlay-z-index: 999;
|
|
61
|
+
|
|
62
|
+
/* --- Icon hover (close button, overflow chevron, etc.) --- */
|
|
63
|
+
--dv-icon-hover-background-color: rgba(255, 255, 255, 0.08);
|
|
64
|
+
|
|
65
|
+
/* --- Scrollbar inside tab strip --- */
|
|
66
|
+
--dv-tabs-container-scrollbar-color: var(--border);
|
|
67
|
+
--dv-scrollbar-background-color: rgba(255, 255, 255, 0.12);
|
|
68
|
+
|
|
69
|
+
/* --- Paneview (accordion-style panels) --- */
|
|
70
|
+
--dv-paneview-active-outline-color: var(--accent);
|
|
71
|
+
--dv-paneview-header-border-color: var(--border);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Light theme overrides for white-overlay hover states */
|
|
75
|
+
[data-theme="light"] .dockview-theme-pixelweaver {
|
|
76
|
+
--dv-icon-hover-background-color: rgba(0, 0, 0, 0.08);
|
|
77
|
+
--dv-scrollbar-background-color: rgba(0, 0, 0, 0.12);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* ------------------------------------------------------------------ */
|
|
81
|
+
/* Structural overrides that cannot be done via CSS variables alone */
|
|
82
|
+
/* ------------------------------------------------------------------ */
|
|
83
|
+
|
|
84
|
+
/* Accent underline on the active tab in the focused group */
|
|
85
|
+
.dockview-theme-pixelweaver .dv-groupview.dv-active-group
|
|
86
|
+
> .dv-tabs-and-actions-container
|
|
87
|
+
.dv-tabs-container
|
|
88
|
+
> .dv-tab.dv-active-tab {
|
|
89
|
+
position: relative;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.dockview-theme-pixelweaver .dv-groupview.dv-active-group
|
|
93
|
+
> .dv-tabs-and-actions-container
|
|
94
|
+
.dv-tabs-container
|
|
95
|
+
> .dv-tab.dv-active-tab::after {
|
|
96
|
+
content: '';
|
|
97
|
+
position: absolute;
|
|
98
|
+
left: 0;
|
|
99
|
+
bottom: 0;
|
|
100
|
+
width: 100%;
|
|
101
|
+
height: 2px;
|
|
102
|
+
background-color: var(--accent);
|
|
103
|
+
z-index: 5;
|
|
104
|
+
pointer-events: none;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* Subtler underline on active tab in an unfocused group */
|
|
108
|
+
.dockview-theme-pixelweaver .dv-groupview.dv-inactive-group
|
|
109
|
+
> .dv-tabs-and-actions-container
|
|
110
|
+
.dv-tabs-container
|
|
111
|
+
> .dv-tab.dv-active-tab {
|
|
112
|
+
position: relative;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.dockview-theme-pixelweaver .dv-groupview.dv-inactive-group
|
|
116
|
+
> .dv-tabs-and-actions-container
|
|
117
|
+
.dv-tabs-container
|
|
118
|
+
> .dv-tab.dv-active-tab::after {
|
|
119
|
+
content: '';
|
|
120
|
+
position: absolute;
|
|
121
|
+
left: 0;
|
|
122
|
+
bottom: 0;
|
|
123
|
+
width: 100%;
|
|
124
|
+
height: 2px;
|
|
125
|
+
background-color: var(--border);
|
|
126
|
+
z-index: 5;
|
|
127
|
+
pointer-events: none;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/* Hover effect on inactive tabs */
|
|
131
|
+
.dockview-theme-pixelweaver .dv-tab.dv-inactive-tab:hover {
|
|
132
|
+
background-color: var(--bg-secondary) !important;
|
|
133
|
+
color: var(--text-primary) !important;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* Inherit UI font for everything inside the dock */
|
|
137
|
+
.dockview-theme-pixelweaver .dv-tabs-and-actions-container,
|
|
138
|
+
.dockview-theme-pixelweaver .dv-tab,
|
|
139
|
+
.dockview-theme-pixelweaver .dv-default-tab {
|
|
140
|
+
font-family: var(--font-ui);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/* Compact tab padding */
|
|
144
|
+
.dockview-theme-pixelweaver .dv-tab {
|
|
145
|
+
padding: 0 var(--space-3);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* Compact close-button icon */
|
|
149
|
+
.dockview-theme-pixelweaver .dv-tab .dv-default-tab .dv-default-tab-action {
|
|
150
|
+
padding: 2px;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.dockview-theme-pixelweaver .dv-tab .dv-svg {
|
|
154
|
+
height: 8px;
|
|
155
|
+
width: 8px;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Bottom border on the tab bar to separate it from panel content */
|
|
159
|
+
.dockview-theme-pixelweaver .dv-tabs-and-actions-container {
|
|
160
|
+
border-bottom: 1px solid var(--border);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/* Floating panels: use panel background and theme border */
|
|
164
|
+
.dockview-theme-pixelweaver .dv-resize-container {
|
|
165
|
+
border: 1px solid var(--border);
|
|
166
|
+
border-radius: var(--radius-sm);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* Drop target anchor styling */
|
|
170
|
+
.dockview-theme-pixelweaver
|
|
171
|
+
.dv-drop-target-container
|
|
172
|
+
.dv-drop-target-anchor.dv-drop-target-anchor-container-changed {
|
|
173
|
+
opacity: 0;
|
|
174
|
+
transition: none;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* Pane header matches toolbar background for visual grouping */
|
|
178
|
+
.dockview-theme-pixelweaver .dv-pane-container .dv-view .dv-default-header {
|
|
179
|
+
background-color: var(--bg-toolbar);
|
|
180
|
+
color: var(--text-primary);
|
|
181
|
+
font-size: var(--text-sm);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* Overflow dropdown styling */
|
|
185
|
+
.dockview-theme-pixelweaver .dv-tabs-overflow-container {
|
|
186
|
+
background-color: var(--bg-panel);
|
|
187
|
+
border-color: var(--border);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.dockview-theme-pixelweaver .dv-tabs-overflow-dropdown-default:hover {
|
|
191
|
+
background-color: var(--bg-secondary);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* "+" button in the right header action area of each tab bar */
|
|
195
|
+
.dockview-theme-pixelweaver .dv-tab-add-btn {
|
|
196
|
+
display: flex;
|
|
197
|
+
align-items: center;
|
|
198
|
+
justify-content: center;
|
|
199
|
+
width: 22px;
|
|
200
|
+
height: 22px;
|
|
201
|
+
margin: 0 4px;
|
|
202
|
+
padding: 0;
|
|
203
|
+
border: none;
|
|
204
|
+
border-radius: var(--radius-sm);
|
|
205
|
+
background: none;
|
|
206
|
+
color: var(--text-muted);
|
|
207
|
+
font-size: 16px;
|
|
208
|
+
font-family: var(--font-ui);
|
|
209
|
+
line-height: 1;
|
|
210
|
+
cursor: pointer;
|
|
211
|
+
transition: color var(--transition-fast), background-color var(--transition-fast);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.dockview-theme-pixelweaver .dv-tab-add-btn:hover {
|
|
215
|
+
color: var(--text-primary);
|
|
216
|
+
background-color: var(--bg-secondary);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/* Collapse the void spacer so the + button sits right after the last tab */
|
|
220
|
+
.dockview-theme-pixelweaver .dv-tabs-and-actions-container .dv-void-container {
|
|
221
|
+
flex-grow: 0 !important;
|
|
222
|
+
flex-basis: 0 !important;
|
|
223
|
+
min-width: 0 !important;
|
|
224
|
+
width: 0 !important;
|
|
225
|
+
overflow: hidden !important;
|
|
226
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PixelWeaver custom dockview theme.
|
|
3
|
+
*
|
|
4
|
+
* Import the CSS side-effect alongside this object:
|
|
5
|
+
* import './dockview-theme.css';
|
|
6
|
+
* import { themePixelWeaver } from './dockview-theme';
|
|
7
|
+
*
|
|
8
|
+
* Then pass it to the DockviewComponent constructor:
|
|
9
|
+
* new DockviewComponent(el, { theme: themePixelWeaver, ... });
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { DockviewTheme } from 'dockview-core';
|
|
13
|
+
|
|
14
|
+
export const themePixelWeaver: DockviewTheme = {
|
|
15
|
+
name: 'pixelweaver',
|
|
16
|
+
className: 'dockview-theme-pixelweaver',
|
|
17
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory for the dockview right-header action component.
|
|
3
|
+
*
|
|
4
|
+
* Creates a small "+" button that appears at the right end of each tab bar.
|
|
5
|
+
* Clicking it opens a context menu (TabAddMenu) with options like
|
|
6
|
+
* "New Project" and "Open File".
|
|
7
|
+
*
|
|
8
|
+
* Implements the IHeaderActionsRenderer interface required by dockview's
|
|
9
|
+
* `createRightHeaderActionComponent` option.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { mount, unmount } from 'svelte';
|
|
13
|
+
import type { IHeaderActionsRenderer, IGroupHeaderProps } from 'dockview-core';
|
|
14
|
+
import type { DockviewGroupPanel } from 'dockview-core';
|
|
15
|
+
import TabAddMenu from './TabAddMenu.svelte';
|
|
16
|
+
|
|
17
|
+
export function createRightHeaderActionComponent(
|
|
18
|
+
_group: DockviewGroupPanel,
|
|
19
|
+
): IHeaderActionsRenderer {
|
|
20
|
+
const el = document.createElement('div');
|
|
21
|
+
el.style.display = 'flex';
|
|
22
|
+
el.style.alignItems = 'center';
|
|
23
|
+
el.style.height = '100%';
|
|
24
|
+
|
|
25
|
+
const btn = document.createElement('button');
|
|
26
|
+
btn.className = 'dv-tab-add-btn';
|
|
27
|
+
btn.textContent = '+';
|
|
28
|
+
btn.title = 'Add...';
|
|
29
|
+
el.appendChild(btn);
|
|
30
|
+
|
|
31
|
+
// The menu Svelte instance, mounted into a portal div when open
|
|
32
|
+
let menuInstance: Record<string, unknown> | null = null;
|
|
33
|
+
let menuHost: HTMLDivElement | null = null;
|
|
34
|
+
|
|
35
|
+
function openMenu() {
|
|
36
|
+
if (menuInstance) return; // already open
|
|
37
|
+
|
|
38
|
+
const rect = btn.getBoundingClientRect();
|
|
39
|
+
menuHost = document.createElement('div');
|
|
40
|
+
document.body.appendChild(menuHost);
|
|
41
|
+
|
|
42
|
+
menuInstance = mount(TabAddMenu, {
|
|
43
|
+
target: menuHost,
|
|
44
|
+
props: {
|
|
45
|
+
x: rect.left,
|
|
46
|
+
y: rect.bottom + 2,
|
|
47
|
+
onClose: closeMenu,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function closeMenu() {
|
|
53
|
+
if (menuInstance && menuHost) {
|
|
54
|
+
void unmount(menuInstance);
|
|
55
|
+
menuHost.remove();
|
|
56
|
+
menuInstance = null;
|
|
57
|
+
menuHost = null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
btn.addEventListener('click', (e) => {
|
|
62
|
+
e.stopPropagation();
|
|
63
|
+
openMenu();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
element: el,
|
|
68
|
+
|
|
69
|
+
init(_params: IGroupHeaderProps) {
|
|
70
|
+
// No additional setup needed; the button is already wired up
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
dispose() {
|
|
74
|
+
closeMenu();
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clipboard State -- in-memory pixel clipboard shared between cut, copy,
|
|
3
|
+
* and paste commands. Stores pixel data as {x,y,r,g,b,a}[] where x/y are
|
|
4
|
+
* absolute canvas coordinates (not relative to the selection bounding box).
|
|
5
|
+
*
|
|
6
|
+
* Not reactive: the UI does not need to react to clipboard changes today.
|
|
7
|
+
* If that changes, upgrade this to a $state rune store.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export type ClipboardPixel = {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
r: number;
|
|
14
|
+
g: number;
|
|
15
|
+
b: number;
|
|
16
|
+
a: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
let clipboardBuffer: ClipboardPixel[] = [];
|
|
20
|
+
|
|
21
|
+
/** Return a reference to the current clipboard contents (do not mutate). */
|
|
22
|
+
export function getClipboard(): readonly ClipboardPixel[] {
|
|
23
|
+
return clipboardBuffer;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Replace the clipboard contents with the given pixels. */
|
|
27
|
+
export function setClipboard(pixels: ClipboardPixel[]): void {
|
|
28
|
+
clipboardBuffer = pixels;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Whether the clipboard currently has any pixels in it. */
|
|
32
|
+
export function hasClipboard(): boolean {
|
|
33
|
+
return clipboardBuffer.length > 0;
|
|
34
|
+
}
|