feat(ui): add Image Map widget with plotly scatter and click-to-select - #38
Open
lstein wants to merge 1 commit into
Open
feat(ui): add Image Map widget with plotly scatter and click-to-select#38lstein wants to merge 1 commit into
lstein wants to merge 1 commit into
Conversation
lstein
force-pushed
the
feat/image-map-05-widget
branch
from
August 2, 2026 21:18
cbcde6b to
0da5cc5
Compare
lstein
marked this pull request as draft
August 2, 2026 22:23
lstein
force-pushed
the
feat/image-map-05-widget
branch
from
August 2, 2026 22:38
0da5cc5 to
5fb4304
Compare
lstein
force-pushed
the
feat/image-map-04-projection
branch
2 times, most recently
from
August 3, 2026 01:38
5091e5d to
ec55e63
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
2 times, most recently
from
August 3, 2026 02:26
599acac to
72b3041
Compare
lstein
force-pushed
the
feat/image-map-04-projection
branch
from
August 3, 2026 02:26
ec55e63 to
9a46659
Compare
lstein
marked this pull request as ready for review
August 3, 2026 18:28
lstein
force-pushed
the
feat/image-map-04-projection
branch
from
August 4, 2026 01:43
9a46659 to
589a09b
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
from
August 4, 2026 01:43
72b3041 to
8030e09
Compare
lstein
force-pushed
the
feat/image-map-04-projection
branch
from
August 4, 2026 05:37
589a09b to
bbab55d
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
from
August 4, 2026 05:37
8030e09 to
0be308f
Compare
lstein
force-pushed
the
feat/image-map-04-projection
branch
from
August 4, 2026 14:58
bbab55d to
fe1b01c
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
from
August 4, 2026 14:58
0be308f to
8f0e63b
Compare
lstein
force-pushed
the
feat/image-map-04-projection
branch
from
August 4, 2026 22:32
fe1b01c to
d1976a2
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
from
August 4, 2026 22:32
8f0e63b to
e4f4132
Compare
lstein
force-pushed
the
feat/image-map-04-projection
branch
from
August 5, 2026 00:31
d1976a2 to
8754846
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
3 times, most recently
from
August 5, 2026 01:18
7259190 to
3726790
Compare
lstein
force-pushed
the
feat/image-map-04-projection
branch
from
August 5, 2026 01:18
8754846 to
285ea0b
Compare
Adds the "Image Map" workbench widget: a semantic 2D map of the gallery
(backed by the /v1/image_map API) rendered as a plotly scattergl scatter,
cluster-colored, with DBSCAN noise dimmed. Clicking a point hydrates the
image via the bulk by-names endpoint and selects it in the gallery, so
Preview follows automatically.
- Imperative plotly on a ref div (no react-plotly), lazy-loaded so the
plotly bundle ships as its own vite chunk (~500KB gz) outside the eager
vendor chunk, only fetched when the widget renders.
- Placed in the right rail between Gallery and Preview in all built-in
layout presets; graceful states for indexing-disabled, computing, empty,
and error (so the widget degrades cleanly if the backend lacks the API).
- Pure trace/layout builders and a small external store keep the plotly
host thin and the logic unit-testable; pan via plotly dragmode, custom
zoom and the live current-image marker come in follow-up PRs.
Amended during the rebase onto the re-architected webv2:
- Widget module restructured to the manifest/implementation split: an
eager manifest.ts with `load: () => import('./implementation')` and an
i18n label (widgets.labels.imageMap in en.json) replaces the old
index.ts single-manifest module; implementation.ts registered in
scripts/widget-sources.mjs so it splits into its own widget chunk.
- Imports moved to the new homes: @workbench/widgetContracts (was
@workbench/types), @platform/transport/http (was @workbench/backend/
http), @platform/state/externalStore (was @workbench/externalStore).
- Selection goes through useWorkbenchCommands().gallery.selectItem with
legacyGeneratedImageToGalleryItem, hydrating via galleryImages
.resolveMany from @features/gallery (the old workbench/gallery/api.ts
export is gone).
- 'image-map' added to FirstPartyWidgetTypeId, the workbench ownership
manifest directoryRules, and workbenchState's default widget states /
instance types alongside the layout presets.
- Plotly chunking uses the codeSplitting group style (manualChunks is
gone) and 'plotly' is added to editorForbiddenInitialChunkNames; the
architecture and browser performance baselines were recaptured to
acknowledge the eager manifest source and the small owned-bytes growth
(launchpad +5 B, editor +426 B raw).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review fix: the image-map store is now registered as an account-owned
resource (reset to idle on account invalidation; scope-guarded fetch).
lstein
force-pushed
the
feat/image-map-04-projection
branch
from
August 5, 2026 01:21
285ea0b to
8984cd4
Compare
lstein
force-pushed
the
feat/image-map-05-widget
branch
from
August 5, 2026 01:21
3726790 to
43542e6
Compare
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
PR 5 of the Image Map stack — the first frontend layer. Adds the "Image Map" workbench widget: a semantic 2D map of the gallery (backed by
/v1/image_map) rendered as a plotlyscatterglscatter, cluster-colored with DBSCAN noise dimmed.selectGalleryImage, so Preview follows automatically. A monotonic sequence guard means rapid clicks always resolve to the latest click, hydrate failures are caught (no unhandled rejections), and DTOs are fetched fresh (no stale star/board state).React.lazy-loaded soplotly.js-gl2d-dist-minships as its own vite chunk (~504KB gz, verified absent from the eager vendor chunk).uirevisionpreserves pan/zoom across data refreshes.An adversarial review of this diff was run; its findings (click-ordering race, unhandled rejections, missing
uirevision,URLSearchParams.sizebeing newer than the browser baseline, stale-DTO cache, error-state UX) are all fixed above. Remaining noted trade-offs: plot-layer behavior (marker, custom zoom) arrives in the next PRs of the stack; the plotly canvas itself isn't jsdom-testable.Testing
17 vitest tests (api mapping incl. query params, store transitions incl. error-keeps-data, cluster palette, trace/layout builders, registry).
pnpm lint(oxfmt + oxlint + tsc) andpnpm buildpass; manual smoke against the dev server pending backend deploy of the stack below it.🤖 Generated with Claude Code