openpencil/crates/openpencil-shell-web/src
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
..
backend feat(shell): canonical .op loader + jian-core layout + visual fidelity pass 2026-05-14 09:26:08 +08:00
event fix(shell-web): Phase C gate — exception-safe listener reg + key coverage 2026-05-09 21:52:00 +08:00
widget_host feat(shell): align + distribute toolbar (multi-select-aware) 2026-05-14 13:27:44 +08:00
lib.rs feat(shell): editor v0.8.0 batch — layer panel, pen, color picker, brand icons, settings modal, corner radius, perf 2026-05-12 21:26:27 +08:00
widget_host.rs feat(shell): export dialog + multi-format raster (PNG/JPEG/WEBP) + Property-panel preview 2026-05-14 14:02:52 +08:00