Commit Graph
316 Commits
Author SHA1 Message Date
BFlat 1abb9083c7 Merge pull request #821 from attisvalentin/fix/rescan-and-load-fonts
M4: fonts installed while the app runs: text.rescanFonts, text.loadFont, text.refit
2026-10-20 03:04:29 +07:00
BFlat 4788c6b819 Merge pull request #870 from MortenHusted/fix/component-paste-instance
M3: copied components paste as instances within their file
2026-10-20 03:04:03 +07:00
BFlat 54e3587fd8 Merge pull request #862 from MortenHusted/fix/instance-main-modes
M3: instances follow the variable modes their main component sets
2026-10-20 03:03:27 +07:00
BFlat 163e840fc3 Merge pull request #818 from leandrodslv/feat/ui-size
feat(ui): add the interface size preference (#540)
2026-10-20 03:01:28 +07:00
BFlat b5904ad4c2 Merge pull request #874 from justinjohn0306/fix/857-start-on-home
M7: a preference to start on the Home screen (#857)
2026-10-20 03:00:49 +07:00
BFlat d32e971685 Merge pull request #832 from Ahmed5Emad/seperate-padding
adding individual padding controls in Layout panel
2026-10-20 02:59:33 +07:00
bflatastic df99f364a7 Merge main into #821 2026-10-20 02:04:35 +07:00
bflatastic f22e2ed825 Merge main into #870 2026-10-20 02:04:33 +07:00
bflatastic 4e8f258300 Merge main into #862 2026-10-20 02:04:32 +07:00
bflatastic e8b7917002 Merge #874 into #818
# Conflicts:
#	crates/ui-egui/locales/es.toml
#	crates/ui-egui/locales/fr.toml
2026-10-20 01:43:53 +07:00
bflatastic 7b478052d1 Merge main into #818 2026-10-20 01:43:44 +07:00
bflatastic bc35f02ecb Merge main into #874 2026-10-20 01:43:43 +07:00
bflatastic 7814c32a05 Merge main into #832 2026-10-20 01:43:40 +07:00
bflatastic cbb95c6412 Merge main into #854 2026-10-20 01:33:53 +07:00
BFlat b51c9b68d7 Merge pull request #866 from YarilaFox/fix/tab-engine-order
M7: Preserve active tab and support tab reordering
2026-10-20 01:11:21 +07:00
BFlat 3ed4578112 Merge pull request #851 from MortenHusted/fix/effect-unknown-keys
M3: effects refuse keys they don't read instead of dropping them
2026-10-20 00:46:45 +07:00
BFlat f3c211eca5 Merge pull request #850 from MortenHusted/fix/make-slot-errors
M3: a refused slot names component.makeSlot
2026-10-20 00:46:07 +07:00
bflatastic b29e17f5c0 Merge main into #842
# Conflicts:
#	crates/engine/src/variables_behaviour_tests.rs
2026-10-20 00:25:18 +07:00
BFlat 7ca8c80a8f Merge pull request #814 from muamerETS/fix/layout-remove-gap-binding
M3: removing auto layout drops its gap and padding bindings (#810)
2026-10-20 00:23:28 +07:00
bflatastic 20e4028afa #818: interface sizes are relative to the system's display scale (100% is native, Auto goes; 75-200% in Preferences, pref.uiScale takes 0.75-3, "auto" reads as 1); interface_size moved above batch_rename_dialog's doc comment; tests and docs follow 2026-10-20 00:23:14 +07:00
bflatastic 9877b8e6cc #874: test that the Start on the Home screen preference persists (old settings read off) 2026-10-20 00:13:46 +07:00
BFlat 409de1a762 Merge pull request #871 from justinjohn0306/fix/809-scalar-bound-edits
M3: explicit edits of bound scalar fields detach their variable (#809)
2026-10-20 00:10:09 +07:00
BFlat ba496eddca Merge pull request #811 from MortenHusted/fix/bound-paint-edits-detach
M3: an explicit paint edit detaches the variable bound to what it changed
2026-10-19 23:59:18 +07:00
bflatastic 203ec13e03 #821: text.loadFont reads at most MAX_FONT_FILE (the font scan's 256 MiB cap) 2026-10-19 23:44:08 +07:00
bflatastic 09427e72be #871: text style shortcuts and text.set detach the bound field they change 2026-10-19 22:09:05 +07:00
justinjohn0306andClaude Opus 5.5 82a50dad1b M7: a preference to start on the Home screen (#857)
Launching opens a new empty file, which then has to be closed to get
back to Home. Preferences ▸ "Start on the Home screen"
(`pref.startOnHome {on?}`, off by default) starts the desktop app on Home
instead. Files named on the command line and recovered files still open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 17:53:24 +05:30
justinjohn0306andClaude Opus 5.5 6a163721dc M3: explicit edits of bound scalar fields detach their variable (#809)
An explicit edit of a bound width, height, opacity, gap, padding, corner
radius, stroke weight, arc or text field reported ok, but normalize wrote
the variable's value straight back. Now the edit sticks and that field's
binding is dropped, as paint edits already do.

- `styles::bound_before` / `detach_edited`: compare each layer-level
  bound field's stored value before and after the edit (`bound_field`),
  so keys written unchanged keep their bindings and fields moved along
  with another (proportions, min/max) lose theirs. A binding the edit
  itself made (`boundVariables`) stays. List and component property
  bindings are left to their own rules.
- Hooked into node.set, transform.resize, object.opacityKeys, text.style
  and `Session::preview` (canvas drags of the selected layers).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 17:33:29 +05:30
MortenHustedandCodex 0108a7c2f5 M3: copied components paste as instances within their file
Co-Authored-By: Codex (GPT-6) <noreply@openai.com>
2026-10-19 13:34:40 +02:00
YarilaFox d2dfe2ef20 M7: preserve active tab and support tab reordering 2026-10-19 14:21:52 +05:00
MortenHustedandClaude Opus 5.5 be9e72f74d M3: instances follow the variable modes their main component sets
An instance copied its main's variable modes when it was made and kept
the copy as modes of its own. Switching it to another variant kept the
old variant's modes, and a mode set on the main later never reached it.

Instances now take the modes their main sets through the link
(`Document::inherited_modes`), closer than any frame around them. Modes
set on the instance itself still win and stay through variant switches.
Bindings are re-applied for the instances of a main that chose another
mode and for an instance that switched mains. Detaching keeps the modes
the instance took from its main, and the Variable modes panel shows them
as the instance's Auto value.

Instances made before this change keep their copy as modes of their
own; setting one back to Auto lets it follow its main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 09:15:34 +02:00
Cody Campbell 4e4bf54bb6 M1: smart-selection drag reordering 2026-10-18 18:53:32 -04:00
MortenHustedandClaude Opus 5.5 6f90717e71 M3: effects refuse keys they don't read instead of dropping them
node.set refuses unknown properties, but the effects inside it were read
by serde, which drops keys it doesn't know. A drop shadow given
offsetX/offsetY (the names variable bindings use for its offset) was
stored with the default offset [0, 4] and the call said ok. effect.add
and effect.set dropped them the same way.

The three now refuse what the effect doesn't read and say what it
takes: "effects[0]: unknown properties: offsetX, offsetY (a dropShadow
takes blend, color, offset, radius, showBehind, spread, type, visible)".
A key counts as read when setting it to null makes the effect fail to
parse or come out different, so serde's aliases count as read without a
list of them here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 23:53:05 +02:00
MortenHustedandClaude Opus 5.5 147a374350 M3: a refused slot names component.makeSlot
component.makeSlot adds its slot property through add_prop, which named
itself in every error: making a second slot called "Content" said
"invalid parameters for `component.addProperty`: a property named
`Content` already exists", a command the caller never ran. add_prop now
takes the command errors name, the fix #807 makes for wrap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 23:53:04 +02:00
Muamer MustaficandCursor 79ac16a256 M3: doc comments for the structure commands and binding re-apply (#810)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-18 23:40:35 +02:00
NetterSilverandClaude Haiku 5.5 39f30d63c8 Refuse empty mode lists and blank names in variable.createCollection
Found while testing crates/engine/src/cmd/styles.rs:119-124

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:27:31 +02:00
Ahmed5Emad 02e8f644fd M2: doc comments for the padding diff's functions 2026-10-18 21:02:22 +03:00
Ahmed5Emad bc10bb190d M2: individual padding in the Layout panel
The Spacing row's toggle opens per-side Top/Right/Bottom/Left fields in a
2x2 grid in place of the H/V fields, each bound to its own padding key with
one undo step; shut H/V fields show both values ("16,54") when the sides
disagree instead of "Mixed". Original code-drawn side icons, English and
Spanish strings (padding_individual_tests).
2026-10-18 20:03:43 +03:00
Attila Valentin NémethandClaude Opus 5.5 33c0f94cc8 M4: font review fixes: new styles of loaded families, ids checks, repeat loads
- text.rescanFonts offers a loaded family the files it hasn't read (styles
  installed since) and refits every family that gained faces; `added` still
  lists only the families that were unknown
- text.refit refuses an `ids` that isn't a list instead of refitting the
  whole document
- text.loadFont with a file already loaded returns its families without
  keeping its bytes or adding its faces again
- doc comments on the functions this change touches

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 18:46:20 +02:00
Attila Valentin NémethandClaude Opus 5.5 ba4c502ada M4: text.refit: auto-sizing text measures its box again once its font is there
A text box keeps the size it was measured at, so text laid out while its
family was missing kept the fallback font's box after the font arrived (a
hugging chip clipped its label).

- text.refit {ids?} measures auto-sizing text again (whole document by
  default) → {refitted}
- text.rescanFonts and text.loadFont refit the open document's text in the
  families they add, as one undo step

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 17:35:31 +02:00
Attila Valentin NémethandClaude Opus 5.5 972e228f41 M4: text.rescanFonts and text.loadFont: fonts installed while the app runs
The system fonts are indexed once per process, so a font installed while
FigCraft (or `figcraft-cli mcp`) runs stayed missing until a restart.

- text.rescanFonts walks the font folders again and offers the families
  installed since (loaded families keep their faces) → {added}
- text.loadFont {path | data} adds a font file without installing it → {families}
- both clear the layout cache so text lays out again in the new face

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 17:13:49 +02:00
Muamer MustaficandCursor 4506f49ad4 M3: removing auto layout drops its gap and padding bindings (#810)
layout.remove and node.set {layout: null|"none"} now drop the bindings of auto layout fields (gap, crossGap, padding...), as frame-to-section already did for some of them (it now drops all of them). Re-applying a binding no longer creates an auto layout on a frame without one: the binding waits for the next auto layout.

Closes #810

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-18 15:21:28 +02:00
leandrodslvandClaude Sonnet 5.5 2c3ea03c2e feat(ui): add the interface size preference (#540)
Preferences > Interface size and the `pref.uiScale` command make the whole
interface larger or smaller. Auto keeps the system's display scale; a fixed
size from 75 % to 300 % is absolute (100 % is one screen pixel per point on
every system). The size is held back while the window is too small for it.

Strings are added in en, es and fr; the control protocol, MCP, UI parity and
roadmap docs are updated.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 14:39:57 +02:00
MortenHustedandClaude Opus 5.5 c7261cb907 M3: an explicit paint edit detaches the variable bound to what it changed
fill.set, stroke.set and node.set fill/fills/stroke/strokes reported ok
while normalize put the bound colour straight back, and node.set
{fills: []} brought the bound paint back. They now drop a paint's
colour, opacity or stop binding where the edit changed that value, as
selection.setPaint already did (its comparison moves to
lists::rebind_edited_paint, which also lets stop bindings follow a
removed stop). boundVariables applies last in props::apply, so a
binding given with the paints in one call stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 14:14:38 +02:00
MortenHustedandClaude Opus 5.5 4707cb1579 M1: wrap errors name the command that was run
Grouping, framing, auto layout, masks, outline stroke and the boolean
commands share wrap(), which named `object.group` in every refusal
(`layout.add` on a page: "invalid parameters for `object.group`").
wrap() now takes the calling command's id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 13:58:13 +02:00
BFlat 018b8166b2 M3: a bound colour variable's alpha applies once, not squared (#802) (#804)
Fixes #802.

Fixes #802.
2026-10-18 18:50:19 +07:00
bflatastic f1d336249a #801: vector.create accepts 0 on an axis the geometry has none of and refuses a flattening size; points scaling tests 2026-10-18 17:54:24 +07:00
phonedu aff3c4f18b M1: gate the outline migration on a marker and refuse impossible vector sizes
Review follow-up. A file written by this version carries editorOutlines, so a stroke someone chose is kept even when it matches the old decoration; only files without the marker get the one-time legacy cleanup. vector.create now errors when a requested side cannot scale the geometry or when both axes would collapse, instead of creating an invisible layer.
2026-10-18 18:22:48 +08:00
phonedu 911831fb89 M1: vector.create scales its path to width/height
A path's intrinsic box replaced the width and height asked for, so an icon imported at 24 stayed on its source grid. Scale the geometry to the requested size; with one side the other keeps its proportion. A path or point set that draws nothing is an error now, not an invisible 0x0 layer.
2026-10-18 17:24:50 +08:00
BFlat 8629a6f586 M3: variable.import reads variables outside meta and never imports nothing silently (#790) (#793)
Fixes #790.

Fixes #790.
2026-10-18 14:59:14 +07:00
bflatastic 401af64bba Merge fix/758 into batch 16 2026-10-18 11:16:43 +07:00