@renderx-plugins/canvas
v1.0.1
Published
Core visual workspace surface for RenderX. The Canvas plugin supplies the host‑embeddable React page (`CanvasPage`) that: (1) exposes a drop surface for library components/containers, (2) renders a lightweight header with zoom + mode toggles + import/expo
Downloads
45
Readme
@renderx-plugins/canvas
Core visual workspace surface for RenderX. The Canvas plugin supplies the host‑embeddable React page (CanvasPage) that: (1) exposes a drop surface for library components/containers, (2) renders a lightweight header with zoom + mode toggles + import/export affordances, and (3) reserves an isolated DOM mount (#rx-canvas) where Stage‑Crew (the orchestration/runtime layer) paints actual component instances. UI chrome stays intentionally “dumb” – all authoritative state flows through the host conductor + event / interaction routing.
Why It Exists
Design / interaction tooling tends to blend structural UI (panels, headers, grids) with runtime mutation logic. We separate them: this plugin owns only the visual shell & user gestures (drag, drop, zoom, mode switches, export buttons). Mutation, persistence, selection resolution, export pipelines, and performance heuristics live in specialized handler / symphony plugins (e.g. @renderx-plugins/canvas-component). This keeps the Canvas surface stable and cheap to re-render while letting interaction logic evolve independently.
Key Capabilities
| Capability | Summary | Implementation Notes |
| ---------- | ------- | -------------------- |
| Drop Surface | Accepts components & containers via HTML5 drag/drop | Normalizes drop coordinates; forwards to library drop interactions (topic: library.*.drop.requested). |
| Mode Switching | Select / Move / Draw placeholders | Local React state only; hooks for future behavior wiring. |
| Zoom Controls | +/- controls 25–200% | Pure UI state today; future: broadcast zoom to stage crew. |
| Export Triggers | Generic export + GIF / MP4 (when element selected) | Resolves interactions: canvas.component.export* sequences. |
| Import Trigger | Launches import flow | Publishes topic canvas.component.import.requested. |
| Selection Awareness | Enables export buttons only when something is selected | Subscribes to canvas.component.selection.changed via EventRouter. |
| Grid & Visual Hints | Background micro‑grid + drop indicator | Pure CSS; no layout coupling. |
| StageCrew Mount | Dedicated <div id="rx-canvas"/> | Runtime injects managed DOM nodes; Canvas never queries them. |
Architectural Principles
- Event / Interaction Boundary: Canvas never mutates domain state directly; it publishes topics or plays resolved interaction sequences.
- Stateless Shell: Persistent model state (components, selection) is external; Canvas reacts to events (e.g. selection changed).
- Performance Hygiene: Drag/drop delegates high‑frequency work to handler plugins that implement coalescing; Canvas only initiates.
- Testability: Core user gestures are funneled into small functions (e.g.
onDropForTest) enabling deterministic unit tests. - Forward Compatibility: A minimal async
register()hook allows future initialization (feature flags, preloading) without a breaking API change.
High-Level Flow (Drop → Render)
- User drags a library item over
CanvasPage. onDropForTestextracts the serialized component + computes normalized coordinates (container‑aware).- Publishes
library.component.drop.requested(or container variant) with callbacks for drag lifecycle + selection. - Library / component orchestration sequence materializes the component and instructs Stage‑Crew to render into
#rx-canvas. - Separate selection / drag handlers emit events the Canvas header listens to for enabling exports.
Public Surface
import { CanvasPage, register } from '@renderx-plugins/canvas';CanvasPage – React component (no props required) that assumes a ConductorProvider (or equivalent) higher in the tree supplying useConductor().
register() – async, currently no‑op, reserved for deferred initialization (preloading fonts, feature flag hydration, etc.). Safe to call multiple times.
Integration Example
import React from 'react';
import { CanvasPage, register } from '@renderx-plugins/canvas';
export function AppShell() {
React.useEffect(() => { register(); }, []);
return <CanvasPage />;
}Feature Roadmap (Indicative)
- Live zoom propagation to runtime render layer.
- Keyboard shortcuts for mode switching & zoom.
- Inline marquee selection overlay (delegated to interaction plugin but visually hosted here).
- Configurable grid density + snap toggles.
- Lazy hydration of export buttons based on capability discovery.
Separation From @renderx-plugins/canvas-component
canvas = visual shell & user affordances.
canvas-component = high-frequency interaction handlers (drag, resize, select, export pipelines, performance gating).
This split ensures: smaller bundle for host embedding, clearer performance boundaries, and independent versioning of heavy logic.
Contributing
To contribute, modify UI elements in the src/ui/ directory, run npm run dev to start the development server, and test drag/drop and export features in your local environment. Add or adjust corresponding interaction tests under the root test suites as needed.
Testing Notes
The component favors event publication over internal state, so unit tests assert on emitted topics / interaction invocations rather than DOM mutation. Use onDropForTest to simulate pointer operations without constructing full DragEvent objects.
License
Follows root project license (TBD upon extraction).
Minimal surface, strong boundaries, future‑proof initialization – the Canvas plugin is the stable anchor for richer interaction layers above it.
