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