@emuanalytics/flow-rdf-core 4.0.4 → 4.0.5
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/README.md +1 -64
- package/dist/index.d.mts +36 -31
- package/dist/index.d.ts +36 -31
- package/dist/index.mjs +20 -3249
- package/dist/lib/context/context-registry.mjs +63 -0
- package/dist/lib/context/debugger.mjs +240 -0
- package/dist/lib/context/flow-context.mjs +61 -0
- package/dist/lib/context/global-state.mjs +70 -0
- package/dist/lib/context/map-registry.mjs +59 -0
- package/dist/lib/context/query-registry.mjs +53 -0
- package/dist/lib/errors/flow-error.mjs +10 -0
- package/dist/lib/errors/flow-expression-error.mjs +14 -0
- package/dist/lib/errors/flow-map-error.mjs +9 -0
- package/dist/lib/expressions/expression-parser.mjs +198 -0
- package/dist/lib/expressions/functions/from-palette.mjs +75 -0
- package/dist/lib/expressions/functions/regex.mjs +25 -0
- package/dist/lib/expressions/functions/state.mjs +25 -0
- package/dist/lib/expressions/parser-helpers.mjs +37 -0
- package/dist/lib/expressions/reactive-expression.mjs +253 -0
- package/dist/lib/map/flow-core-map.mjs +749 -0
- package/dist/lib/map/plugins/annotations/annotation-layers.mjs +163 -0
- package/dist/lib/map/plugins/annotations/annotation.events.mjs +27 -0
- package/dist/lib/map/plugins/annotations/annotation.plugin.mjs +498 -0
- package/dist/lib/map/plugins/annotations/maplibre-gl-draw-circle/lib/modes/DirectModeOverride.mjs +67 -0
- package/dist/lib/map/plugins/annotations/maplibre-gl-draw-circle/lib/modes/DragCircleMode.mjs +65 -0
- package/dist/lib/map/plugins/annotations/maplibre-gl-draw-circle/lib/utils/create_supplementary_points_circle.mjs +15 -0
- package/dist/lib/map/plugins/annotations/maplibre-gl-draw-circle/lib/utils/drag_pan.mjs +20 -0
- package/dist/lib/map/plugins/data-join.plugin.mjs +173 -0
- package/dist/lib/map/plugins/export/export.plugin.mjs +21 -0
- package/dist/lib/map/plugins/export/map-exporter.mjs +177 -0
- package/dist/lib/map/plugins/hover-effect.plugin.mjs +58 -0
- package/dist/lib/map/plugins/index.d.mts +37 -72
- package/dist/lib/map/plugins/index.d.ts +37 -72
- package/dist/lib/map/plugins/index.mjs +11 -1810
- package/dist/lib/map/plugins/keyboard-shortcut-manager.mjs +120 -0
- package/dist/lib/map/plugins/map-plugin-base.mjs +25 -0
- package/dist/lib/map/plugins/plugin-manager.mjs +135 -0
- package/dist/lib/map/plugins/popup.plugin.mjs +55 -0
- package/dist/lib/map/plugins/selection/selection.events.mjs +21 -0
- package/dist/lib/map/plugins/selection/selection.plugin.mjs +136 -0
- package/dist/lib/map/plugins/selection/source-selection.mjs +156 -0
- package/dist/lib/map/plugins/url-sync.plugin.mjs +55 -0
- package/dist/lib/map/support/image-registry.mjs +82 -0
- package/dist/lib/map/support/map-events.mjs +71 -0
- package/dist/lib/map/support/map-feature-stream.mjs +158 -0
- package/dist/lib/map/support/map-popup.mjs +159 -0
- package/dist/lib/map/types.mjs +7 -0
- package/dist/lib/map-style/map-data-source.mjs +192 -0
- package/dist/lib/map-style/map-layer-style-builder-generated.mjs +1307 -0
- package/dist/lib/map-style/map-layer-style-builder.mjs +86 -0
- package/dist/lib/map-style/map-layer.mjs +223 -0
- package/dist/lib/map-style/map-style.mjs +178 -0
- package/dist/lib/queries/async-committer.mjs +30 -0
- package/dist/lib/queries/query.mjs +172 -0
- package/dist/lib/state-store/decorators.mjs +83 -0
- package/dist/lib/state-store/state-store.mjs +534 -0
- package/dist/lib/state-store/utils.mjs +7 -0
- package/dist/lib/utils/announce.mjs +12 -0
- package/dist/lib/utils/assert.mjs +12 -0
- package/dist/{shared/flow-rdf-core.187cb345.mjs → lib/utils/debounce.mjs} +3 -39
- package/dist/lib/utils/decorators.mjs +59 -0
- package/dist/lib/utils/deferred.mjs +11 -0
- package/dist/lib/utils/ensure-array.mjs +16 -0
- package/dist/{shared/flow-rdf-core.1f0901c5.mjs → lib/utils/feature-type-checks.mjs} +2 -2
- package/dist/lib/utils/functional.mjs +22 -0
- package/dist/lib/utils/global.mjs +18 -0
- package/dist/lib/utils/index.mjs +8 -5
- package/dist/lib/utils/random-id.mjs +9 -0
- package/dist/lib/utils/string-utils.mjs +3 -0
- package/dist/lib/utils/throttle.mjs +20 -0
- package/dist/{shared/flow-rdf-core.25e5f6d7.mjs → lib/utils/type-checks.mjs} +1 -26
- package/dist/lib/utils/watchable-promise.mjs +55 -0
- package/dist/package.json.mjs +3 -0
- package/dist/shared/{flow-rdf-core.4dde996e.d.cts → flow-rdf-core.8b5acf14.d.mts} +1315 -172
- package/dist/shared/{flow-rdf-core.4dde996e.d.ts → flow-rdf-core.8b5acf14.d.ts} +1315 -172
- package/package.json +4 -8
- package/dist/index.cjs +0 -3316
- package/dist/index.d.cts +0 -90
- package/dist/lib/map/plugins/index.cjs +0 -1850
- package/dist/lib/map/plugins/index.d.cts +0 -345
- package/dist/lib/utils/index.cjs +0 -48
- package/dist/lib/utils/index.d.cts +0 -160
- package/dist/shared/flow-rdf-core.06e85a6c.cjs +0 -1394
- package/dist/shared/flow-rdf-core.4dde996e.d.mts +0 -1916
- package/dist/shared/flow-rdf-core.55c169ca.cjs +0 -150
- package/dist/shared/flow-rdf-core.63162669.d.cts +0 -10
- package/dist/shared/flow-rdf-core.65045caf.mjs +0 -1360
- package/dist/shared/flow-rdf-core.a82b9be4.cjs +0 -34
- package/dist/shared/flow-rdf-core.f50908f0.cjs +0 -102
package/dist/lib/map/plugins/annotations/maplibre-gl-draw-circle/lib/modes/DirectModeOverride.mjs
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import MapboxDraw from '@emuanalytics/mapbox-gl-draw';
|
|
2
|
+
import turfCircle from '@turf/circle';
|
|
3
|
+
import turfDistance from '@turf/distance';
|
|
4
|
+
import { point } from '@turf/helpers';
|
|
5
|
+
import createSupplementaryPointsForCircle from '../utils/create_supplementary_points_circle.mjs';
|
|
6
|
+
|
|
7
|
+
const DirectModeOverride = MapboxDraw.modes.direct_select;
|
|
8
|
+
const moveFeatures = MapboxDraw.lib.moveFeatures;
|
|
9
|
+
const constrainFeatureMovement = MapboxDraw.lib.constrainFeatureMovement;
|
|
10
|
+
const createSupplementaryPoints = MapboxDraw.lib.createSupplementaryPoints;
|
|
11
|
+
const Constants = MapboxDraw.constants;
|
|
12
|
+
DirectModeOverride.dragFeature = function(state, e, delta) {
|
|
13
|
+
moveFeatures(this.getSelected(), delta);
|
|
14
|
+
this.getSelected().filter((feature) => feature.properties.type === "Circle").map((circle) => circle.properties.circleCenter).forEach((center) => {
|
|
15
|
+
center[0] += delta.lng;
|
|
16
|
+
center[1] += delta.lat;
|
|
17
|
+
});
|
|
18
|
+
state.dragMoveLocation = e.lngLat;
|
|
19
|
+
};
|
|
20
|
+
DirectModeOverride.dragVertex = function(state, e, delta) {
|
|
21
|
+
if (state.feature.properties.type === "Circle") {
|
|
22
|
+
const center = state.feature.properties.circleCenter;
|
|
23
|
+
const movedVertex = [e.lngLat.lng, e.lngLat.lat];
|
|
24
|
+
const radius = turfDistance(point(center), point(movedVertex), { units: "kilometers" });
|
|
25
|
+
const circleFeature = turfCircle(center, radius);
|
|
26
|
+
state.feature.incomingCoords(circleFeature.geometry.coordinates);
|
|
27
|
+
state.feature.properties.circleRadius = radius;
|
|
28
|
+
} else {
|
|
29
|
+
const selectedCoords = state.selectedCoordPaths.map((coord_path) => state.feature.getCoordinate(coord_path));
|
|
30
|
+
const selectedCoordPoints = selectedCoords.map((coords) => ({
|
|
31
|
+
type: Constants.geojsonTypes.FEATURE,
|
|
32
|
+
properties: {},
|
|
33
|
+
geometry: {
|
|
34
|
+
type: Constants.geojsonTypes.POINT,
|
|
35
|
+
coordinates: coords
|
|
36
|
+
}
|
|
37
|
+
}));
|
|
38
|
+
const constrainedDelta = constrainFeatureMovement(selectedCoordPoints, delta);
|
|
39
|
+
for (let i = 0; i < selectedCoords.length; i++) {
|
|
40
|
+
const coord = selectedCoords[i];
|
|
41
|
+
state.feature.updateCoordinate(
|
|
42
|
+
state.selectedCoordPaths[i],
|
|
43
|
+
coord[0] + constrainedDelta.lng,
|
|
44
|
+
coord[1] + constrainedDelta.lat
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
DirectModeOverride.toDisplayFeatures = function(state, geojson, push) {
|
|
50
|
+
if (state.featureId === geojson.properties.id) {
|
|
51
|
+
geojson.properties.active = Constants.activeStates.ACTIVE;
|
|
52
|
+
push(geojson);
|
|
53
|
+
const supplementaryPoints = geojson.properties.user_type === "Circle" ? createSupplementaryPointsForCircle(geojson) : createSupplementaryPoints(geojson, {
|
|
54
|
+
map: this.map,
|
|
55
|
+
midpoints: true,
|
|
56
|
+
selectedPaths: state.selectedCoordPaths
|
|
57
|
+
});
|
|
58
|
+
supplementaryPoints.forEach(push);
|
|
59
|
+
} else {
|
|
60
|
+
geojson.properties.active = Constants.activeStates.INACTIVE;
|
|
61
|
+
push(geojson);
|
|
62
|
+
}
|
|
63
|
+
this.fireActionable(state);
|
|
64
|
+
};
|
|
65
|
+
const DirectMode = DirectModeOverride;
|
|
66
|
+
|
|
67
|
+
export { DirectMode as default };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import MapboxDraw from '@emuanalytics/mapbox-gl-draw';
|
|
2
|
+
import turfCircle from '@turf/circle';
|
|
3
|
+
import turfDistance from '@turf/distance';
|
|
4
|
+
import { point } from '@turf/helpers';
|
|
5
|
+
import dragPan from '../utils/drag_pan.mjs';
|
|
6
|
+
|
|
7
|
+
const DragCircleMode = { ...MapboxDraw.modes.draw_polygon };
|
|
8
|
+
const Constants = MapboxDraw.constants;
|
|
9
|
+
DragCircleMode.onSetup = function(opts) {
|
|
10
|
+
const polygon = this.newFeature({
|
|
11
|
+
type: Constants.geojsonTypes.FEATURE,
|
|
12
|
+
properties: {
|
|
13
|
+
type: "Circle",
|
|
14
|
+
circleCenter: []
|
|
15
|
+
},
|
|
16
|
+
geometry: {
|
|
17
|
+
type: Constants.geojsonTypes.POLYGON,
|
|
18
|
+
coordinates: []
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
this.addFeature(polygon);
|
|
22
|
+
this.clearSelectedFeatures();
|
|
23
|
+
dragPan.disable(this);
|
|
24
|
+
this.updateUIClasses({ mouse: Constants.cursors.ADD });
|
|
25
|
+
this.activateUIButton(Constants.types.POLYGON);
|
|
26
|
+
this.setActionableState({
|
|
27
|
+
trash: true
|
|
28
|
+
});
|
|
29
|
+
return {
|
|
30
|
+
polygon,
|
|
31
|
+
currentVertexPosition: 0
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
DragCircleMode.onMouseDown = DragCircleMode.onTouchStart = function(state, e) {
|
|
35
|
+
const currentCenter = state.polygon.properties.circleCenter;
|
|
36
|
+
if (currentCenter.length === 0) {
|
|
37
|
+
state.polygon.properties.circleCenter = [e.lngLat.lng, e.lngLat.lat];
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
DragCircleMode.onDrag = DragCircleMode.onMouseMove = function(state, e) {
|
|
41
|
+
const center = state.polygon.properties.circleCenter;
|
|
42
|
+
if (center.length > 0) {
|
|
43
|
+
const distanceInKm = turfDistance(point(center), point([e.lngLat.lng, e.lngLat.lat]), {
|
|
44
|
+
units: "kilometers"
|
|
45
|
+
});
|
|
46
|
+
const circleFeature = turfCircle(center, distanceInKm);
|
|
47
|
+
state.polygon.incomingCoords(circleFeature.geometry.coordinates);
|
|
48
|
+
state.polygon.properties.circleRadius = distanceInKm;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
DragCircleMode.onMouseUp = DragCircleMode.onTouchEnd = function(state) {
|
|
52
|
+
dragPan.enable(this);
|
|
53
|
+
return this.changeMode(Constants.modes.SIMPLE_SELECT, { featureIds: [state.polygon.id] });
|
|
54
|
+
};
|
|
55
|
+
DragCircleMode.onClick = DragCircleMode.onTap = function(state) {
|
|
56
|
+
state.polygon.properties.circleCenter = [];
|
|
57
|
+
};
|
|
58
|
+
DragCircleMode.toDisplayFeatures = function(state, geojson, display) {
|
|
59
|
+
const isActivePolygon = geojson.properties.id === state.polygon.id;
|
|
60
|
+
geojson.properties.active = isActivePolygon ? Constants.activeStates.ACTIVE : Constants.activeStates.INACTIVE;
|
|
61
|
+
return display(geojson);
|
|
62
|
+
};
|
|
63
|
+
const DragCircleMode$1 = DragCircleMode;
|
|
64
|
+
|
|
65
|
+
export { DragCircleMode$1 as default };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import MapboxDraw from '@emuanalytics/mapbox-gl-draw';
|
|
2
|
+
|
|
3
|
+
function createSupplementaryPointsForCircle(geojson) {
|
|
4
|
+
const { properties, geometry } = geojson;
|
|
5
|
+
if (properties.user_type !== "Circle")
|
|
6
|
+
return null;
|
|
7
|
+
const supplementaryPoints = [];
|
|
8
|
+
const vertices = geometry.coordinates[0].slice(0, -1);
|
|
9
|
+
for (let index = 0; index < vertices.length; index += Math.round(vertices.length / 4)) {
|
|
10
|
+
supplementaryPoints.push(MapboxDraw.lib.createVertex(properties.id, vertices[index], `0.${index}`, false));
|
|
11
|
+
}
|
|
12
|
+
return supplementaryPoints;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { createSupplementaryPointsForCircle as default };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const dragPan = {
|
|
2
|
+
enable(ctx) {
|
|
3
|
+
setTimeout(() => {
|
|
4
|
+
if (!ctx.map || !ctx.map.dragPan || !ctx._ctx || !ctx._ctx.store || !ctx._ctx.store.getInitialConfigValue)
|
|
5
|
+
return;
|
|
6
|
+
if (!ctx._ctx.store.getInitialConfigValue("dragPan"))
|
|
7
|
+
return;
|
|
8
|
+
ctx.map.dragPan.enable();
|
|
9
|
+
}, 0);
|
|
10
|
+
},
|
|
11
|
+
disable(ctx) {
|
|
12
|
+
setTimeout(() => {
|
|
13
|
+
if (!ctx.map || !ctx.map.doubleClickZoom)
|
|
14
|
+
return;
|
|
15
|
+
ctx.map.dragPan.disable();
|
|
16
|
+
}, 0);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export { dragPan as default };
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import Debug from 'debug';
|
|
2
|
+
import { autorun, toJS } from 'mobx';
|
|
3
|
+
import { isString, isURL, isArrayFull, isNil, isNull } from '../../utils/type-checks.mjs';
|
|
4
|
+
import { MapPluginBase } from './map-plugin-base.mjs';
|
|
5
|
+
import { FlowCoreError } from '../../errors/flow-error.mjs';
|
|
6
|
+
import { ReactiveExpression } from '../../expressions/reactive-expression.mjs';
|
|
7
|
+
|
|
8
|
+
var __defProp = Object.defineProperty;
|
|
9
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10
|
+
var __publicField = (obj, key, value) => {
|
|
11
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
12
|
+
return value;
|
|
13
|
+
};
|
|
14
|
+
const debug = Debug("flow:data-join-map-plugin");
|
|
15
|
+
const _DataJoin = class _DataJoin {
|
|
16
|
+
constructor(id, map, options) {
|
|
17
|
+
this.id = id;
|
|
18
|
+
this.map = map;
|
|
19
|
+
__publicField(this, "autorunDisposer", null);
|
|
20
|
+
__publicField(this, "dataExpression", null);
|
|
21
|
+
__publicField(this, "options");
|
|
22
|
+
__publicField(this, "parameterExpressions", {});
|
|
23
|
+
this.options = {
|
|
24
|
+
..._DataJoin.defaultOptions,
|
|
25
|
+
...options
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
get source() {
|
|
29
|
+
return this.options.source;
|
|
30
|
+
}
|
|
31
|
+
start() {
|
|
32
|
+
this.stop();
|
|
33
|
+
if (isString(this.options.data)) {
|
|
34
|
+
if (isURL(this.options.data))
|
|
35
|
+
this.options.data = `'${this.options.data}'`;
|
|
36
|
+
this.dataExpression = new ReactiveExpression(this.options.data);
|
|
37
|
+
this.dataExpression.bindState(this.map.context.state);
|
|
38
|
+
} else {
|
|
39
|
+
this.dataExpression = null;
|
|
40
|
+
}
|
|
41
|
+
if (isArrayFull(this.options.parameters)) {
|
|
42
|
+
this.parameterExpressions = this.options.parameters.reduce((accum, param) => {
|
|
43
|
+
const expr = new ReactiveExpression(param.value.toString());
|
|
44
|
+
expr.bindState(this.map.context.state);
|
|
45
|
+
accum[param.name] = expr;
|
|
46
|
+
return accum;
|
|
47
|
+
}, {});
|
|
48
|
+
}
|
|
49
|
+
this.autorunDisposer = autorun(
|
|
50
|
+
async () => {
|
|
51
|
+
let data = this.dataExpression ? toJS(this.dataExpression.value) : this.options.data;
|
|
52
|
+
const missingParams = this.options.parameters.map((p) => p.required && isNil(this.parameterExpressions[p.name].value) ? p.name : void 0).filter((p) => !!p);
|
|
53
|
+
if (isNull(data)) {
|
|
54
|
+
debug(`FlowMap<${this.map.id}>: Skipping data join '${this.id}' (null data)`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (missingParams.length) {
|
|
58
|
+
debug(
|
|
59
|
+
`FlowMap<${this.map.id}>: Skipping data join '${this.id}' (null required parameters: ${missingParams.join(
|
|
60
|
+
", "
|
|
61
|
+
)})`
|
|
62
|
+
);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
debug(`FlowMap<${this.map.id}>: Performing data join '${this.id}'`);
|
|
66
|
+
if (isString(data)) {
|
|
67
|
+
try {
|
|
68
|
+
data = await this.loadData(data);
|
|
69
|
+
} catch (e) {
|
|
70
|
+
this.map.emitError(`Failed to load data for data join '${this.id}' - ${e.message}`, e);
|
|
71
|
+
data = [];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
this.doDataJoin(data);
|
|
75
|
+
},
|
|
76
|
+
{ name: `FlowDataJoin.${this.map.id}.${this.id})` }
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
stop() {
|
|
80
|
+
if (this.autorunDisposer) {
|
|
81
|
+
this.autorunDisposer();
|
|
82
|
+
this.autorunDisposer = null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
doDataJoin(data) {
|
|
86
|
+
const source = this.map.getSource(this.options.source);
|
|
87
|
+
const sourceLayer = source.type === "vector" ? this.options.sourceLayer || "geometry" : void 0;
|
|
88
|
+
if (this.options.clear) {
|
|
89
|
+
this.map.removeFeatureState({ source: source.id, sourceLayer }, this.id);
|
|
90
|
+
}
|
|
91
|
+
const featureData = data.reduce((accum, d) => {
|
|
92
|
+
accum[d[this.options.foreignKey]] = { [this.id]: d };
|
|
93
|
+
return accum;
|
|
94
|
+
}, {});
|
|
95
|
+
this.map.setFeatureStateBulk({ source: source.id, sourceLayer }, featureData);
|
|
96
|
+
}
|
|
97
|
+
loadData(datasetOrUrl) {
|
|
98
|
+
if (isURL(datasetOrUrl)) {
|
|
99
|
+
const url = new URL(datasetOrUrl);
|
|
100
|
+
const params = new URLSearchParams(url.searchParams);
|
|
101
|
+
if (isArrayFull(this.options.parameters)) {
|
|
102
|
+
this.options.parameters.forEach((p) => {
|
|
103
|
+
params.append(p.name, this.parameterExpressions[p.name].value);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
url.search = params.toString();
|
|
107
|
+
const headers = new Headers({ Accept: "application/json" });
|
|
108
|
+
const request = new Request(url.toString(), {
|
|
109
|
+
method: "GET",
|
|
110
|
+
mode: "cors",
|
|
111
|
+
headers,
|
|
112
|
+
cache: "default"
|
|
113
|
+
});
|
|
114
|
+
return fetch(request).then((response) => {
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
throw new Error(`status=${response.status} ${response.statusText}`);
|
|
117
|
+
}
|
|
118
|
+
return response.json();
|
|
119
|
+
});
|
|
120
|
+
} else {
|
|
121
|
+
const params = {};
|
|
122
|
+
if (isArrayFull(this.options.parameters)) {
|
|
123
|
+
this.options.parameters.forEach((p) => {
|
|
124
|
+
params[p.name] = this.parameterExpressions[p.name].value;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return this.map.context.flowClient.datasets.query(datasetOrUrl, {}, params);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
__publicField(_DataJoin, "defaultOptions", {
|
|
132
|
+
clear: false,
|
|
133
|
+
parameters: []
|
|
134
|
+
});
|
|
135
|
+
let DataJoin = _DataJoin;
|
|
136
|
+
class DataJoinPlugin extends MapPluginBase {
|
|
137
|
+
constructor(pluginManager) {
|
|
138
|
+
super(pluginManager);
|
|
139
|
+
__publicField(this, "_joins", /* @__PURE__ */ new Map());
|
|
140
|
+
__publicField(this, "name", "DataJoinPlugin");
|
|
141
|
+
}
|
|
142
|
+
addDataJoin(id, options) {
|
|
143
|
+
const dataJoin = new DataJoin(id, this.map, options);
|
|
144
|
+
this._joins.set(id, dataJoin);
|
|
145
|
+
dataJoin.start();
|
|
146
|
+
}
|
|
147
|
+
bindState(state) {
|
|
148
|
+
this._joins.forEach((join) => join.start());
|
|
149
|
+
}
|
|
150
|
+
destroy() {
|
|
151
|
+
this._joins.forEach((join) => join.stop());
|
|
152
|
+
this._joins.clear();
|
|
153
|
+
}
|
|
154
|
+
handleSourceRemoved(event) {
|
|
155
|
+
this._joins.forEach((join) => {
|
|
156
|
+
if (join.source === event.source) {
|
|
157
|
+
join.stop();
|
|
158
|
+
this._joins.delete(join.id);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
removeDataJoin(id) {
|
|
163
|
+
const dataJoin = this._joins.get(id);
|
|
164
|
+
if (dataJoin) {
|
|
165
|
+
dataJoin.stop();
|
|
166
|
+
this._joins.delete(id);
|
|
167
|
+
} else {
|
|
168
|
+
throw new FlowCoreError(`Cannot remove unrecognized data join '${id}'`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export { DataJoin, DataJoinPlugin };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { MapPluginBase } from '../map-plugin-base.mjs';
|
|
2
|
+
import { MapExporter } from './map-exporter.mjs';
|
|
3
|
+
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
+
var __publicField = (obj, key, value) => {
|
|
7
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
8
|
+
return value;
|
|
9
|
+
};
|
|
10
|
+
class ExportPlugin extends MapPluginBase {
|
|
11
|
+
constructor(pluginManager) {
|
|
12
|
+
super(pluginManager);
|
|
13
|
+
__publicField(this, "name", "ExportPlugin");
|
|
14
|
+
}
|
|
15
|
+
exportMap(options) {
|
|
16
|
+
const mapExporter = new MapExporter(this.map);
|
|
17
|
+
return mapExporter.export(options);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { ExportPlugin };
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import maplibre from '@emuanalytics/maplibre-gl';
|
|
2
|
+
import saveAs from 'file-saver';
|
|
3
|
+
import { randomId } from '../../../utils/random-id.mjs';
|
|
4
|
+
import { isFunction } from '../../../utils/type-checks.mjs';
|
|
5
|
+
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __publicField = (obj, key, value) => {
|
|
9
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
10
|
+
return value;
|
|
11
|
+
};
|
|
12
|
+
const _MapExporter = class _MapExporter {
|
|
13
|
+
constructor(map) {
|
|
14
|
+
this.map = map;
|
|
15
|
+
__publicField(this, "nativePixelRatio", window.devicePixelRatio);
|
|
16
|
+
}
|
|
17
|
+
async export(options) {
|
|
18
|
+
options = { ..._MapExporter.defaultOptions, ...options };
|
|
19
|
+
const [container, mapCopy] = await this.createMapCopy(options);
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
const fileName = `${options.name}.${options.format}`;
|
|
22
|
+
const mapCanvas = mapCopy.getCanvas();
|
|
23
|
+
const exportCanvas = this.createExportCanvas(container, mapCanvas);
|
|
24
|
+
const exportContext = exportCanvas.getContext("2d");
|
|
25
|
+
if (!exportContext) {
|
|
26
|
+
this.destroyMapCopy(container, mapCopy);
|
|
27
|
+
reject(new Error("Failed to create export canvas context"));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const drawOverlayCallback = (err) => {
|
|
31
|
+
if (err) {
|
|
32
|
+
this.destroyMapCopy(container, mapCopy);
|
|
33
|
+
reject(err);
|
|
34
|
+
} else {
|
|
35
|
+
switch (options.format) {
|
|
36
|
+
case "png":
|
|
37
|
+
exportCanvas.toBlob((blob) => {
|
|
38
|
+
blob && saveAs(blob, fileName);
|
|
39
|
+
});
|
|
40
|
+
break;
|
|
41
|
+
case "pdf":
|
|
42
|
+
throw new Error("Export to PDF is not currently supported");
|
|
43
|
+
}
|
|
44
|
+
this.destroyMapCopy(container, mapCopy);
|
|
45
|
+
resolve(fileName);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const mapImage = new Image();
|
|
49
|
+
mapImage.onload = () => {
|
|
50
|
+
exportContext.drawImage(mapImage, 0, 0);
|
|
51
|
+
if (isFunction(options.drawOverlayFn)) {
|
|
52
|
+
options.drawOverlayFn(
|
|
53
|
+
exportContext,
|
|
54
|
+
exportCanvas.width,
|
|
55
|
+
exportCanvas.height,
|
|
56
|
+
options.dpmm,
|
|
57
|
+
drawOverlayCallback
|
|
58
|
+
);
|
|
59
|
+
} else {
|
|
60
|
+
drawOverlayCallback(null);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
mapImage.src = mapCopy.getCanvas().toDataURL();
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
createMapCopy(options) {
|
|
67
|
+
const geoBounds = options.bounds || this.map.maplibreMap.getBounds().toArray().flat();
|
|
68
|
+
const geoBottomLeft = [geoBounds[0], geoBounds[1]];
|
|
69
|
+
const geoTopRight = [geoBounds[2], geoBounds[3]];
|
|
70
|
+
const geoCenter = [
|
|
71
|
+
(geoBottomLeft[0] + geoTopRight[0]) / 2,
|
|
72
|
+
(geoBottomLeft[1] + geoTopRight[1]) / 2
|
|
73
|
+
];
|
|
74
|
+
const pxBottomLeft = this.map.maplibreMap.project(geoBottomLeft);
|
|
75
|
+
const pxTopRight = this.map.maplibreMap.project(geoTopRight);
|
|
76
|
+
const pxWidth = pxTopRight.x - pxBottomLeft.x;
|
|
77
|
+
const pxHeight = pxBottomLeft.y - pxTopRight.y;
|
|
78
|
+
const exportWidth = options.width * options.dpmm;
|
|
79
|
+
const exportHeight = options.height * options.dpmm;
|
|
80
|
+
const aspectRatios = {
|
|
81
|
+
width: pxWidth / exportWidth,
|
|
82
|
+
height: pxHeight / exportHeight
|
|
83
|
+
};
|
|
84
|
+
const coverRatio = Math.max(aspectRatios.width, aspectRatios.height);
|
|
85
|
+
const copyWidth = exportWidth * coverRatio;
|
|
86
|
+
const copyHeight = exportHeight * coverRatio;
|
|
87
|
+
const pixelRatio = exportWidth / copyWidth;
|
|
88
|
+
this.setDevicePixelRatio(pixelRatio);
|
|
89
|
+
const container = document.createElement("div");
|
|
90
|
+
container.id = randomId("export");
|
|
91
|
+
container.classList.add("maplibregl-export-container");
|
|
92
|
+
container.style.width = `${copyWidth}px`;
|
|
93
|
+
container.style.height = `${copyHeight}px`;
|
|
94
|
+
this.map.container.insertBefore(container, this.map.container.firstChild);
|
|
95
|
+
const mapCopy = new maplibre.Map({
|
|
96
|
+
container,
|
|
97
|
+
center: geoCenter,
|
|
98
|
+
zoom: this.map.maplibreMap.getZoom(),
|
|
99
|
+
style: { ...this.map.maplibreMap.getStyle(), transition: { delay: 0, duration: 0 } },
|
|
100
|
+
bearing: this.map.maplibreMap.getBearing(),
|
|
101
|
+
pitch: this.map.maplibreMap.getPitch(),
|
|
102
|
+
interactive: false,
|
|
103
|
+
attributionControl: false,
|
|
104
|
+
fadeDuration: 0,
|
|
105
|
+
preserveDrawingBuffer: true,
|
|
106
|
+
transformRequest: this.transformMapRequest.bind(this)
|
|
107
|
+
});
|
|
108
|
+
mapCopy.on("styleimagemissing", this.handleMissingImage.bind(this));
|
|
109
|
+
return new Promise((resolve) => {
|
|
110
|
+
mapCopy.once("load", () => {
|
|
111
|
+
Object.keys(this.map.maplibreMap.style.sourceCaches).forEach((sourceId) => {
|
|
112
|
+
mapCopy.style.sourceCaches[sourceId]._state.stateChanges = this.map.maplibreMap.style.sourceCaches[sourceId]._state.state;
|
|
113
|
+
});
|
|
114
|
+
mapCopy._update();
|
|
115
|
+
setTimeout(() => resolve([container, mapCopy]), 500);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
destroyMapCopy(container, map) {
|
|
120
|
+
this.setDevicePixelRatio(this.nativePixelRatio);
|
|
121
|
+
map.remove();
|
|
122
|
+
container.parentNode.removeChild(container);
|
|
123
|
+
}
|
|
124
|
+
createExportCanvas(container, mapCanvas) {
|
|
125
|
+
const canvasContainer = container.getElementsByClassName("maplibregl-canvas-container")[0];
|
|
126
|
+
const overlayCanvas = document.createElement("canvas");
|
|
127
|
+
overlayCanvas.id = randomId("overlay");
|
|
128
|
+
overlayCanvas.width = mapCanvas.width;
|
|
129
|
+
overlayCanvas.height = mapCanvas.height;
|
|
130
|
+
overlayCanvas.style.position = "absolute";
|
|
131
|
+
overlayCanvas.style.width = mapCanvas.style.width;
|
|
132
|
+
overlayCanvas.style.height = mapCanvas.style.height;
|
|
133
|
+
canvasContainer.appendChild(overlayCanvas);
|
|
134
|
+
return overlayCanvas;
|
|
135
|
+
}
|
|
136
|
+
setDevicePixelRatio(pixelRatio) {
|
|
137
|
+
Object.defineProperty(window, "devicePixelRatio", {
|
|
138
|
+
get: () => pixelRatio
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
async handleMissingImage(e) {
|
|
142
|
+
const imageInfo = this.map.imageRegistry.getImage(e.id);
|
|
143
|
+
if (imageInfo === this.map.imageRegistry.unknownImage) {
|
|
144
|
+
console.error(`Map ${this.map.id}: Image '${e.id}' not registered`);
|
|
145
|
+
}
|
|
146
|
+
if (!imageInfo.image.complete) {
|
|
147
|
+
imageInfo.image.onload = () => {
|
|
148
|
+
this.map.maplibreMap.updateImage(e.id, imageInfo.image);
|
|
149
|
+
this.map.maplibreMap.redraw();
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
this.map.maplibreMap.addImage(e.id, imageInfo.image, {
|
|
153
|
+
pixelRatio: imageInfo.pixelDensity,
|
|
154
|
+
sdf: imageInfo.recolor
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
transformMapRequest(url, _resourceType) {
|
|
158
|
+
if (this.map.context.flowClient.accessToken && url.startsWith(this.map.context.flowClient.baseUrl)) {
|
|
159
|
+
return {
|
|
160
|
+
url,
|
|
161
|
+
headers: { Authorization: `Bearer ${this.map.context.flowClient.accessToken}` }
|
|
162
|
+
};
|
|
163
|
+
} else {
|
|
164
|
+
return { url };
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
__publicField(_MapExporter, "defaultOptions", {
|
|
169
|
+
name: "map",
|
|
170
|
+
width: 297,
|
|
171
|
+
height: 210,
|
|
172
|
+
dpmm: 12,
|
|
173
|
+
format: "png"
|
|
174
|
+
});
|
|
175
|
+
let MapExporter = _MapExporter;
|
|
176
|
+
|
|
177
|
+
export { MapExporter };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { isDefined, isObject } from '../../utils/type-checks.mjs';
|
|
2
|
+
import { isFeatureWithId } from '../types.mjs';
|
|
3
|
+
import { MapPluginBase } from './map-plugin-base.mjs';
|
|
4
|
+
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
7
|
+
var __publicField = (obj, key, value) => {
|
|
8
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
9
|
+
return value;
|
|
10
|
+
};
|
|
11
|
+
class HoverEffectPlugin extends MapPluginBase {
|
|
12
|
+
constructor(pluginManager) {
|
|
13
|
+
super(pluginManager);
|
|
14
|
+
__publicField(this, "hoveredFeature", null);
|
|
15
|
+
__publicField(this, "name", "HoverEffectPlugin");
|
|
16
|
+
}
|
|
17
|
+
handleMouseMove(event) {
|
|
18
|
+
const hoveredFeature = event.features[0];
|
|
19
|
+
if (hoveredFeature) {
|
|
20
|
+
this.map.maplibreMap._container.classList.add("feature-hovered");
|
|
21
|
+
} else {
|
|
22
|
+
this.map.maplibreMap._container.classList.remove("feature-hovered");
|
|
23
|
+
}
|
|
24
|
+
if (!this.compareFeatures(hoveredFeature, this.hoveredFeature)) {
|
|
25
|
+
this.clearHover();
|
|
26
|
+
if (isFeatureWithId(hoveredFeature) && isDefined(this.map.getSource(hoveredFeature.source)?.featureId)) {
|
|
27
|
+
this.map.setFeatureState(hoveredFeature, { hover: true }, false);
|
|
28
|
+
this.hoveredFeature = hoveredFeature;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
handleMouseOut(event) {
|
|
33
|
+
this.clearHover();
|
|
34
|
+
}
|
|
35
|
+
handleSetExclusivePlugin(exclusivePlugins) {
|
|
36
|
+
if (exclusivePlugins.length) {
|
|
37
|
+
this.clearHover();
|
|
38
|
+
this.map.maplibreMap._container.classList.remove("feature-hovered");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
compareFeatures(f1, f2) {
|
|
42
|
+
if (f1 === f2) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
if (isObject(f1) && isObject(f2)) {
|
|
46
|
+
return f1.id == f2.id && f1.source === f2.source && f1.sourceLayer == f2.sourceLayer;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
clearHover() {
|
|
51
|
+
if (this.hoveredFeature && this.map.getSource(this.hoveredFeature.source)) {
|
|
52
|
+
this.map.removeFeatureState(this.hoveredFeature, "hover", false);
|
|
53
|
+
this.hoveredFeature = null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { HoverEffectPlugin };
|