* fix(fig): keep variable metadata, plugin data and default mode on save
Saving a .fig rebuilt every variable record from the model, which held none
of Figma's variable metadata, so each save wrote variables as published to
all scopes with no description or code names, dropped other plugins' data,
and made the first mode the default.
Variables now carry scopes, codeSyntax and pluginData, collections carry
pluginData, and the reader and writer translate description,
symbolDescription, isPublishable, variableScopes and codeSyntax. Figma has
no default-mode field, so setting a default moves that mode first (undo
restores the order) and the writer orders the default first.
This is the base for design tokens: the CSS name will live in
codeSyntax.WEB and unit and mode conditions in OpenPencil plugin data.
* refactor(scene-graph): share the default-first mode order
setDefaultMode and the .fig writer both moved the default mode first by
hand; modesDefaultFirst does it once, with es-toolkit's partition.
* fix(core): undo a default mode change on the collection currently in the graph
Undoing a collection's removal restores a copy of it, so the inverse of
setDefaultMode wrote the previous order and default to an object the
graph no longer held when both were undone. Look the collection up by id
when undoing, as the forward step already does.
parameterConsumptionMap is a VariableDataMap like variableConsumptionMap
beside it, and a variable value can carry PropRefValue or Expression;
the schema declares all three but the codec typed none, so every reader
cast to reach them. Schema coverage counts one more modeled field and
one fewer raw-preserved.
- Preserve Figma min/max constraints, scalar variable bindings, and direct text bounds
- Reflow only authoritative generated instance geometry and pinned descendants
- Avoid double-applying auto spacing and unsafe lone-child normalization
- Move component properties, symbol overrides, derived symbol data, and clone synchronization into @open-pencil/fig\n- Add the public instance-overrides subpath with package tests and packed smoke coverage\n- Remove cross-package forwarding modules and enforce direct owner imports in architecture checks
- Invalidate only edited raw Figma fields and dependent geometry or text payloads\n- Prefer untouched component and layout-grid metadata during export\n- Restore exhaustive gold fixture scene parity and refresh coverage baselines