@orioro/react-maplibre-util 0.1.0 → 0.3.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,17 @@
1
1
  # @orioro/react-maplibre-util
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - better support for 3d, refactor view resolution framework
8
+
9
+ ## 0.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - implement 3D maps
14
+
3
15
  ## 0.1.0
4
16
 
5
17
  ### Minor Changes
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import maplibregl from 'maplibre-gl';
3
+ export type ControlContainerProps = {
4
+ /** Optional style for the outer container */
5
+ style?: React.CSSProperties;
6
+ /** Optional position in MapLibre control bar */
7
+ position?: maplibregl.ControlPosition;
8
+ /** Button content and props */
9
+ children: React.ReactNode;
10
+ };
11
+ export declare function ControlContainer({ style, position, children, }: ControlContainerProps): React.ReactPortal | null;
12
+ export declare namespace ControlContainer {
13
+ var Unstyled: typeof ControlContainerWithStyleReset;
14
+ }
15
+ declare function ControlContainerWithStyleReset({ style, ...props }: ControlContainerProps): React.JSX.Element;
16
+ export {};
@@ -0,0 +1,3 @@
1
+ import { MaplibreInspectOptions } from '@maplibre/maplibre-gl-inspect';
2
+ import '@maplibre/maplibre-gl-inspect/dist/maplibre-gl-inspect.css';
3
+ export declare function InspectControl(props: MaplibreInspectOptions): null;
@@ -0,0 +1 @@
1
+ export * from './InspectControl';
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import { ControlContainerProps } from '../ControlContainer';
3
+ import maplibregl from 'maplibre-gl';
4
+ import type { GlobalContourTileOptions } from 'maplibre-contour/dist/types';
5
+ type TerrainSettings = {
6
+ hillshade?: boolean;
7
+ enable3d?: boolean;
8
+ contours?: boolean;
9
+ };
10
+ type SourceSpecInput = Omit<maplibregl.RasterDEMSourceSpecification, 'type' | 'tiles' | 'url'> & {
11
+ url: string;
12
+ };
13
+ type TerrainControlProps = Omit<ControlContainerProps, 'children'> & {
14
+ value?: TerrainSettings | false;
15
+ onSetValue?: (v: TerrainSettings | false) => any;
16
+ demSourceId?: string;
17
+ demSource?: SourceSpecInput;
18
+ contourTileOptions?: Partial<GlobalContourTileOptions>;
19
+ };
20
+ export declare function TerrainControl({ value: externalValue, onSetValue: onSetExternalValue, demSourceId: DEM_SOURCE_ID, demSource: DEM_SOURCE_SPEC, contourTileOptions: contourTileOptionsInput, }: TerrainControlProps): React.JSX.Element;
21
+ export {};
@@ -0,0 +1 @@
1
+ export * from './TerrainControl';
@@ -0,0 +1,3 @@
1
+ export * from './ControlContainer';
2
+ export * from './TerrainControl';
3
+ export * from './InspectControl';
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
2
  import { FlexProps } from '@orioro/react-ui-core';
3
3
  type DataSectionProps = FlexProps & {
4
- title: string;
5
- entries: [React.ReactNode, React.ReactNode][];
4
+ title?: string;
5
+ entries?: [React.ReactNode, React.ReactNode][];
6
6
  };
7
7
  type HoverTooltipProps = {
8
8
  position: [number, number];
@@ -10,5 +10,6 @@ type HoverTooltipProps = {
10
10
  dataSections?: DataSectionProps[];
11
11
  style?: React.CSSProperties;
12
12
  };
13
+ export declare function useClientRect<T extends HTMLElement>(): readonly [DOMRect | null, (node: T | null) => void];
13
14
  export declare function HoverTooltip({ position, children, dataSections, style, }: HoverTooltipProps): React.JSX.Element;
14
15
  export {};
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { MarkerProps, ControlPosition } from 'react-map-gl/maplibre';
3
+ import { GeocoderOptions } from '@mapbox/mapbox-gl-geocoder';
4
+ import '@mapbox/mapbox-gl-geocoder/dist/mapbox-gl-geocoder.css';
5
+ type MapboxGeocoderControlProps = Omit<GeocoderOptions, 'accessToken' | 'mapboxgl' | 'marker'> & {
6
+ marker?: boolean | Omit<MarkerProps, 'longitude' | 'latitude'>;
7
+ position: ControlPosition;
8
+ onClear?: (e: object) => void;
9
+ onLoading?: (e: object) => void;
10
+ onResults?: (e: object) => void;
11
+ onResult?: (e: object) => void;
12
+ onError?: (e: object) => void;
13
+ [key: string]: any;
14
+ };
15
+ export declare function MapboxGeocoderControl({ position, types, onClear, onLoading, onResults, onResult, onError, accessToken, ...props }: MapboxGeocoderControlProps): React.ReactNode;
16
+ export {};
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ export declare function ResultMarker({ result, ...props }: {
3
+ [x: string]: any;
4
+ result: any;
5
+ }): React.JSX.Element | null;
@@ -0,0 +1 @@
1
+ export * from './MapboxGeocoderControl';
@@ -1,10 +1,12 @@
1
1
  import React from 'react';
2
2
  import { Map, MapInstance, MapMouseEvent } from 'react-map-gl/maplibre';
3
+ import { MapGeoJSONFeature } from 'maplibre-gl';
3
4
  type HoverInfo = {
4
5
  index: number;
5
6
  point: [number, number];
6
7
  coordinates: [number, number];
7
8
  event: MapMouseEvent;
9
+ features?: MapGeoJSONFeature[];
8
10
  };
9
11
  export declare function makeSyncedMaps({ components, }: {
10
12
  components: {
@@ -72,12 +74,12 @@ export declare function makeSyncedMaps({ components, }: {
72
74
  width: number;
73
75
  height: number;
74
76
  };
75
- mapStyle?: string | import("@maplibre/maplibre-gl-style-spec").StyleSpecification | import("react-map-gl/maplibre").ImmutableLike<import("@maplibre/maplibre-gl-style-spec").StyleSpecification>;
77
+ mapStyle?: string | import("maplibre-gl").StyleSpecification | import("react-map-gl/maplibre").ImmutableLike<import("maplibre-gl").StyleSpecification>;
76
78
  styleDiffing?: boolean;
77
- projection?: import("@maplibre/maplibre-gl-style-spec").ProjectionSpecification | "mercator" | "globe";
78
- light?: import("@maplibre/maplibre-gl-style-spec").LightSpecification;
79
- terrain?: import("@maplibre/maplibre-gl-style-spec").TerrainSpecification;
80
- sky?: import("@maplibre/maplibre-gl-style-spec").SkySpecification;
79
+ projection?: import("maplibre-gl").ProjectionSpecification | "mercator" | "globe";
80
+ light?: import("maplibre-gl").LightSpecification;
81
+ terrain?: import("maplibre-gl").TerrainSpecification;
82
+ sky?: import("maplibre-gl").SkySpecification;
81
83
  interactiveLayerIds?: string[];
82
84
  cursor?: string;
83
85
  } & import("@vis.gl/react-maplibre/dist/utils/set-globals").GlobalSettings & {
@@ -152,12 +154,12 @@ export declare function makeSyncedMaps({ components, }: {
152
154
  width: number;
153
155
  height: number;
154
156
  };
155
- mapStyle?: string | import("@maplibre/maplibre-gl-style-spec").StyleSpecification | import("react-map-gl/maplibre").ImmutableLike<import("@maplibre/maplibre-gl-style-spec").StyleSpecification>;
157
+ mapStyle?: string | import("maplibre-gl").StyleSpecification | import("react-map-gl/maplibre").ImmutableLike<import("maplibre-gl").StyleSpecification>;
156
158
  styleDiffing?: boolean;
157
- projection?: import("@maplibre/maplibre-gl-style-spec").ProjectionSpecification | "mercator" | "globe";
158
- light?: import("@maplibre/maplibre-gl-style-spec").LightSpecification;
159
- terrain?: import("@maplibre/maplibre-gl-style-spec").TerrainSpecification;
160
- sky?: import("@maplibre/maplibre-gl-style-spec").SkySpecification;
159
+ projection?: import("maplibre-gl").ProjectionSpecification | "mercator" | "globe";
160
+ light?: import("maplibre-gl").LightSpecification;
161
+ terrain?: import("maplibre-gl").TerrainSpecification;
162
+ sky?: import("maplibre-gl").SkySpecification;
161
163
  interactiveLayerIds?: string[];
162
164
  cursor?: string;
163
165
  } & import("@vis.gl/react-maplibre/dist/utils/set-globals").GlobalSettings & {
@@ -232,12 +234,12 @@ export declare const SyncedMaps: React.ForwardRefExoticComponent<Omit<Omit<{
232
234
  width: number;
233
235
  height: number;
234
236
  };
235
- mapStyle?: string | import("@maplibre/maplibre-gl-style-spec").StyleSpecification | import("react-map-gl/maplibre").ImmutableLike<import("@maplibre/maplibre-gl-style-spec").StyleSpecification>;
237
+ mapStyle?: string | import("maplibre-gl").StyleSpecification | import("react-map-gl/maplibre").ImmutableLike<import("maplibre-gl").StyleSpecification>;
236
238
  styleDiffing?: boolean;
237
- projection?: import("@maplibre/maplibre-gl-style-spec").ProjectionSpecification | "mercator" | "globe";
238
- light?: import("@maplibre/maplibre-gl-style-spec").LightSpecification;
239
- terrain?: import("@maplibre/maplibre-gl-style-spec").TerrainSpecification;
240
- sky?: import("@maplibre/maplibre-gl-style-spec").SkySpecification;
239
+ projection?: import("maplibre-gl").ProjectionSpecification | "mercator" | "globe";
240
+ light?: import("maplibre-gl").LightSpecification;
241
+ terrain?: import("maplibre-gl").TerrainSpecification;
242
+ sky?: import("maplibre-gl").SkySpecification;
241
243
  interactiveLayerIds?: string[];
242
244
  cursor?: string;
243
245
  } & import("@vis.gl/react-maplibre/dist/utils/set-globals").GlobalSettings & {
@@ -312,12 +314,12 @@ export declare const SyncedMaps: React.ForwardRefExoticComponent<Omit<Omit<{
312
314
  width: number;
313
315
  height: number;
314
316
  };
315
- mapStyle?: string | import("@maplibre/maplibre-gl-style-spec").StyleSpecification | import("react-map-gl/maplibre").ImmutableLike<import("@maplibre/maplibre-gl-style-spec").StyleSpecification>;
317
+ mapStyle?: string | import("maplibre-gl").StyleSpecification | import("react-map-gl/maplibre").ImmutableLike<import("maplibre-gl").StyleSpecification>;
316
318
  styleDiffing?: boolean;
317
- projection?: import("@maplibre/maplibre-gl-style-spec").ProjectionSpecification | "mercator" | "globe";
318
- light?: import("@maplibre/maplibre-gl-style-spec").LightSpecification;
319
- terrain?: import("@maplibre/maplibre-gl-style-spec").TerrainSpecification;
320
- sky?: import("@maplibre/maplibre-gl-style-spec").SkySpecification;
319
+ projection?: import("maplibre-gl").ProjectionSpecification | "mercator" | "globe";
320
+ light?: import("maplibre-gl").LightSpecification;
321
+ terrain?: import("maplibre-gl").TerrainSpecification;
322
+ sky?: import("maplibre-gl").SkySpecification;
321
323
  interactiveLayerIds?: string[];
322
324
  cursor?: string;
323
325
  } & import("@vis.gl/react-maplibre/dist/utils/set-globals").GlobalSettings & {
package/dist/index.d.ts CHANGED
@@ -6,3 +6,4 @@ export * from './useHover';
6
6
  export * from './scales';
7
7
  export * from './util';
8
8
  export * from './types';
9
+ export * from './Controls';
package/dist/index.mjs CHANGED
@@ -1,14 +1,23 @@
1
1
  import { __assign, __spreadArray, __rest, __makeTemplateObject } from 'tslib';
2
- import React, { forwardRef, useRef, useMemo, useImperativeHandle, useEffect, createRef, useState, useCallback } from 'react';
3
- import { Map, Source, Layer, useMap } from 'react-map-gl/maplibre';
4
- import { isPlainObject, uniq, uniqBy, pick } from 'lodash-es';
5
- import { Flex, useRefByKey } from '@orioro/react-ui-core';
2
+ import React, { forwardRef, useRef, useMemo, useImperativeHandle, useState, useCallback, useLayoutEffect, useEffect, createRef } from 'react';
3
+ import { Map, Source, Layer, useMap, useControl } from 'react-map-gl/maplibre';
4
+ import { isPlainObject, uniq, uniqBy, pick, omit } from 'lodash-es';
5
+ import { Flex, useRefByKey, useLocalState, DropdownMenu } from '@orioro/react-ui-core';
6
6
  import styled from 'styled-components';
7
+ import { usePrevious } from 'react-use';
7
8
  import { mergeRefs } from 'react-merge-refs';
8
9
  import { ckmeans } from 'simple-statistics';
9
10
  import { schemeYlOrRd } from 'd3-scale-chromatic';
10
11
  import { maxIndex, range, variance, sum } from 'd3';
11
12
  import { bbox } from '@turf/turf';
13
+ import { createPortal } from 'react-dom';
14
+ import { mdiCheck, mdiTerrain, mdiVideo3d } from '@mdi/js';
15
+ import { Icon } from '@mdi/react';
16
+ import { Tooltip } from '@radix-ui/themes';
17
+ import maplibregl from 'maplibre-gl';
18
+ import mlcontour from 'maplibre-contour';
19
+ import MaplibreInspect from '@maplibre/maplibre-gl-inspect';
20
+ import '@maplibre/maplibre-gl-inspect/dist/maplibre-gl-inspect.css';
12
21
 
13
22
  function sortLayers(layers, _a) {
14
23
  var existingLayers = _a.existingLayers;
@@ -181,9 +190,8 @@ var LayeredMap = /*#__PURE__*/forwardRef(function LayeredMapInner(_a, layeredMap
181
190
  var views = _a.views,
182
191
  _b = _a.interactiveLayerIds,
183
192
  interactiveLayerIdsInput = _b === void 0 ? [] : _b,
184
- children = _a.children;
185
- _a.hover;
186
- var mapProps = __rest(_a, ["views", "interactiveLayerIds", "children", "hover"]);
193
+ children = _a.children,
194
+ mapProps = __rest(_a, ["views", "interactiveLayerIds", "children"]);
187
195
  var mapRef = useRef(null);
188
196
  //
189
197
  // Parse sources, layers and interactiveLayerIds from
@@ -233,15 +241,15 @@ var LayeredMap = /*#__PURE__*/forwardRef(function LayeredMapInner(_a, layeredMap
233
241
  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"])));
234
242
  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"])));
235
243
  var DataSectionContainer = styled(Flex)(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n padding: 15px 10px;\n"], ["\n padding: 15px 10px;\n"])));
236
- var EntriesList = styled.ul(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n padding: 0;\n list-style: none;\n margin-bottom: 0;\n > li + li {\n margin-top: 4px;\n }\n // padding: 10px;\n"], ["\n padding: 0;\n list-style: none;\n margin-bottom: 0;\n > li + li {\n margin-top: 4px;\n }\n // padding: 10px;\n"])));
244
+ 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"])));
237
245
  function DataSection(_a) {
238
246
  var title = _a.title,
239
247
  entries = _a.entries,
240
248
  props = __rest(_a, ["title", "entries"]);
241
- return entries.length > 0 && (/*#__PURE__*/React.createElement(DataSectionContainer, __assign({
249
+ return Array.isArray(entries) && entries.length > 0 && (/*#__PURE__*/React.createElement(DataSectionContainer, __assign({
242
250
  direction: "column",
243
251
  gap: "10px"
244
- }, props), title && /*#__PURE__*/React.createElement(DataSectionHeading, null, title), /*#__PURE__*/React.createElement(EntriesList, null, entries.map(function (_a, index) {
252
+ }, props), title && /*#__PURE__*/React.createElement(DataSectionHeading, null, title), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(EntriesList, null, entries.map(function (_a, index) {
245
253
  var label = _a[0],
246
254
  value = _a[1];
247
255
  return /*#__PURE__*/React.createElement("li", {
@@ -251,19 +259,88 @@ function DataSection(_a) {
251
259
  fontWeight: 'bold'
252
260
  }
253
261
  }, value)) : value);
254
- }))));
262
+ })))));
263
+ }
264
+ function useMaxValue(initial) {
265
+ var maxRef = useRef(initial);
266
+ var applyMax = function applyMax(value) {
267
+ if (value > maxRef.current) {
268
+ maxRef.current = value;
269
+ }
270
+ return maxRef.current;
271
+ };
272
+ return applyMax;
273
+ }
274
+ function useClientRect() {
275
+ var _a = useState(null),
276
+ rect = _a[0],
277
+ setRect = _a[1];
278
+ var ref = useCallback(function (node) {
279
+ if (node !== null) {
280
+ setRect(node.getBoundingClientRect());
281
+ }
282
+ }, []);
283
+ useLayoutEffect(function () {
284
+ var handleResize = function handleResize() {
285
+ if (ref.current) {
286
+ setRect(ref.current.getBoundingClientRect());
287
+ }
288
+ };
289
+ window.addEventListener('resize', handleResize);
290
+ return function () {
291
+ return window.removeEventListener('resize', handleResize);
292
+ };
293
+ }, []);
294
+ return [rect, ref];
255
295
  }
296
+ var PADDING = 15;
297
+ var Y_OFFSET = -20;
256
298
  function HoverTooltip(_a) {
257
299
  var position = _a.position,
258
300
  children = _a.children,
259
301
  dataSections = _a.dataSections,
260
302
  _b = _a.style,
261
303
  style = _b === void 0 ? {} : _b;
304
+ var ref = useRef(null);
305
+ var applyMaxW = useMaxValue(0);
306
+ var applyMaxY = useMaxValue(0);
307
+ var prevRef = usePrevious(ref.current);
308
+ var positioning = useMemo(function () {
309
+ var _a;
310
+ if (!ref.current) {
311
+ return {
312
+ opacity: 0
313
+ };
314
+ }
315
+ var rect = ref.current.getBoundingClientRect();
316
+ var parentRect = (_a = ref.current.offsetParent) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
317
+ if (!parentRect) {
318
+ console.warn('could not find parentRect for HoverTooltip');
319
+ return {
320
+ opacity: 0
321
+ };
322
+ }
323
+ var maxW = applyMaxW((rect === null || rect === void 0 ? void 0 : rect.width) || 0);
324
+ var maxH = applyMaxY((rect === null || rect === void 0 ? void 0 : rect.height) || 0);
325
+ var translateX = position[0] + maxW + PADDING * 2 < parentRect.width ? 'translateX(0)' : "translateX(calc(-100% - ".concat(2 * PADDING, "px))");
326
+ var translateY = position[1] + maxH + PADDING * 2 + Y_OFFSET < parentRect.height ? 'translateY(0)' : "translateY(calc(-100% + ".concat(PADDING, "px + ").concat(-1 * Y_OFFSET, "px)");
327
+ return {
328
+ left: position[0] + PADDING,
329
+ top: position[1] + Y_OFFSET,
330
+ transform: "".concat(translateX, " ").concat(translateY),
331
+ //
332
+ // If previous ref was not set, it means
333
+ // that this is the first time the component
334
+ // is being rendered, thus do not animate
335
+ //
336
+ transition: !prevRef ? 'none' : 'transform .3s ease'
337
+ };
338
+ }, [position]);
262
339
  return /*#__PURE__*/React.createElement(Container, {
263
- style: __assign({
264
- left: position[0] + 15,
265
- top: position[1] - 20
266
- }, style)
340
+ ref: ref,
341
+ style: __assign(__assign(__assign({}, positioning), {
342
+ minWidth: 200
343
+ }), style)
267
344
  }, Array.isArray(dataSections) && dataSections.length > 0 && (/*#__PURE__*/React.createElement(Flex, {
268
345
  direction: "column"
269
346
  }, dataSections.map(function (section, index) {
@@ -274,7 +351,6 @@ function HoverTooltip(_a) {
274
351
  width: '100%',
275
352
  margin: 0,
276
353
  borderBottom: '1px solid currentColor'
277
- // marginBottom: 'none',
278
354
  }
279
355
  })));
280
356
  }))), children);
@@ -362,7 +438,6 @@ var MapWindow = /*#__PURE__*/forwardRef(function MapWindowInner(_a, externalRef)
362
438
  mapReady = _c[0],
363
439
  setMapReady = _c[1];
364
440
  var parentMapRef = useMap();
365
- console.log('parentMapRef', parentMapRef);
366
441
  useSyncedMaps(parentMapRef, mapRef, {
367
442
  centerOffsetPixels: centerOffsetPixels
368
443
  }, [centerOffsetPixels, mapReady]);
@@ -401,134 +476,6 @@ var MapWindow = /*#__PURE__*/forwardRef(function MapWindowInner(_a, externalRef)
401
476
  var GhostCursor = styled.div(templateObject_1$1 || (templateObject_1$1 = __makeTemplateObject(["\n --synced-maps-ghost-cursor-size: 24px;\n position: absolute;\n\n height: 0;\n width: 0;\n color: inherit;\n\n &::before {\n content: '';\n display: block;\n background-color: currentColor;\n width: 1px;\n height: var(--synced-maps-ghost-cursor-size);\n position: absolute;\n top: calc(-1 * (var(--synced-maps-ghost-cursor-size) / 2));\n left: 0;\n }\n\n &::after {\n content: '';\n display: block;\n background-color: currentColor;\n height: 1px;\n width: var(--synced-maps-ghost-cursor-size);\n position: absolute;\n left: calc(-1 * (var(--synced-maps-ghost-cursor-size) / 2));\n top: 0;\n }\n"], ["\n --synced-maps-ghost-cursor-size: 24px;\n position: absolute;\n\n height: 0;\n width: 0;\n color: inherit;\n\n &::before {\n content: '';\n display: block;\n background-color: currentColor;\n width: 1px;\n height: var(--synced-maps-ghost-cursor-size);\n position: absolute;\n top: calc(-1 * (var(--synced-maps-ghost-cursor-size) / 2));\n left: 0;\n }\n\n &::after {\n content: '';\n display: block;\n background-color: currentColor;\n height: 1px;\n width: var(--synced-maps-ghost-cursor-size);\n position: absolute;\n left: calc(-1 * (var(--synced-maps-ghost-cursor-size) / 2));\n top: 0;\n }\n"])));
402
477
  var templateObject_1$1;
403
478
 
404
- function parseHoverInfo(index, event) {
405
- return {
406
- index: index,
407
- point: [event.point.x, event.point.y],
408
- coordinates: [event.lngLat.lng, event.lngLat.lat],
409
- event: event
410
- };
411
- }
412
- var SingleMapContainer = styled.div(templateObject_1 || (templateObject_1 = __makeTemplateObject([""], [""])));
413
- function makeSyncedMaps(_a) {
414
- var components = _a.components;
415
- var MapComponent = components.Map;
416
- return /*#__PURE__*/forwardRef(function SyncedMaps(_a, ref) {
417
- var maps = _a.maps,
418
- style = _a.style,
419
- initialViewState = _a.initialViewState,
420
- children = _a.children,
421
- getTooltip = _a.tooltip,
422
- baseMapProps = __rest(_a, ["maps", "style", "initialViewState", "children", "tooltip"]);
423
- var _b = useRefByKey(),
424
- mapInstanceRefs = _b[0],
425
- setMapInstanceRef = _b[1];
426
- var containerRef = useRef(null);
427
- var _c = useState(initialViewState),
428
- viewState = _c[0],
429
- setViewState = _c[1];
430
- var onSyncMove = useCallback(function (evt) {
431
- return setViewState(evt.viewState);
432
- }, []);
433
- var _d = useState(false),
434
- isDragging = _d[0],
435
- setIsDragging = _d[1];
436
- var onDragStart = useCallback(function () {
437
- return setIsDragging(true);
438
- }, [setIsDragging]);
439
- var onDragEnd = useCallback(function () {
440
- return setIsDragging(false);
441
- }, [setIsDragging]);
442
- var _e = useState(null),
443
- hoverInfo = _e[0],
444
- setHoverInfo = _e[1];
445
- var _f = useState(null),
446
- tooltips = _f[0],
447
- setTooltips = _f[1];
448
- var _onMouseMove = useCallback(function (index, event) {
449
- var nextHoverInfo = parseHoverInfo(index, event);
450
- setHoverInfo(nextHoverInfo);
451
- setTooltips(typeof getTooltip === 'function' ? maps.map(function (_a, index) {
452
- var _b = _a.tooltip,
453
- tooltip = _b === void 0 ? true : _b;
454
- if (!tooltip) {
455
- return null;
456
- }
457
- return getTooltip(nextHoverInfo, mapInstanceRefs[index]) || null;
458
- }) : null);
459
- }, [maps]);
460
- //
461
- // Expose map instances
462
- //
463
- useImperativeHandle(ref, function () {
464
- return {
465
- mapInstances: mapInstanceRefs
466
- };
467
- }, [mapInstanceRefs]);
468
- return /*#__PURE__*/React.createElement(Flex, {
469
- ref: containerRef,
470
- direction: "row",
471
- style: __assign({
472
- position: 'relative'
473
- }, style || {})
474
- }, maps.map(function (mapProps, index) {
475
- return /*#__PURE__*/React.createElement(SingleMapContainer, {
476
- key: mapProps.id || index,
477
- style: {
478
- position: 'absolute',
479
- top: 0,
480
- height: '100%',
481
- left: "calc(".concat(index, " * (100% / ").concat(maps.length, "))"),
482
- width: "calc(100% / ".concat(maps.length, ")")
483
- }
484
- }, !isDragging && hoverInfo && hoverInfo.index !== index ? (/*#__PURE__*/React.createElement(GhostCursor, {
485
- style: {
486
- position: 'absolute',
487
- left: hoverInfo.point[0],
488
- top: hoverInfo.point[1],
489
- zIndex: 2
490
- }
491
- })) : null, !isDragging && Array.isArray(tooltips) && tooltips[index], /*#__PURE__*/React.createElement(MapComponent, __assign({
492
- ref: setMapInstanceRef(index),
493
- cursor: isDragging ? 'grabbing' : 'default'
494
- }, baseMapProps, mapProps, viewState || {}, {
495
- style: __assign(__assign({}, mapProps.style || {}), {
496
- position: 'absolute',
497
- top: 0,
498
- left: 0,
499
- width: '100%',
500
- height: '100%'
501
- }),
502
- onMove: onSyncMove,
503
- onDragStart: onDragStart,
504
- onDragEnd: onDragEnd,
505
- onMouseMove: function onMouseMove(event) {
506
- return _onMouseMove(index, event);
507
- },
508
- //
509
- // There is no notion of mouseenter/mouseleave
510
- // in maplibre.gl.
511
- //
512
- // Use onMouseOut instead
513
- //
514
- // https://github.com/mapbox/mapbox-gl-js/issues/10594
515
- // https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapEventType/#mouseout
516
- //
517
- onMouseOut: function onMouseOut() {
518
- setHoverInfo(null);
519
- setTooltips(null);
520
- }
521
- })));
522
- }), children);
523
- });
524
- }
525
- var SyncedMaps = makeSyncedMaps({
526
- components: {
527
- Map: Map
528
- }
529
- });
530
- var templateObject_1;
531
-
532
479
  function hoverParseEvent(event) {
533
480
  return {
534
481
  point: [event.point.x, event.point.y],
@@ -539,6 +486,22 @@ function hoverParseEvent(event) {
539
486
  var DEFAULT_PROPS = {
540
487
  parseEvent: hoverParseEvent
541
488
  };
489
+ function mapSetFeaturesState(map, features, state) {
490
+ if (!Array.isArray(features)) {
491
+ return;
492
+ }
493
+ features.forEach(function (feat) {
494
+ if (feat.id) {
495
+ map.setFeatureState({
496
+ source: feat.source,
497
+ sourceLayer: feat.sourceLayer,
498
+ id: feat.id
499
+ }, state);
500
+ } else {
501
+ console.warn("could not get feature id", feat);
502
+ }
503
+ });
504
+ }
542
505
  function useHover(props, deps) {
543
506
  var _a;
544
507
  if (props === void 0) {
@@ -549,8 +512,9 @@ function useHover(props, deps) {
549
512
  isDragging = _b[0],
550
513
  setIsDragging = _b[1];
551
514
  var onDragStart = useCallback(function () {
552
- return setIsDragging(true);
553
- }, [setIsDragging]);
515
+ setTooltip(null);
516
+ setIsDragging(true);
517
+ }, []);
554
518
  var onDragEnd = useCallback(function () {
555
519
  return setIsDragging(false);
556
520
  }, [setIsDragging]);
@@ -562,8 +526,21 @@ function useHover(props, deps) {
562
526
  setHoverInfo = _d[1];
563
527
  var onMouseMove = useCallback(function (event) {
564
528
  var nextHoverInfo = props.parseEvent(event);
565
- setHoverInfo(nextHoverInfo);
566
529
  setTooltip(props.tooltip ? props.tooltip(nextHoverInfo) : null);
530
+ var map = event.target;
531
+ setHoverInfo(function (prevHoverInfo) {
532
+ if (Array.isArray(prevHoverInfo === null || prevHoverInfo === void 0 ? void 0 : prevHoverInfo.features)) {
533
+ mapSetFeaturesState(map, prevHoverInfo.features, {
534
+ hover: false
535
+ });
536
+ }
537
+ if (Array.isArray(nextHoverInfo === null || nextHoverInfo === void 0 ? void 0 : nextHoverInfo.features)) {
538
+ mapSetFeaturesState(map, nextHoverInfo.features, {
539
+ hover: true
540
+ });
541
+ }
542
+ return nextHoverInfo;
543
+ });
567
544
  }, __spreadArray(__spreadArray([], deps, true), [props.tooltip], false));
568
545
  //
569
546
  // There is no notion of mouseenter/mouseleave
@@ -574,10 +551,15 @@ function useHover(props, deps) {
574
551
  // https://github.com/mapbox/mapbox-gl-js/issues/10594
575
552
  // https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapEventType/#mouseout
576
553
  //
577
- var onMouseOut = useCallback(function () {
554
+ var onMouseOut = useCallback(function (event) {
578
555
  setHoverInfo(null);
579
556
  setTooltip(null);
580
- }, [setHoverInfo, setTooltip]);
557
+ if (Array.isArray(hoverInfo === null || hoverInfo === void 0 ? void 0 : hoverInfo.features)) {
558
+ mapSetFeaturesState(event.target, hoverInfo.features, {
559
+ hover: false
560
+ });
561
+ }
562
+ }, [setHoverInfo, setTooltip, hoverInfo]);
581
563
  return [{
582
564
  onMouseMove: onMouseMove,
583
565
  onMouseOut: onMouseOut,
@@ -655,6 +637,15 @@ function _objectWithoutPropertiesLoose(r, e) {
655
637
  function _slicedToArray(r, e) {
656
638
  return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
657
639
  }
640
+ function _typeof(o) {
641
+ "@babel/helpers - typeof";
642
+
643
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
644
+ return typeof o;
645
+ } : function (o) {
646
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
647
+ }, _typeof(o);
648
+ }
658
649
  function _unsupportedIterableToArray(r, a) {
659
650
  if (r) {
660
651
  if ("string" == typeof r) return _arrayLikeToArray(r, a);
@@ -698,6 +689,159 @@ function withHover(Component, withHoverProps) {
698
689
  });
699
690
  }
700
691
 
692
+ function parseHoverInfo(index, event) {
693
+ return {
694
+ index: index,
695
+ point: [event.point.x, event.point.y],
696
+ coordinates: [event.lngLat.lng, event.lngLat.lat],
697
+ event: event,
698
+ features: event.features
699
+ };
700
+ }
701
+ var SingleMapContainer = styled.div(templateObject_1 || (templateObject_1 = __makeTemplateObject([""], [""])));
702
+ function makeSyncedMaps(_a) {
703
+ var components = _a.components;
704
+ var MapComponent = components.Map;
705
+ return /*#__PURE__*/forwardRef(function SyncedMaps(_a, ref) {
706
+ var maps = _a.maps,
707
+ style = _a.style,
708
+ initialViewState = _a.initialViewState,
709
+ children = _a.children,
710
+ getTooltip = _a.tooltip,
711
+ baseMapProps = __rest(_a, ["maps", "style", "initialViewState", "children", "tooltip"]);
712
+ var _b = useRefByKey(),
713
+ mapInstanceRefs = _b[0],
714
+ setMapInstanceRef = _b[1];
715
+ var containerRef = useRef(null);
716
+ var _c = useState(initialViewState),
717
+ viewState = _c[0],
718
+ setViewState = _c[1];
719
+ var onSyncMove = useCallback(function (evt) {
720
+ return setViewState(evt.viewState);
721
+ }, []);
722
+ var _d = useState(false),
723
+ isDragging = _d[0],
724
+ setIsDragging = _d[1];
725
+ var onDragEnd = useCallback(function () {
726
+ return setIsDragging(false);
727
+ }, [setIsDragging]);
728
+ var _e = useState(null),
729
+ hoverInfo = _e[0],
730
+ setHoverInfo = _e[1];
731
+ var _f = useState(null),
732
+ tooltips = _f[0],
733
+ setTooltips = _f[1];
734
+ var onDragStart = useCallback(function () {
735
+ setIsDragging(true);
736
+ setTooltips(null);
737
+ }, []);
738
+ var _onMouseMove = useCallback(function (index, event) {
739
+ var nextHoverInfo = parseHoverInfo(index, event);
740
+ setHoverInfo(function (prevHoverInfo) {
741
+ mapSetFeaturesState(event.target, prevHoverInfo === null || prevHoverInfo === void 0 ? void 0 : prevHoverInfo.features, {
742
+ hover: false
743
+ });
744
+ mapSetFeaturesState(event.target, nextHoverInfo === null || nextHoverInfo === void 0 ? void 0 : nextHoverInfo.features, {
745
+ hover: true
746
+ });
747
+ return nextHoverInfo;
748
+ });
749
+ setTooltips(typeof getTooltip === 'function' ? maps.map(function (_a, index) {
750
+ var _b = _a.tooltip,
751
+ tooltip = _b === void 0 ? true : _b;
752
+ if (!tooltip) {
753
+ return null;
754
+ }
755
+ return getTooltip(nextHoverInfo, mapInstanceRefs[index]) || null;
756
+ }) : null);
757
+ }, [maps]);
758
+ //
759
+ // There is no notion of mouseenter/mouseleave
760
+ // in maplibre.gl.
761
+ //
762
+ // Use onMouseOut instead
763
+ //
764
+ // https://github.com/mapbox/mapbox-gl-js/issues/10594
765
+ // https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapEventType/#mouseout
766
+ //
767
+ var onMouseOut = useCallback(function (event) {
768
+ setHoverInfo(null);
769
+ setTooltips(null);
770
+ if (Array.isArray(hoverInfo === null || hoverInfo === void 0 ? void 0 : hoverInfo.features)) {
771
+ mapSetFeaturesState(event.target, hoverInfo.features, {
772
+ hover: false
773
+ });
774
+ }
775
+ }, [setHoverInfo, setTooltips, hoverInfo]);
776
+ //
777
+ // Expose map instances
778
+ //
779
+ useImperativeHandle(ref, function () {
780
+ return {
781
+ mapInstances: mapInstanceRefs
782
+ };
783
+ }, [mapInstanceRefs]);
784
+ return /*#__PURE__*/React.createElement(Flex, {
785
+ ref: containerRef,
786
+ direction: "row",
787
+ style: __assign({
788
+ position: 'relative'
789
+ }, style || {})
790
+ }, maps.map(function (mapProps, index) {
791
+ return /*#__PURE__*/React.createElement(SingleMapContainer, {
792
+ key: mapProps.id || index,
793
+ style: {
794
+ position: 'absolute',
795
+ top: 0,
796
+ height: '100%',
797
+ left: "calc(".concat(index, " * (100% / ").concat(maps.length, "))"),
798
+ width: "calc(100% / ".concat(maps.length, ")")
799
+ }
800
+ }, !isDragging && hoverInfo && hoverInfo.index !== index ? (/*#__PURE__*/React.createElement(GhostCursor, {
801
+ style: {
802
+ position: 'absolute',
803
+ left: hoverInfo.point[0],
804
+ top: hoverInfo.point[1],
805
+ zIndex: 2
806
+ }
807
+ })) : null, Array.isArray(tooltips) && tooltips[index], /*#__PURE__*/React.createElement(MapComponent, __assign({
808
+ ref: setMapInstanceRef(index),
809
+ cursor: isDragging ? 'grabbing' : 'default'
810
+ }, baseMapProps, mapProps, maps.length > 1 ? viewState || {} : {}, {
811
+ style: __assign(__assign({}, mapProps.style || {}), {
812
+ position: 'absolute',
813
+ top: 0,
814
+ left: 0,
815
+ width: '100%',
816
+ height: '100%'
817
+ }),
818
+ onMove: onSyncMove,
819
+ onDragStart: onDragStart,
820
+ onDragEnd: onDragEnd,
821
+ onMouseMove: function onMouseMove(event) {
822
+ return _onMouseMove(index, event);
823
+ },
824
+ //
825
+ // There is no notion of mouseenter/mouseleave
826
+ // in maplibre.gl.
827
+ //
828
+ // Use onMouseOut instead
829
+ //
830
+ // https://github.com/mapbox/mapbox-gl-js/issues/10594
831
+ // https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapEventType/#mouseout
832
+ //
833
+ onMouseOut: onMouseOut
834
+ })));
835
+ }), children);
836
+ });
837
+ }
838
+ var SyncedMaps = makeSyncedMaps({
839
+ components: {
840
+ Map: Map
841
+ }
842
+ });
843
+ var templateObject_1;
844
+
701
845
  var DEFAULT_MIN_K = 3;
702
846
  var DEFAULT_MAX_K = 9;
703
847
  //
@@ -805,4 +949,416 @@ function fitGeometry(map, geo, options) {
805
949
  return map.fitBounds([[bounds[0], bounds[1]], [bounds[2], bounds[3]]], __assign(__assign({}, DEFAULT_OPTIONS), options));
806
950
  }
807
951
 
808
- export { $naturalBreaks, HoverTooltip, LayeredMap, MapWindow, SyncedMaps, augmentFeature, fitGeometry, getSrcLayer, getSrcViewByLayerId, hoverParseEvent, makeSyncedMaps, naturalBreakBounds, parseMapViews, scaleNaturalBreaks, sortLayers, useHover, withHover };
952
+ //
953
+ // Taken from react-map-gl/maplibre
954
+ // https://github.com/visgl/react-map-gl/blob/c7112cf50d6985e8427d6b187d23a4d957791bb7/modules/react-maplibre/src/utils/apply-react-style.ts
955
+ //
956
+ // This is a simplified version of
957
+ // https://github.com/facebook/react/blob/4131af3e4bf52f3a003537ec95a1655147c81270/src/renderers/dom/shared/CSSPropertyOperations.js#L62
958
+ var unitlessNumber = /box|flex|grid|column|lineHeight|fontWeight|opacity|order|tabSize|zIndex/;
959
+ function applyReactStyle(element, styles) {
960
+ if (!element || !styles) {
961
+ return;
962
+ }
963
+ var style = element.style;
964
+ for (var key in styles) {
965
+ var value = styles[key];
966
+ if (Number.isFinite(value) && !unitlessNumber.test(key)) {
967
+ style[key] = "".concat(value, "px");
968
+ } else {
969
+ style[key] = value;
970
+ }
971
+ }
972
+ }
973
+
974
+ function ensureAddLayer(map, layerId, layer) {
975
+ if (!map.getLayer(layerId)) {
976
+ map.addLayer(__assign(__assign({}, layer), {
977
+ id: layerId
978
+ }));
979
+ }
980
+ }
981
+ function ensureRemoveLayer(map, layerId) {
982
+ if (map.getLayer(layerId)) {
983
+ map.removeLayer(layerId);
984
+ }
985
+ }
986
+ function ensureAddSource(map, sourceId, sourceSpec) {
987
+ if (!map.getSource(sourceId)) {
988
+ map.addSource(sourceId, sourceSpec);
989
+ }
990
+ }
991
+ function ensureRemoveSource(map, sourceId) {
992
+ if (map.getSource(sourceId)) {
993
+ map.removeSource(sourceId);
994
+ }
995
+ }
996
+
997
+ function ControlContainer(_a) {
998
+ var style = _a.style,
999
+ _b = _a.position,
1000
+ position = _b === void 0 ? 'top-right' : _b,
1001
+ children = _a.children;
1002
+ var containerRef = useRef(null);
1003
+ var mapRef = useRef(null);
1004
+ var _c = useState(null),
1005
+ mountPoint = _c[0],
1006
+ setMountPoint = _c[1];
1007
+ useControl(function () {
1008
+ var container = document.createElement('div');
1009
+ container.className = 'maplibregl-ctrl maplibregl-ctrl-group';
1010
+ var mount = document.createElement('div');
1011
+ container.appendChild(mount);
1012
+ containerRef.current = container;
1013
+ setMountPoint(mount);
1014
+ return {
1015
+ onAdd: function onAdd(map) {
1016
+ mapRef.current = map;
1017
+ return container;
1018
+ },
1019
+ onRemove: function onRemove() {
1020
+ container.remove();
1021
+ mapRef.current = null;
1022
+ }
1023
+ };
1024
+ }, {
1025
+ position: position
1026
+ });
1027
+ useEffect(function () {
1028
+ if (style && containerRef.current) {
1029
+ applyReactStyle(containerRef.current, style);
1030
+ }
1031
+ }, [style]);
1032
+ return mountPoint ? /*#__PURE__*/createPortal(children, mountPoint) : null;
1033
+ }
1034
+ function ControlContainerWithStyleReset(_a) {
1035
+ var _b = _a.style,
1036
+ style = _b === void 0 ? {} : _b,
1037
+ props = __rest(_a, ["style"]);
1038
+ return /*#__PURE__*/React.createElement(ControlContainer, __assign({}, props, {
1039
+ style: __assign(__assign({}, style), {
1040
+ boxShadow: 'none',
1041
+ borderRadius: 0
1042
+ })
1043
+ }));
1044
+ }
1045
+ ControlContainer.Unstyled = ControlContainerWithStyleReset;
1046
+
1047
+ var DEFAULT_DEM_SOURCE_ID = 'dem';
1048
+ var DEFAULT_DEM_SOURCE_SPEC = {
1049
+ url: 'https://elevation-tiles-prod.s3.amazonaws.com/terrarium/{z}/{x}/{y}.png',
1050
+ encoding: 'terrarium',
1051
+ attribution: 'TEST',
1052
+ tileSize: 256
1053
+ };
1054
+ function _parseSettings(nextSettings) {
1055
+ if (_typeof(nextSettings) === 'object' && nextSettings !== null && Object.values(nextSettings).every(function (v) {
1056
+ return !v;
1057
+ })) {
1058
+ return false;
1059
+ }
1060
+ return nextSettings;
1061
+ }
1062
+ function _toggleSetting(setSettings, key) {
1063
+ return setSettings(function (curr) {
1064
+ var _a;
1065
+ return _parseSettings(__assign(__assign({}, curr || {}), (_a = {}, _a[key] = !(curr && curr[key]), _a)));
1066
+ });
1067
+ }
1068
+ var DEFAULT_CONTOUR_TILE_OPTIONS = {
1069
+ // convert meters to feet, default=1 for meters
1070
+ // multiplier: 3.28084,
1071
+ thresholds: {
1072
+ // zoom: [minor, major]
1073
+ // 3: [200, 1000],
1074
+ // 8: [200, 1000],
1075
+ // 9: [200, 1000],
1076
+ 7: [300, 1000],
1077
+ 11: [200, 400],
1078
+ 12: [100, 300],
1079
+ 13: [50, 200],
1080
+ 14: [20, 100],
1081
+ 15: [10, 50]
1082
+ },
1083
+ // optional, override vector tile parameters:
1084
+ contourLayer: 'contours',
1085
+ elevationKey: 'ele',
1086
+ levelKey: 'level',
1087
+ extent: 4096,
1088
+ buffer: 1
1089
+ };
1090
+ function TerrainControl(_a) {
1091
+ var _b, _c;
1092
+ var _d = _a.value,
1093
+ externalValue = _d === void 0 ? false : _d,
1094
+ onSetExternalValue = _a.onSetValue,
1095
+ _e = _a.demSourceId,
1096
+ DEM_SOURCE_ID = _e === void 0 ? DEFAULT_DEM_SOURCE_ID : _e,
1097
+ _f = _a.demSource,
1098
+ DEM_SOURCE_SPEC = _f === void 0 ? DEFAULT_DEM_SOURCE_SPEC : _f,
1099
+ _g = _a.contourTileOptions,
1100
+ contourTileOptionsInput = _g === void 0 ? DEFAULT_CONTOUR_TILE_OPTIONS : _g;
1101
+ var _contourTileOptions = useMemo(function () {
1102
+ return __assign(__assign({}, contourTileOptionsInput), DEFAULT_CONTOUR_TILE_OPTIONS);
1103
+ }, [contourTileOptionsInput]);
1104
+ var _h = useLocalState(externalValue, onSetExternalValue),
1105
+ settings = _h[0],
1106
+ setSettings = _h[1];
1107
+ var mapRef = useMap();
1108
+ var demSrcInstance = useMemo(function () {
1109
+ var source = new mlcontour.DemSource(__assign(__assign({}, DEM_SOURCE_SPEC), {
1110
+ url: DEM_SOURCE_SPEC.url,
1111
+ encoding: DEM_SOURCE_SPEC.encoding,
1112
+ maxzoom: 13
1113
+ }));
1114
+ // calls maplibregl.addProtocol for the shared cache and contour protocols
1115
+ source.setupMaplibre(maplibregl);
1116
+ return source;
1117
+ }, [DEM_SOURCE_SPEC]);
1118
+ function _applySettings() {
1119
+ var _a;
1120
+ var map = (_a = mapRef === null || mapRef === void 0 ? void 0 : mapRef.current) === null || _a === void 0 ? void 0 : _a.getMap();
1121
+ if (!map || !map.isStyleLoaded()) {
1122
+ return;
1123
+ }
1124
+ if (!settings) {
1125
+ // Remove terrain and hillshade
1126
+ map.setTerrain(null);
1127
+ ensureRemoveLayer(map, 'hillshade');
1128
+ ensureRemoveSource(map, DEM_SOURCE_ID);
1129
+ ensureRemoveLayer(map, 'contour-lines');
1130
+ ensureRemoveLayer(map, 'contour-labels');
1131
+ ensureRemoveSource(map, 'contour-source');
1132
+ // Reset pitch if desired
1133
+ if (map.getPitch() > 0) {
1134
+ map.easeTo({
1135
+ pitch: 0,
1136
+ bearing: 0,
1137
+ duration: 500
1138
+ });
1139
+ }
1140
+ return;
1141
+ }
1142
+ // Add DEM source if not present
1143
+ if (!map.getSource(DEM_SOURCE_ID)) {
1144
+ map.addSource(DEM_SOURCE_ID, __assign(__assign({
1145
+ maxzoom: 13,
1146
+ tileSize: 256
1147
+ }, omit(DEM_SOURCE_SPEC, ['url', 'tiles'])), {
1148
+ type: 'raster-dem',
1149
+ encoding: DEM_SOURCE_SPEC.encoding,
1150
+ tiles: [demSrcInstance.sharedDemProtocolUrl]
1151
+ }));
1152
+ }
1153
+ // Add hillshade layer if not present
1154
+ if (settings.hillshade || settings.enable3d) {
1155
+ ensureAddLayer(map, 'hillshade', {
1156
+ id: 'hillshade',
1157
+ type: 'hillshade',
1158
+ source: DEM_SOURCE_ID
1159
+ });
1160
+ } else {
1161
+ ensureRemoveLayer(map, 'hillshade');
1162
+ }
1163
+ if (settings === null || settings === void 0 ? void 0 : settings.enable3d) {
1164
+ ensureAddSource(map, "".concat(DEM_SOURCE_ID, "_terrain"), {
1165
+ type: 'raster-dem',
1166
+ // url: DEM_SOURCE_URL,
1167
+ encoding: DEM_SOURCE_SPEC.encoding,
1168
+ tiles: [demSrcInstance.sharedDemProtocolUrl],
1169
+ maxzoom: 13,
1170
+ tileSize: 256
1171
+ });
1172
+ map.setTerrain({
1173
+ source: "".concat(DEM_SOURCE_ID, "_terrain"),
1174
+ exaggeration: 1.5
1175
+ });
1176
+ // Optional: only tilt if pitch is low
1177
+ if (map.getPitch() < 40) {
1178
+ map.easeTo({
1179
+ pitch: 60,
1180
+ bearing: -20,
1181
+ duration: 1000
1182
+ });
1183
+ }
1184
+ } else {
1185
+ map.setTerrain(null);
1186
+ // Reset pitch if desired
1187
+ if (map.getPitch() > 0) {
1188
+ map.easeTo({
1189
+ pitch: 0,
1190
+ bearing: 0,
1191
+ duration: 500
1192
+ });
1193
+ }
1194
+ }
1195
+ //
1196
+ // Add contour
1197
+ //
1198
+ if (settings.contours) {
1199
+ ensureAddSource(map, 'contour-source', {
1200
+ type: 'vector',
1201
+ tiles: [demSrcInstance.contourProtocolUrl(_contourTileOptions)],
1202
+ maxzoom: 15
1203
+ });
1204
+ ensureAddLayer(map, 'contour-lines', {
1205
+ id: 'contour-lines',
1206
+ type: 'line',
1207
+ source: 'contour-source',
1208
+ 'source-layer': 'contours',
1209
+ paint: {
1210
+ // 'line-color': 'rgba(0,0,0, 50%)',
1211
+ // 'line-color': 'rgb(229, 77, 46, 80%)',
1212
+ // 'line-color': 'rgb(46, 77, 229, 80%)',
1213
+ 'line-color': '#FF4500',
1214
+ // level = highest index in thresholds array the elevation is a multiple of
1215
+ 'line-width': ['match', ['get', 'level'], 1, 1, 0.5]
1216
+ }
1217
+ });
1218
+ ensureAddLayer(map, 'contour-labels', {
1219
+ id: 'contour-labels',
1220
+ type: 'symbol',
1221
+ source: 'contour-source',
1222
+ 'source-layer': 'contours',
1223
+ filter: ['>', ['get', 'level'], 0],
1224
+ layout: {
1225
+ // 'symbol-placement': 'point',
1226
+ 'symbol-placement': 'line-center',
1227
+ // 'symbol-placement': ['step', ['zoom'], 'point', 14, 'line'],
1228
+ 'text-max-angle': 80,
1229
+ 'text-allow-overlap': true,
1230
+ 'text-ignore-placement': true,
1231
+ 'text-size': 10,
1232
+ // 'text-field': 'test',
1233
+ 'text-field': ['concat', ['number-format', ['get', 'ele'], {
1234
+ locale: 'pt-BR'
1235
+ }], 'm'],
1236
+ 'text-font': ['Noto Sans Bold']
1237
+ },
1238
+ paint: {
1239
+ 'text-halo-color': 'white',
1240
+ 'text-halo-width': 1,
1241
+ 'text-color': '#E54D2E'
1242
+ }
1243
+ });
1244
+ var CONTOURS_MIN_ZOOM = Object.keys(_contourTileOptions.thresholds).map(function (k) {
1245
+ return parseInt(k);
1246
+ }).sort(function (a, b) {
1247
+ return a - b;
1248
+ })[0];
1249
+ if (map.getZoom() < CONTOURS_MIN_ZOOM) {
1250
+ map.easeTo({
1251
+ zoom: CONTOURS_MIN_ZOOM,
1252
+ duration: 500
1253
+ });
1254
+ }
1255
+ } else {
1256
+ ensureRemoveLayer(map, 'contour-lines');
1257
+ ensureRemoveLayer(map, 'contour-labels');
1258
+ ensureRemoveSource(map, 'contour-source');
1259
+ }
1260
+ }
1261
+ useEffect(function () {
1262
+ _applySettings();
1263
+ }, [(_b = mapRef.current) === null || _b === void 0 ? void 0 : _b.getMap(), settings]);
1264
+ useEffect(function () {
1265
+ var _a;
1266
+ var map = (_a = mapRef.current) === null || _a === void 0 ? void 0 : _a.getMap();
1267
+ if (!map) {
1268
+ return function () {};
1269
+ }
1270
+ var handleStyleLoad = function handleStyleLoad() {
1271
+ map.once('idle', _applySettings);
1272
+ // setTimeout(_applySettings, 1000)
1273
+ // ()
1274
+ // if (settings && settings.enable3d) {
1275
+ // const terrainDemSourceId = `${DEM_SOURCE_ID}_terrain`
1276
+ // ensureAddSource(map, terrainDemSourceId, {
1277
+ // type: 'raster-dem',
1278
+ // // url: DEM_SOURCE_URL,
1279
+ // encoding: DEM_SOURCE_ENCODING,
1280
+ // tiles: [demSrcInstance.sharedDemProtocolUrl],
1281
+ // maxzoom: 13,
1282
+ // tileSize: 256,
1283
+ // })
1284
+ // map.setTerrain({ source: terrainDemSourceId, exaggeration: 1.5 })
1285
+ // }
1286
+ };
1287
+ map.on('style.load', handleStyleLoad);
1288
+ return function () {
1289
+ return map.off('style.load', handleStyleLoad);
1290
+ };
1291
+ }, [(_c = mapRef.current) === null || _c === void 0 ? void 0 : _c.getMap(), settings && settings.enable3d]);
1292
+ return /*#__PURE__*/React.createElement(ControlContainer, null, /*#__PURE__*/React.createElement(DropdownMenu, {
1293
+ size: "1",
1294
+ options: [{
1295
+ label: (/*#__PURE__*/React.createElement(React.Fragment, null, "Relevo", settings && (settings.hillshade || settings.enable3d) && (/*#__PURE__*/React.createElement(Icon, {
1296
+ path: mdiCheck,
1297
+ size: "12px"
1298
+ })))),
1299
+ disabled: settings && settings.enable3d,
1300
+ onClick: function onClick() {
1301
+ return _toggleSetting(setSettings, 'hillshade');
1302
+ }
1303
+ }, {
1304
+ label: (/*#__PURE__*/React.createElement(React.Fragment, null, "3D", settings && settings.enable3d && (/*#__PURE__*/React.createElement(Icon, {
1305
+ path: mdiCheck,
1306
+ size: "12px"
1307
+ })))),
1308
+ onClick: function onClick() {
1309
+ return _toggleSetting(setSettings, 'enable3d');
1310
+ }
1311
+ }, {
1312
+ label: (/*#__PURE__*/React.createElement(React.Fragment, null, "Curvas de n\xEDvel", settings && settings.contours && (/*#__PURE__*/React.createElement(Icon, {
1313
+ path: mdiCheck,
1314
+ size: "12px"
1315
+ })))),
1316
+ onClick: function onClick() {
1317
+ return _toggleSetting(setSettings, 'contours');
1318
+ }
1319
+ }]
1320
+ }, /*#__PURE__*/React.createElement("button", {
1321
+ type: "button",
1322
+ "aria-label": "Relevo",
1323
+ style: {
1324
+ position: 'relative'
1325
+ }
1326
+ }, /*#__PURE__*/React.createElement(Tooltip, {
1327
+ content: "Relevo"
1328
+ }, /*#__PURE__*/React.createElement(Icon, {
1329
+ color: settings ? 'var(--accent-9)' : 'inherit',
1330
+ path: mdiTerrain,
1331
+ size: "24px"
1332
+ })), settings && settings.enable3d && (/*#__PURE__*/React.createElement("div", {
1333
+ style: {
1334
+ width: 14,
1335
+ height: 14,
1336
+ background: 'var(--accent-9)',
1337
+ color: 'var(--accent-contrast)',
1338
+ borderRadius: '50%',
1339
+ position: 'absolute',
1340
+ top: '100%',
1341
+ left: '100%',
1342
+ transform: 'translate(-50%, -50%)'
1343
+ }
1344
+ }, /*#__PURE__*/React.createElement(Icon, {
1345
+ path: mdiVideo3d,
1346
+ size: "14px"
1347
+ }))))));
1348
+ }
1349
+
1350
+ function InspectControl(props) {
1351
+ useControl(function () {
1352
+ return new MaplibreInspect(__assign(__assign({}, props), {
1353
+ popup: new maplibregl.Popup({
1354
+ closeButton: false,
1355
+ closeOnClick: false
1356
+ })
1357
+ }));
1358
+ }, {
1359
+ // position: props.position,
1360
+ });
1361
+ return null;
1362
+ }
1363
+
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 };
@@ -1,18 +1,19 @@
1
- import { MapMouseEvent } from 'maplibre-gl';
1
+ import { Map, MapGeoJSONFeature, MapMouseEvent } from 'maplibre-gl';
2
2
  import React from 'react';
3
3
  type DefaultHoverInfo = {
4
4
  point: [number, number];
5
5
  coordinates: [number, number];
6
- features: GeoJSON.Feature[];
6
+ features: MapGeoJSONFeature[];
7
7
  };
8
8
  export declare function hoverParseEvent(event: MapMouseEvent): DefaultHoverInfo;
9
9
  export type UseHoverProps<DataT = DefaultHoverInfo> = {
10
10
  parseEvent?: (event: MapMouseEvent) => DataT;
11
11
  tooltip?: (data: DataT) => React.ReactNode;
12
12
  };
13
+ export declare function mapSetFeaturesState(map: Map, features: MapGeoJSONFeature[] | undefined, state: any): void;
13
14
  export declare function useHover<InfoT = any>(props: UseHoverProps | undefined, deps: any[]): (boolean | InfoT | {
14
15
  onMouseMove: (event: MapMouseEvent) => void;
15
- onMouseOut: () => void;
16
+ onMouseOut: (event: any) => void;
16
17
  onDragStart: () => void;
17
18
  onDragEnd: () => void;
18
19
  cursor: string;
@@ -0,0 +1,2 @@
1
+ import * as React from 'react';
2
+ export declare function applyReactStyle(element: HTMLElement, styles: React.CSSProperties): void;
@@ -1 +1,3 @@
1
1
  export * from './fitGeometry';
2
+ export * from './applyReactStyle';
3
+ export * from './misc';
@@ -0,0 +1 @@
1
+ export * from './matchExpFromDict';
@@ -0,0 +1,8 @@
1
+ type Dict = Record<any, (string | number) | (string | number)[]>;
2
+ type MatchExpFromDictProps = {
3
+ valueExp: string | any[];
4
+ dict: Dict;
5
+ defaultValue: any;
6
+ };
7
+ export declare function matchExpFromDict({ valueExp, dict, defaultValue, }: MatchExpFromDictProps): any[];
8
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { LayerSpecification, Map, SourceSpecification } from 'maplibre-gl';
2
+ export declare function ensureAddLayer(map: Map, layerId: string, layer: LayerSpecification): void;
3
+ export declare function ensureRemoveLayer(map: Map, layerId: string): void;
4
+ export declare function ensureAddSource(map: Map, sourceId: string, sourceSpec: SourceSpecification): void;
5
+ export declare function ensureRemoveSource(map: Map, sourceId: string): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orioro/react-maplibre-util",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "packageManager": "yarn@4.0.2",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -29,27 +29,37 @@
29
29
  "storybook": "^8.0.0"
30
30
  },
31
31
  "dependencies": {
32
+ "@mapbox/mapbox-gl-geocoder": "^5.0.3",
33
+ "@maplibre/maplibre-gl-inspect": "^1.7.1",
34
+ "@mdi/js": "^7.4.47",
35
+ "@mdi/react": "^1.6.1",
32
36
  "@orioro/react-chart-util": "^0.1.0",
33
37
  "@orioro/react-select": "^3.0.2",
34
38
  "@orioro/react-ui-core": "^0.0.6",
35
39
  "@orioro/resolve": "^0.1.2",
36
40
  "@orioro/scale-util": "^0.0.2",
41
+ "@radix-ui/themes": "^3.2.1",
37
42
  "@turf/turf": "^7.2.0",
38
43
  "@types/d3": "^7.4.3",
39
44
  "@types/d3-scale-chromatic": "^3.1.0",
40
45
  "@types/geojson": "^7946.0.16",
46
+ "@types/mapbox__mapbox-gl-geocoder": "^5.0.0",
47
+ "@types/react-dom": "^19.1.3",
41
48
  "d3": "^7.9.0",
42
49
  "d3-scale-chromatic": "^3.1.0",
43
50
  "greenlet": "^1.1.0",
44
51
  "lodash-es": "^4.17.21",
52
+ "maplibre-contour": "^0.1.0",
45
53
  "maplibre-gl": "^5.1.0",
46
54
  "query-string": "^9.1.1",
47
55
  "react": "^18.2.0",
56
+ "react-dom": "^19.1.0",
48
57
  "react-map-gl": "^8.0.0",
49
58
  "react-merge-refs": "^2.1.1",
50
59
  "react-use": "^17.5.0",
51
60
  "simple-statistics": "^7.8.7",
52
61
  "styled-components": "^6.1.8",
53
- "tslib": "^2.8.1"
62
+ "tslib": "^2.8.1",
63
+ "type-fest": "^4.40.1"
54
64
  }
55
65
  }
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare function Geocoder({}: {}): React.JSX.Element;
@@ -1,11 +0,0 @@
1
- import React from 'react';
2
- import 'maplibre-gl/dist/maplibre-gl.css';
3
- import '@maplibre/maplibre-gl-geocoder/dist/maplibre-gl-geocoder.css';
4
- declare const _default: {
5
- title: string;
6
- parameters: {
7
- layout: string;
8
- };
9
- };
10
- export default _default;
11
- export declare const Basic: () => React.JSX.Element;
@@ -1,9 +0,0 @@
1
- export type MapboxGeocoderApiProps = {
2
- accessToken: string;
3
- };
4
- export declare function mapboxGeocoderApi({ accessToken }: MapboxGeocoderApiProps): {
5
- forwardGeocode: (input: any) => Promise<void>;
6
- reverseGeocode: (input: any) => Promise<void>;
7
- getSuggestions: (config: any) => any;
8
- searchByPlaceId: ({ query, language, }: MaplibreGeocoderApiConfig) => Promise<MaplibreGeocoderPlaceResults>;
9
- };