@thesteau/artleta-canvas
v1.4.1
Published
An event-aware React canvas for editing, previewing, and playing back visual strategies.
Readme
Artleta Canvas is a reusable, event-aware visual canvas package for React. It provides an editor, a read-only preview, active-state playback, browser PNG export, and YAML/CSV interchange.
Install
Install Artleta Canvas together with its React peer dependencies:
npm install @thesteau/artleta-canvas react react-domImport the package and its standalone theme:
import {
ArtletaCanvasEditor,
ArtletaCanvasPlayback,
ArtletaCanvasPreview,
} from "@thesteau/artleta-canvas";
import "@thesteau/artleta-canvas/styles.css";The stylesheet uses documented --artleta-* custom properties on each
.artleta component root. Override those variables from the host application
to theme the canvas without depending on the package's internal class names.
The PNG export paints its own surfaces on a 2D canvas, where custom properties
cannot reach. The editor resolves the variables from its own .artleta root,
so multiple differently themed instances export correctly. When calling
exportCanvasPng directly, pass a CanvasTheme as the fourth argument or call
readCanvasTheme with the root of the surface being exported:
import { exportCanvasPng, readCanvasTheme } from "@thesteau/artleta-canvas";
await exportCanvasPng(canvas, nodeColor, resolveImage, {
...readCanvasTheme(document.querySelector(".artleta")),
canvas: "#ffffff",
});Boundary
The package owns:
- the persisted canvas document types;
- editor, read-only preview, and active-state playback surfaces;
- geometry, layout, text wrapping, colors, and PNG/YAML/CSV export;
- host ports for entity search, image resolution, and entity inspection.
The host application owns:
- persistence, and every request to a backend;
- whatever domain grouping the canvas colors nodes by;
- the state that decides which nodes are active during playback;
- the surrounding panels, entity viewer, and application-shell behavior.
This dependency direction is deliberate:
Artleta Canvas
↑
host adapters
↑
host applicationArtleta Canvas imports nothing from a host application: its only runtime
dependencies are React and yaml. Host capabilities enter through
ArtletaPorts.
The entity model
A canvas holds three kinds of node: entity, group, and text. An entity
node carries an opaque string or numeric entity_id the host resolves to
artwork, and an optional badge string the surfaces render verbatim.
Artleta Canvas never interprets a badge, so any classification the host cares
about — a type, a status, a rarity — reaches the canvas without that domain's
taxonomy entering the document.
{ id: "n1", kind: "entity", name: "Aluber", entity_id: 62962630, badge: "Extra", x: 24, y: 36 }A link runs between two of the eight points on each box — the four sides and the
four corners — rather than between the two centres, so the line and its arrowhead
stay in the open instead of disappearing under a node. An end with no
source_anchor or target_anchor faces whichever point looks at the other node and
keeps facing it as either node moves. Dragging that end onto a point in the
editor ties it there, which is how two links that would otherwise land on the
same point — a pair pointing opposite ways, say — are told apart:
{ id: "l1", source: "n1", target: "n2", direction: "forward", relation: "leads_to",
label: "leads to", source_anchor: "bottom_right", target_anchor: "left" }Groups may mark themselves primary, or list the groups they overlap. Those
two flags decide which groups count as real categories: an entity in none of
them takes the neutral Ungrouped color rather than an incidental group's. A host
with no such distinction leaves both off and every group counts.
Migrating documents written before 0.2
Up to 0.1.x a node used kind: "card" with card_id, a required card_type of
"monster" | "spell" | "trap" | "unknown", and an extra_deck flag; groups used
engine, overlap_of, and garnet. Run stored documents through the adapter
once on read — it is idempotent, so applying it unconditionally is safe:
import { migrateCanvases, migrateGroups } from "@thesteau/artleta-canvas";
const canvases = migrateCanvases(await loadFromBackend());
const groups = migrateGroups(await loadGroups());extra_deck: true becomes badge: "Extra", since that flag was the only one the
surfaces ever drew on a node. A bare card_type is dropped rather than promoted
to a badge — it never appeared on the node itself, and would read as noise in the
corner. Set badge from the host if you want it back.
The ports were renamed with the model: searchCards → searchEntities,
cardThumbnailUrl → thumbnailUrl, cardImageUrl → imageUrl, and
inspectCard → inspectEntity.
Canvas text interchange
The editor imports YAML and CSV additively into the open canvas. A node may
include both x and y to preserve an exact position; when both are omitted,
the editor chooses the next open position. Links refer to human-readable node
keys and may also target a uniquely named node already on the canvas.
version: 2
canvas: Example combo
nodes:
- key: starter
kind: entity
name: Aluber the Jester of Despia
badge: Starter
- key: result
kind: text
text: Mirrorjade + Branded in Red
x: 1050
y: 300
links:
- from: starter
to: result
label: ends on
from_anchor: right
to_anchor: leftA link may name the point each end is tied to with from_anchor and to_anchor;
omit them to let that end face the other node. CSV uses the same fields with one
canvas, node, or link record per row.
Exports always include coordinates so importing an export recreates its layout.
Browser requirements
The Artleta Canvas React surfaces are client-side components. The editor and
export helpers use browser APIs including window, document, canvas, portals,
clipboard access, file downloads, and pointer events. PNG export also requires
image sources that permit canvas use through CORS.
Repository status
The initial standalone extraction now includes:
- an ESM library build and TypeScript declarations;
- React and React DOM peer dependencies;
- a self-contained stylesheet with
--artleta-*theme variables; - Vitest core coverage and strict TypeScript checks;
- package metadata suitable for
npm pack.
0.2 replaced the card-oriented compatibility types with the generic entity
model above, and ships migrateCanvases for documents written before it.
Broader DOM-level component coverage remains follow-up work.
Support Artleta Canvas
If Artleta Canvas is useful to you, you can support its continued development through Buy Me a Coffee.
Development
Requires Node.js 20.19 or newer.
npm install
npm run check
npm packnpm run check runs lint, strict type checking, unit tests, the ESM build, and
declaration generation.
Releases are managed by Release Please. Conventional commits merged to main
are collected into a generated release pull request; merging that pull request
creates the version tag, GitHub release, and npm publication.
Publishing uses npm trusted publishing with GitHub Actions OIDC, so releases do not require a long-lived npm access token. Sigstore provenance is disabled while the source repository is private because npm provenance requires a public source repository.
Run the standalone example from examples/basic-react:
cd examples/basic-react
npm install
npm run devIt mounts the editor, preview, and playback surfaces against the working tree
rather than the last build, so a change to artleta.css or anything under
react/ shows up without a rebuild. See its
README for how that resolution works. Nothing
under examples/ is published: the files allowlist above covers dist,
brand, and the metadata files only.
