From a4a20506364d130aa10ddabcff1041157a0ab7a9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Mar 2026 17:39:48 +0000 Subject: [PATCH 1/2] Initial plan From 07905017283335225335c22ee885b9a70f4534b5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Mar 2026 17:48:18 +0000 Subject: [PATCH 2/2] Add thumbnail support to base layer switcher Co-authored-by: jumpinjackie <563860+jumpinjackie@users.noreply.github.com> --- src/api/common.ts | 7 ++ src/components/base-layer-switcher.tsx | 73 +++++++++++++++++++- src/styles/index.css | 62 +++++++++++++++++ test/components/base-layer-switcher.spec.tsx | 69 +++++++++++++++++- viewer/generic.html | 7 +- 5 files changed, 212 insertions(+), 6 deletions(-) diff --git a/src/api/common.ts b/src/api/common.ts index 42b386b2a..ef097e8b1 100644 --- a/src/api/common.ts +++ b/src/api/common.ts @@ -424,6 +424,13 @@ export interface IExternalBaseLayer { * */ options?: any; + /** + * An optional URL to a thumbnail image to display in the base layer switcher UI + * + * @type {string} + * @since 0.15 + */ + thumbnailImageUrl?: string; } diff --git a/src/components/base-layer-switcher.tsx b/src/components/base-layer-switcher.tsx index 5adab8c2a..a024f22c3 100644 --- a/src/components/base-layer-switcher.tsx +++ b/src/components/base-layer-switcher.tsx @@ -16,8 +16,24 @@ export interface IBaseLayerSwitcherProps { /** * The BaseLayerSwitcher component provides a user interface for switching the active external - * base layer of the current map - * @param props + * base layer of the current map. + * + * When any base layer has a `thumbnailImageUrl` set, the switcher renders as a thumbnail grid + * instead of a radio-button list. + * + * @example + * ```tsx + * console.log(name)} + * /> + * ``` + * + * @since 0.15 */ export const BaseLayerSwitcher = (props: IBaseLayerSwitcherProps) => { const { locale, externalBaseLayers } = props; @@ -31,6 +47,57 @@ export const BaseLayerSwitcher = (props: IBaseLayerSwitcherProps) => { React.useEffect(() => { setSelected(visLayers.length == 1 ? visLayers[0].name : STR_EMPTY); }, [visLayers]); + + const visualLayers = externalBaseLayers.filter(ebl => isVisualBaseLayer(ebl)); + const hasThumbnails = visualLayers.some(layer => !!layer.thumbnailImageUrl); + + if (hasThumbnails) { + const onThumbnailClick = (layerName: string) => { + setSelected(layerName); + props.onBaseLayerChanged?.(layerName); + }; + const onThumbnailKeyDown = (e: React.KeyboardEvent, layerName: string) => { + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + onThumbnailClick(layerName); + } + }; + const noneLabel = tr("NONE", locale); + return
+
onThumbnailClick(STR_EMPTY)} + onKeyDown={(e) => onThumbnailKeyDown(e, STR_EMPTY)} + > +
{noneLabel}
+
{noneLabel}
+
+ {visualLayers.map(layer => { + const isSelected = layer.name === selected; + return
onThumbnailClick(layer.name)} + onKeyDown={(e) => onThumbnailKeyDown(e, layer.name)} + > + {layer.thumbnailImageUrl + ? + : + } + +
; + })} +
; + } + return
- {externalBaseLayers.filter(ebl => isVisualBaseLayer(ebl)).map(layer => { + {visualLayers.map(layer => { return