Commit Graph
8 Commits
Author SHA1 Message Date
bflatastic d3ebb39706 M1: stroke styles: each side's stroke weight binds to a number variable
Colour styles already applied to strokes (the stroke section's style picker,
style.apply target stroke, edits following, detach). What was missing for
strokes: the per-side weights as their own bindable fields
(strokeTopWeight/Right/Bottom/Left: node.set keys, STROKE_FLOAT scope,
stroke override group, REST boundVariables import). Setting or binding one
side turns on individual strokes with the other sides at the weight. The
Design panel's per-side fields are bindable, two to a row so a variable's
name fits.
2026-10-11 19:31:02 +07:00
BFlat ee82cdd138 M3: extended variable collections, variables import/export, gradient stop and variant bindings (#114)
Library collections can be extended in a consuming file (inherited modes, per-mode overrides with reset, extra variables; library updates keep overrides). Variables export to the REST JSON shape or CSS custom properties and import back (merged by name, validated by the REST reader, one undo step). Gradient stops and variant properties bind to variables. Also fixes clicking a gradient stop adding a new stop.
2026-10-11 10:49:16 +07:00
BFlatandClaude Opus 5.5 1444754f66 M9: collaboration polish: unique ids for styles, variables and comments; live text carets (#107)
- Styles, variables, collections, modes and comment threads created in a live
  session take ids from the creator's client space (figcraft_doc::ids: a
  number from the node id allocator, client_id << 32 | counter); outside a
  session ids are made exactly as before. The server refuses a new entry in
  another connected client's space (removed entries can be put back by undo),
  keeps removed entries in its saved state, and starts client ids above every
  space used by any kind of id.
- Others' text carets and selected characters show on the canvas in their
  colour at the glyph positions, with their name above the caret (no blinking,
  no frames of their own). Typing in a layer someone else is typing in says so
  (toast and tag); collab.peers reports who types where.
- Toasts wrap at a readable width.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 09:29:30 +07:00
BFlatandClaude Opus 5.5 4565c4ab93 M3: reorder paints, effects and layout grids in the Design panel; grid and instance property variable bindings (#81)
Fill, stroke, effect and layout grid rows drag to reorder by their grip (a handle shows over the
row, an insertion line where it lands, the row's label follows the pointer like a dragged layer;
Escape cancels; lists that differ across the selection have nothing to drag). New commands
`fill.move`, `stroke.move` and `grid.move {ids?, from, to}` join `effect.move` (lists bottom first,
one undo step; items keep everything, linked list styles are unlinked).

Variable bindings on list items follow their items when a list is reordered or shrinks:
paint colours bind per paint (`fills/<i>/color`, `strokes/<i>/color`; `fill`/`stroke` stay the
first paint's), so a moved bound paint keeps its variable and its neighbours are never recoloured.
`fill.remove`, `stroke.remove` and `grid.remove` refuse negative indices.

Layout grids get settings in the Design panel (size; count, type, width or height, margin or
offset, gutter; colour) whose numbers bind to number variables (`layoutGrids/<i>/<field>`),
re-applied on variable and mode changes. Instance boolean and text properties bind to boolean and
string variables (`componentProperties/<name>`, from the instance's properties panel), kept across
instance rebuilds, following property renames and dropped on delete, reset and detach.
Inspect names the variable of each paint.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:21:05 +07:00
BFlatandClaude Opus 5.5 d7fd41cd13 M3: library variables (#60)
Publishing a library now includes the file's variable collections (modes,
aliases, scopes), versioned per variable and collection; variables hidden
from publishing stay out unless a published variable aliases them or a
published component binds them. Files using the library see its
collections read-only in the Variables editor and the variable pickers;
binding, aliasing or setting a collection's mode copies the variables in
as read-only linked copies, library components keep their bindings, and
"Library updates available" covers changed variables (bound layers follow).

New commands: library.importVariable, library.bindVariable,
library.aliasVariable, library.setVariableMode; variable.update takes
hiddenFromPublishing.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:06:18 +07:00
BFlatandClaude Opus 5.5 ec5da02a35 M3: bind effects to variables (#55)
Shadow X, Y, blur, spread and colour, and layer/background blur radius
take variables from the Effects section like other fields (variable
button on hover, a chip to change or detach once bound). Bindings are
stored as `effects/<index>/<offsetX|offsetY|radius|spread|color>` and
applied in normalisation; pickers offer effect-scoped variables.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:52:38 +07:00
BFlatandClaude Opus 5.5 d0a21d2a7b M6: REST import of prototypes and variables; export panel polish (#42)
* M6: REST import of prototypes and variables; export panel polish

REST API file JSON import now brings prototyping and variables along:
- interactions: on click/hover/press/drag, after delay, mouse enter/leave/down/up and key
  triggers; navigate, open/swap/close overlay, back, scroll to, change to, open link and set
  variable actions (lone unconditional blocks inlined); dissolve, smart animate, move, push and
  slide transitions with easing incl. custom bezier and spring; the legacy transitionNodeID
- flow starting points (and the deprecated start node), overflowDirection, scrollBehavior,
  prototypeDevice and prototype background
- the local variables response (collections, modes with the default first, values, aliases,
  scopes), passed as `variables` to file.open / file.import (object, JSON text or path), found
  next to the file (<name>.variables.json / variables.json) or embedded; boundVariables, paint
  and text style bindings and explicitVariableModes map onto the fields variable.bind uses
- file.import appends variables, flows and prototype settings with the pages
- unsupported parts (video, gamepad, conditionals, variable modes, library variables) warn

Export panel: rows with a typed or preset size (2x, 512w, 512h), suffix and all five formats
through the new export.update command; export.add steps up (1x, 2x @2x, ...); a preview;
"Export N layers" through the new file.exportLayers (one file per setting, unique safe names)
in the panel and the Export dialog; file.export takes `size`. MCP open_file/export pass the new
params.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* M6: Inspect tab: properties with styles and variables, redlines on hover (#41)

The Inspect tab lists the selected layer's properties for handoff:
layout (size, position from the parent, rotation, opacity, radius), auto
layout (direction, gap, padding, alignment), typography, fills, strokes
and effects, each with the style or variable it comes from. Clicking a
value copies it. With the Inspect tab open, hovering measures distances
from the selection without holding Alt.

New command inspect.properties returns the same groups for agents.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:17:54 +07:00
BFlatandClaude Opus 5.5 1c6f04bf62 M3: Variables editor with aliases, scopes, and rename/delete for variables, modes and collections (#33)
The Local variables window becomes a table editor: collections in a
sidebar, variables grouped by name with one value column per mode, typed
value cells (colour swatch + hex + alpha, number, string, boolean), alias
chips with a variable picker and detach, double-click rename, context
menus, and an Edit variable window for description and scopes.

New commands: variable.update (name, description, scopes),
variable.duplicate, variable.renameMode, variable.removeMode,
variable.renameCollection, variable.deleteCollection. variable.set
validates aliases (same type, no loops) and stores them by id; addMode
always picks a fresh mode id. Pickers offer only variables scoped to the
property. ui.set {variables} opens the editor on a collection.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:12:08 +07:00