feat(publish): publication-ready figure editor - #232
Merged
Conversation
…n to state Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nsets Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…pping Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… overflow modes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…to flexible preset - Fix PNAS 1-col width (88→87 mm), PLOS widths (83→132, 173→190 mm) - Add maxHeightMm to Cell (225), PNAS (225), PLOS (222) presets - Replace Poster preset with Flexible (2048×1024, 300 DPI) - Show mm dimensions in preset buttons - Remove full-resolution checkbox (always render at export resolution) - Remove size mode toggle (presets handle mm constraints directly) - Dimension sliders: label+number on top, full-width slider below - Preset mm constraint: changing DPI adjusts px, changing px adjusts DPI - Height clamped to preset maxHeightMm when applicable - Default preset to flexible, DPI max 1000, legend size max 100% Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove overflow modes (scale/truncate/multi-column) — user controls columns directly via slider - Show item counts in all columns (not just single-column) - Add column gap spacing between count numbers and next column symbols - Variable row heights for wrapped text — no more overlapping labels - Center symbols and text vertically within multi-line items - Tight legend height for overlay/free positions based on content - Remove corner overlay and hidden legend position options - Reserve count width in label maxTextWidth to prevent overlap Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… highlight - Replace single radius with rx/ry for proper circles on non-square canvases - Add rotation field to CircleAnnotation - Resize handles (4 cardinal) and rotate handle on selected circles - Selection persists after click — handles stay visible until clicking empty space - Sidebar items highlight on hover with corresponding canvas outline - Fix handle positions for rotated ellipses Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…onstant-size handles - Add referenceWidth to PublishState for proportional pixel property scaling - Scale strokeWidth, arrow width/headSize, fontSize, inset border proportionally when image dimensions change - Compute displayScale (canvas px / display px) so handles, highlights, and drag indicators appear at constant screen size regardless of canvas resolution - Per-annotation property controls in sidebar: circle stroke, arrow stroke/head, label text/fontSize, inset border — all with slider+input Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…Size - Shaft stops inside arrowhead (no gap, no poke-through) - Arrowhead auto-sized from stroke width (headLen=4x, halfW=2x) - Remove headSize from ArrowAnnotation and sidebar — stroke controls all - Use butt lineCap for clean shaft-to-head transition - Add start/end circle handles for arrow endpoint repositioning Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Text renders with textAlign=center so anchor is the midpoint - Rotation pivots around text center, not left edge - Bounding box centered and measured at scaled font size - Rotate handle at center-top of box, drawn in local space - Rotation uses same atan2 formula as circle (clockwise = positive) - Removed double-click prompt editing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Insets now render at full target-rect resolution by re-capturing the scatterplot at up to 4x when insets exist. Also fixes a latent bug where renderInset used plotRect offset for drawImage source coordinates, causing wrong crops when legend is on the left or top. Additional changes: - Add inset resize/move handles for both source and target rects - Remove magnification slider (zoom determined by size ratio) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use shared .publish-toggle-btn base class for toolbar and preset buttons with blue-border-only active state matching the control-bar filter-active pattern. Remove Escape key and dead CSS (.publish-size-mode-*). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…d fingerprint - Rename Annotation→Overlay, CircleAnnotation→CircleOverlay, etc. across all publish files to avoid naming clash with data annotations - Add PublishState persistence via localStorage (survives page reload) and parquetbundle (survives file sharing) - Add viewFingerprint tracking (projection + dimensionality) to detect when overlays may be stale after projection changes - Add fingerprint mismatch warning banner with "Clear overlays" action - Add "New Figure" button (clears overlays/insets, keeps layout settings) - Remove ExportPersistenceController and all per-annotation export state - Simplify Export dropdown: Figure Editor + Quick Export, no redundant controls Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove duplicate mmToPx/pxToMm from journal-presets.ts (now imports from dimension-utils.ts) - Extract shared _applyStateAndRebuild() from _handleReset/_handleNewFigure - Add _renderSliderInput() helper to consolidate 10 slider+input combos - Create CaptureablePlotElement type alias for repeated cast - Remove dead code (void pr, unused variable) - Add 35 new tests for overlay controller and compositor - Add comprehensive Figure Editor documentation page - Update exporting docs for new Figure Editor workflow Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Target rect now always maintains the same pixel aspect ratio as the source rect — during creation, corner-handle resize, and when the source is resized. The rubber-band indicator also previews the constrained proportions while drawing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fill the gaps left by the previous commit: validator handling of Inset.pointSizeScale (preserves valid, drops invalid), overlay-controller default (newly drawn insets get 2×), and the modal's _captureInsetRenders flow — render dims = target rect, cache on repeat call, fast-path skip during high-frequency state churn, settle timer arming, and graceful null-returns when the plot element doesn't expose the geometric-zoom hooks. 9 new tests, 183 total in the publish suite.
Closes the WebGL-renderer gap that jsdom can't cover. Three Playwright tests run against the dev server: 1. inset content reflects the source rect region — finds a high-color cell on the main preview, sets the inset's source there, and asserts the inset's interior shows the same color family (proves the dataDomain + getRenderInfo translation lands on the right data). 2. Dot size slider scales the rendered point coverage — colored-pixel count at 5× is ≥1.5× the count at 1× (proves pointSizeReference actually multiplies dot pixel size). 3. High-frequency target resize does not stall — 20 rAF-paced target resizes in <2 s, modal still mounted after settle (proves the fast-path skip + rAF throttle path is wired). Wired into the existing app/tests/playwright.config.ts as a new "figure-editor" project. Not in CI by default — run with `pnpm test:e2e`. Full suite ~15 s.
Click an overlay or inset row in the right sidebar to select it (mirrors canvas selection both ways via the controller). With a selection active, Delete or Backspace removes it; Escape clears the selection. Skipped while focus is in an editable element so typing Backspace inside the label-text input still erases characters.
new ProtspacePublishModal() bypassed the customElements registry, so after Vite HMR re-evaluated publish-modal.ts the import handed back a class object that was no longer registered for the tag — the next "Open Figure Editor" then threw "Illegal constructor" and surfaced as an Export failed toast. createElement routes through the registry, matching every other custom-element mount in the app.
…ick-select Rewrites the figure-editor guide for everything added in this PR: Photoshop-style Dimensions panel (Resample, unit toggle, aspect-lock chain), preset constraints (width pinned, height clamped to maxHeight, aspect-lock disabled), legend font pt/px toggle, geometric inset zoom with per-inset Dot size slider, click-to-select sidebar items, Delete/Backspace to remove + Escape to clear, PNG pHYs DPI metadata, mm-accurate PDF page sizing.
fix(publish): address PR #232 review (16 findings)
This was referenced May 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
protspace prepare, fix-f→-aflag, add LocalMAP, annotation groups, embedder models ([DOCS] Update documentation to reflect latest changes #200)