@orioro/react-maplibre-util 0.5.1 → 0.5.3

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.5.3
4
+
5
+ ### Patch Changes
6
+
7
+ - fix layer ordering sync issue
8
+
9
+ ## 0.5.2
10
+
11
+ ### Patch Changes
12
+
13
+ - fix TerrainControl position usage
14
+
3
15
  ## 0.5.1
4
16
 
5
17
  ### Patch Changes
@@ -8,7 +8,7 @@ export type ControlContainerProps = {
8
8
  /** Button content and props */
9
9
  children: React.ReactNode;
10
10
  };
11
- export declare function ControlContainer({ style, position, children, }: ControlContainerProps): any;
11
+ export declare function ControlContainer({ style, position, children, }: ControlContainerProps): React.ReactPortal | null;
12
12
  export declare namespace ControlContainer {
13
13
  var Unstyled: typeof ControlContainerWithStyleReset;
14
14
  }
@@ -17,5 +17,5 @@ type TerrainControlProps = Omit<ControlContainerProps, 'children'> & {
17
17
  demSource?: SourceSpecInput;
18
18
  contourTileOptions?: Partial<GlobalContourTileOptions>;
19
19
  };
20
- export declare function TerrainControl({ value: externalValue, onSetValue: onSetExternalValue, demSourceId: DEM_SOURCE_ID, demSource: DEM_SOURCE_SPEC, contourTileOptions: contourTileOptionsInput, }: TerrainControlProps): React.JSX.Element;
20
+ export declare function TerrainControl({ value: externalValue, onSetValue: onSetExternalValue, demSourceId: DEM_SOURCE_ID, demSource: DEM_SOURCE_SPEC, contourTileOptions: contourTileOptionsInput, ...controlContainerProps }: TerrainControlProps): React.JSX.Element;
21
21
  export {};
@@ -0,0 +1,23 @@
1
+ import type { Map } from 'maplibre-gl';
2
+ export type ParseLayerOrderOpts = {
3
+ map: Map;
4
+ layerIds: string[];
5
+ };
6
+ export declare function parseLayerOrder({ map, layerIds }: ParseLayerOrderOpts): string[];
7
+ export type SyncLayerOrderOpts = {
8
+ expectedLayerOrderId: string[];
9
+ map: Map;
10
+ topAnchorLayerId?: string;
11
+ };
12
+ /**
13
+ * Sync MapLibre layer order to match `expectedLayerOrderId`.
14
+ *
15
+ * - Only layers present in `expectedLayerOrderId` are moved.
16
+ * - Missing layers are ignored (no-op for those entries).
17
+ * - If `topAnchorLayerId` is provided, the last expected layer is positioned
18
+ * just beneath that anchor; otherwise it becomes the topmost layer.
19
+ *
20
+ * This helps counteract dynamic reordering issues when using react-map-gl.
21
+ * See: https://github.com/visgl/react-map-gl/issues/939#issuecomment-1515395161
22
+ */
23
+ export declare function syncLayerOrder({ expectedLayerOrderId, map, topAnchorLayerId, }: SyncLayerOrderOpts): void;
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { __assign, __spreadArray, __rest, __awaiter, __generator, __makeTemplateObject } from 'tslib';
2
- import React, { forwardRef, useContext, createContext, useRef, useMemo, useImperativeHandle, useState, useCallback, useLayoutEffect, useEffect, createRef } from 'react';
2
+ import React, { forwardRef, useContext, createContext, useRef, useMemo, useImperativeHandle, useEffect, useState, useCallback, useLayoutEffect, createRef } from 'react';
3
3
  import { Map, Source, Layer, useMap, useControl } from 'react-map-gl/maplibre';
4
- import { isPlainObject, uniq, uniqBy, pick, omit } from 'lodash-es';
4
+ import { isPlainObject, uniq, uniqBy, isEqual, pick, omit } from 'lodash-es';
5
5
  import { Flex, useRefByKey, useLocalState, DropdownMenu } from '@orioro/react-ui-core';
6
6
  import styled from 'styled-components';
7
7
  import { usePrevious } from 'react-use';
@@ -164,6 +164,58 @@ function parseMapViews(orderedViews, _a) {
164
164
  };
165
165
  }
166
166
 
167
+ //
168
+ // Retrive a list of current ordered layer ids
169
+ // within a given set of layer ids
170
+ //
171
+ function parseLayerOrder(_a) {
172
+ var map = _a.map,
173
+ layerIds = _a.layerIds;
174
+ return map.getLayersOrder().filter(function (layerId) {
175
+ return layerIds.includes(layerId);
176
+ });
177
+ }
178
+ /**
179
+ * Sync MapLibre layer order to match `expectedLayerOrderId`.
180
+ *
181
+ * - Only layers present in `expectedLayerOrderId` are moved.
182
+ * - Missing layers are ignored (no-op for those entries).
183
+ * - If `topAnchorLayerId` is provided, the last expected layer is positioned
184
+ * just beneath that anchor; otherwise it becomes the topmost layer.
185
+ *
186
+ * This helps counteract dynamic reordering issues when using react-map-gl.
187
+ * See: https://github.com/visgl/react-map-gl/issues/939#issuecomment-1515395161
188
+ */
189
+ function syncLayerOrder(_a) {
190
+ var expectedLayerOrderId = _a.expectedLayerOrderId,
191
+ map = _a.map,
192
+ _b = _a.topAnchorLayerId,
193
+ topAnchorLayerId = _b === void 0 ? undefined : _b;
194
+ var currentLayerOrderId = parseLayerOrder({
195
+ map: map,
196
+ layerIds: expectedLayerOrderId
197
+ });
198
+ if (isEqual(expectedLayerOrderId, currentLayerOrderId)) {
199
+ return;
200
+ }
201
+ expectedLayerOrderId.forEach(function (layerId, index) {
202
+ if (!map.getLayer(layerId)) {
203
+ return;
204
+ }
205
+ if (index === expectedLayerOrderId.length - 1) {
206
+ // Place the last expected layer just beneath the top anchor (if any),
207
+ // otherwise move it to the absolute top.
208
+ map.moveLayer(layerId, topAnchorLayerId);
209
+ } else {
210
+ var beneathLayerId = expectedLayerOrderId[index + 1];
211
+ if (!map.getLayer(beneathLayerId)) {
212
+ return;
213
+ }
214
+ map.moveLayer(layerId, beneathLayerId);
215
+ }
216
+ });
217
+ }
218
+
167
219
  // import { mergeRefs } from 'react-merge-refs'
168
220
  //
169
221
  // Augment mouse events with info from original view
@@ -230,6 +282,25 @@ var LayeredMap = /*#__PURE__*/forwardRef(function LayeredMapInner(_a, layeredMap
230
282
  useImperativeHandle(layeredMapRef, function () {
231
283
  return imperativeHandle;
232
284
  }, [imperativeHandle]);
285
+ //
286
+ // Force sync layer order
287
+ // https://github.com/visgl/react-map-gl/issues/939#issuecomment-1515395161
288
+ //
289
+ useEffect(function () {
290
+ if (!(parsed === null || parsed === void 0 ? void 0 : parsed.layers) || !mapRef.current) {
291
+ return;
292
+ }
293
+ // Timeout ensures layers are added to map before moving
294
+ setTimeout(function () {
295
+ var expectedLayerOrderId = parsed.layers.map(function (layer) {
296
+ return layer.id;
297
+ });
298
+ syncLayerOrder({
299
+ expectedLayerOrderId: expectedLayerOrderId,
300
+ map: mapRef.current
301
+ });
302
+ }, 0);
303
+ }, [parsed === null || parsed === void 0 ? void 0 : parsed.layers]);
233
304
  return /*#__PURE__*/React.createElement(Map, __assign({
234
305
  ref: mapRef,
235
306
  interactiveLayerIds: __spreadArray(__spreadArray([], interactiveLayerIdsInput, true), parsed.interactiveLayerIds, true)
@@ -1306,7 +1377,8 @@ function TerrainControl(_a) {
1306
1377
  _f = _a.demSource,
1307
1378
  DEM_SOURCE_SPEC = _f === void 0 ? DEFAULT_DEM_SOURCE_SPEC : _f,
1308
1379
  _g = _a.contourTileOptions,
1309
- contourTileOptionsInput = _g === void 0 ? DEFAULT_CONTOUR_TILE_OPTIONS : _g;
1380
+ contourTileOptionsInput = _g === void 0 ? DEFAULT_CONTOUR_TILE_OPTIONS : _g,
1381
+ controlContainerProps = __rest(_a, ["value", "onSetValue", "demSourceId", "demSource", "contourTileOptions"]);
1310
1382
  var _contourTileOptions = useMemo(function () {
1311
1383
  return __assign(__assign({}, contourTileOptionsInput), DEFAULT_CONTOUR_TILE_OPTIONS);
1312
1384
  }, [contourTileOptionsInput]);
@@ -1498,7 +1570,7 @@ function TerrainControl(_a) {
1498
1570
  return map.off('style.load', handleStyleLoad);
1499
1571
  };
1500
1572
  }, [(_c = mapRef.current) === null || _c === void 0 ? void 0 : _c.getMap(), settings && settings.enable3d]);
1501
- return /*#__PURE__*/React.createElement(ControlContainer, null, /*#__PURE__*/React.createElement(DropdownMenu, {
1573
+ return /*#__PURE__*/React.createElement(ControlContainer, __assign({}, controlContainerProps), /*#__PURE__*/React.createElement(DropdownMenu, {
1502
1574
  size: "1",
1503
1575
  options: [{
1504
1576
  label: (/*#__PURE__*/React.createElement(React.Fragment, null, "Relevo", settings && (settings.hillshade || settings.enable3d) && (/*#__PURE__*/React.createElement(Icon, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orioro/react-maplibre-util",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "packageManager": "yarn@4.0.2",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",