@versatiles/svelte 0.2.0 → 0.3.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.
Files changed (36) hide show
  1. package/README.md +16 -4
  2. package/dist/components/AutoComplete.svelte +4 -5
  3. package/dist/components/BBoxMap/BBoxMap.d.ts +1 -12
  4. package/dist/components/BBoxMap/BBoxMap.js +1 -200
  5. package/dist/components/BBoxMap/BBoxMap.svelte +19 -92
  6. package/dist/components/BBoxMap/BBoxMap.svelte.d.ts +2 -5
  7. package/dist/components/BasicMap/BasicMap.svelte +1 -1
  8. package/dist/components/LocatorMap/LocatorMap.svelte +34 -0
  9. package/dist/components/LocatorMap/LocatorMap.svelte.d.ts +19 -0
  10. package/dist/index.d.ts +2 -1
  11. package/dist/index.js +2 -1
  12. package/dist/utils/draw/abstract.d.ts +5 -0
  13. package/dist/utils/draw/abstract.js +2 -0
  14. package/dist/utils/draw/bbox.d.ts +35 -0
  15. package/dist/utils/draw/bbox.js +198 -0
  16. package/dist/utils/draw/marker.d.ts +24 -0
  17. package/dist/utils/draw/marker.js +97 -0
  18. package/dist/utils/draw/style.d.ts +19 -0
  19. package/dist/utils/draw/style.js +40 -0
  20. package/dist/utils/location.d.ts +2 -1
  21. package/dist/utils/location.js +19 -10
  22. package/dist/utils/sprite_library.d.ts +19 -0
  23. package/dist/utils/sprite_library.js +30 -0
  24. package/package.json +12 -10
  25. package/dist/components/BBoxMap/README.md +0 -70
  26. package/dist/components/BBoxMap/data/countries.jsonl +0 -258
  27. package/dist/components/BBoxMap/data/eu.jsonl +0 -1876
  28. package/dist/components/BBoxMap/data/us.jsonl +0 -52
  29. package/dist/components/BBoxMap/data/world.jsonl +0 -7
  30. package/dist/components/BBoxMap/helpers/geojson2bboxes.d.ts +0 -2
  31. package/dist/components/BBoxMap/helpers/geojson2bboxes.js +0 -183
  32. package/dist/components/BBoxMap/helpers/merge_bboxes.d.ts +0 -2
  33. package/dist/components/BBoxMap/helpers/merge_bboxes.js +0 -84
  34. package/dist/components/BBoxMap/helpers/population.raw.br +0 -0
  35. /package/dist/utils/{style.d.ts → map_style.d.ts} +0 -0
  36. /package/dist/utils/{style.js → map_style.js} +0 -0
@@ -0,0 +1,198 @@
1
+ import { AbstractDrawer } from './abstract.js';
2
+ import { getFillStyle, getLineStyle } from './style.js';
3
+ const maplibregl = await import('maplibre-gl');
4
+ const { LngLatBounds } = maplibregl;
5
+ // prettier-ignore
6
+ export const DragPointMap = new Map([
7
+ ['n', { cursor: 'ns-resize', flipH: 'n', flipV: 's' }],
8
+ ['ne', { cursor: 'nesw-resize', flipH: 'n', flipV: 'se' }],
9
+ ['e', { cursor: 'ew-resize', flipH: 'w', flipV: 'e' }],
10
+ ['se', { cursor: 'nwse-resize', flipH: 'sw', flipV: 'ne' }],
11
+ ['s', { cursor: 'ns-resize', flipH: 's', flipV: 'n' }],
12
+ ['sw', { cursor: 'nesw-resize', flipH: 'se', flipV: 'nw' }],
13
+ ['w', { cursor: 'ew-resize', flipH: 'e', flipV: 'w' }],
14
+ ['nw', { cursor: 'nwse-resize', flipH: 'ne', flipV: 'sw' }],
15
+ [false, { cursor: 'default', flipH: false, flipV: false }],
16
+ ]);
17
+ const worldBBox = [-180, -85, 180, 85];
18
+ export class BBoxDrawer extends AbstractDrawer {
19
+ source;
20
+ dragPoint = false;
21
+ isDragging = false;
22
+ map;
23
+ canvas;
24
+ fillStyle;
25
+ lineStyle;
26
+ inverted;
27
+ bbox;
28
+ constructor(map, options) {
29
+ super();
30
+ this.bbox = options?.bbox ?? worldBBox;
31
+ this.fillStyle = getFillStyle(options);
32
+ this.lineStyle = getLineStyle(options);
33
+ this.inverted = options?.inverted ?? true;
34
+ this.map = map;
35
+ const sourceId = 'bbox_' + Math.random().toString(36).slice(2);
36
+ if (this.source)
37
+ throw new Error('BBoxDrawer already added to map');
38
+ map.addSource(sourceId, { type: 'geojson', data: this.getAsFeatureCollection() });
39
+ map.addLayer({
40
+ id: 'bbox-line_' + Math.random().toString(36).slice(2),
41
+ type: 'line',
42
+ source: sourceId,
43
+ filter: ['==', '$type', 'LineString'],
44
+ ...this.lineStyle
45
+ });
46
+ map.addLayer({
47
+ id: 'bbox-fill_' + Math.random().toString(36).slice(2),
48
+ type: 'fill',
49
+ source: sourceId,
50
+ filter: ['==', '$type', 'Polygon'],
51
+ ...this.fillStyle
52
+ });
53
+ this.source = map.getSource(sourceId);
54
+ this.canvas = map.getCanvasContainer();
55
+ map.on('mousemove', (e) => {
56
+ if (e.originalEvent.buttons % 2 === 0)
57
+ return this.checkDragPointAt(e.point);
58
+ if (!this.isDragging)
59
+ return;
60
+ if (!this.dragPoint)
61
+ return this.checkDragPointAt(e.point);
62
+ this.doDrag(e.lngLat);
63
+ this.redraw();
64
+ e.preventDefault();
65
+ });
66
+ map.on('mousedown', (e) => {
67
+ if (this.isDragging)
68
+ return;
69
+ if (e.originalEvent.buttons % 2) {
70
+ this.checkDragPointAt(e.point);
71
+ if (this.dragPoint)
72
+ this.isDragging = true;
73
+ if (this.isDragging)
74
+ e.preventDefault();
75
+ }
76
+ });
77
+ map.on('mouseup', () => {
78
+ this.isDragging = false;
79
+ this.updateDragPoint(false);
80
+ });
81
+ }
82
+ updateDragPoint(dragPoint) {
83
+ if (this.dragPoint === dragPoint)
84
+ return;
85
+ this.dragPoint = dragPoint;
86
+ this.canvas.style.cursor = this.getCursor(dragPoint);
87
+ }
88
+ getAsFeatureCollection() {
89
+ const ring = getRing(this.bbox);
90
+ return {
91
+ type: 'FeatureCollection',
92
+ features: [
93
+ this.inverted ? polygon(getRing(worldBBox), ring) : polygon(ring),
94
+ linestring(ring)
95
+ ]
96
+ };
97
+ function getRing(bbox) {
98
+ const x0 = Math.min(bbox[0], bbox[2]);
99
+ const x1 = Math.max(bbox[0], bbox[2]);
100
+ const y0 = Math.min(bbox[1], bbox[3]);
101
+ const y1 = Math.max(bbox[1], bbox[3]);
102
+ // prettier-ignore
103
+ return [[x0, y0], [x1, y0], [x1, y1], [x0, y1], [x0, y0]];
104
+ }
105
+ function polygon(...coordinates) {
106
+ return { type: 'Feature', geometry: { type: 'Polygon', coordinates }, properties: {} };
107
+ }
108
+ function linestring(coordinates) {
109
+ return { type: 'Feature', geometry: { type: 'LineString', coordinates }, properties: {} };
110
+ }
111
+ }
112
+ setGeometry(bbox) {
113
+ this.bbox = bbox.slice(0, 4);
114
+ this.redraw();
115
+ }
116
+ getBounds() {
117
+ return new LngLatBounds(this.bbox);
118
+ }
119
+ redraw() {
120
+ this.source?.setData(this.getAsFeatureCollection());
121
+ }
122
+ getAsPixel() {
123
+ const p0 = this.map.project([this.bbox[0], this.bbox[1]]);
124
+ const p1 = this.map.project([this.bbox[2], this.bbox[3]]);
125
+ return [Math.min(p0.x, p1.x), Math.min(p0.y, p1.y), Math.max(p0.x, p1.x), Math.max(p0.y, p1.y)];
126
+ }
127
+ checkDragPointAt(point) {
128
+ const maxDistance = 5;
129
+ const { x, y } = point;
130
+ const [x0, y0, x1, y1] = this.getAsPixel();
131
+ // Don't think outside the box
132
+ if (x < x0 - maxDistance)
133
+ return this.updateDragPoint(false);
134
+ if (x > x1 + maxDistance)
135
+ return this.updateDragPoint(false);
136
+ if (y < y0 - maxDistance)
137
+ return this.updateDragPoint(false);
138
+ if (y > y1 + maxDistance)
139
+ return this.updateDragPoint(false);
140
+ let dragX = (Math.abs(x0 - x) < maxDistance ? 1 : 0) + (Math.abs(x1 - x) < maxDistance ? 2 : 0);
141
+ let dragY = (Math.abs(y0 - y) < maxDistance ? 1 : 0) + (Math.abs(y1 - y) < maxDistance ? 2 : 0);
142
+ if (dragX === 3)
143
+ dragX = Math.abs(x0 - x) < Math.abs(x1 - x) ? 1 : 2;
144
+ if (dragY === 3)
145
+ dragY = Math.abs(y0 - y) < Math.abs(y1 - y) ? 1 : 2;
146
+ const directions = [false, 'w', 'e', 'n', 'nw', 'ne', 's', 'sw', 'se'];
147
+ this.updateDragPoint(directions[dragX + dragY * 3]);
148
+ }
149
+ getCursor(drag) {
150
+ return DragPointMap.get(drag)?.cursor ?? 'default';
151
+ }
152
+ doDrag(lngLat) {
153
+ const x = Math.round(lngLat.lng * 1e3) / 1e3;
154
+ const y = Math.round(lngLat.lat * 1e3) / 1e3;
155
+ // prettier-ignore
156
+ switch (this.dragPoint) {
157
+ case 'n':
158
+ this.bbox[3] = y;
159
+ break;
160
+ case 'ne':
161
+ this.bbox[2] = x;
162
+ this.bbox[3] = y;
163
+ break;
164
+ case 'e':
165
+ this.bbox[2] = x;
166
+ break;
167
+ case 'se':
168
+ this.bbox[2] = x;
169
+ this.bbox[1] = y;
170
+ break;
171
+ case 's':
172
+ this.bbox[1] = y;
173
+ break;
174
+ case 'sw':
175
+ this.bbox[0] = x;
176
+ this.bbox[1] = y;
177
+ break;
178
+ case 'w':
179
+ this.bbox[0] = x;
180
+ break;
181
+ case 'nw':
182
+ this.bbox[0] = x;
183
+ this.bbox[3] = y;
184
+ break;
185
+ default: return;
186
+ }
187
+ if (this.bbox[2] < this.bbox[0]) {
188
+ // flip horizontal
189
+ this.bbox = [this.bbox[2], this.bbox[1], this.bbox[0], this.bbox[3]];
190
+ this.updateDragPoint(DragPointMap.get(this.dragPoint)?.flipH ?? false);
191
+ }
192
+ if (this.bbox[3] < this.bbox[1]) {
193
+ // flip vertical
194
+ this.bbox = [this.bbox[0], this.bbox[3], this.bbox[2], this.bbox[1]];
195
+ this.updateDragPoint(DragPointMap.get(this.dragPoint)?.flipV ?? false);
196
+ }
197
+ }
198
+ }
@@ -0,0 +1,24 @@
1
+ import type geojson from 'geojson';
2
+ import type { SymbolStyle } from './style.js';
3
+ import { AbstractDrawer } from './abstract.js';
4
+ export type Point = [number, number];
5
+ export declare class MarkerDrawer extends AbstractDrawer<geojson.BBox> {
6
+ private source?;
7
+ private isDragging;
8
+ private dragPoint;
9
+ private map;
10
+ private canvas;
11
+ private symbolStyle;
12
+ private point;
13
+ constructor(map: maplibregl.Map, options?: {
14
+ point?: Point;
15
+ } & SymbolStyle);
16
+ private updateDragPoint;
17
+ private getAsFeatureCollection;
18
+ setGeometry(point: geojson.Position): void;
19
+ getBounds(): maplibregl.LngLatBounds;
20
+ private redraw;
21
+ private getAsPixel;
22
+ private checkDragPointAt;
23
+ private doDrag;
24
+ }
@@ -0,0 +1,97 @@
1
+ import { AbstractDrawer } from './abstract.js';
2
+ import { getSymbolStyle } from './style.js';
3
+ const maplibregl = await import('maplibre-gl');
4
+ const { LngLatBounds } = maplibregl;
5
+ export class MarkerDrawer extends AbstractDrawer {
6
+ source;
7
+ isDragging = false;
8
+ dragPoint = false;
9
+ map;
10
+ canvas;
11
+ symbolStyle;
12
+ point;
13
+ constructor(map, options) {
14
+ super();
15
+ this.point = options?.point ?? [0, 0];
16
+ this.symbolStyle = getSymbolStyle(options);
17
+ this.map = map;
18
+ const sourceId = 'marker_' + Math.random().toString(36).slice(2);
19
+ if (this.source)
20
+ throw new Error('BBoxDrawer already added to map');
21
+ map.addSource(sourceId, { type: 'geojson', data: this.getAsFeatureCollection() });
22
+ map.addLayer({
23
+ id: 'marker_' + Math.random().toString(36).slice(2),
24
+ type: 'symbol',
25
+ source: sourceId,
26
+ filter: ['==', '$type', 'Point'],
27
+ ...this.symbolStyle
28
+ });
29
+ this.source = map.getSource(sourceId);
30
+ this.canvas = map.getCanvasContainer();
31
+ map.on('mousemove', (e) => {
32
+ if (e.originalEvent.buttons % 2 === 0)
33
+ return this.checkDragPointAt(e.point);
34
+ if (!this.isDragging)
35
+ return;
36
+ if (!this.dragPoint)
37
+ return this.checkDragPointAt(e.point);
38
+ this.doDrag(e.lngLat);
39
+ this.redraw();
40
+ e.preventDefault();
41
+ });
42
+ map.on('mousedown', (e) => {
43
+ if (this.isDragging)
44
+ return;
45
+ if (e.originalEvent.buttons % 2) {
46
+ this.checkDragPointAt(e.point);
47
+ if (this.dragPoint)
48
+ this.isDragging = true;
49
+ if (this.isDragging)
50
+ e.preventDefault();
51
+ }
52
+ });
53
+ map.on('mouseup', () => {
54
+ this.isDragging = false;
55
+ this.updateDragPoint(false);
56
+ });
57
+ }
58
+ updateDragPoint(dragPoint) {
59
+ if (this.dragPoint === dragPoint)
60
+ return;
61
+ this.dragPoint = dragPoint;
62
+ this.canvas.style.cursor = dragPoint ? 'move' : 'default';
63
+ }
64
+ getAsFeatureCollection() {
65
+ return {
66
+ type: 'FeatureCollection',
67
+ features: [getPoint(this.point)]
68
+ };
69
+ function getPoint(coordinates) {
70
+ return { type: 'Feature', geometry: { type: 'Point', coordinates }, properties: {} };
71
+ }
72
+ }
73
+ setGeometry(point) {
74
+ this.point = [point[0], point[1]];
75
+ this.redraw();
76
+ }
77
+ getBounds() {
78
+ return new LngLatBounds(this.point, this.point);
79
+ }
80
+ redraw() {
81
+ this.source?.setData(this.getAsFeatureCollection());
82
+ }
83
+ getAsPixel() {
84
+ const p = this.map.project([this.point[0], this.point[1]]);
85
+ return [p.x, p.y];
86
+ }
87
+ checkDragPointAt(point) {
88
+ const maxDistance = 5;
89
+ const { x, y } = point;
90
+ const [x0, y0] = this.getAsPixel();
91
+ const distance = Math.sqrt(Math.pow(x - x0, 2) + Math.pow(y - y0, 2));
92
+ this.updateDragPoint(distance < maxDistance);
93
+ }
94
+ doDrag(lngLat) {
95
+ this.point = [Math.round(lngLat.lng * 1e5) / 1e5, Math.round(lngLat.lat * 1e5) / 1e5];
96
+ }
97
+ }
@@ -0,0 +1,19 @@
1
+ import type { FillLayerSpecification, LineLayerSpecification, SymbolLayerSpecification } from 'maplibre-gl';
2
+ export type AbstractLayerStyle<T extends FillLayerSpecification | LineLayerSpecification | SymbolLayerSpecification> = {
3
+ paint: {} & T['paint'];
4
+ layout: {} & T['layout'];
5
+ };
6
+ export interface FillStyle {
7
+ color?: string;
8
+ fillColor?: string;
9
+ }
10
+ export declare function getFillStyle(style?: FillStyle): AbstractLayerStyle<FillLayerSpecification>;
11
+ export interface LineStyle {
12
+ color?: string;
13
+ lineColor?: string;
14
+ }
15
+ export declare function getLineStyle(style?: LineStyle): AbstractLayerStyle<LineLayerSpecification>;
16
+ export interface SymbolStyle {
17
+ color?: string;
18
+ }
19
+ export declare function getSymbolStyle(style?: SymbolStyle): AbstractLayerStyle<SymbolLayerSpecification>;
@@ -0,0 +1,40 @@
1
+ import { Color } from '@versatiles/style';
2
+ export function getFillStyle(style) {
3
+ const result = {
4
+ layout: {},
5
+ paint: {}
6
+ };
7
+ if (style) {
8
+ if (style.fillColor) {
9
+ result.paint['fill-color'] = Color.parse(style.fillColor).asString();
10
+ }
11
+ else if (style.color) {
12
+ result.paint['fill-color'] = Color.parse(style.color).fade(0.8).asString();
13
+ }
14
+ }
15
+ return result;
16
+ }
17
+ export function getLineStyle(style) {
18
+ const result = {
19
+ layout: { 'line-cap': 'round', 'line-join': 'round' },
20
+ paint: {}
21
+ };
22
+ if (style) {
23
+ const color = style.lineColor ?? style.color;
24
+ if (color)
25
+ result.paint['line-color'] = Color.parse(color).asString();
26
+ }
27
+ return result;
28
+ }
29
+ export function getSymbolStyle(style) {
30
+ const result = {
31
+ layout: {},
32
+ paint: {}
33
+ };
34
+ result.paint['icon-color'] = Color.parse(style?.color ?? '#a00').asString();
35
+ result.paint['icon-halo-color'] = Color.parse('#fff').asString();
36
+ result.paint['icon-halo-width'] = 0.5;
37
+ result.paint['icon-halo-blur'] = 0;
38
+ result.layout['icon-image'] = 'basics:icon-embassy';
39
+ return result;
40
+ }
@@ -1,3 +1,4 @@
1
1
  import type { Language } from '@versatiles/style';
2
- export declare function getCountry(): string;
2
+ export declare function getCountryName(): string | null;
3
+ export declare function getCountryCode(): string | null;
3
4
  export declare function getLanguage(): Language;
@@ -1,22 +1,32 @@
1
1
  import { timezone2countrycode } from './zones.js';
2
- export function getCountry() {
2
+ export function getCountryName() {
3
+ try {
4
+ const countryCode = getCountryCode();
5
+ if (!countryCode)
6
+ return null;
7
+ const region = new Intl.DisplayNames(['en-GB'], { type: 'region' });
8
+ const country = region.of(countryCode);
9
+ return country || null;
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ export function getCountryCode() {
3
16
  try {
4
17
  const options = Intl.DateTimeFormat().resolvedOptions();
5
18
  let countryCode = timezone2countrycode(options.timeZone);
6
19
  if (!countryCode)
7
20
  countryCode = navigator.language.split('-')[1];
8
- const region = new Intl.DisplayNames(['en-GB'], { type: 'region' });
9
- const country = region.of(countryCode);
10
- return country || '';
21
+ return countryCode || null;
11
22
  }
12
- catch (error) {
13
- console.error('Could not determine country from timezone:', error);
14
- return ''; // Fallback if no country can be determined
23
+ catch {
24
+ return null;
15
25
  }
16
26
  }
17
27
  export function getLanguage() {
18
28
  try {
19
- const language = Intl.DateTimeFormat().resolvedOptions().locale.split('-')[0];
29
+ const language = Intl.DateTimeFormat().resolvedOptions().locale.split('-')[0].toLowerCase();
20
30
  switch (language) {
21
31
  case 'en':
22
32
  case 'de':
@@ -24,8 +34,7 @@ export function getLanguage() {
24
34
  }
25
35
  return null;
26
36
  }
27
- catch (error) {
28
- console.error('Could not determine country from timezone:', error);
37
+ catch {
29
38
  return null; // Fallback if no country can be determined
30
39
  }
31
40
  }
@@ -0,0 +1,19 @@
1
+ interface SpriteEntry {
2
+ width: number;
3
+ height: number;
4
+ x: number;
5
+ y: number;
6
+ pixelRatio: number;
7
+ sdf: boolean;
8
+ id: string;
9
+ name: string;
10
+ group: string;
11
+ }
12
+ export declare class SpriteLibrary {
13
+ private spriteList;
14
+ private pixelRatio;
15
+ constructor(pixelRatio?: number);
16
+ getSpriteList(): Promise<SpriteEntry[]>;
17
+ private loadSpriteList;
18
+ }
19
+ export default SpriteLibrary;
@@ -0,0 +1,30 @@
1
+ export class SpriteLibrary {
2
+ spriteList = [];
3
+ pixelRatio;
4
+ constructor(pixelRatio = 2) {
5
+ this.pixelRatio = pixelRatio;
6
+ }
7
+ async getSpriteList() {
8
+ await this.loadSpriteList();
9
+ return this.spriteList;
10
+ }
11
+ async loadSpriteList() {
12
+ if (this.spriteList.length)
13
+ return;
14
+ const spriteGroupList = (await fetch('https://tiles.versatiles.org/assets/sprites/index.json').then((r) => r.json()));
15
+ await Promise.all(spriteGroupList.map(async (group) => {
16
+ const spriteGroup = (await fetch(`https://tiles.versatiles.org/assets/sprites/${group}/sprites@${this.pixelRatio}x.json`).then((r) => r.json()));
17
+ Object.entries(spriteGroup).forEach(([name, entry]) => {
18
+ this.spriteList.push({
19
+ ...entry,
20
+ pixelRatio: entry.pixelRatio ?? 1,
21
+ sdf: entry.sdf ?? false,
22
+ id: `${group}/${name}`,
23
+ group,
24
+ name
25
+ });
26
+ });
27
+ }));
28
+ }
29
+ }
30
+ export default SpriteLibrary;
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@versatiles/svelte",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
+ "license": "MIT",
4
5
  "scripts": {
5
- "build": "vite build && npm run package",
6
+ "build": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json && vite build && npm run package",
6
7
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
7
- "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
8
+ "check": "npm run lint && npm run build && npm run test",
8
9
  "dev": "vite dev",
9
10
  "format": "prettier --write .",
10
- "lint": "prettier --check . && eslint .",
11
+ "lint": "prettier --check . && eslint --color .",
11
12
  "package": "svelte-kit sync && svelte-package && publint",
12
13
  "prepack": "npm run package",
13
14
  "prepublishOnly": "npm run package",
@@ -16,7 +17,8 @@
16
17
  "release": "npm run build && npx vrt release-npm",
17
18
  "test:integration": "playwright test",
18
19
  "test:unit": "vitest run",
19
- "test": "npm run test:integration && npm run test:unit",
20
+ "test:coverage": "vitest run --coverage",
21
+ "test": "npm run test:unit && npm run test:integration",
20
22
  "upgrade": "npm-check-updates -u && rm -f package-lock.json; rm -rf node_modules; npm update --save && npm install"
21
23
  },
22
24
  "exports": {
@@ -37,27 +39,27 @@
37
39
  },
38
40
  "devDependencies": {
39
41
  "@playwright/test": "^1.50.0",
40
- "@sveltejs/adapter-auto": "^4.0.0",
42
+ "@sveltejs/adapter-static": "^3.0.8",
41
43
  "@sveltejs/kit": "^2.16.1",
42
44
  "@sveltejs/package": "^2.3.9",
43
45
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
44
46
  "@turf/turf": "^7.2.0",
45
47
  "@types/eslint": "^9.6.1",
46
48
  "@types/node": "^22.10.10",
47
- "@types/split2": "^4.2.3",
48
49
  "@versatiles/release-tool": "^1.2.6",
50
+ "@vitest/coverage-v8": "^3.0.4",
49
51
  "cookie": "^1.0.2",
50
52
  "eslint": "^9.19.0",
51
53
  "eslint-config-prettier": "^10.0.1",
52
54
  "eslint-plugin-svelte": "^2.46.1",
53
55
  "geojson": "^0.5.0",
54
56
  "globals": "^15.14.0",
57
+ "happy-dom": "^16.7.3",
55
58
  "npm-check-updates": "^17.1.14",
56
59
  "prettier": "^3.4.2",
57
60
  "prettier-plugin-svelte": "^3.3.3",
58
61
  "publint": "^0.3.2",
59
- "split2": "^4.2.0",
60
- "svelte": "^5.19.2",
62
+ "svelte": "^5.19.3",
61
63
  "svelte-check": "^4.1.4",
62
64
  "tsx": "^4.19.2",
63
65
  "typescript": "^5.7.3",
@@ -69,7 +71,7 @@
69
71
  "types": "./dist/index.d.ts",
70
72
  "type": "module",
71
73
  "dependencies": {
72
- "@versatiles/style": "^5.2.5",
74
+ "@versatiles/style": "^5.2.9",
73
75
  "maplibre-gl": "^5.0.1"
74
76
  }
75
77
  }
@@ -1,70 +0,0 @@
1
- # BBox Map
2
-
3
- This SvelteKit component generates an interactive world map with a search field that allows users to easily search for geographic bounding boxes (BBoxes) for various regions, including continents, countries, and cities. The selected bounding box can also be manipulated by dragging the edges.
4
-
5
- ## Improving Bounding Boxes
6
-
7
- Bounding boxes for different regions (continents, countries, cities, etc.) are stored in the `bboxes.json` file. This file is generated by the helper script `helpers/merge_bboxes.ts`, which processes the `*.jsonl` files in the `data` directory.
8
-
9
- ### Editing Bounding Boxes
10
-
11
- To edit or add new bounding boxes:
12
-
13
- 1. **Modify or Add a JSONL File**: Edit existing JSONL files in the `data` directory or create new ones with the required bounding box data.
14
- 2. **Run the `merge_bboxes.ts` Script**: After making changes, run the `merge_bboxes.ts` script to update the `bboxes.json` file.
15
-
16
- ### Helper Script: `merge_bboxes.ts`
17
-
18
- This script consolidates bounding box data from multiple JSONL files in the `data` directory, checks for duplicate labels, and outputs a single, sorted JSON file (`bboxes.json`). The bounding box coordinates are also rounded to an appropriate precision based on their size.
19
-
20
- #### Usage
21
-
22
- Simply run the script:
23
-
24
- ```bash
25
- ./helpers/merge_bboxes.ts
26
- ```
27
-
28
- #### Output
29
-
30
- The script writes the processed data to `bboxes.json` in the parent directory. The entries in this file are sorted by population and formatted as:
31
-
32
- ```json
33
- ["Label", lngMin, latMin, lngWidth, latHeight]
34
- ```
35
-
36
- ### Helper Script: `geojson2bboxes.ts`
37
-
38
- This script processes GeoJSON or GeoJSONL files to extract bounding boxes for each geographic feature, generate labels, and either extract or estimate the population for each feature. The results are saved in JSONL format, which can be used by the `merge_bboxes.ts` script.
39
-
40
- #### Usage
41
-
42
- ```bash
43
- ./helpers/geojson2bboxes.ts <FILENAME> <LABEL_TEMPLATE> [POPULATION_KEY]
44
- ```
45
-
46
- - `<FILENAME>`: The name of the input GeoJSON or GeoJSONL file. The file can be optionally compressed with `.br` (Brotli) or `.gz` (Gzip).
47
- - `<LABEL_TEMPLATE>`: A template string used to generate labels for each feature. Placeholders in the form `{propertyName}` will be replaced by the corresponding property value from each feature.
48
- - `[POPULATION_KEY]`: (Optional) The key in the feature's properties that contains the population value. If not provided, the script will estimate the population.
49
-
50
- #### Example
51
-
52
- ```bash
53
- ./helpers/geojson2bboxes.ts africa.geojson "{country}, {city}"
54
- ```
55
-
56
- This command processes the `africa.geojson` file, generating labels in the format `"country, city"` and estimating the population for each region.
57
-
58
- #### Output
59
-
60
- The script outputs a `.jsonl` file with entries formatted as follows:
61
-
62
- ```json
63
- {
64
- "label": "Country - City",
65
- "population": 123456,
66
- "bbox": [minLng, minLat, maxLng, maxLat]
67
- }
68
- ```
69
-
70
- Place this `.jsonl` file in the `data` directory to include it in the `bboxes.json` file when running `merge_bboxes.ts`.