@beyonk/svelte-mapbox 11.0.0 → 12.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/.github/workflows/publish.yml +1 -9
- package/README.md +15 -15
- package/eslint.config.js +0 -0
- package/jsconfig.json +0 -7
- package/package.json +5 -6
- package/src/lib/geocoder/Geocoder.svelte +29 -28
- package/src/lib/geocoder/geocoder-attachment.js +50 -0
- package/src/lib/map/Map.svelte +66 -57
- package/src/lib/map/Marker.svelte +26 -23
- package/src/lib/map/controls/GeolocateControl.svelte +28 -51
- package/src/lib/map/controls/NavigationControl.svelte +9 -10
- package/src/lib/map/controls/ScaleControl.svelte +13 -14
- package/src/lib/map/map-attachment.js +56 -0
- package/src/lib/queue.svelte.js +31 -0
- package/src/routes/+page.svelte +76 -79
- package/svelte.config.js +5 -1
- package/eslint.config.mjs.disabled +0 -21
- package/src/lib/event-bindings.js +0 -24
- package/src/lib/geocoder/geocoder-action.js +0 -60
- package/src/lib/map/map-action.js +0 -62
- package/src/lib/queue.js +0 -31
|
@@ -2,16 +2,8 @@ name: publish
|
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
|
-
branches:
|
|
6
|
-
- '*'
|
|
7
5
|
tags:
|
|
8
6
|
- 'v*'
|
|
9
|
-
pull_request:
|
|
10
|
-
branches:
|
|
11
|
-
- '*'
|
|
12
|
-
|
|
13
|
-
env:
|
|
14
|
-
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
|
15
7
|
|
|
16
8
|
jobs:
|
|
17
9
|
publish-npm:
|
|
@@ -24,7 +16,7 @@ jobs:
|
|
|
24
16
|
- name: set up node and pnpm
|
|
25
17
|
run: |
|
|
26
18
|
corepack enable
|
|
27
|
-
pnpm config set '//registry.npmjs.org/:_authToken' "${
|
|
19
|
+
pnpm config set '//registry.npmjs.org/:_authToken' "${{secrets.NPM_TOKEN}}"
|
|
28
20
|
pnpm i
|
|
29
21
|
|
|
30
22
|
- name: publish
|
package/README.md
CHANGED
|
@@ -30,17 +30,17 @@ npm install --save-dev @beyonk/svelte-mapbox
|
|
|
30
30
|
|
|
31
31
|
The container component is the map, and there are a variety of components which go on the map.
|
|
32
32
|
|
|
33
|
-
```
|
|
33
|
+
```svelte
|
|
34
34
|
<Map
|
|
35
35
|
accessToken="<your api key>" // add your api key here
|
|
36
36
|
bind:this={mapComponent} // Get reference to your map component to use methods
|
|
37
|
-
|
|
37
|
+
onrecentre={e => console.log(e.detail.center.lat, e.detail.center.lng) } // recentre events
|
|
38
38
|
options={{ scrollZoom: false }} // // add arbitrary options to the map from the mapbox api
|
|
39
39
|
>
|
|
40
40
|
<Earthquakes /> // Any custom component you create or want here - see marker example
|
|
41
41
|
<Marker lat={someLat} lng={someLng} color="rgb(255,255,255)" label="some marker label" popupClassName="class-name" /> // built in Marker component
|
|
42
42
|
<NavigationControl />
|
|
43
|
-
<GeolocateControl options={{ some: 'control-option' }}
|
|
43
|
+
<GeolocateControl options={{ some: 'control-option' }} oneventname={eventHandler} />
|
|
44
44
|
<ScaleControl />
|
|
45
45
|
</Map>
|
|
46
46
|
|
|
@@ -73,13 +73,13 @@ The container component is the map, and there are a variety of components which
|
|
|
73
73
|
|
|
74
74
|
By default, markers are typical map pins to which you can pass a color property.
|
|
75
75
|
|
|
76
|
-
```
|
|
76
|
+
```svelte
|
|
77
77
|
<Marker color={brandColour} />
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
You may also create a custom pin with the default slot.
|
|
81
81
|
|
|
82
|
-
```
|
|
82
|
+
```svelte
|
|
83
83
|
<Marker
|
|
84
84
|
lat={waypoint.geo.lat}
|
|
85
85
|
lng={waypoint.geo.lng}
|
|
@@ -98,13 +98,13 @@ lng={waypoint.geo.lng}
|
|
|
98
98
|
### Marker Popups
|
|
99
99
|
By default a popup is revealed when you click a pin. It is populated with text provided in the label property.
|
|
100
100
|
|
|
101
|
-
```
|
|
101
|
+
```svelte
|
|
102
102
|
<Marker label={markerText} />
|
|
103
103
|
```
|
|
104
104
|
|
|
105
105
|
To indicate interactivity, you may target the marker with some custom CSS:
|
|
106
106
|
|
|
107
|
-
```
|
|
107
|
+
```svelte
|
|
108
108
|
<style>
|
|
109
109
|
:global(.mapboxgl-marker){
|
|
110
110
|
cursor: pointer;
|
|
@@ -114,13 +114,13 @@ To indicate interactivity, you may target the marker with some custom CSS:
|
|
|
114
114
|
|
|
115
115
|
Optionally, disable the popup with the `popup={false}` property:
|
|
116
116
|
|
|
117
|
-
```
|
|
117
|
+
```svelte
|
|
118
118
|
<Marker popup={false} />
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
You may alternatively pass a custom DOM element to the marker to use as a popup.
|
|
122
122
|
|
|
123
|
-
```
|
|
123
|
+
```svelte
|
|
124
124
|
<Marker lat={pin.coordinates.latitude} lng={pin.coordinates.longitude}>
|
|
125
125
|
<div class="content" slot="popup">
|
|
126
126
|
<h3>{pin.name}</h3>
|
|
@@ -139,7 +139,7 @@ This also means that if you bind these properties to a variable, that variable w
|
|
|
139
139
|
|
|
140
140
|
This is often easier than waiting for events such as `recentre` or `zoom` to be fired, to update markers and similar:
|
|
141
141
|
|
|
142
|
-
```
|
|
142
|
+
```svelte
|
|
143
143
|
<Map accessToken="<your api key>" bind:center bind:zoom>
|
|
144
144
|
<Marker bind:lat bind:lng />
|
|
145
145
|
</Map>
|
|
@@ -165,19 +165,19 @@ map is ready in your browser when you call it this way.
|
|
|
165
165
|
|
|
166
166
|
The Geocoder is an autocompleting place lookup, which returns a lat and lng for a place.
|
|
167
167
|
|
|
168
|
-
```
|
|
169
|
-
<Geocoder accessToken="<your api key>"
|
|
168
|
+
```svelte
|
|
169
|
+
<Geocoder accessToken="<your api key>" onresult={somePlaceChangeFunction} />
|
|
170
170
|
|
|
171
171
|
<script>
|
|
172
172
|
import { Geocoder } from '@beyonk/svelte-mapbox'
|
|
173
173
|
</script>
|
|
174
174
|
```
|
|
175
175
|
|
|
176
|
-
The geocoder has five events you can subscribe to: `
|
|
176
|
+
The geocoder has five events you can subscribe to: `onloading`, `onresult`, `onresults`, `onclear`, and `onerror` which are [documented here](https://github.com/mapbox/mapbox-gl-geocoder/blob/master/API.md#on)
|
|
177
177
|
|
|
178
|
-
The most important event is `
|
|
178
|
+
The most important event is `onresult` which is fired when a user selects an autocomplete result.
|
|
179
179
|
|
|
180
|
-
There is a sixth event specific to this library, which is `
|
|
180
|
+
There is a sixth event specific to this library, which is `onready`, which is fired when the component is ready for use. You can likely ignore it.
|
|
181
181
|
|
|
182
182
|
## Custom CSS
|
|
183
183
|
|
package/eslint.config.js
ADDED
|
File without changes
|
package/jsconfig.json
CHANGED
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@beyonk/svelte-mapbox",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.1.0",
|
|
4
4
|
"devDependencies": {
|
|
5
5
|
"@beyonk/eslint-config": "^8.0.2",
|
|
6
6
|
"@eslint/eslintrc": "^3.1.0",
|
|
7
7
|
"@eslint/js": "^9.14.0",
|
|
8
|
-
"@sveltejs/kit": "^2.
|
|
9
|
-
"@sveltejs/vite-plugin-svelte": "^
|
|
8
|
+
"@sveltejs/kit": "^2.55.0",
|
|
9
|
+
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
|
10
10
|
"eslint": "^9.14.0",
|
|
11
11
|
"eslint-plugin-svelte": "^2.46.0",
|
|
12
|
-
"svelte": "^5.
|
|
12
|
+
"svelte": "^5.55.0",
|
|
13
13
|
"svelte2tsx": "^0.7.23",
|
|
14
14
|
"typescript": "^5.6.3",
|
|
15
|
-
"vite": "^
|
|
15
|
+
"vite": "^8.0.2"
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {
|
|
18
18
|
"svelte": ">=4.0.0"
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
},
|
|
23
23
|
"types": "./components.d.ts",
|
|
24
24
|
"type": "module",
|
|
25
|
-
"packageManager": "pnpm@8.15.7",
|
|
26
25
|
"scripts": {
|
|
27
26
|
"dev": "vite dev --port 3030",
|
|
28
27
|
"build": "vite build",
|
|
@@ -1,48 +1,49 @@
|
|
|
1
|
-
<div
|
|
2
|
-
id={fieldId}
|
|
3
|
-
use:action={optionsWithDefaults}
|
|
4
|
-
on:ready={init}
|
|
5
|
-
on:results
|
|
6
|
-
on:result
|
|
7
|
-
on:loading
|
|
8
|
-
on:error
|
|
9
|
-
on:clear
|
|
10
|
-
on:load
|
|
11
|
-
></div>
|
|
12
|
-
|
|
13
1
|
<script>
|
|
14
|
-
import
|
|
15
|
-
import action from './geocoder-action.js'
|
|
2
|
+
import geocoderAttachment from './geocoder-attachment.js'
|
|
16
3
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
4
|
+
let {
|
|
5
|
+
accessToken,
|
|
6
|
+
options = {},
|
|
7
|
+
version = 'v5.1.0',
|
|
8
|
+
types = [ 'country', 'region', 'postcode', 'district', 'place', 'locality', 'neighborhood', 'address' ],
|
|
9
|
+
placeholder = 'Search',
|
|
10
|
+
value = null,
|
|
11
|
+
customStylesheetUrl = false,
|
|
12
|
+
geocoder = $bindable(),
|
|
13
|
+
onresults,
|
|
14
|
+
onresult,
|
|
15
|
+
onloading,
|
|
16
|
+
onerror,
|
|
17
|
+
onclear,
|
|
18
|
+
onload,
|
|
19
|
+
...rest
|
|
20
|
+
} = $props()
|
|
25
21
|
|
|
26
|
-
const dispatch = createEventDispatcher()
|
|
27
22
|
const fieldId = 'bsm-' + Math.random().toString(36).substring(6)
|
|
28
23
|
|
|
29
|
-
const optionsWithDefaults = Object.assign({
|
|
24
|
+
const optionsWithDefaults = $derived.by(() => Object.assign({
|
|
30
25
|
version,
|
|
31
26
|
accessToken,
|
|
32
27
|
types: types.join(','),
|
|
33
28
|
placeholder,
|
|
34
29
|
customStylesheetUrl,
|
|
35
30
|
value
|
|
36
|
-
}, options)
|
|
31
|
+
}, options))
|
|
37
32
|
|
|
38
|
-
function init (
|
|
33
|
+
function init (detail) {
|
|
39
34
|
geocoder = detail.geocoder
|
|
40
|
-
dispatch('ready')
|
|
41
35
|
}
|
|
42
36
|
</script>
|
|
43
37
|
|
|
38
|
+
<div
|
|
39
|
+
id={fieldId}
|
|
40
|
+
{@attach geocoderAttachment(optionsWithDefaults, { onresults, onresult, onloading, onerror, onclear, onload })}
|
|
41
|
+
onready={init}
|
|
42
|
+
{...rest}
|
|
43
|
+
></div>
|
|
44
|
+
|
|
44
45
|
<style>
|
|
45
46
|
div {
|
|
46
47
|
padding: 0;
|
|
47
48
|
}
|
|
48
|
-
</style>
|
|
49
|
+
</style>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { load } from '../asset-loader.js'
|
|
2
|
+
|
|
3
|
+
export default function geocoderAttachment (options, { onresults, onresult, onloading, onerror, onclear, onready }) {
|
|
4
|
+
return (element) => {
|
|
5
|
+
let geocoderInstance
|
|
6
|
+
|
|
7
|
+
const resources = [
|
|
8
|
+
{ type: 'script', value: `//api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/${options.version}/mapbox-gl-geocoder.min.js`, id: 'byk-gc-js' }
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
const customStylesheetUrl = options.customStylesheetUrl
|
|
12
|
+
if (customStylesheetUrl) {
|
|
13
|
+
resources.push({ type: 'link', value: customStylesheetUrl, id: 'byk-gcsu-css' })
|
|
14
|
+
} else {
|
|
15
|
+
resources.push({ type: 'link', value: `//api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/${options.version}/mapbox-gl-geocoder.css`, id: 'byk-gc-css' })
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
load(resources, () => {
|
|
19
|
+
geocoderInstance = new window.MapboxGeocoder(options)
|
|
20
|
+
geocoderInstance.addTo(`#${element.id}`)
|
|
21
|
+
if (options.value) {
|
|
22
|
+
geocoderInstance.setInput(options.value)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
geocoderInstance.on('results', (ev) => {
|
|
26
|
+
onresults?.(ev)
|
|
27
|
+
})
|
|
28
|
+
geocoderInstance.on('result', (ev) => {
|
|
29
|
+
console.log('result', onresult, ev)
|
|
30
|
+
onresult?.(ev)
|
|
31
|
+
})
|
|
32
|
+
geocoderInstance.on('loading', (ev) => {
|
|
33
|
+
onloading?.(ev)
|
|
34
|
+
})
|
|
35
|
+
geocoderInstance.on('error', (ev) => {
|
|
36
|
+
onerror?.(ev)
|
|
37
|
+
})
|
|
38
|
+
geocoderInstance.on('clear', (ev) => {
|
|
39
|
+
onclear?.(ev)
|
|
40
|
+
})
|
|
41
|
+
geocoderInstance.on('load', (ev) => {
|
|
42
|
+
onready?.({ ...ev, geocoder: geocoderInstance })
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
return () => {
|
|
47
|
+
geocoderInstance && geocoderInstance.remove && geocoderInstance.remove()
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/lib/map/Map.svelte
CHANGED
|
@@ -1,60 +1,40 @@
|
|
|
1
|
-
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
|
2
|
-
<div
|
|
3
|
-
use:action={optionsWithDefaults}
|
|
4
|
-
on:ready={init}
|
|
5
|
-
on:recentre
|
|
6
|
-
on:dragend
|
|
7
|
-
on:click
|
|
8
|
-
on:zoomstart
|
|
9
|
-
on:zoom
|
|
10
|
-
on:zoomend
|
|
11
|
-
on:drag
|
|
12
|
-
on:keydown
|
|
13
|
-
on:keyup
|
|
14
|
-
role="application"
|
|
15
|
-
>
|
|
16
|
-
{#if map}
|
|
17
|
-
<slot></slot>
|
|
18
|
-
{/if}
|
|
19
|
-
</div>
|
|
20
|
-
|
|
21
|
-
<style>
|
|
22
|
-
div {
|
|
23
|
-
width: 100%;
|
|
24
|
-
height: 100%;
|
|
25
|
-
}
|
|
26
|
-
</style>
|
|
27
|
-
|
|
28
1
|
<script>
|
|
29
|
-
import { setContext,
|
|
2
|
+
import { setContext, untrack } from 'svelte'
|
|
30
3
|
import { contextKey } from '../mapbox.js'
|
|
31
|
-
import
|
|
32
|
-
import { EventQueue } from '../queue.js'
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
4
|
+
import mapAttachment from './map-attachment.js'
|
|
5
|
+
import { EventQueue } from '../queue.svelte.js'
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
version = 'v3.20.0',
|
|
9
|
+
center = [ 0, 0 ],
|
|
10
|
+
zoom = $bindable(9),
|
|
11
|
+
zoomRate = 1,
|
|
12
|
+
wheelZoomRate = 1,
|
|
13
|
+
options = {},
|
|
14
|
+
accessToken,
|
|
15
|
+
customStylesheetUrl = false,
|
|
16
|
+
style = 'mapbox://styles/mapbox/streets-v11',
|
|
17
|
+
children,
|
|
18
|
+
onready,
|
|
19
|
+
ondragend,
|
|
20
|
+
ondrag,
|
|
21
|
+
onmoveend,
|
|
22
|
+
onzoomstart,
|
|
23
|
+
onzoom,
|
|
24
|
+
onzoomend,
|
|
25
|
+
...rest
|
|
26
|
+
} = $props()
|
|
27
|
+
|
|
28
|
+
let map = $state()
|
|
29
|
+
let mapbox = $state()
|
|
46
30
|
|
|
47
31
|
setContext(contextKey, {
|
|
48
32
|
getMap: () => map,
|
|
49
33
|
getMapbox: () => mapbox
|
|
50
34
|
})
|
|
51
35
|
|
|
52
|
-
|
|
53
|
-
let mapbox
|
|
54
|
-
|
|
55
|
-
const optionsWithDefaults = Object.assign({
|
|
36
|
+
const optionsWithDefaults = $derived.by(() => Object.assign({
|
|
56
37
|
accessToken,
|
|
57
|
-
container,
|
|
58
38
|
style,
|
|
59
39
|
center,
|
|
60
40
|
zoom,
|
|
@@ -62,21 +42,32 @@
|
|
|
62
42
|
wheelZoomRate,
|
|
63
43
|
version,
|
|
64
44
|
customStylesheetUrl,
|
|
65
|
-
|
|
66
|
-
}
|
|
45
|
+
...options
|
|
46
|
+
}))
|
|
67
47
|
|
|
68
48
|
const queue = new EventQueue()
|
|
69
49
|
|
|
70
|
-
function init (
|
|
50
|
+
function init (detail) {
|
|
71
51
|
map = detail.map
|
|
72
52
|
mapbox = detail.mapbox
|
|
73
53
|
queue.start(map)
|
|
74
|
-
|
|
54
|
+
|
|
55
|
+
map.on('zoomend', (e) => {
|
|
56
|
+
zoom = map.getZoom()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
onready?.({ map, mapbox })
|
|
75
60
|
}
|
|
76
61
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
62
|
+
$effect(() => {
|
|
63
|
+
return () => {
|
|
64
|
+
queue.stop()
|
|
65
|
+
map = undefined
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
$effect(() => {
|
|
70
|
+
zoom && setZoom(zoom)
|
|
80
71
|
})
|
|
81
72
|
|
|
82
73
|
export function fitBounds (bbox, data = {}) {
|
|
@@ -110,6 +101,24 @@
|
|
|
110
101
|
export function getMapbox () {
|
|
111
102
|
return mapbox
|
|
112
103
|
}
|
|
113
|
-
|
|
114
|
-
$: zoom && setZoom(zoom)
|
|
115
104
|
</script>
|
|
105
|
+
|
|
106
|
+
<div
|
|
107
|
+
{@attach mapAttachment(
|
|
108
|
+
optionsWithDefaults,
|
|
109
|
+
{ onready: init, ondragend, ondrag, onmoveend, onzoomstart, onzoom, onzoomend }
|
|
110
|
+
)}
|
|
111
|
+
{...rest}
|
|
112
|
+
role="presentation"
|
|
113
|
+
>
|
|
114
|
+
{#if map}
|
|
115
|
+
{@render children?.()}
|
|
116
|
+
{/if}
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
<style>
|
|
120
|
+
div {
|
|
121
|
+
width: 100%;
|
|
122
|
+
height: 100%;
|
|
123
|
+
}
|
|
124
|
+
</style>
|
|
@@ -10,36 +10,40 @@
|
|
|
10
10
|
return Math.round(Math.random() * 255)
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
let {
|
|
14
|
+
lat,
|
|
15
|
+
lng,
|
|
16
|
+
label = 'Marker',
|
|
17
|
+
popupClassName = 'beyonk-mapbox-popup',
|
|
18
|
+
markerOffset = [ 0, 0 ],
|
|
19
|
+
popupOffset = 10,
|
|
20
|
+
color = randomColour(),
|
|
21
|
+
popup = true,
|
|
22
|
+
popupOptions = {},
|
|
23
|
+
markerOptions = {},
|
|
24
|
+
children,
|
|
25
|
+
popupContent
|
|
26
|
+
} = $props()
|
|
27
|
+
|
|
28
|
+
let marker = $state()
|
|
29
|
+
let element = $state()
|
|
30
|
+
let elementPopup = $state()
|
|
31
|
+
|
|
13
32
|
function move (lng, lat) {
|
|
14
33
|
marker.setLngLat({ lng, lat })
|
|
15
34
|
}
|
|
16
35
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
export let popupClassName = 'beyonk-mapbox-popup'
|
|
21
|
-
export let markerOffset = [ 0, 0 ]
|
|
22
|
-
export let popupOffset = 10
|
|
23
|
-
export let color = randomColour()
|
|
24
|
-
export let popup = true
|
|
25
|
-
export let popupOptions = {}
|
|
26
|
-
export let markerOptions = {}
|
|
27
|
-
|
|
28
|
-
let marker
|
|
29
|
-
let element
|
|
30
|
-
let elementPopup
|
|
31
|
-
|
|
32
|
-
$: marker && move(lng, lat)
|
|
36
|
+
$effect(() => {
|
|
37
|
+
if (marker) move(lng, lat)
|
|
38
|
+
})
|
|
33
39
|
|
|
34
40
|
onMount(() => {
|
|
35
41
|
const namedParams = Object.assign(
|
|
36
|
-
{
|
|
37
|
-
offset: markerOffset
|
|
38
|
-
},
|
|
42
|
+
{ offset: markerOffset },
|
|
39
43
|
element.hasChildNodes() ? { element } : { color }
|
|
40
44
|
)
|
|
41
45
|
marker = new mapbox.Marker(Object.assign(namedParams, markerOptions))
|
|
42
|
-
|
|
46
|
+
|
|
43
47
|
if (popup) {
|
|
44
48
|
const namedPopupParams = { offset: popupOffset, className: popupClassName }
|
|
45
49
|
const popupEl = new mapbox.Popup(Object.assign(namedPopupParams, popupOptions))
|
|
@@ -48,7 +52,6 @@
|
|
|
48
52
|
} else {
|
|
49
53
|
popupEl.setText(label)
|
|
50
54
|
}
|
|
51
|
-
|
|
52
55
|
marker.setPopup(popupEl)
|
|
53
56
|
}
|
|
54
57
|
|
|
@@ -67,9 +70,9 @@
|
|
|
67
70
|
</script>
|
|
68
71
|
|
|
69
72
|
<div bind:this={element}>
|
|
70
|
-
|
|
73
|
+
{@render children?.()}
|
|
71
74
|
</div>
|
|
72
75
|
|
|
73
76
|
<div class='popup' bind:this={elementPopup}>
|
|
74
|
-
|
|
77
|
+
{@render popupContent?.()}
|
|
75
78
|
</div>
|
|
@@ -1,56 +1,33 @@
|
|
|
1
|
-
<div
|
|
2
|
-
bind:this={dispatcher}
|
|
3
|
-
on:error
|
|
4
|
-
on:geolocate
|
|
5
|
-
on:outofmaxbounds
|
|
6
|
-
on:trackuserlocationend
|
|
7
|
-
on:trackuserlocationstart
|
|
8
|
-
/>
|
|
9
|
-
|
|
10
1
|
<script>
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
},
|
|
37
|
-
trackuserlocationstart: (el, ev) => {
|
|
38
|
-
return [ 'trackuserlocationstart', ev ]
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const geolocate = new mapbox.GeolocateControl(options)
|
|
43
|
-
map.addControl(geolocate, position)
|
|
44
|
-
|
|
45
|
-
onMount(() => {
|
|
46
|
-
return bindEvents(geolocate, handlers, mapbox, dispatcher)
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
export function trigger () {
|
|
50
|
-
geolocate.trigger()
|
|
51
|
-
}
|
|
2
|
+
import { getContext, onMount, untrack } from 'svelte'
|
|
3
|
+
import { contextKey } from '../../mapbox.js'
|
|
4
|
+
|
|
5
|
+
const { getMap, getMapbox } = getContext(contextKey)
|
|
6
|
+
const map = getMap()
|
|
7
|
+
const mapbox = getMapbox()
|
|
8
|
+
|
|
9
|
+
let { position = 'top-left', options = {}, onerror, ongeolocate, onoutofmaxbounds, ontrackuserlocationend, ontrackuserlocationstart, ...rest } = $props()
|
|
10
|
+
|
|
11
|
+
let dispatcher = $state()
|
|
12
|
+
|
|
13
|
+
const geolocate = new mapbox.GeolocateControl(untrack(() => options))
|
|
14
|
+
map.addControl(geolocate, untrack(() => position))
|
|
15
|
+
|
|
16
|
+
onMount(() => {
|
|
17
|
+
geolocate.on('error', onerror)
|
|
18
|
+
geolocate.on('geolocate', ongeolocate)
|
|
19
|
+
geolocate.on('outofmaxbounds', onoutofmaxbounds)
|
|
20
|
+
geolocate.on('trackuserlocationend', ontrackuserlocationend)
|
|
21
|
+
geolocate.on('trackuserlocationstart', ontrackuserlocationstart)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
export function trigger () {
|
|
25
|
+
geolocate.trigger()
|
|
26
|
+
}
|
|
52
27
|
</script>
|
|
53
28
|
|
|
29
|
+
<div bind:this={dispatcher} {...rest}></div>
|
|
30
|
+
|
|
54
31
|
<style>
|
|
55
|
-
|
|
32
|
+
div { display: none; }
|
|
56
33
|
</style>
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { getContext, untrack } from 'svelte'
|
|
3
|
+
import { contextKey } from '../../mapbox.js'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
const { getMap, getMapbox } = getContext(contextKey)
|
|
6
|
+
const map = getMap()
|
|
7
|
+
const mapbox = getMapbox()
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
export let options = {}
|
|
9
|
+
let { position = 'top-right', options = {} } = $props()
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
</script>
|
|
11
|
+
const nav = new mapbox.NavigationControl(untrack(() => options))
|
|
12
|
+
map.addControl(nav, untrack(() => position))
|
|
13
|
+
</script>
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { getContext, untrack } from 'svelte'
|
|
3
|
+
import { contextKey } from '../../mapbox.js'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
const { getMap, getMapbox } = getContext(contextKey)
|
|
6
|
+
const map = getMap()
|
|
7
|
+
const mapbox = getMapbox()
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
export let options = {}
|
|
9
|
+
let { position = 'bottom-right', options = {} } = $props()
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
const optionsWithDefaults = untrack(() => Object.assign({
|
|
12
|
+
maxWidth: 80,
|
|
13
|
+
unit: 'metric'
|
|
14
|
+
}, options))
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
</script>
|
|
16
|
+
const scale = new mapbox.ScaleControl(optionsWithDefaults)
|
|
17
|
+
map.addControl(scale, untrack(() => position))
|
|
18
|
+
</script>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { load } from '../asset-loader.js'
|
|
2
|
+
|
|
3
|
+
export default function mapAttachment (options = {}, { ondragend, ondrag, onmoveend, onzoomstart, onzoom, onzoomend, onready }) {
|
|
4
|
+
return (element) => {
|
|
5
|
+
let map
|
|
6
|
+
|
|
7
|
+
function init (options) {
|
|
8
|
+
window.mapboxgl.accessToken = options.accessToken
|
|
9
|
+
const el = new window.mapboxgl.Map(options)
|
|
10
|
+
|
|
11
|
+
el.on('dragend', () => {
|
|
12
|
+
ondragend?.({ center: el.getCenter() })
|
|
13
|
+
})
|
|
14
|
+
el.on('drag', () => {
|
|
15
|
+
ondrag?.({ center: el.getCenter() })
|
|
16
|
+
})
|
|
17
|
+
el.on('moveend', () => {
|
|
18
|
+
onmoveend?.({ center: el.getCenter() })
|
|
19
|
+
})
|
|
20
|
+
el.on('zoomstart', () => {
|
|
21
|
+
onzoomstart?.({ zoom: el.getZoom() })
|
|
22
|
+
})
|
|
23
|
+
el.on('zoom', () => {
|
|
24
|
+
onzoom?.({ zoom: el.getZoom() })
|
|
25
|
+
})
|
|
26
|
+
el.on('zoomend', () => {
|
|
27
|
+
onzoomend?.({ zoom: el.getZoom() })
|
|
28
|
+
})
|
|
29
|
+
el.on('load', () => {
|
|
30
|
+
onready?.({ map: el, mapbox: window.mapboxgl })
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const resources = [
|
|
35
|
+
{ type: 'script', attr: 'src', value: `//api.mapbox.com/mapbox-gl-js/${options.version}/mapbox-gl.js`, id: 'byk-gl-js' },
|
|
36
|
+
{ type: 'link', attr: 'href', value: `//api.mapbox.com/mapbox-gl-js/${options.version}/mapbox-gl.css`, id: 'byk-gl-css' }
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
const customStylesheetUrl = options.customStylesheetUrl
|
|
40
|
+
if (customStylesheetUrl) {
|
|
41
|
+
resources.push({ type: 'link', attr: 'href', value: customStylesheetUrl, id: 'byk-mcsu-css' })
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let unbind = () => {}
|
|
45
|
+
load(resources, () => {
|
|
46
|
+
unbind = init({ ...options, container: element })
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
destroy () {
|
|
51
|
+
unbind()
|
|
52
|
+
map && map.remove && map.remove()
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export class EventQueue {
|
|
2
|
+
queue = []
|
|
3
|
+
started = false
|
|
4
|
+
map = null
|
|
5
|
+
|
|
6
|
+
send (command, params = []) {
|
|
7
|
+
if (!command) { return }
|
|
8
|
+
this.queue.push([ command, params ])
|
|
9
|
+
this.#process()
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
start (map) {
|
|
13
|
+
this.started = true
|
|
14
|
+
this.map = map
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
#process () {
|
|
18
|
+
if (!this.started) { return }
|
|
19
|
+
while (this.queue.length) {
|
|
20
|
+
const [ command, params ] = this.queue.shift()
|
|
21
|
+
this.map[command].apply(this.map, params)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
stop () {
|
|
26
|
+
if (!this.started) { return }
|
|
27
|
+
this.queue = []
|
|
28
|
+
this.map = null
|
|
29
|
+
this.started = false
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/routes/+page.svelte
CHANGED
|
@@ -1,3 +1,47 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { PUBLIC_MAPBOX_TOKEN } from '$env/static/public'
|
|
3
|
+
import { Map, Geocoder, Marker, controls } from '$lib/components.js'
|
|
4
|
+
import Earthquakes from './_Earthquakes.svelte'
|
|
5
|
+
import { untrack } from 'svelte'
|
|
6
|
+
|
|
7
|
+
const { GeolocateControl, NavigationControl } = controls
|
|
8
|
+
|
|
9
|
+
let place = $state()
|
|
10
|
+
let placeName = $derived(untrack(() => place?.place_name || '(Near London)'))
|
|
11
|
+
let page = $state('about')
|
|
12
|
+
let center = $state({ lat: 53.3358627, lng: -2.8572362 })
|
|
13
|
+
let marker = $derived(center)
|
|
14
|
+
let zoom = $state(11.15)
|
|
15
|
+
let mapComponent = $state()
|
|
16
|
+
|
|
17
|
+
function navigate (next) {
|
|
18
|
+
page = next
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function randomLng () {
|
|
22
|
+
return 77 + (Math.random() - 0.5) * 30
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function randomLat () {
|
|
26
|
+
return 13 + (Math.random() - 0.5) * 30
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function flyToRandomPlace () {
|
|
30
|
+
mapComponent.flyTo({
|
|
31
|
+
center: [ randomLng(), randomLat() ],
|
|
32
|
+
essential: true
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function recentre (result) {
|
|
37
|
+
center = result.center
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function drag (result) {
|
|
41
|
+
marker = result.center
|
|
42
|
+
}
|
|
43
|
+
</script>
|
|
44
|
+
|
|
1
45
|
<header>
|
|
2
46
|
<div class="container">
|
|
3
47
|
<div class="row">
|
|
@@ -31,7 +75,7 @@
|
|
|
31
75
|
</div>
|
|
32
76
|
</div>
|
|
33
77
|
<div class="col-lg-2 col-md-3 col-xs-12 right">
|
|
34
|
-
<a class="btn" href="http://www.github.com/beyonk
|
|
78
|
+
<a class="btn" href="http://www.github.com/beyonk/svelte-mapbox">Github</a>
|
|
35
79
|
</div>
|
|
36
80
|
</div>
|
|
37
81
|
</div>
|
|
@@ -42,39 +86,43 @@
|
|
|
42
86
|
<div class="row">
|
|
43
87
|
<aside>
|
|
44
88
|
<div class="menu-box">
|
|
45
|
-
<h4>Navigation</h4>
|
|
89
|
+
<h4>Navigation</h4>
|
|
46
90
|
<nav>
|
|
47
91
|
<ul>
|
|
48
|
-
<li><a href="#geocoder"
|
|
49
|
-
<li><a href="#map"
|
|
50
|
-
</ul>
|
|
92
|
+
<li><a href="#geocoder" onclick={() => navigate('geocoder')} class:current={page === 'geocoder'}>Geocoder</a></li>
|
|
93
|
+
<li><a href="#map" onclick={() => navigate('map')} class:current={page === 'map'}>Map</a></li>
|
|
94
|
+
</ul>
|
|
51
95
|
</nav>
|
|
52
96
|
</div>
|
|
53
97
|
</aside>
|
|
54
98
|
<div class="content-info">
|
|
55
99
|
<div class="action-buttons">
|
|
56
|
-
<button id="fly-to"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
<button
|
|
61
|
-
id="change-zoom"
|
|
62
|
-
on:click={() => (zoom = Math.floor(Math.random() * 10))}
|
|
63
|
-
>Change Zoom Level</button
|
|
64
|
-
>
|
|
65
|
-
</div>
|
|
100
|
+
<button id="fly-to" onclick={flyToRandomPlace}>Fly to random location</button>
|
|
101
|
+
<button id="change-zoom" onclick={() => (zoom = Math.floor(Math.random() * 10))}>Change Zoom Level</button>
|
|
102
|
+
</div>
|
|
66
103
|
|
|
67
104
|
<div class="section-txt" id="geocoder">
|
|
68
105
|
<form>
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
106
|
+
<Geocoder
|
|
107
|
+
bind:value={placeName}
|
|
108
|
+
accessToken={PUBLIC_MAPBOX_TOKEN}
|
|
109
|
+
onresult={({ result }) => {
|
|
110
|
+
console.log('sets center', result.center)
|
|
111
|
+
mapComponent.setCenter(result.center, 14)
|
|
112
|
+
place = result
|
|
113
|
+
}}
|
|
114
|
+
onclear={() => {
|
|
115
|
+
mapComponent.setCenter({ lng: 0, lat: 0 })
|
|
116
|
+
}}
|
|
117
|
+
/>
|
|
118
|
+
{#if place}
|
|
119
|
+
<dl>
|
|
120
|
+
<dt>Name:</dt>
|
|
121
|
+
<dd>{place.place_name}</dd>
|
|
122
|
+
<dt>Geolocation:</dt>
|
|
123
|
+
<dd>lat: {place.geometry.coordinates[1]}, lng: {place.geometry.coordinates[0]}</dd>
|
|
124
|
+
</dl>
|
|
125
|
+
{/if}
|
|
78
126
|
</form>
|
|
79
127
|
</div>
|
|
80
128
|
<div class="section-txt" id="map">
|
|
@@ -82,14 +130,14 @@
|
|
|
82
130
|
<Map
|
|
83
131
|
bind:this={mapComponent}
|
|
84
132
|
accessToken={PUBLIC_MAPBOX_TOKEN}
|
|
85
|
-
|
|
86
|
-
|
|
133
|
+
onrecentre={recentre}
|
|
134
|
+
ondrag={drag}
|
|
87
135
|
{center}
|
|
88
136
|
bind:zoom
|
|
89
137
|
>
|
|
90
138
|
<Earthquakes />
|
|
91
139
|
<NavigationControl />
|
|
92
|
-
<GeolocateControl
|
|
140
|
+
<GeolocateControl ongeolocate={({ result }) => console.log('geolocated', result)} />
|
|
93
141
|
<Marker lat={marker.lat} lng={marker.lng} />
|
|
94
142
|
</Map>
|
|
95
143
|
</div>
|
|
@@ -117,7 +165,7 @@
|
|
|
117
165
|
<div class="container">
|
|
118
166
|
<div class="row">
|
|
119
167
|
<div class="col-lg-12 center">
|
|
120
|
-
©
|
|
168
|
+
© 2026 Beyonk. All rights reserved.
|
|
121
169
|
</div>
|
|
122
170
|
</div>
|
|
123
171
|
</div>
|
|
@@ -157,55 +205,4 @@
|
|
|
157
205
|
color: #fff;
|
|
158
206
|
background: #ee8a65;
|
|
159
207
|
}
|
|
160
|
-
|
|
161
208
|
</style>
|
|
162
|
-
|
|
163
|
-
<script>
|
|
164
|
-
import { PUBLIC_MAPBOX_TOKEN } from '$env/static/public'
|
|
165
|
-
import { Map, Geocoder, Marker, controls } from '$lib/components.js'
|
|
166
|
-
import Earthquakes from './_Earthquakes.svelte'
|
|
167
|
-
|
|
168
|
-
const { GeolocateControl, NavigationControl } = controls
|
|
169
|
-
const place = null
|
|
170
|
-
|
|
171
|
-
let page = 'about'
|
|
172
|
-
let center = { lat: 53.3358627, lng: -2.8572362 }
|
|
173
|
-
let marker = center
|
|
174
|
-
let zoom = 11.15
|
|
175
|
-
let mapComponent
|
|
176
|
-
|
|
177
|
-
function navigate (next) {
|
|
178
|
-
page = next
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function placeChanged (e) {
|
|
182
|
-
const { result } = e.detail
|
|
183
|
-
mapComponent.setCenter(result.center, 14)
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function randomLng () {
|
|
187
|
-
return 77 + (Math.random() - 0.5) * 30
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
function randomLat () {
|
|
191
|
-
return 13 + (Math.random() - 0.5) * 30
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
function flyToRandomPlace () {
|
|
195
|
-
mapComponent.flyTo({
|
|
196
|
-
center: [
|
|
197
|
-
randomLng(),
|
|
198
|
-
randomLat()
|
|
199
|
-
],
|
|
200
|
-
essential: true
|
|
201
|
-
})
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function recentre ({ detail }) {
|
|
205
|
-
center = detail.center
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function drag ({ detail }) {
|
|
209
|
-
marker = detail.center
|
|
210
|
-
}
|
|
211
|
-
</script>
|
package/svelte.config.js
CHANGED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { fileURLToPath } from "node:url";
|
|
3
|
-
import js from "@eslint/js";
|
|
4
|
-
import { FlatCompat } from "@eslint/eslintrc";
|
|
5
|
-
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
-
const __dirname = path.dirname(__filename);
|
|
8
|
-
const compat = new FlatCompat({
|
|
9
|
-
baseDirectory: __dirname,
|
|
10
|
-
recommendedConfig: js.configs.recommended,
|
|
11
|
-
allConfig: js.configs.all
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
export default [{
|
|
15
|
-
ignores: ["**/package", "**/.svelte-kit"],
|
|
16
|
-
}, ...compat.extends("@beyonk/eslint-config/svelte"), {
|
|
17
|
-
languageOptions: {
|
|
18
|
-
ecmaVersion: 2020,
|
|
19
|
-
sourceType: "module",
|
|
20
|
-
},
|
|
21
|
-
}];
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
function bindEvents (el, handlers, mapbox, node) {
|
|
2
|
-
const unbindings = []
|
|
3
|
-
|
|
4
|
-
for (const [ handler, fn ] of Object.entries(handlers)) {
|
|
5
|
-
const cmd = ev => {
|
|
6
|
-
const [ eventName, detail ] = fn(el, ev, mapbox)
|
|
7
|
-
node.dispatchEvent(
|
|
8
|
-
new CustomEvent(eventName, { detail })
|
|
9
|
-
)
|
|
10
|
-
}
|
|
11
|
-
el.on(handler, cmd)
|
|
12
|
-
unbindings.push([ handler, cmd ])
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return () => {
|
|
16
|
-
for (const [ handler, cmd ] of unbindings) {
|
|
17
|
-
el.off(handler, cmd)
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export {
|
|
23
|
-
bindEvents
|
|
24
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { load } from '../asset-loader.js'
|
|
2
|
-
import { bindEvents } from '../event-bindings.js'
|
|
3
|
-
|
|
4
|
-
export default function action (node, options = {}) {
|
|
5
|
-
let map
|
|
6
|
-
|
|
7
|
-
const resources = [
|
|
8
|
-
{ type: 'script', value: `//api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/${options.version}/mapbox-gl-geocoder.min.js`, id: 'byk-gc-js' }
|
|
9
|
-
]
|
|
10
|
-
|
|
11
|
-
const customStylesheetUrl = options.customStylesheetUrl
|
|
12
|
-
if (customStylesheetUrl) {
|
|
13
|
-
resources.push({ type: 'link', value: customStylesheetUrl, id: 'byk-gcsu-css' })
|
|
14
|
-
} else {
|
|
15
|
-
resources.push({ type: 'link', value: `//api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/${options.version}/mapbox-gl-geocoder.css`, id: 'byk-gc-css' })
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
let unbind = () => {}
|
|
19
|
-
load(resources, () => {
|
|
20
|
-
unbind = init(options, node)
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
return {
|
|
24
|
-
destroy () {
|
|
25
|
-
unbind()
|
|
26
|
-
map && map.remove && map.remove()
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function init (options, node) {
|
|
32
|
-
const geocoder = new window.MapboxGeocoder(options)
|
|
33
|
-
geocoder.addTo(`#${node.id}`)
|
|
34
|
-
if (options.value) {
|
|
35
|
-
geocoder.setInput(options.value)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return bindEvents(geocoder, handlers, false, node)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const handlers = {
|
|
42
|
-
results: (el, ev) => {
|
|
43
|
-
return [ 'results', ev ]
|
|
44
|
-
},
|
|
45
|
-
result: (el, ev) => {
|
|
46
|
-
return [ 'result', ev ]
|
|
47
|
-
},
|
|
48
|
-
loading: (el, ev) => {
|
|
49
|
-
return [ 'loading', ev ]
|
|
50
|
-
},
|
|
51
|
-
error: (el, ev) => {
|
|
52
|
-
return [ 'error', ev ]
|
|
53
|
-
},
|
|
54
|
-
clear: (el, ev) => {
|
|
55
|
-
return [ 'clear', ev ]
|
|
56
|
-
},
|
|
57
|
-
load: el => {
|
|
58
|
-
return [ 'ready', { geocoder: el } ]
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { load } from '../asset-loader.js'
|
|
2
|
-
import { bindEvents } from '../event-bindings.js'
|
|
3
|
-
|
|
4
|
-
export default function action (node, options = {}) {
|
|
5
|
-
let map
|
|
6
|
-
|
|
7
|
-
const resources = [
|
|
8
|
-
{ type: 'script', attr: 'src', value: `//api.mapbox.com/mapbox-gl-js/${options.version}/mapbox-gl.js`, id: 'byk-gl-js' },
|
|
9
|
-
{ type: 'link', attr: 'href', value: `//api.mapbox.com/mapbox-gl-js/${options.version}/mapbox-gl.css`, id: 'byk-gl-css' }
|
|
10
|
-
]
|
|
11
|
-
|
|
12
|
-
const customStylesheetUrl = options.customStylesheetUrl
|
|
13
|
-
if (customStylesheetUrl) {
|
|
14
|
-
resources.push({ type: 'link', attr: 'href', value: customStylesheetUrl, id: 'byk-mcsu-css' })
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
let unbind = () => {}
|
|
18
|
-
load(resources, () => {
|
|
19
|
-
unbind = init({ ...options, container: node }, node)
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
return {
|
|
23
|
-
destroy () {
|
|
24
|
-
unbind()
|
|
25
|
-
map && map.remove && map.remove()
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function init (options, node) {
|
|
31
|
-
window.mapboxgl.accessToken = options.accessToken
|
|
32
|
-
const el = new window.mapboxgl.Map(options)
|
|
33
|
-
|
|
34
|
-
return bindEvents(el, handlers, window.mapboxgl, node)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const handlers = {
|
|
38
|
-
dragend: el => {
|
|
39
|
-
return [ 'dragend', { center: el.getCenter() } ]
|
|
40
|
-
},
|
|
41
|
-
drag: el => {
|
|
42
|
-
return [ 'drag', { center: el.getCenter() } ]
|
|
43
|
-
},
|
|
44
|
-
moveend: el => {
|
|
45
|
-
return [ 'recentre', { center: el.getCenter() } ]
|
|
46
|
-
},
|
|
47
|
-
click: (el, { lngLat }) => {
|
|
48
|
-
return [ 'click', { lng: lngLat.lng, lat: lngLat.lat } ]
|
|
49
|
-
},
|
|
50
|
-
zoomstart: el => {
|
|
51
|
-
return [ 'zoomstart', { zoom: el.getZoom() } ]
|
|
52
|
-
},
|
|
53
|
-
zoom: el => {
|
|
54
|
-
return [ 'zoom', { zoom: el.getZoom() } ]
|
|
55
|
-
},
|
|
56
|
-
zoomend: el => {
|
|
57
|
-
return [ 'zoomend', { zoom: el.getZoom() } ]
|
|
58
|
-
},
|
|
59
|
-
load: (el, ev, mapbox) => {
|
|
60
|
-
return [ 'ready', { map: el, mapbox } ]
|
|
61
|
-
}
|
|
62
|
-
}
|
package/src/lib/queue.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { writable } from 'svelte/store'
|
|
2
|
-
|
|
3
|
-
export class EventQueue {
|
|
4
|
-
constructor () {
|
|
5
|
-
this.queue = writable([])
|
|
6
|
-
this.unsubscribe = null
|
|
7
|
-
this.started = false
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
send (command, params = []) {
|
|
11
|
-
if (!command) { return }
|
|
12
|
-
this.queue.update(q => ([ ...q, [ command, params ] ]))
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
start (map) {
|
|
16
|
-
this.unsubscribe = this.queue.subscribe(queue => {
|
|
17
|
-
while (queue.length) {
|
|
18
|
-
const [ command, params ] = queue.shift()
|
|
19
|
-
map[command].apply(map, params)
|
|
20
|
-
}
|
|
21
|
-
})
|
|
22
|
-
this.started = true
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
stop () {
|
|
26
|
-
if (!this.started) { return }
|
|
27
|
-
this.unsubscribe()
|
|
28
|
-
this.queue = writable([])
|
|
29
|
-
this.started = false
|
|
30
|
-
}
|
|
31
|
-
}
|