@jupytergis/base 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commands/BaseCommandIDs.d.ts +1 -1
- package/lib/commands/BaseCommandIDs.js +1 -1
- package/lib/commands/index.js +28 -34
- package/lib/constants.js +1 -0
- package/lib/dialogs/symbology/classificationModes.js +12 -16
- package/lib/dialogs/symbology/colorRampUtils.d.ts +47 -3
- package/lib/dialogs/symbology/colorRampUtils.js +112 -13
- package/lib/dialogs/symbology/components/color_ramp/ColorRampSelector.js +6 -14
- package/lib/dialogs/symbology/components/color_ramp/ColorRampSelectorEntry.d.ts +2 -2
- package/lib/dialogs/symbology/components/color_ramp/ColorRampSelectorEntry.js +3 -11
- package/lib/dialogs/symbology/components/color_ramp/RgbaColorPicker.d.ts +13 -0
- package/lib/dialogs/symbology/components/color_ramp/RgbaColorPicker.js +98 -0
- package/lib/dialogs/symbology/components/color_stops/StopContainer.js +3 -1
- package/lib/dialogs/symbology/components/color_stops/StopRow.d.ts +1 -1
- package/lib/dialogs/symbology/components/color_stops/StopRow.js +12 -7
- package/lib/dialogs/symbology/symbologyDialog.d.ts +2 -1
- package/lib/dialogs/symbology/symbologyUtils.d.ts +2 -2
- package/lib/dialogs/symbology/symbologyUtils.js +58 -40
- package/lib/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.js +14 -2
- package/lib/dialogs/symbology/vector_layer/VectorRendering.js +6 -5
- package/lib/dialogs/symbology/vector_layer/components/ValueSelect.js +3 -1
- package/lib/dialogs/symbology/vector_layer/types/Canonical.js +70 -5
- package/lib/dialogs/symbology/vector_layer/types/Categorized.js +81 -34
- package/lib/dialogs/symbology/vector_layer/types/Graduated.js +155 -43
- package/lib/dialogs/symbology/vector_layer/types/SimpleSymbol.js +31 -16
- package/lib/formbuilder/formselectors.js +4 -1
- package/lib/formbuilder/objectform/components/WmsTileSourceUrlInput.d.ts +3 -0
- package/lib/formbuilder/objectform/components/WmsTileSourceUrlInput.js +84 -0
- package/lib/formbuilder/objectform/source/index.d.ts +1 -0
- package/lib/formbuilder/objectform/source/index.js +1 -0
- package/lib/formbuilder/objectform/source/wmsTileSource.d.ts +4 -0
- package/lib/formbuilder/objectform/source/wmsTileSource.js +78 -0
- package/lib/formbuilder/objectform/useSchemaFormState.d.ts +1 -1
- package/lib/mainview/mainView.d.ts +3 -1
- package/lib/mainview/mainView.js +170 -23
- package/lib/menus.js +4 -0
- package/lib/panelview/components/layers.js +19 -2
- package/lib/panelview/components/legendItem.js +14 -4
- package/lib/panelview/filter-panel/Filter.d.ts +3 -0
- package/lib/panelview/filter-panel/Filter.js +9 -9
- package/lib/panelview/leftpanel.js +0 -7
- package/lib/panelview/story-maps/SpectaPanel.js +2 -2
- package/lib/panelview/story-maps/StoryViewerPanel.d.ts +1 -2
- package/lib/panelview/story-maps/StoryViewerPanel.js +1 -1
- package/lib/panelview/story-maps/components/SpectaDesktopView.d.ts +2 -1
- package/lib/panelview/story-maps/components/SpectaDesktopView.js +4 -4
- package/lib/panelview/story-maps/hooks/useStoryMap.d.ts +1 -0
- package/lib/panelview/story-maps/hooks/useStoryMap.js +3 -0
- package/lib/stacBrowser/components/filter-extension/QueryableComboBox.js +61 -20
- package/lib/stacBrowser/hooks/useStacFilterExtension.d.ts +1 -1
- package/lib/stacBrowser/hooks/useStacFilterExtension.js +195 -111
- package/lib/stacBrowser/hooks/useStacSearch.d.ts +1 -0
- package/lib/stacBrowser/hooks/useStacSearch.js +18 -10
- package/lib/tools.d.ts +1 -1
- package/lib/tools.js +3 -3
- package/lib/types.d.ts +7 -1
- package/package.json +5 -2
- package/style/shared/button.css +2 -5
- package/style/shared/input.css +2 -2
- package/style/shared/tabs.css +2 -2
- package/style/storyPanel.css +7 -0
- package/style/symbologyDialog.css +45 -1
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { UUID } from '@lumino/coreutils';
|
|
1
2
|
import React, { useEffect, useState } from 'react';
|
|
2
3
|
import { VectorClassifications } from "../../classificationModes";
|
|
4
|
+
import { colorToRgba, DEFAULT_COLOR, DEFAULT_STROKE_WIDTH, getColorMapList, isColor, } from "../../colorRampUtils";
|
|
3
5
|
import ColorRampControls from "../../components/color_ramp/ColorRampControls";
|
|
6
|
+
import RgbaColorPicker from "../../components/color_ramp/RgbaColorPicker";
|
|
4
7
|
import StopContainer from "../../components/color_stops/StopContainer";
|
|
5
8
|
import { useOkSignal } from "../../hooks/useOkSignal";
|
|
6
9
|
import { saveSymbology, Utils, VectorUtils, } from "../../symbologyUtils";
|
|
@@ -19,15 +22,23 @@ const Graduated = ({ model, okSignalPromise, layerId, symbologyTab, selectableAt
|
|
|
19
22
|
const [colorStopRows, setColorStopRows] = useState([]);
|
|
20
23
|
const [radiusStopRows, setRadiusStopRows] = useState([]);
|
|
21
24
|
const [colorRampOptions, setColorRampOptions] = useState();
|
|
25
|
+
const [fallbackColor, setFallbackColor] = useState([0, 0, 0, 0]);
|
|
26
|
+
const [strokeFollowsFill, setStrokeFollowsFill] = useState(false);
|
|
27
|
+
const fallbackColorRef = useLatest(fallbackColor);
|
|
28
|
+
const strokeFollowsFillRef = useLatest(strokeFollowsFill);
|
|
22
29
|
const [colorManualStyle, setColorManualStyle] = useState({
|
|
23
|
-
strokeColor:
|
|
24
|
-
strokeWidth:
|
|
30
|
+
strokeColor: DEFAULT_COLOR,
|
|
31
|
+
strokeWidth: String(DEFAULT_STROKE_WIDTH),
|
|
25
32
|
});
|
|
26
33
|
const [radiusManualStyle, setRadiusManualStyle] = useState({
|
|
27
34
|
radius: 5,
|
|
28
35
|
});
|
|
36
|
+
const [vmin, setVmin] = useState('');
|
|
37
|
+
const [vmax, setVmax] = useState('');
|
|
29
38
|
const selectableAttributeRef = useLatest(selectedAttribute);
|
|
30
39
|
const symbologyTabRef = useLatest(symbologyTab);
|
|
40
|
+
const vminRef = useLatest(vmin);
|
|
41
|
+
const vmaxRef = useLatest(vmax);
|
|
31
42
|
const colorStopRowsRef = useLatest(colorStopRows);
|
|
32
43
|
const radiusStopRowsRef = useLatest(radiusStopRows);
|
|
33
44
|
const colorRampOptionsRef = useLatest(colorRampOptions);
|
|
@@ -51,31 +62,54 @@ const Graduated = ({ model, okSignalPromise, layerId, symbologyTab, selectableAt
|
|
|
51
62
|
updateStopRowsBasedOnLayer();
|
|
52
63
|
}, []);
|
|
53
64
|
useEffect(() => {
|
|
65
|
+
var _a, _b, _c, _d;
|
|
54
66
|
if (params.color) {
|
|
55
67
|
const strokeColor = params.color['stroke-color'];
|
|
56
68
|
const circleStrokeColor = params.color['circle-stroke-color'];
|
|
57
|
-
const
|
|
69
|
+
const effectiveStroke = isColor(strokeColor)
|
|
70
|
+
? strokeColor
|
|
71
|
+
: isColor(circleStrokeColor)
|
|
72
|
+
? circleStrokeColor
|
|
73
|
+
: DEFAULT_COLOR;
|
|
58
74
|
setColorManualStyle({
|
|
59
|
-
strokeColor:
|
|
60
|
-
|
|
61
|
-
: isSimpleColor(circleStrokeColor)
|
|
62
|
-
? circleStrokeColor
|
|
63
|
-
: '#3399CC',
|
|
64
|
-
strokeWidth: params.color['stroke-width'] ||
|
|
75
|
+
strokeColor: colorToRgba(effectiveStroke),
|
|
76
|
+
strokeWidth: String(params.color['stroke-width'] ||
|
|
65
77
|
params.color['circle-stroke-width'] ||
|
|
66
|
-
|
|
78
|
+
DEFAULT_STROKE_WIDTH),
|
|
67
79
|
});
|
|
68
80
|
setRadiusManualStyle({
|
|
69
81
|
radius: params.color['circle-radius'] || 5,
|
|
70
82
|
});
|
|
71
83
|
}
|
|
84
|
+
setFallbackColor(colorToRgba((_b = (_a = params.symbologyState) === null || _a === void 0 ? void 0 : _a.fallbackColor) !== null && _b !== void 0 ? _b : [0, 0, 0, 0]));
|
|
85
|
+
setStrokeFollowsFill((_d = (_c = params.symbologyState) === null || _c === void 0 ? void 0 : _c.strokeFollowsFill) !== null && _d !== void 0 ? _d : false);
|
|
72
86
|
}, [layerId]);
|
|
73
87
|
useEffect(() => {
|
|
74
88
|
var _a;
|
|
75
|
-
const
|
|
76
|
-
|
|
89
|
+
const savedValue = (_a = params.symbologyState) === null || _a === void 0 ? void 0 : _a.value;
|
|
90
|
+
const attribute = savedValue && savedValue in selectableAttributesAndValues
|
|
91
|
+
? savedValue
|
|
92
|
+
: Object.keys(selectableAttributesAndValues)[0];
|
|
77
93
|
setSelectedAttribute(attribute);
|
|
78
94
|
}, [selectableAttributesAndValues]);
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
var _a, _b;
|
|
97
|
+
if (!selectedAttribute ||
|
|
98
|
+
!selectableAttributesAndValues[selectedAttribute]) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (((_a = params.symbologyState) === null || _a === void 0 ? void 0 : _a.vmin) !== undefined) {
|
|
102
|
+
setVmin(String(params.symbologyState.vmin));
|
|
103
|
+
setVmax(String((_b = params.symbologyState.vmax) !== null && _b !== void 0 ? _b : ''));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const values = Array.from(selectableAttributesAndValues[selectedAttribute]).filter(Number.isFinite);
|
|
107
|
+
if (values.length === 0) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
setVmin(String(Math.min(...values)));
|
|
111
|
+
setVmax(String(Math.max(...values)));
|
|
112
|
+
}, [selectedAttribute]);
|
|
79
113
|
const updateStopRowsBasedOnLayer = () => {
|
|
80
114
|
if (!layer) {
|
|
81
115
|
return;
|
|
@@ -88,27 +122,42 @@ const Graduated = ({ model, okSignalPromise, layerId, symbologyTab, selectableAt
|
|
|
88
122
|
const newStyle = Object.assign({}, params.color);
|
|
89
123
|
// Apply color symbology
|
|
90
124
|
if (colorStopRowsRef.current.length > 0) {
|
|
91
|
-
const
|
|
125
|
+
const interpolateExpr = [
|
|
92
126
|
'interpolate',
|
|
93
127
|
['linear'],
|
|
94
128
|
['get', selectableAttributeRef.current],
|
|
95
129
|
];
|
|
96
130
|
colorStopRowsRef.current.forEach(stop => {
|
|
97
|
-
|
|
98
|
-
|
|
131
|
+
interpolateExpr.push(stop.stop);
|
|
132
|
+
interpolateExpr.push(stop.output);
|
|
99
133
|
});
|
|
134
|
+
// Wrap in case so features missing the attribute use the fallback color
|
|
135
|
+
// instead of causing OL to throw at render time.
|
|
136
|
+
const colorExpr = [
|
|
137
|
+
'case',
|
|
138
|
+
['has', selectableAttributeRef.current],
|
|
139
|
+
interpolateExpr,
|
|
140
|
+
fallbackColorRef.current,
|
|
141
|
+
];
|
|
100
142
|
newStyle['fill-color'] = colorExpr;
|
|
101
143
|
newStyle['circle-fill-color'] = colorExpr;
|
|
102
|
-
|
|
103
|
-
|
|
144
|
+
if (strokeFollowsFillRef.current) {
|
|
145
|
+
newStyle['stroke-color'] = colorExpr;
|
|
146
|
+
newStyle['circle-stroke-color'] = colorExpr;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
newStyle['stroke-color'] = colorManualStyleRef.current.strokeColor;
|
|
150
|
+
newStyle['circle-stroke-color'] =
|
|
151
|
+
colorManualStyleRef.current.strokeColor;
|
|
152
|
+
}
|
|
104
153
|
}
|
|
105
154
|
else {
|
|
106
155
|
// use manual style
|
|
156
|
+
newStyle['stroke-color'] = colorManualStyleRef.current.strokeColor;
|
|
157
|
+
newStyle['circle-stroke-color'] = colorManualStyleRef.current.strokeColor;
|
|
107
158
|
}
|
|
108
|
-
newStyle['stroke-
|
|
109
|
-
newStyle['circle-stroke-
|
|
110
|
-
newStyle['stroke-width'] = colorManualStyleRef.current.strokeWidth;
|
|
111
|
-
newStyle['circle-stroke-width'] = colorManualStyleRef.current.strokeWidth;
|
|
159
|
+
newStyle['stroke-width'] = Math.max(0, parseFloat(colorManualStyleRef.current.strokeWidth));
|
|
160
|
+
newStyle['circle-stroke-width'] = Math.max(0, parseFloat(colorManualStyleRef.current.strokeWidth));
|
|
112
161
|
// Apply radius symbology
|
|
113
162
|
if (radiusStopRowsRef.current.length > 0) {
|
|
114
163
|
const radiusExpr = [
|
|
@@ -125,15 +174,9 @@ const Graduated = ({ model, okSignalPromise, layerId, symbologyTab, selectableAt
|
|
|
125
174
|
else {
|
|
126
175
|
newStyle['circle-radius'] = radiusManualStyleRef.current.radius;
|
|
127
176
|
}
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
method: symbologyTabRef.current,
|
|
132
|
-
colorRamp: (_a = colorRampOptionsRef.current) === null || _a === void 0 ? void 0 : _a.selectedRamp,
|
|
133
|
-
nClasses: (_b = colorRampOptionsRef.current) === null || _b === void 0 ? void 0 : _b.numberOfShades,
|
|
134
|
-
mode: (_c = colorRampOptionsRef.current) === null || _c === void 0 ? void 0 : _c.selectedMode,
|
|
135
|
-
reverseRamp: (_d = colorRampOptionsRef.current) === null || _d === void 0 ? void 0 : _d.reverseRamp,
|
|
136
|
-
};
|
|
177
|
+
const parsedVmin = parseFloat(vminRef.current);
|
|
178
|
+
const parsedVmax = parseFloat(vmaxRef.current);
|
|
179
|
+
const symbologyState = Object.assign(Object.assign({ renderType: 'Graduated', value: selectableAttributeRef.current, method: symbologyTabRef.current, colorRamp: (_a = colorRampOptionsRef.current) === null || _a === void 0 ? void 0 : _a.selectedRamp, nClasses: (_b = colorRampOptionsRef.current) === null || _b === void 0 ? void 0 : _b.numberOfShades, mode: (_c = colorRampOptionsRef.current) === null || _c === void 0 ? void 0 : _c.selectedMode, reverseRamp: (_d = colorRampOptionsRef.current) === null || _d === void 0 ? void 0 : _d.reverseRamp, fallbackColor: fallbackColorRef.current, strokeFollowsFill: strokeFollowsFillRef.current }, (Number.isFinite(parsedVmin) && { vmin: parsedVmin })), (Number.isFinite(parsedVmax) && { vmax: parsedVmax }));
|
|
137
180
|
saveSymbology({
|
|
138
181
|
model,
|
|
139
182
|
layerId,
|
|
@@ -159,30 +202,73 @@ const Graduated = ({ model, okSignalPromise, layerId, symbologyTab, selectableAt
|
|
|
159
202
|
reverseRamp,
|
|
160
203
|
});
|
|
161
204
|
let stops;
|
|
162
|
-
|
|
205
|
+
if (!selectableAttributesAndValues[selectedAttribute]) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const allValues = Array.from(selectableAttributesAndValues[selectedAttribute]);
|
|
209
|
+
const parsed = (s) => {
|
|
210
|
+
const n = parseFloat(s);
|
|
211
|
+
return Number.isFinite(n) ? n : undefined;
|
|
212
|
+
};
|
|
213
|
+
const parsedVmin = parsed(vmin);
|
|
214
|
+
const parsedVmax = parsed(vmax);
|
|
215
|
+
const values = allValues.filter(v => {
|
|
216
|
+
if (!Number.isFinite(v)) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
if (parsedVmin !== undefined && v < parsedVmin) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
if (parsedVmax !== undefined && v > parsedVmax) {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
return true;
|
|
226
|
+
});
|
|
227
|
+
const dataMin = Math.min(...values);
|
|
228
|
+
const dataMax = Math.max(...values);
|
|
229
|
+
const rangeMin = parsedVmin !== null && parsedVmin !== void 0 ? parsedVmin : dataMin;
|
|
230
|
+
const rangeMax = parsedVmax !== null && parsedVmax !== void 0 ? parsedVmax : dataMax;
|
|
231
|
+
const rangeValues = [rangeMin, rangeMax];
|
|
163
232
|
switch (selectedMode) {
|
|
164
233
|
case 'quantile':
|
|
165
234
|
stops = VectorClassifications.calculateQuantileBreaks(values, numberOfShades);
|
|
166
235
|
break;
|
|
167
236
|
case 'equal interval':
|
|
168
|
-
stops = VectorClassifications.calculateEqualIntervalBreaks(
|
|
237
|
+
stops = VectorClassifications.calculateEqualIntervalBreaks(rangeValues, numberOfShades);
|
|
169
238
|
break;
|
|
170
239
|
case 'jenks':
|
|
171
240
|
stops = VectorClassifications.calculateJenksBreaks(values, numberOfShades);
|
|
172
241
|
break;
|
|
173
242
|
case 'pretty':
|
|
174
|
-
stops = VectorClassifications.calculatePrettyBreaks(
|
|
243
|
+
stops = VectorClassifications.calculatePrettyBreaks(rangeValues, numberOfShades);
|
|
175
244
|
break;
|
|
176
245
|
case 'logarithmic':
|
|
177
|
-
stops = VectorClassifications.calculateLogarithmicBreaks(
|
|
246
|
+
stops = VectorClassifications.calculateLogarithmicBreaks(rangeValues, numberOfShades);
|
|
178
247
|
break;
|
|
179
248
|
default:
|
|
180
249
|
console.warn('No mode selected');
|
|
181
250
|
return;
|
|
182
251
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
252
|
+
// Pin outer stops to the user-specified range for all modes.
|
|
253
|
+
// Range-based modes (equal interval, pretty, logarithmic) already receive
|
|
254
|
+
// rangeValues so their outer stops are correct; this clamp ensures
|
|
255
|
+
// data-driven modes (quantile, jenks) also honour vmin/vmax at the edges,
|
|
256
|
+
// which is useful e.g. for excluding outliers while keeping the ramp
|
|
257
|
+
// anchored to the chosen range.
|
|
258
|
+
if (stops.length > 0) {
|
|
259
|
+
stops[0] = rangeMin;
|
|
260
|
+
stops[stops.length - 1] = rangeMax;
|
|
261
|
+
}
|
|
262
|
+
const colorRamp = getColorMapList().find(c => c.name === selectedRamp);
|
|
263
|
+
const getStopOutputPairs = () => {
|
|
264
|
+
if (symbologyTab === 'radius') {
|
|
265
|
+
return stops.map(v => ({ id: UUID.uuid4(), stop: v, output: v }));
|
|
266
|
+
}
|
|
267
|
+
return colorRamp
|
|
268
|
+
? Utils.getValueColorPairs(stops, colorRamp, numberOfShades, reverseRamp)
|
|
269
|
+
: [];
|
|
270
|
+
};
|
|
271
|
+
const stopOutputPairs = getStopOutputPairs();
|
|
186
272
|
if (symbologyTab === 'radius') {
|
|
187
273
|
setRadiusStopRows(stopOutputPairs);
|
|
188
274
|
}
|
|
@@ -225,20 +311,46 @@ const Graduated = ({ model, okSignalPromise, layerId, symbologyTab, selectableAt
|
|
|
225
311
|
"symbology."),
|
|
226
312
|
React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
227
313
|
React.createElement("label", null, "Stroke Color:"),
|
|
228
|
-
React.createElement("
|
|
229
|
-
|
|
230
|
-
|
|
314
|
+
React.createElement("div", { style: {
|
|
315
|
+
display: 'flex',
|
|
316
|
+
alignItems: 'center',
|
|
317
|
+
gap: 8,
|
|
318
|
+
flex: '1 0 50%',
|
|
319
|
+
maxWidth: '50%',
|
|
320
|
+
} },
|
|
321
|
+
React.createElement("div", { style: {
|
|
322
|
+
opacity: strokeFollowsFill ? 0.3 : 1,
|
|
323
|
+
pointerEvents: strokeFollowsFill ? 'none' : 'auto',
|
|
324
|
+
} },
|
|
325
|
+
React.createElement(RgbaColorPicker, { color: colorManualStyle.strokeColor, onChange: color => setColorManualStyle(prev => (Object.assign(Object.assign({}, prev), { strokeColor: color }))) })),
|
|
326
|
+
React.createElement("label", { style: {
|
|
327
|
+
display: 'flex',
|
|
328
|
+
alignItems: 'center',
|
|
329
|
+
gap: 4,
|
|
330
|
+
whiteSpace: 'nowrap',
|
|
331
|
+
} },
|
|
332
|
+
React.createElement("input", { type: "checkbox", checked: strokeFollowsFill, onChange: e => setStrokeFollowsFill(e.target.checked) }),
|
|
333
|
+
"match fill"))),
|
|
231
334
|
React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
232
335
|
React.createElement("label", null, "Stroke Width:"),
|
|
233
|
-
React.createElement("input", { type: "
|
|
234
|
-
setColorManualStyle(Object.assign(Object.assign({}, colorManualStyle), { strokeWidth:
|
|
235
|
-
} }))
|
|
336
|
+
React.createElement("input", { type: "text", className: "jp-mod-styled", value: colorManualStyle.strokeWidth, onChange: e => {
|
|
337
|
+
setColorManualStyle(Object.assign(Object.assign({}, colorManualStyle), { strokeWidth: e.target.value }));
|
|
338
|
+
} })),
|
|
339
|
+
React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
340
|
+
React.createElement("label", null, "Fallback Color:"),
|
|
341
|
+
React.createElement(RgbaColorPicker, { color: fallbackColor, onChange: setFallbackColor })))),
|
|
236
342
|
symbologyTab === 'radius' && (React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
237
343
|
React.createElement("label", null, "Circle Radius:"),
|
|
238
344
|
React.createElement("input", { type: "number", className: "jp-mod-styled", value: radiusManualStyle.radius, onChange: e => {
|
|
239
345
|
handleReset('radius');
|
|
240
346
|
setRadiusManualStyle(Object.assign(Object.assign({}, radiusManualStyle), { radius: +e.target.value }));
|
|
241
347
|
} })))),
|
|
348
|
+
React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
349
|
+
React.createElement("label", null, "Min value:"),
|
|
350
|
+
React.createElement("input", { type: "text", className: "jp-mod-styled", placeholder: "auto", value: vmin, onChange: e => setVmin(e.target.value) })),
|
|
351
|
+
React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
352
|
+
React.createElement("label", null, "Max value:"),
|
|
353
|
+
React.createElement("input", { type: "text", className: "jp-mod-styled", placeholder: "auto", value: vmax, onChange: e => setVmax(e.target.value) })),
|
|
242
354
|
React.createElement(ColorRampControls, { layerParams: params, modeOptions: modeOptions, classifyFunc: buildColorInfoFromClassification, showModeRow: true, showRampSelector: symbologyTab === 'color' }),
|
|
243
355
|
React.createElement(StopContainer, { selectedMethod: symbologyTab || 'color', stopRows: symbologyTab === 'color' ? colorStopRows : radiusStopRows, setStopRows: symbologyTab === 'color' ? setColorStopRows : setRadiusStopRows })));
|
|
244
356
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { colorToRgba, DEFAULT_COLOR, } from "../../colorRampUtils";
|
|
3
|
+
import { DEFAULT_STROKE_WIDTH } from "../../colorRampUtils";
|
|
4
|
+
import RgbaColorPicker from "../../components/color_ramp/RgbaColorPicker";
|
|
2
5
|
import { useEffectiveSymbologyParams } from "../../hooks/useEffectiveSymbologyParams";
|
|
3
6
|
import { useOkSignal } from "../../hooks/useOkSignal";
|
|
4
7
|
import { saveSymbology, } from "../../symbologyUtils";
|
|
@@ -10,10 +13,14 @@ const SimpleSymbol = ({ model, okSignalPromise, layerId, symbologyTab, isStorySe
|
|
|
10
13
|
joinStyle: 'round',
|
|
11
14
|
strokeColor: '#3399CC',
|
|
12
15
|
capStyle: 'round',
|
|
13
|
-
strokeWidth:
|
|
16
|
+
strokeWidth: String(DEFAULT_STROKE_WIDTH),
|
|
14
17
|
radius: 5,
|
|
15
18
|
});
|
|
16
19
|
const styleRef = useLatest(style);
|
|
20
|
+
const [fillRgba, setFillRgba] = useState(DEFAULT_COLOR);
|
|
21
|
+
const [strokeRgba, setStrokeRgba] = useState(DEFAULT_COLOR);
|
|
22
|
+
const fillRgbaRef = useLatest(fillRgba);
|
|
23
|
+
const strokeRgbaRef = useLatest(strokeRgba);
|
|
17
24
|
const layer = layerId !== undefined ? model.getLayer(layerId) : null;
|
|
18
25
|
const params = useEffectiveSymbologyParams({
|
|
19
26
|
model,
|
|
@@ -23,7 +30,7 @@ const SimpleSymbol = ({ model, okSignalPromise, layerId, symbologyTab, isStorySe
|
|
|
23
30
|
segmentId,
|
|
24
31
|
});
|
|
25
32
|
useEffect(() => {
|
|
26
|
-
var _a;
|
|
33
|
+
var _a, _b, _c;
|
|
27
34
|
if (!params) {
|
|
28
35
|
return;
|
|
29
36
|
}
|
|
@@ -32,25 +39,33 @@ const SimpleSymbol = ({ model, okSignalPromise, layerId, symbologyTab, isStorySe
|
|
|
32
39
|
if (parsed) {
|
|
33
40
|
setStyle(parsed);
|
|
34
41
|
}
|
|
42
|
+
const fillColor = (_b = params.color['circle-fill-color']) !== null && _b !== void 0 ? _b : params.color['fill-color'];
|
|
43
|
+
const strokeColor = (_c = params.color['circle-stroke-color']) !== null && _c !== void 0 ? _c : params.color['stroke-color'];
|
|
44
|
+
if (fillColor !== undefined) {
|
|
45
|
+
setFillRgba(colorToRgba(fillColor));
|
|
46
|
+
}
|
|
47
|
+
if (strokeColor !== undefined) {
|
|
48
|
+
setStrokeRgba(colorToRgba(strokeColor));
|
|
49
|
+
}
|
|
35
50
|
}
|
|
36
51
|
}, [params]);
|
|
37
52
|
const handleOk = () => {
|
|
38
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j
|
|
53
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
39
54
|
if (!layerId || !(layer === null || layer === void 0 ? void 0 : layer.parameters)) {
|
|
40
55
|
return;
|
|
41
56
|
}
|
|
42
57
|
const styleExpr = {
|
|
43
58
|
'circle-radius': (_a = styleRef.current) === null || _a === void 0 ? void 0 : _a.radius,
|
|
44
|
-
'circle-fill-color':
|
|
45
|
-
'circle-stroke-color':
|
|
46
|
-
'circle-stroke-width': (
|
|
47
|
-
'circle-stroke-line-join': (
|
|
48
|
-
'circle-stroke-line-cap': (
|
|
49
|
-
'fill-color':
|
|
50
|
-
'stroke-color':
|
|
51
|
-
'stroke-width': (
|
|
52
|
-
'stroke-line-join': (
|
|
53
|
-
'stroke-line-cap': (
|
|
59
|
+
'circle-fill-color': fillRgbaRef.current,
|
|
60
|
+
'circle-stroke-color': strokeRgbaRef.current,
|
|
61
|
+
'circle-stroke-width': Math.max(0, parseFloat((_c = (_b = styleRef.current) === null || _b === void 0 ? void 0 : _b.strokeWidth) !== null && _c !== void 0 ? _c : '0')),
|
|
62
|
+
'circle-stroke-line-join': (_d = styleRef.current) === null || _d === void 0 ? void 0 : _d.joinStyle,
|
|
63
|
+
'circle-stroke-line-cap': (_e = styleRef.current) === null || _e === void 0 ? void 0 : _e.capStyle,
|
|
64
|
+
'fill-color': fillRgbaRef.current,
|
|
65
|
+
'stroke-color': strokeRgbaRef.current,
|
|
66
|
+
'stroke-width': Math.max(0, parseFloat((_g = (_f = styleRef.current) === null || _f === void 0 ? void 0 : _f.strokeWidth) !== null && _g !== void 0 ? _g : '0')),
|
|
67
|
+
'stroke-line-join': (_h = styleRef.current) === null || _h === void 0 ? void 0 : _h.joinStyle,
|
|
68
|
+
'stroke-line-cap': (_j = styleRef.current) === null || _j === void 0 ? void 0 : _j.capStyle,
|
|
54
69
|
};
|
|
55
70
|
const symbologyState = {
|
|
56
71
|
renderType: 'Single Symbol',
|
|
@@ -80,13 +95,13 @@ const SimpleSymbol = ({ model, okSignalPromise, layerId, symbologyTab, isStorySe
|
|
|
80
95
|
const renderColorTab = () => (React.createElement(React.Fragment, null,
|
|
81
96
|
React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
82
97
|
React.createElement("label", { htmlFor: 'vector-value-select' }, "Fill Color:"),
|
|
83
|
-
React.createElement(
|
|
98
|
+
React.createElement(RgbaColorPicker, { color: fillRgba, onChange: setFillRgba })),
|
|
84
99
|
React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
85
100
|
React.createElement("label", { htmlFor: 'vector-value-select' }, "Stroke Color:"),
|
|
86
|
-
React.createElement(
|
|
101
|
+
React.createElement(RgbaColorPicker, { color: strokeRgba, onChange: setStrokeRgba })),
|
|
87
102
|
React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
88
103
|
React.createElement("label", { htmlFor: 'vector-value-select' }, "Stroke Width:"),
|
|
89
|
-
React.createElement("input", { type: "
|
|
104
|
+
React.createElement("input", { type: "text", value: style.strokeWidth, className: "jp-mod-styled", onChange: event => setStyle(prevState => (Object.assign(Object.assign({}, prevState), { strokeWidth: event.target.value }))) })),
|
|
90
105
|
React.createElement("div", { className: "jp-gis-symbology-row" },
|
|
91
106
|
React.createElement("label", { htmlFor: 'vector-join-select' }, "Join Style:"),
|
|
92
107
|
React.createElement("div", { className: "jp-select-wrapper" },
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HeatmapLayerPropertiesForm, HillshadeLayerPropertiesForm, StorySegmentLayerPropertiesForm, LayerPropertiesForm, VectorLayerPropertiesForm, WebGlLayerPropertiesForm, } from './objectform/layer';
|
|
2
|
-
import { GeoJSONSourcePropertiesForm, GeoTiffSourcePropertiesForm, PathBasedSourcePropertiesForm, TileSourcePropertiesForm, SourcePropertiesForm, } from './objectform/source';
|
|
2
|
+
import { GeoJSONSourcePropertiesForm, GeoTiffSourcePropertiesForm, PathBasedSourcePropertiesForm, TileSourcePropertiesForm, WmsTileSourceForm, SourcePropertiesForm, } from './objectform/source';
|
|
3
3
|
export function getLayerTypeForm(layerType) {
|
|
4
4
|
let LayerForm = LayerPropertiesForm;
|
|
5
5
|
switch (layerType) {
|
|
@@ -38,6 +38,9 @@ export function getSourceTypeForm(sourceType) {
|
|
|
38
38
|
case 'GeoTiffSource':
|
|
39
39
|
SourceForm = GeoTiffSourcePropertiesForm;
|
|
40
40
|
break;
|
|
41
|
+
case 'WmsTileSource':
|
|
42
|
+
SourceForm = WmsTileSourceForm;
|
|
43
|
+
break;
|
|
41
44
|
case 'RasterSource':
|
|
42
45
|
case 'VectorTileSource':
|
|
43
46
|
SourceForm = TileSourcePropertiesForm;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { WMS_AVAILABLE_LAYERS_CACHE } from "../source";
|
|
3
|
+
import { Button } from "../../../shared/components/Button";
|
|
4
|
+
import { Input } from "../../../shared/components/Input";
|
|
5
|
+
import { GlobalStateDbManager } from "../../../store";
|
|
6
|
+
import { fetchWithProxies } from "../../../tools";
|
|
7
|
+
export function WmsTileSourceUrlInput(props) {
|
|
8
|
+
var _a;
|
|
9
|
+
const { value, formContext, onChange, id, name, onBlur, onFocus, disabled, readonly, } = props;
|
|
10
|
+
const context = formContext;
|
|
11
|
+
const model = context === null || context === void 0 ? void 0 : context.model;
|
|
12
|
+
const layers = (_a = context === null || context === void 0 ? void 0 : context.wmsAvailableLayers) !== null && _a !== void 0 ? _a : [];
|
|
13
|
+
const setWmsAvailableLayers = context === null || context === void 0 ? void 0 : context.setWmsAvailableLayers;
|
|
14
|
+
const stateDb = GlobalStateDbManager.getInstance().getStateDb();
|
|
15
|
+
const text = !value ? '' : String(value);
|
|
16
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
17
|
+
const [error, setError] = useState(undefined);
|
|
18
|
+
const handleChange = (event) => {
|
|
19
|
+
onChange(event.target.value);
|
|
20
|
+
};
|
|
21
|
+
const handleConnect = async () => {
|
|
22
|
+
var _a, _b, _c;
|
|
23
|
+
if (!model || !setWmsAvailableLayers) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
setIsLoading(true);
|
|
27
|
+
setError(undefined);
|
|
28
|
+
const slash = text.endsWith('/') ? '' : '/';
|
|
29
|
+
const url = `${text}${slash}?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities`;
|
|
30
|
+
try {
|
|
31
|
+
if (stateDb) {
|
|
32
|
+
const cacheKey = `${WMS_AVAILABLE_LAYERS_CACHE}:${text}`;
|
|
33
|
+
const cached = (await stateDb.fetch(cacheKey));
|
|
34
|
+
if (cached && cached.length > 0) {
|
|
35
|
+
setWmsAvailableLayers(cached);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const xmlText = await fetchWithProxies(url, model, (response) => response.text());
|
|
40
|
+
const xml = typeof xmlText === 'string' ? xmlText : '';
|
|
41
|
+
const doc = new DOMParser().parseFromString(xml, 'text/xml');
|
|
42
|
+
const hasParseError = Boolean(doc.querySelector('parsererror'));
|
|
43
|
+
const serviceException = doc.querySelector('ServiceExceptionReport');
|
|
44
|
+
if (hasParseError || serviceException) {
|
|
45
|
+
setError((_b = (_a = serviceException === null || serviceException === void 0 ? void 0 : serviceException.textContent) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : 'Failed to parse WMS GetCapabilities XML.');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const rootLayer = doc.querySelector('Capability > Layer');
|
|
49
|
+
const layerEls = Array.from((_c = rootLayer === null || rootLayer === void 0 ? void 0 : rootLayer.querySelectorAll(':scope > Layer')) !== null && _c !== void 0 ? _c : []);
|
|
50
|
+
const parsed = layerEls
|
|
51
|
+
.map(layerEl => {
|
|
52
|
+
var _a, _b, _c, _d, _e, _f;
|
|
53
|
+
const name = (_c = (_b = (_a = layerEl.querySelector('Name')) === null || _a === void 0 ? void 0 : _a.textContent) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : '';
|
|
54
|
+
const title = (_f = (_e = (_d = layerEl.querySelector('Title')) === null || _d === void 0 ? void 0 : _d.textContent) === null || _e === void 0 ? void 0 : _e.trim()) !== null && _f !== void 0 ? _f : name;
|
|
55
|
+
return { name, title };
|
|
56
|
+
})
|
|
57
|
+
.filter(layer => layer.name !== '' || layer.title !== '');
|
|
58
|
+
setWmsAvailableLayers(parsed);
|
|
59
|
+
if (stateDb) {
|
|
60
|
+
const cacheKey = `${WMS_AVAILABLE_LAYERS_CACHE}:${text}`;
|
|
61
|
+
await stateDb.save(cacheKey, parsed);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
setError(e instanceof Error ? e.message : String(e));
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
setIsLoading(false);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
return (React.createElement(React.Fragment, null,
|
|
72
|
+
React.createElement("div", { style: {
|
|
73
|
+
display: 'flex',
|
|
74
|
+
gap: '0.5rem',
|
|
75
|
+
alignItems: 'center',
|
|
76
|
+
margin: '0 7px',
|
|
77
|
+
} },
|
|
78
|
+
React.createElement(Input, { id: id, name: name, type: "text", value: text, onChange: handleChange, onBlur: e => onBlur(id, e.target.value), onFocus: e => onFocus(id, e.target.value), disabled: disabled, readOnly: readonly, placeholder: "Enter WMS URL", style: { flexGrow: 1 } }),
|
|
79
|
+
React.createElement(Button, { variant: "outline", size: "sm", type: "button", onClick: handleConnect, disabled: isLoading }, isLoading ? 'Connecting…' : 'Connect')),
|
|
80
|
+
error && (React.createElement("div", { style: { marginTop: '0.5rem', color: 'var(--jp-error-color1)' } }, error)),
|
|
81
|
+
layers.length > 0 && (React.createElement("div", { style: { marginTop: '0.5rem' } },
|
|
82
|
+
layers.length,
|
|
83
|
+
" layer(s) found. Choose one in the `params.layers` dropdown."))));
|
|
84
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
import type { ISourceFormProps } from "./sourceform";
|
|
3
|
+
export declare const WMS_AVAILABLE_LAYERS_CACHE = "jgis:wmsTileSource:availableLayers";
|
|
4
|
+
export declare function WmsTileSourceForm(props: ISourceFormProps): ReactElement | null;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { SchemaForm } from "../SchemaForm";
|
|
3
|
+
import { WmsTileSourceUrlInput } from "../components/WmsTileSourceUrlInput";
|
|
4
|
+
import { processBaseSchema, removeFormEntry, } from "../schemaUtils";
|
|
5
|
+
import { useSchemaFormState } from "../useSchemaFormState";
|
|
6
|
+
import { GlobalStateDbManager } from "../../../store";
|
|
7
|
+
import { deepCopy } from "../../../tools";
|
|
8
|
+
export const WMS_AVAILABLE_LAYERS_CACHE = 'jgis:wmsTileSource:availableLayers';
|
|
9
|
+
export function WmsTileSourceForm(props) {
|
|
10
|
+
const { schema: schemaProp, sourceData, syncData, model, filePath, formContext, dialogOptions, cancel, formErrorSignal, } = props;
|
|
11
|
+
const { formData, schema, formContextValue, hasSchema, handleChangeBase, handleSubmitBase, } = useSchemaFormState({
|
|
12
|
+
sourceData,
|
|
13
|
+
schemaProp,
|
|
14
|
+
model,
|
|
15
|
+
syncData,
|
|
16
|
+
cancel,
|
|
17
|
+
onAfterChange: dialogOptions
|
|
18
|
+
? (data) => {
|
|
19
|
+
dialogOptions.sourceData = Object.assign({}, data);
|
|
20
|
+
}
|
|
21
|
+
: undefined,
|
|
22
|
+
});
|
|
23
|
+
const [wmsAvailableLayers, setWmsAvailableLayers] = useState([]);
|
|
24
|
+
const stateDb = GlobalStateDbManager.getInstance().getStateDb();
|
|
25
|
+
// Rehydrate available WMS layers from StateDB to avoid having to refetch on remount.
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
const wmsUrl = formData === null || formData === void 0 ? void 0 : formData.url;
|
|
28
|
+
if (!stateDb || !wmsUrl) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const db = stateDb;
|
|
32
|
+
const cacheKey = `${WMS_AVAILABLE_LAYERS_CACHE}:${wmsUrl}`;
|
|
33
|
+
async function loadLayersFromCache() {
|
|
34
|
+
var _a, _b;
|
|
35
|
+
const cached = (await db.fetch(cacheKey));
|
|
36
|
+
if (cached && cached.length > 0) {
|
|
37
|
+
setWmsAvailableLayers(cached);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
setWmsAvailableLayers([]);
|
|
41
|
+
handleChangeBase(Object.assign(Object.assign({}, (formData !== null && formData !== void 0 ? formData : {})), { params: Object.assign(Object.assign({}, ((_b = ((_a = formData === null || formData === void 0 ? void 0 : formData.params) !== null && _a !== void 0 ? _a : {})) !== null && _b !== void 0 ? _b : {})), { layers: undefined }) }));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
void loadLayersFromCache();
|
|
45
|
+
}, [stateDb, formData === null || formData === void 0 ? void 0 : formData.url]);
|
|
46
|
+
const uiSchema = useMemo(() => {
|
|
47
|
+
var _a, _b, _c, _d;
|
|
48
|
+
const builtUiSchema = {};
|
|
49
|
+
const dataCopy = deepCopy(formData);
|
|
50
|
+
processBaseSchema(dataCopy, schema, builtUiSchema, formContext, removeFormEntry);
|
|
51
|
+
const layerNames = wmsAvailableLayers
|
|
52
|
+
.map(layer => layer.name)
|
|
53
|
+
.filter(name => name !== '');
|
|
54
|
+
// Populate schema enum dynamically so RJSF renders a select for params.layers
|
|
55
|
+
const params = ((_b = (_a = schema.properties) === null || _a === void 0 ? void 0 : _a.params) !== null && _b !== void 0 ? _b : {});
|
|
56
|
+
const paramsProperties = ((_c = params.properties) !== null && _c !== void 0 ? _c : {});
|
|
57
|
+
if (paramsProperties.layers) {
|
|
58
|
+
// Keep select options in sync with the cached/available layers list.
|
|
59
|
+
if (layerNames.length > 0) {
|
|
60
|
+
paramsProperties.layers.enum = layerNames;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// Avoid invalid schema (`enum` must be a non-empty array).
|
|
64
|
+
delete paramsProperties.layers.enum;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
builtUiSchema.url = {
|
|
68
|
+
'ui:widget': WmsTileSourceUrlInput,
|
|
69
|
+
};
|
|
70
|
+
builtUiSchema.params = Object.assign(Object.assign({}, builtUiSchema.params), { 'ui:title': false, layers: Object.assign(Object.assign({}, (_d = builtUiSchema.params) === null || _d === void 0 ? void 0 : _d.layers), { 'ui:widget': 'select', 'ui:placeholder': 'Select a layer', 'ui:enumNames': wmsAvailableLayers.map(layer => layer.title) }) });
|
|
71
|
+
return builtUiSchema;
|
|
72
|
+
}, [schema, formData, formContext, wmsAvailableLayers]);
|
|
73
|
+
if (!hasSchema) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
return (React.createElement(SchemaForm, { schema: schema, formData: formData, onChange: handleChangeBase, onSubmit: handleSubmitBase, formContext: Object.assign(Object.assign({}, formContextValue), { wmsAvailableLayers,
|
|
77
|
+
setWmsAvailableLayers }), filePath: filePath, uiSchema: uiSchema, formErrorSignal: formErrorSignal }));
|
|
78
|
+
}
|
|
@@ -29,7 +29,7 @@ export interface IUseSchemaFormStateResult {
|
|
|
29
29
|
setFormData: Dispatch<SetStateAction<IDict>>;
|
|
30
30
|
/** Schema to pass to SchemaForm (deep copy of schemaProp). */
|
|
31
31
|
schema: RJSFSchema;
|
|
32
|
-
/** Form context value
|
|
32
|
+
/** Form context value for SchemaForm (available to custom fields/widgets). */
|
|
33
33
|
formContextValue: {
|
|
34
34
|
model: IJupyterGISModel;
|
|
35
35
|
formData: IDict;
|
|
@@ -42,7 +42,7 @@ export declare class MainView extends React.Component<IMainViewProps, IStates> {
|
|
|
42
42
|
componentDidMount(): Promise<void>;
|
|
43
43
|
componentDidUpdate(prevProps: IMainViewProps, prevState: IStates): void;
|
|
44
44
|
componentWillUnmount(): void;
|
|
45
|
-
generateMap(center: number[], zoom: number): Promise<void>;
|
|
45
|
+
generateMap(center: number[], zoom: number, projection?: string): Promise<void>;
|
|
46
46
|
updateCenter: () => void;
|
|
47
47
|
getViewBbox: (targetProjection?: string) => import("ol/extent").Extent;
|
|
48
48
|
createSelectInteraction: () => void;
|
|
@@ -189,6 +189,7 @@ export declare class MainView extends React.Component<IMainViewProps, IStates> {
|
|
|
189
189
|
private _onZoomToPosition;
|
|
190
190
|
private _moveToPosition;
|
|
191
191
|
private _flyToPosition;
|
|
192
|
+
private _lastPointerCoord;
|
|
192
193
|
private _onPointerMove;
|
|
193
194
|
private _syncPointer;
|
|
194
195
|
private _addMarker;
|
|
@@ -205,6 +206,7 @@ export declare class MainView extends React.Component<IMainViewProps, IStates> {
|
|
|
205
206
|
private _commands;
|
|
206
207
|
private _isPositionInitialized;
|
|
207
208
|
private divRef;
|
|
209
|
+
private mainViewRef;
|
|
208
210
|
private controlsToolbarRef;
|
|
209
211
|
private spectaContainerRef;
|
|
210
212
|
private storyViewerPanelRef;
|