figcraft/crates/engine/src/cmd
bflatastic e917d3c2e6 M1: frames, groups, sections and masks behaviour suite and fixes
**A frames, groups, sections and masks behaviour suite written from the public documentation, and fixes for every divergence it found.** Each documented rule (frames vs. groups when resized, constraints, Cmd/Ctrl-resize, clip content, Frame selection, grouping and ungrouping, group bounds and opacity, X/Y in groups, click targets, drawing a frame or section around layers, dropping into and out of frames, where sections may go, resizing sections, top-level frames as screens and exports, Use as mask, what a mask covers, alpha / vector / luminance masks, groups as masks, clicks on masked-out areas, a mask group's box and exports) is a table-driven case with the result the rule implies and a one-line derivation; where the documentation is silent the case says so and pins today's behaviour.

**Fixes (the suite failed on 7 tests before them)**
- **Masked-out areas don't take clicks**: hit testing and Select layer skip what a visible mask hides (the nearest mask below a layer; for a group or frame used as a mask, what its layers draw), so a click there reaches what's behind. Checked only once something is hit, and skipped in files without a mask (`Document::has_masks`, worked out once after each change), so hit testing costs what it did.
- **A mask group's box and exports are the mask's**: a group's bounds and export area count a mask for the layers it masks (layers under the mask still count), so the selection box, W/H, snapping and PNG/SVG/PDF exports crop to the mask instead of the whole masked layer (`Document::box_children`).
- **Sections stay on the page or in sections**: moving a section into a frame or group (`node.reparent`, refused at the root in `Document::reparent`), dragging one over a frame (it lands in the section around the frame, or on the page), grouping or framing a section, creating a section in a frame and pasting one into a selected frame (it goes on the page) no longer put sections where they can't be.
- **Drawing a frame or section around layers puts them in it**: the layers fully inside the drawn box (its siblings; visible and unlocked; a frame never takes a section; not in auto layout) move into it, in their order, without moving on the page; one undo step.
- **Resizing a section leaves its contents** where they are on the page (no constraints in sections), from a field, a handle (also the left/top edges) or `transform.resize` with any anchor.
- **Cmd/Ctrl while resizing a frame leaves its layers as they are**: #133 (merged in) keeps their places; this branch also keeps their sizes (the frame is resized without running constraints, so a left & right or scale child no longer stretches and is only moved back).
- **X/Y are measured in the frame, not the group**: groups and boolean groups have no coordinate space of their own, so a layer in a group shows (Design panel, `node.get`, `inspect_document`) and takes (`node.set`, `node.create` with a group parent) X/Y in the frame the group is in, or on the page (`Document::frame_relative`). Rotated groups too.

Already there and now covered by the suite: constraints when a frame resizes, groups scaling their layers, clip content (drawing, hits, export size), Frame selection's size and place, grouping/ungrouping keeping world transforms (rotated groups too), nested groups, empty groups going away, group opacity on the composite, click / Cmd-click / double-click targets (frames in sections count as top-level frames), dropping by the pointer and pulling out, group layers staying in their group when dragged, top-level frames as prototype screens and export boards, Use as mask (bottom layer, "Mask group", at the topmost layer's place, single-layer toggle), masks covering every layer above them, hidden masks, alpha / vector / luminance masks, a group as a mask, masks in SVG and PDF exports.

No new commands or UI strings (no i18n changes); each edit stays one undo step.
2026-10-12 00:57:43 +07:00
..
arrange.rs M1: frames, groups, sections and masks behaviour suite and fixes 2026-10-12 00:57:43 +07:00
comment.rs M9: collaboration polish: unique ids for styles, variables and comments; live text carets (#107) 2026-10-11 09:29:30 +07:00
component.rs M3: components behaviour suite and fixes 2026-10-12 00:57:43 +07:00
create.rs M1: frames, groups, sections and masks behaviour suite and fixes 2026-10-12 00:57:43 +07:00
edit.rs M1: frames, groups, sections and masks behaviour suite and fixes 2026-10-12 00:57:43 +07:00
file.rs M6: .fig import (best effort) (#132) 2026-10-11 18:59:59 +07:00
image.rs M3: paint: colour profiles (Display P3), image adjustment presets, style picker (#54) 2026-10-10 07:38:17 +07:00
layout.rs M2: auto layout depth: min/max UI, ignore auto layout toggle, text baseline alignment, grid tracks and cells (#3) 2026-10-10 02:23:43 +07:00
library.rs M9: team libraries on the server; swap library (#117) 2026-10-11 13:05:46 +07:00
lists.rs M3: extended variable collections, variables import/export, gradient stop and variant bindings (#114) 2026-10-11 10:49:16 +07:00
mod.rs M6: code connect: link components to real code (#122) 2026-10-11 14:02:37 +07:00
page.rs M1: frame guides (#70) 2026-10-10 12:16:56 +07:00
props.rs M1: frames, groups, sections and masks behaviour suite and fixes 2026-10-12 00:57:43 +07:00
proto.rs M5: prototyping behaviour suite and fixes 2026-10-12 00:57:43 +07:00
proto_actions.rs M5: build conditionals in the interaction editor; hotspot hints; inspect in the presenter (#82) 2026-10-10 16:00:02 +07:00
section.rs M6: Dev Mode compare changes, focus view, annotation categories (#97) 2026-10-10 23:29:17 +07:00
structure.rs M1: frames, groups, sections and masks behaviour suite and fixes 2026-10-12 00:57:43 +07:00
styles.rs M3: styles and variables behaviour suite and fixes 2026-10-12 00:57:43 +07:00
text.rs M4: text on a path and pattern fills (#118) 2026-10-11 13:25:33 +07:00
variables.rs M3: styles and variables behaviour suite and fixes 2026-10-12 00:57:43 +07:00
variables_io.rs M3: styles and variables behaviour suite and fixes 2026-10-12 00:57:43 +07:00
view.rs M1: layers panel keyboard (box selection, F2 rename, context menu) and stroke styles (#135) 2026-10-11 23:10:41 +07:00