From 7a9699c727be9f7bad6c9fc5853b48d5931f0002 Mon Sep 17 00:00:00 2001 From: mike Date: Sun, 26 Jul 2026 23:54:17 -0400 Subject: [PATCH 01/12] fix(react-maplibre): support maplibre-gl v6 (transform getters, setTransformCameraUpdate, event typing) --- docs/whats-new.md | 65 +++++++++---------- modules/react-maplibre/package.json | 2 +- .../react-maplibre/src/components/layer.ts | 9 +-- .../react-maplibre/src/maplibre/maplibre.ts | 24 ++++--- modules/react-maplibre/src/types/events.ts | 2 +- modules/react-maplibre/src/utils/transform.ts | 17 +++++ 6 files changed, 72 insertions(+), 47 deletions(-) diff --git a/docs/whats-new.md b/docs/whats-new.md index 3d2c2a405..058a7eeae 100644 --- a/docs/whats-new.md +++ b/docs/whats-new.md @@ -1,5 +1,9 @@ # What's new +## react-map-gl v8.2 + +- The Maplibre wrapper (`react-map-gl/maplibre`) now supports `maplibre-gl` v6, which replaced the public `map.transform` property and the `map.transformCameraUpdate` field with getter methods (`getCenter()`, `getZoom()`, etc.) and `map.setTransformCameraUpdate()`. The wrapper now uses these getters and falls back to the old field assignment when running against `maplibre-gl` v4/v5. + ## react-map-gl v8.1 Release date: Oct 2025 @@ -14,9 +18,9 @@ Release date: Jan 2025 - First version to support Mapbox GL JS' official types and MapLibre GL JS v5. This version fully separates the code that support each compatible map library: - + `react-map-gl/mapbox`: for use with `mapbox-gl>=3.5.0` - + `react-map-gl/maplibre`: for use with `maplibre-gl>=4` - + `react-map-gl/mapbox-legacy`: for use with `mapbox-gl` v1.x and v2.x and `@types/mapbox-gl` + - `react-map-gl/mapbox`: for use with `mapbox-gl>=3.5.0` + - `react-map-gl/maplibre`: for use with `maplibre-gl>=4` + - `react-map-gl/mapbox-legacy`: for use with `mapbox-gl` v1.x and v2.x and `@types/mapbox-gl` - As a result, each endpoint now have slightly smaller bundle size and more precise types. - Maplibre wrapper is expected to have better functionality and performance than v7 by utilizing an [upstream API](https://github.com/maplibre/maplibre-gl-js/issues/1545) for the React use case. @@ -109,7 +113,7 @@ Release date: Mar 14, 2019 - **New Components**: [`FullscreenControl`](https://github.com/visgl/react-map-gl/tree/4.1-release/docs/components/fullscreen-control.md), [`GeolocateControl`](https://github.com/visgl/react-map-gl/tree/4.1-release/docs/components/geolocate-control.md) have been added to provide better React parity with the `Mapbox GL JS` API. - **New callback props** `InteractiveMap` supports more callbacks: - + `onNativeClick` + - `onNativeClick` ## react-map-gl v4.0 @@ -126,17 +130,17 @@ Release date: Nov 5, 2018 - **Interaction states** `onViewportChange` is now called with richer descriptors of the user interaction, including `isPanning`, `isZooming` and `isRotating`. - **Interactive layers** Dropped the requirement for the deprecated `interactive` property on the layer styles. Use the `interactiveLayerIds` prop to specify which layers are clickable. - **New callback props** `InteractiveMap` supports more callbacks: - + `onDblClick` - + `onMouseDown` - + `onMouseMove` - + `onMouseUp` - + `onTouchStart` - + `onTouchMove` - + `onTouchEnd` - + `onMouseEnter` - + `onMouseLeave` - + `onWheel` - + `onMouseOut` + - `onDblClick` + - `onMouseDown` + - `onMouseMove` + - `onMouseUp` + - `onTouchStart` + - `onTouchMove` + - `onTouchEnd` + - `onMouseEnter` + - `onMouseLeave` + - `onWheel` + - `onMouseOut` See [upgrade guide](./upgrade-guide.md) for breaking changes. @@ -149,7 +153,6 @@ Release date: July, 2018 - **New `viewState` Property**: Makes it possible to specify all map state properties (`longitude`, `latitude`, `zoom`, `bearing` and `pitch`) as a single property. - **New `onViewStateChange` callback**: An alternative callback that matches the new `viewState` prop. - ## react-map-gl v3.2 Realease date: January, 2018 @@ -161,10 +164,9 @@ Realease date: January, 2018 - **Support for Map Reuse (experimental)**: A new property `reuseMaps` is provided for applications that create and destroy maps, to help work around a mapbox-gl resource leak issue that can lead to a browser crash in certain situations. - **mapbox-gl 0.42.2** - **New props** of the InteractiveMap component: - + Map creation: `transformRequest`, `reuseMaps` - + Interaction: `touchZoom`, `touchRotate` - + Transition: `transitionDuration`, `transitionInterpolator`, `transitionEasing`, `transitionInterruption`, `onTransitionStart`, `onTransitionInterrupt`, `onTransitionEnd` - + - Map creation: `transformRequest`, `reuseMaps` + - Interaction: `touchZoom`, `touchRotate` + - Transition: `transitionDuration`, `transitionInterpolator`, `transitionEasing`, `transitionInterruption`, `onTransitionStart`, `onTransitionInterrupt`, `onTransitionEnd` ## react-map-gl v3.1 @@ -173,14 +175,13 @@ Release date: October 19, 2017 ### Highlights - **Event handling** - + Support right mouse drag to rotate - + Support keyboard navigation - + Allow controls and overlays to block map interactions + - Support right mouse drag to rotate + - Support keyboard navigation + - Allow controls and overlays to block map interactions - **React 16** - react-map-gl is now being tested with React 16, but the React peer dependency requirement is unchanged at `>=15.4.x`. - **mapbox-gl v0.40.1** - **No Token warning**: react-map-gl now renders an HTML message if no mapbox token is supplied. - ## react-map-gl v3.0 Release date: July 27th, 2017 @@ -192,7 +193,7 @@ Release date: July 27th, 2017 - **New Components**: The `MapGL` component has been split into [`StaticMap`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/static-map.md) and [`InteractiveMap`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/interactive-map.md) (the default). Also, [`Popup`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/popup.md), [`Marker`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/marker.md), [`NavigationControl`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/navigation-control.md) have been added to provide better React parity with the `Mapbox GL JS` API. - **Improved Overlay Components**: Supplying viewport props (`width` `height` `zoom` `longitude` and `latitude`) are no longer required if you render [`SVGOverlay`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/overlays/svg-overlay.md), [`CanvasOverlay`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/overlays/canvas-overlay.md) or [`HTMLOverlay`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/overlays/html-overlay.md) as a child of the map. Perspective mode is now supported in all overlays. - **New Props**: `maxPitch`, `minPitch`, `dragPan`, `doubleClickZoom`, `touchZoomRotate`, -`scrollZoom` are now provided to allow granular control of map interactivity. + `scrollZoom` are now provided to allow granular control of map interactivity. - **Documentation**: Significantly expanded and linked with our other geospatial frameworks. - **Examples**: New stand-alone examples to get you started instantly with the new features. - **Event Handling**: New event handling architecture that enables full customization of event handling (experimental). @@ -209,37 +210,35 @@ This is the React wrapper around `Mapbox GL JS` and takes in viewport properties #### Overlays -* Three overlays (`ScatterplotOverlay`, `DraggablePointsOverlay`, `ChoroplethOverlay`), have been moved out of the library and are now only provided as examples. +- Three overlays (`ScatterplotOverlay`, `DraggablePointsOverlay`, `ChoroplethOverlay`), have been moved out of the library and are now only provided as examples. ### Property Changes - **Property Names** - some prop names have been modernized, the old ones will still work for now with a warning. - **Internal Properties** such as `isHovering`, `isDragging`, `startDragLngLat` have been removed. -These were never meant to be useful publicly and have caused confusions in the past. + These were never meant to be useful publicly and have caused confusions in the past. ### Utilities -* **fitBounds**: `fitBounds` has been moved to another repository and has been rewritten to provide a more logical interface. +- **fitBounds**: `fitBounds` has been moved to another repository and has been rewritten to provide a more logical interface. For more information, see the `Upgrade Guide`. - ## react-map-gl v2.0 Date: Jan 17, 2017 ### Highlights + - **Latest mapbox-gl**: Bump `mapbox-gl` to v0.31.0 - **new maxZoom prop** - Add `maxZoom` prop and defaults to `20` - **New onLoad prop** - Add `onLoad` event handler - **new onClick prop** - Add `onClick` prop handler (#140) - ## react-map-gl v1.0 -* **Perspective Mode** - Now supports `bearing` and `pitch` properties, per mapbox-gl api documentation. These props default to 0 which means that maps will still be rendered in flat/ortographic mode when they are not provided -* **Support for ES6 imports** - The map overlay components (HTMLOverlay, CanvasOverlay, SVGOverlay etc) previously had to be imported via their relative source paths can now be imported directly. - +- **Perspective Mode** - Now supports `bearing` and `pitch` properties, per mapbox-gl api documentation. These props default to 0 which means that maps will still be rendered in flat/ortographic mode when they are not provided +- **Support for ES6 imports** - The map overlay components (HTMLOverlay, CanvasOverlay, SVGOverlay etc) previously had to be imported via their relative source paths can now be imported directly. ## react-map-gl v0.6 diff --git a/modules/react-maplibre/package.json b/modules/react-maplibre/package.json index 18bac01dd..8b619a860 100644 --- a/modules/react-maplibre/package.json +++ b/modules/react-maplibre/package.json @@ -33,7 +33,7 @@ "@maplibre/maplibre-gl-style-spec": "^19.2.1" }, "devDependencies": { - "maplibre-gl": "^5.0.0" + "maplibre-gl": "^6.0.0" }, "peerDependencies": { "maplibre-gl": ">=4.0.0", diff --git a/modules/react-maplibre/src/components/layer.ts b/modules/react-maplibre/src/components/layer.ts index d927e380a..9cc0981b8 100644 --- a/modules/react-maplibre/src/components/layer.ts +++ b/modules/react-maplibre/src/components/layer.ts @@ -5,6 +5,7 @@ import {deepEqual} from '../utils/deep-equal'; import type {MapInstance, CustomLayerInterface} from '../types/lib'; import type {LayerSpecification} from '../types/style-spec'; +import type {AllLayoutProperties, AllPaintProperties} from 'maplibre-gl'; // Omiting property from a union type, see // https://github.com/microsoft/TypeScript/issues/39556#issuecomment-656925230 @@ -35,12 +36,12 @@ function updateLayer(map: MapInstance, id: string, props: LayerProps, prevProps: const prevLayout = prevProps.layout || {}; for (const key in layout) { if (!deepEqual(layout[key], prevLayout[key])) { - map.setLayoutProperty(id, key, layout[key]); + map.setLayoutProperty(id, key as keyof AllLayoutProperties, layout[key]); } } for (const key in prevLayout) { if (!layout.hasOwnProperty(key)) { - map.setLayoutProperty(id, key, undefined); + map.setLayoutProperty(id, key as keyof AllLayoutProperties, undefined); } } } @@ -48,12 +49,12 @@ function updateLayer(map: MapInstance, id: string, props: LayerProps, prevProps: const prevPaint = prevProps.paint || {}; for (const key in paint) { if (!deepEqual(paint[key], prevPaint[key])) { - map.setPaintProperty(id, key, paint[key]); + map.setPaintProperty(id, key as keyof AllPaintProperties, paint[key]); } } for (const key in prevPaint) { if (!paint.hasOwnProperty(key)) { - map.setPaintProperty(id, key, undefined); + map.setPaintProperty(id, key as keyof AllPaintProperties, undefined); } } } diff --git a/modules/react-maplibre/src/maplibre/maplibre.ts b/modules/react-maplibre/src/maplibre/maplibre.ts index fa16e53ad..4e09aa9bf 100644 --- a/modules/react-maplibre/src/maplibre/maplibre.ts +++ b/modules/react-maplibre/src/maplibre/maplibre.ts @@ -1,4 +1,4 @@ -import {transformToViewState, applyViewStateToTransform} from '../utils/transform'; +import {transformToViewState, applyViewStateToTransform, getTransformLike} from '../utils/transform'; import {normalizeStyle} from '../utils/style-utils'; import {deepEqual} from '../utils/deep-equal'; @@ -20,6 +20,7 @@ import type { ProjectionSpecification } from '../types/style-spec'; import type {MapInstance} from '../types/lib'; +import type {MapEventType} from 'maplibre-gl'; import type { MapCallbacks, ViewStateChangeEvent, @@ -310,7 +311,13 @@ export default class Maplibre { } // add listeners - map.transformCameraUpdate = this._onCameraUpdate; + if (map.setTransformCameraUpdate) { + // maplibre-gl v6+ + map.setTransformCameraUpdate(this._onCameraUpdate); + } else { + // @ts-ignore transformCameraUpdate does not exist in v6, replaced by setTransformCameraUpdate() + map.transformCameraUpdate = this._onCameraUpdate; + } map.on('style.load', () => { // Map style has changed, this would have wiped out all settings from props this._styleComponents = { @@ -327,13 +334,13 @@ export default class Maplibre { this._updateStyleComponents(this.props); }); for (const eventName in pointerEvents) { - map.on(eventName, this._onPointerEvent); + map.on(eventName as keyof MapEventType, this._onPointerEvent); } for (const eventName in cameraEvents) { - map.on(eventName, this._onCameraEvent); + map.on(eventName as keyof MapEventType, this._onCameraEvent); } for (const eventName in otherEvents) { - map.on(eventName, this._onEvent); + map.on(eventName as keyof MapEventType, this._onEvent); } this._map = map; } @@ -380,7 +387,8 @@ export default class Maplibre { const {viewState} = nextProps; if (viewState) { const map = this._map; - if (viewState.width !== map.transform.width || viewState.height !== map.transform.height) { + const container = map.getContainer(); + if (viewState.width !== container.clientWidth || viewState.height !== container.clientHeight) { map.resize(); return true; } @@ -396,7 +404,7 @@ export default class Maplibre { */ private _updateViewState(nextProps: MaplibreProps): boolean { const map = this._map; - const tr = map.transform; + const tr = getTransformLike(map); const isMoving = map.isMoving(); // Avoid manipulating the real transform when interaction/animation is ongoing @@ -519,7 +527,7 @@ export default class Maplibre { if (this._internalUpdate) { return; } - e.viewState = this._propsedCameraUpdate || transformToViewState(this._map.transform); + e.viewState = this._propsedCameraUpdate || transformToViewState(getTransformLike(this._map)); // @ts-ignore const cb = this.props[cameraEvents[e.type]]; if (cb) { diff --git a/modules/react-maplibre/src/types/events.ts b/modules/react-maplibre/src/types/events.ts index 32cd10188..6aa9bde63 100644 --- a/modules/react-maplibre/src/types/events.ts +++ b/modules/react-maplibre/src/types/events.ts @@ -13,7 +13,7 @@ import type { MapStyleDataEvent, MapSourceDataEvent, MapWheelEvent, - MapLibreZoomEvent as MapBoxZoomEvent + MapBoxZoomEvent } from 'maplibre-gl'; export type { diff --git a/modules/react-maplibre/src/utils/transform.ts b/modules/react-maplibre/src/utils/transform.ts index bd7f74880..28da658da 100644 --- a/modules/react-maplibre/src/utils/transform.ts +++ b/modules/react-maplibre/src/utils/transform.ts @@ -1,8 +1,25 @@ import type {MaplibreProps} from '../maplibre/maplibre'; import type {ViewState} from '../types/common'; import type {TransformLike} from '../types/internal'; +import type {MapInstance} from '../types/lib'; import {deepEqual} from './deep-equal'; +/** + * maplibre-gl v6 removed the public `map.transform` property in favor of + * discrete getters. Reconstruct a TransformLike snapshot from those getters + * so it works across maplibre-gl v4/v5/v6. + */ +export function getTransformLike(map: MapInstance): TransformLike { + return { + center: map.getCenter(), + zoom: map.getZoom(), + bearing: map.getBearing(), + pitch: map.getPitch(), + elevation: map.getCenterElevation(), + padding: map.getPadding() + }; +} + /** * Capture a transform's current state * @param transform From faf6c1d3fd127845c8efec79f8c71ca25881834c Mon Sep 17 00:00:00 2001 From: mike Date: Mon, 27 Jul 2026 00:05:47 -0400 Subject: [PATCH 02/12] clean up --- docs/whats-new.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/whats-new.md b/docs/whats-new.md index 058a7eeae..8aa5746d4 100644 --- a/docs/whats-new.md +++ b/docs/whats-new.md @@ -1,9 +1,5 @@ # What's new -## react-map-gl v8.2 - -- The Maplibre wrapper (`react-map-gl/maplibre`) now supports `maplibre-gl` v6, which replaced the public `map.transform` property and the `map.transformCameraUpdate` field with getter methods (`getCenter()`, `getZoom()`, etc.) and `map.setTransformCameraUpdate()`. The wrapper now uses these getters and falls back to the old field assignment when running against `maplibre-gl` v4/v5. - ## react-map-gl v8.1 Release date: Oct 2025 From 7abc8f52f6426af3ac51d042d59ed45106731f7e Mon Sep 17 00:00:00 2001 From: mike Date: Mon, 27 Jul 2026 00:11:11 -0400 Subject: [PATCH 03/12] clean up --- docs/whats-new.md | 61 +++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/docs/whats-new.md b/docs/whats-new.md index 8aa5746d4..3d2c2a405 100644 --- a/docs/whats-new.md +++ b/docs/whats-new.md @@ -14,9 +14,9 @@ Release date: Jan 2025 - First version to support Mapbox GL JS' official types and MapLibre GL JS v5. This version fully separates the code that support each compatible map library: - - `react-map-gl/mapbox`: for use with `mapbox-gl>=3.5.0` - - `react-map-gl/maplibre`: for use with `maplibre-gl>=4` - - `react-map-gl/mapbox-legacy`: for use with `mapbox-gl` v1.x and v2.x and `@types/mapbox-gl` + + `react-map-gl/mapbox`: for use with `mapbox-gl>=3.5.0` + + `react-map-gl/maplibre`: for use with `maplibre-gl>=4` + + `react-map-gl/mapbox-legacy`: for use with `mapbox-gl` v1.x and v2.x and `@types/mapbox-gl` - As a result, each endpoint now have slightly smaller bundle size and more precise types. - Maplibre wrapper is expected to have better functionality and performance than v7 by utilizing an [upstream API](https://github.com/maplibre/maplibre-gl-js/issues/1545) for the React use case. @@ -109,7 +109,7 @@ Release date: Mar 14, 2019 - **New Components**: [`FullscreenControl`](https://github.com/visgl/react-map-gl/tree/4.1-release/docs/components/fullscreen-control.md), [`GeolocateControl`](https://github.com/visgl/react-map-gl/tree/4.1-release/docs/components/geolocate-control.md) have been added to provide better React parity with the `Mapbox GL JS` API. - **New callback props** `InteractiveMap` supports more callbacks: - - `onNativeClick` + + `onNativeClick` ## react-map-gl v4.0 @@ -126,17 +126,17 @@ Release date: Nov 5, 2018 - **Interaction states** `onViewportChange` is now called with richer descriptors of the user interaction, including `isPanning`, `isZooming` and `isRotating`. - **Interactive layers** Dropped the requirement for the deprecated `interactive` property on the layer styles. Use the `interactiveLayerIds` prop to specify which layers are clickable. - **New callback props** `InteractiveMap` supports more callbacks: - - `onDblClick` - - `onMouseDown` - - `onMouseMove` - - `onMouseUp` - - `onTouchStart` - - `onTouchMove` - - `onTouchEnd` - - `onMouseEnter` - - `onMouseLeave` - - `onWheel` - - `onMouseOut` + + `onDblClick` + + `onMouseDown` + + `onMouseMove` + + `onMouseUp` + + `onTouchStart` + + `onTouchMove` + + `onTouchEnd` + + `onMouseEnter` + + `onMouseLeave` + + `onWheel` + + `onMouseOut` See [upgrade guide](./upgrade-guide.md) for breaking changes. @@ -149,6 +149,7 @@ Release date: July, 2018 - **New `viewState` Property**: Makes it possible to specify all map state properties (`longitude`, `latitude`, `zoom`, `bearing` and `pitch`) as a single property. - **New `onViewStateChange` callback**: An alternative callback that matches the new `viewState` prop. + ## react-map-gl v3.2 Realease date: January, 2018 @@ -160,9 +161,10 @@ Realease date: January, 2018 - **Support for Map Reuse (experimental)**: A new property `reuseMaps` is provided for applications that create and destroy maps, to help work around a mapbox-gl resource leak issue that can lead to a browser crash in certain situations. - **mapbox-gl 0.42.2** - **New props** of the InteractiveMap component: - - Map creation: `transformRequest`, `reuseMaps` - - Interaction: `touchZoom`, `touchRotate` - - Transition: `transitionDuration`, `transitionInterpolator`, `transitionEasing`, `transitionInterruption`, `onTransitionStart`, `onTransitionInterrupt`, `onTransitionEnd` + + Map creation: `transformRequest`, `reuseMaps` + + Interaction: `touchZoom`, `touchRotate` + + Transition: `transitionDuration`, `transitionInterpolator`, `transitionEasing`, `transitionInterruption`, `onTransitionStart`, `onTransitionInterrupt`, `onTransitionEnd` + ## react-map-gl v3.1 @@ -171,13 +173,14 @@ Release date: October 19, 2017 ### Highlights - **Event handling** - - Support right mouse drag to rotate - - Support keyboard navigation - - Allow controls and overlays to block map interactions + + Support right mouse drag to rotate + + Support keyboard navigation + + Allow controls and overlays to block map interactions - **React 16** - react-map-gl is now being tested with React 16, but the React peer dependency requirement is unchanged at `>=15.4.x`. - **mapbox-gl v0.40.1** - **No Token warning**: react-map-gl now renders an HTML message if no mapbox token is supplied. + ## react-map-gl v3.0 Release date: July 27th, 2017 @@ -189,7 +192,7 @@ Release date: July 27th, 2017 - **New Components**: The `MapGL` component has been split into [`StaticMap`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/static-map.md) and [`InteractiveMap`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/interactive-map.md) (the default). Also, [`Popup`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/popup.md), [`Marker`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/marker.md), [`NavigationControl`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/navigation-control.md) have been added to provide better React parity with the `Mapbox GL JS` API. - **Improved Overlay Components**: Supplying viewport props (`width` `height` `zoom` `longitude` and `latitude`) are no longer required if you render [`SVGOverlay`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/overlays/svg-overlay.md), [`CanvasOverlay`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/overlays/canvas-overlay.md) or [`HTMLOverlay`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/overlays/html-overlay.md) as a child of the map. Perspective mode is now supported in all overlays. - **New Props**: `maxPitch`, `minPitch`, `dragPan`, `doubleClickZoom`, `touchZoomRotate`, - `scrollZoom` are now provided to allow granular control of map interactivity. +`scrollZoom` are now provided to allow granular control of map interactivity. - **Documentation**: Significantly expanded and linked with our other geospatial frameworks. - **Examples**: New stand-alone examples to get you started instantly with the new features. - **Event Handling**: New event handling architecture that enables full customization of event handling (experimental). @@ -206,35 +209,37 @@ This is the React wrapper around `Mapbox GL JS` and takes in viewport properties #### Overlays -- Three overlays (`ScatterplotOverlay`, `DraggablePointsOverlay`, `ChoroplethOverlay`), have been moved out of the library and are now only provided as examples. +* Three overlays (`ScatterplotOverlay`, `DraggablePointsOverlay`, `ChoroplethOverlay`), have been moved out of the library and are now only provided as examples. ### Property Changes - **Property Names** - some prop names have been modernized, the old ones will still work for now with a warning. - **Internal Properties** such as `isHovering`, `isDragging`, `startDragLngLat` have been removed. - These were never meant to be useful publicly and have caused confusions in the past. +These were never meant to be useful publicly and have caused confusions in the past. ### Utilities -- **fitBounds**: `fitBounds` has been moved to another repository and has been rewritten to provide a more logical interface. +* **fitBounds**: `fitBounds` has been moved to another repository and has been rewritten to provide a more logical interface. For more information, see the `Upgrade Guide`. + ## react-map-gl v2.0 Date: Jan 17, 2017 ### Highlights - - **Latest mapbox-gl**: Bump `mapbox-gl` to v0.31.0 - **new maxZoom prop** - Add `maxZoom` prop and defaults to `20` - **New onLoad prop** - Add `onLoad` event handler - **new onClick prop** - Add `onClick` prop handler (#140) + ## react-map-gl v1.0 -- **Perspective Mode** - Now supports `bearing` and `pitch` properties, per mapbox-gl api documentation. These props default to 0 which means that maps will still be rendered in flat/ortographic mode when they are not provided -- **Support for ES6 imports** - The map overlay components (HTMLOverlay, CanvasOverlay, SVGOverlay etc) previously had to be imported via their relative source paths can now be imported directly. +* **Perspective Mode** - Now supports `bearing` and `pitch` properties, per mapbox-gl api documentation. These props default to 0 which means that maps will still be rendered in flat/ortographic mode when they are not provided +* **Support for ES6 imports** - The map overlay components (HTMLOverlay, CanvasOverlay, SVGOverlay etc) previously had to be imported via their relative source paths can now be imported directly. + ## react-map-gl v0.6 From 3c8e87e543f154d14a2d53b8365a1e86e6e2156c Mon Sep 17 00:00:00 2001 From: mike Date: Mon, 27 Jul 2026 13:01:21 -0400 Subject: [PATCH 04/12] code review --- modules/react-maplibre/src/maplibre/maplibre.ts | 4 ++-- modules/react-maplibre/src/types/events.ts | 15 +++++++++++---- modules/react-maplibre/src/utils/transform.ts | 3 ++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/modules/react-maplibre/src/maplibre/maplibre.ts b/modules/react-maplibre/src/maplibre/maplibre.ts index 4e09aa9bf..9e3b4e3cf 100644 --- a/modules/react-maplibre/src/maplibre/maplibre.ts +++ b/modules/react-maplibre/src/maplibre/maplibre.ts @@ -387,8 +387,8 @@ export default class Maplibre { const {viewState} = nextProps; if (viewState) { const map = this._map; - const container = map.getContainer(); - if (viewState.width !== container.clientWidth || viewState.height !== container.clientHeight) { + const canvas = map.getCanvas(); + if (viewState.width !== canvas.clientWidth || viewState.height !== canvas.clientHeight) { map.resize(); return true; } diff --git a/modules/react-maplibre/src/types/events.ts b/modules/react-maplibre/src/types/events.ts index 6aa9bde63..bcda953a4 100644 --- a/modules/react-maplibre/src/types/events.ts +++ b/modules/react-maplibre/src/types/events.ts @@ -12,10 +12,18 @@ import type { MapLayerTouchEvent, MapStyleDataEvent, MapSourceDataEvent, - MapWheelEvent, - MapBoxZoomEvent + MapWheelEvent } from 'maplibre-gl'; +// Defined locally instead of imported: maplibre-gl renamed this type from +// `MapLibreZoomEvent` (v4/v5) to `MapBoxZoomEvent` (v6). Both versions' +// exports share this shape, so redeclaring it avoids depending on either name. +export type MapBoxZoomEvent = { + type: 'boxzoomstart' | 'boxzoomend' | 'boxzoomcancel'; + target: Map; + originalEvent: MouseEvent; +}; + export type { MapLibreEvent as MapEvent, MapLayerMouseEvent, @@ -23,8 +31,7 @@ export type { MapLayerTouchEvent, MapStyleDataEvent, MapSourceDataEvent, - MapWheelEvent, - MapBoxZoomEvent + MapWheelEvent }; export type MapCallbacks = { diff --git a/modules/react-maplibre/src/utils/transform.ts b/modules/react-maplibre/src/utils/transform.ts index 28da658da..bcbe08dd4 100644 --- a/modules/react-maplibre/src/utils/transform.ts +++ b/modules/react-maplibre/src/utils/transform.ts @@ -15,7 +15,8 @@ export function getTransformLike(map: MapInstance): TransformLike { zoom: map.getZoom(), bearing: map.getBearing(), pitch: map.getPitch(), - elevation: map.getCenterElevation(), + // @ts-ignore getCenterElevation does not exist before v5.0.0 + elevation: map.getCenterElevation?.() ?? 0, padding: map.getPadding() }; } From 6648ee0c5639f235c8f227e73079dbb940c43e51 Mon Sep 17 00:00:00 2001 From: Chris Gervang Date: Mon, 27 Jul 2026 17:49:12 -0700 Subject: [PATCH 05/12] test(react-maplibre): cover public camera getters --- .../react-maplibre/src/maplibre/maplibre.ts | 8 ++- .../test/utils/transform.spec.js | 59 +++++++++++++++++-- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/modules/react-maplibre/src/maplibre/maplibre.ts b/modules/react-maplibre/src/maplibre/maplibre.ts index 9e3b4e3cf..d69d2739c 100644 --- a/modules/react-maplibre/src/maplibre/maplibre.ts +++ b/modules/react-maplibre/src/maplibre/maplibre.ts @@ -1,4 +1,8 @@ -import {transformToViewState, applyViewStateToTransform, getTransformLike} from '../utils/transform'; +import { + transformToViewState, + applyViewStateToTransform, + getTransformLike +} from '../utils/transform'; import {normalizeStyle} from '../utils/style-utils'; import {deepEqual} from '../utils/deep-equal'; @@ -311,7 +315,7 @@ export default class Maplibre { } // add listeners - if (map.setTransformCameraUpdate) { + if (typeof map.setTransformCameraUpdate === 'function') { // maplibre-gl v6+ map.setTransformCameraUpdate(this._onCameraUpdate); } else { diff --git a/modules/react-maplibre/test/utils/transform.spec.js b/modules/react-maplibre/test/utils/transform.spec.js index 25e575540..2ef046c20 100644 --- a/modules/react-maplibre/test/utils/transform.spec.js +++ b/modules/react-maplibre/test/utils/transform.spec.js @@ -1,13 +1,64 @@ import test from 'tape-promise/tape'; import { + getTransformLike, transformToViewState, applyViewStateToTransform } from '@vis.gl/react-maplibre/utils/transform'; -import maplibregl from 'maplibre-gl'; +import {LngLat} from 'maplibre-gl'; + +test('getTransformLike', t => { + const center = new LngLat(-122.45, 37.78); + const padding = {top: 1, left: 2, right: 3, bottom: 4}; + const map = { + get transform() { + throw new Error('map.transform should not be accessed'); + }, + getCenter: () => center, + getZoom: () => 10.5, + getBearing: () => -70, + getPitch: () => 30, + getCenterElevation: () => 100, + getPadding: () => padding + }; + + const tr = getTransformLike(map); + + t.is(tr.center, center, 'center retains its LngLat instance'); + t.is(tr.padding, padding, 'padding retains its identity'); + t.deepEqual( + tr, + { + center, + zoom: 10.5, + bearing: -70, + pitch: 30, + elevation: 100, + padding + }, + 'camera state is read from public getters' + ); + + t.end(); +}); + +test('getTransformLike#pre-v5', t => { + const center = new LngLat(-122.45, 37.78); + const map = { + getCenter: () => center, + getZoom: () => 10.5, + getBearing: () => -70, + getPitch: () => 30, + getPadding: () => ({top: 0, left: 0, right: 0, bottom: 0}) + }; + + t.is(getTransformLike(map).elevation, 0, 'missing center elevation defaults to zero'); + + t.end(); +}); test('transformToViewState', t => { const tr = { - center: new maplibregl.LngLat(-122.45, 37.78), + center: new LngLat(-122.45, 37.78), zoom: 10.5, bearing: -70, pitch: 30, @@ -28,7 +79,7 @@ test('transformToViewState', t => { test('applyViewStateToTransform', t => { const tr = { - center: new maplibregl.LngLat(-122.45, 37.78), + center: new LngLat(-122.45, 37.78), zoom: 10.5, bearing: -70, pitch: 30, @@ -42,7 +93,7 @@ test('applyViewStateToTransform', t => { t.deepEqual( changed, { - center: new maplibregl.LngLat(-10, 5) + center: new LngLat(-10, 5) }, 'center changed' ); From 16f20fddb5e8b5944d925f6fc72b1b89ef2a7c93 Mon Sep 17 00:00:00 2001 From: Chris Gervang Date: Mon, 27 Jul 2026 23:23:58 -0700 Subject: [PATCH 06/12] fix(react-maplibre): bridge box zoom event types --- modules/react-maplibre/src/types/events.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/modules/react-maplibre/src/types/events.ts b/modules/react-maplibre/src/types/events.ts index bcda953a4..2c3e922aa 100644 --- a/modules/react-maplibre/src/types/events.ts +++ b/modules/react-maplibre/src/types/events.ts @@ -10,19 +10,16 @@ import type { MapLayerMouseEvent, MapTouchEvent, MapLayerTouchEvent, + MapEventType, MapStyleDataEvent, MapSourceDataEvent, MapWheelEvent } from 'maplibre-gl'; -// Defined locally instead of imported: maplibre-gl renamed this type from -// `MapLibreZoomEvent` (v4/v5) to `MapBoxZoomEvent` (v6). Both versions' -// exports share this shape, so redeclaring it avoids depending on either name. -export type MapBoxZoomEvent = { - type: 'boxzoomstart' | 'boxzoomend' | 'boxzoomcancel'; - target: Map; - originalEvent: MouseEvent; -}; +// MapLibre renamed this type from `MapLibreZoomEvent` (v4/v5) to +// `MapBoxZoomEvent` (v6). The event map is exported under the same name +// across supported versions. +export type MapBoxZoomEvent = MapEventType['boxzoomstart' | 'boxzoomend' | 'boxzoomcancel']; export type { MapLibreEvent as MapEvent, From 4ec12f5ef640c20fcf06a5297b21fa6d7ed7a4a7 Mon Sep 17 00:00:00 2001 From: Chris Gervang Date: Mon, 27 Jul 2026 23:36:59 -0700 Subject: [PATCH 07/12] fix: deduplicate gl-matrix dependency --- package.json | 3 + yarn.lock | 155 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 111 insertions(+), 47 deletions(-) diff --git a/package.json b/package.json index d57426b99..aa6f513c4 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,9 @@ "react-dom": "^18.0.0", "typescript": "^5.0.0" }, + "resolutions": { + "gl-matrix": "3.4.4" + }, "pre-commit": [ "test-fast" ], diff --git a/yarn.lock b/yarn.lock index 638e5e817..32f2c3fc0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -508,7 +508,7 @@ resolved "https://registry.yarnpkg.com/@luma.gl/constants/-/constants-9.0.28.tgz#beda6d1c716a2e546dae7e46008105b1cd94cb6f" integrity sha512-mw3YwYfCbpCa8y28nNZGaJemprSkqthsunz0V79qpnMrFD3pOMIh+rw/hjQuqVW9ffmSXx+xY2bI8FT1YC8f7A== -"@mapbox/geojson-rewind@^0.5.0", "@mapbox/geojson-rewind@^0.5.2": +"@mapbox/geojson-rewind@^0.5.0": version "0.5.2" resolved "https://registry.yarnpkg.com/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz#591a5d71a9cd1da1a0bf3420b3bea31b0fc7946a" integrity sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA== @@ -526,6 +526,11 @@ resolved "https://registry.yarnpkg.com/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz#ce56e539f83552b58d10d672ea4d6fc9adc7b234" integrity sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ== +"@mapbox/jsonlint-lines-primitives@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.3.tgz#7d7b0b971fbaf6d60953272db4df03020d3fb004" + integrity sha512-0SElaV0uMxEnxzBhhX9WTuPyUeMsAN/SS0i16tjuba4/mio63MG9khjC1a0JAiPGXAwvwm4UfHJURCN7nyudQg== + "@mapbox/mapbox-gl-supported@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-1.5.0.tgz#f60b6a55a5d8e5ee908347d2ce4250b15103dc8e" @@ -541,6 +546,11 @@ resolved "https://registry.yarnpkg.com/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz#8a83f9335c7860effa2eeeca254332aa0aeed8f2" integrity sha1-ioP5M1x4YO/6Lu7KJUMyqgru2PI= +"@mapbox/point-geometry@^1.1.0", "@mapbox/point-geometry@~1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz#3328fb54b3a1273bc619bf0a6baad8de37181749" + integrity sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ== + "@mapbox/tiny-sdf@^1.1.1": version "1.2.5" resolved "https://registry.yarnpkg.com/@mapbox/tiny-sdf/-/tiny-sdf-1.2.5.tgz#424c620a96442b20402552be70a7f62a8407cc59" @@ -551,6 +561,11 @@ resolved "https://registry.yarnpkg.com/@mapbox/tiny-sdf/-/tiny-sdf-2.0.6.tgz#9a1d33e5018093e88f6a4df2343e886056287282" integrity sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA== +"@mapbox/tiny-sdf@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@mapbox/tiny-sdf/-/tiny-sdf-2.2.0.tgz#95dae0dc371b8c55c53d70f3e25d56823427f4c8" + integrity sha512-LVL4wgI9YAum5V+LNVQO6QgFBPw7/MIIY4XJPNsPDMrjEwcE+JfKk1LuIl8GnF197ejVdC9QdPaxrx5gfgdGXg== + "@mapbox/unitbezier@^0.0.0": version "0.0.0" resolved "https://registry.yarnpkg.com/@mapbox/unitbezier/-/unitbezier-0.0.0.tgz#15651bd553a67b8581fb398810c98ad86a34524e" @@ -561,6 +576,11 @@ resolved "https://registry.yarnpkg.com/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz#d32deb66c7177e9e9dfc3bbd697083e2e657ff01" integrity sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw== +"@mapbox/unitbezier@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@mapbox/unitbezier/-/unitbezier-1.0.0.tgz#54319aff6c467bb1b909e04895c08cdb966bfbff" + integrity sha512-fqd515fjBmANKGGsQ286E2Wvj/XvDFpGzwJxq4CI6jMQue6Oy04uCKp+JWKF00xRTmk6cEu1jPJ9p3xqH8YWqQ== + "@mapbox/vector-tile@^1.3.1": version "1.3.1" resolved "https://registry.yarnpkg.com/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz#d3a74c90402d06e89ec66de49ec817ff53409666" @@ -568,11 +588,27 @@ dependencies: "@mapbox/point-geometry" "~0.1.0" +"@mapbox/vector-tile@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@mapbox/vector-tile/-/vector-tile-3.0.0.tgz#71a75acb5ee20c20adca5c4e1ffb5ef95a56e351" + integrity sha512-Qf10S1uIHMk20ri/IVBnpS+esUEkVaR5Hftmz88jTInrpmWgPGJfPe3LVjjlE77trLx8tH6qjTG7uWH9hIq/0Q== + dependencies: + "@mapbox/point-geometry" "~1.1.0" + "@types/geojson" "^7946.0.16" + pbf "^5.0.0" + "@mapbox/whoots-js@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe" integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q== +"@maplibre/geojson-vt@^6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@maplibre/geojson-vt/-/geojson-vt-6.1.1.tgz#25a032435b4ce2236ea0ba911aff5fb6d5454fc1" + integrity sha512-FVMOcmSP/yqol45t7StApEyTL5/vmqBCuFhH9n+fFuINenhaX+YgHHIt1yJ86S8kln3uJLcMvmEU2cfn6E2eCQ== + dependencies: + kdbush "^4.1.0" + "@maplibre/maplibre-gl-style-spec@^19.2.1": version "19.3.3" resolved "https://registry.yarnpkg.com/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-19.3.3.tgz#a106248bd2e25e77c963a362aeaf630e00f924e9" @@ -585,19 +621,34 @@ rw "^1.3.3" sort-object "^3.0.3" -"@maplibre/maplibre-gl-style-spec@^23.0.0": - version "23.1.0" - resolved "https://registry.yarnpkg.com/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-23.1.0.tgz#ad59731b0547ee0986ba4ccff699894dd60f0650" - integrity sha512-R6/ihEuC5KRexmKIYkWqUv84Gm+/QwsOUgHyt1yy2XqCdGdLvlBWVWIIeTZWN4NGdwmY6xDzdSGU2R9oBLNg2w== +"@maplibre/maplibre-gl-style-spec@^26.1.0": + version "26.2.1" + resolved "https://registry.yarnpkg.com/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-26.2.1.tgz#00eb056468c6957bc762088a085ded91000caee8" + integrity sha512-QFKCXkOeSzOr8jF75jm6kySOg+dUvOehPhRi68gcOYPHb7U5JloUq0dJW0Y5/fZV8ygfT0Vp2RWodvq+fyxFWA== dependencies: - "@mapbox/jsonlint-lines-primitives" "~2.0.2" - "@mapbox/unitbezier" "^0.0.1" + "@mapbox/jsonlint-lines-primitives" "^2.0.3" + "@mapbox/unitbezier" "^1.0.0" json-stringify-pretty-compact "^4.0.0" minimist "^1.2.8" quickselect "^3.0.0" - rw "^1.3.3" tinyqueue "^3.0.0" +"@maplibre/mlt@^1.1.12": + version "1.1.12" + resolved "https://registry.yarnpkg.com/@maplibre/mlt/-/mlt-1.1.12.tgz#32c5e41eeb765a107125ec92a8533cb27cddf253" + integrity sha512-ZeK5w2TTeHOajcLaEQs1KZXw2V9wIKo1PmThlxlsHoXsQsYlBqLJzPOd6tJHRtGTChUY3DPPmjXRArYVvAbmZw== + dependencies: + "@mapbox/point-geometry" "^1.1.0" + +"@maplibre/vt-pbf@^4.3.2": + version "4.3.2" + resolved "https://registry.yarnpkg.com/@maplibre/vt-pbf/-/vt-pbf-4.3.2.tgz#cfcdbdadaf88b4cb8645e43c8eead77cd6546030" + integrity sha512-j6p0AdjvAR19Z3XaCysle7A4ZSo08tYOzxD0Y9NQylwPAkwJJeYub5b2eVucdeDh7erhv69DahoLOevDRERRUw== + dependencies: + "@mapbox/point-geometry" "^1.1.0" + "@types/geojson" "^7946.0.16" + pbf "^5.1.0" + "@napi-rs/wasm-runtime@0.2.4": version "0.2.4" resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz#d27788176f250d86e498081e3c5ff48a17606918" @@ -1119,7 +1170,7 @@ dependencies: tslib "^2.4.0" -"@types/geojson-vt@3.2.5", "@types/geojson-vt@^3.2.5": +"@types/geojson-vt@^3.2.5": version "3.2.5" resolved "https://registry.yarnpkg.com/@types/geojson-vt/-/geojson-vt-3.2.5.tgz#b6c356874991d9ab4207533476dfbcdb21e38408" integrity sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g== @@ -1136,6 +1187,11 @@ resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.15.tgz#f9d55fd5a0aa2de9dc80b1b04e437538b7298868" integrity sha512-9oSxFzDCT2Rj6DfcHF8G++jxBKS7mBqXl5xrRW+Kbvjry6Uduya2iiwqHPhVXpasAVMBYKkEPGgKhd3+/HZ6xA== +"@types/geojson@^7946.0.16": + version "7946.0.16" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.16.tgz#8ebe53d69efada7044454e3305c19017d97ced2a" + integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg== + "@types/istanbul-lib-coverage@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" @@ -2672,11 +2728,16 @@ earcut@^2.2.2: resolved "https://registry.yarnpkg.com/earcut/-/earcut-2.2.4.tgz#6d02fd4d68160c114825d06890a92ecaae60343a" integrity sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ== -earcut@^3.0.0, earcut@^3.0.1: +earcut@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/earcut/-/earcut-3.0.1.tgz#f60b3f671c5657cca9d3e131c5527c5dde00ef38" integrity sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw== +earcut@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/earcut/-/earcut-3.2.3.tgz#74aec19555a7e28773429826729d2e4bfeb19022" + integrity sha512-vnS4AVwp1KHAF13i1vp1/2D5evWy3k5u/iW/B81QVsUZtV8cv2tU0b2VNFlqvh4kYwrFMDdjPCfAmfyJW9y14Q== + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -3730,10 +3791,10 @@ gitconfiglocal@^1.0.0: dependencies: ini "^1.3.2" -gl-matrix@^3.2.1, gl-matrix@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-3.4.3.tgz#fc1191e8320009fd4d20e9339595c6041ddc22c9" - integrity sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA== +gl-matrix@3.4.4, gl-matrix@^3.2.1, gl-matrix@^3.4.3, gl-matrix@^3.4.4: + version "3.4.4" + resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-3.4.4.tgz#7789ee4982f62c7a7af447ee488f3bd6b0c77003" + integrity sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ== glob-parent@6.0.2, glob-parent@^6.0.2: version "6.0.2" @@ -4894,6 +4955,11 @@ kdbush@^4.0.2: resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-4.0.2.tgz#2f7b7246328b4657dd122b6c7f025fbc2c868e39" integrity sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA== +kdbush@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-4.1.0.tgz#d504bc0447a59be4fb75533a5c25e316b3ed8859" + integrity sha512-e9vurzrXJQrFX6ckpHP3bvj5l+9CnYzkxDNnNQ1h2QTqdWsUAJgXiKdGNcOa1EY85dU8KbQ+z/FdQdB7P+9yfQ== + kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" @@ -5333,37 +5399,28 @@ mapbox-gl@^3.9.0: tinyqueue "^3.0.0" vt-pbf "^3.1.3" -maplibre-gl@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/maplibre-gl/-/maplibre-gl-5.0.1.tgz#5eeb520de26dca820a12f270164c5eb5db1d16e2" - integrity sha512-kNvod1Tq0BcZvn43UAciA3DrzaEGmowqMoI6nh3kUo9rf+7m89mFJI9dELxkWzJ/N9Pgnkp7xF1jzTP08PGpCw== - dependencies: - "@mapbox/geojson-rewind" "^0.5.2" - "@mapbox/jsonlint-lines-primitives" "^2.0.2" - "@mapbox/point-geometry" "^0.1.0" - "@mapbox/tiny-sdf" "^2.0.6" - "@mapbox/unitbezier" "^0.0.1" - "@mapbox/vector-tile" "^1.3.1" - "@mapbox/whoots-js" "^3.1.0" - "@maplibre/maplibre-gl-style-spec" "^23.0.0" - "@types/geojson" "^7946.0.15" - "@types/geojson-vt" "3.2.5" - "@types/mapbox__point-geometry" "^0.1.4" - "@types/mapbox__vector-tile" "^1.3.4" - "@types/pbf" "^3.0.5" - "@types/supercluster" "^7.1.3" - earcut "^3.0.1" - geojson-vt "^4.0.2" - gl-matrix "^3.4.3" - global-prefix "^4.0.0" - kdbush "^4.0.2" +maplibre-gl@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/maplibre-gl/-/maplibre-gl-6.0.0.tgz#b1fc03697cdd21e03eeeae88030b976305d1d268" + integrity sha512-1wBgEhzTZfA+cDpFdt0fM1mJA5mJ90fifORJ7D8JcKLJCvPT/iTx9bNxkP7DqEYde65DJd7gE7h83khwNRqdyg== + dependencies: + "@mapbox/point-geometry" "^1.1.0" + "@mapbox/tiny-sdf" "^2.2.0" + "@mapbox/unitbezier" "^1.0.0" + "@mapbox/vector-tile" "^3.0.0" + "@maplibre/geojson-vt" "^6.1.1" + "@maplibre/maplibre-gl-style-spec" "^26.1.0" + "@maplibre/mlt" "^1.1.12" + "@maplibre/vt-pbf" "^4.3.2" + "@types/geojson" "^7946.0.16" + earcut "^3.2.3" + gl-matrix "^3.4.4" + kdbush "^4.1.0" murmurhash-js "^1.0.0" - pbf "^3.3.0" - potpack "^2.0.0" + pbf "^5.1.2" + potpack "^2.1.0" quickselect "^3.0.0" - supercluster "^8.0.1" tinyqueue "^3.0.0" - vt-pbf "^3.1.3" math-intrinsics@^1.1.0: version "1.1.0" @@ -6359,12 +6416,11 @@ pbf@^3.2.1: ieee754 "^1.1.12" resolve-protobuf-schema "^2.1.0" -pbf@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/pbf/-/pbf-3.3.0.tgz#1790f3d99118333cc7f498de816028a346ef367f" - integrity sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q== +pbf@^5.0.0, pbf@^5.1.0, pbf@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/pbf/-/pbf-5.1.2.tgz#07c427819eda32f02f1ec9741558f61444f2e1c0" + integrity sha512-mnvGdvOrIvJOBGUEdGkrVXjN8E/VkIJCkf2eS1DH2yv82ORUlLttmDt0rWY38yYZmVwciZwBUvHM20qxBZf40w== dependencies: - ieee754 "^1.1.12" resolve-protobuf-schema "^2.1.0" pend@~1.2.0: @@ -6463,6 +6519,11 @@ potpack@^2.0.0: resolved "https://registry.yarnpkg.com/potpack/-/potpack-2.0.0.tgz#61f4dd2dc4b3d5e996e3698c0ec9426d0e169104" integrity sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw== +potpack@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/potpack/-/potpack-2.1.0.tgz#fe548e2f9061e9937f17191c1ab6dd98ca30e02f" + integrity sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ== + pre-commit@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/pre-commit/-/pre-commit-1.2.2.tgz#dbcee0ee9de7235e57f79c56d7ce94641a69eec6" From 49fdf12236e12eaa9a87c442e7356984f969e4eb Mon Sep 17 00:00:00 2001 From: Chris Gervang Date: Mon, 27 Jul 2026 23:39:26 -0700 Subject: [PATCH 08/12] chore: rely on deduplicated gl-matrix lockfile --- package.json | 3 --- yarn.lock | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/package.json b/package.json index aa6f513c4..d57426b99 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,6 @@ "react-dom": "^18.0.0", "typescript": "^5.0.0" }, - "resolutions": { - "gl-matrix": "3.4.4" - }, "pre-commit": [ "test-fast" ], diff --git a/yarn.lock b/yarn.lock index 32f2c3fc0..c69487ed1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3791,7 +3791,7 @@ gitconfiglocal@^1.0.0: dependencies: ini "^1.3.2" -gl-matrix@3.4.4, gl-matrix@^3.2.1, gl-matrix@^3.4.3, gl-matrix@^3.4.4: +gl-matrix@^3.2.1, gl-matrix@^3.4.3, gl-matrix@^3.4.4: version "3.4.4" resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-3.4.4.tgz#7789ee4982f62c7a7af447ee488f3bd6b0c77003" integrity sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ== From a2e8b03a9fc306b1172d242b5b358e16c5ba6042 Mon Sep 17 00:00:00 2001 From: Chris Gervang Date: Tue, 28 Jul 2026 16:47:02 -0700 Subject: [PATCH 09/12] test: configure MapLibre worker for browser tests --- test/browser.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/browser.js b/test/browser.js index 327bdbb80..80d36a12d 100644 --- a/test/browser.js +++ b/test/browser.js @@ -1,5 +1,10 @@ /* global window */ import test from 'tape'; +import {setWorkerUrl} from 'maplibre-gl'; + +// MapLibre v6 resolves its worker relative to import.meta.url. Vite prebundles +// dependencies into .vite/deps, where the sibling worker file is not present. +setWorkerUrl('/node_modules/maplibre-gl/dist/maplibre-gl-worker.mjs'); test.onFinish(window.browserTestDriver_finish); test.onFailure(window.browserTestDriver_fail); From 2a22d6a3427b9175830d810f0041613511944f38 Mon Sep 17 00:00:00 2001 From: Chris Gervang Date: Tue, 28 Jul 2026 16:55:24 -0700 Subject: [PATCH 10/12] ci: test MapLibre v6 --- .github/workflows/test.yml | 2 +- test/browser.js | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3c400c4cc..61d91cc64 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - maplibre: ['^4.0.0', '^5.0.0'] + maplibre: ['^4.0.0', '^5.0.0', '^6.0.0'] permissions: checks: write contents: read diff --git a/test/browser.js b/test/browser.js index 80d36a12d..3bd6069c7 100644 --- a/test/browser.js +++ b/test/browser.js @@ -1,10 +1,12 @@ /* global window */ import test from 'tape'; -import {setWorkerUrl} from 'maplibre-gl'; +import {getVersion, setWorkerUrl} from 'maplibre-gl'; // MapLibre v6 resolves its worker relative to import.meta.url. Vite prebundles // dependencies into .vite/deps, where the sibling worker file is not present. -setWorkerUrl('/node_modules/maplibre-gl/dist/maplibre-gl-worker.mjs'); +if (Number.parseInt(getVersion(), 10) >= 6) { + setWorkerUrl('/node_modules/maplibre-gl/dist/maplibre-gl-worker.mjs'); +} test.onFinish(window.browserTestDriver_finish); test.onFailure(window.browserTestDriver_fail); From 5fb47e435a06ac0e08d8ee7a61a06af84af7733b Mon Sep 17 00:00:00 2001 From: Chris Gervang Date: Tue, 28 Jul 2026 16:59:18 -0700 Subject: [PATCH 11/12] fix(react-maplibre): bridge versioned MapLibre types --- modules/react-maplibre/src/components/layer.ts | 14 +++++++++----- modules/react-maplibre/src/maplibre/maplibre.ts | 13 ++++++++----- .../react-maplibre/test/utils/transform.spec.js | 4 +++- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/modules/react-maplibre/src/components/layer.ts b/modules/react-maplibre/src/components/layer.ts index 9cc0981b8..7f70b1c57 100644 --- a/modules/react-maplibre/src/components/layer.ts +++ b/modules/react-maplibre/src/components/layer.ts @@ -5,7 +5,6 @@ import {deepEqual} from '../utils/deep-equal'; import type {MapInstance, CustomLayerInterface} from '../types/lib'; import type {LayerSpecification} from '../types/style-spec'; -import type {AllLayoutProperties, AllPaintProperties} from 'maplibre-gl'; // Omiting property from a union type, see // https://github.com/microsoft/TypeScript/issues/39556#issuecomment-656925230 @@ -26,6 +25,11 @@ function updateLayer(map: MapInstance, id: string, props: LayerProps, prevProps: return; } + const mapWithLayerPropertySetters = map as { + setLayoutProperty(layerId: string, name: string, value: unknown): void; + setPaintProperty(layerId: string, name: string, value: unknown): void; + }; + // @ts-ignore filter does not exist in some Layer types const {layout = {}, paint = {}, filter, minzoom, maxzoom, beforeId} = props; @@ -36,12 +40,12 @@ function updateLayer(map: MapInstance, id: string, props: LayerProps, prevProps: const prevLayout = prevProps.layout || {}; for (const key in layout) { if (!deepEqual(layout[key], prevLayout[key])) { - map.setLayoutProperty(id, key as keyof AllLayoutProperties, layout[key]); + mapWithLayerPropertySetters.setLayoutProperty(id, key, layout[key]); } } for (const key in prevLayout) { if (!layout.hasOwnProperty(key)) { - map.setLayoutProperty(id, key as keyof AllLayoutProperties, undefined); + mapWithLayerPropertySetters.setLayoutProperty(id, key, undefined); } } } @@ -49,12 +53,12 @@ function updateLayer(map: MapInstance, id: string, props: LayerProps, prevProps: const prevPaint = prevProps.paint || {}; for (const key in paint) { if (!deepEqual(paint[key], prevPaint[key])) { - map.setPaintProperty(id, key as keyof AllPaintProperties, paint[key]); + mapWithLayerPropertySetters.setPaintProperty(id, key, paint[key]); } } for (const key in prevPaint) { if (!paint.hasOwnProperty(key)) { - map.setPaintProperty(id, key as keyof AllPaintProperties, undefined); + mapWithLayerPropertySetters.setPaintProperty(id, key, undefined); } } } diff --git a/modules/react-maplibre/src/maplibre/maplibre.ts b/modules/react-maplibre/src/maplibre/maplibre.ts index 60987e5c5..3bef84e39 100644 --- a/modules/react-maplibre/src/maplibre/maplibre.ts +++ b/modules/react-maplibre/src/maplibre/maplibre.ts @@ -26,7 +26,7 @@ import type { ProjectionSpecification } from '../types/style-spec'; import type {MapInstance} from '../types/lib'; -import type {MapEventType} from 'maplibre-gl'; +import type {CameraUpdateTransformFunction, MapEventType} from 'maplibre-gl'; import type { MapCallbacks, ViewStateChangeEvent, @@ -334,12 +334,15 @@ export default class Maplibre { } // add listeners - if (typeof map.setTransformCameraUpdate === 'function') { + const mapWithCameraUpdate = map as MapInstance & { + setTransformCameraUpdate?: (value: CameraUpdateTransformFunction | null) => void; + transformCameraUpdate?: CameraUpdateTransformFunction | null; + }; + if (typeof mapWithCameraUpdate.setTransformCameraUpdate === 'function') { // maplibre-gl v6+ - map.setTransformCameraUpdate(this._onCameraUpdate); + mapWithCameraUpdate.setTransformCameraUpdate(this._onCameraUpdate); } else { - // @ts-ignore transformCameraUpdate does not exist in v6, replaced by setTransformCameraUpdate() - map.transformCameraUpdate = this._onCameraUpdate; + mapWithCameraUpdate.transformCameraUpdate = this._onCameraUpdate; } map.on('style.load', () => { // Map style has changed, this would have wiped out all settings from props diff --git a/modules/react-maplibre/test/utils/transform.spec.js b/modules/react-maplibre/test/utils/transform.spec.js index 9fa706793..1402c310a 100644 --- a/modules/react-maplibre/test/utils/transform.spec.js +++ b/modules/react-maplibre/test/utils/transform.spec.js @@ -6,7 +6,9 @@ import { updateZoomConstraint, updatePitchConstraint } from '@vis.gl/react-maplibre/utils/transform'; -import {LngLat} from 'maplibre-gl'; +import * as maplibregl from 'maplibre-gl'; + +const {LngLat} = maplibregl.default || maplibregl; test('getTransformLike', t => { const center = new LngLat(-122.45, 37.78); From 732bbef99de444523fa46a79aa9cc6b6d618ea97 Mon Sep 17 00:00:00 2001 From: Chris Gervang Date: Tue, 28 Jul 2026 18:23:57 -0700 Subject: [PATCH 12/12] refactor(react-maplibre): simplify layer property setters --- modules/react-maplibre/src/components/layer.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/modules/react-maplibre/src/components/layer.ts b/modules/react-maplibre/src/components/layer.ts index 7f70b1c57..439be9c8d 100644 --- a/modules/react-maplibre/src/components/layer.ts +++ b/modules/react-maplibre/src/components/layer.ts @@ -25,11 +25,6 @@ function updateLayer(map: MapInstance, id: string, props: LayerProps, prevProps: return; } - const mapWithLayerPropertySetters = map as { - setLayoutProperty(layerId: string, name: string, value: unknown): void; - setPaintProperty(layerId: string, name: string, value: unknown): void; - }; - // @ts-ignore filter does not exist in some Layer types const {layout = {}, paint = {}, filter, minzoom, maxzoom, beforeId} = props; @@ -40,12 +35,12 @@ function updateLayer(map: MapInstance, id: string, props: LayerProps, prevProps: const prevLayout = prevProps.layout || {}; for (const key in layout) { if (!deepEqual(layout[key], prevLayout[key])) { - mapWithLayerPropertySetters.setLayoutProperty(id, key, layout[key]); + map.setLayoutProperty(id, key as any, layout[key]); } } for (const key in prevLayout) { if (!layout.hasOwnProperty(key)) { - mapWithLayerPropertySetters.setLayoutProperty(id, key, undefined); + map.setLayoutProperty(id, key as any, undefined); } } } @@ -53,12 +48,12 @@ function updateLayer(map: MapInstance, id: string, props: LayerProps, prevProps: const prevPaint = prevProps.paint || {}; for (const key in paint) { if (!deepEqual(paint[key], prevPaint[key])) { - mapWithLayerPropertySetters.setPaintProperty(id, key, paint[key]); + map.setPaintProperty(id, key as any, paint[key]); } } for (const key in prevPaint) { if (!paint.hasOwnProperty(key)) { - mapWithLayerPropertySetters.setPaintProperty(id, key, undefined); + map.setPaintProperty(id, key as any, undefined); } } }