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,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for plugin-registered extensions: tools, panels, exporters,
|
|
3
|
+
* importers, and shortcuts. Separated from plugin-api.ts to avoid circular
|
|
4
|
+
* imports -- registries.ts needs these types but should not depend on the API.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Command, CommandDefinition } from './commands.js';
|
|
8
|
+
import type { CommandType, ParamsOf } from './command-params.js';
|
|
9
|
+
import type { AppNotification } from './notification-state.svelte.js';
|
|
10
|
+
import type { PixelBuffer } from '../canvas/pixel-buffer.js';
|
|
11
|
+
import type { LayerTreeState } from '../layers/layer-types.js';
|
|
12
|
+
import type { Frame, FramesSerialized } from '../animation/frame-model.svelte.js';
|
|
13
|
+
import type { Palette } from '../color/palette.js';
|
|
14
|
+
|
|
15
|
+
// --- Plugin API interface ---
|
|
16
|
+
// Defined here (not in plugin-api.ts) so that ToolContext can reference it
|
|
17
|
+
// without creating a circular import: plugin-api.ts imports from this file.
|
|
18
|
+
|
|
19
|
+
export interface PluginAPI {
|
|
20
|
+
addCommand<T extends CommandType>(name: T, definition: CommandDefinition<ParamsOf<T>>): void;
|
|
21
|
+
addCommand<P extends object = Record<string, unknown>>(name: string, definition: CommandDefinition<P>): void;
|
|
22
|
+
addTool(name: string, definition: ToolDefinition): void;
|
|
23
|
+
addPanel(name: string, definition: PanelConfig): void;
|
|
24
|
+
addExporter(name: string, definition: ExporterDefinition): void;
|
|
25
|
+
addImporter(name: string, definition: ImporterDefinition): void;
|
|
26
|
+
addShortcut(name: string, definition: ShortcutDefinition): void;
|
|
27
|
+
addMenuItem(name: string, contribution: MenuContribution): void;
|
|
28
|
+
addToolbarItem(name: string, contribution: ToolbarContribution): void;
|
|
29
|
+
|
|
30
|
+
/** Push a notification into the banner system */
|
|
31
|
+
notify(notification: AppNotification): void;
|
|
32
|
+
/** Dismiss a notification by id */
|
|
33
|
+
dismissNotification(id: string): void;
|
|
34
|
+
|
|
35
|
+
/** Dispatch a command (id and timestamp are auto-filled) */
|
|
36
|
+
dispatch<T extends CommandType>(command: Omit<Command, 'id' | 'timestamp'> & { type: T; params: ParamsOf<T> }): void;
|
|
37
|
+
dispatch(command: Omit<Command, 'id' | 'timestamp'>): void;
|
|
38
|
+
|
|
39
|
+
/** Listen to all executed commands */
|
|
40
|
+
onCommand(callback: (command: Command) => void): () => void;
|
|
41
|
+
|
|
42
|
+
// Getters -- return placeholders until real systems are connected
|
|
43
|
+
getCanvas(): unknown;
|
|
44
|
+
getProject(): unknown;
|
|
45
|
+
getActiveFrame(): unknown;
|
|
46
|
+
getActiveLayers(): unknown;
|
|
47
|
+
/**
|
|
48
|
+
* Read-only view of the current pixel selection. The returned object is
|
|
49
|
+
* stable (safe to capture once at register time); its methods read live
|
|
50
|
+
* state on each call.
|
|
51
|
+
*/
|
|
52
|
+
getSelection(): {
|
|
53
|
+
hasSelection(): boolean;
|
|
54
|
+
getSelectedPixels(): ReadonlySet<string>;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// --- Mutators (used by importers and project-loading plugins) ---
|
|
58
|
+
|
|
59
|
+
/** Set the canvas pixel dimensions. Values are clamped to the [MIN_CANVAS_SIZE, MAX_CANVAS_SIZE] range. */
|
|
60
|
+
setCanvasSize(width: number, height: number): void;
|
|
61
|
+
|
|
62
|
+
/** Add a new pixel layer to the tree. Returns the new layer's id. */
|
|
63
|
+
addLayer(name: string, options?: { parentId?: string; index?: number; id?: string }): string;
|
|
64
|
+
|
|
65
|
+
/** Add a new group layer to the tree. Returns the new group's id. */
|
|
66
|
+
addGroup(name: string, options?: { parentId?: string; index?: number; id?: string }): string;
|
|
67
|
+
|
|
68
|
+
/** Set a layer's visibility flag. */
|
|
69
|
+
setLayerVisibility(id: string, visible: boolean): void;
|
|
70
|
+
|
|
71
|
+
/** Set a layer's opacity (0-100). */
|
|
72
|
+
setLayerOpacity(id: string, opacity: number): void;
|
|
73
|
+
|
|
74
|
+
/** Replace the entire layer tree with the given serialized state. */
|
|
75
|
+
deserializeLayers(state: LayerTreeState): void;
|
|
76
|
+
|
|
77
|
+
/** Append a new frame. Returns the new frame's index. */
|
|
78
|
+
addFrame(options?: { afterIndex?: number; duplicate?: boolean }): number;
|
|
79
|
+
|
|
80
|
+
/** Read-only access to the current frame list. */
|
|
81
|
+
getFrames(): Frame[];
|
|
82
|
+
|
|
83
|
+
/** Set a frame's per-frame duration override (or null to use global FPS). */
|
|
84
|
+
setFrameDuration(index: number, durationMs: number | null): void;
|
|
85
|
+
|
|
86
|
+
/** Make `index` the current frame. */
|
|
87
|
+
setCurrentFrame(index: number): void;
|
|
88
|
+
|
|
89
|
+
/** Set the global animation FPS (1..120). */
|
|
90
|
+
setGlobalFps(fps: number): void;
|
|
91
|
+
|
|
92
|
+
/** Replace all animation state with the given serialized data. */
|
|
93
|
+
deserializeFrames(data: FramesSerialized): void;
|
|
94
|
+
|
|
95
|
+
/** Factory for a blank RGBA pixel buffer. */
|
|
96
|
+
createPixelBuffer(width: number, height: number): PixelBuffer;
|
|
97
|
+
|
|
98
|
+
/** Write pixel data for a specific layer in a specific frame. */
|
|
99
|
+
setFramePixelData(frameIndex: number, layerId: string, buffer: PixelBuffer): void;
|
|
100
|
+
|
|
101
|
+
/** Set the project palette (or clear it by passing null). */
|
|
102
|
+
setProjectPalette(palette: Palette | null): void;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// --- Tool ---
|
|
106
|
+
|
|
107
|
+
export interface ToolContext {
|
|
108
|
+
canvasX: number; // pixel coordinate on the canvas
|
|
109
|
+
canvasY: number;
|
|
110
|
+
pressure: number; // 0-1, from Pointer Events API
|
|
111
|
+
color: string; // current foreground color
|
|
112
|
+
api: PluginAPI;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** A declarative toggle option rendered as a single sub-button in the toolbar. */
|
|
116
|
+
export interface ToolOptionToggle {
|
|
117
|
+
/** Unique id within the tool, e.g. 'filled' */
|
|
118
|
+
id: string;
|
|
119
|
+
/** Human-readable label shown in tooltip */
|
|
120
|
+
label: string;
|
|
121
|
+
/** Icon shown on the sub-button (Svelte component or text) */
|
|
122
|
+
icon?: string | import('svelte').Component;
|
|
123
|
+
/** Option type */
|
|
124
|
+
type: 'toggle';
|
|
125
|
+
/** Default value when the tool is first activated */
|
|
126
|
+
defaultValue: boolean;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** A declarative select option rendered as a row of choice buttons in the toolbar. */
|
|
130
|
+
export interface ToolOptionSelect {
|
|
131
|
+
/** Unique id within the tool, e.g. 'size' */
|
|
132
|
+
id: string;
|
|
133
|
+
/** Human-readable label shown in tooltip */
|
|
134
|
+
label: string;
|
|
135
|
+
/** Option type */
|
|
136
|
+
type: 'select';
|
|
137
|
+
/** Available choices the user can pick from */
|
|
138
|
+
choices: { value: number; label: string }[];
|
|
139
|
+
/** Default value when the tool is first activated */
|
|
140
|
+
defaultValue: number;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** A declarative option that a tool exposes (rendered as sub-buttons in the toolbar). */
|
|
144
|
+
export type ToolOption = ToolOptionToggle | ToolOptionSelect;
|
|
145
|
+
|
|
146
|
+
export interface ToolDefinition {
|
|
147
|
+
icon: string | import('svelte').Component; // text label or Svelte icon component
|
|
148
|
+
cursor: string; // CSS cursor value, e.g. "crosshair"
|
|
149
|
+
onPointerDown?: (e: PointerEvent, ctx: ToolContext) => void;
|
|
150
|
+
onPointerMove?: (e: PointerEvent, ctx: ToolContext) => void;
|
|
151
|
+
onPointerUp?: (e: PointerEvent, ctx: ToolContext) => void;
|
|
152
|
+
onActivate?: () => void;
|
|
153
|
+
onDeactivate?: () => void;
|
|
154
|
+
/** Declarative options rendered as sub-buttons in the toolbar */
|
|
155
|
+
options?: ToolOption[];
|
|
156
|
+
/** Svelte component for tool-specific options (placeholder type for now) */
|
|
157
|
+
optionsPanel?: unknown;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// --- Panel ---
|
|
161
|
+
|
|
162
|
+
export interface PanelConfig {
|
|
163
|
+
/** Display title shown in the panel header / dock tab */
|
|
164
|
+
title: string;
|
|
165
|
+
/** Svelte component to render inside the panel (props passed via `props` field) */
|
|
166
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- props are passed dynamically at mount time
|
|
167
|
+
component: import('svelte').Component<any>;
|
|
168
|
+
/** Props to pass to the component */
|
|
169
|
+
props?: Record<string, unknown>;
|
|
170
|
+
/** Default dock position */
|
|
171
|
+
position?: 'left' | 'right' | 'bottom' | 'top' | 'center';
|
|
172
|
+
/** Minimum width in px (for side panels) */
|
|
173
|
+
minWidth?: number;
|
|
174
|
+
/** Minimum height in px (for bottom panels) */
|
|
175
|
+
minHeight?: number;
|
|
176
|
+
/** Maximum width in px (for side panels) */
|
|
177
|
+
maxWidth?: number;
|
|
178
|
+
/** Maximum height in px (for bottom panels) */
|
|
179
|
+
maxHeight?: number;
|
|
180
|
+
/** Whether this panel can be closed. Default: true */
|
|
181
|
+
closeable?: boolean;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// --- Exporter ---
|
|
185
|
+
|
|
186
|
+
export interface ExporterDefinition {
|
|
187
|
+
/** Human-readable label, e.g. "PNG Image" */
|
|
188
|
+
label: string;
|
|
189
|
+
/** File extension, e.g. "png" */
|
|
190
|
+
extension: string;
|
|
191
|
+
/** MIME type, e.g. "image/png" */
|
|
192
|
+
mimeType: string;
|
|
193
|
+
/** Performs the export and returns the result as a Blob or Uint8Array */
|
|
194
|
+
export: (context: ExportContext) => Promise<Blob | Uint8Array>;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export interface ExportContext {
|
|
198
|
+
/** Placeholder -- will contain canvas data, frame selection, etc. */
|
|
199
|
+
[key: string]: unknown;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// --- Importer ---
|
|
203
|
+
|
|
204
|
+
export interface ImporterDefinition {
|
|
205
|
+
/** Human-readable label, e.g. "PNG Image" */
|
|
206
|
+
label: string;
|
|
207
|
+
/** File extensions this importer handles, e.g. ["png", "jpg"] */
|
|
208
|
+
extensions: string[];
|
|
209
|
+
/** Performs the import from a File or ArrayBuffer */
|
|
210
|
+
import: (data: File | ArrayBuffer, context: ImportContext) => Promise<void>;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export interface ImportContext {
|
|
214
|
+
/** Placeholder -- will contain project handle, etc. */
|
|
215
|
+
[key: string]: unknown;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// --- Shortcut ---
|
|
219
|
+
|
|
220
|
+
export interface ShortcutDefinition {
|
|
221
|
+
/** Key combination, e.g. "Ctrl+Z", "B", "Shift+X" */
|
|
222
|
+
key: string;
|
|
223
|
+
/** Human-readable description for the shortcut list */
|
|
224
|
+
description: string;
|
|
225
|
+
/** Callback when the shortcut is triggered */
|
|
226
|
+
action: () => void;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// --- Menu contribution ---
|
|
230
|
+
|
|
231
|
+
export interface MenuContribution {
|
|
232
|
+
/** ID of the command to execute (must be registered in commandRegistry) */
|
|
233
|
+
commandId: string;
|
|
234
|
+
/**
|
|
235
|
+
* Slash-separated menu path. First segment = top-level menu, rest = submenus.
|
|
236
|
+
* Examples: "effects", "file/import", "layer", "context/canvas"
|
|
237
|
+
*/
|
|
238
|
+
menuPath: string;
|
|
239
|
+
/** Grouping within the menu. Items in the same group are together, separated by dividers. */
|
|
240
|
+
group: string;
|
|
241
|
+
/** Sort order within the group (lower = earlier). Default: 100. */
|
|
242
|
+
order: number;
|
|
243
|
+
/** Human-readable label override. If omitted, uses CommandDefinition.label or the commandId. */
|
|
244
|
+
label?: string;
|
|
245
|
+
/** Conditional visibility. Return false to hide the item. */
|
|
246
|
+
when?: () => boolean;
|
|
247
|
+
/** Conditional enabled state. Return false to disable/gray out. */
|
|
248
|
+
enabled?: () => boolean;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// --- Toolbar contribution ---
|
|
252
|
+
|
|
253
|
+
/** Discriminator for toolbar item kinds */
|
|
254
|
+
export type ToolbarItemKind = 'tool' | 'command' | 'separator' | 'widget';
|
|
255
|
+
|
|
256
|
+
/** A plugin-declared item for a toolbar */
|
|
257
|
+
export interface ToolbarContribution {
|
|
258
|
+
/** Which toolbar this item belongs to (e.g. 'drawing-tools', 'view-controls') */
|
|
259
|
+
toolbarId: string;
|
|
260
|
+
/** What kind of item this is */
|
|
261
|
+
kind: ToolbarItemKind;
|
|
262
|
+
/** Tool name or command name (not needed for separator/widget) */
|
|
263
|
+
targetId?: string;
|
|
264
|
+
/** Grouping bucket -- items in the same group are together, separators between groups */
|
|
265
|
+
group: string;
|
|
266
|
+
/** Sort position within the group (lower = earlier) */
|
|
267
|
+
order: number;
|
|
268
|
+
/** Override label */
|
|
269
|
+
label?: string;
|
|
270
|
+
/** Override icon (falls back to command/tool icon) */
|
|
271
|
+
icon?: string | import('svelte').Component;
|
|
272
|
+
/** Svelte component for kind: 'widget' */
|
|
273
|
+
widget?: import('svelte').Component;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/** Per-toolbar configuration */
|
|
277
|
+
export interface ToolbarConfig {
|
|
278
|
+
/** Unique toolbar ID */
|
|
279
|
+
id: string;
|
|
280
|
+
/** Display title for the dock tab */
|
|
281
|
+
title: string;
|
|
282
|
+
/** Icon dimensions in px */
|
|
283
|
+
iconSize: number;
|
|
284
|
+
/** Whether user can close this toolbar. Default: true */
|
|
285
|
+
closeable?: boolean;
|
|
286
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Central registries for all plugin-registered extensions.
|
|
3
|
+
*
|
|
4
|
+
* Each registry is a reactive Map (using Svelte 5 $state) so that UI
|
|
5
|
+
* components can reactively list registered tools, panels, etc.
|
|
6
|
+
*
|
|
7
|
+
* Module-level singletons -- one set of registries per app instance.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { SvelteMap } from 'svelte/reactivity';
|
|
11
|
+
import type { CommandDefinition } from './commands.js';
|
|
12
|
+
import type {
|
|
13
|
+
ToolDefinition,
|
|
14
|
+
PanelConfig,
|
|
15
|
+
ExporterDefinition,
|
|
16
|
+
ImporterDefinition,
|
|
17
|
+
ShortcutDefinition,
|
|
18
|
+
MenuContribution,
|
|
19
|
+
ToolbarContribution,
|
|
20
|
+
} from './plugin-types.js';
|
|
21
|
+
|
|
22
|
+
// --- Reactive registry factory ---
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Creates a reactive registry backed by SvelteMap.
|
|
26
|
+
* SvelteMap is inherently reactive in Svelte 5 -- mutations automatically
|
|
27
|
+
* trigger re-renders in any component that reads from the map.
|
|
28
|
+
*/
|
|
29
|
+
function createRegistry<T>(): ReactiveRegistry<T> {
|
|
30
|
+
const entries = new SvelteMap<string, T>();
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
get(name: string): T | undefined {
|
|
34
|
+
return entries.get(name);
|
|
35
|
+
},
|
|
36
|
+
set(name: string, value: T): void {
|
|
37
|
+
entries.set(name, value);
|
|
38
|
+
},
|
|
39
|
+
has(name: string): boolean {
|
|
40
|
+
return entries.has(name);
|
|
41
|
+
},
|
|
42
|
+
delete(name: string): boolean {
|
|
43
|
+
return entries.delete(name);
|
|
44
|
+
},
|
|
45
|
+
/** Returns the underlying map for read-only iteration */
|
|
46
|
+
getAll(): ReadonlyMap<string, T> {
|
|
47
|
+
return entries;
|
|
48
|
+
},
|
|
49
|
+
get size(): number {
|
|
50
|
+
return entries.size;
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface ReactiveRegistry<T> {
|
|
56
|
+
get(name: string): T | undefined;
|
|
57
|
+
set(name: string, value: T): void;
|
|
58
|
+
has(name: string): boolean;
|
|
59
|
+
delete(name: string): boolean;
|
|
60
|
+
getAll(): ReadonlyMap<string, T>;
|
|
61
|
+
readonly size: number;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// --- Singleton registries ---
|
|
65
|
+
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- type-erasure boundary: registry stores heterogeneous CommandDefinition<P> values
|
|
67
|
+
export const commandRegistry = createRegistry<CommandDefinition<any>>();
|
|
68
|
+
export const toolRegistry = createRegistry<ToolDefinition>();
|
|
69
|
+
export const panelRegistry = createRegistry<PanelConfig>();
|
|
70
|
+
export const exporterRegistry = createRegistry<ExporterDefinition>();
|
|
71
|
+
export const importerRegistry = createRegistry<ImporterDefinition>();
|
|
72
|
+
export const shortcutRegistry = createRegistry<ShortcutDefinition>();
|
|
73
|
+
export const menuRegistry = createRegistry<MenuContribution>();
|
|
74
|
+
export const toolbarRegistry = createRegistry<ToolbarContribution>();
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reactive state for tool option values.
|
|
3
|
+
*
|
|
4
|
+
* Tracks per-tool option values (e.g. filled toggle for shape tools).
|
|
5
|
+
* Values persist across tool switches within a session -- switching away
|
|
6
|
+
* from a tool and back preserves the user's choices.
|
|
7
|
+
*
|
|
8
|
+
* Module-level singleton using Svelte 5 $state via SvelteMap.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { SvelteMap } from 'svelte/reactivity';
|
|
12
|
+
import { toolRegistry } from './registries.svelte.js';
|
|
13
|
+
|
|
14
|
+
/** Supported option value types: boolean for toggles, number for selects. */
|
|
15
|
+
export type ToolOptionValue = boolean | number;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Nested map: toolName -> optionId -> current value.
|
|
19
|
+
* Outer SvelteMap is reactive so toolbar UI updates when tools change.
|
|
20
|
+
* Inner SvelteMap is reactive so sub-buttons update when toggled.
|
|
21
|
+
*/
|
|
22
|
+
const optionValues = new SvelteMap<string, SvelteMap<string, ToolOptionValue>>();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Ensure a tool's options are initialized with defaults (idempotent).
|
|
26
|
+
* Called when a tool becomes active or when reading its options.
|
|
27
|
+
*/
|
|
28
|
+
function ensureDefaults(toolName: string): SvelteMap<string, ToolOptionValue> {
|
|
29
|
+
let toolOpts = optionValues.get(toolName);
|
|
30
|
+
if (toolOpts) return toolOpts;
|
|
31
|
+
|
|
32
|
+
toolOpts = new SvelteMap<string, ToolOptionValue>();
|
|
33
|
+
const def = toolRegistry.get(toolName);
|
|
34
|
+
if (def?.options) {
|
|
35
|
+
for (const opt of def.options) {
|
|
36
|
+
toolOpts.set(opt.id, opt.defaultValue);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
optionValues.set(toolName, toolOpts);
|
|
40
|
+
return toolOpts;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Get the current value of a tool option. Returns the default if not yet set. */
|
|
44
|
+
export function getToolOptionValue(toolName: string, optionId: string): ToolOptionValue {
|
|
45
|
+
const toolOpts = ensureDefaults(toolName);
|
|
46
|
+
return toolOpts.get(optionId) ?? false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Set the value of a tool option (e.g. when the user clicks a toggle or picks a select choice). */
|
|
50
|
+
export function setToolOptionValue(toolName: string, optionId: string, value: ToolOptionValue): void {
|
|
51
|
+
const toolOpts = ensureDefaults(toolName);
|
|
52
|
+
toolOpts.set(optionId, value);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Toggle a boolean tool option and return the new value. */
|
|
56
|
+
export function toggleToolOption(toolName: string, optionId: string): boolean {
|
|
57
|
+
const current = getToolOptionValue(toolName, optionId);
|
|
58
|
+
const next = !current;
|
|
59
|
+
setToolOptionValue(toolName, optionId, next);
|
|
60
|
+
return next;
|
|
61
|
+
}
|