mirror of
https://github.com/tabler/tabler.git
synced 2026-10-22 07:44:18 +04:00
92 lines
3.8 KiB
Plaintext
92 lines
3.8 KiB
Plaintext
---
|
|
// A map drawn by the Tabler `MapView` component (core/js/src/map.ts) on top of
|
|
// MapLibre GL JS: the markup below is all a page needs, there is no script.
|
|
// Markers go in the default slot, as elements with `data-bs-lng` and
|
|
// `data-bs-lat`; content laid over the map goes in the `overlay` slot.
|
|
// Renders nothing unless maps[mapId] exists or `center` is set.
|
|
import maps from '@data/maps.json';
|
|
|
|
interface Props {
|
|
/** Key into the maps data; also the suffix of the container id */
|
|
mapId: string;
|
|
ratio?: string;
|
|
/** for a map with no entry in the maps data: [latitude, longitude] */
|
|
center?: [number, number];
|
|
zoom?: number;
|
|
title?: string;
|
|
style?: string;
|
|
/** buttons over the map: true for zoom, or a list such as "zoom,north,fullscreen" */
|
|
controls?: boolean | string;
|
|
/** draws the map as a 3D globe instead of a flat map */
|
|
globe?: boolean;
|
|
/** rounded corners; turn off when the map fills a box that has its own corners */
|
|
rounded?: boolean;
|
|
/** fixed height (any CSS length) instead of an aspect ratio */
|
|
height?: string;
|
|
/** a path drawn as a line: [longitude, latitude] points */
|
|
route?: number[][];
|
|
/** index of the route point reached so far: the rest of the path is dashed */
|
|
routeProgress?: number;
|
|
/** color of the route and the GeoJSON shapes */
|
|
layerColor?: string;
|
|
/** accessible names of the control buttons, by action */
|
|
labels?: Record<string, string>;
|
|
/** GeoJSON drawn over the map: an object, or the URL of a file */
|
|
geojson?: object | string;
|
|
}
|
|
|
|
const { mapId, ratio, center: centerProp, zoom: zoomProp, title, style: styleProp, controls: controlsProp, globe = false, rounded = true, height, route, routeProgress, layerColor, labels, geojson } = Astro.props;
|
|
|
|
type MapData = {
|
|
title?: string | undefined;
|
|
ratio?: string;
|
|
card?: boolean;
|
|
/** OpenFreeMap style name: positron (default), liberty, bright, dark or fiord */
|
|
style?: string | undefined;
|
|
/** style used in dark mode, `dark` by default */
|
|
darkStyle?: string;
|
|
/** buttons over the map: true for zoom, or a list such as "zoom,north,fullscreen" */
|
|
controls?: boolean | string | undefined;
|
|
zoom?: number | undefined;
|
|
center?: [number, number];
|
|
markers?: { name?: string; center: [number, number] }[];
|
|
};
|
|
|
|
const data: MapData | undefined = (maps as unknown as Record<string, MapData>)[mapId] ?? (centerProp ? { title, center: centerProp, zoom: zoomProp, style: styleProp, controls: controlsProp } : undefined);
|
|
|
|
// The data keeps [latitude, longitude]; the component takes longitude first
|
|
const center = data?.center ? `${data.center[1]},${data.center[0]}` : '13.4049,52.518827';
|
|
const ratioClass = data?.ratio ?? ratio ?? '16x9';
|
|
---
|
|
|
|
{
|
|
data && (
|
|
<div class:list={height ? 'position-relative' : `ratio ratio-${ratioClass}`} style={height ? `height: ${height}` : undefined}>
|
|
<div class:list={[height && 'h-100']}>
|
|
<div
|
|
id={`map-${mapId}`}
|
|
class:list={['w-100 h-100', rounded && 'rounded']}
|
|
role="region"
|
|
aria-label={data.title ?? 'Map'}
|
|
data-bs-toggle="map"
|
|
data-bs-center={center}
|
|
data-bs-zoom={data.zoom ?? 13}
|
|
data-bs-map-style={data.style}
|
|
data-bs-map-style-dark={data.darkStyle}
|
|
data-bs-controls={data.controls ? String(data.controls) : undefined}
|
|
data-bs-globe={globe ? 'true' : undefined}
|
|
data-bs-route={route ? JSON.stringify(route) : undefined}
|
|
data-bs-route-progress={routeProgress}
|
|
data-bs-layer-color={layerColor}
|
|
data-bs-labels={labels ? JSON.stringify(labels) : undefined}
|
|
data-bs-geojson={typeof geojson === 'object' ? JSON.stringify(geojson) : geojson}
|
|
>
|
|
{(data.markers ?? []).map((marker) => <span class="map-marker map-marker-dot" data-bs-lng={marker.center[1]} data-bs-lat={marker.center[0]} data-bs-popup={marker.name} />)}
|
|
<slot />
|
|
</div>
|
|
<slot name="overlay" />
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|