HAEditor (D:\AICore\workspace\haeditor) is the standalone NW.js desktop graphical studio for creating, editing, animating, and inspecting .hacanvas hybrid vector + raster documents and reusable Shared Object libraries. It is powered directly by @nexustools/hacanvas (D:\GitHub\hacanvas).
Key features of HAEditor:
- Interactive Hybrid Viewport: Pan, zoom, grid overlay, checkerboard transparency, live selection handles, Bezier node & segment curve deformation handles (
NodeEditTool), In-Place (Double-Click) and Isolated Tab editing of Shared Objects, and live non-destructive dynamic filter preview with automatic bypass while actively editing an object. - 18 Interactive Viewport Tools: Selection (
select_move,node_edit,rect_select,ellipse_select,lasso_select,magic_wand), Raster Painting (brush,pencil,airbrush,eraser,bucket_fill,eyedropper), and Vector Creation (rect,ellipse,polygon,star,line,pen,text). - Dockable Studio Panels & Modals: Layers & Objects tree (with per-layer and per-object
fxdynamic filter badges and eye preview toggles), Categorized GIMP Filters Dock (121+presets + custom JS filter editor + Attach Dynamic vs. Apply Immediately mode), Categorized Keyframe Transitions Dock (14+presets + custom JS transition editor), Shared Object Library Dock, Undo History Dock, Document Metadata (EXIF/XMP) & Embedded Fonts Dock, and Timeline + Cubic-Bezier Curve Editor. - Integrated AI Studio (
AiAssistantPanel): Connects to LM Studio or OpenAI-compatible multimodal LLMs/VLMs with real-time streaming tool calls across all 33 AI tools from@nexustools/hacanvas.
HAEditor, @nexustools/hacanvas, and AICore are developed together simultaneously using directory symlinks (Windows junctions):
-
D:\AICore\workspace\haeditor\node_modules\@nexustools\hacanvas$\longrightarrow$ D:\GitHub\hacanvas -
D:\AICore\node_modules\@nexustools\hacanvas$\longrightarrow$ D:\GitHub\hacanvas
- Direct 1:1 Updates via Symlink: Because
node_modules/@nexustools/hacanvasis a directory junction pointing directly toD:\GitHub\hacanvas, any changes built inD:\GitHub\hacanvas(npm run build) are immediately live inHAEditorandAICorewith zero manual copying ornpm updatesteps. - Preserve the Symlink: Never replace
node_modules/@nexustools/hacanvaswith a static folder copy. Ifnpm installever removes the junction, recreate it immediately:New-Item -ItemType Junction -Path "D:\AICore\workspace\haeditor\node_modules\@nexustools\hacanvas" -Target "D:\GitHub\hacanvas"
- Build & Test Verification:
- When modifying
@nexustools/hacanvas(D:\GitHub\hacanvas), runnpm run buildinD:\GitHub\hacanvasfirst. - Then run
npm run buildandnpm testinD:\AICore\workspace\haeditor, and inspectD:\AICore\workspace\haeditor\testrunner\test-results\desktop-tests.logto verify all desktop integration tests pass (Failed: 0).
- When modifying
To keep the HAEditor codebase clean, navigable, and maintainable, every .ts file in D:\AICore\workspace\haeditor\src\ MUST adhere to the 1-Class-Per-File rule and modular directory structure:
- Maximum 1 Exported Class Per
.tsFile:- Every
.tsfile insrc/MUST export at most 1 class. - Never combine multiple tools, UI panels, modals, or state classes into a single
.tsfile.
- Every
- Dedicated Folders by Responsibility:
- Abstract Viewport Tool Base Classes (
src/tools/base/):src/tools/base/abstract-editor-tool-base.ts—AbstractEditorToolsrc/tools/base/abstract-raster-stroke-tool.ts—AbstractRasterStrokeToolsrc/tools/base/abstract-vector-shape-tool.ts—AbstractVectorShapeToolsrc/tools/base/abstract-selection-drag-tool.ts—AbstractSelectionDragToolsrc/tools/base/abstract-color-point-tool.ts—AbstractColorPointTool
- Concrete Viewport Tools (
src/tools/):- Each interactive tool MUST be in its own file
src/tools/<tool-name>-tool.ts(e.g.select-move-tool.ts,node-edit-tool.ts,rect-select-tool.ts,ellipse-select-tool.ts,lasso-select-tool.ts,magic-wand-tool.ts,brush-tool.ts,pencil-tool.ts,airbrush-tool.ts,eraser-tool.ts,bucket-fill-tool.ts,eyedropper-tool.ts,rect-shape-tool.ts,ellipse-shape-tool.ts,polygon-shape-tool.ts,star-shape-tool.ts,line-shape-tool.ts,pen-path-tool.ts,text-tool.ts) and registered insrc/tools/editor-tool-registry.ts.
- Each interactive tool MUST be in its own file
- Observable Session State (
src/state/):src/state/abstract-observable-state.ts—AbstractObservableStatesrc/state/editor-session-state.ts—EditorSessionStatesrc/state/editor-state.ts— Barrel re-export for state types and classes
- Top-Level UI Chrome & Viewport (
src/ui/):src/ui/top-menu-bar.ts—TopMenuBarsrc/ui/left-toolbox.ts—LeftToolboxsrc/ui/canvas-viewport.ts—CanvasViewportsrc/ui/right-inspector-dock.ts—RightInspectorDocksrc/ui/timeline-curve-panel.ts—TimelineAndCurvePanelsrc/ui/ai-assistant-panel.ts—AiAssistantPanel
- Specialized Dock Panels (
src/ui/panels/):- Each dock tab/panel MUST live in its own 1-class file under
src/ui/panels/(abstract-categorized-tree-panel.ts,gimp-filters-dock-panel.ts,raster-transitions-dock-panel.ts,history-dock-panel.ts,metadata-and-fonts-dock-panel.ts).
- Each dock tab/panel MUST live in its own 1-class file under
- Modal Dialogs (
src/ui/modals/):- Each modal dialog MUST live in its own 1-class file under
src/ui/modals/(ico-export-modal.ts,pdf-import-modal.ts,pdf-export-modal.ts).
- Each modal dialog MUST live in its own 1-class file under
- AI Tool Re-Exports (
src/ai/):HAEditorconsumes all AI tools directly from@nexustools/hacanvasviasrc/ai/haeditor-ai-tools.tsandsrc/ai/lmstudio-ai-service.ts. When adding or updating AI tools, implement the tool in its own file insideD:\GitHub\hacanvas\src\ai\tools\.
- Abstract Viewport Tool Base Classes (
- UI + AI Tool Parity: Every capability exposed in the
HAEditorUI MUST also be exposed to the AI agent via@nexustools/hacanvasAI tools so the AI can inspect and perform every action a human user can perform. - Automated NW.js Test Suite: Always add or update tests in
src/tests/HaEditorSuites.tsand verify vianpm test. - Documentation Maintenance: Keep
README.md,docs/USER_GUIDE.md,docs/AI_STUDIO_AND_TOOLS.md, anddocs/ARCHITECTURE_AND_TESTING.mdupdated whenever features or tools change. - No Assumptions: Always ask the user for feedback if there is any ambiguity.