@versatiles/svelte 0.2.0 → 1.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.
Files changed (60) hide show
  1. package/README.md +21 -4
  2. package/dist/components/BBoxMap/AutoComplete.svelte +176 -0
  3. package/dist/components/{AutoComplete.svelte.d.ts → BBoxMap/AutoComplete.svelte.d.ts} +12 -18
  4. package/dist/components/BBoxMap/BBoxMap.d.ts +1 -12
  5. package/dist/components/BBoxMap/BBoxMap.js +1 -200
  6. package/dist/components/BBoxMap/BBoxMap.svelte +43 -127
  7. package/dist/components/BBoxMap/BBoxMap.svelte.d.ts +4 -20
  8. package/dist/components/BasicMap/BasicMap.svelte +34 -37
  9. package/dist/components/BasicMap/BasicMap.svelte.d.ts +9 -24
  10. package/dist/components/LocatorMap/LocatorMap.svelte +75 -0
  11. package/dist/components/LocatorMap/LocatorMap.svelte.d.ts +19 -0
  12. package/dist/components/MapEditor/Editor.svelte +25 -0
  13. package/dist/components/MapEditor/Editor.svelte.d.ts +7 -0
  14. package/dist/components/MapEditor/EditorLine.svelte +27 -0
  15. package/dist/components/MapEditor/EditorLine.svelte.d.ts +7 -0
  16. package/dist/components/MapEditor/EditorMarker.svelte +42 -0
  17. package/dist/components/MapEditor/EditorMarker.svelte.d.ts +7 -0
  18. package/dist/components/MapEditor/MapEditor.svelte +99 -0
  19. package/dist/components/MapEditor/MapEditor.svelte.d.ts +4 -0
  20. package/dist/components/MapEditor/editor.scss +16 -0
  21. package/dist/components/MapEditor/lib/element_abstract.d.ts +20 -0
  22. package/dist/components/MapEditor/lib/element_abstract.js +58 -0
  23. package/dist/components/MapEditor/lib/element_line.d.ts +14 -0
  24. package/dist/components/MapEditor/lib/element_line.js +76 -0
  25. package/dist/components/MapEditor/lib/element_marker.d.ts +20 -0
  26. package/dist/components/MapEditor/lib/element_marker.js +191 -0
  27. package/dist/components/MapEditor/lib/geocoder.d.ts +1 -0
  28. package/dist/components/MapEditor/lib/geocoder.js +8 -0
  29. package/dist/components/MapEditor/lib/geometry_manager.d.ts +18 -0
  30. package/dist/components/MapEditor/lib/geometry_manager.js +117 -0
  31. package/dist/components/MapEditor/lib/map_layer.d.ts +14 -0
  32. package/dist/components/MapEditor/lib/map_layer.js +61 -0
  33. package/dist/components/MapEditor/lib/types.d.ts +112 -0
  34. package/dist/components/MapEditor/lib/types.js +1 -0
  35. package/dist/components/MapEditor/lib/utils.d.ts +2 -0
  36. package/dist/components/MapEditor/lib/utils.js +11 -0
  37. package/dist/index.d.ts +3 -1
  38. package/dist/index.js +3 -1
  39. package/dist/utils/draw/bbox.d.ts +28 -0
  40. package/dist/utils/draw/bbox.js +193 -0
  41. package/dist/utils/location.d.ts +2 -1
  42. package/dist/utils/location.js +19 -10
  43. package/dist/utils/map_style.d.ts +6 -0
  44. package/dist/utils/map_style.js +28 -0
  45. package/dist/utils/sprite_library.d.ts +19 -0
  46. package/dist/utils/sprite_library.js +30 -0
  47. package/package.json +19 -14
  48. package/dist/components/AutoComplete.svelte +0 -197
  49. package/dist/components/BBoxMap/README.md +0 -70
  50. package/dist/components/BBoxMap/data/countries.jsonl +0 -258
  51. package/dist/components/BBoxMap/data/eu.jsonl +0 -1876
  52. package/dist/components/BBoxMap/data/us.jsonl +0 -52
  53. package/dist/components/BBoxMap/data/world.jsonl +0 -7
  54. package/dist/components/BBoxMap/helpers/geojson2bboxes.d.ts +0 -2
  55. package/dist/components/BBoxMap/helpers/geojson2bboxes.js +0 -183
  56. package/dist/components/BBoxMap/helpers/merge_bboxes.d.ts +0 -2
  57. package/dist/components/BBoxMap/helpers/merge_bboxes.js +0 -84
  58. package/dist/components/BBoxMap/helpers/population.raw.br +0 -0
  59. package/dist/utils/style.d.ts +0 -3
  60. package/dist/utils/style.js +0 -21
@@ -0,0 +1,20 @@
1
+ import { AbstractElement } from './element_abstract.js';
2
+ import type { GeometryManager } from './geometry_manager.js';
3
+ import type { ElementPoint, LayerSymbol, SelectionNode } from './types.js';
4
+ export declare const symbols: Map<string, {
5
+ image: string;
6
+ offset?: [number, number];
7
+ }>;
8
+ export declare class MarkerElement extends AbstractElement<LayerSymbol> {
9
+ readonly color: import("svelte/store").Writable<string>;
10
+ readonly halo: import("svelte/store").Writable<number>;
11
+ readonly rotate: import("svelte/store").Writable<number>;
12
+ readonly size: import("svelte/store").Writable<number>;
13
+ readonly symbol: import("svelte/store").Writable<string>;
14
+ readonly label: import("svelte/store").Writable<string>;
15
+ private point;
16
+ constructor(manager: GeometryManager, name: string, point?: ElementPoint);
17
+ getFeature(): GeoJSON.Feature<GeoJSON.Point>;
18
+ getSelectionNodes(): SelectionNode[];
19
+ getSelectionNodeUpdater(): ((lng: number, lat: number) => void) | undefined;
20
+ }
@@ -0,0 +1,191 @@
1
+ import { Color } from '@versatiles/style';
2
+ import { AbstractElement } from './element_abstract.js';
3
+ import { get, writable } from 'svelte/store';
4
+ export const symbols = new Map([
5
+ ['airplane', { image: 'basics:icon-airfield' }],
6
+ ['airport', { image: 'basics:icon-airport' }],
7
+ ['alcohol shop', { image: 'basics:icon-alcohol_shop' }],
8
+ ['art gallery', { image: 'basics:icon-art_gallery' }],
9
+ ['artwork', { image: 'basics:icon-artwork' }],
10
+ ['atm', { image: 'basics:icon-atm' }],
11
+ ['bakery', { image: 'basics:icon-bakery' }],
12
+ ['bank', { image: 'basics:icon-bank' }],
13
+ ['beauty', { image: 'basics:icon-beauty' }],
14
+ ['beer', { image: 'basics:icon-beer' }],
15
+ ['beergarden', { image: 'basics:icon-beergarden' }],
16
+ ['bench', { image: 'basics:icon-bench' }],
17
+ ['beverages', { image: 'basics:icon-beverages' }],
18
+ ['bicycle share', { image: 'basics:icon-bicycle_share' }],
19
+ ['books', { image: 'basics:icon-books' }],
20
+ ['bus', { image: 'basics:icon-bus' }],
21
+ ['butcher', { image: 'basics:icon-butcher' }],
22
+ ['cafe', { image: 'basics:icon-cafe', offset: [2, 0] }],
23
+ ['car rental', { image: 'basics:icon-car_rental' }],
24
+ ['car wash', { image: 'basics:icon-car_wash' }],
25
+ ['castle', { image: 'basics:icon-castle' }],
26
+ ['cemetery', { image: 'basics:icon-cemetery' }],
27
+ ['chalet', { image: 'basics:icon-chalet' }],
28
+ ['chemist', { image: 'basics:icon-chemist' }],
29
+ ['cinema', { image: 'basics:icon-cinema' }],
30
+ ['clothes', { image: 'basics:icon-clothes' }],
31
+ ['college', { image: 'basics:icon-college' }],
32
+ ['community', { image: 'basics:icon-community' }],
33
+ ['defibrillator', { image: 'basics:icon-defibrillator' }],
34
+ ['doctor', { image: 'basics:icon-doctor' }],
35
+ ['dog park', { image: 'basics:icon-dog_park' }],
36
+ ['doityourself', { image: 'basics:icon-doityourself' }],
37
+ ['drinking water', { image: 'basics:icon-drinking_water' }],
38
+ ['drycleaning', { image: 'basics:icon-drycleaning' }],
39
+ ['emergency phone', { image: 'basics:icon-emergency_phone' }],
40
+ ['fast food', { image: 'basics:icon-fast_food' }],
41
+ ['fire station', { image: 'basics:icon-fire_station' }],
42
+ ['flag', { image: 'basics:icon-embassy', offset: [7.5, -10] }],
43
+ ['florist', { image: 'basics:icon-florist' }],
44
+ ['fountain', { image: 'basics:icon-fountain' }],
45
+ ['furniture', { image: 'basics:icon-furniture' }],
46
+ ['garden centre', { image: 'basics:icon-garden_centre' }],
47
+ ['gift', { image: 'basics:icon-gift' }],
48
+ ['glasses', { image: 'basics:icon-optician' }],
49
+ ['golf', { image: 'basics:icon-golf' }],
50
+ ['greengrocer', { image: 'basics:icon-greengrocer' }],
51
+ ['hardware', { image: 'basics:icon-hardware' }],
52
+ ['hospital', { image: 'basics:icon-hospital' }],
53
+ ['huntingstand', { image: 'basics:icon-huntingstand' }],
54
+ ['hydrant', { image: 'basics:icon-hydrant' }],
55
+ ['icerink', { image: 'basics:icon-icerink' }],
56
+ ['information', { image: 'basics:transport-information' }],
57
+ ['jewelry store', { image: 'basics:icon-jewelry_store' }],
58
+ ['kiosk', { image: 'basics:icon-kiosk' }],
59
+ ['laundry', { image: 'basics:icon-laundry' }],
60
+ ['letter', { image: 'basics:icon-post' }],
61
+ ['library', { image: 'basics:icon-library' }],
62
+ ['lighthouse', { image: 'basics:icon-lighthouse' }],
63
+ ['marketplace', { image: 'basics:icon-marketplace' }],
64
+ ['money', { image: 'basics:icon-bar' }],
65
+ ['monument', { image: 'basics:icon-monument' }],
66
+ ['newsagent', { image: 'basics:icon-newsagent' }],
67
+ ['nightclub', { image: 'basics:icon-nightclub' }],
68
+ ['nursinghome', { image: 'basics:icon-nursinghome' }],
69
+ ['observation tower', { image: 'basics:icon-observation_tower' }],
70
+ ['outdoor', { image: 'basics:icon-outdoor' }],
71
+ ['pharmacy', { image: 'basics:icon-pharmacy' }],
72
+ ['picnic site', { image: 'basics:icon-picnic_site' }],
73
+ ['place of worship', { image: 'basics:icon-place_of_worship' }],
74
+ ['playground', { image: 'basics:icon-playground' }],
75
+ ['police', { image: 'basics:icon-police', offset: [-1, -3] }],
76
+ ['postbox', { image: 'basics:icon-postbox' }],
77
+ ['prison', { image: 'basics:icon-prison' }],
78
+ ['rail light', { image: 'basics:icon-rail_light' }],
79
+ ['rail metro', { image: 'basics:icon-rail_metro' }],
80
+ ['rail', { image: 'basics:icon-rail' }],
81
+ ['recycling', { image: 'basics:icon-recycling' }],
82
+ ['restaurant', { image: 'basics:icon-restaurant' }],
83
+ ['run', { image: 'basics:icon-pitch' }],
84
+ ['school', { image: 'basics:icon-school' }],
85
+ ['scissor', { image: 'basics:icon-hairdresser' }],
86
+ ['shield', { image: 'basics:icon-historic', offset: [0, -10] }],
87
+ ['shoes', { image: 'basics:icon-shoes', offset: [-5, 0] }],
88
+ ['shop', { image: 'basics:icon-shop' }],
89
+ ['shop', { image: 'basics:icon-shop' }],
90
+ ['shrine', { image: 'basics:icon-shrine' }],
91
+ ['sports', { image: 'basics:icon-sports' }],
92
+ ['stadium', { image: 'basics:icon-stadium' }],
93
+ ['stationery', { image: 'basics:icon-stationery' }],
94
+ ['surveillance', { image: 'basics:icon-surveillance' }],
95
+ ['swimming', { image: 'basics:icon-swimming' }],
96
+ ['telephone', { image: 'basics:icon-telephone' }],
97
+ ['theatre', { image: 'basics:icon-theatre' }],
98
+ ['toilet', { image: 'basics:icon-toilet' }],
99
+ ['tooth', { image: 'basics:icon-dentist' }],
100
+ ['town hall', { image: 'basics:icon-town_hall' }],
101
+ ['toys', { image: 'basics:icon-toys' }],
102
+ ['tram', { image: 'basics:transport-tram' }],
103
+ ['travel agent', { image: 'basics:icon-travel_agent' }],
104
+ ['vendingmachine', { image: 'basics:icon-vendingmachine' }],
105
+ ['veterinary', { image: 'basics:icon-veterinary' }],
106
+ ['video', { image: 'basics:icon-video' }],
107
+ ['viewpoint', { image: 'basics:icon-viewpoint', offset: [0, -6] }],
108
+ ['waste basket', { image: 'basics:icon-waste_basket' }],
109
+ ['watermill', { image: 'basics:icon-watermill' }],
110
+ ['waterpark', { image: 'basics:icon-waterpark' }],
111
+ ['windmill', { image: 'basics:icon-windmill' }],
112
+ ['zoo', { image: 'basics:icon-zoo' }]
113
+ ]);
114
+ export class MarkerElement extends AbstractElement {
115
+ color = writable('#ff0000');
116
+ halo = writable(1);
117
+ rotate = writable(0);
118
+ size = writable(1);
119
+ symbol = writable('flag');
120
+ label = writable('');
121
+ point = [0, 0];
122
+ constructor(manager, name, point) {
123
+ super(manager, name, 'symbol');
124
+ this.point = point ?? this.randomPositions(name, 1)[0];
125
+ const getSymbol = () => {
126
+ const entry = symbols.get(get(this.symbol)) ?? symbols.get('flag');
127
+ return { image: entry.image, offset: entry.offset ?? [0, 0] };
128
+ };
129
+ this.layer.setLayout({
130
+ 'icon-image': getSymbol().image,
131
+ 'icon-offset': getSymbol().offset,
132
+ 'icon-overlap': 'always',
133
+ 'icon-rotate': get(this.rotate),
134
+ 'icon-size': get(this.size),
135
+ 'text-field': get(this.label),
136
+ 'text-font': ['noto_sans_regular'],
137
+ 'text-justify': 'left',
138
+ 'text-anchor': 'right',
139
+ 'text-offset': [-0.4, -0.6]
140
+ });
141
+ this.layer.setPaint({
142
+ 'icon-color': Color.parse(get(this.color)).asString(),
143
+ 'icon-halo-blur': 0,
144
+ 'icon-halo-color': '#FFFFFF',
145
+ 'icon-halo-width': get(this.halo) * get(this.size),
146
+ 'icon-opacity': 1,
147
+ 'text-halo-blur': 0,
148
+ 'text-halo-color': '#FFFFFF',
149
+ 'text-halo-width': get(this.halo) * get(this.size)
150
+ });
151
+ this.color.subscribe((value) => this.layer.updatePaint('icon-color', Color.parse(value)));
152
+ this.halo.subscribe((value) => {
153
+ this.layer.updatePaint('icon-halo-width', value * get(this.size));
154
+ this.layer.updatePaint('text-halo-width', value * get(this.size));
155
+ });
156
+ this.label.subscribe((value) => this.layer.updateLayout('text-field', value));
157
+ this.rotate.subscribe((value) => this.layer.updateLayout('icon-rotate', value));
158
+ this.size.subscribe((value) => {
159
+ this.layer.updateLayout('icon-size', value);
160
+ this.layer.updatePaint('icon-halo-width', value * get(this.halo));
161
+ this.layer.updateLayout('text-size', value * 16);
162
+ this.layer.updatePaint('text-halo-width', value * get(this.halo));
163
+ });
164
+ this.symbol.subscribe(() => {
165
+ const symbol = getSymbol();
166
+ this.layer.updateLayout('icon-image', symbol.image);
167
+ this.layer.updateLayout('icon-offset', symbol.offset);
168
+ });
169
+ this.source.setData(this.getFeature());
170
+ }
171
+ getFeature() {
172
+ return {
173
+ type: 'Feature',
174
+ properties: {},
175
+ geometry: {
176
+ type: 'Point',
177
+ coordinates: this.point
178
+ }
179
+ };
180
+ }
181
+ getSelectionNodes() {
182
+ return [{ index: 0, coordinates: this.point }];
183
+ }
184
+ getSelectionNodeUpdater() {
185
+ return (lng, lat) => {
186
+ this.point[0] = lng;
187
+ this.point[1] = lat;
188
+ this.source.setData(this.getFeature());
189
+ };
190
+ }
191
+ }
@@ -0,0 +1 @@
1
+ export declare function getLatLng(query: string): Promise<[number, number] | undefined>;
@@ -0,0 +1,8 @@
1
+ export async function getLatLng(query) {
2
+ const url = `https://photon.komoot.io/api/?${new URLSearchParams(query)}`;
3
+ const result = await fetch(url).then((r) => r.json());
4
+ const geometry = result?.features?.[0]?.geometry;
5
+ if (geometry?.type !== 'Point')
6
+ return;
7
+ return geometry.coordinates;
8
+ }
@@ -0,0 +1,18 @@
1
+ import { type Writable } from 'svelte/store';
2
+ import type { AbstractElement } from './element_abstract.js';
3
+ import type maplibregl from 'maplibre-gl';
4
+ export declare class GeometryManager {
5
+ readonly elements: Writable<AbstractElement[]>;
6
+ readonly map: maplibregl.Map;
7
+ readonly activeElement: Writable<AbstractElement | undefined>;
8
+ private readonly selection_nodes;
9
+ private readonly canvas;
10
+ constructor(map: maplibregl.Map);
11
+ setActiveElement(element: AbstractElement | undefined): void;
12
+ private drawSelectionNodes;
13
+ getElement(index: number): AbstractElement;
14
+ getNewMarker(): AbstractElement;
15
+ getNewLine(): AbstractElement;
16
+ private addElement;
17
+ private newName;
18
+ }
@@ -0,0 +1,117 @@
1
+ import { get, writable } from 'svelte/store';
2
+ import { MarkerElement } from './element_marker.js';
3
+ import { LineElement } from './element_line.js';
4
+ export class GeometryManager {
5
+ elements;
6
+ map;
7
+ activeElement = writable(undefined);
8
+ selection_nodes;
9
+ canvas;
10
+ constructor(map) {
11
+ this.elements = writable([]);
12
+ this.map = map;
13
+ this.canvas = this.map.getCanvasContainer();
14
+ map.addSource('selection_nodes', {
15
+ type: 'geojson',
16
+ data: { type: 'FeatureCollection', features: [] }
17
+ });
18
+ this.selection_nodes = map.getSource('selection_nodes');
19
+ map.addLayer({
20
+ id: 'selection_nodes',
21
+ source: 'selection_nodes',
22
+ type: 'circle',
23
+ layout: {},
24
+ paint: {
25
+ 'circle-color': '#ffffff',
26
+ 'circle-opacity': ['get', 'opacity'],
27
+ 'circle-radius': 4,
28
+ 'circle-stroke-color': '#000000',
29
+ 'circle-stroke-opacity': ['get', 'opacity'],
30
+ 'circle-stroke-width': 1.5
31
+ }
32
+ });
33
+ map.on('mousedown', 'selection_nodes', (e) => {
34
+ const element = get(this.activeElement);
35
+ if (element == undefined)
36
+ return;
37
+ const feature = map.queryRenderedFeatures(e.point, { layers: ['selection_nodes'] })[0];
38
+ const updateSelectionNode = element.getSelectionNodeUpdater(feature.properties);
39
+ if (updateSelectionNode == undefined)
40
+ return;
41
+ e.preventDefault();
42
+ const onMove = (e) => {
43
+ e.preventDefault();
44
+ this.canvas.style.cursor = 'grabbing';
45
+ updateSelectionNode(e.lngLat.lng, e.lngLat.lat);
46
+ this.drawSelectionNodes(element.getSelectionNodes());
47
+ };
48
+ const onUp = () => {
49
+ map.off('mousemove', onMove);
50
+ this.canvas.style.cursor = 'default';
51
+ };
52
+ map.once('mouseup', onUp);
53
+ map.on('mousemove', onMove);
54
+ });
55
+ map.on('mouseover', 'selection_nodes', () => (this.canvas.style.cursor = 'move'));
56
+ map.on('mouseout', 'selection_nodes', () => (this.canvas.style.cursor = 'default'));
57
+ map.on('click', (e) => {
58
+ this.setActiveElement(undefined);
59
+ e.preventDefault();
60
+ });
61
+ }
62
+ setActiveElement(element) {
63
+ if (element) {
64
+ if (!get(this.elements).includes(element))
65
+ throw new Error('Element not in list');
66
+ this.drawSelectionNodes(element.getSelectionNodes());
67
+ }
68
+ else {
69
+ this.drawSelectionNodes([]);
70
+ }
71
+ this.activeElement.set(element);
72
+ }
73
+ drawSelectionNodes(nodes) {
74
+ this.selection_nodes.setData({
75
+ type: 'FeatureCollection',
76
+ features: nodes.map((n) => ({
77
+ type: 'Feature',
78
+ properties: { index: n.index, opacity: n.transparent ? 0.3 : 1 },
79
+ geometry: { type: 'Point', coordinates: n.coordinates }
80
+ }))
81
+ });
82
+ }
83
+ getElement(index) {
84
+ return get(this.elements)[index];
85
+ }
86
+ getNewMarker() {
87
+ const element = new MarkerElement(this, this.newName('Marker '));
88
+ this.addElement(element);
89
+ return element;
90
+ }
91
+ getNewLine() {
92
+ const element = new LineElement(this, this.newName('Line '));
93
+ this.addElement(element);
94
+ return element;
95
+ }
96
+ addElement(element) {
97
+ this.elements.update((elements) => [...elements, element]);
98
+ }
99
+ newName(prefix) {
100
+ const set = new Set();
101
+ const elements = get(this.elements);
102
+ elements.forEach((e) => {
103
+ const name = e.name;
104
+ if (!name.startsWith(prefix))
105
+ return;
106
+ const index = name.substring(prefix.length);
107
+ if (!/^[0-9]+/.test(index))
108
+ return;
109
+ set.add(parseInt(index, 10));
110
+ });
111
+ for (let i = 1; i <= elements.length + 1; i++) {
112
+ if (!set.has(i))
113
+ return prefix + i;
114
+ }
115
+ throw new Error('Unreachable');
116
+ }
117
+ }
@@ -0,0 +1,14 @@
1
+ import type { LayerFill, LayerLine, LayerSymbol } from './types.js';
2
+ type LayerSpec = LayerFill | LayerLine | LayerSymbol;
3
+ export declare class MapLayer<T extends LayerSpec> {
4
+ readonly map: maplibregl.Map;
5
+ readonly id: string;
6
+ readonly layoutProperties: T["layout"];
7
+ readonly paintProperties: T["paint"];
8
+ constructor(map: maplibregl.Map, id: string, source: string, type: 'symbol' | 'line' | 'fill');
9
+ setPaint(paint: T['paint']): void;
10
+ updatePaint<K extends keyof T['paint'], V extends T['paint'][K]>(key: K, value: V): void;
11
+ setLayout(layout: T['layout']): void;
12
+ updateLayout<K extends keyof T['layout'], V extends T['layout'][K]>(key: K, value: V): void;
13
+ }
14
+ export {};
@@ -0,0 +1,61 @@
1
+ import { Color } from '@versatiles/style';
2
+ export class MapLayer {
3
+ map;
4
+ id;
5
+ layoutProperties = {};
6
+ paintProperties = {};
7
+ constructor(map, id, source, type) {
8
+ this.map = map;
9
+ this.id = id;
10
+ let filter;
11
+ switch (type) {
12
+ case 'symbol':
13
+ filter = 'Point';
14
+ break;
15
+ case 'line':
16
+ filter = 'LineString';
17
+ break;
18
+ case 'fill':
19
+ filter = 'Polygon';
20
+ break;
21
+ default:
22
+ throw new Error('Invalid layer type');
23
+ }
24
+ this.map.addLayer({
25
+ id,
26
+ source,
27
+ type,
28
+ layout: this.layoutProperties,
29
+ paint: this.paintProperties,
30
+ filter: ['==', '$type', filter]
31
+ }, 'selection_nodes');
32
+ }
33
+ setPaint(paint) {
34
+ if (paint === undefined)
35
+ return;
36
+ const keys = new Set(Object.keys(paint).concat(Object.keys(this.paintProperties)));
37
+ for (const key of keys.values())
38
+ this.updatePaint(key, paint[key]);
39
+ }
40
+ updatePaint(key, value) {
41
+ if (value instanceof Color)
42
+ value = value.asString();
43
+ if (this.paintProperties[key] == value)
44
+ return;
45
+ this.map.setPaintProperty(this.id, key, value);
46
+ this.paintProperties[key] = value;
47
+ }
48
+ setLayout(layout) {
49
+ if (layout === undefined)
50
+ return;
51
+ const keys = new Set(Object.keys(layout).concat(Object.keys(this.layoutProperties)));
52
+ for (const key of keys.values())
53
+ this.updateLayout(key, layout[key]);
54
+ }
55
+ updateLayout(key, value) {
56
+ if (this.layoutProperties[key] == value)
57
+ return;
58
+ this.map.setLayoutProperty(this.id, key, value);
59
+ this.layoutProperties[key] = value;
60
+ }
61
+ }
@@ -0,0 +1,112 @@
1
+ import type { Color } from '@versatiles/style';
2
+ import type { ExpressionSpecification, FormattedSpecification, PaddingSpecification, ResolvedImageSpecification, VariableAnchorOffsetCollectionSpecification } from 'maplibre-gl';
3
+ export interface LayerFill {
4
+ layout: {
5
+ 'fill-sort-key'?: number;
6
+ visibility?: 'visible' | 'none';
7
+ };
8
+ paint: {
9
+ 'fill-antialias'?: boolean;
10
+ 'fill-opacity'?: number;
11
+ 'fill-color'?: string | Color;
12
+ 'fill-outline-color'?: string | Color;
13
+ 'fill-translate'?: [number, number];
14
+ 'fill-translate-anchor'?: 'map' | 'viewport';
15
+ 'fill-pattern'?: ResolvedImageSpecification;
16
+ };
17
+ }
18
+ export interface LayerLine {
19
+ layout: {
20
+ 'line-cap'?: 'butt' | 'round' | 'square';
21
+ 'line-join'?: 'bevel' | 'round' | 'miter';
22
+ 'line-miter-limit'?: number;
23
+ 'line-round-limit'?: number;
24
+ 'line-sort-key'?: number;
25
+ visibility?: 'visible' | 'none';
26
+ };
27
+ paint: {
28
+ 'line-opacity'?: number;
29
+ 'line-color'?: string | Color;
30
+ 'line-translate'?: [number, number];
31
+ 'line-translate-anchor'?: 'map' | 'viewport';
32
+ 'line-width'?: number;
33
+ 'line-gap-width'?: number;
34
+ 'line-offset'?: number;
35
+ 'line-blur'?: number;
36
+ 'line-dasharray'?: Array<number>;
37
+ 'line-pattern'?: ResolvedImageSpecification;
38
+ 'line-gradient'?: ExpressionSpecification;
39
+ };
40
+ }
41
+ export interface LayerSymbol {
42
+ layout: {
43
+ 'symbol-placement'?: 'point' | 'line' | 'line-center';
44
+ 'symbol-spacing'?: number;
45
+ 'symbol-avoid-edges'?: boolean;
46
+ 'symbol-sort-key'?: number;
47
+ 'symbol-z-order'?: 'auto' | 'viewport-y' | 'source';
48
+ 'icon-allow-overlap'?: boolean;
49
+ 'icon-overlap'?: 'never' | 'always' | 'cooperative';
50
+ 'icon-ignore-placement'?: boolean;
51
+ 'icon-optional'?: boolean;
52
+ 'icon-rotation-alignment'?: 'map' | 'viewport' | 'auto';
53
+ 'icon-size'?: number;
54
+ 'icon-text-fit'?: 'none' | 'width' | 'height' | 'both';
55
+ 'icon-text-fit-padding'?: [number, number, number, number];
56
+ 'icon-image'?: ResolvedImageSpecification;
57
+ 'icon-rotate'?: number;
58
+ 'icon-padding'?: PaddingSpecification;
59
+ 'icon-keep-upright'?: boolean;
60
+ 'icon-offset'?: [number, number];
61
+ 'icon-anchor'?: 'center' | 'left' | 'right' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
62
+ 'icon-pitch-alignment'?: 'map' | 'viewport' | 'auto';
63
+ 'text-pitch-alignment'?: 'map' | 'viewport' | 'auto';
64
+ 'text-rotation-alignment'?: 'map' | 'viewport' | 'viewport-glyph' | 'auto';
65
+ 'text-field'?: FormattedSpecification;
66
+ 'text-font'?: Array<string>;
67
+ 'text-size'?: number;
68
+ 'text-max-width'?: number;
69
+ 'text-line-height'?: number;
70
+ 'text-letter-spacing'?: number;
71
+ 'text-justify'?: 'auto' | 'left' | 'center' | 'right';
72
+ 'text-radial-offset'?: number;
73
+ 'text-variable-anchor'?: Array<'center' | 'left' | 'right' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'>;
74
+ 'text-variable-anchor-offset'?: VariableAnchorOffsetCollectionSpecification;
75
+ 'text-anchor'?: 'center' | 'left' | 'right' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
76
+ 'text-max-angle'?: number;
77
+ 'text-writing-mode'?: Array<'horizontal' | 'vertical'>;
78
+ 'text-rotate'?: number;
79
+ 'text-padding'?: number;
80
+ 'text-keep-upright'?: boolean;
81
+ 'text-transform'?: 'none' | 'uppercase' | 'lowercase';
82
+ 'text-offset'?: [number, number];
83
+ 'text-allow-overlap'?: boolean;
84
+ 'text-overlap'?: 'never' | 'always' | 'cooperative';
85
+ 'text-ignore-placement'?: boolean;
86
+ 'text-optional'?: boolean;
87
+ visibility?: 'visible' | 'none';
88
+ };
89
+ paint: {
90
+ 'icon-opacity'?: number;
91
+ 'icon-color'?: string | Color;
92
+ 'icon-halo-color'?: string | Color;
93
+ 'icon-halo-width'?: number;
94
+ 'icon-halo-blur'?: number;
95
+ 'icon-translate'?: [number, number];
96
+ 'icon-translate-anchor'?: 'map' | 'viewport';
97
+ 'text-opacity'?: number;
98
+ 'text-color'?: string | Color;
99
+ 'text-halo-color'?: string | Color;
100
+ 'text-halo-width'?: number;
101
+ 'text-halo-blur'?: number;
102
+ 'text-translate'?: [number, number];
103
+ 'text-translate-anchor'?: 'map' | 'viewport';
104
+ };
105
+ }
106
+ export type ElementPoint = [number, number];
107
+ export type ElementLine = ElementPoint[];
108
+ export interface SelectionNode {
109
+ coordinates: ElementPoint;
110
+ index: number;
111
+ transparent?: boolean;
112
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { ElementPoint } from './types.js';
2
+ export declare function getMiddlePoint(p0: ElementPoint, p1: ElementPoint): ElementPoint;
@@ -0,0 +1,11 @@
1
+ export function getMiddlePoint(p0, p1) {
2
+ const y0 = lat2mercator(p0[1]);
3
+ const y1 = lat2mercator(p1[1]);
4
+ return [(p0[0] + p1[0]) / 2, mercator2lat((y0 + y1) / 2)];
5
+ }
6
+ function lat2mercator(lat) {
7
+ return Math.log(Math.tan(Math.PI / 4 + (lat * Math.PI) / 360));
8
+ }
9
+ function mercator2lat(y) {
10
+ return ((2 * Math.atan(Math.exp(y)) - Math.PI / 2) * 180) / Math.PI;
11
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  import BasicMap from './components/BasicMap/BasicMap.svelte';
2
2
  import BBoxMap from './components/BBoxMap/BBoxMap.svelte';
3
- export { BasicMap, BBoxMap };
3
+ import LocatorMap from './components/LocatorMap/LocatorMap.svelte';
4
+ import MapEditor from './components/MapEditor/MapEditor.svelte';
5
+ export { BasicMap, BBoxMap, LocatorMap, MapEditor };
package/dist/index.js CHANGED
@@ -1,3 +1,5 @@
1
1
  import BasicMap from './components/BasicMap/BasicMap.svelte';
2
2
  import BBoxMap from './components/BBoxMap/BBoxMap.svelte';
3
- export { BasicMap, BBoxMap };
3
+ import LocatorMap from './components/LocatorMap/LocatorMap.svelte';
4
+ import MapEditor from './components/MapEditor/MapEditor.svelte';
5
+ export { BasicMap, BBoxMap, LocatorMap, MapEditor };
@@ -0,0 +1,28 @@
1
+ import type geojson from 'geojson';
2
+ type DragPoint = 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw' | false;
3
+ export declare const DragPointMap: Map<DragPoint, {
4
+ cursor: string;
5
+ flipH: DragPoint;
6
+ flipV: DragPoint;
7
+ }>;
8
+ export type BBox = [number, number, number, number];
9
+ export declare class BBoxDrawer {
10
+ private source?;
11
+ private dragPoint;
12
+ private isDragging;
13
+ private map;
14
+ private canvas;
15
+ private inverted;
16
+ private bbox;
17
+ constructor(map: maplibregl.Map, bbox: BBox, color: string, inverted?: boolean);
18
+ private updateDragPoint;
19
+ private getAsFeatureCollection;
20
+ setGeometry(bbox: geojson.BBox): void;
21
+ getBounds(): maplibregl.LngLatBounds;
22
+ private redraw;
23
+ private getAsPixel;
24
+ private checkDragPointAt;
25
+ private getCursor;
26
+ private doDrag;
27
+ }
28
+ export {};