Skip to content

feat: runtime plugins can register drag tools with style pickers and live previews (goal 0252 S1) - #526

Merged
alicoding merged 1 commit into
mainfrom
feat/0252-s1-plugin-drawing-doors
Aug 30, 2026
Merged

feat: runtime plugins can register drag tools with style pickers and live previews (goal 0252 S1)#526
alicoding merged 1 commit into
mainfrom
feat/0252-s1-plugin-drawing-doors

Conversation

@alicoding

Copy link
Copy Markdown
Owner

First slice of goal 0252 (drawing becomes a plugin — owner-ratified direction from tonight's decision round). Opens the three doors that separated a plugin tool from a built-in drawing tool.

The audit finding that shrank this slice: every kernel consumer — the tray's drag-to-draw branch, AtlasStylePanel, the one gesture engine, AtlasBoard's armed-descriptor lookup — was already generic over the registry, and ATLAS_TOOLS already includes third-party nouns. So the doors are a registration-surface widening plus a host adapter, with zero plugin-aware branches added to tray/panel/engine.

  • interaction: drag-to-draw / ephemeral-drag beside the click-to-place default. Drag tools create through their own gesture; a stray armed click places nothing. Ephemeral tools (laser-shape) may omit renderFace — nothing is ever placed, no claims.
  • styleFields: color / color-or-none / stroke-width, adapted onto the panel's descriptor shape (kind-derived testids, verbatim labels via i18next's missing-key fallback, the existing generic px option labels); defaults seed the style store at registration. shape-kind stays compiled-in-only (icon components) — S2.
  • gesture: { onPoint?, onEnd, renderPreview?, fadeMs? }. renderPreview(el, points, now) is the DOM twin of the built-in React preview, wrapped into the one overlay slot. The gesture ctx is deliberately narrow: screenToFlowPosition, styleValues, and createObject scoped to the plugin's own kind — no kernel internals leak. Disarm is host-owned (drag tools default sticky).

examples/plugins/mill-scribble is the shipping proof — a freehand polyline tool with no file behind it — e2e-driven from the artifact: the picked color reaches the committed stroke, the preview mounts mid-drag, a stray click lands nothing, sticky lands a second stroke. Verified live too (screenshot in session): armed tray button + style picker + a red stroke drawn onto the seeded board. 7 new unit tests pin validation/adaptation; the six existing runtime-plugin e2e tests pass with the second plugin installed.

Docs: install-a-plugin gains the Drawing-tools section, extending-the-canvas's two-door framing updated, SPEC bullet in mill-docs. S2 (port the four built-ins into a bundled Drawing plugin; erase-door design; shape-kind; shortcut keys) is next.

🤖 Generated with Claude Code

https://claude.ai/code/session_012im1JxQQV2ahnXzZDdVmZq

…live previews (goal 0252 S1)

The three doors that separated a plugin tool from a built-in drawing
tool, opened as a registration-surface widening (the S1 design lock's
audit finding: tray, style panel, gesture engine, and descriptor
lookup were already generic over the one registry):

- interaction: 'drag-to-draw' / 'ephemeral-drag' beside the
  click-to-place default. A drag tool creates through its own gesture;
  a stray armed click places nothing (placeThirdPartyObject gates on
  interaction). Ephemeral tools may omit renderFace -- nothing is ever
  placed, no content registration, no drop/paste claims.
- styleFields: color / color-or-none / stroke-width declarations,
  adapted onto the panel's own descriptor shape (kind-derived testids,
  verbatim group labels through i18next's missing-key fallback, the
  existing generic px option labels); defaults seed the one style
  store at registration so the picker highlights before first use.
  shape-kind stays compiled-in-only (icon components) -- S2.
- gesture: { onPoint?, onEnd, renderPreview?, fadeMs? } adapted onto
  AtlasToolGesture. renderPreview is the DOM twin of the built-in
  React preview, wrapped into the ONE overlay slot. The plugin ctx is
  deliberately narrow: screenToFlowPosition, styleValues, and
  createObject scoped to the plugin's own kind (frame-filing,
  refresh, undo like any placement). Disarm is host-owned: non-sticky
  disarms after onEnd; drag tools default sticky.

examples/plugins/mill-scribble is the proving consumer -- a freehand
polyline tool (board-local payload, no file) -- e2e-driven from the
shipping artifact: style pick reaches the committed stroke, preview
mounts mid-drag, stray click lands nothing, sticky lands a second
stroke. 7 new unit tests pin the validation/adaptation rules; the six
existing runtime-plugin tests pass with the second plugin installed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012im1JxQQV2ahnXzZDdVmZq
@alicoding
alicoding enabled auto-merge (squash) August 30, 2026 01:45
@alicoding
alicoding merged commit db9a6f3 into main Aug 30, 2026
30 checks passed
@alicoding
alicoding deleted the feat/0252-s1-plugin-drawing-doors branch August 30, 2026 01:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant