@uiness/map 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +153 -2
- package/dist/index.cjs +744 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +230 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +230 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +724 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +69 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["createContext","useContext","useRef","useState"],"sources":["../src/engine.ts","../src/projection.ts","../src/apple.ts","../src/google.ts","../src/providers.tsx","../src/map.tsx","../src/overlays.tsx"],"sourcesContent":["import type { LngLat, MapView, Point } from './projection'\n\n/**\n * A map platform drawn in place of the built-in tiles. It owns the panning and zooming, the\n * `<Map>` keeps the view and lays markers and popups over it with `project`.\n *\n * Called once per mount with the element to draw into, the starting view and a callback to\n * report every move made on the platform's side, while it happens.\n */\nexport type MapEngine = (\n container: HTMLElement,\n view: MapView,\n onMove: (view: MapView) => void,\n) => EngineMap | Promise<EngineMap>\n\nexport interface EngineMap {\n /** Move to a view the `<Map>` asks for. */\n setView(view: MapView): void\n /** A coordinate to a point in CSS pixels from the container's top left corner. */\n project(lngLat: LngLat): Point\n /** A point of the container back to a coordinate. */\n unproject(point: Point): LngLat\n /** Tear the platform's map down. */\n destroy(): void\n}\n\nconst scripts: Record<string, Promise<void>> = {}\n\n/**\n * Loads a script once per `src`, resolving when it calls back the global named `callback`.\n * Both Google and Apple announce they are ready that way.\n */\nexport function loadScript(\n src: string,\n callback: string,\n attributes: Record<string, string> = {},\n): Promise<void> {\n scripts[src] ??= new Promise<void>((resolve, reject) => {\n const script = document.createElement('script')\n ;(window as unknown as Record<string, () => void>)[callback] = () => resolve()\n script.src = src\n script.async = true\n for (const [name, value] of Object.entries(attributes)) script.setAttribute(name, value)\n script.onerror = () => {\n delete scripts[src]\n script.remove()\n reject(new Error(`Could not load ${src}`))\n }\n document.head.append(script)\n })\n return scripts[src]\n}\n","/** `[longitude, latitude]` in degrees, the GeoJSON order. */\nexport type LngLat = [lng: number, lat: number]\n/** `[x, y]` in CSS pixels from the top left corner of the map. */\nexport type Point = [x: number, y: number]\n\nexport interface MapView {\n center: LngLat\n zoom: number\n}\n\nexport interface Tile {\n /** Tile coordinates, `x` already wrapped around the world. */\n x: number\n y: number\n z: number\n /** Where it goes in the map, rounded so neighbours meet without seams. */\n left: number\n top: number\n width: number\n height: number\n key: string\n}\n\nexport const TILE_SIZE = 256\n/** The latitude where Web Mercator turns the world into a square. */\nexport const MAX_LAT = 85.0511287798\n\nconst clamp = (n: number, min: number, max: number) => Math.min(max, Math.max(min, n))\nconst worldSize = (zoom: number) => TILE_SIZE * 2 ** zoom\n\n/** Longitude into [-180, 180), latitude into what Web Mercator can draw. */\nexport function normalize([lng, lat]: LngLat): LngLat {\n return [((((lng + 180) % 360) + 360) % 360) - 180, clamp(lat, -MAX_LAT, MAX_LAT)]\n}\n\n/** A coordinate to pixels of the whole world at `zoom`, from its top left corner. */\nexport function lngLatToWorld([lng, lat]: LngLat, zoom: number): Point {\n const size = worldSize(zoom)\n const sin = Math.sin((clamp(lat, -MAX_LAT, MAX_LAT) * Math.PI) / 180)\n return [\n ((lng + 180) / 360) * size,\n (0.5 - Math.log((1 + sin) / (1 - sin)) / (4 * Math.PI)) * size,\n ]\n}\n\n/** World pixels at `zoom` back to a coordinate. */\nexport function worldToLngLat([x, y]: Point, zoom: number): LngLat {\n const size = worldSize(zoom)\n const n = Math.PI - (2 * Math.PI * y) / size\n return [(x / size) * 360 - 180, (180 / Math.PI) * Math.atan(Math.sinh(n))]\n}\n\n/** A coordinate to a point of a map of `size` showing `view`, on the copy of the world nearest the center. */\nexport function project(lngLat: LngLat, view: MapView, size: Point): Point {\n const [cx, cy] = lngLatToWorld(view.center, view.zoom)\n const [x, y] = lngLatToWorld(lngLat, view.zoom)\n const world = worldSize(view.zoom)\n const dx = x - cx - world * Math.round((x - cx) / world)\n return [dx + size[0] / 2, y - cy + size[1] / 2]\n}\n\n/** A point of the map back to a coordinate. */\nexport function unproject(point: Point, view: MapView, size: Point): LngLat {\n const [cx, cy] = lngLatToWorld(view.center, view.zoom)\n return normalize(\n worldToLngLat([cx + point[0] - size[0] / 2, cy + point[1] - size[1] / 2], view.zoom),\n )\n}\n\n/** The view moved by `delta` pixels, the way a drag moves it. */\nexport function pan(view: MapView, delta: Point, size: Point): MapView {\n return {\n center: unproject([size[0] / 2 - delta[0], size[1] / 2 - delta[1]], view, size),\n zoom: view.zoom,\n }\n}\n\n/** The view at `zoom` that keeps the coordinate under `point` where it is. */\nexport function zoomAround(view: MapView, zoom: number, point: Point, size: Point): MapView {\n const [x, y] = lngLatToWorld(unproject(point, view, size), zoom)\n return {\n center: normalize(\n worldToLngLat([x - point[0] + size[0] / 2, y - point[1] + size[1] / 2], zoom),\n ),\n zoom,\n }\n}\n\n/** The tiles of zoom level `z` that cover a map of `size` showing `view`, scaled to its fractional zoom. */\nexport function visibleTiles(view: MapView, size: Point, z: number): Tile[] {\n const scale = 2 ** (view.zoom - z)\n const [cx, cy] = lngLatToWorld(view.center, z)\n const count = 2 ** z\n const left = (x: number) => Math.round((x * TILE_SIZE - cx) * scale + size[0] / 2)\n const top = (y: number) => Math.round((y * TILE_SIZE - cy) * scale + size[1] / 2)\n const span = (px: number, c: number): Point => [\n Math.floor((c - px / 2 / scale) / TILE_SIZE),\n Math.floor((c + px / 2 / scale) / TILE_SIZE),\n ]\n const [x0, x1] = span(size[0], cx)\n const [y0, y1] = span(size[1], cy)\n const tiles: Tile[] = []\n for (let y = Math.max(0, y0); y <= Math.min(count - 1, y1); y++) {\n for (let x = x0; x <= x1; x++) {\n tiles.push({\n x: ((x % count) + count) % count,\n y,\n z,\n left: left(x),\n top: top(y),\n width: left(x + 1) - left(x),\n height: top(y + 1) - top(y),\n key: `${z}/${x}/${y}`,\n })\n }\n }\n return tiles\n}\n","import { type EngineMap, loadScript, type MapEngine } from './engine'\nimport { type LngLat, type MapView, TILE_SIZE, unproject } from './projection'\n\n// biome-ignore lint/suspicious/noExplicitAny: the SDK ships no types without a dependency\ntype Sdk = any\n\nexport interface AppleMapsOptions {\n /** MapKit JS token, from your Apple Developer account. */\n token: string\n /** Extra `mapkit.Map` constructor options, such as `colorScheme`. */\n options?: Record<string, unknown>\n}\n\n/**\n * Draws the map with Apple Maps (MapKit JS), loading it on first use.\n * Create it once, outside the component, so the map is not mounted again on every render.\n */\nexport function appleMaps({ token, options }: AppleMapsOptions): MapEngine {\n return async (container, view, onMove) => {\n await loadScript('https://cdn.apple-mapkit.com/mk/5.x.x/mapkit.core.js', '__uinessMapKit', {\n crossorigin: 'anonymous',\n 'data-callback': '__uinessMapKit',\n 'data-libraries': 'map',\n 'data-initial-token': token,\n })\n const mapkit: Sdk = (window as Sdk).mapkit\n const map = new mapkit.Map(container, options)\n\n // MapKit speaks in regions, not zoom levels: the longitude span the container's width shows.\n const span = (zoom: number) => (360 * container.clientWidth) / (TILE_SIZE * 2 ** zoom)\n const current = (): MapView => {\n const { center, span: s } = map.region\n return {\n center: [center.longitude, center.latitude],\n zoom: Math.log2((360 * container.clientWidth) / (TILE_SIZE * s.longitudeDelta)),\n }\n }\n const setView = (next: MapView) => {\n const [lng, lat] = next.center\n const size: [number, number] = [container.clientWidth, container.clientHeight]\n const lngDelta = span(next.zoom)\n const latDelta = unproject([0, 0], next, size)[1] - unproject([0, size[1]], next, size)[1]\n map.setRegionAnimated(\n new mapkit.CoordinateRegion(\n new mapkit.Coordinate(lat, lng),\n new mapkit.CoordinateSpan(latDelta, lngDelta),\n ),\n false,\n )\n }\n setView(view)\n\n // MapKit only says when a move starts and ends, so follow it frame by frame in between.\n let frame = 0\n const follow = () => {\n onMove(current())\n frame = requestAnimationFrame(follow)\n }\n const start = () => {\n cancelAnimationFrame(frame)\n follow()\n }\n const end = () => {\n cancelAnimationFrame(frame)\n onMove(current())\n }\n map.addEventListener('region-change-start', start)\n map.addEventListener('region-change-end', end)\n\n const offset = (): [number, number] => {\n const rect = container.getBoundingClientRect()\n return [rect.left + window.scrollX, rect.top + window.scrollY]\n }\n const engine: EngineMap = {\n setView,\n project: ([lng, lat]) => {\n const p = map.convertCoordinateToPointOnPage(new mapkit.Coordinate(lat, lng))\n const [x, y] = offset()\n return [p.x - x, p.y - y]\n },\n unproject: ([px, py]) => {\n const [x, y] = offset()\n const c = map.convertPointOnPageToCoordinate(new DOMPoint(px + x, py + y))\n return [c.longitude, c.latitude] as LngLat\n },\n destroy: () => {\n cancelAnimationFrame(frame)\n map.removeEventListener('region-change-start', start)\n map.removeEventListener('region-change-end', end)\n map.destroy()\n },\n }\n return engine\n }\n}\n","import { type EngineMap, loadScript, type MapEngine } from './engine'\nimport type { MapView } from './projection'\n\n// biome-ignore lint/suspicious/noExplicitAny: the SDK ships no types without a dependency\ntype Sdk = any\n\nexport interface GoogleMapsOptions {\n /** Maps JavaScript API key. */\n apiKey: string\n /** Extra `google.maps.MapOptions`, such as `mapId` or `disableDefaultUI`. `gestureHandling` is `'cooperative'` unless set: the wheel zooms with Ctrl or ⌘ and scrolls the page otherwise, `'greedy'` always zooms. */\n options?: Record<string, unknown>\n}\n\n/**\n * Draws the map with Google Maps (Maps JavaScript API), loading it on first use.\n * Create it once, outside the component, so the map is not mounted again on every render.\n */\nexport function googleMaps({ apiKey, options }: GoogleMapsOptions): MapEngine {\n return async (container, view, onMove) => {\n await loadScript(\n `https://maps.googleapis.com/maps/api/js?key=${encodeURIComponent(apiKey)}&loading=async&callback=__uinessGoogleMaps`,\n '__uinessGoogleMaps',\n )\n const maps: Sdk = (window as Sdk).google.maps\n const toLatLng = ([lng, lat]: [number, number]) => ({ lat, lng })\n const map = new maps.Map(container, {\n center: toLatLng(view.center),\n zoom: view.zoom,\n gestureHandling: 'cooperative',\n ...options,\n })\n const current = (): MapView => {\n const center = map.getCenter()\n return { center: [center.lng(), center.lat()], zoom: map.getZoom() }\n }\n // An empty overlay, only for the projection between coordinates and container pixels.\n const overlay = new maps.OverlayView()\n overlay.onAdd = () => {}\n overlay.onRemove = () => {}\n const ready = new Promise<void>((resolve) => {\n // Google calls draw whenever the projection changes: every pan and zoom.\n overlay.draw = () => {\n resolve()\n onMove(current())\n }\n })\n overlay.setMap(map)\n const listener = map.addListener('bounds_changed', () => onMove(current()))\n await ready\n\n const engine: EngineMap = {\n setView: ({ center, zoom }) => {\n map.setCenter(toLatLng(center))\n map.setZoom(zoom)\n },\n project: (lngLat) => {\n const p = overlay.getProjection().fromLatLngToContainerPixel(toLatLng(lngLat))\n return [p.x, p.y]\n },\n unproject: ([x, y]) => {\n const ll = overlay.getProjection().fromContainerPixelToLatLng(new maps.Point(x, y))\n return [ll.lng(), ll.lat()]\n },\n destroy: () => {\n listener.remove()\n overlay.setMap(null)\n maps.event.clearInstanceListeners(map)\n container.replaceChildren()\n },\n }\n return engine\n }\n}\n","import type { ReactNode } from 'react'\n\n/** Any XYZ raster tile service. */\nexport interface TileProvider {\n /** Template with `{z}`, `{x}`, `{y}` and optionally `{s}` for a subdomain. */\n url: string\n /** Credit the service asks for, shown in the corner of the map. */\n attribution: ReactNode\n /** Deepest zoom level it serves. Default 19. */\n maxZoom?: number\n /** Values for `{s}`, spread across tiles so the browser fetches in parallel. */\n subdomains?: string[]\n}\n\nconst link = (href: string, text: string) => (\n <a href={href} target=\"_blank\" rel=\"noreferrer\">\n {text}\n </a>\n)\n\nconst osmCredit = (\n <>© {link('https://www.openstreetmap.org/copyright', 'OpenStreetMap')} contributors</>\n)\n\nexport const providers = {\n osm: {\n url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',\n attribution: osmCredit,\n maxZoom: 19,\n },\n // CARTO watermarks its tiles without `?key=` appended to the url.\n cartoLight: {\n url: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',\n attribution: (\n <>\n {osmCredit} © {link('https://carto.com/attributions', 'CARTO')}\n </>\n ),\n maxZoom: 20,\n subdomains: ['a', 'b', 'c', 'd'],\n },\n cartoDark: {\n url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png',\n attribution: (\n <>\n {osmCredit} © {link('https://carto.com/attributions', 'CARTO')}\n </>\n ),\n maxZoom: 20,\n subdomains: ['a', 'b', 'c', 'd'],\n },\n openTopoMap: {\n url: 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',\n attribution: (\n <>\n {osmCredit}, SRTM | © {link('https://opentopomap.org', 'OpenTopoMap')} (CC-BY-SA)\n </>\n ),\n maxZoom: 17,\n subdomains: ['a', 'b', 'c'],\n },\n} satisfies Record<string, TileProvider>\n\n/** The address of one tile. */\nexport function tileUrl(provider: TileProvider, z: number, x: number, y: number): string {\n const subdomains = provider.subdomains ?? []\n return provider.url\n .replace('{s}', subdomains[(x + y) % subdomains.length] ?? '')\n .replace('{z}', String(z))\n .replace('{x}', String(x))\n .replace('{y}', String(y))\n}\n","import {\n createContext,\n type HTMLAttributes,\n type KeyboardEvent,\n type MouseEvent,\n type PointerEvent,\n type ReactNode,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react'\nimport type { EngineMap, MapEngine } from './engine'\nimport {\n type LngLat,\n type MapView,\n normalize,\n type Point,\n pan,\n project,\n unproject,\n visibleTiles,\n zoomAround,\n} from './projection'\nimport { providers, type TileProvider, tileUrl } from './providers'\n\nexport interface MapContextValue extends MapView {\n /** Width and height of the map in CSS pixels. 0 until it has been measured. */\n size: Point\n /** A coordinate to a point of the map, `[NaN, NaN]` while a platform is still loading. */\n project(lngLat: LngLat): Point\n /** A point of the map back to a coordinate. */\n unproject(point: Point): LngLat\n /** Move the map. What is left out stays as it is. */\n setView(view: Partial<MapView>): void\n}\n\nconst MapContext = createContext<MapContextValue | null>(null)\n\n/** The map around a component: its view, the projection and `setView`, to overlay anything. */\nexport function useMap(): MapContextValue {\n const map = useContext(MapContext)\n if (!map) throw new Error('useMap must be used inside a <Map>')\n return map\n}\n\n/**\n * When the wheel zooms the map. `'modifier'`: with Ctrl or ⌘ held, which is also what a\n * trackpad pinch sends, and the page scrolls otherwise. `'always'`: every wheel turn over the\n * map zooms, and the page cannot scroll past it. `'never'`: the wheel only scrolls.\n */\nexport type WheelZoom = 'modifier' | 'always' | 'never'\n\n/** Whether a wheel event over the map should zoom it rather than scroll the page. */\nexport function zoomsOnWheel(\n mode: WheelZoom,\n event: Pick<WheelEvent, 'ctrlKey' | 'metaKey'>,\n): boolean {\n if (mode === 'always') return true\n if (mode === 'never') return false\n return event.ctrlKey || event.metaKey\n}\n\nexport interface MapProps extends Omit<HTMLAttributes<HTMLElement>, 'children'> {\n /** Controlled center, `[lng, lat]`. */\n center?: LngLat\n /** Controlled zoom, fractional levels allowed. */\n zoom?: number\n /** Starting center when uncontrolled. Default `[0, 20]`. */\n defaultCenter?: LngLat\n /** Starting zoom when uncontrolled. Default 2. */\n defaultZoom?: number\n /** Every move: drags, pinches, the wheel, the keyboard, the zoom buttons. */\n onViewChange?: (view: MapView) => void\n /** Default 0. */\n minZoom?: number\n /** Default the provider's `maxZoom`, or 22 with an engine. */\n maxZoom?: number\n /**\n * When the wheel zooms the map: `'modifier'` (default) with Ctrl or ⌘ held or a trackpad\n * pinch, so the page scrolls past it; `'always'`; or `'never'`. Tiles only: an `engine`\n * handles its own wheel.\n */\n wheelZoom?: WheelZoom\n /** Where the tiles come from. Default OpenStreetMap. */\n provider?: TileProvider\n /** Draw with another platform instead of tiles, like `googleMaps()` or `appleMaps()`. */\n engine?: MapEngine\n /** Markers, popups, controls and anything that reads `useMap()`. */\n children?: ReactNode\n}\n\nconst KEY_PAN = 80\nconst NAN: Point = [Number.NaN, Number.NaN]\n\nconst sameView = (a: MapView, b: MapView) =>\n a.zoom === b.zoom && a.center[0] === b.center[0] && a.center[1] === b.center[1]\n\n/**\n * A slippy map of XYZ raster tiles in Web Mercator, or of another platform through `engine`.\n * Give it a size: it fills its box and has no height of its own.\n */\nexport function Map({\n center,\n zoom,\n defaultCenter = [0, 20],\n defaultZoom = 2,\n onViewChange,\n minZoom = 0,\n maxZoom,\n wheelZoom = 'modifier',\n provider = providers.osm,\n engine,\n children,\n style,\n onKeyDown,\n onPointerDown,\n onPointerMove,\n onPointerUp,\n onPointerCancel,\n onDoubleClick,\n ...props\n}: MapProps) {\n const ref = useRef<HTMLElement>(null)\n const engineRef = useRef<HTMLDivElement>(null)\n const [inner, setInner] = useState<MapView>({ center: defaultCenter, zoom: defaultZoom })\n const [size, setSize] = useState<Point>([0, 0])\n const [platform, setPlatform] = useState<EngineMap | null>(null)\n const view: MapView = { center: center ?? inner.center, zoom: zoom ?? inner.zoom }\n const max = maxZoom ?? (engine ? 22 : (provider.maxZoom ?? 19))\n\n // Read by native listeners and gestures, which outlive a render.\n const latest = useRef({ view, size, setView: (_: Partial<MapView>) => {} })\n const fromPlatform = useRef<MapView | null>(null)\n const setView = (next: Partial<MapView>) => {\n const merged = { ...latest.current.view, ...next }\n const v = {\n center: normalize(merged.center),\n zoom: Math.min(max, Math.max(minZoom, merged.zoom)),\n }\n latest.current.view = v\n setInner(v)\n onViewChange?.(v)\n }\n latest.current = { view, size, setView }\n\n useEffect(() => {\n const el = ref.current\n if (!el) return\n const measure = () => setSize([el.clientWidth, el.clientHeight])\n measure()\n const observer = new ResizeObserver(measure)\n observer.observe(el)\n return () => observer.disconnect()\n }, [])\n\n // Not passive, so a wheel that zooms can keep the page from scrolling; one that does not is left alone.\n useEffect(() => {\n const el = ref.current\n if (!el || engine) return\n const wheel = (e: WheelEvent) => {\n if (!zoomsOnWheel(wheelZoom, e)) return\n e.preventDefault()\n const { view, size, setView } = latest.current\n const rect = el.getBoundingClientRect()\n const delta = e.deltaY * (e.deltaMode === 1 ? 40 : 1)\n // A trackpad pinch arrives as small wheel steps with ctrlKey.\n const zoom = view.zoom - delta / (e.ctrlKey ? 50 : 100)\n setView(zoomAround(view, zoom, [e.clientX - rect.left, e.clientY - rect.top], size))\n }\n el.addEventListener('wheel', wheel, { passive: false })\n return () => el.removeEventListener('wheel', wheel)\n }, [engine, wheelZoom])\n\n useEffect(() => {\n const el = engineRef.current\n if (!engine || !el) return\n let alive = true\n let mounted: EngineMap | undefined\n Promise.resolve(\n engine(el, latest.current.view, (v) => {\n latest.current.setView(v)\n fromPlatform.current = latest.current.view\n }),\n )\n .then((m) => {\n if (!alive) return m.destroy()\n mounted = m\n setPlatform(m)\n })\n .catch((error) => console.error(error))\n return () => {\n alive = false\n mounted?.destroy()\n setPlatform(null)\n }\n }, [engine])\n\n const [lng, lat] = view.center\n useEffect(() => {\n const v = { center: [lng, lat] as LngLat, zoom: view.zoom }\n // Moves the platform reported itself are not sent back to it.\n if (platform && !(fromPlatform.current && sameView(fromPlatform.current, v))) {\n platform.setView(v)\n }\n }, [platform, lng, lat, view.zoom])\n\n // Pointers on the map, by id, for drags and pinches.\n const pointers = useRef<Record<number, Point>>({})\n const local = (e: { clientX: number; clientY: number }): Point => {\n const rect = ref.current?.getBoundingClientRect()\n return [e.clientX - (rect?.left ?? 0), e.clientY - (rect?.top ?? 0)]\n }\n // Markers, popups and controls keep their own clicks.\n const onOverlay = (target: EventTarget) => (target as Element).closest?.('[data-map-overlay]')\n\n const gestures = engine\n ? {}\n : {\n onPointerDown: (e: PointerEvent<HTMLElement>) => {\n onPointerDown?.(e)\n if (onOverlay(e.target) || e.button !== 0) return\n e.currentTarget.setPointerCapture(e.pointerId)\n pointers.current[e.pointerId] = local(e)\n },\n onPointerMove: (e: PointerEvent<HTMLElement>) => {\n onPointerMove?.(e)\n const before = pointers.current\n if (!before[e.pointerId]) return\n const { view, size } = latest.current\n const after = { ...before, [e.pointerId]: local(e) }\n pointers.current = after\n const [a, b] = Object.values(before)\n const [c, d] = Object.values(after)\n if (!a || !c) return\n if (!b || !d) {\n setView(pan(view, [c[0] - a[0], c[1] - a[1]], size))\n return\n }\n // Two fingers: move with their middle, zoom with their distance.\n const mid = (p: Point, q: Point): Point => [(p[0] + q[0]) / 2, (p[1] + q[1]) / 2]\n const dist = (p: Point, q: Point) => Math.hypot(p[0] - q[0], p[1] - q[1]) || 1\n const [m0, m1] = [mid(a, b), mid(c, d)]\n const moved = pan(view, [m1[0] - m0[0], m1[1] - m0[1]], size)\n setView(zoomAround(moved, view.zoom + Math.log2(dist(c, d) / dist(a, b)), m1, size))\n },\n onPointerUp: (e: PointerEvent<HTMLElement>) => {\n onPointerUp?.(e)\n delete pointers.current[e.pointerId]\n },\n onPointerCancel: (e: PointerEvent<HTMLElement>) => {\n onPointerCancel?.(e)\n delete pointers.current[e.pointerId]\n },\n onDoubleClick: (e: MouseEvent<HTMLElement>) => {\n onDoubleClick?.(e)\n if (onOverlay(e.target)) return\n const { view, size } = latest.current\n setView(zoomAround(view, Math.round(view.zoom) + (e.shiftKey ? -1 : 1), local(e), size))\n },\n }\n\n const keyDown = (e: KeyboardEvent<HTMLElement>) => {\n onKeyDown?.(e)\n if (e.target !== e.currentTarget || e.altKey || e.ctrlKey || e.metaKey) return\n const { view, size } = latest.current\n const step: Record<string, Point> = {\n ArrowLeft: [KEY_PAN, 0],\n ArrowRight: [-KEY_PAN, 0],\n ArrowUp: [0, KEY_PAN],\n ArrowDown: [0, -KEY_PAN],\n }\n const by = step[e.key]\n if (by) setView(pan(view, by, size))\n else if (e.key === '+' || e.key === '=') setView({ zoom: Math.round(view.zoom) + 1 })\n else if (e.key === '-' || e.key === '_') setView({ zoom: Math.round(view.zoom) - 1 })\n else return\n e.preventDefault()\n }\n\n const z = Math.round(Math.min(view.zoom, provider.maxZoom ?? 19))\n const value: MapContextValue = {\n ...view,\n size,\n project: engine ? (ll) => platform?.project(ll) ?? NAN : (ll) => project(ll, view, size),\n unproject: engine ? (p) => platform?.unproject(p) ?? NAN : (p) => unproject(p, view, size),\n setView,\n }\n\n return (\n <section\n ref={ref}\n aria-roledescription=\"map\"\n aria-label=\"Map\"\n // biome-ignore lint/a11y/noNoninteractiveTabindex: the map takes the keyboard to pan and zoom\n tabIndex={0}\n {...props}\n {...gestures}\n onKeyDown={keyDown}\n style={{\n position: 'relative',\n overflow: 'hidden',\n touchAction: engine ? undefined : 'none',\n userSelect: 'none',\n ...style,\n }}\n >\n {engine ? (\n <div ref={engineRef} style={{ position: 'absolute', inset: 0 }} />\n ) : (\n size[0] > 0 &&\n visibleTiles(view, size, Math.max(0, z)).map((t) => (\n <img\n key={t.key}\n src={tileUrl(provider, t.z, t.x, t.y)}\n alt=\"\"\n data-map-tile=\"\"\n draggable={false}\n style={{\n position: 'absolute',\n left: t.left,\n top: t.top,\n width: t.width,\n height: t.height,\n maxWidth: 'none',\n pointerEvents: 'none',\n }}\n />\n ))\n )}\n <MapContext.Provider value={value}>\n <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>{children}</div>\n </MapContext.Provider>\n {!engine && (\n <div\n data-map-attribution=\"\"\n data-map-overlay=\"\"\n style={{\n position: 'absolute',\n right: 0,\n bottom: 0,\n padding: '1px 5px',\n font: '11px/1.4 system-ui, sans-serif',\n color: '#333',\n background: 'rgba(255, 255, 255, 0.8)',\n }}\n >\n {provider.attribution}\n </div>\n )}\n </section>\n )\n}\n","import type { CSSProperties, HTMLAttributes, MouseEventHandler, ReactNode } from 'react'\nimport { useMap } from './map'\nimport type { LngLat } from './projection'\n\n/** Placed at a coordinate, anchored by `transform`, hidden while the projection is unknown. */\nfunction useAnchor(lngLat: LngLat, transform: string): CSSProperties {\n const [x, y] = useMap().project(lngLat)\n return {\n position: 'absolute',\n left: 0,\n top: 0,\n transform: `translate(${x}px, ${y}px) ${transform}`,\n visibility: Number.isNaN(x) ? 'hidden' : undefined,\n }\n}\n\nconst pin = (\n <svg width=\"27\" height=\"41\" viewBox=\"0 0 27 41\" aria-hidden=\"true\" style={{ display: 'block' }}>\n <path\n d=\"M13.5 1C6.6 1 1 6.6 1 13.5 1 23 13.5 40 13.5 40S26 23 26 13.5C26 6.6 20.4 1 13.5 1Z\"\n fill=\"#e5484d\"\n stroke=\"#fff\"\n strokeWidth=\"2\"\n />\n <circle cx=\"13.5\" cy=\"13.5\" r=\"4.5\" fill=\"#fff\" />\n </svg>\n)\n\nexport interface MarkerProps {\n lngLat: LngLat\n /** The pin. Default a red drop. Its bottom center sits on the coordinate. */\n children?: ReactNode\n /** Makes the marker a button. */\n onClick?: MouseEventHandler<HTMLButtonElement>\n /** Accessible name of the button. */\n label?: string\n className?: string\n style?: CSSProperties\n}\n\n/** A pin at a coordinate. With `onClick` it is a button, else it lets the map be dragged through it. */\nexport function Marker({ lngLat, children = pin, onClick, label, className, style }: MarkerProps) {\n const anchor = { ...useAnchor(lngLat, 'translate(-50%, -100%)'), ...style }\n if (!onClick) {\n return (\n <div className={className} style={anchor}>\n {children}\n </div>\n )\n }\n return (\n <button\n type=\"button\"\n data-map-overlay=\"\"\n aria-label={label}\n onClick={onClick}\n className={className}\n style={{\n padding: 0,\n border: 0,\n background: 'none',\n cursor: 'pointer',\n pointerEvents: 'auto',\n ...anchor,\n }}\n >\n {children}\n </button>\n )\n}\n\nconst card: CSSProperties = {\n padding: '8px 12px',\n borderRadius: 8,\n background: '#fff',\n color: '#111',\n font: '14px/1.4 system-ui, sans-serif',\n boxShadow: '0 2px 12px rgba(0, 0, 0, 0.25)',\n}\n\nexport interface PopupProps extends HTMLAttributes<HTMLDivElement> {\n lngLat: LngLat\n /** Pixels between the coordinate and the popup's bottom edge. Default 44, above the default pin. */\n offset?: number\n /** Called on Escape, and by the close button it adds. */\n onClose?: () => void\n /** Accessible name of the close button. Default `'Close'`. */\n closeLabel?: string\n /** Content of the close button. Default `'×'`. */\n closeIcon?: ReactNode\n}\n\n/**\n * A box above a coordinate. Render it while it should be open. A `className` replaces its\n * default white card, so the look can come from your styles.\n */\nexport function Popup({\n lngLat,\n offset = 44,\n onClose,\n closeLabel = 'Close',\n closeIcon = '×',\n className,\n style,\n children,\n onKeyDown,\n ...props\n}: PopupProps) {\n const anchor = useAnchor(lngLat, `translate(-50%, calc(-100% - ${offset}px))`)\n return (\n <div\n role=\"dialog\"\n data-map-overlay=\"\"\n className={className}\n onKeyDown={(e) => {\n onKeyDown?.(e)\n if (e.key === 'Escape' && onClose) {\n e.stopPropagation()\n onClose()\n }\n }}\n {...props}\n style={{\n ...(className ? null : card),\n ...anchor,\n pointerEvents: 'auto',\n userSelect: 'text',\n ...style,\n }}\n >\n {onClose && (\n <button\n type=\"button\"\n aria-label={closeLabel}\n onClick={onClose}\n data-map-popup-close=\"\"\n style={\n className\n ? undefined\n : {\n float: 'right',\n margin: '-4px -6px 0 8px',\n padding: 0,\n border: 0,\n background: 'none',\n font: 'inherit',\n fontSize: 18,\n lineHeight: 1,\n cursor: 'pointer',\n color: 'inherit',\n }\n }\n >\n <span aria-hidden=\"true\" style={{ display: 'contents' }}>\n {closeIcon}\n </span>\n </button>\n )}\n {children}\n </div>\n )\n}\n\nexport interface ZoomControlProps {\n /** Default `'Zoom in'`. */\n zoomInLabel?: string\n /** Default `'Zoom out'`. */\n zoomOutLabel?: string\n className?: string\n style?: CSSProperties\n}\n\nconst zoomButton: CSSProperties = {\n display: 'block',\n width: 32,\n height: 32,\n border: 0,\n background: '#fff',\n color: '#111',\n font: '20px/1 system-ui, sans-serif',\n cursor: 'pointer',\n}\n\n/** Plus and minus buttons in the top right corner. A `className` replaces their default look. */\nexport function ZoomControl({\n zoomInLabel = 'Zoom in',\n zoomOutLabel = 'Zoom out',\n className,\n style,\n}: ZoomControlProps) {\n const map = useMap()\n const look = className ? undefined : zoomButton\n return (\n <div\n data-map-overlay=\"\"\n className={className}\n style={{\n position: 'absolute',\n top: 10,\n right: 10,\n pointerEvents: 'auto',\n ...(className\n ? null\n : { borderRadius: 6, overflow: 'hidden', boxShadow: '0 1px 6px rgba(0, 0, 0, 0.3)' }),\n ...style,\n }}\n >\n <button\n type=\"button\"\n aria-label={zoomInLabel}\n style={look}\n onClick={() => map.setView({ zoom: Math.round(map.zoom) + 1 })}\n >\n +\n </button>\n <button\n type=\"button\"\n aria-label={zoomOutLabel}\n style={look && { ...look, borderTop: '1px solid #ddd' }}\n onClick={() => map.setView({ zoom: Math.round(map.zoom) - 1 })}\n >\n −\n </button>\n </div>\n )\n}\n"],"mappings":"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"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
|
|
2
|
+
import { CSSProperties, HTMLAttributes, MouseEventHandler, ReactNode } from "react";
|
|
3
|
+
//#region src/projection.d.ts
|
|
4
|
+
/** `[longitude, latitude]` in degrees, the GeoJSON order. */
|
|
5
|
+
type LngLat = [lng: number, lat: number];
|
|
6
|
+
/** `[x, y]` in CSS pixels from the top left corner of the map. */
|
|
7
|
+
type Point = [x: number, y: number];
|
|
8
|
+
interface MapView {
|
|
9
|
+
center: LngLat;
|
|
10
|
+
zoom: number;
|
|
11
|
+
}
|
|
12
|
+
interface Tile {
|
|
13
|
+
/** Tile coordinates, `x` already wrapped around the world. */
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
z: number;
|
|
17
|
+
/** Where it goes in the map, rounded so neighbours meet without seams. */
|
|
18
|
+
left: number;
|
|
19
|
+
top: number;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
key: string;
|
|
23
|
+
}
|
|
24
|
+
export declare const TILE_SIZE = 256;
|
|
25
|
+
/** Longitude into [-180, 180), latitude into what Web Mercator can draw. */
|
|
26
|
+
export declare function normalize([lng, lat]: LngLat): LngLat;
|
|
27
|
+
/** A coordinate to pixels of the whole world at `zoom`, from its top left corner. */
|
|
28
|
+
export declare function lngLatToWorld([lng, lat]: LngLat, zoom: number): Point;
|
|
29
|
+
/** World pixels at `zoom` back to a coordinate. */
|
|
30
|
+
export declare function worldToLngLat([x, y]: Point, zoom: number): LngLat;
|
|
31
|
+
/** A coordinate to a point of a map of `size` showing `view`, on the copy of the world nearest the center. */
|
|
32
|
+
export declare function project(lngLat: LngLat, view: MapView, size: Point): Point;
|
|
33
|
+
/** A point of the map back to a coordinate. */
|
|
34
|
+
export declare function unproject(point: Point, view: MapView, size: Point): LngLat;
|
|
35
|
+
/** The view moved by `delta` pixels, the way a drag moves it. */
|
|
36
|
+
export declare function pan(view: MapView, delta: Point, size: Point): MapView;
|
|
37
|
+
/** The view at `zoom` that keeps the coordinate under `point` where it is. */
|
|
38
|
+
export declare function zoomAround(view: MapView, zoom: number, point: Point, size: Point): MapView;
|
|
39
|
+
/** The tiles of zoom level `z` that cover a map of `size` showing `view`, scaled to its fractional zoom. */
|
|
40
|
+
export declare function visibleTiles(view: MapView, size: Point, z: number): Tile[];
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/engine.d.ts
|
|
43
|
+
/**
|
|
44
|
+
* A map platform drawn in place of the built-in tiles. It owns the panning and zooming, the
|
|
45
|
+
* `<Map>` keeps the view and lays markers and popups over it with `project`.
|
|
46
|
+
*
|
|
47
|
+
* Called once per mount with the element to draw into, the starting view and a callback to
|
|
48
|
+
* report every move made on the platform's side, while it happens.
|
|
49
|
+
*/
|
|
50
|
+
type MapEngine = (container: HTMLElement, view: MapView, onMove: (view: MapView) => void) => EngineMap | Promise<EngineMap>;
|
|
51
|
+
interface EngineMap {
|
|
52
|
+
/** Move to a view the `<Map>` asks for. */
|
|
53
|
+
setView(view: MapView): void;
|
|
54
|
+
/** A coordinate to a point in CSS pixels from the container's top left corner. */
|
|
55
|
+
project(lngLat: LngLat): Point;
|
|
56
|
+
/** A point of the container back to a coordinate. */
|
|
57
|
+
unproject(point: Point): LngLat;
|
|
58
|
+
/** Tear the platform's map down. */
|
|
59
|
+
destroy(): void;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Loads a script once per `src`, resolving when it calls back the global named `callback`.
|
|
63
|
+
* Both Google and Apple announce they are ready that way.
|
|
64
|
+
*/
|
|
65
|
+
export declare function loadScript(src: string, callback: string, attributes?: Record<string, string>): Promise<void>;
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/apple.d.ts
|
|
68
|
+
interface AppleMapsOptions {
|
|
69
|
+
/** MapKit JS token, from your Apple Developer account. */
|
|
70
|
+
token: string;
|
|
71
|
+
/** Extra `mapkit.Map` constructor options, such as `colorScheme`. */
|
|
72
|
+
options?: Record<string, unknown>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Draws the map with Apple Maps (MapKit JS), loading it on first use.
|
|
76
|
+
* Create it once, outside the component, so the map is not mounted again on every render.
|
|
77
|
+
*/
|
|
78
|
+
export declare function appleMaps({ token, options }: AppleMapsOptions): MapEngine;
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/google.d.ts
|
|
81
|
+
interface GoogleMapsOptions {
|
|
82
|
+
/** Maps JavaScript API key. */
|
|
83
|
+
apiKey: string;
|
|
84
|
+
/** Extra `google.maps.MapOptions`, such as `mapId` or `disableDefaultUI`. `gestureHandling` is `'cooperative'` unless set: the wheel zooms with Ctrl or ⌘ and scrolls the page otherwise, `'greedy'` always zooms. */
|
|
85
|
+
options?: Record<string, unknown>;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Draws the map with Google Maps (Maps JavaScript API), loading it on first use.
|
|
89
|
+
* Create it once, outside the component, so the map is not mounted again on every render.
|
|
90
|
+
*/
|
|
91
|
+
export declare function googleMaps({ apiKey, options }: GoogleMapsOptions): MapEngine;
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/providers.d.ts
|
|
94
|
+
/** Any XYZ raster tile service. */
|
|
95
|
+
interface TileProvider {
|
|
96
|
+
/** Template with `{z}`, `{x}`, `{y}` and optionally `{s}` for a subdomain. */
|
|
97
|
+
url: string;
|
|
98
|
+
/** Credit the service asks for, shown in the corner of the map. */
|
|
99
|
+
attribution: ReactNode;
|
|
100
|
+
/** Deepest zoom level it serves. Default 19. */
|
|
101
|
+
maxZoom?: number;
|
|
102
|
+
/** Values for `{s}`, spread across tiles so the browser fetches in parallel. */
|
|
103
|
+
subdomains?: string[];
|
|
104
|
+
}
|
|
105
|
+
export declare const providers: {
|
|
106
|
+
osm: {
|
|
107
|
+
url: string;
|
|
108
|
+
attribution: import("react").JSX.Element;
|
|
109
|
+
maxZoom: number;
|
|
110
|
+
};
|
|
111
|
+
cartoLight: {
|
|
112
|
+
url: string;
|
|
113
|
+
attribution: import("react").JSX.Element;
|
|
114
|
+
maxZoom: number;
|
|
115
|
+
subdomains: string[];
|
|
116
|
+
};
|
|
117
|
+
cartoDark: {
|
|
118
|
+
url: string;
|
|
119
|
+
attribution: import("react").JSX.Element;
|
|
120
|
+
maxZoom: number;
|
|
121
|
+
subdomains: string[];
|
|
122
|
+
};
|
|
123
|
+
openTopoMap: {
|
|
124
|
+
url: string;
|
|
125
|
+
attribution: import("react").JSX.Element;
|
|
126
|
+
maxZoom: number;
|
|
127
|
+
subdomains: string[];
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
/** The address of one tile. */
|
|
131
|
+
export declare function tileUrl(provider: TileProvider, z: number, x: number, y: number): string;
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/map.d.ts
|
|
134
|
+
interface MapContextValue extends MapView {
|
|
135
|
+
/** Width and height of the map in CSS pixels. 0 until it has been measured. */
|
|
136
|
+
size: Point;
|
|
137
|
+
/** A coordinate to a point of the map, `[NaN, NaN]` while a platform is still loading. */
|
|
138
|
+
project(lngLat: LngLat): Point;
|
|
139
|
+
/** A point of the map back to a coordinate. */
|
|
140
|
+
unproject(point: Point): LngLat;
|
|
141
|
+
/** Move the map. What is left out stays as it is. */
|
|
142
|
+
setView(view: Partial<MapView>): void;
|
|
143
|
+
}
|
|
144
|
+
/** The map around a component: its view, the projection and `setView`, to overlay anything. */
|
|
145
|
+
export declare function useMap(): MapContextValue;
|
|
146
|
+
/**
|
|
147
|
+
* When the wheel zooms the map. `'modifier'`: with Ctrl or ⌘ held, which is also what a
|
|
148
|
+
* trackpad pinch sends, and the page scrolls otherwise. `'always'`: every wheel turn over the
|
|
149
|
+
* map zooms, and the page cannot scroll past it. `'never'`: the wheel only scrolls.
|
|
150
|
+
*/
|
|
151
|
+
type WheelZoom = 'modifier' | 'always' | 'never';
|
|
152
|
+
/** Whether a wheel event over the map should zoom it rather than scroll the page. */
|
|
153
|
+
export declare function zoomsOnWheel(mode: WheelZoom, event: Pick<WheelEvent, 'ctrlKey' | 'metaKey'>): boolean;
|
|
154
|
+
interface MapProps extends Omit<HTMLAttributes<HTMLElement>, 'children'> {
|
|
155
|
+
/** Controlled center, `[lng, lat]`. */
|
|
156
|
+
center?: LngLat;
|
|
157
|
+
/** Controlled zoom, fractional levels allowed. */
|
|
158
|
+
zoom?: number;
|
|
159
|
+
/** Starting center when uncontrolled. Default `[0, 20]`. */
|
|
160
|
+
defaultCenter?: LngLat;
|
|
161
|
+
/** Starting zoom when uncontrolled. Default 2. */
|
|
162
|
+
defaultZoom?: number;
|
|
163
|
+
/** Every move: drags, pinches, the wheel, the keyboard, the zoom buttons. */
|
|
164
|
+
onViewChange?: (view: MapView) => void;
|
|
165
|
+
/** Default 0. */
|
|
166
|
+
minZoom?: number;
|
|
167
|
+
/** Default the provider's `maxZoom`, or 22 with an engine. */
|
|
168
|
+
maxZoom?: number;
|
|
169
|
+
/**
|
|
170
|
+
* When the wheel zooms the map: `'modifier'` (default) with Ctrl or ⌘ held or a trackpad
|
|
171
|
+
* pinch, so the page scrolls past it; `'always'`; or `'never'`. Tiles only: an `engine`
|
|
172
|
+
* handles its own wheel.
|
|
173
|
+
*/
|
|
174
|
+
wheelZoom?: WheelZoom;
|
|
175
|
+
/** Where the tiles come from. Default OpenStreetMap. */
|
|
176
|
+
provider?: TileProvider;
|
|
177
|
+
/** Draw with another platform instead of tiles, like `googleMaps()` or `appleMaps()`. */
|
|
178
|
+
engine?: MapEngine;
|
|
179
|
+
/** Markers, popups, controls and anything that reads `useMap()`. */
|
|
180
|
+
children?: ReactNode;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* A slippy map of XYZ raster tiles in Web Mercator, or of another platform through `engine`.
|
|
184
|
+
* Give it a size: it fills its box and has no height of its own.
|
|
185
|
+
*/
|
|
186
|
+
export declare function Map({ center, zoom, defaultCenter, defaultZoom, onViewChange, minZoom, maxZoom, wheelZoom, provider, engine, children, style, onKeyDown, onPointerDown, onPointerMove, onPointerUp, onPointerCancel, onDoubleClick, ...props }: MapProps): import("react").JSX.Element;
|
|
187
|
+
//#endregion
|
|
188
|
+
//#region src/overlays.d.ts
|
|
189
|
+
interface MarkerProps {
|
|
190
|
+
lngLat: LngLat;
|
|
191
|
+
/** The pin. Default a red drop. Its bottom center sits on the coordinate. */
|
|
192
|
+
children?: ReactNode;
|
|
193
|
+
/** Makes the marker a button. */
|
|
194
|
+
onClick?: MouseEventHandler<HTMLButtonElement>;
|
|
195
|
+
/** Accessible name of the button. */
|
|
196
|
+
label?: string;
|
|
197
|
+
className?: string;
|
|
198
|
+
style?: CSSProperties;
|
|
199
|
+
}
|
|
200
|
+
/** A pin at a coordinate. With `onClick` it is a button, else it lets the map be dragged through it. */
|
|
201
|
+
export declare function Marker({ lngLat, children, onClick, label, className, style }: MarkerProps): import("react").JSX.Element;
|
|
202
|
+
interface PopupProps extends HTMLAttributes<HTMLDivElement> {
|
|
203
|
+
lngLat: LngLat;
|
|
204
|
+
/** Pixels between the coordinate and the popup's bottom edge. Default 44, above the default pin. */
|
|
205
|
+
offset?: number;
|
|
206
|
+
/** Called on Escape, and by the close button it adds. */
|
|
207
|
+
onClose?: () => void;
|
|
208
|
+
/** Accessible name of the close button. Default `'Close'`. */
|
|
209
|
+
closeLabel?: string;
|
|
210
|
+
/** Content of the close button. Default `'×'`. */
|
|
211
|
+
closeIcon?: ReactNode;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* A box above a coordinate. Render it while it should be open. A `className` replaces its
|
|
215
|
+
* default white card, so the look can come from your styles.
|
|
216
|
+
*/
|
|
217
|
+
export declare function Popup({ lngLat, offset, onClose, closeLabel, closeIcon, className, style, children, onKeyDown, ...props }: PopupProps): import("react").JSX.Element;
|
|
218
|
+
interface ZoomControlProps {
|
|
219
|
+
/** Default `'Zoom in'`. */
|
|
220
|
+
zoomInLabel?: string;
|
|
221
|
+
/** Default `'Zoom out'`. */
|
|
222
|
+
zoomOutLabel?: string;
|
|
223
|
+
className?: string;
|
|
224
|
+
style?: CSSProperties;
|
|
225
|
+
}
|
|
226
|
+
/** Plus and minus buttons in the top right corner. A `className` replaces their default look. */
|
|
227
|
+
export declare function ZoomControl({ zoomInLabel, zoomOutLabel, className, style }: ZoomControlProps): import("react").JSX.Element;
|
|
228
|
+
//#endregion
|
|
229
|
+
export type { AppleMapsOptions, EngineMap, GoogleMapsOptions, LngLat, MapContextValue, MapEngine, MapProps, MapView, MarkerProps, Point, PopupProps, Tile, TileProvider, WheelZoom, ZoomControlProps };
|
|
230
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/projection.ts","../src/engine.ts","../src/apple.ts","../src/google.ts","../src/providers.tsx","../src/map.tsx","../src/overlays.tsx"],"mappings":";;;;KACY,UAAU,aAAa;;KAEvB,SAAS,WAAW;UAEf;EACf,QAAQ;EACR;;UAGe;;EAEf;EACA;EACA;;EAEA;EACA;EACA;EACA;EACA;;qBAGW;;wBAQG,WAAW,KAAK,MAAM,SAAS;;wBAK/B,eAAe,KAAK,MAAM,QAAQ,eAAe;;wBAUjD,eAAe,GAAG,IAAI,OAAO,eAAe;;wBAO5C,QAAQ,QAAQ,QAAQ,MAAM,SAAS,MAAM,QAAQ;;wBASrD,UAAU,OAAO,OAAO,MAAM,SAAS,MAAM,QAAQ;;wBAQrD,IAAI,MAAM,SAAS,OAAO,OAAO,MAAM,QAAQ;;wBAQ/C,WAAW,MAAM,SAAS,cAAc,OAAO,OAAO,MAAM,QAAQ;;wBAWpE,aAAa,MAAM,SAAS,MAAM,OAAO,YAAY;;;;;;;;;;KChFzD,aACV,WAAW,aACX,MAAM,SACN,SAAS,MAAM,qBACZ,YAAY,QAAQ;UAER;;EAEf,QAAQ,MAAM;;EAEd,QAAQ,QAAQ,SAAS;;EAEzB,UAAU,OAAO,QAAQ;;EAEzB;;;;;;wBASc,WACd,aACA,kBACA,aAAY,yBACX;;;UC9Bc;;EAEf;;EAEA,UAAU;;;;;;wBAOI,YAAY,OAAO,WAAW,mBAAmB;;;UCXhD;;EAEf;;EAEA,UAAU;;;;;;wBAOI,aAAa,QAAQ,WAAW,oBAAoB;;;;UCdnD;;EAEf;;EAEA,aAAa;;EAEb;;EAEA;;qBAaW;;IAET;IACA,6BAAW,IAAA;IACX;;;IAIA;IACA,6BAAW,IAAA;IAKX;IACA;;;IAGA;IACA,6BAAW,IAAA;IAKX;IACA;;;IAGA;IACA,6BAAW,IAAA;IAKX;IACA;;;;wBAKY,QAAQ,UAAU,cAAc,WAAW,WAAW;;;UCtCrD,wBAAwB;;EAEvC,MAAM;;EAEN,QAAQ,QAAQ,SAAS;;EAEzB,UAAU,OAAO,QAAQ;;EAEzB,QAAQ,MAAM,QAAQ;;;wBAMR,UAAU;;;;;;KAWd;;wBAGI,aACd,MAAM,WACN,OAAO,KAAK;UAOG,iBAAiB,KAAK,eAAe;;EAEpD,SAAS;;EAET;;EAEA,gBAAgB;;EAEhB;;EAEA,gBAAgB,MAAM;;EAEtB;;EAEA;;;;;;EAMA,YAAY;;EAEZ,WAAW;;EAEX,SAAS;;EAET,WAAW;;;;;;wBAaG,MACd,QACA,MACA,eACA,aACA,cACA,SACA,SACA,WACA,UACA,QACA,UACA,OACA,WACA,eACA,eACA,aACA,iBACA,kBACG,SACF,2BAAQ,IAAA;;;UC9FM;EACf,QAAQ;;EAER,WAAW;;EAEX,UAAU,kBAAkB;;EAE5B;EACA;EACA,QAAQ;;;wBAIM,SAAS,QAAQ,UAAgB,SAAS,OAAO,WAAW,SAAS,8BAAW,IAAA;UAuC/E,mBAAmB,eAAe;EACjD,QAAQ;;EAER;;EAEA;;EAEA;;EAEA,YAAY;;;;;;wBAOE,QACd,QACA,QACA,SACA,YACA,WACA,WACA,OACA,UACA,cACG,SACF,6BAAU,IAAA;UAwDI;;EAEf;;EAEA;EACA;EACA,QAAQ;;;wBAeM,cACd,aACA,cACA,WACA,SACC,mCAAgB,IAAA"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
|
|
2
|
+
import { CSSProperties, HTMLAttributes, MouseEventHandler, ReactNode } from "react";
|
|
3
|
+
//#region src/projection.d.ts
|
|
4
|
+
/** `[longitude, latitude]` in degrees, the GeoJSON order. */
|
|
5
|
+
type LngLat = [lng: number, lat: number];
|
|
6
|
+
/** `[x, y]` in CSS pixels from the top left corner of the map. */
|
|
7
|
+
type Point = [x: number, y: number];
|
|
8
|
+
interface MapView {
|
|
9
|
+
center: LngLat;
|
|
10
|
+
zoom: number;
|
|
11
|
+
}
|
|
12
|
+
interface Tile {
|
|
13
|
+
/** Tile coordinates, `x` already wrapped around the world. */
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
z: number;
|
|
17
|
+
/** Where it goes in the map, rounded so neighbours meet without seams. */
|
|
18
|
+
left: number;
|
|
19
|
+
top: number;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
key: string;
|
|
23
|
+
}
|
|
24
|
+
export declare const TILE_SIZE = 256;
|
|
25
|
+
/** Longitude into [-180, 180), latitude into what Web Mercator can draw. */
|
|
26
|
+
export declare function normalize([lng, lat]: LngLat): LngLat;
|
|
27
|
+
/** A coordinate to pixels of the whole world at `zoom`, from its top left corner. */
|
|
28
|
+
export declare function lngLatToWorld([lng, lat]: LngLat, zoom: number): Point;
|
|
29
|
+
/** World pixels at `zoom` back to a coordinate. */
|
|
30
|
+
export declare function worldToLngLat([x, y]: Point, zoom: number): LngLat;
|
|
31
|
+
/** A coordinate to a point of a map of `size` showing `view`, on the copy of the world nearest the center. */
|
|
32
|
+
export declare function project(lngLat: LngLat, view: MapView, size: Point): Point;
|
|
33
|
+
/** A point of the map back to a coordinate. */
|
|
34
|
+
export declare function unproject(point: Point, view: MapView, size: Point): LngLat;
|
|
35
|
+
/** The view moved by `delta` pixels, the way a drag moves it. */
|
|
36
|
+
export declare function pan(view: MapView, delta: Point, size: Point): MapView;
|
|
37
|
+
/** The view at `zoom` that keeps the coordinate under `point` where it is. */
|
|
38
|
+
export declare function zoomAround(view: MapView, zoom: number, point: Point, size: Point): MapView;
|
|
39
|
+
/** The tiles of zoom level `z` that cover a map of `size` showing `view`, scaled to its fractional zoom. */
|
|
40
|
+
export declare function visibleTiles(view: MapView, size: Point, z: number): Tile[];
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/engine.d.ts
|
|
43
|
+
/**
|
|
44
|
+
* A map platform drawn in place of the built-in tiles. It owns the panning and zooming, the
|
|
45
|
+
* `<Map>` keeps the view and lays markers and popups over it with `project`.
|
|
46
|
+
*
|
|
47
|
+
* Called once per mount with the element to draw into, the starting view and a callback to
|
|
48
|
+
* report every move made on the platform's side, while it happens.
|
|
49
|
+
*/
|
|
50
|
+
type MapEngine = (container: HTMLElement, view: MapView, onMove: (view: MapView) => void) => EngineMap | Promise<EngineMap>;
|
|
51
|
+
interface EngineMap {
|
|
52
|
+
/** Move to a view the `<Map>` asks for. */
|
|
53
|
+
setView(view: MapView): void;
|
|
54
|
+
/** A coordinate to a point in CSS pixels from the container's top left corner. */
|
|
55
|
+
project(lngLat: LngLat): Point;
|
|
56
|
+
/** A point of the container back to a coordinate. */
|
|
57
|
+
unproject(point: Point): LngLat;
|
|
58
|
+
/** Tear the platform's map down. */
|
|
59
|
+
destroy(): void;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Loads a script once per `src`, resolving when it calls back the global named `callback`.
|
|
63
|
+
* Both Google and Apple announce they are ready that way.
|
|
64
|
+
*/
|
|
65
|
+
export declare function loadScript(src: string, callback: string, attributes?: Record<string, string>): Promise<void>;
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/apple.d.ts
|
|
68
|
+
interface AppleMapsOptions {
|
|
69
|
+
/** MapKit JS token, from your Apple Developer account. */
|
|
70
|
+
token: string;
|
|
71
|
+
/** Extra `mapkit.Map` constructor options, such as `colorScheme`. */
|
|
72
|
+
options?: Record<string, unknown>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Draws the map with Apple Maps (MapKit JS), loading it on first use.
|
|
76
|
+
* Create it once, outside the component, so the map is not mounted again on every render.
|
|
77
|
+
*/
|
|
78
|
+
export declare function appleMaps({ token, options }: AppleMapsOptions): MapEngine;
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/google.d.ts
|
|
81
|
+
interface GoogleMapsOptions {
|
|
82
|
+
/** Maps JavaScript API key. */
|
|
83
|
+
apiKey: string;
|
|
84
|
+
/** Extra `google.maps.MapOptions`, such as `mapId` or `disableDefaultUI`. `gestureHandling` is `'cooperative'` unless set: the wheel zooms with Ctrl or ⌘ and scrolls the page otherwise, `'greedy'` always zooms. */
|
|
85
|
+
options?: Record<string, unknown>;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Draws the map with Google Maps (Maps JavaScript API), loading it on first use.
|
|
89
|
+
* Create it once, outside the component, so the map is not mounted again on every render.
|
|
90
|
+
*/
|
|
91
|
+
export declare function googleMaps({ apiKey, options }: GoogleMapsOptions): MapEngine;
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/providers.d.ts
|
|
94
|
+
/** Any XYZ raster tile service. */
|
|
95
|
+
interface TileProvider {
|
|
96
|
+
/** Template with `{z}`, `{x}`, `{y}` and optionally `{s}` for a subdomain. */
|
|
97
|
+
url: string;
|
|
98
|
+
/** Credit the service asks for, shown in the corner of the map. */
|
|
99
|
+
attribution: ReactNode;
|
|
100
|
+
/** Deepest zoom level it serves. Default 19. */
|
|
101
|
+
maxZoom?: number;
|
|
102
|
+
/** Values for `{s}`, spread across tiles so the browser fetches in parallel. */
|
|
103
|
+
subdomains?: string[];
|
|
104
|
+
}
|
|
105
|
+
export declare const providers: {
|
|
106
|
+
osm: {
|
|
107
|
+
url: string;
|
|
108
|
+
attribution: import("react").JSX.Element;
|
|
109
|
+
maxZoom: number;
|
|
110
|
+
};
|
|
111
|
+
cartoLight: {
|
|
112
|
+
url: string;
|
|
113
|
+
attribution: import("react").JSX.Element;
|
|
114
|
+
maxZoom: number;
|
|
115
|
+
subdomains: string[];
|
|
116
|
+
};
|
|
117
|
+
cartoDark: {
|
|
118
|
+
url: string;
|
|
119
|
+
attribution: import("react").JSX.Element;
|
|
120
|
+
maxZoom: number;
|
|
121
|
+
subdomains: string[];
|
|
122
|
+
};
|
|
123
|
+
openTopoMap: {
|
|
124
|
+
url: string;
|
|
125
|
+
attribution: import("react").JSX.Element;
|
|
126
|
+
maxZoom: number;
|
|
127
|
+
subdomains: string[];
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
/** The address of one tile. */
|
|
131
|
+
export declare function tileUrl(provider: TileProvider, z: number, x: number, y: number): string;
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/map.d.ts
|
|
134
|
+
interface MapContextValue extends MapView {
|
|
135
|
+
/** Width and height of the map in CSS pixels. 0 until it has been measured. */
|
|
136
|
+
size: Point;
|
|
137
|
+
/** A coordinate to a point of the map, `[NaN, NaN]` while a platform is still loading. */
|
|
138
|
+
project(lngLat: LngLat): Point;
|
|
139
|
+
/** A point of the map back to a coordinate. */
|
|
140
|
+
unproject(point: Point): LngLat;
|
|
141
|
+
/** Move the map. What is left out stays as it is. */
|
|
142
|
+
setView(view: Partial<MapView>): void;
|
|
143
|
+
}
|
|
144
|
+
/** The map around a component: its view, the projection and `setView`, to overlay anything. */
|
|
145
|
+
export declare function useMap(): MapContextValue;
|
|
146
|
+
/**
|
|
147
|
+
* When the wheel zooms the map. `'modifier'`: with Ctrl or ⌘ held, which is also what a
|
|
148
|
+
* trackpad pinch sends, and the page scrolls otherwise. `'always'`: every wheel turn over the
|
|
149
|
+
* map zooms, and the page cannot scroll past it. `'never'`: the wheel only scrolls.
|
|
150
|
+
*/
|
|
151
|
+
type WheelZoom = 'modifier' | 'always' | 'never';
|
|
152
|
+
/** Whether a wheel event over the map should zoom it rather than scroll the page. */
|
|
153
|
+
export declare function zoomsOnWheel(mode: WheelZoom, event: Pick<WheelEvent, 'ctrlKey' | 'metaKey'>): boolean;
|
|
154
|
+
interface MapProps extends Omit<HTMLAttributes<HTMLElement>, 'children'> {
|
|
155
|
+
/** Controlled center, `[lng, lat]`. */
|
|
156
|
+
center?: LngLat;
|
|
157
|
+
/** Controlled zoom, fractional levels allowed. */
|
|
158
|
+
zoom?: number;
|
|
159
|
+
/** Starting center when uncontrolled. Default `[0, 20]`. */
|
|
160
|
+
defaultCenter?: LngLat;
|
|
161
|
+
/** Starting zoom when uncontrolled. Default 2. */
|
|
162
|
+
defaultZoom?: number;
|
|
163
|
+
/** Every move: drags, pinches, the wheel, the keyboard, the zoom buttons. */
|
|
164
|
+
onViewChange?: (view: MapView) => void;
|
|
165
|
+
/** Default 0. */
|
|
166
|
+
minZoom?: number;
|
|
167
|
+
/** Default the provider's `maxZoom`, or 22 with an engine. */
|
|
168
|
+
maxZoom?: number;
|
|
169
|
+
/**
|
|
170
|
+
* When the wheel zooms the map: `'modifier'` (default) with Ctrl or ⌘ held or a trackpad
|
|
171
|
+
* pinch, so the page scrolls past it; `'always'`; or `'never'`. Tiles only: an `engine`
|
|
172
|
+
* handles its own wheel.
|
|
173
|
+
*/
|
|
174
|
+
wheelZoom?: WheelZoom;
|
|
175
|
+
/** Where the tiles come from. Default OpenStreetMap. */
|
|
176
|
+
provider?: TileProvider;
|
|
177
|
+
/** Draw with another platform instead of tiles, like `googleMaps()` or `appleMaps()`. */
|
|
178
|
+
engine?: MapEngine;
|
|
179
|
+
/** Markers, popups, controls and anything that reads `useMap()`. */
|
|
180
|
+
children?: ReactNode;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* A slippy map of XYZ raster tiles in Web Mercator, or of another platform through `engine`.
|
|
184
|
+
* Give it a size: it fills its box and has no height of its own.
|
|
185
|
+
*/
|
|
186
|
+
export declare function Map({ center, zoom, defaultCenter, defaultZoom, onViewChange, minZoom, maxZoom, wheelZoom, provider, engine, children, style, onKeyDown, onPointerDown, onPointerMove, onPointerUp, onPointerCancel, onDoubleClick, ...props }: MapProps): import("react").JSX.Element;
|
|
187
|
+
//#endregion
|
|
188
|
+
//#region src/overlays.d.ts
|
|
189
|
+
interface MarkerProps {
|
|
190
|
+
lngLat: LngLat;
|
|
191
|
+
/** The pin. Default a red drop. Its bottom center sits on the coordinate. */
|
|
192
|
+
children?: ReactNode;
|
|
193
|
+
/** Makes the marker a button. */
|
|
194
|
+
onClick?: MouseEventHandler<HTMLButtonElement>;
|
|
195
|
+
/** Accessible name of the button. */
|
|
196
|
+
label?: string;
|
|
197
|
+
className?: string;
|
|
198
|
+
style?: CSSProperties;
|
|
199
|
+
}
|
|
200
|
+
/** A pin at a coordinate. With `onClick` it is a button, else it lets the map be dragged through it. */
|
|
201
|
+
export declare function Marker({ lngLat, children, onClick, label, className, style }: MarkerProps): import("react").JSX.Element;
|
|
202
|
+
interface PopupProps extends HTMLAttributes<HTMLDivElement> {
|
|
203
|
+
lngLat: LngLat;
|
|
204
|
+
/** Pixels between the coordinate and the popup's bottom edge. Default 44, above the default pin. */
|
|
205
|
+
offset?: number;
|
|
206
|
+
/** Called on Escape, and by the close button it adds. */
|
|
207
|
+
onClose?: () => void;
|
|
208
|
+
/** Accessible name of the close button. Default `'Close'`. */
|
|
209
|
+
closeLabel?: string;
|
|
210
|
+
/** Content of the close button. Default `'×'`. */
|
|
211
|
+
closeIcon?: ReactNode;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* A box above a coordinate. Render it while it should be open. A `className` replaces its
|
|
215
|
+
* default white card, so the look can come from your styles.
|
|
216
|
+
*/
|
|
217
|
+
export declare function Popup({ lngLat, offset, onClose, closeLabel, closeIcon, className, style, children, onKeyDown, ...props }: PopupProps): import("react").JSX.Element;
|
|
218
|
+
interface ZoomControlProps {
|
|
219
|
+
/** Default `'Zoom in'`. */
|
|
220
|
+
zoomInLabel?: string;
|
|
221
|
+
/** Default `'Zoom out'`. */
|
|
222
|
+
zoomOutLabel?: string;
|
|
223
|
+
className?: string;
|
|
224
|
+
style?: CSSProperties;
|
|
225
|
+
}
|
|
226
|
+
/** Plus and minus buttons in the top right corner. A `className` replaces their default look. */
|
|
227
|
+
export declare function ZoomControl({ zoomInLabel, zoomOutLabel, className, style }: ZoomControlProps): import("react").JSX.Element;
|
|
228
|
+
//#endregion
|
|
229
|
+
export type { AppleMapsOptions, EngineMap, GoogleMapsOptions, LngLat, MapContextValue, MapEngine, MapProps, MapView, MarkerProps, Point, PopupProps, Tile, TileProvider, WheelZoom, ZoomControlProps };
|
|
230
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/projection.ts","../src/engine.ts","../src/apple.ts","../src/google.ts","../src/providers.tsx","../src/map.tsx","../src/overlays.tsx"],"mappings":";;;;KACY,UAAU,aAAa;;KAEvB,SAAS,WAAW;UAEf;EACf,QAAQ;EACR;;UAGe;;EAEf;EACA;EACA;;EAEA;EACA;EACA;EACA;EACA;;qBAGW;;wBAQG,WAAW,KAAK,MAAM,SAAS;;wBAK/B,eAAe,KAAK,MAAM,QAAQ,eAAe;;wBAUjD,eAAe,GAAG,IAAI,OAAO,eAAe;;wBAO5C,QAAQ,QAAQ,QAAQ,MAAM,SAAS,MAAM,QAAQ;;wBASrD,UAAU,OAAO,OAAO,MAAM,SAAS,MAAM,QAAQ;;wBAQrD,IAAI,MAAM,SAAS,OAAO,OAAO,MAAM,QAAQ;;wBAQ/C,WAAW,MAAM,SAAS,cAAc,OAAO,OAAO,MAAM,QAAQ;;wBAWpE,aAAa,MAAM,SAAS,MAAM,OAAO,YAAY;;;;;;;;;;KChFzD,aACV,WAAW,aACX,MAAM,SACN,SAAS,MAAM,qBACZ,YAAY,QAAQ;UAER;;EAEf,QAAQ,MAAM;;EAEd,QAAQ,QAAQ,SAAS;;EAEzB,UAAU,OAAO,QAAQ;;EAEzB;;;;;;wBASc,WACd,aACA,kBACA,aAAY,yBACX;;;UC9Bc;;EAEf;;EAEA,UAAU;;;;;;wBAOI,YAAY,OAAO,WAAW,mBAAmB;;;UCXhD;;EAEf;;EAEA,UAAU;;;;;;wBAOI,aAAa,QAAQ,WAAW,oBAAoB;;;;UCdnD;;EAEf;;EAEA,aAAa;;EAEb;;EAEA;;qBAaW;;IAET;IACA,6BAAW,IAAA;IACX;;;IAIA;IACA,6BAAW,IAAA;IAKX;IACA;;;IAGA;IACA,6BAAW,IAAA;IAKX;IACA;;;IAGA;IACA,6BAAW,IAAA;IAKX;IACA;;;;wBAKY,QAAQ,UAAU,cAAc,WAAW,WAAW;;;UCtCrD,wBAAwB;;EAEvC,MAAM;;EAEN,QAAQ,QAAQ,SAAS;;EAEzB,UAAU,OAAO,QAAQ;;EAEzB,QAAQ,MAAM,QAAQ;;;wBAMR,UAAU;;;;;;KAWd;;wBAGI,aACd,MAAM,WACN,OAAO,KAAK;UAOG,iBAAiB,KAAK,eAAe;;EAEpD,SAAS;;EAET;;EAEA,gBAAgB;;EAEhB;;EAEA,gBAAgB,MAAM;;EAEtB;;EAEA;;;;;;EAMA,YAAY;;EAEZ,WAAW;;EAEX,SAAS;;EAET,WAAW;;;;;;wBAaG,MACd,QACA,MACA,eACA,aACA,cACA,SACA,SACA,WACA,UACA,QACA,UACA,OACA,WACA,eACA,eACA,aACA,iBACA,kBACG,SACF,2BAAQ,IAAA;;;UC9FM;EACf,QAAQ;;EAER,WAAW;;EAEX,UAAU,kBAAkB;;EAE5B;EACA;EACA,QAAQ;;;wBAIM,SAAS,QAAQ,UAAgB,SAAS,OAAO,WAAW,SAAS,8BAAW,IAAA;UAuC/E,mBAAmB,eAAe;EACjD,QAAQ;;EAER;;EAEA;;EAEA;;EAEA,YAAY;;;;;;wBAOE,QACd,QACA,QACA,SACA,YACA,WACA,WACA,OACA,UACA,cACG,SACF,6BAAU,IAAA;UAwDI;;EAEf;;EAEA;EACA;EACA,QAAQ;;;wBAeM,cACd,aACA,cACA,WACA,SACC,mCAAgB,IAAA"}
|