feat: runtime plugins can register drag tools with style pickers and live previews (goal 0252 S1) - #526
Merged
Merged
Conversation
…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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-dragbeside the click-to-place default. Drag tools create through their own gesture; a stray armed click places nothing. Ephemeral tools (laser-shape) may omitrenderFace— 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, andcreateObjectscoped to the plugin's own kind — no kernel internals leak. Disarm is host-owned (drag tools default sticky).examples/plugins/mill-scribbleis 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