openpencil/crates/openpencil-shell-web
Kayshen-X 5503eefeb1 feat(shell): export dialog + multi-format raster (PNG/JPEG/WEBP) + Property-panel preview
Phase 1 — codec plumbing:
  - RasterFormat::{Png, Jpeg, Webp} enum.
  - export_raster(doc, target, format, scale) with NaN-guarded scale
    clamp; JPEG forces white background (no alpha); quality 100/92/92
    matches TS canvas.toDataURL.
  - File dialog filters expanded from {PNG, SVG} to {PNG, JPEG, WEBP, SVG}.
  - 6 unit tests cover format dispatch + alpha matrix + byte
    signatures + scale clamp.

Phase 2 — ExportDialog modal:
  - widgets/export_dialog.rs (new, ~330 lines). 5 format pills + 3 scale
    pills + Cancel / Export buttons. ExportFormat::is_implemented gates
    PDF off until Phase 4 ships real emit (codex stop-gate concern:
    PDF pill was selectable but always errored).
  - File menu "Export Image…" opens the modal first; the dialog's
    Export button queues new FileAction::ExportImageConfirm which uses
    Document.ui.export_format + export_scale.
  - Native widget host: scrim + paint after figma-import modal,
    top-most-modal hit-test slot before file-menu / canvas, Escape
    closes the dialog.
  - persistence.rs branches Confirm path on ui.export_format: PNG/JPEG/
    WEBP via export_raster, SVG via export_svg, PDF returns an
    explicit "not yet implemented" error (unreachable from UI now).
  - 8 unit tests (format coverage, hit-test per pill, button rects,
    centred-on-viewport, in-dialog contains, scale round-trip).

Phase 3 — Property panel preview:
  - paint_export_section shows live ui.export_format / export_scale
    instead of hardcoded "1x" / "PNG" placeholders.
  - PropertyPanel struct gains export_format / export_scale; populated
    by build_from_snapshot.
  - PropertyPanelAction::OpenExportDialog routes to FileAction::
    ExportImage on both native + web dispatchers.

Codex review: 2 rounds. Round 1 (Phase 1): NaN guard + nicer error
strings landed in-flight. Round 2 (Phase 2): 3 CONCERNs (Escape
unwired, PDF papercut, file-menu/dialog z-order race) + 2 NITs
(rect_contains half-open bounds, file caps) all addressed.

Tests: 195 total (177 shell-core + 12 shell-native + 6 desktop). wasm32
build clean.

Follow-ups: PDF emit (Phase 4), Property-panel section hit-test for
single-click open, input.rs / main.rs over-cap split.
2026-05-14 14:02:52 +08:00
..
assets feat(shell): step 4-6 chrome — TS-equivalent editor UI + interactions 2026-05-10 17:07:59 +08:00
smoke feat(shell): switch openpencil-shell-web to wasm32-unknown-unknown C-hard pipeline 2026-05-09 21:08:00 +08:00
src feat(shell): export dialog + multi-format raster (PNG/JPEG/WEBP) + Property-panel preview 2026-05-14 14:02:52 +08:00
tests style(shell): cargo fmt --all (rustfmt-clean) 2026-05-10 18:47:33 +08:00
.gitignore feat(shell): switch openpencil-shell-web to wasm32-unknown-unknown C-hard pipeline 2026-05-09 21:08:00 +08:00
Cargo.toml fix(shell-web): Step 3 stop-hook — actually render canvas text 2026-05-10 12:38:33 +08:00