@swr-data-lab/components 2.43.2 → 3.0.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.
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">import maplibre, {} from 'maplibre-gl';
2
+ import {} from '../types';
2
3
  import { onMount, onDestroy, getContext, hasContext } from 'svelte';
3
4
  import { createMapContext, MapContext } from '../context.svelte.js';
4
- import {} from '../types';
5
5
  import FallbackStyle from './FallbackStyle';
6
6
  import { de } from './locale';
7
7
  let { children, options, style = FallbackStyle, minZoom = 0, maxZoom = 14.99, zoom = $bindable(), center = $bindable(), pitch = $bindable(0), bearing = $bindable(0), loading = $bindable(true), projection = { type: 'mercator' }, allowPan = true, allowRotation = false, allowZoom = true, showDebug = false, cursor, initialBounds, maxBounds, initialLocation: receivedInitialLocation,
@@ -9,19 +9,20 @@ let { children, options, style = FallbackStyle, minZoom = 0, maxZoom = 14.99, zo
9
9
  // available, see: https://github.com/sveltejs/svelte/issues/7712
10
10
  mapContext = $bindable(), cooperativeGestures = false, onmoveend, onmovestart } = $props();
11
11
  let container;
12
- // Merge initial location with default object so individual
13
- // properties (like pitch) can be omitted by the caller
14
- let initialLocation = {
12
+ mapContext = createMapContext();
13
+ // Initial location is determined by (in order of precedence) :
14
+ // 1. An arbitrary default location
15
+ // 2. initialLocation prop
16
+ // 3. initialLocation context (notably set by <WithLinkLocation/>)
17
+ let contextLocation = getContext('initialLocation');
18
+ let initialLocation = $derived({
15
19
  lat: 51.3,
16
20
  lng: 10.2,
17
21
  zoom: 5,
18
22
  pitch: 0,
19
- ...receivedInitialLocation
20
- };
21
- mapContext = createMapContext();
22
- if (getContext('initialLocation') !== undefined && getContext('initialLocation') !== false) {
23
- initialLocation = getContext('initialLocation');
24
- }
23
+ ...receivedInitialLocation,
24
+ ...contextLocation
25
+ });
25
26
  onMount(() => {
26
27
  mapContext.map = new maplibre.Map({
27
28
  container,
@@ -76,6 +77,12 @@ $effect(() => {
76
77
  mapContext.map?.setProjection(projection);
77
78
  }
78
79
  });
80
+ $effect(() => {
81
+ mapContext.map?.jumpTo({
82
+ center: [initialLocation.lng, initialLocation.lat],
83
+ zoom: initialLocation.zoom
84
+ });
85
+ });
79
86
  $effect(() => {
80
87
  if (allowZoom === false) {
81
88
  mapContext.map?.scrollZoom.disable();
@@ -1,7 +1,7 @@
1
1
  import maplibre, { type LngLatBoundsLike, type MapLibreEvent, type ProjectionSpecification, type StyleSpecification } from 'maplibre-gl';
2
+ import { type Location } from '../types';
2
3
  import { type Snippet } from 'svelte';
3
4
  import { MapContext } from '../context.svelte.js';
4
- import { type Location } from '../types';
5
5
  interface MapProps {
6
6
  style?: StyleSpecification | string;
7
7
  /**
@@ -24,7 +24,7 @@ interface MapProps {
24
24
  showDebug?: boolean;
25
25
  options?: any;
26
26
  /**
27
- * Set the mouse cursor. `""` (empty string) restores Maplibre's default behaviour. See VectorLayer/Default for a common usage example
27
+ * Set the mouse cursor. `""` (empty string) restores Maplibre's default behaviour. See VectorLayer/Default for a usage example
28
28
  */
29
29
  cursor?: string;
30
30
  mapContext?: MapContext;
@@ -31,6 +31,12 @@ $effect(() => {
31
31
  map.addLayer(layerSpec, beforeId);
32
32
  }
33
33
  });
34
+ // Make filter reactive
35
+ $effect(() => {
36
+ if (styleLoaded && filter) {
37
+ map?.setFilter(id, filter);
38
+ }
39
+ });
34
40
  $effect(() => resetLayerEventListener(map, 'click', id, onclick));
35
41
  $effect(() => resetLayerEventListener(map, 'mousemove', id, onmousemove));
36
42
  $effect(() => resetLayerEventListener(map, 'mouseleave', id, onmouseleave));
@@ -1,4 +1,4 @@
1
- import { type CircleLayoutProps, type CirclePaintProps, type FillLayoutProps, type FillPaintProps, type LineLayoutProps, type SymbolPaintProps, type SymbolLayoutProps, type LinePaintProps, type MapGeoJSONFeature, type MapLayerMouseEvent } from 'maplibre-gl';
1
+ import { type CircleLayoutProps, type CirclePaintProps, type FillLayoutProps, type FillPaintProps, type LineLayoutProps, type SymbolPaintProps, type SymbolLayoutProps, type LinePaintProps, type MapGeoJSONFeature, type MapLayerMouseEvent, type FilterSpecification } from 'maplibre-gl';
2
2
  interface VectorLayerProps {
3
3
  id: string;
4
4
  sourceId: string;
@@ -6,7 +6,7 @@ interface VectorLayerProps {
6
6
  /**
7
7
  * Maplibre [filter expression](https://maplibre.org/maplibre-style-spec/layers/#filter)
8
8
  */
9
- filter?: any[];
9
+ filter?: FilterSpecification;
10
10
  type: 'line' | 'fill' | 'circle' | 'symbol';
11
11
  placeBelow?: string;
12
12
  visible?: boolean;
@@ -1,13 +1,16 @@
1
1
  <script lang="ts">import {} from 'maplibre-gl';
2
2
  import MapSource from '../Source/MapSource.svelte';
3
- const { minZoom = 0, maxZoom = 24, id, url, attribution = '' } = $props();
4
- const sourceSpec = {
3
+ import fetchTileJSON from './fetchTileJson';
4
+ const { minZoom, maxZoom, id, url, tiles, attribution, promoteId } = $props();
5
+ let tileJsonData = $derived(url ? await fetchTileJSON(url) : {});
6
+ const sourceSpec = $derived({
5
7
  type: 'vector',
6
- tiles: [url],
7
- maxzoom: maxZoom,
8
- minzoom: minZoom,
9
- attribution
10
- };
8
+ tiles: tiles || tileJsonData.tiles || [],
9
+ maxzoom: maxZoom || tileJsonData.maxZoom || 24,
10
+ minzoom: minZoom || tileJsonData.minZoom || 0,
11
+ attribution: attribution || tileJsonData.attribution || '',
12
+ promoteId
13
+ });
11
14
  </script>
12
15
 
13
16
  <MapSource {id} {sourceSpec} />
@@ -1,12 +1,15 @@
1
+ import { type PromoteIdSpecification } from 'maplibre-gl';
1
2
  interface VectorTileSourceProps {
2
3
  id: string;
3
- url: string;
4
+ url?: string;
5
+ tiles?: string[];
4
6
  minZoom?: number;
5
7
  maxZoom?: number;
6
8
  /**
7
- * Attribution string for your data, usually rendered using an `<AttributionControl>`
9
+ * Attribution string for your data, usually rendered using an `<AttributionControl/>`
8
10
  */
9
11
  attribution?: string;
12
+ promoteId?: PromoteIdSpecification;
10
13
  }
11
14
  declare const VectorTileSource: import("svelte").Component<VectorTileSourceProps, {}, "">;
12
15
  type VectorTileSource = ReturnType<typeof VectorTileSource>;
@@ -0,0 +1,2 @@
1
+ import { type TileJsonData } from './types';
2
+ export default function fetchTileJSON(url: string): Promise<TileJsonData>;
@@ -0,0 +1,16 @@
1
+ import {} from './types';
2
+ // Workaround for https://github.com/versatiles-org/versatiles-rs/issues/184
3
+ // Drop when/if this lands: https://github.com/maplibre/maplibre-gl-js/issues/182
4
+ export default async function fetchTileJSON(url) {
5
+ const u = new URL(url);
6
+ const res = await fetch(u);
7
+ const data = await res.json();
8
+ // Simple heuristic for absolute URLs
9
+ const re = /(((http)s?)):\/\/.*/gi;
10
+ return {
11
+ tiles: data?.tiles.map((path) => (re.test(path) ? path : `${u.origin}${path}`)),
12
+ attribution: data?.attribution || data?.author,
13
+ minZoom: data?.minzoom,
14
+ maxZoom: data?.maxzoom
15
+ };
16
+ }
@@ -0,0 +1,7 @@
1
+ interface TileJsonData {
2
+ tiles?: string[];
3
+ attribution?: string;
4
+ minZoom?: number;
5
+ maxZoom?: number;
6
+ }
7
+ export { type TileJsonData };
@@ -0,0 +1 @@
1
+ export {};
@@ -8,11 +8,11 @@ let geocoder;
8
8
  if (service === 'maptiler') {
9
9
  geocoder = new MaptilerGeocoderAPI(key);
10
10
  }
11
- let location = $state();
11
+ let location = $state({});
12
12
  function bboxToArea(bbox) {
13
13
  return (bbox[2] - bbox[0]) * (bbox[3] - bbox[1]);
14
14
  }
15
- onMount(async () => {
15
+ $effect(async () => {
16
16
  const params = new URLSearchParams(window.location.search);
17
17
  if (params.has(urlParameter)) {
18
18
  const config = {
@@ -23,22 +23,17 @@ onMount(async () => {
23
23
  };
24
24
  const res = await geocoder.forwardGeocode(config);
25
25
  if (res.features[0].bbox && res.features[0].geometry.type === 'Point') {
26
- location = {
27
- lat: res.features[0].geometry.coordinates[1],
28
- lng: res.features[0].geometry.coordinates[0],
29
- zoom: 11 - bboxToArea(res.features[0].bbox) * 5.5
30
- };
26
+ location.lat = res.features[0].geometry.coordinates[1];
27
+ location.lng = res.features[0].geometry.coordinates[0];
28
+ location.zoom = 11 - bboxToArea(res.features[0].bbox) * 5.5;
29
+ location.active = true;
31
30
  }
32
31
  }
33
32
  else {
34
- location = false;
33
+ location = {};
35
34
  }
36
35
  });
37
- $effect.pre(() => {
38
- setContext('initialLocation', location);
39
- });
36
+ setContext('initialLocation', location);
40
37
  </script>
41
38
 
42
- {#if location !== undefined}
43
- {@render children?.()}
44
- {/if}
39
+ {@render children?.()}
@@ -10,7 +10,13 @@ interface WithLinkLocationProps {
10
10
  * Limit search to one or more countries
11
11
  */
12
12
  countries?: GeocodingLanguage | GeocodingCountry[];
13
+ /**
14
+ * Limit search to one or more languages
15
+ */
13
16
  languages?: GeocodingLanguage | GeocodingLanguage[];
17
+ /**
18
+ * Customise the URL parameter used to set the initial location
19
+ */
14
20
  urlParameter?: string;
15
21
  children: Snippet;
16
22
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@swr-data-lab/components",
3
3
  "description": "SWR Data Lab component library",
4
- "version": "2.43.2",
4
+ "version": "3.0.0",
5
5
  "author": "SWR Data Lab",
6
6
  "license": "UNLICENSED",
7
7
  "type": "module",
@@ -41,16 +41,16 @@
41
41
  "devDependencies": {
42
42
  "@semantic-release/changelog": "6.0.3",
43
43
  "@semantic-release/git": "10.0.1",
44
- "@semantic-release/npm": "13.1.3",
45
- "@storybook/addon-docs": "10.2.7",
46
- "@storybook/addon-links": "10.2.7",
47
- "@storybook/addon-svelte-csf": "^5.0.10",
48
- "@storybook/addon-vitest": "10.2.7",
49
- "@storybook/sveltekit": "10.2.7",
44
+ "@semantic-release/npm": "13.1.5",
45
+ "@storybook/addon-docs": "10.2.13",
46
+ "@storybook/addon-links": "10.2.13",
47
+ "@storybook/addon-svelte-csf": "^5.0.11",
48
+ "@storybook/addon-vitest": "10.2.13",
49
+ "@storybook/sveltekit": "10.2.13",
50
50
  "@storybook/test-runner": "^0.24.2",
51
- "@sveltejs/adapter-auto": "7.0.0",
52
- "@sveltejs/enhanced-img": "0.9.3",
53
- "@sveltejs/kit": "2.50.1",
51
+ "@sveltejs/adapter-auto": "7.0.1",
52
+ "@sveltejs/enhanced-img": "0.10.3",
53
+ "@sveltejs/kit": "2.53.4",
54
54
  "@sveltejs/package": "2.5.7",
55
55
  "@sveltejs/vite-plugin-svelte": "6.2.4",
56
56
  "@types/geojson": "7946.0.16",
@@ -69,8 +69,8 @@
69
69
  "sass": "1.93.2",
70
70
  "sass-embedded": "1.97.3",
71
71
  "semantic-release": "25.0.3",
72
- "storybook": "10.2.7",
73
- "svelte": "5.49.1",
72
+ "storybook": "10.2.13",
73
+ "svelte": "5.53.5",
74
74
  "svelte-check": "4.3.2",
75
75
  "svelte-preprocess": "6.0.3",
76
76
  "typescript": "5.9.3",