@dynatrace/strato-geo 3.6.0 → 3.7.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/esm/map/MapView.js +42 -34
- package/esm/map/MapView.js.map +2 -2
- package/esm/map/components/BubbleLayer/BubbleCircleLayer.js +2 -0
- package/esm/map/components/BubbleLayer/BubbleCircleLayer.js.map +2 -2
- package/esm/map/components/BubbleLayer/BubbleLayer.js +4 -1
- package/esm/map/components/BubbleLayer/BubbleLayer.js.map +2 -2
- package/esm/map/components/BubbleLayer/utils/parse-bubble-data-to-geo-json.js +5 -5
- package/esm/map/components/BubbleLayer/utils/parse-bubble-data-to-geo-json.js.map +2 -2
- package/esm/map/components/ChoroplethLayer/ChoroplethLayer.js +5 -2
- package/esm/map/components/ChoroplethLayer/ChoroplethLayer.js.map +2 -2
- package/esm/map/components/ChoroplethLayer/ChoroplethLayerTooltip.js.map +2 -2
- package/esm/map/components/ChoroplethLayer/ChoroplethOutlineLayer.js +3 -1
- package/esm/map/components/ChoroplethLayer/ChoroplethOutlineLayer.js.map +2 -2
- package/esm/map/components/ChoroplethLayer/utils/parse-region-data-to-geo-json.js +6 -5
- package/esm/map/components/ChoroplethLayer/utils/parse-region-data-to-geo-json.js.map +2 -2
- package/esm/map/components/ConnectionLayer/ConnectionLayer.js +1 -1
- package/esm/map/components/ConnectionLayer/ConnectionLayer.js.map +2 -2
- package/esm/map/components/ConnectionLayer/ConnectionLayerLine.js +3 -0
- package/esm/map/components/ConnectionLayer/ConnectionLayerLine.js.map +2 -2
- package/esm/map/components/ConnectionLayer/ConnectionLayerTooltip.js +7 -9
- package/esm/map/components/ConnectionLayer/ConnectionLayerTooltip.js.map +2 -2
- package/esm/map/components/ConnectionLayer/utils/parse-connection-data-to-geo-json.js +20 -18
- package/esm/map/components/ConnectionLayer/utils/parse-connection-data-to-geo-json.js.map +2 -2
- package/esm/map/components/DotLayer/DotLayer.js +4 -1
- package/esm/map/components/DotLayer/DotLayer.js.map +2 -2
- package/esm/map/components/DotLayer/DotLayerTooltip.js.map +2 -2
- package/esm/map/components/DotLayer/utils/parse-dot-data-to-geo-json.js +5 -5
- package/esm/map/components/DotLayer/utils/parse-dot-data-to-geo-json.js.map +2 -2
- package/esm/map/components/MapContent.js +22 -12
- package/esm/map/components/MapContent.js.map +2 -2
- package/esm/map/contexts/geo-data-lookup.context.js +8 -0
- package/esm/map/contexts/geo-data-lookup.context.js.map +7 -0
- package/esm/map/hooks/use-active-interaction.js +59 -43
- package/esm/map/hooks/use-active-interaction.js.map +2 -2
- package/esm/map/hooks/use-attach-image-from-icon.js +4 -2
- package/esm/map/hooks/use-attach-image-from-icon.js.map +2 -2
- package/esm/map/hooks/use-hover-interaction.js +59 -41
- package/esm/map/hooks/use-hover-interaction.js.map +2 -2
- package/esm/map/hooks/use-layer-before-id.js +24 -0
- package/esm/map/hooks/use-layer-before-id.js.map +7 -0
- package/esm/map/hooks/use-map-runtime-error.js +93 -0
- package/esm/map/hooks/use-map-runtime-error.js.map +7 -0
- package/esm/map/hooks/use-overlay-events.js +11 -2
- package/esm/map/hooks/use-overlay-events.js.map +2 -2
- package/esm/map/hooks/use-webgl-context-error.js +2 -1
- package/esm/map/hooks/use-webgl-context-error.js.map +2 -2
- package/esm/map/index.js.map +1 -1
- package/esm/map/slots/Tooltip.js.map +2 -2
- package/esm/map/utils/attach-image-from-shape.js +4 -2
- package/esm/map/utils/attach-image-from-shape.js.map +2 -2
- package/esm/map/utils/extract-layers-data.js +24 -15
- package/esm/map/utils/extract-layers-data.js.map +2 -2
- package/esm/map/utils/is-browser-firefox.js +7 -0
- package/esm/map/utils/is-browser-firefox.js.map +7 -0
- package/esm/map/utils/parse-tooltip-data.js +22 -7
- package/esm/map/utils/parse-tooltip-data.js.map +2 -2
- package/map/MapView.js +42 -34
- package/map/components/BubbleLayer/BubbleCircleLayer.d.ts +2 -1
- package/map/components/BubbleLayer/BubbleCircleLayer.js +2 -0
- package/map/components/BubbleLayer/BubbleLayer.js +4 -1
- package/map/components/BubbleLayer/utils/parse-bubble-data-to-geo-json.d.ts +3 -1
- package/map/components/BubbleLayer/utils/parse-bubble-data-to-geo-json.js +5 -5
- package/map/components/ChoroplethLayer/ChoroplethLayer.js +5 -2
- package/map/components/ChoroplethLayer/ChoroplethOutlineLayer.d.ts +1 -0
- package/map/components/ChoroplethLayer/ChoroplethOutlineLayer.js +3 -1
- package/map/components/ChoroplethLayer/utils/parse-region-data-to-geo-json.d.ts +3 -1
- package/map/components/ChoroplethLayer/utils/parse-region-data-to-geo-json.js +6 -5
- package/map/components/ConnectionLayer/ConnectionLayer.js +1 -1
- package/map/components/ConnectionLayer/ConnectionLayerLine.js +3 -0
- package/map/components/ConnectionLayer/ConnectionLayerTooltip.js +7 -9
- package/map/components/ConnectionLayer/utils/parse-connection-data-to-geo-json.d.ts +3 -1
- package/map/components/ConnectionLayer/utils/parse-connection-data-to-geo-json.js +20 -18
- package/map/components/DotLayer/DotLayer.js +4 -1
- package/map/components/DotLayer/utils/parse-dot-data-to-geo-json.d.ts +3 -1
- package/map/components/DotLayer/utils/parse-dot-data-to-geo-json.js +5 -5
- package/map/components/MapContent.js +21 -12
- package/map/contexts/geo-data-lookup.context.d.ts +9 -0
- package/map/{components/ConnectionLayer/utils/restore-null-props.js → contexts/geo-data-lookup.context.js} +8 -9
- package/map/hooks/use-active-interaction.d.ts +8 -1
- package/map/hooks/use-active-interaction.js +58 -42
- package/map/hooks/use-attach-image-from-icon.js +4 -2
- package/map/hooks/use-hover-interaction.d.ts +6 -2
- package/map/hooks/use-hover-interaction.js +52 -39
- package/map/hooks/use-layer-before-id.d.ts +13 -0
- package/map/hooks/{use-map-mouse-move.js → use-layer-before-id.js} +20 -15
- package/map/hooks/use-map-runtime-error.d.ts +34 -0
- package/map/hooks/use-map-runtime-error.js +112 -0
- package/map/hooks/use-overlay-events.js +11 -2
- package/map/hooks/use-webgl-context-error.js +2 -1
- package/map/slots/Tooltip.d.ts +2 -0
- package/map/types/connection-layer.d.ts +1 -8
- package/map/types/tooltip.d.ts +1 -0
- package/map/utils/attach-image-from-shape.js +4 -2
- package/map/utils/extract-layers-data.d.ts +2 -0
- package/map/utils/extract-layers-data.js +24 -15
- package/map/utils/is-browser-firefox.d.ts +5 -0
- package/map/utils/is-browser-firefox.js +26 -0
- package/map/utils/parse-tooltip-data.d.ts +11 -3
- package/map/utils/parse-tooltip-data.js +22 -7
- package/package.json +2 -2
- package/esm/map/components/ConnectionLayer/utils/restore-null-props.js +0 -9
- package/esm/map/components/ConnectionLayer/utils/restore-null-props.js.map +0 -7
- package/esm/map/hooks/use-map-mouse-move.js +0 -19
- package/esm/map/hooks/use-map-mouse-move.js.map +0 -7
- package/map/components/ConnectionLayer/utils/restore-null-props.d.ts +0 -2
- package/map/hooks/use-map-mouse-move.d.ts +0 -2
|
@@ -24,9 +24,16 @@ module.exports = __toCommonJS(use_hover_interaction_exports);
|
|
|
24
24
|
var import_react_maplibre = require("@vis.gl/react-maplibre");
|
|
25
25
|
var import_lodash_es = require("lodash");
|
|
26
26
|
var import_react = require("react");
|
|
27
|
-
var import_constants = require("../constants.js");
|
|
28
27
|
var import_associated_features = require("../utils/associated-features.js");
|
|
29
28
|
var import_get_min_value_feature = require("../utils/get-min-value-feature.js");
|
|
29
|
+
const MOUSEMOVE_THROTTLE_MS = 16;
|
|
30
|
+
const blurTrackedFeature = (map, featureIdRef, sourceIdRef) => {
|
|
31
|
+
if (!(0, import_lodash_es.isNil)(featureIdRef.current) && !(0, import_lodash_es.isNil)(sourceIdRef.current)) {
|
|
32
|
+
blurFeature(map, sourceIdRef.current, featureIdRef.current);
|
|
33
|
+
featureIdRef.current = void 0;
|
|
34
|
+
sourceIdRef.current = void 0;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
30
37
|
const featureExists = (map, source, id) => {
|
|
31
38
|
const isSourcePresent = map.getSource(source) !== void 0;
|
|
32
39
|
return isSourcePresent && map.getFeatureState({
|
|
@@ -68,53 +75,59 @@ const hoverFeature = (map, source, id) => {
|
|
|
68
75
|
}
|
|
69
76
|
}
|
|
70
77
|
};
|
|
71
|
-
const useHoverInteraction = () => {
|
|
78
|
+
const useHoverInteraction = (interactiveLayerIds) => {
|
|
72
79
|
const map = (0, import_react_maplibre.useMap)().current;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
80
|
+
const featureIdRef = (0, import_react.useRef)(void 0);
|
|
81
|
+
const sourceIdRef = (0, import_react.useRef)(void 0);
|
|
82
|
+
const interactiveLayerIdsRef = (0, import_react.useRef)(interactiveLayerIds);
|
|
83
|
+
interactiveLayerIdsRef.current = interactiveLayerIds;
|
|
84
|
+
const handleMouseOut = (0, import_react.useCallback)(() => {
|
|
85
|
+
if (!(0, import_lodash_es.isNil)(map)) {
|
|
86
|
+
blurTrackedFeature(map, featureIdRef, sourceIdRef);
|
|
87
|
+
}
|
|
88
|
+
}, [map]);
|
|
89
|
+
const throttledMouseMove = (0, import_react.useMemo)(
|
|
90
|
+
() => (0, import_lodash_es.throttle)(
|
|
91
|
+
({ point }) => {
|
|
92
|
+
if ((0, import_lodash_es.isNil)(map)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
let features;
|
|
96
|
+
try {
|
|
97
|
+
features = map.queryRenderedFeatures(point, {
|
|
98
|
+
layers: interactiveLayerIdsRef.current
|
|
99
|
+
}).filter((feature) => !(0, import_associated_features.isAssociatedFeature)(feature.properties.id));
|
|
100
|
+
} catch {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
88
103
|
const layerId = features?.[0]?.layer?.id;
|
|
89
104
|
const hasHoveredFeatures = !(0, import_lodash_es.isNil)(features) && features.length > 0 && !(0, import_lodash_es.isUndefined)(layerId);
|
|
90
|
-
|
|
91
|
-
if (hasHoveredFeatures && !isBaseLayer) {
|
|
92
|
-
map.getCanvas().style.cursor = "pointer";
|
|
93
|
-
if (!(0, import_lodash_es.isUndefined)(featureId) && !(0, import_lodash_es.isUndefined)(sourceId)) {
|
|
94
|
-
blurFeature(map, sourceId, featureId);
|
|
95
|
-
}
|
|
96
|
-
const minFeature = (0, import_get_min_value_feature.getMinValueFeature)(features);
|
|
97
|
-
featureId = minFeature.id;
|
|
98
|
-
sourceId = minFeature.layer.source;
|
|
99
|
-
if (!(0, import_lodash_es.isUndefined)(featureId)) {
|
|
100
|
-
hoverFeature(map, sourceId, featureId);
|
|
101
|
-
}
|
|
102
|
-
} else {
|
|
105
|
+
if (!hasHoveredFeatures) {
|
|
103
106
|
map.getCanvas().style.cursor = "grab";
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
+
blurTrackedFeature(map, featureIdRef, sourceIdRef);
|
|
108
|
+
return;
|
|
107
109
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
map.getCanvas().style.cursor = "pointer";
|
|
111
|
+
blurTrackedFeature(map, featureIdRef, sourceIdRef);
|
|
112
|
+
const minFeature = (0, import_get_min_value_feature.getMinValueFeature)(features);
|
|
113
|
+
featureIdRef.current = minFeature.id;
|
|
114
|
+
sourceIdRef.current = minFeature.layer.source;
|
|
115
|
+
if (!(0, import_lodash_es.isUndefined)(featureIdRef.current)) {
|
|
116
|
+
hoverFeature(map, sourceIdRef.current, featureIdRef.current);
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
MOUSEMOVE_THROTTLE_MS,
|
|
120
|
+
{ trailing: true }
|
|
121
|
+
),
|
|
122
|
+
[map]
|
|
111
123
|
);
|
|
112
124
|
(0, import_react.useEffect)(() => {
|
|
113
|
-
map?.on("mousemove",
|
|
125
|
+
map?.on("mousemove", throttledMouseMove);
|
|
114
126
|
map?.on("mouseout", handleMouseOut);
|
|
115
127
|
return () => {
|
|
116
|
-
|
|
128
|
+
throttledMouseMove.cancel();
|
|
129
|
+
map?.off("mousemove", throttledMouseMove);
|
|
117
130
|
map?.off("mouseout", handleMouseOut);
|
|
118
131
|
};
|
|
119
|
-
}, []);
|
|
132
|
+
}, [map, throttledMouseMove, handleMouseOut]);
|
|
120
133
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the maplibre layer id that the current layer should be inserted before,
|
|
3
|
+
* based on the JSX order of `MapView` children.
|
|
4
|
+
*
|
|
5
|
+
* Without this, layers that mount asynchronously (e.g. `{apiData && <ChoroplethLayer>}`)
|
|
6
|
+
* are appended to the top of the maplibre stack and end up visually above siblings
|
|
7
|
+
* that mounted earlier — even when JSX puts them first. Passing the returned value as
|
|
8
|
+
* `beforeId` to a `<Layer>` keeps the rendered stack aligned with JSX order.
|
|
9
|
+
*
|
|
10
|
+
* Only returns an id that actually exists in the map right now, so the result is
|
|
11
|
+
* always safe to pass to `map.addLayer(opts, beforeId)`.
|
|
12
|
+
*/
|
|
13
|
+
export declare const useLayerBeforeId: (layerId: string) => string | undefined;
|
|
@@ -16,23 +16,28 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
return to;
|
|
17
17
|
};
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var
|
|
20
|
-
__export(
|
|
21
|
-
|
|
19
|
+
var use_layer_before_id_exports = {};
|
|
20
|
+
__export(use_layer_before_id_exports, {
|
|
21
|
+
useLayerBeforeId: () => useLayerBeforeId
|
|
22
22
|
});
|
|
23
|
-
module.exports = __toCommonJS(
|
|
23
|
+
module.exports = __toCommonJS(use_layer_before_id_exports);
|
|
24
24
|
var import_react_maplibre = require("@vis.gl/react-maplibre");
|
|
25
25
|
var import_react = require("react");
|
|
26
|
-
|
|
26
|
+
var import_layer_ids_context = require("../contexts/layer-ids.context.js");
|
|
27
|
+
const useLayerBeforeId = (layerId) => {
|
|
28
|
+
const layerIds = (0, import_react.useContext)(import_layer_ids_context.LayerIdsContext);
|
|
27
29
|
const { current: map } = (0, import_react_maplibre.useMap)();
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
if (!map) {
|
|
31
|
+
return void 0;
|
|
32
|
+
}
|
|
33
|
+
const currentIndex = layerIds.indexOf(layerId);
|
|
34
|
+
if (currentIndex === -1) {
|
|
35
|
+
return void 0;
|
|
36
|
+
}
|
|
37
|
+
for (let i = currentIndex + 1; i < layerIds.length; i++) {
|
|
38
|
+
if (map.getLayer(layerIds[i])) {
|
|
39
|
+
return layerIds[i];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return void 0;
|
|
38
43
|
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface UseMapRuntimeErrorOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Called when the retry budget (3 attempts) is exhausted and the map cannot
|
|
4
|
+
* recover. Throwing inside this callback will propagate to the nearest React
|
|
5
|
+
* ErrorBoundary, showing the fallback UI.
|
|
6
|
+
*/
|
|
7
|
+
onError: () => void;
|
|
8
|
+
/**
|
|
9
|
+
* Optional callback invoked on each recoverable error attempt before the
|
|
10
|
+
* budget is exhausted. The `attempt` argument is 1-indexed.
|
|
11
|
+
*/
|
|
12
|
+
onRetry?: (attempt: number) => void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Unified hook that guards MapView against maplibre-gl runtime errors from
|
|
16
|
+
* three distinct sources:
|
|
17
|
+
*
|
|
18
|
+
* 1. **WebGL context loss** (`webglcontextlost` on the canvas) — composed via
|
|
19
|
+
* `useWebGLContextError`.
|
|
20
|
+
* 2. **maplibre's own error events** (`map.on('error', ...)`), covering tile
|
|
21
|
+
* load failures and other internally dispatched errors.
|
|
22
|
+
* 3. **Synchronous throws from the rAF render loop** that escape to
|
|
23
|
+
* `window.onerror` — shader compilation, program link, and feature-index
|
|
24
|
+
* out-of-bounds errors that maplibre does not catch internally.
|
|
25
|
+
*
|
|
26
|
+
* A shared retry counter (max 3) is maintained across all sources. Error
|
|
27
|
+
* counting is debounced at 500 ms so that a burst of errors within a single
|
|
28
|
+
* render frame counts as one occurrence. The counter resets whenever the map
|
|
29
|
+
* fires an `idle` event (indicating a successful render). Once the budget is
|
|
30
|
+
* exhausted, `onError` is invoked.
|
|
31
|
+
*
|
|
32
|
+
* APPDEV-17938
|
|
33
|
+
*/
|
|
34
|
+
export declare const useMapRuntimeError: ({ onError, onRetry, }: UseMapRuntimeErrorOptions) => void;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var use_map_runtime_error_exports = {};
|
|
20
|
+
__export(use_map_runtime_error_exports, {
|
|
21
|
+
useMapRuntimeError: () => useMapRuntimeError
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(use_map_runtime_error_exports);
|
|
24
|
+
var import_react_maplibre = require("@vis.gl/react-maplibre");
|
|
25
|
+
var import_react = require("react");
|
|
26
|
+
var import_use_webgl_context_error = require("./use-webgl-context-error.js");
|
|
27
|
+
const MAX_RETRIES = 3;
|
|
28
|
+
const ERROR_DEBOUNCE_MS = 500;
|
|
29
|
+
const MAPLIBRE_RUNTIME_ERROR_PATTERNS = [
|
|
30
|
+
"Could not compile fragment shader",
|
|
31
|
+
"Could not compile vertex shader",
|
|
32
|
+
"Program failed to link",
|
|
33
|
+
"feature index out of bounds",
|
|
34
|
+
"Out of bounds. Index requested"
|
|
35
|
+
];
|
|
36
|
+
const isMaplibreRuntimeError = (message) => MAPLIBRE_RUNTIME_ERROR_PATTERNS.some((pattern) => message.includes(pattern));
|
|
37
|
+
const useMapRuntimeError = ({
|
|
38
|
+
onError,
|
|
39
|
+
onRetry
|
|
40
|
+
}) => {
|
|
41
|
+
const { current: mapRef } = (0, import_react_maplibre.useMap)();
|
|
42
|
+
const retryCountRef = (0, import_react.useRef)(0);
|
|
43
|
+
const lastErrorTimeRef = (0, import_react.useRef)(0);
|
|
44
|
+
const isMapActiveRef = (0, import_react.useRef)(true);
|
|
45
|
+
const onErrorRef = (0, import_react.useRef)(onError);
|
|
46
|
+
onErrorRef.current = onError;
|
|
47
|
+
const onRetryRef = (0, import_react.useRef)(onRetry);
|
|
48
|
+
onRetryRef.current = onRetry;
|
|
49
|
+
const handleError = (0, import_react.useCallback)(() => {
|
|
50
|
+
const now = Date.now();
|
|
51
|
+
if (now - lastErrorTimeRef.current < ERROR_DEBOUNCE_MS) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
lastErrorTimeRef.current = now;
|
|
55
|
+
retryCountRef.current += 1;
|
|
56
|
+
if (retryCountRef.current >= MAX_RETRIES) {
|
|
57
|
+
onErrorRef.current();
|
|
58
|
+
} else {
|
|
59
|
+
onRetryRef.current?.(retryCountRef.current);
|
|
60
|
+
}
|
|
61
|
+
}, []);
|
|
62
|
+
(0, import_use_webgl_context_error.useWebGLContextError)(handleError);
|
|
63
|
+
(0, import_react.useEffect)(() => {
|
|
64
|
+
const map = mapRef?.getMap();
|
|
65
|
+
if (!map) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const handleMapError = ({ error }) => {
|
|
69
|
+
if (isMaplibreRuntimeError(error.message)) {
|
|
70
|
+
handleError();
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
map.on("error", handleMapError);
|
|
74
|
+
return () => {
|
|
75
|
+
map.off("error", handleMapError);
|
|
76
|
+
};
|
|
77
|
+
}, [mapRef, handleError]);
|
|
78
|
+
(0, import_react.useEffect)(() => {
|
|
79
|
+
const handleWindowError = (event) => {
|
|
80
|
+
if (!isMapActiveRef.current) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (isMaplibreRuntimeError(event.message)) {
|
|
84
|
+
event.preventDefault();
|
|
85
|
+
handleError();
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
window.addEventListener("error", handleWindowError);
|
|
89
|
+
return () => {
|
|
90
|
+
window.removeEventListener("error", handleWindowError);
|
|
91
|
+
};
|
|
92
|
+
}, [handleError]);
|
|
93
|
+
(0, import_react.useEffect)(() => {
|
|
94
|
+
const map = mapRef?.getMap();
|
|
95
|
+
if (!map) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const handleRender = () => {
|
|
99
|
+
isMapActiveRef.current = true;
|
|
100
|
+
};
|
|
101
|
+
const handleIdle = () => {
|
|
102
|
+
isMapActiveRef.current = false;
|
|
103
|
+
retryCountRef.current = 0;
|
|
104
|
+
};
|
|
105
|
+
map.on("render", handleRender);
|
|
106
|
+
map.on("idle", handleIdle);
|
|
107
|
+
return () => {
|
|
108
|
+
map.off("render", handleRender);
|
|
109
|
+
map.off("idle", handleIdle);
|
|
110
|
+
};
|
|
111
|
+
}, [mapRef]);
|
|
112
|
+
};
|
|
@@ -21,7 +21,9 @@ __export(use_overlay_events_exports, {
|
|
|
21
21
|
useOverlayEvents: () => useOverlayEvents
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(use_overlay_events_exports);
|
|
24
|
+
var import_react = require("react");
|
|
24
25
|
var import_charts = require("@dynatrace/strato-components/charts");
|
|
26
|
+
var import_geo_data_lookup_context = require("../contexts/geo-data-lookup.context.js");
|
|
25
27
|
var import_store = require("../store/store.js");
|
|
26
28
|
var import_build_geo_tooltip_state = require("../utils/build-geo-tooltip-state.js");
|
|
27
29
|
var import_parse_tooltip_data = require("../utils/parse-tooltip-data.js");
|
|
@@ -38,6 +40,7 @@ const layerIdToGeometry = (layerId) => {
|
|
|
38
40
|
return "geoDot";
|
|
39
41
|
};
|
|
40
42
|
const useOverlayEvents = () => {
|
|
43
|
+
const dataLookupRegistry = (0, import_react.useContext)(import_geo_data_lookup_context.GeoDataLookupContext);
|
|
41
44
|
const setOverlayState = (0, import_store.useSetStateOverlay)();
|
|
42
45
|
const setState = (0, import_store.useSetState)();
|
|
43
46
|
const dispatch = (0, import_charts._useOverlayTooltipReducer)();
|
|
@@ -72,7 +75,10 @@ const useOverlayEvents = () => {
|
|
|
72
75
|
if (currentState.pinned) {
|
|
73
76
|
return;
|
|
74
77
|
}
|
|
75
|
-
const { data, hoveredLayerId } = (0, import_parse_tooltip_data.extractDataFromEvent)(
|
|
78
|
+
const { data, hoveredLayerId } = (0, import_parse_tooltip_data.extractDataFromEvent)(
|
|
79
|
+
event,
|
|
80
|
+
dataLookupRegistry
|
|
81
|
+
);
|
|
76
82
|
overlay.clear();
|
|
77
83
|
setTooltipMarker(hoveredLayerId, event.lngLat);
|
|
78
84
|
const pos = getAbsolutePosition(event);
|
|
@@ -102,7 +108,10 @@ const useOverlayEvents = () => {
|
|
|
102
108
|
}
|
|
103
109
|
};
|
|
104
110
|
const handleMouseClick = (event) => {
|
|
105
|
-
const { data, featureId, hoveredLayerId } = (0, import_parse_tooltip_data.extractDataFromEvent)(
|
|
111
|
+
const { data, featureId, hoveredLayerId } = (0, import_parse_tooltip_data.extractDataFromEvent)(
|
|
112
|
+
event,
|
|
113
|
+
dataLookupRegistry
|
|
114
|
+
);
|
|
106
115
|
if (!featureId) {
|
|
107
116
|
hideTooltip();
|
|
108
117
|
return;
|
|
@@ -30,7 +30,8 @@ const useWebGLContextError = (onContextLost) => {
|
|
|
30
30
|
if (!canvas) {
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
|
-
const handleContextLost = () => {
|
|
33
|
+
const handleContextLost = (event) => {
|
|
34
|
+
event.preventDefault();
|
|
34
35
|
onContextLost?.();
|
|
35
36
|
};
|
|
36
37
|
canvas.addEventListener("webglcontextlost", handleContextLost);
|
package/map/slots/Tooltip.d.ts
CHANGED
|
@@ -4,11 +4,13 @@ import type { ChartTooltip } from '../types/tooltip.js';
|
|
|
4
4
|
* Tooltip is responsible for exposing the
|
|
5
5
|
* ChartTooltip props, such as, sections, to the consumer
|
|
6
6
|
* @public
|
|
7
|
+
* @deprecated Use `ChartTooltip` from `@dynatrace/strato-components/charts` instead. Removal: APPDEV-17834
|
|
7
8
|
*/
|
|
8
9
|
export declare const Tooltip: ChartTooltip;
|
|
9
10
|
/**
|
|
10
11
|
* TooltipAtoms is responsible for exposing the
|
|
11
12
|
* ChartTooltip atoms.
|
|
12
13
|
* @public
|
|
14
|
+
* @deprecated Use `ChartTooltip` from `@dynatrace/strato-components/charts` instead. Removal: APPDEV-17834
|
|
13
15
|
*/
|
|
14
16
|
export declare const TooltipAtoms: ChartTooltipAtomsType;
|
|
@@ -53,12 +53,12 @@ export type InternalConnectionLayerProps<T extends Connection> = ConnectionLayer
|
|
|
53
53
|
/** @internal */
|
|
54
54
|
export interface FeatureProperties {
|
|
55
55
|
id: string;
|
|
56
|
+
__dataIndex?: number;
|
|
56
57
|
__lineColor: string;
|
|
57
58
|
__lineHoveredColor: string;
|
|
58
59
|
__lineWidth: number;
|
|
59
60
|
__angle?: number;
|
|
60
61
|
curve?: CurvedLine;
|
|
61
|
-
path: Location[];
|
|
62
62
|
}
|
|
63
63
|
export type GeoJSONFeature<T extends GeoJSON.Geometry> = GeoJSON.Feature<T, FeatureProperties>;
|
|
64
64
|
/**
|
|
@@ -79,10 +79,3 @@ export interface ConnectionColorProps<T extends Connection> {
|
|
|
79
79
|
*/
|
|
80
80
|
color?: string | ((connection: T) => string);
|
|
81
81
|
}
|
|
82
|
-
/** @internal */
|
|
83
|
-
export type ConnectionTooltipStatePayload = {
|
|
84
|
-
path: Location[];
|
|
85
|
-
__lineColor: string;
|
|
86
|
-
__lineWidth: number;
|
|
87
|
-
__nullValues: string[] | undefined;
|
|
88
|
-
};
|
package/map/types/tooltip.d.ts
CHANGED
|
@@ -145,5 +145,6 @@ export interface ChoroplethLayerTooltipHandlerProps {
|
|
|
145
145
|
/**
|
|
146
146
|
* Map Geo Tooltip Props
|
|
147
147
|
* @public
|
|
148
|
+
* @deprecated Use `ChartTooltip` from `@dynatrace/strato-components/charts` instead. Removal: APPDEV-17834
|
|
148
149
|
*/
|
|
149
150
|
export type ChartTooltip = ChartTooltipSlotsType & ChartTooltipTemplateType;
|
|
@@ -25,20 +25,22 @@ var import_attach_image_to_map = require("./attach-image-to-map.js");
|
|
|
25
25
|
var import_create_bitmap_config_options = require("./create-bitmap-config-options.js");
|
|
26
26
|
var import_get_data_uri = require("./get-data-uri.js");
|
|
27
27
|
var import_constants = require("../constants.js");
|
|
28
|
+
var import_is_browser_firefox = require("./is-browser-firefox.js");
|
|
28
29
|
var import_shape_picker = require("../shapes/shape-picker.js");
|
|
29
30
|
const attachImageFromShape = (map, shape, name, outputSize) => {
|
|
30
31
|
const pickedShape = (0, import_shape_picker.getShape)(shape);
|
|
31
32
|
const stringUrl = (0, import_get_data_uri.getDataUri)(encodeURIComponent(pickedShape));
|
|
32
33
|
const img = new Image(import_constants.DEFAULT_INPUT_ICON_SIZE, import_constants.DEFAULT_INPUT_ICON_SIZE);
|
|
33
34
|
img.addEventListener("load", () => {
|
|
34
|
-
createImageBitmap(
|
|
35
|
+
const bitmapPromise = (0, import_is_browser_firefox.isFirefox)() ? createImageBitmap(img, (0, import_create_bitmap_config_options.createBitmapConfigOptions)(outputSize)) : createImageBitmap(
|
|
35
36
|
img,
|
|
36
37
|
0,
|
|
37
38
|
0,
|
|
38
39
|
import_constants.DEFAULT_INPUT_ICON_SIZE,
|
|
39
40
|
import_constants.DEFAULT_INPUT_ICON_SIZE,
|
|
40
41
|
(0, import_create_bitmap_config_options.createBitmapConfigOptions)(outputSize)
|
|
41
|
-
)
|
|
42
|
+
);
|
|
43
|
+
bitmapPromise.then((bitmap) => {
|
|
42
44
|
if (!map) {
|
|
43
45
|
return;
|
|
44
46
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
+
import type { GeoDataLookupRegistry } from '../contexts/geo-data-lookup.context.js';
|
|
2
3
|
/**
|
|
3
4
|
* Extract layers data
|
|
4
5
|
* @param children - MapView children
|
|
@@ -9,4 +10,5 @@ export declare const extractLayersData: (children: ReactNode, valueAccessors: Ma
|
|
|
9
10
|
flattenData: Record<string, unknown>[];
|
|
10
11
|
categories: string[];
|
|
11
12
|
legendDomain: [number, number];
|
|
13
|
+
dataLookupRegistry: GeoDataLookupRegistry;
|
|
12
14
|
};
|
|
@@ -47,17 +47,20 @@ const extractLayersData = (children, valueAccessors) => {
|
|
|
47
47
|
let flattenData = [];
|
|
48
48
|
const categoriesSet = /* @__PURE__ */ new Set();
|
|
49
49
|
let legendDomain = [Infinity, -Infinity];
|
|
50
|
+
const dataLookupRegistry = /* @__PURE__ */ new Map();
|
|
50
51
|
import_react.Children.forEach(children, (child) => {
|
|
51
52
|
if ((0, import_is_component.isComponent)(child, import_BubbleLayer.BubbleLayer) || (0, import_is_component.isComponent)(child, import_DotLayer.DotLayer)) {
|
|
52
|
-
const { data } = child.props;
|
|
53
|
-
|
|
53
|
+
const { data, layerId } = child.props;
|
|
54
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
55
|
+
data.forEach((dataPoint, index) => {
|
|
56
|
+
lookup.set(index, dataPoint);
|
|
54
57
|
const extendedDataPoint = {
|
|
55
58
|
...dataPoint,
|
|
56
|
-
"layer-name":
|
|
59
|
+
"layer-name": layerId
|
|
57
60
|
};
|
|
58
61
|
const category = addCategory(
|
|
59
62
|
extendedDataPoint,
|
|
60
|
-
valueAccessors.get(
|
|
63
|
+
valueAccessors.get(layerId)
|
|
61
64
|
);
|
|
62
65
|
category && categoriesSet.add(category);
|
|
63
66
|
if (typeof category === "number") {
|
|
@@ -65,14 +68,14 @@ const extractLayersData = (children, valueAccessors) => {
|
|
|
65
68
|
}
|
|
66
69
|
flattenData = flattenData.concat(extendedDataPoint);
|
|
67
70
|
});
|
|
71
|
+
dataLookupRegistry.set(`source-${layerId}`, lookup);
|
|
68
72
|
} else if ((0, import_is_component.isComponent)(child, import_ConnectionLayer.ConnectionLayer)) {
|
|
69
|
-
const { data } = child.props;
|
|
73
|
+
const { data, layerId } = child.props;
|
|
74
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
70
75
|
data.forEach((connection, connectionIndex) => {
|
|
76
|
+
lookup.set(connectionIndex, connection);
|
|
71
77
|
if (connection.path.length >= 2) {
|
|
72
|
-
const category = addCategory(
|
|
73
|
-
connection,
|
|
74
|
-
valueAccessors.get(child.props.layerId)
|
|
75
|
-
);
|
|
78
|
+
const category = addCategory(connection, valueAccessors.get(layerId));
|
|
76
79
|
category && categoriesSet.add(category);
|
|
77
80
|
if (typeof category === "number") {
|
|
78
81
|
legendDomain = updateDomain(legendDomain, category);
|
|
@@ -82,24 +85,28 @@ const extractLayersData = (children, valueAccessors) => {
|
|
|
82
85
|
...path,
|
|
83
86
|
"connection-name": `connection-${connectionIndex + 1}`,
|
|
84
87
|
"connection-item-index": pathIndex,
|
|
85
|
-
"layer-name":
|
|
88
|
+
"layer-name": layerId
|
|
86
89
|
};
|
|
87
90
|
flattenData.push(parsedPath);
|
|
88
91
|
});
|
|
89
92
|
}
|
|
90
93
|
});
|
|
94
|
+
dataLookupRegistry.set(`source-${layerId}`, lookup);
|
|
91
95
|
} else if ((0, import_is_component.isComponent)(child, import_ChoroplethLayer.ChoroplethLayer)) {
|
|
92
|
-
const { data, regionAccessor } = child.props;
|
|
93
|
-
|
|
96
|
+
const { data, regionAccessor, layerId } = child.props;
|
|
97
|
+
const sourceId = layerId.replace("layer", "source");
|
|
98
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
99
|
+
data.forEach((dataEntry, index) => {
|
|
100
|
+
lookup.set(index, dataEntry);
|
|
94
101
|
const region = (0, import_lodash_es.isString)(regionAccessor) ? dataEntry[regionAccessor] : regionAccessor(dataEntry);
|
|
95
102
|
const choroplethLayerData = {
|
|
96
103
|
...dataEntry,
|
|
97
104
|
region,
|
|
98
|
-
"layer-name":
|
|
105
|
+
"layer-name": layerId
|
|
99
106
|
};
|
|
100
107
|
const category = addCategory(
|
|
101
108
|
choroplethLayerData,
|
|
102
|
-
valueAccessors.get(
|
|
109
|
+
valueAccessors.get(layerId)
|
|
103
110
|
);
|
|
104
111
|
category && categoriesSet.add(category);
|
|
105
112
|
if (typeof category === "number") {
|
|
@@ -107,11 +114,13 @@ const extractLayersData = (children, valueAccessors) => {
|
|
|
107
114
|
}
|
|
108
115
|
flattenData.push(choroplethLayerData);
|
|
109
116
|
});
|
|
117
|
+
dataLookupRegistry.set(sourceId, lookup);
|
|
110
118
|
}
|
|
111
119
|
});
|
|
112
120
|
return {
|
|
113
121
|
flattenData,
|
|
114
122
|
categories: [...categoriesSet],
|
|
115
|
-
legendDomain
|
|
123
|
+
legendDomain,
|
|
124
|
+
dataLookupRegistry
|
|
116
125
|
};
|
|
117
126
|
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var is_browser_firefox_exports = {};
|
|
20
|
+
__export(is_browser_firefox_exports, {
|
|
21
|
+
isFirefox: () => isFirefox
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(is_browser_firefox_exports);
|
|
24
|
+
function isFirefox() {
|
|
25
|
+
return typeof navigator !== "undefined" && navigator.userAgent.toLowerCase().includes("firefox");
|
|
26
|
+
}
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import type { MapGeoJSONFeature, MapLayerMouseEvent } from 'maplibre-gl';
|
|
2
|
+
import type { GeoDataLookupRegistry } from '../contexts/geo-data-lookup.context.js';
|
|
2
3
|
/**
|
|
3
|
-
* Extracts useful map features data for the tooltip
|
|
4
|
+
* Extracts useful map features data for the tooltip.
|
|
5
|
+
*
|
|
6
|
+
* When a data lookup registry is provided, the full original data
|
|
7
|
+
* is restored from the `__dataIndex` stored in GeoJSON properties.
|
|
8
|
+
* This allows GeoJSON features to carry only rendering-relevant
|
|
9
|
+
* fields while still providing full data for tooltips.
|
|
10
|
+
*
|
|
4
11
|
* @param features - map features
|
|
12
|
+
* @param registry - optional data lookup registry for restoring full data
|
|
5
13
|
*/
|
|
6
|
-
export declare const parseTooltipData: (features: MapGeoJSONFeature[]) => unknown[];
|
|
7
|
-
export declare const extractDataFromEvent: (event: MapLayerMouseEvent) => {
|
|
14
|
+
export declare const parseTooltipData: (features: MapGeoJSONFeature[], registry?: GeoDataLookupRegistry) => unknown[];
|
|
15
|
+
export declare const extractDataFromEvent: (event: MapLayerMouseEvent, registry?: GeoDataLookupRegistry) => {
|
|
8
16
|
featureId?: undefined;
|
|
9
17
|
hoveredLayerId?: undefined;
|
|
10
18
|
data?: undefined;
|
|
@@ -40,20 +40,35 @@ const parseFeatureProperties = (featureProperties) => {
|
|
|
40
40
|
}
|
|
41
41
|
return properties;
|
|
42
42
|
};
|
|
43
|
-
const
|
|
43
|
+
const resolveSourceId = (feature) => feature.source ?? feature.layer?.source;
|
|
44
|
+
const restoreDataFromLookup = (sourceId, dataIndex, registry) => {
|
|
45
|
+
if (registry === void 0 || sourceId === void 0 || dataIndex === void 0) {
|
|
46
|
+
return void 0;
|
|
47
|
+
}
|
|
48
|
+
const lookup = registry.get(sourceId);
|
|
49
|
+
return lookup?.get(dataIndex);
|
|
50
|
+
};
|
|
51
|
+
const parseTooltipData = (features, registry) => {
|
|
44
52
|
const data = [];
|
|
45
53
|
for (const feature of features) {
|
|
46
54
|
const properties = parseFeatureProperties(feature.properties);
|
|
47
|
-
const
|
|
55
|
+
const sourceId = resolveSourceId(feature);
|
|
56
|
+
const { __dataIndex, ...visibleProperties } = properties;
|
|
57
|
+
const dataIndex = typeof __dataIndex === "number" ? __dataIndex : void 0;
|
|
58
|
+
const originalData = restoreDataFromLookup(sourceId, dataIndex, registry);
|
|
59
|
+
const coordinates = feature.geometry.type === "Point" ? {
|
|
60
|
+
longitude: feature.geometry.coordinates[0],
|
|
61
|
+
latitude: feature.geometry.coordinates[1]
|
|
62
|
+
} : {};
|
|
48
63
|
data.push({
|
|
49
|
-
...
|
|
50
|
-
|
|
51
|
-
|
|
64
|
+
...visibleProperties,
|
|
65
|
+
...originalData !== void 0 ? { data: originalData } : {},
|
|
66
|
+
...coordinates
|
|
52
67
|
});
|
|
53
68
|
}
|
|
54
69
|
return data;
|
|
55
70
|
};
|
|
56
|
-
const extractDataFromEvent = (event) => {
|
|
71
|
+
const extractDataFromEvent = (event, registry) => {
|
|
57
72
|
if (!event.features?.length) {
|
|
58
73
|
return {};
|
|
59
74
|
}
|
|
@@ -62,7 +77,7 @@ const extractDataFromEvent = (event) => {
|
|
|
62
77
|
const hoveredFeatures = event.features.filter(
|
|
63
78
|
(feature2) => feature2.layer.id === hoveredLayerId
|
|
64
79
|
);
|
|
65
|
-
const data = parseTooltipData(hoveredFeatures);
|
|
80
|
+
const data = parseTooltipData(hoveredFeatures, registry);
|
|
66
81
|
return {
|
|
67
82
|
featureId: `${hoveredLayerId}-${feature.id}`,
|
|
68
83
|
hoveredLayerId,
|