Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 54 additions & 2 deletions components/src/maplibre/Map/Map.stories.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script module lang="ts">
import { defineMeta } from '@storybook/addon-svelte-csf';
import { within, expect, userEvent, fn } from 'storybook/test';
import { within, expect, userEvent, fn, spyOn } from 'storybook/test';

import Map from './Map.svelte';
import ScaleControl from '../ScaleControl/ScaleControl.svelte';
Expand Down Expand Up @@ -142,7 +142,6 @@
name="Toggle zoom and pan"
play={async ({ canvasElement, step }) => {
const canvas = within(canvasElement);
const containerEl = canvas.getByTestId('map-container');
const toggleZoomButton = canvas.getByTestId('toggle-zoom');
const togglePanButton = canvas.getByTestId('toggle-pan');

Expand Down Expand Up @@ -231,6 +230,7 @@
</DesignTokens>
</div>
</Story>

<Story asChild name="initialBounds">
<div class="container">
<DesignTokens theme="light">
Expand All @@ -242,6 +242,58 @@
</div>
</Story>

<Story
asChild
name="Debug overlay"
play={async ({ canvasElement, step }) => {
const canvas = within(canvasElement);
const containerEl = canvas.getByTestId('map-container');

await step('debug overlay renders', async () => {
const el = containerEl.querySelector('.debug');
expect(el).toBeTruthy();
});
await step('shows correct location', async () => {
const el = containerEl.querySelector('.debug-location');
expect(el).toHaveTextContent('[51.30, 10.20]');
});
await step('shows correct zoom', async () => {
const el = containerEl.querySelector('.debug-zoom');
expect(el).toHaveTextContent('zoom=5');
});
await step('shows correct bearing', async () => {
const el = containerEl.querySelector('.debug-bearing');
expect(el).toHaveTextContent('bearing=0');
});
await step('shows correct pitch', async () => {
const el = containerEl.querySelector('.debug-pitch');
expect(el).toHaveTextContent('pitch=0');
});
await step('copy location button yields correct result', async () => {
const spy = spyOn(navigator.clipboard, 'writeText');
const el = canvas.getByText('Copy Location');
el.click();
expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledWith('{"lng":10.2,"lat":51.3,"zoom":5,"pitch":0,"bearing":0}');
});
await step('copy bounds button yields correct result', async () => {
const spy = spyOn(navigator.clipboard, 'writeText');
const el = canvas.getByText('Copy Bounds');
el.click();
expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledWith('[["3.608","48.470"],["16.792","53.966"]]');
});
}}
>
<div class="container" style:width="600px" style:height="400px">
<DesignTokens theme="light">
<Map showDebug style={SWRDataLabLight()} initialLocation={{ lat: 51.3, lng: 10.2, zoom: 5 }}>
<AttributionControl />
</Map>
</DesignTokens>
</div>
</Story>

<Story asChild name="Alternate Style">
<div class="container">
<DesignTokens theme="dark">
Expand Down
55 changes: 37 additions & 18 deletions components/src/maplibre/Map/Map.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import maplibre, {
type LngLatBoundsLike,
type LngLatLike,
type MapLibreEvent,
type ProjectionSpecification,
type StyleSpecification
Expand Down Expand Up @@ -31,6 +32,7 @@
center?: maplibre.LngLat;
pitch?: number;
bearing?: number;
bounds?: LngLatBounds;
loading?: boolean;
projection?: ProjectionSpecification;
showDebug?: boolean;
Expand Down Expand Up @@ -59,6 +61,7 @@
center = $bindable(),
pitch = $bindable(0),
bearing = $bindable(0),
bounds = $bindable(),
loading = $bindable(true),
projection = { type: 'mercator' },
allowPan = true,
Expand All @@ -85,7 +88,7 @@
// 2. initialLocation prop
// 3. initialLocation context (notably set by <WithLinkLocation/>)

let contextLocation: Location = getContext('initialLocation');
let contextLocation: Partial<Location> = getContext('initialLocation');

let initialLocation = $derived({
lat: 51.3,
Expand Down Expand Up @@ -119,13 +122,15 @@
center = mapContext.map?.getCenter();
pitch = mapContext.map?.getPitch() || 0;
bearing = mapContext.map?.getBearing() || 0;
bounds = mapContext.map?.getBounds();
});

mapContext.map.on('moveend', () => {
zoom = mapContext.map?.getZoom();
center = mapContext.map?.getCenter();
pitch = mapContext.map?.getPitch() || 0;
bearing = mapContext.map?.getBearing() || 0;
bounds = mapContext.map?.getBounds();
});

if (onmoveend) {
Expand Down Expand Up @@ -178,7 +183,9 @@
}
});

const debugValues = $derived(Object.entries({ zoom, pitch, bearing, allowZoom, allowPan, allowRotation }));
const debugValues = $derived(
Object.entries({ zoom, pitch, bearing, allowZoom, allowPan, allowRotation })
);
const handleDebugValueClick = (e: MouseEvent) => {
if (e.target) {
const t = e.target as HTMLElement;
Expand All @@ -192,6 +199,14 @@
navigator.clipboard.writeText(s);
}
};
const handleDebugCopyBoundsClick = (e: MouseEvent) => {
if (e.target) {
const s = JSON.stringify(
bounds.toArray().map((ll: [number, number]) => ll.map((c: number) => c.toFixed(3)))
);
navigator.clipboard.writeText(s);
}
};
</script>

<div bind:this={container} class="container" data-testid="map-container">
Expand All @@ -201,19 +216,24 @@
{/if}
{/if}
{#if showDebug}
<ul class="debug">
<li>
[{center?.lat.toFixed(2)}, {center?.lng.toFixed(2)}]
</li>
{#each debugValues as [key, value]}
<li>
{key}=<button onclick={handleDebugValueClick}
>{value?.toLocaleString('en', { maximumSignificantDigits: 6 })}</button
>
<div class="debug">
<ul>
<li class="debug-location">
[{center?.lat.toFixed(2)}, {center?.lng.toFixed(2)}]
</li>
{/each}
<li><button onclick={handleDebugCopyLocationClick}>[Copy Location]</button></li>
</ul>
{#each debugValues as [key, value]}
<li class={`debug-${key}`}>
{key}=<button onclick={handleDebugValueClick}
>{value?.toLocaleString('en', { maximumSignificantDigits: 6 })}</button
>
</li>
{/each}
</ul>
<ul>
<li><button onclick={handleDebugCopyLocationClick}>Copy Location</button></li>
<li><button onclick={handleDebugCopyBoundsClick}>Copy Bounds</button></li>
</ul>
</div>
{/if}
</div>

Expand All @@ -227,17 +247,16 @@
position: absolute;
top: 0;
background: rgba(0, 0, 0, 0.75);
color: white;
color: #eee;
z-index: 1000;
padding: 2px;
padding: 4px;
font-size: 10px;
font-family: monospace;
display: flex;
flex-flow: column;
@media (min-width: 600px) {
gap: 1em;
gap: 0.5em;
right: 0;
flex-flow: row;
}
li {
list-style: none;
Expand Down
Loading