@orioro/react-maplibre-util 0.5.3 → 0.6.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/CHANGELOG.md +11 -0
- package/dist/DynamicImages/index.d.ts +3 -0
- package/dist/DynamicImages/svgImages/iconPathToSvg.d.ts +9 -0
- package/dist/DynamicImages/svgImages/index.d.ts +7 -28
- package/dist/DynamicImages/svgImages/svgToMaplibreImage.d.ts +16 -0
- package/dist/DynamicImages/svgPatterns/index.d.ts +8 -0
- package/dist/LayeredMap/layeredMapOnClickHandler.d.ts +3 -2
- package/dist/SyncedMaps/index.d.ts +2 -0
- package/dist/SyncedMaps/useMapRegistry.d.ts +7 -0
- package/dist/SyncedMaps/useTilesLoading.d.ts +2 -0
- package/dist/index.mjs +300 -34
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type IconPathToSvgOptions = {
|
|
2
|
+
size?: number;
|
|
3
|
+
fill?: string;
|
|
4
|
+
stroke?: string;
|
|
5
|
+
strokeWidth?: string | number;
|
|
6
|
+
viewBox?: string;
|
|
7
|
+
style?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function iconPathToSvg(path: string, { size, fill, stroke, strokeWidth, viewBox, style, }?: IconPathToSvgOptions): string;
|
|
@@ -1,30 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
strokeWidth?: string | number;
|
|
7
|
-
viewBox?: string;
|
|
8
|
-
style?: string;
|
|
9
|
-
};
|
|
10
|
-
export declare function iconPathToSvg(path: string, { size, fill, stroke, strokeWidth, viewBox, style, }?: IconPathToSvgOptions): string;
|
|
11
|
-
/**
|
|
12
|
-
* Renders an SVG string onto a canvas and returns an object compatible with maplibre `addImage`.
|
|
13
|
-
*
|
|
14
|
-
* @param svgString - The SVG markup as a string
|
|
15
|
-
* @param pixelRatio - (Optional) device pixel ratio, defaults to window.devicePixelRatio
|
|
16
|
-
* @returns Promise resolving to { width, height, data, pixelRatio }
|
|
17
|
-
*/
|
|
18
|
-
export declare function svgToMaplibreImage(svgString: string, pixelRatio?: number): Promise<[
|
|
19
|
-
{
|
|
20
|
-
width: number;
|
|
21
|
-
height: number;
|
|
22
|
-
data: Uint8ClampedArray;
|
|
23
|
-
},
|
|
24
|
-
Partial<StyleImageMetadata>
|
|
25
|
-
]>;
|
|
26
|
-
export declare function svgIconId(iconId: string, options?: IconPathToSvgOptions): string;
|
|
27
|
-
type SvgIconGeneratorReturn<T extends Record<string, string>> = {
|
|
1
|
+
import { type IconPathToSvgOptions } from './iconPathToSvg';
|
|
2
|
+
import type { StyleImageMetadata } from 'maplibre-gl';
|
|
3
|
+
export declare function svgImageId(imageId: string, options?: IconPathToSvgOptions): string;
|
|
4
|
+
type SvgIconSpecsById = Record<string, string | ((options: Record<string, any>) => string)>;
|
|
5
|
+
type SvgIconGeneratorReturn<T extends SvgIconSpecsById> = {
|
|
28
6
|
(imageId: string): Promise<[
|
|
29
7
|
{
|
|
30
8
|
width: number;
|
|
@@ -36,5 +14,6 @@ type SvgIconGeneratorReturn<T extends Record<string, string>> = {
|
|
|
36
14
|
} & {
|
|
37
15
|
[K in keyof T]: (options?: IconPathToSvgOptions) => string;
|
|
38
16
|
};
|
|
39
|
-
export declare function
|
|
17
|
+
export declare function svgImageGenerator<T extends SvgIconSpecsById>(svgImageSpecsById: T): SvgIconGeneratorReturn<T>;
|
|
18
|
+
export declare function svgIconGenerator(...args: any[]): SvgIconGeneratorReturn<any>;
|
|
40
19
|
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { StyleImageMetadata } from 'maplibre-gl';
|
|
2
|
+
/**
|
|
3
|
+
* Renders an SVG string onto a canvas and returns an object compatible with maplibre `addImage`.
|
|
4
|
+
*
|
|
5
|
+
* @param svgString - The SVG markup as a string
|
|
6
|
+
* @param pixelRatio - (Optional) device pixel ratio, defaults to window.devicePixelRatio
|
|
7
|
+
* @returns Promise resolving to { width, height, data, pixelRatio }
|
|
8
|
+
*/
|
|
9
|
+
export declare function svgToMaplibreImage(svgString: string, inputPixelRatio?: number): Promise<[
|
|
10
|
+
{
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
data: Uint8ClampedArray;
|
|
14
|
+
},
|
|
15
|
+
Partial<StyleImageMetadata>
|
|
16
|
+
]>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const squares_1: (data: Record<string, any>) => string;
|
|
2
|
+
export declare const triangles_1: (data: Record<string, any>) => string;
|
|
3
|
+
export declare const diamonds_1: (data: Record<string, any>) => string;
|
|
4
|
+
export declare const cross_1: (data: Record<string, any>) => string;
|
|
5
|
+
export declare const mosaic_1: (data: Record<string, any>) => string;
|
|
6
|
+
export declare const waves_1: (data: Record<string, any>) => string;
|
|
7
|
+
export declare const circles_1: (data: Record<string, any>) => string;
|
|
8
|
+
export declare const lines_1: (data: Record<string, any>) => string;
|
|
@@ -3,7 +3,7 @@ import { Merge } from 'type-fest';
|
|
|
3
3
|
type ClickableFeature = Merge<MapGeoJSONFeature, {
|
|
4
4
|
layer: {
|
|
5
5
|
id: string;
|
|
6
|
-
onClick: (feature: MapGeoJSONFeature, event: AugmentedMouseEvent) => any;
|
|
6
|
+
onClick: (feature: MapGeoJSONFeature, event: AugmentedMouseEvent, context: Record<string, any>) => any;
|
|
7
7
|
};
|
|
8
8
|
}>;
|
|
9
9
|
type AugmentedMouseEvent = Merge<MapMouseEvent, {
|
|
@@ -11,6 +11,7 @@ type AugmentedMouseEvent = Merge<MapMouseEvent, {
|
|
|
11
11
|
}>;
|
|
12
12
|
type LayeredMapOnClickHandlerProps = {
|
|
13
13
|
resolveTargetFeature?: (features: AugmentedMouseEvent['features'], event: AugmentedMouseEvent) => ClickableFeature | Promise<ClickableFeature>;
|
|
14
|
+
context?: Record<string, any>;
|
|
14
15
|
};
|
|
15
|
-
export declare function layeredMapOnClickHandler({ resolveTargetFeature, }?: LayeredMapOnClickHandlerProps): (e: AugmentedMouseEvent) => Promise<void>;
|
|
16
|
+
export declare function layeredMapOnClickHandler({ resolveTargetFeature, context, }?: LayeredMapOnClickHandlerProps): (e: AugmentedMouseEvent) => Promise<void>;
|
|
16
17
|
export {};
|
package/dist/index.mjs
CHANGED
|
@@ -6,19 +6,27 @@ import { Flex, useRefByKey, useLocalState, DropdownMenu } from '@orioro/react-ui
|
|
|
6
6
|
import styled from 'styled-components';
|
|
7
7
|
import { usePrevious } from 'react-use';
|
|
8
8
|
import { mergeRefs } from 'react-merge-refs';
|
|
9
|
-
import {
|
|
9
|
+
import { mdiCloseCircleOutline, mdiCheck, mdiTerrain, mdiVideo3d } from '@mdi/js';
|
|
10
|
+
import { interpolate, strExpr } from '@orioro/util';
|
|
10
11
|
import { ckmeans } from 'simple-statistics';
|
|
11
12
|
import { schemeYlOrRd } from 'd3-scale-chromatic';
|
|
12
13
|
import { maxIndex, range, variance, sum } from 'd3';
|
|
13
14
|
import { bbox } from '@turf/turf';
|
|
14
15
|
import { createPortal } from 'react-dom';
|
|
15
|
-
import { mdiCheck, mdiTerrain, mdiVideo3d } from '@mdi/js';
|
|
16
16
|
import { Icon } from '@mdi/react';
|
|
17
17
|
import { Tooltip } from '@radix-ui/themes';
|
|
18
18
|
import maplibregl from 'maplibre-gl';
|
|
19
19
|
import mlcontour from 'maplibre-contour';
|
|
20
20
|
import MaplibreInspect from '@maplibre/maplibre-gl-inspect';
|
|
21
21
|
|
|
22
|
+
function _validZIndex(zIndex) {
|
|
23
|
+
return typeof zIndex === 'number' && !Number.isNaN(zIndex);
|
|
24
|
+
}
|
|
25
|
+
// Return 1 makes layerB come first in array order
|
|
26
|
+
// and layerA later, so it will be
|
|
27
|
+
// rendered on top of layerB
|
|
28
|
+
var LAYER_A_ON_TOP_OF_B = 1;
|
|
29
|
+
var LAYER_B_ON_TOP_OF_A = -1;
|
|
22
30
|
function sortLayers(layers, _a) {
|
|
23
31
|
var existingLayers = _a.existingLayers;
|
|
24
32
|
var existingLayersById = existingLayers ? Object.fromEntries(existingLayers.map(function (layer) {
|
|
@@ -31,7 +39,27 @@ function sortLayers(layers, _a) {
|
|
|
31
39
|
// - Later in the list → Rendered on top (higher z-index).
|
|
32
40
|
// - Earlier in the list → Rendered below.
|
|
33
41
|
//
|
|
34
|
-
return layers
|
|
42
|
+
return layers
|
|
43
|
+
//
|
|
44
|
+
// PREVIOUS SORT:
|
|
45
|
+
// .map((layer, index) => ({
|
|
46
|
+
// ...layer,
|
|
47
|
+
// //
|
|
48
|
+
// // Allow for zIndex overriding
|
|
49
|
+
// // In case no zIndex is set, respect the order in which
|
|
50
|
+
// // layers were provided.
|
|
51
|
+
// //
|
|
52
|
+
// // Layers that come after are rendered on top of previous layers
|
|
53
|
+
// //
|
|
54
|
+
// zIndex: typeof layer.zIndex === 'number' ? layer.zIndex : index,
|
|
55
|
+
// }))
|
|
56
|
+
// //
|
|
57
|
+
// // Order layers in ascending zIndex order, so that
|
|
58
|
+
// // layers with higher zIndex are rendered later and on top of
|
|
59
|
+
// // previous ones
|
|
60
|
+
// //
|
|
61
|
+
// .sort((layerA, layerB) => (layerA.zIndex >= layerB.zIndex ? 1 : -1))
|
|
62
|
+
.map(function (layer, index) {
|
|
35
63
|
return __assign(__assign({}, layer), {
|
|
36
64
|
//
|
|
37
65
|
// Allow for zIndex overriding
|
|
@@ -40,7 +68,8 @@ function sortLayers(layers, _a) {
|
|
|
40
68
|
//
|
|
41
69
|
// Layers that come after are rendered on top of previous layers
|
|
42
70
|
//
|
|
43
|
-
|
|
71
|
+
_inputOrderIndex: index,
|
|
72
|
+
zIndex: typeof layer.zIndex === 'number' ? layer.zIndex : null
|
|
44
73
|
});
|
|
45
74
|
})
|
|
46
75
|
//
|
|
@@ -48,9 +77,38 @@ function sortLayers(layers, _a) {
|
|
|
48
77
|
// layers with higher zIndex are rendered later and on top of
|
|
49
78
|
// previous ones
|
|
50
79
|
//
|
|
80
|
+
// Layers without zIndex are always rendered beneath
|
|
81
|
+
// those with zIndex
|
|
82
|
+
//
|
|
83
|
+
// Layers with the same zIndex are compared using _inputOrderIndex
|
|
84
|
+
//
|
|
51
85
|
.sort(function (layerA, layerB) {
|
|
52
|
-
|
|
53
|
-
|
|
86
|
+
var aValid = _validZIndex(layerA.zIndex);
|
|
87
|
+
var bValid = _validZIndex(layerB.zIndex);
|
|
88
|
+
var aZIndex = layerA.zIndex;
|
|
89
|
+
var bZIndex = layerB.zIndex;
|
|
90
|
+
if (aValid && !bValid) {
|
|
91
|
+
return LAYER_A_ON_TOP_OF_B;
|
|
92
|
+
} else if (!aValid && bValid) {
|
|
93
|
+
return LAYER_B_ON_TOP_OF_A;
|
|
94
|
+
} else if (!aValid && !bValid || aZIndex === bZIndex) {
|
|
95
|
+
return layerA._inputOrderIndex >= layerB._inputOrderIndex ? LAYER_A_ON_TOP_OF_B : LAYER_B_ON_TOP_OF_A;
|
|
96
|
+
} else {
|
|
97
|
+
return aZIndex > bZIndex ? LAYER_A_ON_TOP_OF_B : LAYER_B_ON_TOP_OF_A;
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
//
|
|
101
|
+
// This was a strategy to use beforeId to
|
|
102
|
+
// sync map order. We've faced some pitfalls:
|
|
103
|
+
// - Some layers do not exist when multiple layers
|
|
104
|
+
// are created at once, thus maplibre fails to
|
|
105
|
+
// apply beforeId (and throws errors)
|
|
106
|
+
// - There are issues related to layer dynamic ordering,
|
|
107
|
+
// see: https://github.com/visgl/react-map-gl/issues/939#issuecomment-1515395161
|
|
108
|
+
// - We've opted for manually syncing layer orders when
|
|
109
|
+
// layers update
|
|
110
|
+
//
|
|
111
|
+
.map(function (layer, index, sortedLayers) {
|
|
54
112
|
if (index === sortedLayers.length - 1) {
|
|
55
113
|
// is last layer
|
|
56
114
|
return __assign(__assign({}, layer), {
|
|
@@ -211,7 +269,11 @@ function syncLayerOrder(_a) {
|
|
|
211
269
|
if (!map.getLayer(beneathLayerId)) {
|
|
212
270
|
return;
|
|
213
271
|
}
|
|
214
|
-
|
|
272
|
+
try {
|
|
273
|
+
map.moveLayer(layerId, beneathLayerId);
|
|
274
|
+
} catch (err) {
|
|
275
|
+
console.warn("failed to move ".concat(layerId, " beneath ").concat(beneathLayerId));
|
|
276
|
+
}
|
|
215
277
|
}
|
|
216
278
|
});
|
|
217
279
|
}
|
|
@@ -291,7 +353,7 @@ var LayeredMap = /*#__PURE__*/forwardRef(function LayeredMapInner(_a, layeredMap
|
|
|
291
353
|
return;
|
|
292
354
|
}
|
|
293
355
|
// Timeout ensures layers are added to map before moving
|
|
294
|
-
setTimeout(function () {
|
|
356
|
+
var timeoutId = setTimeout(function () {
|
|
295
357
|
var expectedLayerOrderId = parsed.layers.map(function (layer) {
|
|
296
358
|
return layer.id;
|
|
297
359
|
});
|
|
@@ -300,6 +362,9 @@ var LayeredMap = /*#__PURE__*/forwardRef(function LayeredMapInner(_a, layeredMap
|
|
|
300
362
|
map: mapRef.current
|
|
301
363
|
});
|
|
302
364
|
}, 0);
|
|
365
|
+
return function () {
|
|
366
|
+
clearTimeout(timeoutId);
|
|
367
|
+
};
|
|
303
368
|
}, [parsed === null || parsed === void 0 ? void 0 : parsed.layers]);
|
|
304
369
|
return /*#__PURE__*/React.createElement(Map, __assign({
|
|
305
370
|
ref: mapRef,
|
|
@@ -330,7 +395,9 @@ function selectFirstClickableFeature(features) {
|
|
|
330
395
|
function layeredMapOnClickHandler(_a) {
|
|
331
396
|
var _b = _a === void 0 ? {} : _a,
|
|
332
397
|
_c = _b.resolveTargetFeature,
|
|
333
|
-
resolveTargetFeature = _c === void 0 ? selectFirstClickableFeature : _c
|
|
398
|
+
resolveTargetFeature = _c === void 0 ? selectFirstClickableFeature : _c,
|
|
399
|
+
_d = _b.context,
|
|
400
|
+
context = _d === void 0 ? {} : _d;
|
|
334
401
|
return function onClick(e) {
|
|
335
402
|
return __awaiter(this, void 0, void 0, function () {
|
|
336
403
|
var features, clickableFeatures, targetFeature, _a;
|
|
@@ -353,7 +420,7 @@ function layeredMapOnClickHandler(_a) {
|
|
|
353
420
|
_b.label = 3;
|
|
354
421
|
case 3:
|
|
355
422
|
targetFeature = _a;
|
|
356
|
-
targetFeature.layer.onClick(targetFeature, e);
|
|
423
|
+
targetFeature.layer.onClick(targetFeature, e, context);
|
|
357
424
|
_b.label = 4;
|
|
358
425
|
case 4:
|
|
359
426
|
return [2 /*return*/];
|
|
@@ -367,6 +434,9 @@ var Container = styled.div(templateObject_1$2 || (templateObject_1$2 = __makeTem
|
|
|
367
434
|
var DataSectionHeading = styled.h3(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n margin: 0;\n line-height: 1.2;\n font-size: 1rem;\n"], ["\n margin: 0;\n line-height: 1.2;\n font-size: 1rem;\n"])));
|
|
368
435
|
var DataSectionContainer = styled(Flex)(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n padding: 15px 10px;\n"], ["\n padding: 15px 10px;\n"])));
|
|
369
436
|
var EntriesList = styled.ul(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n padding: 0;\n list-style: none;\n margin-top: 0;\n margin-bottom: 0;\n > li + li {\n margin-top: 4px;\n }\n"], ["\n padding: 0;\n list-style: none;\n margin-top: 0;\n margin-bottom: 0;\n > li + li {\n margin-top: 4px;\n }\n"])));
|
|
437
|
+
function _notEmpty(value) {
|
|
438
|
+
return typeof value !== 'undefined' && value !== null && value !== '';
|
|
439
|
+
}
|
|
370
440
|
function DataSection(_a) {
|
|
371
441
|
var title = _a.title,
|
|
372
442
|
entries = _a.entries,
|
|
@@ -374,12 +444,12 @@ function DataSection(_a) {
|
|
|
374
444
|
return Array.isArray(entries) && entries.length > 0 && (/*#__PURE__*/React.createElement(DataSectionContainer, __assign({
|
|
375
445
|
direction: "column",
|
|
376
446
|
gap: "10px"
|
|
377
|
-
}, props), title && /*#__PURE__*/React.createElement(DataSectionHeading, null, title), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(EntriesList, null, entries.map(function (_a, index) {
|
|
447
|
+
}, props), title && /*#__PURE__*/React.createElement(DataSectionHeading, null, title), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(EntriesList, null, entries.filter(Boolean).map(function (_a, index) {
|
|
378
448
|
var label = _a[0],
|
|
379
449
|
value = _a[1];
|
|
380
450
|
return /*#__PURE__*/React.createElement("li", {
|
|
381
451
|
key: index
|
|
382
|
-
}, typeof label === 'string' ? /*#__PURE__*/React.createElement("span", null, label
|
|
452
|
+
}, typeof label === 'string' ? (/*#__PURE__*/React.createElement("span", null, "".concat(label).concat(_notEmpty(value) ? ': ' : ''))) : label, typeof value === 'string' ? (/*#__PURE__*/React.createElement("span", {
|
|
383
453
|
style: {
|
|
384
454
|
fontWeight: 'bold'
|
|
385
455
|
}
|
|
@@ -907,6 +977,14 @@ function makeSyncedMaps(_a) {
|
|
|
907
977
|
mapInstances: mapInstanceRefs
|
|
908
978
|
};
|
|
909
979
|
}, [mapInstanceRefs]);
|
|
980
|
+
// Let's review, this might have performance impact
|
|
981
|
+
var cursor = useMemo(function () {
|
|
982
|
+
var _a;
|
|
983
|
+
return isDragging ? 'grabbing' : (((_a = hoverInfo === null || hoverInfo === void 0 ? void 0 : hoverInfo.features) === null || _a === void 0 ? void 0 : _a.length) || 0) > 0 ? hoverInfo.features.some(function (feat) {
|
|
984
|
+
var _a;
|
|
985
|
+
return typeof ((_a = feat.layer) === null || _a === void 0 ? void 0 : _a.onClick) === 'function';
|
|
986
|
+
}) ? 'pointer' : 'default' : 'default';
|
|
987
|
+
}, [isDragging, hoverInfo]);
|
|
910
988
|
return /*#__PURE__*/React.createElement(Flex, {
|
|
911
989
|
ref: containerRef,
|
|
912
990
|
direction: "row",
|
|
@@ -932,7 +1010,9 @@ function makeSyncedMaps(_a) {
|
|
|
932
1010
|
}
|
|
933
1011
|
})) : null, Array.isArray(tooltips) && tooltips[index], /*#__PURE__*/React.createElement(MapComponent, __assign({
|
|
934
1012
|
ref: setMapInstanceRef(index),
|
|
935
|
-
cursor
|
|
1013
|
+
// cursor={isDragging ? 'grabbing' : 'default'}
|
|
1014
|
+
// Let's review, this might have performance impact
|
|
1015
|
+
cursor: cursor
|
|
936
1016
|
}, baseMapProps, mapProps, maps.length > 1 ? viewState || {} : {}, {
|
|
937
1017
|
style: __assign(__assign({}, mapProps.style || {}), {
|
|
938
1018
|
position: 'absolute',
|
|
@@ -968,6 +1048,70 @@ var SyncedMaps = makeSyncedMaps({
|
|
|
968
1048
|
});
|
|
969
1049
|
var templateObject_1;
|
|
970
1050
|
|
|
1051
|
+
function useTilesLoading(maps) {
|
|
1052
|
+
maps = Array.isArray(maps) ? maps : [maps];
|
|
1053
|
+
var _a = useState(false),
|
|
1054
|
+
loading = _a[0],
|
|
1055
|
+
setLoading = _a[1];
|
|
1056
|
+
var checkLoading = function checkLoading() {
|
|
1057
|
+
var loading = maps.some(function (map) {
|
|
1058
|
+
return !map.areTilesLoaded();
|
|
1059
|
+
});
|
|
1060
|
+
setLoading(loading);
|
|
1061
|
+
};
|
|
1062
|
+
useEffect(function () {
|
|
1063
|
+
var handlers = maps.map(function (map) {
|
|
1064
|
+
var update = function update() {
|
|
1065
|
+
return checkLoading();
|
|
1066
|
+
};
|
|
1067
|
+
map.on('dataloading', update);
|
|
1068
|
+
// map.on('data', update)
|
|
1069
|
+
map.on('idle', update);
|
|
1070
|
+
return function () {
|
|
1071
|
+
map.off('dataloading', update);
|
|
1072
|
+
// map.off('data', update)
|
|
1073
|
+
map.off('idle', update);
|
|
1074
|
+
};
|
|
1075
|
+
});
|
|
1076
|
+
checkLoading(); // initial
|
|
1077
|
+
return function () {
|
|
1078
|
+
return handlers.forEach(function (off) {
|
|
1079
|
+
return off();
|
|
1080
|
+
});
|
|
1081
|
+
};
|
|
1082
|
+
}, [maps]);
|
|
1083
|
+
return loading;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
function useMapRegistry() {
|
|
1087
|
+
var _a = useState([]),
|
|
1088
|
+
maps = _a[0],
|
|
1089
|
+
setMaps = _a[1];
|
|
1090
|
+
var onLoad = useCallback(function (evt) {
|
|
1091
|
+
//
|
|
1092
|
+
// Set maps in next tick, so that does not interfere
|
|
1093
|
+
// in map element rendering
|
|
1094
|
+
//
|
|
1095
|
+
return setTimeout(function () {
|
|
1096
|
+
return setMaps(function (currMaps) {
|
|
1097
|
+
return __spreadArray(__spreadArray([], currMaps, true), [evt.target], false);
|
|
1098
|
+
});
|
|
1099
|
+
}, 0);
|
|
1100
|
+
}, []);
|
|
1101
|
+
var onRemove = useCallback(function (evt) {
|
|
1102
|
+
return setMaps(function (currMaps) {
|
|
1103
|
+
return currMaps.filter(function (map) {
|
|
1104
|
+
return map !== evt.target;
|
|
1105
|
+
});
|
|
1106
|
+
});
|
|
1107
|
+
}, []);
|
|
1108
|
+
return {
|
|
1109
|
+
maps: maps,
|
|
1110
|
+
onLoad: onLoad,
|
|
1111
|
+
onRemove: onRemove
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
|
|
971
1115
|
function DynamicImages(_a) {
|
|
972
1116
|
var _this = this;
|
|
973
1117
|
var onGenerateImage = _a.onGenerateImage;
|
|
@@ -1032,6 +1176,7 @@ function iconPathToSvg(path, _a) {
|
|
|
1032
1176
|
var pathAttrs = ["fill=\"".concat(fill, "\""), style ? "style=\"".concat(style, "\"") : ''].filter(Boolean).join(' ');
|
|
1033
1177
|
return "<svg ".concat(svgAttrs, "><path ").concat(pathAttrs, " d=\"").concat(path, "\" /></svg>");
|
|
1034
1178
|
}
|
|
1179
|
+
|
|
1035
1180
|
/**
|
|
1036
1181
|
* Renders an SVG string onto a canvas and returns an object compatible with maplibre `addImage`.
|
|
1037
1182
|
*
|
|
@@ -1040,9 +1185,9 @@ function iconPathToSvg(path, _a) {
|
|
|
1040
1185
|
* @returns Promise resolving to { width, height, data, pixelRatio }
|
|
1041
1186
|
*/
|
|
1042
1187
|
function svgToMaplibreImage(svgString_1) {
|
|
1043
|
-
return __awaiter(this, arguments, void 0, function (svgString,
|
|
1044
|
-
if (
|
|
1045
|
-
|
|
1188
|
+
return __awaiter(this, arguments, void 0, function (svgString, inputPixelRatio) {
|
|
1189
|
+
if (inputPixelRatio === void 0) {
|
|
1190
|
+
inputPixelRatio = typeof window !== 'undefined' ? window.devicePixelRatio : 1;
|
|
1046
1191
|
}
|
|
1047
1192
|
return __generator(this, function (_a) {
|
|
1048
1193
|
return [2 /*return*/, new Promise(function (resolve, reject) {
|
|
@@ -1052,6 +1197,8 @@ function svgToMaplibreImage(svgString_1) {
|
|
|
1052
1197
|
var url = URL.createObjectURL(svgBlob);
|
|
1053
1198
|
var img = new Image();
|
|
1054
1199
|
img.onload = function () {
|
|
1200
|
+
// Normalize pixel ratio: integer and at least 1
|
|
1201
|
+
var pixelRatio = Math.max(1, Math.round(inputPixelRatio || 1));
|
|
1055
1202
|
var width = img.width * pixelRatio;
|
|
1056
1203
|
var height = img.height * pixelRatio;
|
|
1057
1204
|
var canvas = document.createElement('canvas');
|
|
@@ -1079,21 +1226,64 @@ function svgToMaplibreImage(svgString_1) {
|
|
|
1079
1226
|
});
|
|
1080
1227
|
});
|
|
1081
1228
|
}
|
|
1082
|
-
|
|
1083
|
-
|
|
1229
|
+
|
|
1230
|
+
function svgImageId(imageId, options) {
|
|
1231
|
+
return options ? "".concat(imageId, "(").concat(JSON.stringify(options), ")") : imageId;
|
|
1084
1232
|
}
|
|
1085
|
-
function
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1233
|
+
var ERROR_ICON_EXPR = function ERROR_ICON_EXPR(options) {
|
|
1234
|
+
if (options === void 0) {
|
|
1235
|
+
options = {};
|
|
1236
|
+
}
|
|
1237
|
+
return function () {
|
|
1238
|
+
return iconPathToSvg(mdiCloseCircleOutline, __assign({
|
|
1239
|
+
fill: 'red'
|
|
1240
|
+
}, options));
|
|
1241
|
+
};
|
|
1242
|
+
};
|
|
1243
|
+
function svgImageGenerator(svgImageSpecsById) {
|
|
1244
|
+
var fns = Object.fromEntries(Object.entries(svgImageSpecsById).map(function (_a) {
|
|
1245
|
+
var imageId = _a[0],
|
|
1246
|
+
iconSpec = _a[1];
|
|
1247
|
+
if (typeof iconSpec === 'string' && iconSpec.startsWith('<svg')) {
|
|
1248
|
+
//
|
|
1249
|
+
// Full svg
|
|
1250
|
+
//
|
|
1251
|
+
return [imageId, function (options) {
|
|
1252
|
+
if (options === void 0) {
|
|
1253
|
+
options = {};
|
|
1254
|
+
}
|
|
1255
|
+
return function () {
|
|
1256
|
+
return interpolate(iconSpec, options);
|
|
1257
|
+
};
|
|
1258
|
+
}];
|
|
1259
|
+
} else if (typeof iconSpec === 'string') {
|
|
1260
|
+
//
|
|
1261
|
+
// Its a string, assume it is an svg path
|
|
1262
|
+
//
|
|
1263
|
+
return [imageId, function (options) {
|
|
1264
|
+
if (options === void 0) {
|
|
1265
|
+
options = {};
|
|
1266
|
+
}
|
|
1267
|
+
return function () {
|
|
1268
|
+
return iconPathToSvg(iconSpec, options);
|
|
1269
|
+
};
|
|
1270
|
+
}];
|
|
1271
|
+
} else if (typeof iconSpec === 'function') {
|
|
1272
|
+
//
|
|
1273
|
+
// Function that returns custom svg
|
|
1274
|
+
//
|
|
1275
|
+
return [imageId, function (options) {
|
|
1276
|
+
if (options === void 0) {
|
|
1277
|
+
options = {};
|
|
1278
|
+
}
|
|
1279
|
+
return function () {
|
|
1280
|
+
return iconSpec(options);
|
|
1281
|
+
};
|
|
1282
|
+
}];
|
|
1283
|
+
} else {
|
|
1284
|
+
console.warn("Invalid icon spec for ".concat(imageId, ", will ignore"), iconSpec);
|
|
1285
|
+
return [imageId, ERROR_ICON_EXPR];
|
|
1286
|
+
}
|
|
1097
1287
|
}));
|
|
1098
1288
|
var expr = strExpr({
|
|
1099
1289
|
expressions: fns
|
|
@@ -1114,13 +1304,89 @@ function svgIconGenerator(iconPathsById) {
|
|
|
1114
1304
|
});
|
|
1115
1305
|
});
|
|
1116
1306
|
}
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1307
|
+
//
|
|
1308
|
+
// Expose generator fns
|
|
1309
|
+
//
|
|
1310
|
+
Object.assign(onGenerateSvgImage, Object.fromEntries(Object.keys(svgImageSpecsById).map(function (imageId) {
|
|
1311
|
+
return [imageId, function (options) {
|
|
1312
|
+
return svgImageId(imageId, options);
|
|
1120
1313
|
}];
|
|
1121
1314
|
})));
|
|
1122
1315
|
return onGenerateSvgImage;
|
|
1123
1316
|
}
|
|
1317
|
+
function svgIconGenerator() {
|
|
1318
|
+
var args = [];
|
|
1319
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
1320
|
+
args[_i] = arguments[_i];
|
|
1321
|
+
}
|
|
1322
|
+
console.warn('svgIconGenerator is deprecated, migrate to svgImageGenerator');
|
|
1323
|
+
return svgImageGenerator.apply(void 0, args);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
function _pattern(strTemplate) {
|
|
1327
|
+
return function (data) {
|
|
1328
|
+
return interpolate(strTemplate, data);
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
function _svgViewBox(_a) {
|
|
1332
|
+
var height = _a.height,
|
|
1333
|
+
width = _a.width;
|
|
1334
|
+
return "viewBox=\"0 0 ".concat(width, " ").concat(height, "\" height=\"").concat(height, "\" width=\"").concat(width, "\"");
|
|
1335
|
+
}
|
|
1336
|
+
function _bgRect() {
|
|
1337
|
+
return "<rect\n width=\"100%\"\n height=\"100%\"\n fill=\"${ fill = transparent }\"\n />";
|
|
1338
|
+
}
|
|
1339
|
+
// Source:
|
|
1340
|
+
// https://pattern.monster/cross-section
|
|
1341
|
+
var squares_1 = _pattern("<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n ".concat(_svgViewBox({
|
|
1342
|
+
height: 20,
|
|
1343
|
+
width: 20
|
|
1344
|
+
}), ">\n <defs>\n <pattern\n patternTransform=\"scale(${ scale = 1 })\"\n id=\"a\"\n width=\"20\"\n height=\"20\"\n patternUnits=\"userSpaceOnUse\"\n >\n ").concat(_bgRect(), "\n <path\n fill=\"transparent\"\n stroke=\"${ stroke = #000000 }\"\n stroke-width=\"2\"\n d=\"M10 0v20ZM0 10h20Z\"\n />\n </pattern>\n </defs>\n <rect width=\"800%\" height=\"800%\" fill=\"url(#a)\" />\n</svg>"));
|
|
1345
|
+
// Source:
|
|
1346
|
+
// https://pattern.monster/triangles-4
|
|
1347
|
+
var triangles_1 = _pattern("<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n ".concat(_svgViewBox({
|
|
1348
|
+
height: 40,
|
|
1349
|
+
width: 20
|
|
1350
|
+
}), ">\n <defs>\n <pattern\n patternTransform=\"scale(${ scale = 1 })\"\n id=\"a\"\n width=\"20\"\n height=\"40\"\n patternUnits=\"userSpaceOnUse\"\n >\n ").concat(_bgRect(), "\n <path\n fill=\"transparent\"\n stroke=\"${ stroke = #000000 }\"\n stroke-width=\"${ strokeWidth = 2 }\"\n d=\"M0 30h20L10 50zm-10-20h20L0 30zm20 0h20L20 30zM0-10h20L10 10z\"\n />\n </pattern>\n </defs>\n <rect width=\"800%\" height=\"800%\" fill=\"url(#a)\" />\n</svg>"));
|
|
1351
|
+
// Source:
|
|
1352
|
+
// https://pattern.monster/diamonds-1
|
|
1353
|
+
var diamonds_1 = _pattern("<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n ".concat(_svgViewBox({
|
|
1354
|
+
height: 50,
|
|
1355
|
+
width: 50
|
|
1356
|
+
}), ">\n <defs>\n <pattern\n patternTransform=\"scale(${ scale = 1 })\"\n id=\"a\"\n width=\"50\"\n height=\"50\"\n patternUnits=\"userSpaceOnUse\"\n >\n ").concat(_bgRect(), "\n <path\n fill=\"transparent\"\n stroke=\"${ stroke = #000000 }\"\n stroke-width=\"${ strokeWidth = 2 }\"\n d=\"M50 25 37.5 50 25 25 37.5 0zm-25 0L12.5 50 0 25 12.5 0z\"\n />\n </pattern>\n </defs>\n <rect width=\"800%\" height=\"800%\" fill=\"url(#a)\" />\n</svg>"));
|
|
1357
|
+
var cross_1 = _pattern("<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n ".concat(_svgViewBox({
|
|
1358
|
+
height: 20,
|
|
1359
|
+
width: 20
|
|
1360
|
+
}), ">\n <defs>\n <pattern\n patternTransform=\"scale(${ scale = 1 })\"\n id=\"a\"\n width=\"20\"\n height=\"20\"\n patternUnits=\"userSpaceOnUse\"\n >\n ").concat(_bgRect(), "\n <path\n fill=\"transparent\"\n stroke=\"${ stroke = #000000 }\"\n stroke-width=\"${ strokeWidth = 2 }\"\n stroke-linecap=\"square\"\n d=\"M3.25 10h13.5M10 3.25v13.5\"\n />\n </pattern>\n </defs>\n <rect width=\"800%\" height=\"800%\" fill=\"url(#a)\" />\n</svg>"));
|
|
1361
|
+
// https://pattern.monster/cubes-1
|
|
1362
|
+
var mosaic_1 = _pattern("<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n ".concat(_svgViewBox({
|
|
1363
|
+
width: 60,
|
|
1364
|
+
height: 60
|
|
1365
|
+
}), ">\n <defs>\n <pattern\n patternTransform=\"scale(${ scale = 1 })\"\n id=\"a\"\n width=\"60\"\n height=\"60\"\n patternUnits=\"userSpaceOnUse\">\n ").concat(_bgRect(), "\n <path\n fill=\"transparent\"\n stroke=\"${ stroke = #000000 }\"\n stroke-width=\"${ strokeWidth = 2 }\"\n d=\"M15 30v30m-7.5 0V30h15v30m7.5 0H0V30h30M45 0v30m7.5-30v30m-15 0V0M30 0h30v30M30 45h30m-30-7.5h30m0 15H30M30 30h30v30H30zM0 15h30M0 7.5h30m0 15H0M0 0h30v30H0z\"\n />\n </pattern>\n </defs>\n <rect width=\"800%\" height=\"800%\" fill=\"url(#a)\" />\n</svg>"));
|
|
1366
|
+
var waves_1 = _pattern("<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n ".concat(_svgViewBox({
|
|
1367
|
+
width: 120,
|
|
1368
|
+
height: 80
|
|
1369
|
+
}), ">\n <defs>\n <pattern\n patternTransform=\"scale(${ scale = 1 })\"\n id=\"a\"\n width=\"120\"\n height=\"80\"\n patternUnits=\"userSpaceOnUse\">\n ").concat(_bgRect(), "\n <path\n fill=\"transparent\"\n stroke=\"${ stroke = #000000 }\"\n stroke-width=\"${ strokeWidth = 2 }\"\n d=\"M-50.129 12.685C-33.346 12.358-16.786 4.918 0 5c16.787.082 43.213 10 60 10s43.213-9.918 60-10 33.346 7.358 50.129 7.685\"\n />\n <path\n fill=\"transparent\"\n stroke=\"${ stroke = #000000 }\"\n stroke-width=\"${ strokeWidth = 2 }\"\n d=\"M-50.129 32.685C-33.346 32.358-16.786 24.918 0 25c16.787.082 43.213 10 60 10s43.213-9.918 60-10 33.346 7.358 50.129 7.685\"\n />\n <path\n fill=\"transparent\"\n stroke=\"${ stroke = #000000 }\"\n stroke-width=\"${ strokeWidth = 2 }\"\n d=\"M-50.129 52.685C-33.346 52.358-16.786 44.918 0 45c16.787.082 43.213 10 60 10s43.213-9.918 60-10 33.346 7.358 50.129 7.685\"\n />\n <path\n fill=\"transparent\"\n stroke=\"${ stroke = #000000 }\"\n stroke-width=\"${ strokeWidth = 2 }\"\n d=\"M-50.129 72.685C-33.346 72.358-16.786 64.918 0 65c16.787.082 43.213 10 60 10s43.213-9.918 60-10 33.346 7.358 50.129 7.685\"\n />\n </pattern>\n </defs>\n <rect width=\"800%\" height=\"800%\" fill=\"url(#a)\" />\n</svg>"));
|
|
1370
|
+
var circles_1 = _pattern("<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n ".concat(_svgViewBox({
|
|
1371
|
+
width: 20,
|
|
1372
|
+
height: 20
|
|
1373
|
+
}), ">\n <defs>\n <pattern\n patternTransform=\"scale(${ scale = 1 })\"\n id=\"a\"\n width=\"20\"\n height=\"20\"\n patternUnits=\"userSpaceOnUse\">\n ").concat(_bgRect(), "\n <path\n fill=\"transparent\"\n stroke=\"${ stroke = #000000 }\"\n stroke-width=\"${ strokeWidth = 2 }\"\n d=\"M10 15a5 5 0 1 1 0-10 5 5 0 0 1 0 10z\"\n />\n </pattern>\n </defs>\n <rect width=\"800%\" height=\"800%\" fill=\"url(#a)\" />\n</svg>"));
|
|
1374
|
+
var lines_1 = _pattern("<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n ".concat(_svgViewBox({
|
|
1375
|
+
width: 20,
|
|
1376
|
+
height: 80
|
|
1377
|
+
}), ">\n <defs>\n <pattern\n patternTransform=\"scale(${ scale = 1 })\"\n id=\"a\"\n width=\"20\"\n height=\"80\"\n patternUnits=\"userSpaceOnUse\">\n ").concat(_bgRect(), "\n <path\n fill=\"transparent\"\n stroke=\"${ stroke = #000000 }\"\n stroke-width=\"${ strokeWidth = 2 }\"\n d=\"M0 10h20z\"\n />\n <path\n fill=\"transparent\"\n stroke=\"${ stroke = #000000 }\"\n stroke-width=\"${ strokeWidth = 2 }\"\n d=\"M0 30h20z\"\n />\n <path\n fill=\"transparent\"\n stroke=\"${ stroke = #000000 }\"\n stroke-width=\"${ strokeWidth = 2 }\"\n d=\"M0 50h20z\"\n />\n <path\n fill=\"transparent\"\n stroke=\"${ stroke = #000000 }\"\n stroke-width=\"${ strokeWidth = 2 }\"\n d=\"M0 70h20z\"\n />\n </pattern>\n </defs>\n <rect width=\"800%\" height=\"800%\" fill=\"url(#a)\" />\n</svg>"));
|
|
1378
|
+
|
|
1379
|
+
var index = /*#__PURE__*/Object.freeze({
|
|
1380
|
+
__proto__: null,
|
|
1381
|
+
circles_1: circles_1,
|
|
1382
|
+
cross_1: cross_1,
|
|
1383
|
+
diamonds_1: diamonds_1,
|
|
1384
|
+
lines_1: lines_1,
|
|
1385
|
+
mosaic_1: mosaic_1,
|
|
1386
|
+
squares_1: squares_1,
|
|
1387
|
+
triangles_1: triangles_1,
|
|
1388
|
+
waves_1: waves_1
|
|
1389
|
+
});
|
|
1124
1390
|
|
|
1125
1391
|
var DEFAULT_MIN_K = 3;
|
|
1126
1392
|
var DEFAULT_MAX_K = 9;
|
|
@@ -1642,4 +1908,4 @@ function InspectControl(props) {
|
|
|
1642
1908
|
return null;
|
|
1643
1909
|
}
|
|
1644
1910
|
|
|
1645
|
-
export { $naturalBreaks, ControlContainer, DynamicImages, HoverTooltip, InspectControl, LayeredMap, MapWindow, SyncedMaps, TerrainControl, applyReactStyle, augmentFeature, ensureAddLayer, ensureAddSource, ensureRemoveLayer, ensureRemoveSource, fitGeometry, fmtLayerAbsoluteId, getSrcLayer, getSrcViewByLayerId, hoverParseEvent,
|
|
1911
|
+
export { $naturalBreaks, ControlContainer, DynamicImages, HoverTooltip, InspectControl, LayeredMap, MapWindow, index as SVG_PATTERNS, SyncedMaps, TerrainControl, applyReactStyle, augmentFeature, circles_1, cross_1, diamonds_1, ensureAddLayer, ensureAddSource, ensureRemoveLayer, ensureRemoveSource, fitGeometry, fmtLayerAbsoluteId, getSrcLayer, getSrcViewByLayerId, hoverParseEvent, layeredMapOnClickHandler, lines_1, makeSyncedMaps, mapSetFeaturesState, mosaic_1, naturalBreakBounds, parseMapViews, scaleNaturalBreaks, sortLayers, squares_1, svgIconGenerator, svgImageGenerator, svgImageId, triangles_1, useClientRect, useHover, useLayeredMap, useMapRegistry, useTilesLoading, waves_1, withHover };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orioro/react-maplibre-util",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"packageManager": "yarn@4.0.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -51,12 +51,12 @@
|
|
|
51
51
|
"@maplibre/maplibre-gl-inspect": "^1.7.1",
|
|
52
52
|
"@mdi/js": "^7.4.47",
|
|
53
53
|
"@mdi/react": "^1.6.1",
|
|
54
|
-
"@orioro/react-chart-util": "^0.
|
|
54
|
+
"@orioro/react-chart-util": "^0.3.0",
|
|
55
55
|
"@orioro/react-select": "^3.0.2",
|
|
56
|
-
"@orioro/react-ui-core": "^0.0.
|
|
57
|
-
"@orioro/resolve": "^0.1.
|
|
56
|
+
"@orioro/react-ui-core": "^0.0.14",
|
|
57
|
+
"@orioro/resolve": "^0.1.9",
|
|
58
58
|
"@orioro/scale-util": "^0.0.2",
|
|
59
|
-
"@orioro/util": "^0.
|
|
59
|
+
"@orioro/util": "^0.15.1",
|
|
60
60
|
"@turf/turf": "^7.2.0",
|
|
61
61
|
"d3": "^7.9.0",
|
|
62
62
|
"d3-scale-chromatic": "^3.1.0",
|