@emuanalytics/flow-rdf-core 4.0.3 → 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 -1811
- 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 -1851
- 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
|
@@ -1,1360 +0,0 @@
|
|
|
1
|
-
import * as mobx from 'mobx';
|
|
2
|
-
import { makeObservable, observable, computed, action, onBecomeObserved, onBecomeUnobserved, runInAction } from 'mobx';
|
|
3
|
-
import { f as isString, j as isArray, b as isNil, d as isDefined, r as isIn, g as isStringFull, z as isURL, n as isObjectFull, c as capitalize } from './flow-rdf-core.25e5f6d7.mjs';
|
|
4
|
-
import * as maplibreSpec from '@emuanalytics/maplibre-gl-style-spec';
|
|
5
|
-
import { toStream } from 'mobx-utils';
|
|
6
|
-
import P from 'parsimmon';
|
|
7
|
-
import colorbrewer from 'colorbrewer';
|
|
8
|
-
import Debug from 'debug';
|
|
9
|
-
|
|
10
|
-
class FlowError extends Error {
|
|
11
|
-
constructor(message, cause) {
|
|
12
|
-
super(message);
|
|
13
|
-
this.cause = cause;
|
|
14
|
-
this.name = this.constructor.name;
|
|
15
|
-
this.cause = cause;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
class FlowExpressionError extends FlowError {
|
|
20
|
-
constructor(expression, reason, errors) {
|
|
21
|
-
super(`Failed to evaluate expression:
|
|
22
|
-
${expression}
|
|
23
|
-
------
|
|
24
|
-
${errors.join(", ")}`);
|
|
25
|
-
this.reason = reason;
|
|
26
|
-
this.errors = errors;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function PREFIX(operatorsParser, nextParser) {
|
|
31
|
-
const parser = P.lazy(() => {
|
|
32
|
-
return P.seq(operatorsParser, parser).or(nextParser);
|
|
33
|
-
});
|
|
34
|
-
return parser;
|
|
35
|
-
}
|
|
36
|
-
function BINARY_RIGHT(operatorsParser, nextParser) {
|
|
37
|
-
const parser = P.lazy(() => nextParser.chain((next) => P.seq(operatorsParser, P.of(next), parser).or(P.of(next))));
|
|
38
|
-
return parser;
|
|
39
|
-
}
|
|
40
|
-
function TERNARY_RIGHT(operatorsParser, nextParser) {
|
|
41
|
-
const parser = P.lazy(
|
|
42
|
-
() => nextParser.chain(
|
|
43
|
-
(next) => P.seqMap(
|
|
44
|
-
operatorsParser,
|
|
45
|
-
P.of(next),
|
|
46
|
-
parser,
|
|
47
|
-
P.string(":").trim(P.optWhitespace),
|
|
48
|
-
parser,
|
|
49
|
-
(op, cond, val1, _colon, val2) => [op, ["to-boolean", cond], val1, val2]
|
|
50
|
-
).or(P.of(next))
|
|
51
|
-
)
|
|
52
|
-
);
|
|
53
|
-
return parser;
|
|
54
|
-
}
|
|
55
|
-
function BINARY_LEFT(operatorsParser, nextParser) {
|
|
56
|
-
return P.seqMap(nextParser, P.seq(operatorsParser, nextParser).many(), (first, rest) => {
|
|
57
|
-
return rest.reduce((acc, ch) => {
|
|
58
|
-
const [op, another] = ch;
|
|
59
|
-
return [op, acc, another];
|
|
60
|
-
}, first);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
var __defProp$7 = Object.defineProperty;
|
|
65
|
-
var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
66
|
-
var __publicField$7 = (obj, key, value) => {
|
|
67
|
-
__defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
68
|
-
return value;
|
|
69
|
-
};
|
|
70
|
-
class ExpressionParser {
|
|
71
|
-
constructor() {
|
|
72
|
-
__publicField$7(this, "language");
|
|
73
|
-
this.language = this.createLanguage();
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Parse an expression
|
|
77
|
-
*
|
|
78
|
-
* @param expr Expression to parse
|
|
79
|
-
*/
|
|
80
|
-
parseExpression(expr) {
|
|
81
|
-
return this.language.Expr.parse(expr);
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Parse a complete assignment program of the form:
|
|
85
|
-
* a: expr1;
|
|
86
|
-
* b: expr2;
|
|
87
|
-
*
|
|
88
|
-
* @param program Program to parse
|
|
89
|
-
*/
|
|
90
|
-
parseProgram(program) {
|
|
91
|
-
return this.language.ProgramOrEmpty.parse(program);
|
|
92
|
-
}
|
|
93
|
-
createLanguage() {
|
|
94
|
-
const operatorTable = [
|
|
95
|
-
{ type: PREFIX, ops: this.operators({ "-": "-", "!": "!" }) },
|
|
96
|
-
{ type: BINARY_RIGHT, ops: this.operators({ "^": "**" }) },
|
|
97
|
-
{ type: BINARY_LEFT, ops: this.operators({ "*": "*", "/": "/", "%": "%" }) },
|
|
98
|
-
{ type: BINARY_LEFT, ops: this.operators({ "+": "+", "-": "-" }) },
|
|
99
|
-
{ type: BINARY_LEFT, ops: this.operators({ ">=": ">=", "<=": "<=" }) },
|
|
100
|
-
{ type: BINARY_LEFT, ops: this.operators({ "<": "<", ">": ">" }) },
|
|
101
|
-
{
|
|
102
|
-
type: BINARY_LEFT,
|
|
103
|
-
ops: this.operators({ regexi: "~*", equali: "=*", "==": "==", "!=": "!=", "~": "~" })
|
|
104
|
-
},
|
|
105
|
-
{ type: BINARY_LEFT, ops: this.operators({ all: "&&" }) },
|
|
106
|
-
{ type: BINARY_LEFT, ops: this.operators({ any: "||" }) },
|
|
107
|
-
{ type: TERNARY_RIGHT, ops: this.operators({ case: "?" }) }
|
|
108
|
-
];
|
|
109
|
-
return P.createLanguage({
|
|
110
|
-
Whitespace: () => P.regexp(/[ \n]*/).desc("whitespace"),
|
|
111
|
-
NotNewline: () => P.regexp(/[^\n]*/).desc("non-newline"),
|
|
112
|
-
LineComment: (r) => r.NotNewline.wrap(P.string("//"), P.alt(P.string("\n"), P.eof)),
|
|
113
|
-
BlockComment: () => P.regexp(/\/\*[\s\S]*?\*\//),
|
|
114
|
-
Comment: (r) => P.alt(r.LineComment, r.BlockComment).desc("comment"),
|
|
115
|
-
End: () => P.alt(P.string(";"), P.eof),
|
|
116
|
-
_: (r) => r.Comment.sepBy(r.Whitespace).trim(r.Whitespace),
|
|
117
|
-
Integer: () => {
|
|
118
|
-
return P.regexp(/-?[0-9]+/).map(Number);
|
|
119
|
-
},
|
|
120
|
-
Decimal: () => {
|
|
121
|
-
return P.regexp(/-?[0-9]+\.[0-9]+/).map(Number);
|
|
122
|
-
},
|
|
123
|
-
Number: (r) => {
|
|
124
|
-
return P.alt(r.Decimal, r.Integer).desc("number");
|
|
125
|
-
},
|
|
126
|
-
Boolean: () => {
|
|
127
|
-
return P.alt(P.string("true"), P.string("false")).map((val) => val === "true").desc("boolean");
|
|
128
|
-
},
|
|
129
|
-
Null: () => {
|
|
130
|
-
return P.string("null").result(null).desc("null");
|
|
131
|
-
},
|
|
132
|
-
DoubleQuoteString: () => {
|
|
133
|
-
return P.regexp(/"((?:\\.|.)*?)"/, 1).desc("string");
|
|
134
|
-
},
|
|
135
|
-
SingleQuoteString: () => {
|
|
136
|
-
return P.regexp(/'((?:\\.|.)*?)'/, 1).desc("string");
|
|
137
|
-
},
|
|
138
|
-
UnquotedString: () => {
|
|
139
|
-
return P.regexp(/[a-zA-Z_][a-zA-Z0-9_-]*/).desc("string");
|
|
140
|
-
},
|
|
141
|
-
HexColor: () => {
|
|
142
|
-
return P.regexp(/#(?:[0-9a-f]{3}){1,2}/i).desc("hex color");
|
|
143
|
-
},
|
|
144
|
-
String: (r) => {
|
|
145
|
-
return P.alt(r.SingleQuoteString, r.DoubleQuoteString, r.HexColor, r.UnquotedString).map(
|
|
146
|
-
(s) => s.replace(/\\n/gm, "\n")
|
|
147
|
-
);
|
|
148
|
-
},
|
|
149
|
-
Symbol: () => {
|
|
150
|
-
return P.regexp(/[a-zA-Z_][a-zA-Z0-9_-]*/).desc("symbol");
|
|
151
|
-
},
|
|
152
|
-
PartialSymbol: () => {
|
|
153
|
-
return P.regexp(/[a-zA-Z0-9_-]+/).desc("symbol");
|
|
154
|
-
},
|
|
155
|
-
Feature: (r) => {
|
|
156
|
-
return P.seqMap(
|
|
157
|
-
P.string("@"),
|
|
158
|
-
r.PartialSymbol.sepBy(P.string(".")),
|
|
159
|
-
(_feat, symbols) => ["get"].concat(symbols)
|
|
160
|
-
);
|
|
161
|
-
},
|
|
162
|
-
FeatureState: (r) => {
|
|
163
|
-
return P.seqMap(
|
|
164
|
-
P.string("@@"),
|
|
165
|
-
r.PartialSymbol.sepBy(P.string(".")),
|
|
166
|
-
(_feat, symbols) => this.expandFeatureState(symbols)
|
|
167
|
-
);
|
|
168
|
-
},
|
|
169
|
-
Array: (r) => P.string("[").trim(r._).then(r.Value.trim(r._).sepBy(P.string(","))).skip(P.string("]")),
|
|
170
|
-
State: (r) => {
|
|
171
|
-
return P.seqMap(
|
|
172
|
-
P.string("$"),
|
|
173
|
-
r.PartialSymbol.sepBy(P.string(".")),
|
|
174
|
-
(_state, symbols) => ["state"].concat(symbols)
|
|
175
|
-
);
|
|
176
|
-
},
|
|
177
|
-
Paren: (r) => {
|
|
178
|
-
return P.seqMap(P.string("("), r.Expr.trim(r._), P.string(")"), (_lb, expr, _rb) => expr);
|
|
179
|
-
},
|
|
180
|
-
Func: (r) => {
|
|
181
|
-
return P.seqMap(
|
|
182
|
-
r.Symbol.trim(r._),
|
|
183
|
-
P.string("("),
|
|
184
|
-
r.Expr.trim(r._).sepBy(P.string(",")),
|
|
185
|
-
P.string(")"),
|
|
186
|
-
(func, _lb, args, _rb) => [func, ...args]
|
|
187
|
-
);
|
|
188
|
-
},
|
|
189
|
-
Value: (r) => {
|
|
190
|
-
return P.alt(
|
|
191
|
-
r.Paren,
|
|
192
|
-
r.Array,
|
|
193
|
-
r.Func,
|
|
194
|
-
r.Boolean,
|
|
195
|
-
r.Null,
|
|
196
|
-
r.Number,
|
|
197
|
-
r.String,
|
|
198
|
-
r.FeatureState,
|
|
199
|
-
r.Feature,
|
|
200
|
-
r.State
|
|
201
|
-
);
|
|
202
|
-
},
|
|
203
|
-
Expr: (r) => {
|
|
204
|
-
return this.tableParser(operatorTable, r.Value);
|
|
205
|
-
},
|
|
206
|
-
PropertyName: () => {
|
|
207
|
-
return P.regexp(/[a-zA-Z_-][a-zA-Z0-9_-]*/).desc("symbol");
|
|
208
|
-
},
|
|
209
|
-
Assignment: (r) => {
|
|
210
|
-
return P.seqMap(
|
|
211
|
-
r.PropertyName,
|
|
212
|
-
P.string(":").trim(r._),
|
|
213
|
-
r.Expr.trim(r._).node("expr"),
|
|
214
|
-
r.End,
|
|
215
|
-
(key, _colon, node) => [key, { expr: node.value, start: node.start, end: node.end }]
|
|
216
|
-
);
|
|
217
|
-
},
|
|
218
|
-
Program: (r) => {
|
|
219
|
-
return r.Assignment.trim(r._).many().map((statements) => {
|
|
220
|
-
return statements.filter((s) => s !== "").reduce((acc, s) => {
|
|
221
|
-
acc[s[0]] = s[1];
|
|
222
|
-
return acc;
|
|
223
|
-
}, {});
|
|
224
|
-
});
|
|
225
|
-
},
|
|
226
|
-
EmptyProgram: (r) => {
|
|
227
|
-
return P.seqMap(r._, P.eof, () => null);
|
|
228
|
-
},
|
|
229
|
-
ProgramOrEmpty: (r) => {
|
|
230
|
-
return P.alt(r.EmptyProgram, r.Program);
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Helper function to create a parser that parsers a set of operators at the same precedence level
|
|
236
|
-
*
|
|
237
|
-
* @param ops Operator table
|
|
238
|
-
*/
|
|
239
|
-
operators(ops) {
|
|
240
|
-
const keys = Object.keys(ops);
|
|
241
|
-
const ps = keys.map((k) => P.string(ops[k]).trim(P.optWhitespace).result(k));
|
|
242
|
-
return P.alt.apply(null, ps);
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* Helper function to create a table-driver operator parser
|
|
246
|
-
*
|
|
247
|
-
*/
|
|
248
|
-
tableParser(operatorTable, valueParser) {
|
|
249
|
-
return operatorTable.reduce((acc, level) => level.type(level.ops, acc), valueParser);
|
|
250
|
-
}
|
|
251
|
-
expandFeatureState(symbols) {
|
|
252
|
-
let expandedFeatureState = ["feature-state", symbols.shift()];
|
|
253
|
-
symbols.forEach((s) => expandedFeatureState = ["get", s, expandedFeatureState]);
|
|
254
|
-
return expandedFeatureState;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
const palettes = {};
|
|
259
|
-
function registerColorBrewerPalettes() {
|
|
260
|
-
Object.keys(colorbrewer).filter((key) => key !== "schemeGroups").forEach(
|
|
261
|
-
(key) => palettes[key.toLowerCase()] = {
|
|
262
|
-
id: key,
|
|
263
|
-
colors: colorbrewer[key][5]
|
|
264
|
-
}
|
|
265
|
-
);
|
|
266
|
-
}
|
|
267
|
-
function fromPalette(expr, parentExpression) {
|
|
268
|
-
const paletteIdOrArray = expr[1];
|
|
269
|
-
const property = expr[2];
|
|
270
|
-
let colorStops = expr.slice(3);
|
|
271
|
-
let palette;
|
|
272
|
-
if (isString(paletteIdOrArray)) {
|
|
273
|
-
palette = palettes[paletteIdOrArray.toLowerCase()]?.colors || palettes["Greys"].colors;
|
|
274
|
-
} else if (isArray(paletteIdOrArray) && paletteIdOrArray[0] === "literal") {
|
|
275
|
-
palette = paletteIdOrArray[1];
|
|
276
|
-
} else {
|
|
277
|
-
throw new FlowExpressionError(parentExpression.expression, "evaluationError", [
|
|
278
|
-
"from-palette requires palette id as string or custom palette array"
|
|
279
|
-
]);
|
|
280
|
-
}
|
|
281
|
-
const numPaletteEntries = palette.length;
|
|
282
|
-
let reversePalette = false;
|
|
283
|
-
if (numPaletteEntries < 5) {
|
|
284
|
-
throw new FlowExpressionError(parentExpression.expression, "evaluationError", [
|
|
285
|
-
"custom palette requires at least 5 color entries"
|
|
286
|
-
]);
|
|
287
|
-
}
|
|
288
|
-
switch (colorStops.length) {
|
|
289
|
-
case 2:
|
|
290
|
-
break;
|
|
291
|
-
case 3:
|
|
292
|
-
reversePalette = !!colorStops[2];
|
|
293
|
-
colorStops = colorStops.slice(0, 2);
|
|
294
|
-
break;
|
|
295
|
-
case numPaletteEntries:
|
|
296
|
-
break;
|
|
297
|
-
case numPaletteEntries + 1:
|
|
298
|
-
reversePalette = !!colorStops[numPaletteEntries];
|
|
299
|
-
colorStops = colorStops.slice(0, numPaletteEntries);
|
|
300
|
-
break;
|
|
301
|
-
default:
|
|
302
|
-
throw new FlowExpressionError(parentExpression.expression, "evaluationError", [
|
|
303
|
-
"incorrect color stop arguments"
|
|
304
|
-
]);
|
|
305
|
-
}
|
|
306
|
-
if (colorStops.length === 2) {
|
|
307
|
-
const min = colorStops[0];
|
|
308
|
-
const max = colorStops[1];
|
|
309
|
-
colorStops = [];
|
|
310
|
-
const step = (max - min) / (numPaletteEntries - 1);
|
|
311
|
-
for (let i = 0; i < numPaletteEntries; i++) {
|
|
312
|
-
colorStops.push(min + i * step);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
expr = ["interpolate-lab", ["linear"], property];
|
|
316
|
-
for (let i = 0; i < colorStops.length; i++) {
|
|
317
|
-
expr.push(colorStops[i]);
|
|
318
|
-
expr.push(reversePalette ? palette[colorStops.length - i - 1] : palette[i]);
|
|
319
|
-
}
|
|
320
|
-
return expr;
|
|
321
|
-
}
|
|
322
|
-
const customFromPaletteFn = {
|
|
323
|
-
name: "from-palette",
|
|
324
|
-
initialize: registerColorBrewerPalettes,
|
|
325
|
-
fn: fromPalette
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
function regexFunction(operator, caseSensitive = true) {
|
|
329
|
-
return (expr, _) => {
|
|
330
|
-
expr[0] = operator;
|
|
331
|
-
expr.push(["collator", { "case-sensitive": caseSensitive }]);
|
|
332
|
-
return expr;
|
|
333
|
-
};
|
|
334
|
-
}
|
|
335
|
-
const equal = {
|
|
336
|
-
name: "equal",
|
|
337
|
-
fn: regexFunction("==", true)
|
|
338
|
-
};
|
|
339
|
-
const equali = {
|
|
340
|
-
name: "iequal",
|
|
341
|
-
fn: regexFunction("==", false)
|
|
342
|
-
};
|
|
343
|
-
const regex = {
|
|
344
|
-
name: "regex",
|
|
345
|
-
fn: regexFunction("~", true)
|
|
346
|
-
};
|
|
347
|
-
const regexi = {
|
|
348
|
-
name: "regexi",
|
|
349
|
-
fn: regexFunction("~", false)
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
function stateCustomFunction(expr, parentExpression) {
|
|
353
|
-
if (!parentExpression.store) {
|
|
354
|
-
console.warn(
|
|
355
|
-
`The reactive expression '${parentExpression.expression}' references state properties but is not bound to a state store. The expression cannot be evaluated - returning null.`
|
|
356
|
-
);
|
|
357
|
-
return null;
|
|
358
|
-
}
|
|
359
|
-
const path = expr.slice(1).join(".");
|
|
360
|
-
const val = parentExpression.store.get(path);
|
|
361
|
-
if (isNil(val)) {
|
|
362
|
-
return null;
|
|
363
|
-
} else if (typeof val === "object") {
|
|
364
|
-
return ["literal", val];
|
|
365
|
-
} else {
|
|
366
|
-
return val;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
const customStateFn = {
|
|
370
|
-
name: "state",
|
|
371
|
-
fn: stateCustomFunction
|
|
372
|
-
};
|
|
373
|
-
|
|
374
|
-
var __defProp$6 = Object.defineProperty;
|
|
375
|
-
var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
376
|
-
var __publicField$6 = (obj, key, value) => {
|
|
377
|
-
__defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
378
|
-
return value;
|
|
379
|
-
};
|
|
380
|
-
const _ReactiveExpression = class _ReactiveExpression {
|
|
381
|
-
constructor(expression, parsedExpression) {
|
|
382
|
-
__publicField$6(this, "_expression", "");
|
|
383
|
-
__publicField$6(this, "parsedResult");
|
|
384
|
-
__publicField$6(this, "_store", null);
|
|
385
|
-
makeObservable(
|
|
386
|
-
this,
|
|
387
|
-
{
|
|
388
|
-
_store: observable.ref,
|
|
389
|
-
maplibreExpression: computed,
|
|
390
|
-
value: computed,
|
|
391
|
-
bindState: action
|
|
392
|
-
},
|
|
393
|
-
{ name: this.formatName(expression) }
|
|
394
|
-
);
|
|
395
|
-
this._expression = expression;
|
|
396
|
-
if (isDefined(parsedExpression)) {
|
|
397
|
-
this.parsedResult = {
|
|
398
|
-
status: true,
|
|
399
|
-
value: parsedExpression
|
|
400
|
-
};
|
|
401
|
-
} else {
|
|
402
|
-
this.parsedResult = _ReactiveExpression.parser.parseExpression(expression);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
static hasCustomFunction(fn) {
|
|
406
|
-
return !!this.customFunctions[fn];
|
|
407
|
-
}
|
|
408
|
-
static registerCustomFunction(fn) {
|
|
409
|
-
if (fn.initialize)
|
|
410
|
-
fn.initialize();
|
|
411
|
-
this.customFunctions[fn.name] = fn;
|
|
412
|
-
}
|
|
413
|
-
static parseProgram(program) {
|
|
414
|
-
const parsedProgram = this.parser.parseProgram(program);
|
|
415
|
-
if (isString(program) && program.length === 0) {
|
|
416
|
-
return {};
|
|
417
|
-
}
|
|
418
|
-
if (parsedProgram.status) {
|
|
419
|
-
const keys = Object.keys(parsedProgram.value);
|
|
420
|
-
const expressions = keys.reduce((accum, key) => {
|
|
421
|
-
const expr = parsedProgram.value[key];
|
|
422
|
-
const expressionString = program.slice(expr.start.offset, expr.end.offset);
|
|
423
|
-
accum[key] = new _ReactiveExpression(expressionString, expr.expr);
|
|
424
|
-
return accum;
|
|
425
|
-
}, {});
|
|
426
|
-
return expressions;
|
|
427
|
-
} else {
|
|
428
|
-
throw new FlowExpressionError(program, "parseError", [
|
|
429
|
-
`expected ${parsedProgram.expected.join(" ")} at line ${parsedProgram.index.line}, column ${parsedProgram.index.column}]`
|
|
430
|
-
]);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
// Computed
|
|
434
|
-
get maplibreExpression() {
|
|
435
|
-
if (this.isParseError(this.parsedResult)) {
|
|
436
|
-
throw this.parseError;
|
|
437
|
-
}
|
|
438
|
-
return this.expandCustomFunctions(this.parsedResult.value);
|
|
439
|
-
}
|
|
440
|
-
// Computed
|
|
441
|
-
get value() {
|
|
442
|
-
return this.evaluateExpression();
|
|
443
|
-
}
|
|
444
|
-
get parseError() {
|
|
445
|
-
if (this.isParseError(this.parsedResult)) {
|
|
446
|
-
return new FlowExpressionError(this._expression, "parseError", [
|
|
447
|
-
`index: ${this.parsedResult.index.offset}`,
|
|
448
|
-
`expected: ${this.parsedResult.expected.join(" ")}`
|
|
449
|
-
]);
|
|
450
|
-
}
|
|
451
|
-
return null;
|
|
452
|
-
}
|
|
453
|
-
get expression() {
|
|
454
|
-
return this._expression;
|
|
455
|
-
}
|
|
456
|
-
get store() {
|
|
457
|
-
return this._store;
|
|
458
|
-
}
|
|
459
|
-
bindState(store) {
|
|
460
|
-
this._store = store;
|
|
461
|
-
return this;
|
|
462
|
-
}
|
|
463
|
-
toStream(fireImmediately = true) {
|
|
464
|
-
return toStream(() => this.value, fireImmediately);
|
|
465
|
-
}
|
|
466
|
-
evaluateExpression() {
|
|
467
|
-
const { result, value } = maplibreSpec.expression.createExpression(this.maplibreExpression);
|
|
468
|
-
if (result === "success") {
|
|
469
|
-
return value.evaluate({ zoom: 0 });
|
|
470
|
-
}
|
|
471
|
-
throw new FlowExpressionError(
|
|
472
|
-
this.expression,
|
|
473
|
-
"evaluationError",
|
|
474
|
-
value.map((value2) => value2.message)
|
|
475
|
-
);
|
|
476
|
-
}
|
|
477
|
-
expandCustomFunctions(expr) {
|
|
478
|
-
if (this.isFunctionExpression(expr)) {
|
|
479
|
-
const func = expr[0];
|
|
480
|
-
const args = expr.slice(1).map((arg) => this.expandCustomFunctions(arg));
|
|
481
|
-
expr = [func, ...args];
|
|
482
|
-
return _ReactiveExpression.hasCustomFunction(func) ? _ReactiveExpression.customFunctions[func].fn(expr, this) : expr;
|
|
483
|
-
}
|
|
484
|
-
return expr;
|
|
485
|
-
}
|
|
486
|
-
isParseError(val) {
|
|
487
|
-
return !val.status;
|
|
488
|
-
}
|
|
489
|
-
isFunctionExpression(expr) {
|
|
490
|
-
return Array.isArray(expr);
|
|
491
|
-
}
|
|
492
|
-
formatName(expr) {
|
|
493
|
-
return `FlowCoreExpression<${expr}>}`;
|
|
494
|
-
}
|
|
495
|
-
};
|
|
496
|
-
__publicField$6(_ReactiveExpression, "parser", new ExpressionParser());
|
|
497
|
-
__publicField$6(_ReactiveExpression, "customFunctions", {});
|
|
498
|
-
let ReactiveExpression = _ReactiveExpression;
|
|
499
|
-
ReactiveExpression.registerCustomFunction(customStateFn);
|
|
500
|
-
ReactiveExpression.registerCustomFunction(customFromPaletteFn);
|
|
501
|
-
ReactiveExpression.registerCustomFunction(regex);
|
|
502
|
-
ReactiveExpression.registerCustomFunction(regexi);
|
|
503
|
-
ReactiveExpression.registerCustomFunction(equal);
|
|
504
|
-
ReactiveExpression.registerCustomFunction(equali);
|
|
505
|
-
|
|
506
|
-
var __defProp$5 = Object.defineProperty;
|
|
507
|
-
var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
508
|
-
var __publicField$5 = (obj, key, value) => {
|
|
509
|
-
__defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
510
|
-
return value;
|
|
511
|
-
};
|
|
512
|
-
const _MapDataSource = class _MapDataSource {
|
|
513
|
-
constructor(options) {
|
|
514
|
-
__publicField$5(this, "_options");
|
|
515
|
-
__publicField$5(this, "_srcExpression", null);
|
|
516
|
-
__publicField$5(this, "_parameters", {});
|
|
517
|
-
__publicField$5(this, "_state", null);
|
|
518
|
-
this._options = {
|
|
519
|
-
..._MapDataSource.defaultOptions,
|
|
520
|
-
...options
|
|
521
|
-
};
|
|
522
|
-
if (!isIn(options.type, ["vector", "geojson", "raster"])) {
|
|
523
|
-
throw new FlowError(`${this.formattedName()}: unrecognized type '${options.type}'`);
|
|
524
|
-
}
|
|
525
|
-
this.setSrcExpression(options.src);
|
|
526
|
-
mobx.makeObservable(
|
|
527
|
-
this,
|
|
528
|
-
{
|
|
529
|
-
//observable
|
|
530
|
-
_options: mobx.observable.shallow,
|
|
531
|
-
_srcExpression: mobx.observable,
|
|
532
|
-
_parameters: mobx.observable,
|
|
533
|
-
//computed
|
|
534
|
-
dataSourceSpecification: mobx.computed,
|
|
535
|
-
// actions
|
|
536
|
-
bindState: mobx.action,
|
|
537
|
-
setSrc: mobx.action,
|
|
538
|
-
setParameter: mobx.action
|
|
539
|
-
},
|
|
540
|
-
{ name: this.formattedName(options.id) }
|
|
541
|
-
);
|
|
542
|
-
}
|
|
543
|
-
get id() {
|
|
544
|
-
return this._options.id;
|
|
545
|
-
}
|
|
546
|
-
get type() {
|
|
547
|
-
return this._options.type;
|
|
548
|
-
}
|
|
549
|
-
get featureId() {
|
|
550
|
-
return this._options.featureId;
|
|
551
|
-
}
|
|
552
|
-
get dataSourceSpecification() {
|
|
553
|
-
let src = this._srcExpression ? mobx.toJS(this._srcExpression.value) : this._options.src;
|
|
554
|
-
if (isString(src)) {
|
|
555
|
-
src = this.expandSrc(src, this._options.type);
|
|
556
|
-
}
|
|
557
|
-
let ds;
|
|
558
|
-
switch (this._options.type) {
|
|
559
|
-
case "vector":
|
|
560
|
-
ds = isStringFull(src) ? {
|
|
561
|
-
type: "vector",
|
|
562
|
-
url: src
|
|
563
|
-
} : (
|
|
564
|
-
// For null src use an empty geojson datasource as a placeholder
|
|
565
|
-
{
|
|
566
|
-
type: "geojson",
|
|
567
|
-
data: { type: "FeatureCollection", features: [] }
|
|
568
|
-
}
|
|
569
|
-
);
|
|
570
|
-
if (this._options.featureId) {
|
|
571
|
-
ds.promoteId = this._options.featureId;
|
|
572
|
-
}
|
|
573
|
-
return ds;
|
|
574
|
-
case "raster":
|
|
575
|
-
ds = isStringFull(src) ? {
|
|
576
|
-
type: "raster",
|
|
577
|
-
url: src
|
|
578
|
-
} : (
|
|
579
|
-
// For null src use an empty geojson datasource as a placeholder
|
|
580
|
-
{
|
|
581
|
-
type: "geojson",
|
|
582
|
-
data: { type: "FeatureCollection", features: [] }
|
|
583
|
-
}
|
|
584
|
-
);
|
|
585
|
-
return ds;
|
|
586
|
-
case "geojson":
|
|
587
|
-
ds = {
|
|
588
|
-
type: "geojson",
|
|
589
|
-
data: src || { type: "FeatureCollection", features: [] }
|
|
590
|
-
};
|
|
591
|
-
if (this._options.cluster) {
|
|
592
|
-
ds.cluster = true;
|
|
593
|
-
ds.clusterMaxZoom = this._options.clusterMaxZoom;
|
|
594
|
-
ds.clusterMinPoints = this._options.clusterMinPoints;
|
|
595
|
-
ds.clusterRadius = this._options.clusterRadius;
|
|
596
|
-
}
|
|
597
|
-
if (this._options.featureId) {
|
|
598
|
-
ds.promoteId = this._options.featureId;
|
|
599
|
-
}
|
|
600
|
-
return ds;
|
|
601
|
-
default:
|
|
602
|
-
throw new FlowError(`${this.formattedName()}: unrecognized type '${this._options.type}'`);
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
bindState(state) {
|
|
606
|
-
this._state = state;
|
|
607
|
-
if (this._srcExpression) {
|
|
608
|
-
this._srcExpression?.bindState(state);
|
|
609
|
-
}
|
|
610
|
-
Object.values(this._parameters).forEach((expr) => expr.bindState(state));
|
|
611
|
-
return this;
|
|
612
|
-
}
|
|
613
|
-
setSrc(val) {
|
|
614
|
-
this._options.src = val;
|
|
615
|
-
this.setSrcExpression(val);
|
|
616
|
-
}
|
|
617
|
-
setParameter(name, expression) {
|
|
618
|
-
if (isNil(expression)) {
|
|
619
|
-
delete this._parameters[name];
|
|
620
|
-
} else {
|
|
621
|
-
const expr = new ReactiveExpression(expression);
|
|
622
|
-
this._parameters[name] = expr.bindState(this._state);
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
setFlowEndpoint(endpoint) {
|
|
626
|
-
this._options.flowHost = endpoint.host;
|
|
627
|
-
this._options.flowApiKey = endpoint.apiKey;
|
|
628
|
-
}
|
|
629
|
-
formattedName(id) {
|
|
630
|
-
return `MapDataSource<${id || this._options.id}>`;
|
|
631
|
-
}
|
|
632
|
-
setSrcExpression(src) {
|
|
633
|
-
if (isString(src)) {
|
|
634
|
-
if (isURL(src))
|
|
635
|
-
src = `'${src}'`;
|
|
636
|
-
this._srcExpression = new ReactiveExpression(src);
|
|
637
|
-
this._srcExpression.bindState(this._state);
|
|
638
|
-
} else {
|
|
639
|
-
this._srcExpression = null;
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
/**
|
|
643
|
-
* Convert a src parameter to final URL
|
|
644
|
-
*
|
|
645
|
-
* @param src Data source url/dataset/tilesource ID
|
|
646
|
-
* @param type Data source type
|
|
647
|
-
* @returns URL
|
|
648
|
-
*/
|
|
649
|
-
expandSrc(src, type) {
|
|
650
|
-
const host = this._options.flowHost;
|
|
651
|
-
let isGeoJSON = false;
|
|
652
|
-
if (!isURL(src)) {
|
|
653
|
-
switch (type) {
|
|
654
|
-
case "vector":
|
|
655
|
-
case "raster":
|
|
656
|
-
src = `${host}/tiles/${src}/index.json`;
|
|
657
|
-
break;
|
|
658
|
-
case "geojson":
|
|
659
|
-
src = `${host}/api/v1/datasets/${src}/query`;
|
|
660
|
-
isGeoJSON = true;
|
|
661
|
-
break;
|
|
662
|
-
default:
|
|
663
|
-
throw new FlowError(`${this.formattedName()}: unrecognized type '${this._options.type}'`);
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
const urlObj = new URL(src);
|
|
667
|
-
const combinedParams = new URLSearchParams(urlObj.searchParams);
|
|
668
|
-
Object.entries(this._parameters).filter(([_, expr]) => !isNil(expr.value)).forEach(([key, expr]) => combinedParams.append(key, expr.value));
|
|
669
|
-
if (this._options.flowHost && src.startsWith(this._options.flowHost) && !combinedParams.has("apikey") && this._options.flowApiKey) {
|
|
670
|
-
combinedParams.append("apikey", this._options.flowApiKey);
|
|
671
|
-
}
|
|
672
|
-
if (this._options.limit) {
|
|
673
|
-
combinedParams.append("limit", this._options.limit.toString(10));
|
|
674
|
-
}
|
|
675
|
-
if (isGeoJSON) {
|
|
676
|
-
combinedParams.append("format", "geojson");
|
|
677
|
-
}
|
|
678
|
-
urlObj.search = combinedParams.toString();
|
|
679
|
-
return urlObj.toString();
|
|
680
|
-
}
|
|
681
|
-
};
|
|
682
|
-
__publicField$5(_MapDataSource, "defaultOptions", {
|
|
683
|
-
type: "vector",
|
|
684
|
-
cluster: false,
|
|
685
|
-
clusterRadius: 50,
|
|
686
|
-
clusterMaxZoom: 20,
|
|
687
|
-
clusterMinPoints: 2,
|
|
688
|
-
flowHost: "https://flow.emu-analytics.net"
|
|
689
|
-
});
|
|
690
|
-
let MapDataSource = _MapDataSource;
|
|
691
|
-
|
|
692
|
-
var __defProp$4 = Object.defineProperty;
|
|
693
|
-
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
694
|
-
var __publicField$4 = (obj, key, value) => {
|
|
695
|
-
__defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
696
|
-
return value;
|
|
697
|
-
};
|
|
698
|
-
const _MapLayer = class _MapLayer {
|
|
699
|
-
constructor(options) {
|
|
700
|
-
__publicField$4(this, "_options");
|
|
701
|
-
__publicField$4(this, "_state", null);
|
|
702
|
-
__publicField$4(this, "_filter", null);
|
|
703
|
-
__publicField$4(this, "_paintProps", {});
|
|
704
|
-
__publicField$4(this, "_layoutProps", {});
|
|
705
|
-
this._options = {
|
|
706
|
-
..._MapLayer._defaultOptions,
|
|
707
|
-
...options
|
|
708
|
-
};
|
|
709
|
-
this.getPropertyMetadata("visibility", options.type);
|
|
710
|
-
makeObservable(
|
|
711
|
-
this,
|
|
712
|
-
{
|
|
713
|
-
//observable
|
|
714
|
-
_paintProps: observable,
|
|
715
|
-
_layoutProps: observable,
|
|
716
|
-
_filter: observable,
|
|
717
|
-
_options: observable,
|
|
718
|
-
//computed
|
|
719
|
-
layerSpecification: computed,
|
|
720
|
-
// actions
|
|
721
|
-
bindState: action,
|
|
722
|
-
setMinZoom: action,
|
|
723
|
-
setMaxZoom: action,
|
|
724
|
-
setInteractive: action,
|
|
725
|
-
setAbove: action,
|
|
726
|
-
setBelow: action,
|
|
727
|
-
setStyle: action,
|
|
728
|
-
setStyleProperty: action,
|
|
729
|
-
setFilter: action
|
|
730
|
-
},
|
|
731
|
-
{ name: this.formattedName(options.id) }
|
|
732
|
-
);
|
|
733
|
-
if (options.filter) {
|
|
734
|
-
this.setFilter(options.filter);
|
|
735
|
-
}
|
|
736
|
-
if (options.style) {
|
|
737
|
-
this.setStyle(options.style);
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
get layerSpecification() {
|
|
741
|
-
this._options.above;
|
|
742
|
-
this._options.below;
|
|
743
|
-
const layer = {
|
|
744
|
-
id: this._options.id,
|
|
745
|
-
type: this._options.type,
|
|
746
|
-
source: this._options.source
|
|
747
|
-
};
|
|
748
|
-
if (isDefined(this._options.minZoom)) {
|
|
749
|
-
layer.minzoom = this._options.minZoom;
|
|
750
|
-
}
|
|
751
|
-
if (isDefined(this._options.maxZoom)) {
|
|
752
|
-
layer.maxzoom = this._options.maxZoom;
|
|
753
|
-
}
|
|
754
|
-
if (isDefined(this._options.sourceLayer)) {
|
|
755
|
-
layer["source-layer"] = this._options.sourceLayer;
|
|
756
|
-
}
|
|
757
|
-
if (isDefined(this._filter)) {
|
|
758
|
-
layer.filter = this._filter.maplibreExpression;
|
|
759
|
-
}
|
|
760
|
-
if (isObjectFull(this._paintProps)) {
|
|
761
|
-
layer.paint = Object.keys(this._paintProps).reduce((accum, key) => {
|
|
762
|
-
accum[key] = this._paintProps[key].maplibreExpression;
|
|
763
|
-
return accum;
|
|
764
|
-
}, {});
|
|
765
|
-
}
|
|
766
|
-
if (isObjectFull(this._layoutProps)) {
|
|
767
|
-
layer.layout = Object.keys(this._layoutProps).reduce((accum, key) => {
|
|
768
|
-
let expr = this._layoutProps[key].maplibreExpression;
|
|
769
|
-
if (key === "visibility") {
|
|
770
|
-
expr = this._layoutProps[key].value ? "visible" : "none";
|
|
771
|
-
}
|
|
772
|
-
accum[key] = expr;
|
|
773
|
-
return accum;
|
|
774
|
-
}, {});
|
|
775
|
-
}
|
|
776
|
-
return layer;
|
|
777
|
-
}
|
|
778
|
-
get id() {
|
|
779
|
-
return this._options.id;
|
|
780
|
-
}
|
|
781
|
-
get type() {
|
|
782
|
-
return this._options.type;
|
|
783
|
-
}
|
|
784
|
-
get source() {
|
|
785
|
-
return this._options.source;
|
|
786
|
-
}
|
|
787
|
-
get interactive() {
|
|
788
|
-
return !!this._options.interactive;
|
|
789
|
-
}
|
|
790
|
-
get above() {
|
|
791
|
-
return this._options.above;
|
|
792
|
-
}
|
|
793
|
-
get below() {
|
|
794
|
-
return this._options.below;
|
|
795
|
-
}
|
|
796
|
-
bindState(state) {
|
|
797
|
-
this._state = state;
|
|
798
|
-
if (this._filter) {
|
|
799
|
-
this._filter.bindState(state);
|
|
800
|
-
}
|
|
801
|
-
Object.values(this._paintProps).forEach((prop) => prop.bindState(state));
|
|
802
|
-
Object.values(this._layoutProps).forEach((prop) => prop.bindState(state));
|
|
803
|
-
return this;
|
|
804
|
-
}
|
|
805
|
-
setMinZoom(zoom) {
|
|
806
|
-
this._options.minZoom = zoom;
|
|
807
|
-
return this;
|
|
808
|
-
}
|
|
809
|
-
setMaxZoom(zoom) {
|
|
810
|
-
this._options.maxZoom = zoom;
|
|
811
|
-
return this;
|
|
812
|
-
}
|
|
813
|
-
setInteractive(interactive) {
|
|
814
|
-
this._options.interactive = interactive;
|
|
815
|
-
return this;
|
|
816
|
-
}
|
|
817
|
-
setAbove(layerId) {
|
|
818
|
-
this._options.above = layerId;
|
|
819
|
-
return this;
|
|
820
|
-
}
|
|
821
|
-
setBelow(layerId) {
|
|
822
|
-
this._options.below = layerId;
|
|
823
|
-
return this;
|
|
824
|
-
}
|
|
825
|
-
setStyle(styleProgram) {
|
|
826
|
-
const parsedProgram = ReactiveExpression.parseProgram(styleProgram);
|
|
827
|
-
const props = Object.keys(parsedProgram);
|
|
828
|
-
props.forEach((prop) => {
|
|
829
|
-
const metadata = this.getPropertyMetadata(prop, this._options.type);
|
|
830
|
-
const layerProps = metadata.type === "paint" ? this._paintProps : this._layoutProps;
|
|
831
|
-
layerProps[prop] = parsedProgram[prop].bindState(this._state);
|
|
832
|
-
});
|
|
833
|
-
}
|
|
834
|
-
/**
|
|
835
|
-
* Set an individual style property.
|
|
836
|
-
*
|
|
837
|
-
* @param property Property name.
|
|
838
|
-
* @param expression Property style expression.
|
|
839
|
-
*/
|
|
840
|
-
setStyleProperty(property, expression) {
|
|
841
|
-
const metadata = this.getPropertyMetadata(property, this._options.type);
|
|
842
|
-
const props = metadata.type === "paint" ? this._paintProps : this._layoutProps;
|
|
843
|
-
if (isNil(expression)) {
|
|
844
|
-
delete props[property];
|
|
845
|
-
} else {
|
|
846
|
-
const expr = new ReactiveExpression(expression).bindState(this._state);
|
|
847
|
-
if (expr.parseError) {
|
|
848
|
-
throw expr.parseError;
|
|
849
|
-
}
|
|
850
|
-
props[property] = expr;
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
setFilter(expression) {
|
|
854
|
-
this._filter = null;
|
|
855
|
-
if (isDefined(expression)) {
|
|
856
|
-
let expr = new ReactiveExpression(expression).bindState(this._state);
|
|
857
|
-
if (expr.parseError) {
|
|
858
|
-
throw expr.parseError;
|
|
859
|
-
}
|
|
860
|
-
if (!maplibreSpec.expression.isExpressionFilter(expr.maplibreExpression)) {
|
|
861
|
-
expr = new ReactiveExpression(expr.expression, ["to-boolean", expr.maplibreExpression]);
|
|
862
|
-
}
|
|
863
|
-
this._filter = expr;
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
formattedName(id) {
|
|
867
|
-
return `MapLayer<${id || this._options.id}>`;
|
|
868
|
-
}
|
|
869
|
-
getPropertyMetadata(property, layerType) {
|
|
870
|
-
if (!_MapLayer._propertyMetadataIndex) {
|
|
871
|
-
_MapLayer.initializePropertyMetadataIndex();
|
|
872
|
-
}
|
|
873
|
-
const layerMetadata = _MapLayer._propertyMetadataIndex[layerType];
|
|
874
|
-
if (!layerMetadata) {
|
|
875
|
-
throw new FlowError(`${this.formattedName()}: unknown layer type '${layerType}'`);
|
|
876
|
-
}
|
|
877
|
-
const propertyMetadata = layerMetadata[property];
|
|
878
|
-
if (!propertyMetadata) {
|
|
879
|
-
throw new FlowError(`${this.formattedName()}: unknown layer property '${property}'`);
|
|
880
|
-
}
|
|
881
|
-
return propertyMetadata;
|
|
882
|
-
}
|
|
883
|
-
static initializePropertyMetadataIndex() {
|
|
884
|
-
const layerTypes = Object.keys(maplibreSpec.latest.layer.type.values);
|
|
885
|
-
this._propertyMetadataIndex = layerTypes.reduce((acc, layerType) => {
|
|
886
|
-
acc[layerType] = {};
|
|
887
|
-
["layout", "paint"].forEach((propType) => {
|
|
888
|
-
Object.keys(maplibreSpec.latest[`${propType}_${layerType}`]).forEach((prop) => {
|
|
889
|
-
acc[layerType][prop] = {
|
|
890
|
-
property: prop,
|
|
891
|
-
type: propType,
|
|
892
|
-
definition: maplibreSpec.latest[`${propType}_${layerType}`][prop]
|
|
893
|
-
};
|
|
894
|
-
});
|
|
895
|
-
});
|
|
896
|
-
return acc;
|
|
897
|
-
}, {});
|
|
898
|
-
}
|
|
899
|
-
};
|
|
900
|
-
__publicField$4(_MapLayer, "_propertyMetadataIndex");
|
|
901
|
-
__publicField$4(_MapLayer, "_defaultOptions", {
|
|
902
|
-
interactive: true,
|
|
903
|
-
minZoom: 0,
|
|
904
|
-
maxZoom: 18
|
|
905
|
-
});
|
|
906
|
-
let MapLayer = _MapLayer;
|
|
907
|
-
|
|
908
|
-
class FlowMapError extends FlowError {
|
|
909
|
-
constructor(message, originalError) {
|
|
910
|
-
super(message, originalError);
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
function assert(condition, message) {
|
|
915
|
-
if (!condition) {
|
|
916
|
-
throw new FlowError(message ?? "Assertion failed");
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
function die(message) {
|
|
920
|
-
throw new FlowError(message);
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
var __defProp$3 = Object.defineProperty;
|
|
924
|
-
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
925
|
-
var __publicField$3 = (obj, key, value) => {
|
|
926
|
-
__defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
927
|
-
return value;
|
|
928
|
-
};
|
|
929
|
-
class KeyboardShortcutManager {
|
|
930
|
-
constructor() {
|
|
931
|
-
__publicField$3(this, "listeners");
|
|
932
|
-
/**
|
|
933
|
-
* Handles key events of the root handler and passes them down to listeners.
|
|
934
|
-
* @param event
|
|
935
|
-
*/
|
|
936
|
-
__publicField$3(this, "handleKeyboardEvent", (event) => {
|
|
937
|
-
if (this.isInputEvent(event))
|
|
938
|
-
return;
|
|
939
|
-
const key = this.keyDefinitionFromEvent(event);
|
|
940
|
-
for (const listener of this.listeners) {
|
|
941
|
-
const handler = listener.bindings[key];
|
|
942
|
-
if (handler) {
|
|
943
|
-
const propagate = handler(event);
|
|
944
|
-
if (propagate === true) {
|
|
945
|
-
continue;
|
|
946
|
-
} else {
|
|
947
|
-
event.stopPropagation();
|
|
948
|
-
return;
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
});
|
|
953
|
-
this.listeners = [];
|
|
954
|
-
document.addEventListener("keydown", this.handleKeyboardEvent);
|
|
955
|
-
}
|
|
956
|
-
/**
|
|
957
|
-
* Adds listener to keyboard events.
|
|
958
|
-
* @param bindings Object containing key/value pairs of keyCode/eventHandler function. Can add multiple comma separated `,` keyCodes for the same handler. Can optionally return `false` to stop propagation of other handlers.
|
|
959
|
-
* @param priority Can optionally set the priority of event handler, higher value means higher priority. Defaults to 0.
|
|
960
|
-
* @returns Function that can be used to unbind the listener.
|
|
961
|
-
*/
|
|
962
|
-
addListener(bindings, priority) {
|
|
963
|
-
bindings = this.splitEventBindings(bindings);
|
|
964
|
-
const listener = this.addToListeners({ bindings, priority: priority ?? 0 });
|
|
965
|
-
const removeListener = () => {
|
|
966
|
-
this.removeFromListeners(listener);
|
|
967
|
-
};
|
|
968
|
-
return removeListener;
|
|
969
|
-
}
|
|
970
|
-
/**
|
|
971
|
-
* Splits multiple keyCode events and creates a new bindings map.
|
|
972
|
-
* @param bindings
|
|
973
|
-
*/
|
|
974
|
-
splitEventBindings(bindings) {
|
|
975
|
-
const splitBindings = {};
|
|
976
|
-
for (const event in bindings) {
|
|
977
|
-
event.split(",").forEach((splitEvent) => {
|
|
978
|
-
splitBindings[this.normalizeKeyDefinition(splitEvent)] = bindings[event];
|
|
979
|
-
});
|
|
980
|
-
}
|
|
981
|
-
return splitBindings;
|
|
982
|
-
}
|
|
983
|
-
/**
|
|
984
|
-
* Checks is the event comes from an input type.
|
|
985
|
-
* @param event
|
|
986
|
-
*/
|
|
987
|
-
isInputEvent(event) {
|
|
988
|
-
if (event.target instanceof Node) {
|
|
989
|
-
switch (event.target.nodeName) {
|
|
990
|
-
case "INPUT":
|
|
991
|
-
case "SELECT":
|
|
992
|
-
case "TEXTAREA":
|
|
993
|
-
return true;
|
|
994
|
-
default:
|
|
995
|
-
return false;
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
return false;
|
|
999
|
-
}
|
|
1000
|
-
/**
|
|
1001
|
-
* Adds listener into internal array of listeners and sorts in `descending` order.
|
|
1002
|
-
* @param listener
|
|
1003
|
-
*/
|
|
1004
|
-
addToListeners(listener) {
|
|
1005
|
-
this.listeners.push(listener);
|
|
1006
|
-
this.listeners.sort((a, b) => b.priority - a.priority);
|
|
1007
|
-
return listener;
|
|
1008
|
-
}
|
|
1009
|
-
/**
|
|
1010
|
-
* Removes listener from internal array of listeners.
|
|
1011
|
-
* @param listenerToRemove
|
|
1012
|
-
*/
|
|
1013
|
-
removeFromListeners(listenerToRemove) {
|
|
1014
|
-
this.listeners = this.listeners.filter((listener) => listener !== listenerToRemove);
|
|
1015
|
-
}
|
|
1016
|
-
normalizeKeyDefinition(keyDef) {
|
|
1017
|
-
const parts = keyDef.split("+");
|
|
1018
|
-
const ev = {
|
|
1019
|
-
ctrlKey: parts.includes("Ctrl"),
|
|
1020
|
-
shiftKey: parts.includes("Shift"),
|
|
1021
|
-
altKey: parts.includes("Alt"),
|
|
1022
|
-
metaKey: parts.includes("Meta"),
|
|
1023
|
-
code: parts[parts.length - 1]
|
|
1024
|
-
};
|
|
1025
|
-
return this.keyDefinitionFromEvent(ev);
|
|
1026
|
-
}
|
|
1027
|
-
keyDefinitionFromEvent(ev) {
|
|
1028
|
-
let keyDef = "";
|
|
1029
|
-
if (ev.ctrlKey)
|
|
1030
|
-
keyDef += "Ctrl+";
|
|
1031
|
-
if (ev.shiftKey)
|
|
1032
|
-
keyDef += "Shift+";
|
|
1033
|
-
if (ev.altKey)
|
|
1034
|
-
keyDef += "Alt+";
|
|
1035
|
-
if (ev.metaKey)
|
|
1036
|
-
keyDef += "Meta+";
|
|
1037
|
-
keyDef += ev.code;
|
|
1038
|
-
return keyDef;
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
var __defProp$2 = Object.defineProperty;
|
|
1043
|
-
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1044
|
-
var __publicField$2 = (obj, key, value) => {
|
|
1045
|
-
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1046
|
-
return value;
|
|
1047
|
-
};
|
|
1048
|
-
const debug = Debug("flow:map-plugin-manager");
|
|
1049
|
-
class PluginManager {
|
|
1050
|
-
constructor(map) {
|
|
1051
|
-
__publicField$2(this, "_map");
|
|
1052
|
-
__publicField$2(this, "_keyboardShortcutManager", new KeyboardShortcutManager());
|
|
1053
|
-
__publicField$2(this, "_plugins", /* @__PURE__ */ new Map());
|
|
1054
|
-
__publicField$2(this, "_initialized", false);
|
|
1055
|
-
__publicField$2(this, "_exclusivePlugins", /* @__PURE__ */ new Set());
|
|
1056
|
-
this._map = map;
|
|
1057
|
-
this.map.initialized.then(() => {
|
|
1058
|
-
this._initialized = true;
|
|
1059
|
-
for (const plugin of this._plugins.values()) {
|
|
1060
|
-
if (plugin.initialize) {
|
|
1061
|
-
plugin.initialize();
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
});
|
|
1065
|
-
}
|
|
1066
|
-
get map() {
|
|
1067
|
-
return this._map;
|
|
1068
|
-
}
|
|
1069
|
-
usePlugin(plugin, options) {
|
|
1070
|
-
if (this._plugins.has(plugin)) {
|
|
1071
|
-
const oldInstance = this._plugins.get(plugin);
|
|
1072
|
-
if (oldInstance.destroy) {
|
|
1073
|
-
oldInstance.destroy();
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
const pluginInstance = new plugin(this, options);
|
|
1077
|
-
this._plugins.set(plugin, pluginInstance);
|
|
1078
|
-
debug(`FlowMap<${this.map.id}>: Using plugin '${pluginInstance.name}'`);
|
|
1079
|
-
if (this._initialized && pluginInstance.initialize)
|
|
1080
|
-
pluginInstance.initialize();
|
|
1081
|
-
return pluginInstance;
|
|
1082
|
-
}
|
|
1083
|
-
getPlugin(pluginOrName) {
|
|
1084
|
-
let name;
|
|
1085
|
-
let pluginInstance;
|
|
1086
|
-
if (isString(pluginOrName)) {
|
|
1087
|
-
pluginInstance = Array.from(this._plugins.values()).find((p) => p.name === pluginOrName);
|
|
1088
|
-
name = pluginOrName;
|
|
1089
|
-
} else {
|
|
1090
|
-
pluginInstance = this._plugins.get(pluginOrName);
|
|
1091
|
-
name = pluginOrName.name;
|
|
1092
|
-
}
|
|
1093
|
-
if (!pluginInstance) {
|
|
1094
|
-
throw new FlowError(`<${name}>: plugin not registered`);
|
|
1095
|
-
}
|
|
1096
|
-
return pluginInstance;
|
|
1097
|
-
}
|
|
1098
|
-
removePlugin(pluginOrName) {
|
|
1099
|
-
let pluginConstructor;
|
|
1100
|
-
let pluginInstance;
|
|
1101
|
-
if (isString(pluginOrName)) {
|
|
1102
|
-
const pair = Array.from(this._plugins.entries()).find(([_, p]) => p.name === pluginOrName);
|
|
1103
|
-
pluginConstructor = pair && pair[0];
|
|
1104
|
-
pluginInstance = pair && pair[1];
|
|
1105
|
-
} else {
|
|
1106
|
-
pluginConstructor = pluginOrName;
|
|
1107
|
-
pluginInstance = this._plugins.get(pluginOrName);
|
|
1108
|
-
}
|
|
1109
|
-
if (pluginInstance && pluginInstance.destroy) {
|
|
1110
|
-
pluginInstance.destroy();
|
|
1111
|
-
}
|
|
1112
|
-
if (pluginConstructor)
|
|
1113
|
-
this._plugins.delete(pluginConstructor);
|
|
1114
|
-
return this;
|
|
1115
|
-
}
|
|
1116
|
-
removeAllPlugins() {
|
|
1117
|
-
this._plugins.forEach((plugin) => {
|
|
1118
|
-
if (plugin.destroy)
|
|
1119
|
-
plugin.destroy();
|
|
1120
|
-
});
|
|
1121
|
-
this._plugins.clear();
|
|
1122
|
-
return this;
|
|
1123
|
-
}
|
|
1124
|
-
setExclusivePlugin(plugin) {
|
|
1125
|
-
this._exclusivePlugins.add(plugin);
|
|
1126
|
-
this.forwardSetExclusivePlugin();
|
|
1127
|
-
return this;
|
|
1128
|
-
}
|
|
1129
|
-
removeExclusivePlugin(plugin) {
|
|
1130
|
-
this._exclusivePlugins.delete(plugin);
|
|
1131
|
-
this.forwardSetExclusivePlugin();
|
|
1132
|
-
return this;
|
|
1133
|
-
}
|
|
1134
|
-
addKeyboardShortcuts(keyboardShortcuts, priority = 0) {
|
|
1135
|
-
return this._keyboardShortcutManager.addListener(keyboardShortcuts, priority);
|
|
1136
|
-
}
|
|
1137
|
-
forwardEvent(eventName, ...args) {
|
|
1138
|
-
const handlerName = `handle${capitalize(eventName)}`;
|
|
1139
|
-
this._plugins.forEach((plugin) => {
|
|
1140
|
-
if (this._exclusivePlugins.size && !this._exclusivePlugins.has(plugin))
|
|
1141
|
-
return;
|
|
1142
|
-
const handler = plugin[handlerName];
|
|
1143
|
-
if (handler) {
|
|
1144
|
-
handler.apply(plugin, args);
|
|
1145
|
-
}
|
|
1146
|
-
});
|
|
1147
|
-
}
|
|
1148
|
-
forwardStyleChangeEvent(event) {
|
|
1149
|
-
this._plugins.forEach((plugin) => {
|
|
1150
|
-
if (this._exclusivePlugins.size && !this._exclusivePlugins.has(plugin))
|
|
1151
|
-
return;
|
|
1152
|
-
if (plugin.handleBeforeStyleChanged) {
|
|
1153
|
-
const result = plugin.handleBeforeStyleChanged(event);
|
|
1154
|
-
if (result) {
|
|
1155
|
-
event.newStyle = result;
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
});
|
|
1159
|
-
return event.newStyle;
|
|
1160
|
-
}
|
|
1161
|
-
forwardSetExclusivePlugin() {
|
|
1162
|
-
this._plugins.forEach((plugin) => {
|
|
1163
|
-
if (plugin.handleSetExclusivePlugin) {
|
|
1164
|
-
plugin.handleSetExclusivePlugin(Array.from(this._exclusivePlugins));
|
|
1165
|
-
}
|
|
1166
|
-
});
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
var __defProp$1 = Object.defineProperty;
|
|
1171
|
-
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1172
|
-
var __publicField$1 = (obj, key, value) => {
|
|
1173
|
-
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1174
|
-
return value;
|
|
1175
|
-
};
|
|
1176
|
-
class MapEvent {
|
|
1177
|
-
constructor(type, map, originalEvent) {
|
|
1178
|
-
__publicField$1(this, "type");
|
|
1179
|
-
__publicField$1(this, "map");
|
|
1180
|
-
__publicField$1(this, "originalEvent");
|
|
1181
|
-
this.type = type;
|
|
1182
|
-
this.map = map;
|
|
1183
|
-
this.originalEvent = originalEvent;
|
|
1184
|
-
}
|
|
1185
|
-
static fromMaplibreEvent(type, map, maplibreEvent) {
|
|
1186
|
-
return new MapEvent(type, map, maplibreEvent.originalEvent);
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
class MapMouseEvent extends MapEvent {
|
|
1190
|
-
constructor(type, map, point, lngLat, features, originalEvent) {
|
|
1191
|
-
super(type, map, originalEvent);
|
|
1192
|
-
/**
|
|
1193
|
-
* The pixel coordinates of the mouse cursor, relative to the map and measured from the top left corner.
|
|
1194
|
-
*/
|
|
1195
|
-
__publicField$1(this, "point");
|
|
1196
|
-
/**
|
|
1197
|
-
* The geographic location on the map of the mouse cursor.
|
|
1198
|
-
*/
|
|
1199
|
-
__publicField$1(this, "lngLat");
|
|
1200
|
-
__publicField$1(this, "features");
|
|
1201
|
-
this.point = point;
|
|
1202
|
-
this.lngLat = lngLat;
|
|
1203
|
-
this.features = features;
|
|
1204
|
-
}
|
|
1205
|
-
static fromMaplibreMouseEvent(type, maplibreMouseEvent, map, features) {
|
|
1206
|
-
return new MapMouseEvent(
|
|
1207
|
-
type,
|
|
1208
|
-
map,
|
|
1209
|
-
[maplibreMouseEvent.point.x, maplibreMouseEvent.point.y],
|
|
1210
|
-
[maplibreMouseEvent.lngLat.lng, maplibreMouseEvent.lngLat.lat],
|
|
1211
|
-
features,
|
|
1212
|
-
maplibreMouseEvent.originalEvent
|
|
1213
|
-
);
|
|
1214
|
-
}
|
|
1215
|
-
}
|
|
1216
|
-
class MapSourceEvent extends MapEvent {
|
|
1217
|
-
constructor(type, map, source) {
|
|
1218
|
-
super(type, map);
|
|
1219
|
-
__publicField$1(this, "source");
|
|
1220
|
-
this.source = source;
|
|
1221
|
-
}
|
|
1222
|
-
}
|
|
1223
|
-
class MapLoadingEvent extends MapEvent {
|
|
1224
|
-
constructor(map, loading) {
|
|
1225
|
-
super("loading", map);
|
|
1226
|
-
__publicField$1(this, "loading");
|
|
1227
|
-
this.loading = loading;
|
|
1228
|
-
}
|
|
1229
|
-
}
|
|
1230
|
-
class MapStyleChangeEvent extends MapEvent {
|
|
1231
|
-
constructor(type, map, oldStyle, newStyle) {
|
|
1232
|
-
super(type, map);
|
|
1233
|
-
__publicField$1(this, "oldStyle");
|
|
1234
|
-
__publicField$1(this, "newStyle");
|
|
1235
|
-
this.oldStyle = oldStyle;
|
|
1236
|
-
this.newStyle = newStyle;
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
|
-
var __defProp = Object.defineProperty;
|
|
1241
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1242
|
-
var __publicField = (obj, key, value) => {
|
|
1243
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1244
|
-
return value;
|
|
1245
|
-
};
|
|
1246
|
-
Debug("flow:map-feature-stream");
|
|
1247
|
-
class MapFeatureStream {
|
|
1248
|
-
constructor(options) {
|
|
1249
|
-
__publicField(this, "_boundHandleLoading");
|
|
1250
|
-
__publicField(this, "_boundHandleSourceFeatureState");
|
|
1251
|
-
__publicField(this, "_options");
|
|
1252
|
-
__publicField(this, "_sourceLoadCount", 0);
|
|
1253
|
-
__publicField(this, "_sourceLoaded", true);
|
|
1254
|
-
var _a;
|
|
1255
|
-
this._options = {
|
|
1256
|
-
fireImmediately: true,
|
|
1257
|
-
...options
|
|
1258
|
-
};
|
|
1259
|
-
const sourceType = options.map.getSource(options.source).type;
|
|
1260
|
-
if (sourceType === "vector")
|
|
1261
|
-
(_a = this._options).sourceLayer ?? (_a.sourceLayer = "geometry");
|
|
1262
|
-
makeObservable(this, {
|
|
1263
|
-
_options: observable,
|
|
1264
|
-
_sourceLoadCount: observable,
|
|
1265
|
-
featureData: computed.struct
|
|
1266
|
-
});
|
|
1267
|
-
this._boundHandleLoading = this.handleLoading.bind(this);
|
|
1268
|
-
this._boundHandleSourceFeatureState = this.handleSourceFeatureState.bind(this);
|
|
1269
|
-
onBecomeObserved(this, "featureData", this.resume.bind(this));
|
|
1270
|
-
onBecomeUnobserved(this, "featureData", this.suspend.bind(this));
|
|
1271
|
-
}
|
|
1272
|
-
// Computed
|
|
1273
|
-
get featureData() {
|
|
1274
|
-
this._sourceLoadCount;
|
|
1275
|
-
const featureData = this.queryFeatureData(this._options.featureIds);
|
|
1276
|
-
return featureData;
|
|
1277
|
-
}
|
|
1278
|
-
get featureIds() {
|
|
1279
|
-
return this._options.featureIds;
|
|
1280
|
-
}
|
|
1281
|
-
set featureIds(featureIds) {
|
|
1282
|
-
runInAction(() => {
|
|
1283
|
-
this._options.featureIds = featureIds;
|
|
1284
|
-
});
|
|
1285
|
-
}
|
|
1286
|
-
subscribe(handler) {
|
|
1287
|
-
const mobxSubscription = toStream(() => this.featureData, this._options.fireImmediately).subscribe(handler);
|
|
1288
|
-
return {
|
|
1289
|
-
unsubscribe: () => {
|
|
1290
|
-
mobxSubscription.unsubscribe();
|
|
1291
|
-
}
|
|
1292
|
-
};
|
|
1293
|
-
}
|
|
1294
|
-
featureFromMaplibreFeature(feature) {
|
|
1295
|
-
return {
|
|
1296
|
-
id: feature.id,
|
|
1297
|
-
geometry: feature.geometry,
|
|
1298
|
-
source: this._options.source,
|
|
1299
|
-
sourceLayer: this._options.sourceLayer,
|
|
1300
|
-
properties: feature.properties,
|
|
1301
|
-
state: this._options.map.maplibreMap.getFeatureState({
|
|
1302
|
-
id: feature.id,
|
|
1303
|
-
source: this._options.source,
|
|
1304
|
-
sourceLayer: this._options.sourceLayer
|
|
1305
|
-
})
|
|
1306
|
-
};
|
|
1307
|
-
}
|
|
1308
|
-
handleLoading(event) {
|
|
1309
|
-
let loaded = false;
|
|
1310
|
-
if (event.type === "sourcedata" && event.sourceId === this._options.source) {
|
|
1311
|
-
loaded = event.isSourceLoaded;
|
|
1312
|
-
} else if (event.type === "idle") {
|
|
1313
|
-
loaded = true;
|
|
1314
|
-
}
|
|
1315
|
-
if (this._sourceLoaded !== loaded) {
|
|
1316
|
-
this._sourceLoaded = loaded;
|
|
1317
|
-
if (loaded) {
|
|
1318
|
-
runInAction(() => {
|
|
1319
|
-
this._sourceLoadCount++;
|
|
1320
|
-
});
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
}
|
|
1324
|
-
handleSourceFeatureState(event) {
|
|
1325
|
-
if (event.type === "sourceFeatureState" && event.source === this._options.source) {
|
|
1326
|
-
runInAction(() => {
|
|
1327
|
-
this._sourceLoadCount++;
|
|
1328
|
-
});
|
|
1329
|
-
}
|
|
1330
|
-
}
|
|
1331
|
-
queryFeatureData(featureIDs) {
|
|
1332
|
-
if (featureIDs.length === 0) {
|
|
1333
|
-
return {};
|
|
1334
|
-
}
|
|
1335
|
-
const featureIdProp = this._options.map.getSource(this._options.source).featureId;
|
|
1336
|
-
let features = this._options.map.maplibreMap.querySourceFeatures(this._options.source, {
|
|
1337
|
-
sourceLayer: this._options.sourceLayer,
|
|
1338
|
-
filter: ["in", ["get", featureIdProp], ["literal", featureIDs]]
|
|
1339
|
-
});
|
|
1340
|
-
const ids = /* @__PURE__ */ new Set();
|
|
1341
|
-
features = features.filter((feature) => ids.has(feature.id) ? false : ids.add(feature.id) && true);
|
|
1342
|
-
const featureData = features.reduce((accum, f) => {
|
|
1343
|
-
accum[f.id] = this.featureFromMaplibreFeature(f);
|
|
1344
|
-
return accum;
|
|
1345
|
-
}, {});
|
|
1346
|
-
return featureData;
|
|
1347
|
-
}
|
|
1348
|
-
resume() {
|
|
1349
|
-
this._options.map.maplibreMap.on("sourcedata", this._boundHandleLoading);
|
|
1350
|
-
this._options.map.maplibreMap.on("idle", this._boundHandleLoading);
|
|
1351
|
-
this._options.map.on("sourceFeatureState", this._boundHandleSourceFeatureState);
|
|
1352
|
-
}
|
|
1353
|
-
suspend() {
|
|
1354
|
-
this._options.map.maplibreMap.off("sourcedata", this._boundHandleLoading);
|
|
1355
|
-
this._options.map.maplibreMap.off("idle", this._boundHandleLoading);
|
|
1356
|
-
this._options.map.off("sourceFeatureState", this._boundHandleSourceFeatureState);
|
|
1357
|
-
}
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
export { FlowError as F, MapEvent as M, PluginManager as P, ReactiveExpression as R, assert as a, MapFeatureStream as b, FlowMapError as c, MapDataSource as d, MapLayer as e, MapStyleChangeEvent as f, MapSourceEvent as g, MapLoadingEvent as h, MapMouseEvent as i, die as j };
|