openpencil/crates
Kayshen-X 6fd6f63a6f feat(color-picker): variable-mode commit routes through set_color_hex
Closes the missing wire between the new `VariableTable::set_color_hex`
write path (round 3 fix in febe7a76) and the existing ColorPicker
floating UI. The host can now route a VariablesPanel row click into
the picker keyed to a variable; HSV drag flows back through the
variable's storage, paint reflects the change on the next frame.

`crates/openpencil-shell-core/src/document.rs`:
  - `ColorPickerState` grew two parallel fields:
      `variable: Option<String>` — name of the Color variable
                                   being edited; `None` ⇒ node-target
                                   mode (existing Fill/Stroke path).
      `variable_pre_color: Option<Color>` — resolved colour at open
                                   time, used by `close_color_picker`
                                   to detect "did anything change?"
                                   without requiring DocumentSnapshot
                                   to carry var_table.
  - `ColorTarget` stays Copy + Fill/Stroke-only. Adding a
    `Variable(String)` variant would have forced touching every
    pattern-match site; the parallel field keeps the existing 18+
    `ColorTarget` callers untouched.

`crates/openpencil-shell-core/src/document/color_picker.rs`:
  - `Document::open_color_picker_for_variable(name, anchor_y)`:
    new entry point. Seeds HSV from `var_table.resolve_color(name)`,
    captures the resolved colour into `variable_pre_color`. Returns
    `false` when the name is unknown or the variable isn't
    Color-kind — so a host-side dispatcher can `if !doc.open_...
    return;` without inspecting state.
  - `Document::color_picker_set_hsv` branches on `variable.is_some()`:
    routes through `format_color_hex_for_var(rgb)` →
    `var_table.set_color_hex(name, hex)`. The set_color_hex
    correctness saga (3 commits, no shadowing, no cross-axis
    clobber) carries this commit transparently.
  - `Document::close_color_picker` for the variable path compares
    `state.variable_pre_color` vs `var_table.resolve_color(name)` to
    decide whether to push the pre-edit snapshot onto undo.
    Single-bool changed-check matches the node-target branch.
  - New `format_color_hex_for_var(rgba) -> String` helper emits
    `#rrggbb` for the var-write commit path.

Tests (4 added, 294 shell-core total):
  - `open_color_picker_for_variable_seeds_hsv_from_resolved_color`
    — picker opens against `#ff8800`; HSV anchor reads as orange-hue
    (20°–45° range), near-max sat + val.
  - `open_color_picker_for_variable_fails_when_var_missing_or_wrong_kind`
    — unknown name returns false; Number-kind variable returns false;
    picker state stays None in both cases.
  - `color_picker_set_hsv_writes_through_variable_path` — end-to-end:
    open on `#ff8800`, push HSV (0°, 1, 1) = pure red, assert
    `resolve_color` returns red.
  - `close_color_picker_after_variable_edit_pushes_history_only_when_changed`
    — open + close with no HSV change → no history push. Open +
    drag + close → history depth grows by 1.

The full variable edit UX now has a working host integration point:
when VariablesPanel emits `VariablesPanelHit::Row(idx)` for a color
variable, the host calls `open_color_picker_for_variable(name)` and
the existing picker chrome takes over.
2026-05-14 18:59:14 +08:00
..
anthropic-agent-sdk chore(crates): move vendored SDKs into workspace as forkable crates 2026-05-14 16:49:17 +08:00
copilot-sdk chore(crates): move vendored SDKs into workspace as forkable crates 2026-05-14 16:49:17 +08:00
openpencil-app feat(openpencil-app): skeleton crate (Stage F entry placeholder) 2026-05-03 22:05:00 +08:00
openpencil-desktop refactor(desktop): extract rotate-cursor builder into cursor_icon.rs 2026-05-14 17:38:16 +08:00
openpencil-shell-core feat(color-picker): variable-mode commit routes through set_color_hex 2026-05-14 18:59:14 +08:00
openpencil-shell-native fix(geometry): canvas_region shrinks for VariablesPanel too (codex BLOCK) 2026-05-14 17:57:55 +08:00
openpencil-shell-web feat(shell): export dialog + multi-format raster (PNG/JPEG/WEBP) + Property-panel preview 2026-05-14 14:02:52 +08:00
pen-codegen chore(workspace): cargo-deny 0.18 activation (Phase 1 Task 1.8 Step 6) 2026-05-03 23:05:00 +08:00
pen-core chore(workspace): cargo-deny 0.18 activation (Phase 1 Task 1.8 Step 6) 2026-05-03 23:05:00 +08:00
pen-engine chore(workspace): cargo-deny 0.18 activation (Phase 1 Task 1.8 Step 6) 2026-05-03 23:05:00 +08:00
pen-figma chore(workspace): cargo-deny 0.18 activation (Phase 1 Task 1.8 Step 6) 2026-05-03 23:05:00 +08:00
pen-types feat(pen-types): skeleton crate (bucket A) 2026-05-03 22:35:00 +08:00
wasm-libc-shim style(shell): cargo fmt --all (rustfmt-clean) 2026-05-10 18:47:33 +08:00
CLAUDE.md feat(shell): canonical .op loader + jian-core layout + visual fidelity pass 2026-05-14 09:26:08 +08:00