* fix(resize): scale children when resizing GROUP or BOOLEAN_OPERATION
Resizing a group (or boolean operation) only moved the bounding box and
rescaled the selection outline — the rendered fill stayed at its original
size, so the blue outline and the filled content visibly diverged.
Two root causes, both in the resize preview path:
1. During drag, children were scaled in the preview graph via
updateNodePreview(), which mutates nodes without emitting a node:updated
event. The renderer's vector/geometry caches (vectorPathCache,
fillGeometryCache, strokeGeometryCache) were therefore never invalidated,
so fills kept drawing from stale, unscaled cached paths while outlines
drew live from the new dimensions. Fixed by calling
renderer.invalidateVectorPath(childId) after each child preview update.
2. On commit, the final scaled values were written with updateNode() but no
repaint was requested, leaving the canvas frozen on the last mismatched
drag frame until the next interaction. Fixed by calling requestRepaint()
after commitGroupResize().
collectDescendants() now also collects children for BOOLEAN_OPERATION nodes,
which render purely from child geometry (no node-level scale), so scaling the
children is the only way to scale the result — same mechanism as GROUP, no
double-transform. Group resize verified visually; boolean resize verified in
-browser via the editor automation API.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(editor): preserve vector undo during group resize
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Danila Poyarkov <dev@dannote.net>
* fix(kiwi): import Figma groups as GROUP nodes instead of FRAME
- Map FRAME nodes with `resizeToFit === true` to `GROUP` type on import
- Write `resizeToFit = true` when exporting `GROUP` nodes back to Kiwi format
- Document findings and diagnosis in packages/docs/development/group-to-frame-import-issue.md
- Extract resolveNodeType helper to satisfy cyclomatic complexity limits
* test(kiwi): harden Figma group import + add coverage
Follow-up hardening on the group import/export fix:
- convert.ts: reorder so the COMPONENT_SET check runs before the FRAME→GROUP
reclassification, and guard the group check on the absence of auto-layout
(`stackMode` unset/NONE). Figma auto-layout "hug" frames use
stackPrimarySizing/stackCounterSizing, not `resizeToFit`, so this prevents a
component-set or auto-layout frame that happens to carry `resizeToFit` from being
misclassified as a group.
- Add tests/engine/io/fig/import/group-reclassify.test.ts: unit coverage for the
reclassification (FRAME+resizeToFit → GROUP, plain frame stays FRAME, auto-layout
hug frame stays FRAME), plus a real-file assertion that gold-preview.fig imports
its groups as GROUP.
- Add tests/engine/io/fig/roundtrip/group.test.ts: a created GROUP survives
export → re-import as a GROUP (validates the export-side resizeToFit write).
- Update exhaustive.test.ts gold-preview golden: 519 nodes that were misimported as
FRAME are now correctly GROUP (FRAME 4525→4006, GROUP 519), and export size shifts
594758→594770 because exported groups now carry resizeToFit.
Note: the pre-existing material3 variables roundtrip failure
("Invalid value EXCLUDE for enum BooleanOperation") is unrelated to groups and
also fails on master — out of scope here.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* chore(kiwi): remove temporary group-to-frame analysis doc
It was a scratch diagnostic artifact (and contained a hardcoded local path);
the rationale now lives in the fix's commit messages, code comments, and tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Danila Poyarkov <dev@dannote.net>
- Update EffectType schema assertion for modern Figma enum values
- Treat unsupported OpenType font buffers as unavailable
- Skip CJK outline fallback coverage when the LFS font fixture is not materialized
- Add AST-based lint checks for broad unknown object assertions and local JsonObject aliases
- Centralize JsonObject in core and package-local MCP RPC JSON typing
- Replace baseline Record<string, unknown> assertions with named shared/domain types
- Resolve numeric variable aliases in symbol override radius fields
- Preserve imported 999 corner sentinels through G0 to G1 roundtrips
- Remove the resolved corner-radius roundtrip TODO
- Prefer raw derivedTextData for imported Figma nodes during export
- Keep G1 exports idempotent with preserved text glyph and baseline payloads
- Remove the resolved derivedTextData roundtrip TODO