Commit Graph
3465 Commits
Author SHA1 Message Date
bflatastic 293ab33eaa Merge #1166: M7: Cmd/Ctrl+S saves while a panel field has the keyboard (#1157) (@switch87) 2026-10-24 09:12:49 +07:00
bflatastic 90f401d73c Merge #1173: M8: the unsaved-changes question on close offers Save (#1170) (@switch87) 2026-10-24 09:12:45 +07:00
bflatastic 2053098e8e Merge #1200: The colour picker's eyedropper applies the colour to the paint the picker edits (Reported in storytold/vectorcraft#3342) (@marcoarnulfo)
# Conflicts:
#	crates/engine/src/tools.rs
2026-10-24 09:12:42 +07:00
bflatastic 2c9f5267a9 Merge #1232: M5: a top-level frame taller than the device scrolls without an overflow setting (@seltzdesign) 2026-10-24 09:11:46 +07:00
bflatastic 703d55cc67 Merge #983: Fix invisible dropdown options in the light theme (@Ridzzz0Alam) 2026-10-24 09:11:41 +07:00
midasdf 18832c620e Merge remote-tracking branch 'origin/main' into jp/kinsoku-jis
# Conflicts:
#	ROADMAP.md
#	docs/target-app-parity.md
2026-10-24 09:44:03 +09:00
vetlucasmartins 7a2568fe55 tailwind: emit @theme static; fix assertion precedence in tests
Tailwind v4 drops theme variables no utility uses, but page code also
reads tokens through var() and (--name) utilities, so the export keeps
them all. Two test assertions mixed && and || without parentheses.
2026-10-24 00:50:53 +01:00
vetlucasmartins 788d1df7be Merge remote-tracking branch 'origin/feat/css-export-px' into feat/tailwind-output 2026-10-24 00:47:30 +01:00
vetlucasmartins 90455cc429 token roles: follow alias chains to their end
variable.set does not cap alias chains, so propagate until a pass adds
nothing instead of a fixed eight rounds.
2026-10-24 00:43:59 +01:00
vetlucasmartins 3734965cce Merge remote-tracking branch 'upstream/main' into feat/css-export-px 2026-10-24 00:41:08 +01:00
vetlucasmartins 3a3746d45d Merge upstream/main into feat/data-fill 2026-10-24 00:33:14 +01:00
vetlucasmartins 601a9701a5 text.fit: keep sizes that fit, respect the floor, skip one-word paragraphs
- Text that already fits keeps its exact size; shrunk sizes round to a
  tenth but never below minSize (per run, its share of it).
- A last line after a hard break is not an orphan, and the no-break space
  is only placed inside the last paragraph.
- docs: data.fill documents formats? and errors?.
2026-10-24 00:32:24 +01:00
NetterSilverandClaude Haiku 5.5 6494743b6e Fix duplicate SVG ids when a layer name matches a generated id
Found while testing crates/svg/src/lib.rs:549 (unique_id) with :162 (id) and :387

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 22:55:35 +00:00
ArminandClaude Opus 5.5 95db91def9 M5: a top-level frame taller than the device scrolls without an overflow setting
On a device, a presented frame bigger than the screen now scrolls through
its whole size whatever its overflow, as Figma documents for top-level
frames. Before, "No scrolling" frames only clipped, so the landing page
template's long Phone frame couldn't be scrolled in Present. Content past
a frame's own edges still scrolls only on the axes its overflow allows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 00:04:28 +02:00
BFlat 8167f13a6a M12: Boards: a collaborative whiteboard file kind (#1229)
Board files (File > New board) with sticky notes, shapes with text, connectors that follow what they join (straight or elbow, arrowheads, labels), marker, highlighter and eraser, and stamps; a board toolbar and a contextual bar; the Design panel hidden on boards, Prototype and Dev Mode refused there. Boards are ordinary FigCraft files built from ordinary layers, so saving, undo, export, MCP and live sessions work unchanged. File tabs, recent files and Open files show a pen nib for design files and a note for boards (original icons drawn in code).
2026-10-24 04:18:55 +07:00
BFlat 17ed21d128 M6: Dev Mode tail: imports in layer trees, compare with versions, an inspect-only canvas (#538)
Import lines for connected components inside generated layer trees; Compare changes against any saved version; a Dev Mode behaviour suite with an inspect-only canvas (menus, shortcuts, paste and Revert to saved refuse design edits; a drag under way is dropped on entering), Changed in the ready list, statuses only on top-level frames and sections; read-only plugins' panels from the Inspect tab.
2026-10-24 02:56:55 +07:00
NetterSilverandClaude Haiku 5.5 068634b586 Honour even-odd fill rule when hit testing vectors
Found while testing crates/doc/src/geometry.rs:75 (hits_node_itself, the `_` arm, using path.winding(lp) != 0); compare VectorNetwork::fill_contains at crates/doc/src/vector.rs:321

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 21:53:25 +02:00
aiongg 70f702ca17 i18n: a missing translation fails no check; cargo xtask i18n-report lists them (#1228) 2026-10-23 15:43:21 -04:00
midasdf 04e60e23bc Merge remote-tracking branch 'origin/main' into jp/kinsoku-jis
# Conflicts:
#	ROADMAP.md
#	docs/target-app-parity.md
2026-10-24 04:11:13 +09:00
saturngod 95d4a1e6ce Merge commit '6ba02236367320fef0b373b461f6e9796bfc6de0' into fix/boolean-stroke-outlines 2026-10-23 13:02:40 -05:00
RicardoandClaude Opus 5.5 c19b7d0799 .fig export: a property name used with two types in a set writes both definitions
The set wrote one definition per name, so a variant whose property of
that name had another type named a definition the file didn't hold
(CodeRabbit review on #1152).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 12:00:22 -06:00
saturngod 690f31719d Merge commit 'c48102350b1ef00614b105ac07451ff0ca8a5141' into fix/boolean-stroke-outlines 2026-10-23 12:51:13 -05:00
aiongg 6ba0223636 Tests: the paragraph indent test loads system fonts and skips only without glyphs (#1227) 2026-10-23 13:50:42 -04:00
aiongg fc7a744519 CI: one test binary per crate, nextest, line tables only (#1208)
* Dev profile: line tables for workspace crates, no debug info for dependencies

* Tests: one integration-test binary per crate with several test files

* xtask ci: nextest, doctests, tests without examples, --keep-going; add xtask test
2026-10-23 13:01:12 -04:00
CosmoNetinfoandClaude Sonnet 5.5 98b90b3c56 Add Italian (it) interface language
Adds crates/ui-egui/locales/it.toml: all 1747 UI strings (42 plural entries,
one/other), 574 command labels and 31 menu wordings, marked as a draft awaiting
native review like the other machine-drafted catalogs. Adds a resolve/plural
test for Italian locales and lists Italian in docs/translating.md.

Not compiled locally; the catalog was validated with a script (same keys as
en.toml, identical placeholders and ellipses per entry).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fr2xzM8A8RiUwZWddELBCt
2026-10-23 16:49:31 +02:00
Dylan M. Taylor 32735549c4 test: explain the discarded reads in the fake servers (SonarCloud)
read() returns Result<Message>, not a lock guard; these test loops
deliberately ignore what the client sent first.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-10-23 09:44:02 -04:00
Salah1StandClaude Opus 5.5 f728b8f9fe M7: test that text.create and the Text tool start in DEFAULT_FONT
Review: the doc test serialised TextStyle directly. The engine test makes
text with text.create (no fontFamily) and with a Text tool click, and
checks each starts in figcraft_doc::DEFAULT_FONT and writes it with the
text. Passes with FIGCRAFT_DEFAULT_FONT unset and set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 18:07:40 +07:00
Salah1StandClaude Opus 5.5 dd37c1763c M4: the Thai fallback test checks the characters it draws
Review: the test chose its Thai face, and checked each glyph's face, by
U+0E01, which the sample doesn't contain. It now asks for a face that has
every Thai character of the sample, and checks that each glyph's face has
the characters of its cluster.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:36:24 +07:00
Salah1StandClaude Opus 5.5 c4be9c1a34 M7: say what a default font family in files does and doesn't promise
Review: a saved family renders only where that family is available. The
docs and the test's comment now say the variable changes only what new
text starts in, and that a file keeps its fonts in a build with another
default, falling back like any missing family elsewhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:34:43 +07:00
Marco Arnulfo 2a6e460a7b Let the box of another layer's points win over a region of the active one
With points selected only on another edited layer, a press inside the
combined box over an unselected filled region of the active layer picked
the region instead of dragging the box. Other layers' selections now count
in the same priority check; a press on an already selected region still
drags the regions.
2026-10-23 10:17:56 +02:00
aryans2611andClaude Sonnet 5.5 ea03f90aaf M6: mobile: test that the toolbar pill fits a phone canvas; rustfmt
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 13:09:25 +05:30
Salah1StandClaude Opus 5.5 b649035695 M7: FIGCRAFT_DEFAULT_FONT names the font new text starts in
TextStyle::default() hard-coded Inter, which has no Thai (nor Hebrew,
Devanagari, ...). In a build for users who mostly write such a script,
every new text layer started in a font that can't draw what they type:
fallback faces hide the boxes, but the layer still says Inter and gets
Inter's metrics and line height.

Like FIGCRAFT_DEFAULT_SERVER, a build variable read with option_env!
names another family; unset or empty means Inter. font_family is always
written, so files open in the same font whichever build reads them.
docs/releasing.md gets a "The default font" section.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 13:28:29 +07:00
Salah1StandClaude Opus 5.5 a51d3eed53 M7: Noto Sans Thai as a UI fallback when the build embeds it
In the web build, Thai layer names, frame labels on the canvas, text in
property fields and the layer search were drawn as missing-glyph boxes,
even when the build embedded Noto Sans Thai: the UI's built-in fallback
list (BUILT_IN in theme::install_fonts) didn't name it, and the browser
has no system fonts to fall back on.

Noto Sans Thai joins BUILT_IN. It is used only when the face is
embedded, so builds without it are unchanged. Test: with it embedded,
the UI fonts draw Thai, marks included (skips without it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 13:27:21 +07:00
Salah1StandClaude Opus 5.5 1340e32b16 M4: Thai faces in the text fallback list
Thai typed into a layer whose font has no Thai glyphs (Inter, which new
text starts in) was drawn as missing-glyph boxes, on the desktop and on
the web, even with a Thai face embedded or installed: FALLBACK_FAMILIES
listed Latin, CJK, Hangul, Arabic and symbol families but no Thai one.

Noto Sans Thai, Noto Sans Thai UI, Leelawadee UI, Thonburi and Tahoma go
after Noto Sans Arabic; they are only consulted for characters the
layer's own font lacks. Tests: the list has a Thai face for each
platform, and with one installed or embedded every Thai cluster in a
Latin layer, marks included, is drawn from it (skips without one).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 13:26:37 +07:00
Salah1StandClaude Opus 5.5 6b46a9c81a M7: FIGCRAFT_WEB_FONTS embeds more craft-fonts families in the web build
The web build has no system fonts, so it can only draw text in faces
compiled into the wasm, and crates/text/build.rs keeps a fixed set:
Inter, Noto Sans Georgian, the Archivo wordmark, and Noto Sans CJK with
FIGCRAFT_EMBED_CJK. A distribution for users of another script (Thai,
Hebrew, Devanagari, ...) had no supported way to add the face they need,
so their text was drawn as missing-glyph boxes.

FIGCRAFT_WEB_FONTS names extra manifest families, comma-separated, to
embed on wasm32. Unset, nothing changes; the variable is declared with
rerun-if-env-changed. docs/releasing.md says how to use it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 13:24:53 +07:00
aryans2611andClaude Sonnet 5.5 ab375119ad M6: mobile: submenus stay on screen, toolbar hides while a side panel is open
A submenu with no room beside its row (a phone) opens over its parent menu instead of off the
right edge. The toolbar pill is not drawn while a narrow window shows a side panel, where it was
squeezed into the strip left beside the panel.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 11:36:32 +05:30
aryans2611andClaude Sonnet 5.5 0289890197 M6: mobile layout: one side panel at a time on phones, two-finger pan, scrolling toolbar
Windows narrower than 760 pt show the Layers or Design panel over the canvas, opened from two
touch-sized buttons. Two fingers pan as well as pinch. The main toolbar pill is capped to the
canvas width and scrolls sideways (drag or wheel) when its buttons don't fit; the help button
moves above it when they would overlap. The web page's viewport covers the safe area and stops
touch scrolling and overscroll.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 11:36:31 +05:30
Nicek 261b8c5146 fix: 处理 PR 评审意见(剪贴板、图案填充、ArkUI 生成、资产缩略图)
粘贴其他应用的设计图层时保留已复制的填充/描边/效果行;粘贴重复图案前校验来源,拒绝自引用;ArkUI 生成补上变体枚举导出、对齐文本的宽度、auto layout 内绝对定位子节点,并用容器包裹带定位的 instance swap builder;资产列表只为可见行生成缩略图;Shift+Del 检查所有编辑图层的选中点;文档把 ArkUI 标为 FigCraft 自有能力并更新状态与修订历史。
2026-10-23 13:20:31 +08:00
phonedu c79bc04a29 M6: default Vue instance swaps and keep text out of attribute detection
A Vue component's instance-swap prop now defaults to its component reference in withDefaults, so the dynamic component renders the design default. Attribute detection only applies inside an unfinished opening tag, so text like `Total = {title}` stays text instead of becoming a quoted attribute value.
2026-10-23 10:48:21 +08:00
RicardoandClaude Opus 5.5 4c6c4d9667 .fig export: warn when a set's variants disagree on a property default
The format keeps one default per property of a set; the first variant's
is written (CodeRabbit review on #1152).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 20:46:12 -06:00
RicardoandClaude Opus 5.5 19d6c17b6d .fig export: grid track sizes
Grids wrote their tracks as equal ones, with a warning. Track sizes
(fixed px, hug, fill shares) are now written as gridColumnsSizing /
gridRowsSizing, the fields the import already reads.

Checked on a synthetic grid in the incumbent (fixed 320/140/112/34/34 px
columns): written as equal tracks it came in with five equal columns and
its layers overflowing their cells; now its columns keep their sizes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 20:43:55 -06:00
Nicek 1ad244d9e9 Merge remote-tracking branch 'origin/main' into local/vector-edit 2026-10-23 10:34:37 +08:00
phonedu 878e299724 M6: keep Vue attribute context and escape plain attribute entities
A quoted Vue attribute stays open across placeholders, so `title="{a} {b}"` escapes both values as attribute text. Plain Vue attribute values in instance calls now HTML-escape `&`, `<` and `>`, so a literal `&amp;` survives the round trip. Tests cover both.
2026-10-23 10:29:46 +08:00
Marco Arnulfo 410c1f10e2 The colour picker's eyedropper applies the colour to the paint the picker edits (Reported in storytold/vectorcraft#3342) 2026-10-23 04:08:48 +02:00
Nicek 5b97d03701 fix: 修复异形描边生成重叠区域的问题
通过将自相交路径简化为简单轮廓,解决了中心描边在异形尖角处产生重叠区域的问题。新增clean_poly函数清理多边形中的重复点和亚像素细条,修改路径处理逻辑确保生成的区域不重叠,同时添加相关测试验证正确性。
2026-10-23 09:49:32 +08:00
Marco Arnulfo af0b150736 M3: instance-swap properties in the Dev Mode component playground 2026-10-23 03:28:55 +02:00
skylar taylor-barrick 3b440d01e6 #237: test that wrapped colour picker swatches stay inset inside the picker
The "On this page" swatches were indented by a single add_space, so once they wrapped the later rows started at the picker's left edge and ran past its right edge. The test fills a page with 40 distinct colours, opens the picker and checks every painted swatch lies at least 16 pt inside both sides of the picker window. Without the fix the rightmost swatch ends 3 pt inside the edge instead of 16.
2026-10-22 18:39:53 -06:00
NetterSilverandClaude Haiku 5.5 ffe61d1880 Accept a version string for the plugin manifest api field
Fixes #1040

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 00:13:46 +02:00
NetterSilverandClaude Haiku 5.5 b57c67782f Deny library.publishToServer to plugins
Fixes #1055

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:54:59 +02:00
NetterSilverandClaude Haiku 5.5 b3e65c89f9 Refuse non-local library paths in the library Cache
Fixes #1056

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:46:52 +02:00