@orioro/react-maplibre-util 0.3.2 → 0.5.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 CHANGED
@@ -1,5 +1,22 @@
1
1
  # @orioro/react-maplibre-util
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - implement onClick handler on LayeredMap layers; implement DynamicImage component and CustomSprite
8
+
9
+ ## 0.4.0
10
+
11
+ ### Minor Changes
12
+
13
+ - implement proof-of-concept of hover interaction on legend
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies
18
+ - @orioro/react-chart-util@0.2.0
19
+
3
20
  ## 0.3.2
4
21
 
5
22
  ### Patch Changes
package/README.md CHANGED
@@ -1 +0,0 @@
1
- # Template react lib
@@ -1,3 +1,2 @@
1
1
  import { MaplibreInspectOptions } from '@maplibre/maplibre-gl-inspect';
2
- import '@maplibre/maplibre-gl-inspect/dist/maplibre-gl-inspect.css';
3
2
  export declare function InspectControl(props: MaplibreInspectOptions): null;
@@ -0,0 +1,5 @@
1
+ type CustomSpriteProps = {
2
+ url: string;
3
+ };
4
+ export declare function CustomSprite({ url }: CustomSpriteProps): null;
5
+ export {};
@@ -0,0 +1 @@
1
+ export * from './CustomSprite';
@@ -0,0 +1,7 @@
1
+ import { Map, MapStyleImageMissingEvent, StyleImageMetadata } from 'maplibre-gl';
2
+ type OnGenerateImageRes = Parameters<Map['addImage']>[1] | [Parameters<Map['addImage']>[1], Partial<StyleImageMetadata>];
3
+ type DynamicImagesProps = {
4
+ onGenerateImage: (imageId: string, event: MapStyleImageMissingEvent) => OnGenerateImageRes | Promise<OnGenerateImageRes>;
5
+ };
6
+ export declare function DynamicImages({ onGenerateImage }: DynamicImagesProps): null;
7
+ export {};
@@ -0,0 +1,2 @@
1
+ export * from './DynamicImages';
2
+ export * from './svgImages';
@@ -0,0 +1 @@
1
+ export declare const MARKER = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<svg fill=\"#000000\" width=\"800px\" height=\"800px\" viewBox=\"-64 0 512 512\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M172.268 501.67C26.97 291.031 0 269.413 0 192 0 85.961 85.961 0 192 0s192 85.961 192 192c0 77.413-26.97 99.031-172.268 309.67-9.535 13.774-29.93 13.773-39.464 0z\"/></svg>";
@@ -0,0 +1,32 @@
1
+ import { StyleImageMetadata } from 'maplibre-gl';
2
+ type IconPathToSvgOptions = {
3
+ size?: number;
4
+ fill?: string;
5
+ stroke?: string;
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
+ export declare function svgIconGenerator(iconPathsById: Record<string, string>): (imageId: string) => Promise<[{
28
+ width: number;
29
+ height: number;
30
+ data: Uint8ClampedArray;
31
+ }, Partial<StyleImageMetadata>]>;
32
+ export {};
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { MapInstance } from 'react-map-gl/maplibre';
3
3
  import { LayeredMapProps } from '../types';
4
4
  import { augmentFeature, getSrcLayer, getSrcViewByLayerId } from './parseMapViews';
5
+ export declare function useLayeredMap(): null;
5
6
  export declare const LayeredMap: React.ForwardRefExoticComponent<Omit<LayeredMapProps, "ref"> & React.RefAttributes<{
6
7
  map: MapInstance;
7
8
  augmentFeature: (feature: Parameters<typeof augmentFeature>[1]) => ReturnType<typeof augmentFeature>;
@@ -1,2 +1,3 @@
1
1
  export * from './LayeredMap';
2
2
  export * from './parseMapViews';
3
+ export * from './layeredMapOnClickHandler';
@@ -0,0 +1,16 @@
1
+ import type { MapGeoJSONFeature, MapMouseEvent } from 'maplibre-gl';
2
+ import { Merge } from 'type-fest';
3
+ type ClickableFeature = Merge<MapGeoJSONFeature, {
4
+ layer: {
5
+ id: string;
6
+ onClick: (feature: MapGeoJSONFeature, event: AugmentedMouseEvent) => any;
7
+ };
8
+ }>;
9
+ type AugmentedMouseEvent = Merge<MapMouseEvent, {
10
+ features: ClickableFeature[];
11
+ }>;
12
+ type LayeredMapOnClickHandlerProps = {
13
+ resolveTargetFeature?: (features: AugmentedMouseEvent['features'], event: AugmentedMouseEvent) => ClickableFeature | Promise<ClickableFeature>;
14
+ };
15
+ export declare function layeredMapOnClickHandler({ resolveTargetFeature, }?: LayeredMapOnClickHandlerProps): (e: AugmentedMouseEvent) => Promise<void>;
16
+ export {};
@@ -1,5 +1,6 @@
1
1
  import { AnyLayer } from 'react-map-gl/dist/esm/exports-maplibre';
2
2
  import { MapView, MapViewLayer, MapViewSource } from '../types';
3
+ import { MapMouseEvent } from 'maplibre-gl';
3
4
  type ParsedSource = MapViewSource & {
4
5
  id: string;
5
6
  viewId: string;
@@ -7,6 +8,7 @@ type ParsedSource = MapViewSource & {
7
8
  type ParsedLayer = MapViewLayer & {
8
9
  id: string;
9
10
  viewId: string;
11
+ onClick?: (feature: GeoJSON.Feature, event: MapMouseEvent) => any;
10
12
  };
11
13
  export type MapViewsParseResult = {
12
14
  srcMapViews: MapView[];
@@ -41,5 +43,6 @@ export declare function augmentFeature(parsed: MapViewsParseResult, feature: Geo
41
43
  properties: import("geojson").GeoJsonProperties;
42
44
  bbox?: import("geojson").BBox | undefined;
43
45
  };
46
+ export declare function fmtLayerAbsoluteId(viewId: string, layerRelativeId: string): string;
44
47
  export declare function parseMapViews(orderedViews: MapView[], { existingLayers }?: ParseMapViewsOptions): MapViewsParseResult;
45
48
  export {};
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export * from './LayeredMap';
2
2
  export * from './HoverTooltip';
3
3
  export * from './MapWindow';
4
4
  export * from './SyncedMaps';
5
+ export * from './DynamicImages';
5
6
  export * from './useHover';
6
7
  export * from './scales';
7
8
  export * from './util';
package/dist/index.mjs CHANGED
@@ -1,11 +1,12 @@
1
- import { __assign, __spreadArray, __rest, __makeTemplateObject } from 'tslib';
2
- import React, { forwardRef, useRef, useMemo, useImperativeHandle, useState, useCallback, useLayoutEffect, useEffect, createRef } from 'react';
1
+ import { __assign, __spreadArray, __rest, __awaiter, __generator, __makeTemplateObject } from 'tslib';
2
+ import React, { forwardRef, useContext, createContext, useRef, useMemo, useImperativeHandle, useState, useCallback, useLayoutEffect, useEffect, createRef } from 'react';
3
3
  import { Map, Source, Layer, useMap, useControl } from 'react-map-gl/maplibre';
4
4
  import { isPlainObject, uniq, uniqBy, pick, omit } from 'lodash-es';
5
5
  import { Flex, useRefByKey, useLocalState, DropdownMenu } from '@orioro/react-ui-core';
6
6
  import styled from 'styled-components';
7
7
  import { usePrevious } from 'react-use';
8
8
  import { mergeRefs } from 'react-merge-refs';
9
+ import { strExpr } from '@orioro/util';
9
10
  import { ckmeans } from 'simple-statistics';
10
11
  import { schemeYlOrRd } from 'd3-scale-chromatic';
11
12
  import { maxIndex, range, variance, sum } from 'd3';
@@ -17,7 +18,6 @@ import { Tooltip } from '@radix-ui/themes';
17
18
  import maplibregl from 'maplibre-gl';
18
19
  import mlcontour from 'maplibre-contour';
19
20
  import MaplibreInspect from '@maplibre/maplibre-gl-inspect';
20
- import '@maplibre/maplibre-gl-inspect/dist/maplibre-gl-inspect.css';
21
21
 
22
22
  function sortLayers(layers, _a) {
23
23
  var existingLayers = _a.existingLayers;
@@ -53,7 +53,9 @@ function sortLayers(layers, _a) {
53
53
  }).map(function (layer, index, sortedLayers) {
54
54
  if (index === sortedLayers.length - 1) {
55
55
  // is last layer
56
- return layer;
56
+ return __assign(__assign({}, layer), {
57
+ beforeId: null
58
+ });
57
59
  } else {
58
60
  var beforeId = sortedLayers[index + 1].id;
59
61
  //
@@ -99,6 +101,9 @@ function augmentFeature(parsed, feature) {
99
101
  mapView: mapView
100
102
  });
101
103
  }
104
+ function fmtLayerAbsoluteId(viewId, layerRelativeId) {
105
+ return "".concat(viewId, "__").concat(layerRelativeId);
106
+ }
102
107
  function parseMapViews(orderedViews, _a) {
103
108
  var _b = _a === void 0 ? {} : _a,
104
109
  existingLayers = _b.existingLayers;
@@ -120,9 +125,10 @@ function parseMapViews(orderedViews, _a) {
120
125
  if (!layer) {
121
126
  return acc;
122
127
  }
123
- var layerId = layer.absoluteId ? layer.absoluteId : "".concat(viewId, "__").concat(layerRelativeId);
128
+ var layerId = layer.absoluteId ? layer.absoluteId : fmtLayerAbsoluteId(viewId, layerRelativeId);
129
+ // : `${viewId}__${layerRelativeId}`
124
130
  return {
125
- interactiveLayerIds: layer.interactive ? __spreadArray(__spreadArray([], acc.interactiveLayerIds, true), [layerId], false) : acc.interactiveLayerIds,
131
+ interactiveLayerIds: layer.interactive || typeof layer.onClick === 'function' ? __spreadArray(__spreadArray([], acc.interactiveLayerIds, true), [layerId], false) : acc.interactiveLayerIds,
126
132
  _layers: __spreadArray(__spreadArray([], acc._layers, true), [__assign(__assign({}, layer), {
127
133
  viewId: viewId,
128
134
  id: layerId,
@@ -173,6 +179,10 @@ var VIEW_AUGMENTED_EVENT_HANDLERS = ['onMouseDown', 'onMouseUp', 'onMouseOver',
173
179
  // 'onMouseEnter',
174
180
  // 'onMouseLeave',
175
181
  'onMouseMove', 'onMouseOut', 'onClick', 'onDblClick', 'onContextMenu'];
182
+ var LayeredMapContext = /*#__PURE__*/createContext(null);
183
+ function useLayeredMap() {
184
+ return useContext(LayeredMapContext);
185
+ }
176
186
  function useViewAugmentedEventHandlers(props, parsedMapViews) {
177
187
  var handlers = Object.fromEntries(VIEW_AUGMENTED_EVENT_HANDLERS.map(function (handlerName) {
178
188
  return typeof props[handlerName] === 'function' ? [handlerName, function (evt) {
@@ -209,7 +219,7 @@ var LayeredMap = /*#__PURE__*/forwardRef(function LayeredMapInner(_a, layeredMap
209
219
  };
210
220
  }, [views, mapRef.current]);
211
221
  var evtHandlers = useViewAugmentedEventHandlers(mapProps, parsed);
212
- useImperativeHandle(layeredMapRef, function () {
222
+ var imperativeHandle = useMemo(function () {
213
223
  return {
214
224
  map: mapRef.current,
215
225
  augmentFeature: augmentFeature.bind(null, parsed),
@@ -217,10 +227,15 @@ var LayeredMap = /*#__PURE__*/forwardRef(function LayeredMapInner(_a, layeredMap
217
227
  getSrcLayer: getSrcLayer.bind(null, parsed)
218
228
  };
219
229
  }, [mapRef.current, parsed]);
230
+ useImperativeHandle(layeredMapRef, function () {
231
+ return imperativeHandle;
232
+ }, [imperativeHandle]);
220
233
  return /*#__PURE__*/React.createElement(Map, __assign({
221
234
  ref: mapRef,
222
235
  interactiveLayerIds: __spreadArray(__spreadArray([], interactiveLayerIdsInput, true), parsed.interactiveLayerIds, true)
223
- }, mapProps, evtHandlers), children, parsed.sources.map(function (_a) {
236
+ }, mapProps, evtHandlers), /*#__PURE__*/React.createElement(LayeredMapContext.Provider, {
237
+ value: imperativeHandle
238
+ }, children, parsed.sources.map(function (_a) {
224
239
  var id = _a.id;
225
240
  _a.viewId;
226
241
  var source = __rest(_a, ["id", "viewId"]);
@@ -235,9 +250,48 @@ var LayeredMap = /*#__PURE__*/forwardRef(function LayeredMapInner(_a, layeredMap
235
250
  key: id,
236
251
  id: id
237
252
  }, layer));
238
- }));
253
+ })));
239
254
  });
240
255
 
256
+ function selectFirstClickableFeature(features) {
257
+ return features[0];
258
+ }
259
+ function layeredMapOnClickHandler(_a) {
260
+ var _b = _a === void 0 ? {} : _a,
261
+ _c = _b.resolveTargetFeature,
262
+ resolveTargetFeature = _c === void 0 ? selectFirstClickableFeature : _c;
263
+ return function onClick(e) {
264
+ return __awaiter(this, void 0, void 0, function () {
265
+ var features, clickableFeatures, targetFeature, _a;
266
+ return __generator(this, function (_b) {
267
+ switch (_b.label) {
268
+ case 0:
269
+ features = e.features || [];
270
+ clickableFeatures = features.filter(function (feature) {
271
+ var _a;
272
+ return typeof ((_a = feature.layer) === null || _a === void 0 ? void 0 : _a.onClick) === 'function';
273
+ });
274
+ if (!(clickableFeatures.length > 0)) return [3 /*break*/, 4];
275
+ if (!(clickableFeatures.length === 1)) return [3 /*break*/, 1];
276
+ _a = clickableFeatures[0];
277
+ return [3 /*break*/, 3];
278
+ case 1:
279
+ return [4 /*yield*/, resolveTargetFeature(clickableFeatures, e)];
280
+ case 2:
281
+ _a = _b.sent();
282
+ _b.label = 3;
283
+ case 3:
284
+ targetFeature = _a;
285
+ targetFeature.layer.onClick(targetFeature, e);
286
+ _b.label = 4;
287
+ case 4:
288
+ return [2 /*return*/];
289
+ }
290
+ });
291
+ });
292
+ };
293
+ }
294
+
241
295
  var Container = styled.div(templateObject_1$2 || (templateObject_1$2 = __makeTemplateObject(["\n pointer-events: none;\n position: absolute;\n z-index: 2;\n\n background: rgba(0, 0, 0, 0.5);\n border-radius: 16px;\n box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);\n backdrop-filter: blur(5px);\n -webkit-backdrop-filter: blur(5px);\n border: 1px solid rgba(0, 0, 0, 0.3);\n\n // background-color: black;\n color: white;\n border-radius: 5px;\n font-size: 0.9rem;\n\n max-width: 300px;\n\n hyphens: auto;\n word-break: break-word; /* Avoids overflow */\n overflow-wrap: break-word; /* Ensures long words break */\n white-space: normal;\n"], ["\n pointer-events: none;\n position: absolute;\n z-index: 2;\n\n background: rgba(0, 0, 0, 0.5);\n border-radius: 16px;\n box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);\n backdrop-filter: blur(5px);\n -webkit-backdrop-filter: blur(5px);\n border: 1px solid rgba(0, 0, 0, 0.3);\n\n // background-color: black;\n color: white;\n border-radius: 5px;\n font-size: 0.9rem;\n\n max-width: 300px;\n\n hyphens: auto;\n word-break: break-word; /* Avoids overflow */\n overflow-wrap: break-word; /* Ensures long words break */\n white-space: normal;\n"])));
242
296
  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"])));
243
297
  var DataSectionContainer = styled(Flex)(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n padding: 15px 10px;\n"], ["\n padding: 15px 10px;\n"])));
@@ -491,14 +545,12 @@ function mapSetFeaturesState(map, features, state) {
491
545
  return;
492
546
  }
493
547
  features.forEach(function (feat) {
494
- if (feat.id) {
548
+ if (typeof feat.id === 'number' || typeof feat.id === 'string') {
495
549
  map.setFeatureState({
496
550
  source: feat.source,
497
551
  sourceLayer: feat.sourceLayer,
498
552
  id: feat.id
499
553
  }, state);
500
- } else {
501
- console.warn("could not get feature id", feat);
502
554
  }
503
555
  });
504
556
  }
@@ -565,7 +617,10 @@ function useHover(props, deps) {
565
617
  onMouseOut: onMouseOut,
566
618
  onDragStart: onDragStart,
567
619
  onDragEnd: onDragEnd,
568
- cursor: isDragging ? 'grabbing' : ((_a = hoverInfo === null || hoverInfo === void 0 ? void 0 : hoverInfo.features) === null || _a === void 0 ? void 0 : _a.length) > 0 ? 'default' : 'grab',
620
+ cursor: 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) {
621
+ var _a;
622
+ return typeof ((_a = feat.layer) === null || _a === void 0 ? void 0 : _a.onClick) === 'function';
623
+ }) ? 'pointer' : 'default' : 'grab',
569
624
  children: isDragging ? null : /*#__PURE__*/React.createElement(React.Fragment, null, tooltip)
570
625
  }, hoverInfo, isDragging];
571
626
  }
@@ -842,6 +897,147 @@ var SyncedMaps = makeSyncedMaps({
842
897
  });
843
898
  var templateObject_1;
844
899
 
900
+ function DynamicImages(_a) {
901
+ var _this = this;
902
+ var onGenerateImage = _a.onGenerateImage;
903
+ var map = useMap().current;
904
+ useEffect(function () {
905
+ if (!map) return function () {};
906
+ var handler = function handler(event) {
907
+ return __awaiter(_this, void 0, void 0, function () {
908
+ var imageId, result, err_1;
909
+ return __generator(this, function (_a) {
910
+ switch (_a.label) {
911
+ case 0:
912
+ imageId = event.id;
913
+ if (map.hasImage(imageId)) return [2 /*return*/];
914
+ _a.label = 1;
915
+ case 1:
916
+ _a.trys.push([1, 3,, 4]);
917
+ return [4 /*yield*/, onGenerateImage(imageId, event)];
918
+ case 2:
919
+ result = _a.sent();
920
+ if (!map.hasImage(imageId)) {
921
+ if (Array.isArray(result)) {
922
+ map.addImage(imageId, result[0], result[1]);
923
+ } else {
924
+ map.addImage(imageId, result);
925
+ }
926
+ }
927
+ return [3 /*break*/, 4];
928
+ case 3:
929
+ err_1 = _a.sent();
930
+ console.error("Failed to generate image for \"".concat(imageId, "\""), err_1);
931
+ return [3 /*break*/, 4];
932
+ case 4:
933
+ return [2 /*return*/];
934
+ }
935
+ });
936
+ });
937
+ };
938
+ map.on('styleimagemissing', handler);
939
+ return function () {
940
+ return map.off('styleimagemissing', handler);
941
+ };
942
+ }, [map, onGenerateImage]);
943
+ return null;
944
+ }
945
+
946
+ function iconPathToSvg(path, _a) {
947
+ var _b = _a === void 0 ? {} : _a,
948
+ _c = _b.size,
949
+ size = _c === void 0 ? 24 : _c,
950
+ _d = _b.fill,
951
+ fill = _d === void 0 ? 'black' : _d,
952
+ stroke = _b.stroke,
953
+ strokeWidth = _b.strokeWidth,
954
+ _e = _b.viewBox,
955
+ viewBox = _e === void 0 ? '0 0 24 24' : _e,
956
+ style = _b.style;
957
+ if (path.startsWith('<svg')) {
958
+ return path;
959
+ }
960
+ var svgAttrs = ["xmlns=\"http://www.w3.org/2000/svg\"", "width=\"".concat(size, "\""), "height=\"".concat(size, "\""), "viewBox=\"".concat(viewBox, "\""), stroke ? "stroke=\"".concat(stroke, "\"") : '', strokeWidth ? "stroke-width=\"".concat(strokeWidth, "\"") : ''].filter(Boolean).join(' ');
961
+ var pathAttrs = ["fill=\"".concat(fill, "\""), style ? "style=\"".concat(style, "\"") : ''].filter(Boolean).join(' ');
962
+ return "<svg ".concat(svgAttrs, "><path ").concat(pathAttrs, " d=\"").concat(path, "\" /></svg>");
963
+ }
964
+ /**
965
+ * Renders an SVG string onto a canvas and returns an object compatible with maplibre `addImage`.
966
+ *
967
+ * @param svgString - The SVG markup as a string
968
+ * @param pixelRatio - (Optional) device pixel ratio, defaults to window.devicePixelRatio
969
+ * @returns Promise resolving to { width, height, data, pixelRatio }
970
+ */
971
+ function svgToMaplibreImage(svgString_1) {
972
+ return __awaiter(this, arguments, void 0, function (svgString, pixelRatio) {
973
+ if (pixelRatio === void 0) {
974
+ pixelRatio = typeof window !== 'undefined' ? window.devicePixelRatio : 1;
975
+ }
976
+ return __generator(this, function (_a) {
977
+ return [2 /*return*/, new Promise(function (resolve, reject) {
978
+ var svgBlob = new Blob([svgString], {
979
+ type: 'image/svg+xml'
980
+ });
981
+ var url = URL.createObjectURL(svgBlob);
982
+ var img = new Image();
983
+ img.onload = function () {
984
+ var width = img.width * pixelRatio;
985
+ var height = img.height * pixelRatio;
986
+ var canvas = document.createElement('canvas');
987
+ canvas.width = width;
988
+ canvas.height = height;
989
+ var ctx = canvas.getContext('2d');
990
+ ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
991
+ ctx.drawImage(img, 0, 0);
992
+ var imageData = ctx.getImageData(0, 0, width, height);
993
+ URL.revokeObjectURL(url);
994
+ resolve([{
995
+ width: width,
996
+ height: height,
997
+ data: imageData.data
998
+ }, {
999
+ pixelRatio: pixelRatio
1000
+ }]);
1001
+ };
1002
+ img.onerror = function () {
1003
+ URL.revokeObjectURL(url);
1004
+ reject(new Error('Failed to load SVG as image'));
1005
+ };
1006
+ img.src = url;
1007
+ })];
1008
+ });
1009
+ });
1010
+ }
1011
+ function svgIconId(iconId, options) {
1012
+ return options ? "".concat(iconId, "(").concat(JSON.stringify(options), ")") : iconId;
1013
+ }
1014
+ function svgIconGenerator(iconPathsById) {
1015
+ var fns = Object.fromEntries(Object.entries(iconPathsById).map(function (_a) {
1016
+ var iconId = _a[0],
1017
+ iconPath = _a[1];
1018
+ return [iconId, function (options) {
1019
+ if (options === void 0) {
1020
+ options = {};
1021
+ }
1022
+ return function () {
1023
+ return iconPathToSvg(iconPath, options);
1024
+ };
1025
+ }];
1026
+ }));
1027
+ var expr = strExpr({
1028
+ expressions: fns
1029
+ });
1030
+ return function onGenerateSvgImage(imageId) {
1031
+ return __awaiter(this, void 0, void 0, function () {
1032
+ var svg;
1033
+ return __generator(this, function (_a) {
1034
+ svg = expr.apply(imageId, undefined);
1035
+ return [2 /*return*/, svgToMaplibreImage(svg)];
1036
+ });
1037
+ });
1038
+ };
1039
+ }
1040
+
845
1041
  var DEFAULT_MIN_K = 3;
846
1042
  var DEFAULT_MAX_K = 9;
847
1043
  //
@@ -1361,4 +1557,4 @@ function InspectControl(props) {
1361
1557
  return null;
1362
1558
  }
1363
1559
 
1364
- export { $naturalBreaks, ControlContainer, HoverTooltip, InspectControl, LayeredMap, MapWindow, SyncedMaps, TerrainControl, applyReactStyle, augmentFeature, ensureAddLayer, ensureAddSource, ensureRemoveLayer, ensureRemoveSource, fitGeometry, getSrcLayer, getSrcViewByLayerId, hoverParseEvent, makeSyncedMaps, mapSetFeaturesState, naturalBreakBounds, parseMapViews, scaleNaturalBreaks, sortLayers, useClientRect, useHover, withHover };
1560
+ export { $naturalBreaks, ControlContainer, DynamicImages, HoverTooltip, InspectControl, LayeredMap, MapWindow, SyncedMaps, TerrainControl, applyReactStyle, augmentFeature, ensureAddLayer, ensureAddSource, ensureRemoveLayer, ensureRemoveSource, fitGeometry, fmtLayerAbsoluteId, getSrcLayer, getSrcViewByLayerId, hoverParseEvent, iconPathToSvg, layeredMapOnClickHandler, makeSyncedMaps, mapSetFeaturesState, naturalBreakBounds, parseMapViews, scaleNaturalBreaks, sortLayers, svgIconGenerator, svgIconId, svgToMaplibreImage, useClientRect, useHover, useLayeredMap, withHover };
package/dist/types.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Map } from 'react-map-gl/maplibre';
2
2
  import type { AnyLayer, AnySource } from 'react-map-gl/dist/esm/exports-maplibre';
3
+ import { MapGeoJSONFeature, MapMouseEvent } from 'maplibre-gl';
3
4
  export type MapViewSource = AnySource & {
4
5
  absoluteId?: string;
5
6
  };
@@ -9,6 +10,7 @@ export type MapViewLayer = Omit<AnyLayer, 'id'> & {
9
10
  source?: string;
10
11
  absoluteSourceId?: string;
11
12
  zIndex?: number;
13
+ onClick?: (feature: MapGeoJSONFeature, event: MapMouseEvent) => any;
12
14
  };
13
15
  type MapViewLegend = {
14
16
  type: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orioro/react-maplibre-util",
3
- "version": "0.3.2",
3
+ "version": "0.5.0",
4
4
  "packageManager": "yarn@4.0.2",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -50,11 +50,12 @@
50
50
  "@maplibre/maplibre-gl-inspect": "^1.7.1",
51
51
  "@mdi/js": "^7.4.47",
52
52
  "@mdi/react": "^1.6.1",
53
- "@orioro/react-chart-util": "^0.1.0",
53
+ "@orioro/react-chart-util": "^0.2.0",
54
54
  "@orioro/react-select": "^3.0.2",
55
55
  "@orioro/react-ui-core": "^0.0.6",
56
56
  "@orioro/resolve": "^0.1.2",
57
57
  "@orioro/scale-util": "^0.0.2",
58
+ "@orioro/util": "^0.13.0",
58
59
  "@turf/turf": "^7.2.0",
59
60
  "d3": "^7.9.0",
60
61
  "d3-scale-chromatic": "^3.1.0",