Merge branch 'bundler-2/rm-plugin-only' into bundler-2/handoff
# Conflicts: # plugin-designs/doxa-research-map/research-map.vue
This commit is contained in:
commit
964b4c4ccf
1 changed files with 50 additions and 5 deletions
|
|
@ -123,9 +123,16 @@ function _syncScrollZoomToHost(m) {
|
|||
// non-interactive and left the strips redundant. Two fixes for one bug, and the second one
|
||||
// silently undid the feature.
|
||||
//
|
||||
// So: keep scroll-zoom ON, and let the strips carry the page. `docScrolls`/`ancestorScrolls`
|
||||
// are still computed because the edge affordance below keys its gray indicator off the same
|
||||
// question — a map with nothing stacked under it should not advertise a scroll lane.
|
||||
// So: keep scroll-zoom ON, and let the strips carry the page.
|
||||
//
|
||||
// ★ THE TWO SCROLL PROBES THAT USED TO SIT HERE ARE GONE, AND THE COMMENT THAT KEPT THEM WAS
|
||||
// WRONG. It said docScrolls/ancestorScrolls were still computed because "the edge affordance
|
||||
// keys its gray indicator off the same question". This profile has no such indicator and never
|
||||
// calls useEdgeScrollAffordance: its .map-scroll-edge strips are background:transparent lanes
|
||||
// that are always present (see the rules near the bottom of this stylesheet). They were
|
||||
// function-local consts, computed and discarded — the comment described a consumer that does
|
||||
// not exist here, which is worse than no comment, because it makes dead code look load-bearing.
|
||||
// _findScrollportAncestor STAYS: it is still used to pick a second ResizeObserver target below.
|
||||
m.scrollZoom.enable()
|
||||
} catch (_) { /* an engine without scrollZoom must never break the panel */ }
|
||||
}
|
||||
|
|
@ -428,6 +435,20 @@ useShadowStyles(`
|
|||
.map-scroll-edge, .rm-provider-badge, .rm-loading { display:none !important; }
|
||||
}
|
||||
.rm-map-canvas { position:absolute;inset:0; }
|
||||
|
||||
/* ★ PRINT: GIVE THE MAP AREA A HEIGHT, OR EVERYTHING ANCHORED TO IT RISES.
|
||||
.rm-map-area is flex:1 1 0 — it has no height of its own and fills a viewport-height ancestor.
|
||||
Print layout has no viewport height, so that box collapses toward its content height, and the
|
||||
toolbar and legend (position:absolute against it) move UP with its top edge. That is the Driver-reported
|
||||
print breakage (the map controls and legend jump upward), and it needs no print
|
||||
stylesheet to cause — the browser's DEFAULT print styles are enough, because nothing here declared
|
||||
one. A profile with no @media print rules is not neutral in print; it is unspecified.
|
||||
A definite height restores the anchor. This does not change what the poster prints — that is a
|
||||
separate document in its own frame (printInPlace) — it stops the LIVE page deforming while the
|
||||
dialog is open. */
|
||||
@media print {
|
||||
.rm-map-area { flex: 0 0 auto; height: 100vh; min-height: 0; }
|
||||
}
|
||||
/* MATERIAL LIGHT (2026-09-21). Was background #0f1216 / color #7c8cf8 — same unconditional
|
||||
loading overlay as .dsm-loading, .apg-loading and countries-map's .rm-loading. Rendered on
|
||||
every load via v-if="!appReady", so it was the first surface a visitor saw.
|
||||
|
|
@ -437,6 +458,9 @@ useShadowStyles(`
|
|||
map did manage to render stays visible around it. A spinner that outlives the
|
||||
failure reads as "slow" and the user just waits; this says the map is gone. */
|
||||
.rm-error { position:absolute;top:50%;left:12px;right:12px;z-index:7;transform:translateY(-50%);text-align:center;font:13px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;color:#fecaca;background:rgba(15,18,22,.95);border:1px solid rgba(254,202,202,.28);border-radius:10px;padding:12px 14px;box-shadow:0 2px 10px rgba(0,0,0,.4); }
|
||||
/* inset-inline-end, not right: this badge is pinned to the READING edge, so under ar it belongs on
|
||||
the left. .map-scroll-edge--left/right below stay physical on purpose — those are literal screen
|
||||
edges for a scroll affordance and do not mirror. */
|
||||
.rm-badge { position:absolute;top:10px;inset-inline-end:10px;background:rgba(124,140,248,0.12);color:#7c8cf8;border:1px solid rgba(124,140,248,0.3);padding:3px 9px;border-radius:4px;font-size:11px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;pointer-events:none;z-index:50; }
|
||||
/* Engine badge — bottom-left, unobtrusive. Colour differs per engine so a
|
||||
side-by-side comparison is readable at a glance. */
|
||||
|
|
@ -1469,6 +1493,15 @@ function onExport(kind) {
|
|||
if (base === 'poster') return openPoster()
|
||||
if (base === 'packet') return openPacket(variant || 'full')
|
||||
}
|
||||
// ★ THE PHONE HAD NO EXPORT AT ALL, AND THE KILL-SWITCH ONLY COVERED THE DESKTOP.
|
||||
// LegendDesktop takes :export-enabled="EXPORT_FEATURE_ENABLED", so turning that flag off hid the
|
||||
// desktop menu — but LegendMobile is OPT-IN BY CONSTRUCTION: its exportEnabled is
|
||||
// `typeof inject('onLegendExport') === 'function'` (LegendMobile.vue:393), and this profile provided
|
||||
// nothing. So a reader on a phone had no way to export a poster or a packet, while the same map on a
|
||||
// desktop did. country-posters already carries the guarded line; this is the missing half here.
|
||||
// Providing it UNGUARDED would be the other error — the phone would then keep an affordance the
|
||||
// desktop deliberately hides whenever the flag is off, which is the bug exp's card names.
|
||||
provide('onLegendExport', EXPORT_FEATURE_ENABLED ? onExport : null)
|
||||
|
||||
// ★ THE PHONE HAD NO EXPORT AT ALL. The desktop legend gets :export-enabled and @export in the
|
||||
// template, but LegendMobile does not read props from here — it reaches for an injected handler, and
|
||||
|
|
@ -1487,7 +1520,19 @@ provide('onLegendExport', EXPORT_FEATURE_ENABLED ? onExport : null)
|
|||
// ─── Packet export (printed, multi-page: map + a card per people group) ──────
|
||||
// Lazy-loaded on first use, the same pattern openPoster() uses. Defensive throughout: never throw
|
||||
// uncaught into the UI; guard against double-run.
|
||||
let _packetBusy = false
|
||||
// ★ A REF, NOT A PLAIN LET, AND THAT IS THE WHOLE DEFECT. This guarded re-entrancy correctly and could
|
||||
// not tell the reader anything, because a non-reactive binding drives no UI. Its sibling openPoster()
|
||||
// has had `posterBusy` as a ref wired to :active/:disabled/:aria-busy since it was written — so the
|
||||
// FASTER action showed a busy state and the SLOWER one (dynamic imports, a map render, then a card per
|
||||
// people group) showed none. One path was given feedback and its sibling was never looked at; upg100
|
||||
// found the identical shape on their own surface the same day.
|
||||
// Widened by me today: providing onLegendExport gave the legend's Export menu a mobile entry point,
|
||||
// so there is now a second way into this path.
|
||||
const packetBusy = ref(false)
|
||||
// The legend's Export menu reaches BOTH builds, so it reports either one. Provided rather than passed
|
||||
// because the mobile sheet's legend is mounted by LegendMobile, not by this template.
|
||||
const exportBusy = computed(() => posterBusy.value || packetBusy.value)
|
||||
provide('legendExportBusy', exportBusy)
|
||||
// Neither export hands over a file any more: the poster prints through printImageBlob and the packet
|
||||
// through the shared usePosterPrints.printPacket, so the download helper that served packet.pdf is gone.
|
||||
async function openPacket(variant = 'full') {
|
||||
|
|
@ -1624,7 +1669,7 @@ async function openPacket(variant = 'full') {
|
|||
} catch (err) {
|
||||
console.error('[research-map] packet export failed:', err)
|
||||
} finally {
|
||||
_packetBusy = false
|
||||
packetBusy.value = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue