@superrouteca/smap-mapbox 1.1.5 → 1.1.6
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/CHANGELOG.md +7 -0
- package/README.md +35 -0
- package/package.json +2 -2
- package/src/index.js +4 -3
- package/src/plan.js +191 -0
- package/types/index.d.ts +39 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.6 — 2026-10-28
|
|
4
|
+
|
|
5
|
+
- Plan editor: `addPlanEditor(map, options)` edits a plan of routes on a Mapbox GL JS map — drag a stop within its
|
|
6
|
+
route or onto another route with mouse or touch (priced as a preview while dragging), take stops off, place new
|
|
7
|
+
orders, refine and undo or redo, each a call of the Open Platform's plan editing. The routes are drawn as layers of
|
|
8
|
+
the map and the ready-made panel in 14 languages sits in a corner as a control.
|
|
9
|
+
|
|
3
10
|
## 1.1.5 — 2026-10-28
|
|
4
11
|
|
|
5
12
|
- The version follows the shared 1.1.5 release; no change of its own.
|
package/README.md
CHANGED
|
@@ -126,6 +126,41 @@ sMap slot (`bottom` → `bottom`, `middle` → `labels`, `top` → `top`); optio
|
|
|
126
126
|
none; without any, a layer draws on top in the order added. `prefix` renames every source and layer; `layers` or
|
|
127
127
|
`filter` choose them. Icons of the style's own sprite are not loaded (a warning says so).
|
|
128
128
|
|
|
129
|
+
## Plan editor
|
|
130
|
+
|
|
131
|
+
`addPlanEditor(map, options)` lets a person edit a plan of routes on a Mapbox GL JS map (or an `SMapMapbox`): drag a
|
|
132
|
+
stop within its route or onto another route, take stops off, place new orders at the positions the service ranks
|
|
133
|
+
best, refine routes around locked stops, and undo or redo. Each edit is one call of the Open Platform's plan editing
|
|
134
|
+
with the whole plan; the answer replaces the routes, distances, times and violations drawn. Nothing is kept on a
|
|
135
|
+
server: keep the plan from the `change` event. The editor is the Web SDK's (`PlanEditor` of `@superrouteca/smap`), so
|
|
136
|
+
its calls, events and credentials are the same (see the Web SDK README, "Plan editor").
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
import { addPlanEditor } from '@superrouteca/smap-mapbox';
|
|
140
|
+
|
|
141
|
+
const plan = addPlanEditor(map, {
|
|
142
|
+
// Your own server mints the token with POST /v1/plan/token; or { key: 'smk_…' } with plan editing switched on.
|
|
143
|
+
credentials: { token: () => fetch('/plan-token').then((r) => r.json()) },
|
|
144
|
+
plan: { region: 'NA', profile: 'car', vehicles, jobs, routes },
|
|
145
|
+
language: 'fr',
|
|
146
|
+
});
|
|
147
|
+
plan.editor.on('change', (e) => save(e.plan));
|
|
148
|
+
// later
|
|
149
|
+
plan.remove();
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
- The plan is drawn as GeoJSON sources and layers named after `id` (default `plan`): `plan:legs` (with
|
|
153
|
+
`plan:legs-casing` under it), `plan:starts`, `plan:unassigned`, `plan:stops` and `plan:stops-label`; `before` puts
|
|
154
|
+
them under a layer of your style. They are added once the style has loaded (`plan.ready`).
|
|
155
|
+
- Press on a stop or an unassigned job and drag it: drop it on a stop to put it before that stop, on a route's line to
|
|
156
|
+
put it into that leg, or on a vehicle's start to make it the first stop. The map does not pan meanwhile, and the
|
|
157
|
+
plan with the stop at the target is priced as a preview (`preview: false` turns that off). Mouse and touch both work.
|
|
158
|
+
- The ready-made panel is a control (top right; `panel: { position, className, labels, label }`, or `panel: false`):
|
|
159
|
+
routes and totals, violations, undo / redo / refine, the unassigned jobs and insert positions, in 14 languages. Its
|
|
160
|
+
stylesheet is added to the page unless `css: false`.
|
|
161
|
+
- `editor: myEditor` binds an editor you made; `remove()` then leaves it running. `editor.destroy()` also removes
|
|
162
|
+
everything from the map.
|
|
163
|
+
|
|
129
164
|
## Example
|
|
130
165
|
|
|
131
166
|
`examples/index.html` shows both ways. Serve the repository root (for example `npx serve .`) and open
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superrouteca/smap-mapbox",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"description": "sMap for Mapbox GL JS: maps from Superroute's sMap service in Mapbox GL JS, and Mapbox GL JS styles and layers on an sMap map.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Goodneo Solutions",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
}
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@superrouteca/smap": "1.1.
|
|
62
|
+
"@superrouteca/smap": "1.1.6"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@types/geojson": "7946.0.16",
|
package/src/index.js
CHANGED
|
@@ -9,11 +9,12 @@ import * as sMapModule from '@superrouteca/smap';
|
|
|
9
9
|
import { SMapAccess, checkStyle, rasterPath, stylePath, FLAVORS, DEFAULT_BASE } from './common/access.js';
|
|
10
10
|
import { OSM_ATTRIBUTION, createBadge, injectCss } from './common/badge.js';
|
|
11
11
|
import { createEmbedded } from './common/embed.js';
|
|
12
|
+
import { addPlanEditor } from './plan.js';
|
|
12
13
|
|
|
13
14
|
const SDK = sMapModule.default && sMapModule.default.Map ? sMapModule.default : sMapModule;
|
|
14
15
|
|
|
15
|
-
export const version = '1.1.
|
|
16
|
-
export { FLAVORS as styles, checkStyle, rasterPath, stylePath, SMapAccess, DEFAULT_BASE, OSM_ATTRIBUTION };
|
|
16
|
+
export const version = '1.1.6';
|
|
17
|
+
export { FLAVORS as styles, checkStyle, rasterPath, stylePath, SMapAccess, DEFAULT_BASE, OSM_ATTRIBUTION, addPlanEditor };
|
|
17
18
|
|
|
18
19
|
const ACCESS_OPTIONS = ['baseUrl', 'token', 'getToken', 'apiKey', 'nodes', 'nearest', 'fetch', 'timeoutMs', 'client', 'access'];
|
|
19
20
|
const OWN_OPTIONS = ['style', 'language', 'basemap', 'buildings3D', 'sdk', 'popup', 'popupLoading', 'autoZoom', 'overlay'];
|
|
@@ -471,5 +472,5 @@ export function smapAccess(options) { return new SMapAccess(options); }
|
|
|
471
472
|
|
|
472
473
|
export { isMapboxSource, OSM_ATTRIBUTION as attribution };
|
|
473
474
|
|
|
474
|
-
const SMapMapboxModule = { version, styles: FLAVORS, SMapMapbox, createMap, switchBasemap, smapAccess, smapTransformRequest, SMapBadgeControl, SMapAccess, checkStyle, rasterPath };
|
|
475
|
+
const SMapMapboxModule = { version, styles: FLAVORS, SMapMapbox, createMap, switchBasemap, smapAccess, smapTransformRequest, SMapBadgeControl, SMapAccess, checkStyle, rasterPath, addPlanEditor };
|
|
475
476
|
export default SMapMapboxModule;
|
package/src/plan.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// The plan editor (Superroute OPEN-ROUTE-EDIT E10) on a Mapbox GL JS map: the plan drawn as GeoJSON sources and
|
|
2
|
+
// layers, stops dragged within and between routes through the map's layer events, and the ready-made panel as a
|
|
3
|
+
// control. The editor itself (state, calls, undo / redo, the panel) is the Web SDK's: PlanEditor and planEditorParts.
|
|
4
|
+
import * as sMapModule from '@superrouteca/smap';
|
|
5
|
+
|
|
6
|
+
const SDK = sMapModule.default && sMapModule.default.PlanEditor ? sMapModule.default : sMapModule;
|
|
7
|
+
|
|
8
|
+
/** Options of the binding, not of the editor. */
|
|
9
|
+
const OWN = ['editor', 'id', 'colors', 'preview', 'language', 'labels', 'panel', 'css', 'before', 'plan'];
|
|
10
|
+
const POSITIONS = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];
|
|
11
|
+
const fc = function (list) { return { type: 'FeatureCollection', features: list }; };
|
|
12
|
+
|
|
13
|
+
function editorOptions(options) {
|
|
14
|
+
const out = {};
|
|
15
|
+
Object.keys(options).forEach(function (k) { if (OWN.indexOf(k) < 0) { out[k] = options[k]; } });
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A plan editor on a Mapbox GL JS map (or an SMapMapbox: its `map` is used).
|
|
21
|
+
* const plan = addPlanEditor(map, { credentials: { token: getPlanToken }, plan, language: 'fr' });
|
|
22
|
+
* plan.editor.on('change', (e) => save(e.plan));
|
|
23
|
+
* Options: every PlanEditor option, or `editor` (an editor of your own to bind), plus `id` (default 'plan'),
|
|
24
|
+
* `colors`, `preview` (default true), `language`, `labels`, `panel` (true | false | { position, className, labels,
|
|
25
|
+
* label }), `css` (default true: the panel's stylesheet is added to the page), `before` (a layer id to draw under).
|
|
26
|
+
* @returns {{ editor, layerIds: string[], sourceIds: string[], control, panel, ready: Promise, features(): Object, remove(): void }}
|
|
27
|
+
*/
|
|
28
|
+
export function addPlanEditor(target, options) {
|
|
29
|
+
options = options || {};
|
|
30
|
+
const map = target && target.map && typeof target.map.addLayer === 'function' ? target.map : target;
|
|
31
|
+
if (!map || typeof map.addLayer !== 'function') { throw new Error('sMap: addPlanEditor(map, options) needs a Mapbox GL JS map'); }
|
|
32
|
+
const parts = SDK.planEditorParts;
|
|
33
|
+
const own = !options.editor;
|
|
34
|
+
const editor = options.editor || new SDK.PlanEditor(Object.assign(editorOptions(options), { plan: null }));
|
|
35
|
+
const id = options.id || 'plan';
|
|
36
|
+
const src = { legs: id + ':legs', starts: id + ':starts', unassigned: id + ':unassigned', stops: id + ':stops' };
|
|
37
|
+
const layers = {
|
|
38
|
+
casing: id + ':legs-casing', legs: id + ':legs', starts: id + ':starts', unassigned: id + ':unassigned', stops: id + ':stops', labels: id + ':stops-label',
|
|
39
|
+
};
|
|
40
|
+
const hitLayers = [layers.stops, layers.unassigned, layers.starts, layers.legs];
|
|
41
|
+
const drag = parts.planDrag(editor, { preview: options.preview !== false });
|
|
42
|
+
const container = map.getContainer ? map.getContainer() : null;
|
|
43
|
+
const doc = (container && container.ownerDocument) || (typeof document !== 'undefined' ? document : null);
|
|
44
|
+
let added = false;
|
|
45
|
+
let removed = false;
|
|
46
|
+
let current = null;
|
|
47
|
+
|
|
48
|
+
function features() { return parts.planFeatures(editor, id, options.colors); }
|
|
49
|
+
function draw() {
|
|
50
|
+
if (removed || !added) { return; }
|
|
51
|
+
current = features();
|
|
52
|
+
Object.keys(src).forEach(function (k) { const s = map.getSource(src[k]); if (s) { s.setData(fc(current[k])); } });
|
|
53
|
+
}
|
|
54
|
+
function addAll() {
|
|
55
|
+
if (removed || added) { return; }
|
|
56
|
+
current = features();
|
|
57
|
+
Object.keys(src).forEach(function (k) { map.addSource(src[k], { type: 'geojson', data: fc(current[k]) }); });
|
|
58
|
+
const before = options.before;
|
|
59
|
+
map.addLayer({ id: layers.casing, type: 'line', source: src.legs, layout: { 'line-cap': 'round', 'line-join': 'round' }, paint: { 'line-color': '#ffffff', 'line-width': 7 } }, before);
|
|
60
|
+
map.addLayer({ id: layers.legs, type: 'line', source: src.legs, layout: { 'line-cap': 'round', 'line-join': 'round' }, paint: { 'line-color': ['get', 'color'], 'line-width': 4 } }, before);
|
|
61
|
+
map.addLayer({ id: layers.starts, type: 'circle', source: src.starts, paint: { 'circle-radius': 8, 'circle-color': ['get', 'color'], 'circle-stroke-color': '#ffffff', 'circle-stroke-width': 2 } }, before);
|
|
62
|
+
map.addLayer({ id: layers.unassigned, type: 'circle', source: src.unassigned, paint: { 'circle-radius': 8, 'circle-color': '#9ca3af', 'circle-stroke-color': '#ffffff', 'circle-stroke-width': 2 } }, before);
|
|
63
|
+
map.addLayer({ id: layers.stops, type: 'circle', source: src.stops, paint: { 'circle-radius': 11, 'circle-color': ['get', 'color'], 'circle-stroke-color': ['get', 'border'], 'circle-stroke-width': 3 } }, before);
|
|
64
|
+
map.addLayer({
|
|
65
|
+
id: layers.labels, type: 'symbol', source: src.stops,
|
|
66
|
+
layout: { 'text-field': ['get', 'label'], 'text-size': 11, 'text-allow-overlap': true, 'text-ignore-placement': true },
|
|
67
|
+
paint: { 'text-color': '#ffffff' },
|
|
68
|
+
}, before);
|
|
69
|
+
added = true;
|
|
70
|
+
listen();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function hitsAt(point) {
|
|
74
|
+
if (typeof map.queryRenderedFeatures !== 'function') { return []; }
|
|
75
|
+
const box = [[point.x - 6, point.y - 6], [point.x + 6, point.y + 6]];
|
|
76
|
+
return (map.queryRenderedFeatures(box, { layers: hitLayers }) || []).filter(function (f) { return f && f.properties && f.properties.smap_plan === id; });
|
|
77
|
+
}
|
|
78
|
+
function setPan(on) { if (map.dragPan) { if (on) { map.dragPan.enable(); } else { map.dragPan.disable(); } } }
|
|
79
|
+
// The dragged pin follows the pointer; a redraw puts it back.
|
|
80
|
+
function follow(lngLat) {
|
|
81
|
+
const stopId = drag.dragging();
|
|
82
|
+
if (!current || !lngLat) { return; }
|
|
83
|
+
const kind = current.stops.some(function (f) { return f.properties.id === stopId; }) ? 'stops' : 'unassigned';
|
|
84
|
+
const s = map.getSource(src[kind]);
|
|
85
|
+
if (!s) { return; }
|
|
86
|
+
s.setData(fc(current[kind].map(function (f) {
|
|
87
|
+
return f.properties.id === stopId ? { type: 'Feature', properties: f.properties, geometry: { type: 'Point', coordinates: [lngLat.lng, lngLat.lat] } } : f;
|
|
88
|
+
})));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function down(e) {
|
|
92
|
+
if (removed || !e.point || (e.originalEvent && e.originalEvent.button)) { return; }
|
|
93
|
+
const hit = (e.features && e.features.length ? e.features : hitsAt(e.point)).filter(function (f) {
|
|
94
|
+
return f.properties && f.properties.smap_plan === id && (f.properties.kind === 'stop' || f.properties.kind === 'unassigned');
|
|
95
|
+
})[0];
|
|
96
|
+
if (!hit) { return; }
|
|
97
|
+
drag.start(hit.properties.id, e.point);
|
|
98
|
+
setPan(false);
|
|
99
|
+
if (e.preventDefault) { e.preventDefault(); }
|
|
100
|
+
}
|
|
101
|
+
function move(e) {
|
|
102
|
+
if (!drag.dragging() || !e.point) { return; }
|
|
103
|
+
drag.move(hitsAt(e.point), e.point);
|
|
104
|
+
if (drag.moved()) { follow(e.lngLat); }
|
|
105
|
+
}
|
|
106
|
+
function up(e) {
|
|
107
|
+
if (!drag.dragging()) { return; }
|
|
108
|
+
const moved = drag.moved();
|
|
109
|
+
setPan(true);
|
|
110
|
+
drag.end(e && e.point ? hitsAt(e.point) : null);
|
|
111
|
+
if (moved) { draw(); }
|
|
112
|
+
}
|
|
113
|
+
let listening = false;
|
|
114
|
+
function listen() {
|
|
115
|
+
if (listening) { return; }
|
|
116
|
+
listening = true;
|
|
117
|
+
[layers.stops, layers.unassigned].forEach(function (l) { map.on('mousedown', l, down); map.on('touchstart', l, down); });
|
|
118
|
+
map.on('mousemove', move);
|
|
119
|
+
map.on('touchmove', move);
|
|
120
|
+
map.on('mouseup', up);
|
|
121
|
+
map.on('touchend', up);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
let control = null;
|
|
125
|
+
let panel = null;
|
|
126
|
+
if (options.panel !== false && doc) {
|
|
127
|
+
const po = typeof options.panel === 'object' && options.panel ? options.panel : {};
|
|
128
|
+
if (options.css !== false) { parts.injectCss(doc); }
|
|
129
|
+
const language = options.language || (typeof navigator !== 'undefined' && navigator.language) || 'en';
|
|
130
|
+
panel = parts.createPanel(editor, { language, labels: po.labels || options.labels, document: doc, colors: options.colors, className: po.className });
|
|
131
|
+
const element = doc.createElement('div');
|
|
132
|
+
element.className = 'mapboxgl-ctrl smap-plan-control';
|
|
133
|
+
element.setAttribute('aria-label', po.label || parts.textsFor(language, po.labels || options.labels).editor);
|
|
134
|
+
element.appendChild(panel.element);
|
|
135
|
+
control = {
|
|
136
|
+
onAdd: function () { return element; },
|
|
137
|
+
onRemove: function () { if (element.parentNode) { element.parentNode.removeChild(element); } },
|
|
138
|
+
getDefaultPosition: function () { return 'top-right'; },
|
|
139
|
+
};
|
|
140
|
+
map.addControl(control, POSITIONS.indexOf(po.position) >= 0 ? po.position : 'top-right');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const onChange = function () { draw(); };
|
|
144
|
+
editor.on('change', onChange);
|
|
145
|
+
const gone = function () { handle.remove(); };
|
|
146
|
+
editor.on('destroy', gone);
|
|
147
|
+
const loaded = typeof map.isStyleLoaded === 'function' ? map.isStyleLoaded() : true;
|
|
148
|
+
const ready = loaded ? Promise.resolve() : new Promise(function (resolve) {
|
|
149
|
+
let done = false;
|
|
150
|
+
const go = function () { if (!done) { done = true; resolve(); } };
|
|
151
|
+
map.once('style.load', go);
|
|
152
|
+
map.once('load', go);
|
|
153
|
+
});
|
|
154
|
+
if (loaded) { addAll(); } else { ready.then(addAll); }
|
|
155
|
+
// A new style (a scheme or language switch) can leave the plan's sources out: they are added again.
|
|
156
|
+
const restyled = function () {
|
|
157
|
+
if (removed || !added || map.getSource(src.legs)) { return; }
|
|
158
|
+
added = false;
|
|
159
|
+
addAll();
|
|
160
|
+
};
|
|
161
|
+
map.on('style.load', restyled);
|
|
162
|
+
if (own && options.plan) { editor.setPlan(options.plan).catch(function () {}); }
|
|
163
|
+
|
|
164
|
+
const handle = {
|
|
165
|
+
editor, control, panel, features,
|
|
166
|
+
ready: ready.then(function () { return handle; }),
|
|
167
|
+
layerIds: [layers.casing, layers.legs, layers.starts, layers.unassigned, layers.stops, layers.labels],
|
|
168
|
+
sourceIds: [src.legs, src.starts, src.unassigned, src.stops],
|
|
169
|
+
remove: function () {
|
|
170
|
+
if (removed) { return; }
|
|
171
|
+
removed = true;
|
|
172
|
+
drag.cancel();
|
|
173
|
+
setPan(true);
|
|
174
|
+
map.off('style.load', restyled);
|
|
175
|
+
editor.off('change', onChange);
|
|
176
|
+
editor.off('destroy', gone);
|
|
177
|
+
if (listening) {
|
|
178
|
+
[layers.stops, layers.unassigned].forEach(function (l) { map.off('mousedown', l, down); map.off('touchstart', l, down); });
|
|
179
|
+
map.off('mousemove', move); map.off('touchmove', move); map.off('mouseup', up); map.off('touchend', up);
|
|
180
|
+
}
|
|
181
|
+
if (added) {
|
|
182
|
+
handle.layerIds.slice().reverse().forEach(function (l) { if (map.getLayer(l)) { map.removeLayer(l); } });
|
|
183
|
+
handle.sourceIds.forEach(function (s) { if (map.getSource(s)) { map.removeSource(s); } });
|
|
184
|
+
}
|
|
185
|
+
if (control && map.removeControl) { map.removeControl(control); }
|
|
186
|
+
if (panel) { panel.destroy(); }
|
|
187
|
+
if (own) { editor.destroy(); }
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
return handle;
|
|
191
|
+
}
|
package/types/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type * as mapboxgl from 'mapbox-gl';
|
|
3
3
|
import type { Map as SMapMap, StyleFlavor, BasemapOverrides, StyleLayer, StyleSource, Slot, PointOptions, LineOptions, PolygonOptions,
|
|
4
4
|
LayerData, PopupOptions, PopupContent, FitOptions, RasterLayerOptions, VectorTilesOptions, WmsLayerOptions, WmtsLayerOptions, ArcGisLayerOptions,
|
|
5
|
-
LayerDescription, DataOptions, FileInput, LngLatLike } from '@superrouteca/smap';
|
|
5
|
+
LayerDescription, DataOptions, FileInput, LngLatLike, PlanEditor, PlanEditorOptions, PlanFeatures, PlanPanel, PlanTextKey } from '@superrouteca/smap';
|
|
6
6
|
import type SMapClient from '@superrouteca/smap/client';
|
|
7
7
|
|
|
8
8
|
export type { StyleFlavor };
|
|
@@ -149,6 +149,43 @@ export declare const OSM_ATTRIBUTION: string;
|
|
|
149
149
|
export declare const attribution: string;
|
|
150
150
|
export declare const OVERLAY_CALLS: string[];
|
|
151
151
|
|
|
152
|
+
/** Options of addPlanEditor: the editor's (or an editor of your own as `editor`) and the binding's. */
|
|
153
|
+
export type PlanEditorBindingOptions = (PlanEditorOptions | (Partial<PlanEditorOptions> & { editor: PlanEditor })) & {
|
|
154
|
+
/** Prefix of the source and layer ids, and the features' `smap_plan` (default 'plan'). */
|
|
155
|
+
id?: string;
|
|
156
|
+
/** Route colours, one per vehicle in the plan's order (repeated). */
|
|
157
|
+
colors?: string[];
|
|
158
|
+
/** Price the drop target while a stop is dragged (default true). */
|
|
159
|
+
preview?: boolean;
|
|
160
|
+
/** The panel's language (any BCP-47 tag; default the browser's). */
|
|
161
|
+
language?: string;
|
|
162
|
+
labels?: Partial<Record<PlanTextKey, string>>;
|
|
163
|
+
/** The ready-made panel (default true): false for none, or its corner, class, texts and label. */
|
|
164
|
+
panel?: boolean | { position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; className?: string; labels?: Partial<Record<PlanTextKey, string>>; label?: string };
|
|
165
|
+
/** Add the panel's stylesheet to the page (default true). */
|
|
166
|
+
css?: boolean;
|
|
167
|
+
/** A layer of the map to draw the plan under. */
|
|
168
|
+
before?: string;
|
|
169
|
+
};
|
|
170
|
+
/** A plan editor on a Mapbox GL JS map. */
|
|
171
|
+
export interface MapboxPlanEditor {
|
|
172
|
+
editor: PlanEditor;
|
|
173
|
+
/** `<id>:legs-casing`, `<id>:legs`, `<id>:starts`, `<id>:unassigned`, `<id>:stops`, `<id>:stops-label`. */
|
|
174
|
+
layerIds: string[];
|
|
175
|
+
/** `<id>:legs`, `<id>:starts`, `<id>:unassigned`, `<id>:stops` (GeoJSON). */
|
|
176
|
+
sourceIds: string[];
|
|
177
|
+
/** The panel as a control; null with `panel: false`. */
|
|
178
|
+
control: mapboxgl.IControl | null;
|
|
179
|
+
panel: PlanPanel | null;
|
|
180
|
+
/** Resolves once the layers are on the map (after the style has loaded). */
|
|
181
|
+
ready: Promise<MapboxPlanEditor>;
|
|
182
|
+
features(): PlanFeatures;
|
|
183
|
+
/** Takes the layers, sources, listeners and control off the map; ends the editor when this call made it. */
|
|
184
|
+
remove(): void;
|
|
185
|
+
}
|
|
186
|
+
/** A plan editor on a Mapbox GL JS map (or an SMapMapbox): the plan drawn, stops dragged within and between routes, the panel. */
|
|
187
|
+
export declare function addPlanEditor(map: mapboxgl.Map | SMapMapbox, options: PlanEditorBindingOptions): MapboxPlanEditor;
|
|
188
|
+
|
|
152
189
|
declare const SMapMapboxModule: {
|
|
153
190
|
version: string;
|
|
154
191
|
styles: StyleFlavor[];
|
|
@@ -161,5 +198,6 @@ declare const SMapMapboxModule: {
|
|
|
161
198
|
SMapAccess: typeof SMapAccess;
|
|
162
199
|
checkStyle: typeof checkStyle;
|
|
163
200
|
rasterPath: typeof rasterPath;
|
|
201
|
+
addPlanEditor: typeof addPlanEditor;
|
|
164
202
|
};
|
|
165
203
|
export default SMapMapboxModule;
|