From 7cc28b7aee22759568b1fc426c8998125765d099 Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Wed, 30 Sep 2026 21:21:20 +0000 Subject: [PATCH] PosterWall: a previewSrc seam so a host can supply each card's thumbnail A card's thumbnail was always the stored previews/.webp. A gallery of poster templates drawn from the library has no stored file, and must show a library change the moment it lands, so the thumbnail can now come from the host: previewSrc: async (item) => an image URL | null. Default null keeps the stored webp and creates no observer, so every current wall is unchanged. When set, a card renders only once it is in view, one render at a time, cached on the page by instanceId + item id. Until it answers the card shows its label; null, a throw or no answer within 20 s shows the existing "preview unavailable" placeholder. The header-action gate becomes check:poster-wall-host-seams and covers both seams: arms D to G for previewSrc (default webp and no observer; lazy, one at a time and the null fallback; the timeout; the cache). Six mutants of the new code each fail it. --- ...n.mjs => check-poster-wall-host-seams.mjs} | 97 ++++++++++++++++++- library/components/poster/PosterWall.vue | 85 +++++++++++++++- package.json | 6 +- 3 files changed, 179 insertions(+), 9 deletions(-) rename internal/{check-poster-wall-header-action.mjs => check-poster-wall-host-seams.mjs} (64%) diff --git a/internal/check-poster-wall-header-action.mjs b/internal/check-poster-wall-host-seams.mjs similarity index 64% rename from internal/check-poster-wall-header-action.mjs rename to internal/check-poster-wall-host-seams.mjs index 7dcd3d0ad..b9f002009 100644 --- a/internal/check-poster-wall-header-action.mjs +++ b/internal/check-poster-wall-host-seams.mjs @@ -1,14 +1,21 @@ #!/usr/bin/env node /** - * check-poster-wall-header-action.mjs: PosterWall's header sticker does what its headerAction prop says. + * check-poster-wall-host-seams.mjs: PosterWall's two host seams, headerAction and previewSrc, do what they + * say, and with neither set every wall behaves as before. * - * WHY. PosterWall's card header was hard-wired to "Show on map". A wall with no map beside it (the + * WHY (headerAction). PosterWall's card header was hard-wired to "Show on map". A wall with no map beside it (the * Poster Design gallery) needs the same card with a different action, so the header became a seam: * headerAction null (the default) keeps the "Show on map" TOGGLE; { labelKey, ariaKey } makes it a * plain button that emits 'header-action'. Every existing wall passes nothing, so the default path is * the one that must not move, and the new path must not leak the old one's side effects (a window * event a map would act on, aria-pressed, the is-last highlight). * + * WHY (previewSrc). The card's thumbnail was always the stored previews/.webp. A gallery of templates + * drawn from the library has no stored file and must show a library change, so the thumbnail can come + * from the host. A gallery renders many cards, so the seam is LAZY (only cards in view), ONE render at a + * time, cached per page, and bounded: no answer, a throw or a timeout falls back to the wall's + * "preview unavailable" placeholder, never a blank or an endless wait. + * * HOW. No browser (fleet policy). PosterWall has no