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