mirror of
https://github.com/visgl/react-map-gl.git
synced 2026-01-18 15:54:22 +00:00
[v8] Align type names across modules (#2468)
This commit is contained in:
parent
2785a32263
commit
4f856f0838
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@ -7,7 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
check_branch:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
should_build: ${{ steps.permitted.outputs.result }}
|
||||
|
||||
@ -30,7 +30,7 @@ jobs:
|
||||
echo "result=${result}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
needs: check_branch
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
@ -1,32 +1,28 @@
|
||||
import * as React from 'react';
|
||||
import {useEffect, memo} from 'react';
|
||||
import {applyReactStyle} from '../utils/apply-react-style';
|
||||
import useControl from './use-control';
|
||||
import {useControl} from './use-control';
|
||||
|
||||
import type {ControlPosition, AttributionControlInstance} from '../types';
|
||||
import type {ControlPosition, AttributionControlOptions} from '../types/lib';
|
||||
|
||||
export type AttributionControlProps<OptionsT> = OptionsT & {
|
||||
export type AttributionControlProps = AttributionControlOptions & {
|
||||
/** Placement of the control relative to the map. */
|
||||
position?: ControlPosition;
|
||||
/** CSS style override, applied to the control's container */
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
|
||||
function AttributionControl<AttributionControlOptions, ControlT extends AttributionControlInstance>(
|
||||
props: AttributionControlProps<AttributionControlOptions>
|
||||
): null {
|
||||
const ctrl = useControl<ControlT>(
|
||||
({mapLib}) => new mapLib.AttributionControl(props) as ControlT,
|
||||
{
|
||||
position: props.position
|
||||
}
|
||||
);
|
||||
function _AttributionControl(props: AttributionControlProps) {
|
||||
const ctrl = useControl(({mapLib}) => new mapLib.AttributionControl(props), {
|
||||
position: props.position
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// @ts-expect-error accessing private member
|
||||
applyReactStyle(ctrl._container, props.style);
|
||||
}, [props.style]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default memo(AttributionControl);
|
||||
export const AttributionControl = memo(_AttributionControl);
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
import * as React from 'react';
|
||||
import {useEffect, memo} from 'react';
|
||||
import {applyReactStyle} from '../utils/apply-react-style';
|
||||
import useControl from './use-control';
|
||||
import {useControl} from './use-control';
|
||||
|
||||
import type {ControlPosition, FullscreenControlInstance} from '../types';
|
||||
import type {ControlPosition, FullscreenControlOptions} from '../types/lib';
|
||||
|
||||
export type FullscreenControlProps<OptionsT> = Omit<OptionsT, 'container'> & {
|
||||
export type FullscreenControlProps = Omit<FullscreenControlOptions, 'container'> & {
|
||||
/** Id of the DOM element which should be made full screen. By default, the map container
|
||||
* element will be made full screen. */
|
||||
containerId?: string;
|
||||
@ -16,22 +16,21 @@ export type FullscreenControlProps<OptionsT> = Omit<OptionsT, 'container'> & {
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
|
||||
function FullscreenControl<FullscreenControlOptions, ControlT extends FullscreenControlInstance>(
|
||||
props: FullscreenControlProps<FullscreenControlOptions>
|
||||
): null {
|
||||
const ctrl = useControl<ControlT>(
|
||||
function _FullscreenControl(props: FullscreenControlProps) {
|
||||
const ctrl = useControl(
|
||||
({mapLib}) =>
|
||||
new mapLib.FullscreenControl({
|
||||
container: props.containerId && document.getElementById(props.containerId)
|
||||
}) as ControlT,
|
||||
}),
|
||||
{position: props.position}
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// @ts-expect-error accessing private member
|
||||
applyReactStyle(ctrl._controlContainer, props.style);
|
||||
}, [props.style]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default memo(FullscreenControl);
|
||||
export const FullscreenControl = memo(_FullscreenControl);
|
||||
|
||||
@ -1,74 +1,68 @@
|
||||
import * as React from 'react';
|
||||
import {useImperativeHandle, useRef, useEffect, forwardRef, memo} from 'react';
|
||||
import {applyReactStyle} from '../utils/apply-react-style';
|
||||
import useControl from './use-control';
|
||||
import {useControl} from './use-control';
|
||||
|
||||
import type {
|
||||
ControlPosition,
|
||||
GeolocateControlInstance,
|
||||
GeolocateEvent,
|
||||
GeolocateResultEvent,
|
||||
GeolocateErrorEvent
|
||||
} from '../types';
|
||||
GeolocateControlOptions
|
||||
} from '../types/lib';
|
||||
import type {GeolocateEvent, GeolocateResultEvent, GeolocateErrorEvent} from '../types/events';
|
||||
|
||||
export type GeolocateControlProps<
|
||||
OptionsT,
|
||||
ControlT extends GeolocateControlInstance
|
||||
> = OptionsT & {
|
||||
export type GeolocateControlProps = GeolocateControlOptions & {
|
||||
/** Placement of the control relative to the map. */
|
||||
position?: ControlPosition;
|
||||
/** CSS style override, applied to the control's container */
|
||||
style?: React.CSSProperties;
|
||||
|
||||
/** Called on each Geolocation API position update that returned as success. */
|
||||
onGeolocate?: (e: GeolocateResultEvent<ControlT>) => void;
|
||||
onGeolocate?: (e: GeolocateResultEvent) => void;
|
||||
/** Called on each Geolocation API position update that returned as an error. */
|
||||
onError?: (e: GeolocateErrorEvent<ControlT>) => void;
|
||||
onError?: (e: GeolocateErrorEvent) => void;
|
||||
/** Called on each Geolocation API position update that returned as success but user position
|
||||
* is out of map `maxBounds`. */
|
||||
onOutOfMaxBounds?: (e: GeolocateResultEvent<ControlT>) => void;
|
||||
onOutOfMaxBounds?: (e: GeolocateResultEvent) => void;
|
||||
/** Called when the GeolocateControl changes to the active lock state. */
|
||||
onTrackUserLocationStart?: (e: GeolocateEvent<ControlT>) => void;
|
||||
onTrackUserLocationStart?: (e: GeolocateEvent) => void;
|
||||
/** Called when the GeolocateControl changes to the background state. */
|
||||
onTrackUserLocationEnd?: (e: GeolocateEvent<ControlT>) => void;
|
||||
onTrackUserLocationEnd?: (e: GeolocateEvent) => void;
|
||||
};
|
||||
|
||||
function GeolocateControl<GeolocateControlOptions, ControlT extends GeolocateControlInstance>(
|
||||
props: GeolocateControlProps<GeolocateControlOptions, ControlT>,
|
||||
ref: React.Ref<ControlT>
|
||||
) {
|
||||
function _GeolocateControl(props: GeolocateControlProps, ref: React.Ref<GeolocateControlInstance>) {
|
||||
const thisRef = useRef({props});
|
||||
|
||||
const ctrl = useControl<ControlT>(
|
||||
const ctrl = useControl(
|
||||
({mapLib}) => {
|
||||
const gc = new mapLib.GeolocateControl(props) as ControlT;
|
||||
const gc = new mapLib.GeolocateControl(props);
|
||||
|
||||
// Hack: fix GeolocateControl reuse
|
||||
// When using React strict mode, the component is mounted twice.
|
||||
// GeolocateControl's UI creation is asynchronous. Removing and adding it back causes the UI to be initialized twice.
|
||||
// @ts-expect-error private method
|
||||
const setupUI = gc._setupUI;
|
||||
// @ts-expect-error private method
|
||||
// @ts-expect-error accessing private method
|
||||
const setupUI = gc._setupUI.bind(gc);
|
||||
// @ts-expect-error overriding private method
|
||||
gc._setupUI = args => {
|
||||
// @ts-expect-error accessing private member
|
||||
if (!gc._container.hasChildNodes()) {
|
||||
setupUI(args);
|
||||
}
|
||||
};
|
||||
|
||||
gc.on('geolocate', e => {
|
||||
thisRef.current.props.onGeolocate?.(e as GeolocateResultEvent<ControlT>);
|
||||
thisRef.current.props.onGeolocate?.(e as GeolocateResultEvent);
|
||||
});
|
||||
gc.on('error', e => {
|
||||
thisRef.current.props.onError?.(e as GeolocateErrorEvent<ControlT>);
|
||||
thisRef.current.props.onError?.(e as GeolocateErrorEvent);
|
||||
});
|
||||
gc.on('outofmaxbounds', e => {
|
||||
thisRef.current.props.onOutOfMaxBounds?.(e as GeolocateResultEvent<ControlT>);
|
||||
thisRef.current.props.onOutOfMaxBounds?.(e as GeolocateResultEvent);
|
||||
});
|
||||
gc.on('trackuserlocationstart', e => {
|
||||
thisRef.current.props.onTrackUserLocationStart?.(e as GeolocateEvent<ControlT>);
|
||||
thisRef.current.props.onTrackUserLocationStart?.(e as GeolocateEvent);
|
||||
});
|
||||
gc.on('trackuserlocationend', e => {
|
||||
thisRef.current.props.onTrackUserLocationEnd?.(e as GeolocateEvent<ControlT>);
|
||||
thisRef.current.props.onTrackUserLocationEnd?.(e as GeolocateEvent);
|
||||
});
|
||||
|
||||
return gc;
|
||||
@ -81,10 +75,11 @@ function GeolocateControl<GeolocateControlOptions, ControlT extends GeolocateCon
|
||||
useImperativeHandle(ref, () => ctrl, []);
|
||||
|
||||
useEffect(() => {
|
||||
// @ts-expect-error accessing private member
|
||||
applyReactStyle(ctrl._container, props.style);
|
||||
}, [props.style]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default memo(forwardRef(GeolocateControl));
|
||||
export const GeolocateControl = memo(forwardRef(_GeolocateControl));
|
||||
|
||||
@ -3,25 +3,21 @@ import {MapContext} from './map';
|
||||
import assert from '../utils/assert';
|
||||
import {deepEqual} from '../utils/deep-equal';
|
||||
|
||||
import type {MapInstance, CustomLayerInterface, ILayer} from '../types';
|
||||
import type {MapInstance, CustomLayerInterface} from '../types/lib';
|
||||
import type {AnyLayer} from '../types/style-spec';
|
||||
|
||||
// Omiting property from a union type, see
|
||||
// https://github.com/microsoft/TypeScript/issues/39556#issuecomment-656925230
|
||||
type OptionalId<T> = T extends {id: string} ? Omit<T, 'id'> & {id?: string} : T;
|
||||
type OptionalSource<T> = T extends {source: string} ? Omit<T, 'source'> & {source?: string} : T;
|
||||
|
||||
export type LayerProps<LayerT> = OptionalSource<OptionalId<LayerT>> & {
|
||||
export type LayerProps = (OptionalSource<OptionalId<AnyLayer>> | CustomLayerInterface) & {
|
||||
/** If set, the layer will be inserted before the specified layer */
|
||||
beforeId?: string;
|
||||
};
|
||||
|
||||
/* eslint-disable complexity, max-statements */
|
||||
function updateLayer<LayerT extends ILayer>(
|
||||
map: MapInstance,
|
||||
id: string,
|
||||
props: LayerProps<LayerT>,
|
||||
prevProps: LayerProps<LayerT>
|
||||
) {
|
||||
function updateLayer(map: MapInstance, id: string, props: LayerProps, prevProps: LayerProps) {
|
||||
assert(props.id === prevProps.id, 'layer id changed');
|
||||
assert(props.type === prevProps.type, 'layer type changed');
|
||||
|
||||
@ -29,6 +25,7 @@ function updateLayer<LayerT extends ILayer>(
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-ignore filter does not exist in some Layer types
|
||||
const {layout = {}, paint = {}, filter, minzoom, maxzoom, beforeId} = props;
|
||||
|
||||
if (beforeId !== prevProps.beforeId) {
|
||||
@ -38,12 +35,12 @@ function updateLayer<LayerT extends ILayer>(
|
||||
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 any, layout[key]);
|
||||
}
|
||||
}
|
||||
for (const key in prevLayout) {
|
||||
if (!layout.hasOwnProperty(key)) {
|
||||
map.setLayoutProperty(id, key, undefined);
|
||||
map.setLayoutProperty(id, key as any, undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -51,16 +48,17 @@ function updateLayer<LayerT extends ILayer>(
|
||||
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 any, paint[key]);
|
||||
}
|
||||
}
|
||||
for (const key in prevPaint) {
|
||||
if (!paint.hasOwnProperty(key)) {
|
||||
map.setPaintProperty(id, key, undefined);
|
||||
map.setPaintProperty(id, key as any, undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore filter does not exist in some Layer types
|
||||
if (!deepEqual(filter, prevProps.filter)) {
|
||||
map.setFilter(id, filter);
|
||||
}
|
||||
@ -69,14 +67,10 @@ function updateLayer<LayerT extends ILayer>(
|
||||
}
|
||||
}
|
||||
|
||||
function createLayer<LayerT extends ILayer>(
|
||||
map: MapInstance,
|
||||
id: string,
|
||||
props: LayerProps<LayerT>
|
||||
) {
|
||||
function createLayer(map: MapInstance, id: string, props: LayerProps) {
|
||||
// @ts-ignore
|
||||
if (map.style && map.style._loaded && (!('source' in props) || map.getSource(props.source))) {
|
||||
const options: LayerProps<LayerT> = {...props, id};
|
||||
const options: LayerProps = {...props, id};
|
||||
delete options.beforeId;
|
||||
|
||||
// @ts-ignore
|
||||
@ -88,7 +82,7 @@ function createLayer<LayerT extends ILayer>(
|
||||
|
||||
let layerCounter = 0;
|
||||
|
||||
function Layer<LayerT extends ILayer>(props: LayerProps<LayerT | CustomLayerInterface>) {
|
||||
export function Layer(props: LayerProps) {
|
||||
const map = useContext(MapContext).map.getMap();
|
||||
const propsRef = useRef(props);
|
||||
const [, setStyleLoaded] = useState(0);
|
||||
@ -129,5 +123,3 @@ function Layer<LayerT extends ILayer>(props: LayerProps<LayerT | CustomLayerInte
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default Layer;
|
||||
|
||||
@ -8,29 +8,24 @@ import createRef, {MapRef} from '../mapbox/create-ref';
|
||||
import type {CSSProperties} from 'react';
|
||||
import useIsomorphicLayoutEffect from '../utils/use-isomorphic-layout-effect';
|
||||
import setGlobals, {GlobalSettings} from '../utils/set-globals';
|
||||
import type {MapLib, MapInstance, MapStyle, Callbacks} from '../types';
|
||||
import type {MapLib, MapOptions} from '../types/lib';
|
||||
|
||||
export type MapContextValue<MapT extends MapInstance = MapInstance> = {
|
||||
mapLib: MapLib<MapT>;
|
||||
map: MapRef<MapT>;
|
||||
export type MapContextValue = {
|
||||
mapLib: MapLib;
|
||||
map: MapRef;
|
||||
};
|
||||
|
||||
export const MapContext = React.createContext<MapContextValue>(null);
|
||||
|
||||
type MapInitOptions<MapOptions> = Omit<
|
||||
type MapInitOptions = Omit<
|
||||
MapOptions,
|
||||
'style' | 'container' | 'bounds' | 'fitBoundsOptions' | 'center'
|
||||
>;
|
||||
|
||||
export type MapProps<
|
||||
MapOptions,
|
||||
StyleT extends MapStyle,
|
||||
CallbacksT extends Callbacks,
|
||||
MapT extends MapInstance
|
||||
> = MapInitOptions<MapOptions> &
|
||||
MapboxProps<StyleT, CallbacksT> &
|
||||
export type MapProps = MapInitOptions &
|
||||
MapboxProps &
|
||||
GlobalSettings & {
|
||||
mapLib?: MapLib<MapT> | Promise<MapLib<MapT>>;
|
||||
mapLib?: MapLib | Promise<MapLib>;
|
||||
reuseMaps?: boolean;
|
||||
/** Map container id */
|
||||
id?: string;
|
||||
@ -39,29 +34,20 @@ export type MapProps<
|
||||
children?: any;
|
||||
};
|
||||
|
||||
export default function Map<
|
||||
MapOptions,
|
||||
StyleT extends MapStyle,
|
||||
CallbacksT extends Callbacks,
|
||||
MapT extends MapInstance
|
||||
>(
|
||||
props: MapProps<MapOptions, StyleT, CallbacksT, MapT>,
|
||||
ref: React.Ref<MapRef<MapT>>,
|
||||
defaultLib: MapLib<MapT> | Promise<MapLib<MapT>>
|
||||
) {
|
||||
function _Map(props: MapProps, ref: React.Ref<MapRef>) {
|
||||
const mountedMapsContext = useContext(MountedMapsContext);
|
||||
const [mapInstance, setMapInstance] = useState<Mapbox<StyleT, CallbacksT, MapT>>(null);
|
||||
const [mapInstance, setMapInstance] = useState<Mapbox>(null);
|
||||
const containerRef = useRef();
|
||||
|
||||
const {current: contextValue} = useRef<MapContextValue<MapT>>({mapLib: null, map: null});
|
||||
const {current: contextValue} = useRef<MapContextValue>({mapLib: null, map: null});
|
||||
|
||||
useEffect(() => {
|
||||
const mapLib = props.mapLib;
|
||||
let isMounted = true;
|
||||
let mapbox: Mapbox<StyleT, CallbacksT, MapT>;
|
||||
let mapbox: Mapbox;
|
||||
|
||||
Promise.resolve(mapLib || defaultLib)
|
||||
.then((module: MapLib<MapT> | {default: MapLib<MapT>}) => {
|
||||
Promise.resolve(mapLib || import('mapbox-gl'))
|
||||
.then((module: MapLib | {default: MapLib}) => {
|
||||
if (!isMounted) {
|
||||
return;
|
||||
}
|
||||
@ -98,8 +84,8 @@ export default function Map<
|
||||
onError({
|
||||
type: 'error',
|
||||
target: null,
|
||||
originalEvent: null,
|
||||
error
|
||||
error,
|
||||
originalEvent: error
|
||||
});
|
||||
} else {
|
||||
console.error(error); // eslint-disable-line
|
||||
@ -153,3 +139,5 @@ export default function Map<
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const Map = React.forwardRef(_Map);
|
||||
|
||||
@ -4,134 +4,126 @@ import {createPortal} from 'react-dom';
|
||||
import {useImperativeHandle, useEffect, useMemo, useRef, useContext, forwardRef, memo} from 'react';
|
||||
import {applyReactStyle} from '../utils/apply-react-style';
|
||||
|
||||
import type {MarkerEvent, MarkerDragEvent, PointLike, MarkerInstance} from '../types';
|
||||
import type {PopupInstance, MarkerInstance, MarkerOptions} from '../types/lib';
|
||||
import type {MarkerEvent, MarkerDragEvent} from '../types/events';
|
||||
|
||||
import {MapContext} from './map';
|
||||
import {arePointsEqual} from '../utils/deep-equal';
|
||||
|
||||
export type MarkerProps<OptionsT, MarkerT extends MarkerInstance> = OptionsT & {
|
||||
export type MarkerProps = MarkerOptions & {
|
||||
/** Longitude of the anchor location */
|
||||
longitude: number;
|
||||
/** Latitude of the anchor location */
|
||||
latitude: number;
|
||||
|
||||
// These types will be further constraint by OptionsT
|
||||
draggable?: boolean;
|
||||
offset?: PointLike;
|
||||
pitchAlignment?: string;
|
||||
rotation?: number;
|
||||
rotationAlignment?: string;
|
||||
popup?: any;
|
||||
popup?: PopupInstance;
|
||||
|
||||
/** CSS style override, applied to the control's container */
|
||||
style?: React.CSSProperties;
|
||||
onClick?: (e: MarkerEvent<MarkerT, MouseEvent>) => void;
|
||||
onDragStart?: (e: MarkerDragEvent<MarkerT>) => void;
|
||||
onDrag?: (e: MarkerDragEvent<MarkerT>) => void;
|
||||
onDragEnd?: (e: MarkerDragEvent<MarkerT>) => void;
|
||||
onClick?: (e: MarkerEvent<MouseEvent>) => void;
|
||||
onDragStart?: (e: MarkerDragEvent) => void;
|
||||
onDrag?: (e: MarkerDragEvent) => void;
|
||||
onDragEnd?: (e: MarkerDragEvent) => void;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
/* eslint-disable complexity,max-statements */
|
||||
function Marker<MarkerOptions, MarkerT extends MarkerInstance>(
|
||||
props: MarkerProps<MarkerOptions, MarkerT>,
|
||||
ref: React.Ref<MarkerT>
|
||||
) {
|
||||
const {map, mapLib} = useContext(MapContext);
|
||||
const thisRef = useRef({props});
|
||||
thisRef.current.props = props;
|
||||
export const Marker = memo(
|
||||
forwardRef((props: MarkerProps, ref: React.Ref<MarkerInstance>) => {
|
||||
const {map, mapLib} = useContext(MapContext);
|
||||
const thisRef = useRef({props});
|
||||
thisRef.current.props = props;
|
||||
|
||||
const marker: MarkerT = useMemo(() => {
|
||||
let hasChildren = false;
|
||||
React.Children.forEach(props.children, el => {
|
||||
if (el) {
|
||||
hasChildren = true;
|
||||
}
|
||||
});
|
||||
const options = {
|
||||
...props,
|
||||
element: hasChildren ? document.createElement('div') : null
|
||||
};
|
||||
|
||||
const mk = new mapLib.Marker(options) as MarkerT;
|
||||
mk.setLngLat([props.longitude, props.latitude]);
|
||||
|
||||
mk.getElement().addEventListener('click', (e: MouseEvent) => {
|
||||
thisRef.current.props.onClick?.({
|
||||
type: 'click',
|
||||
target: mk,
|
||||
originalEvent: e
|
||||
const marker: MarkerInstance = useMemo(() => {
|
||||
let hasChildren = false;
|
||||
React.Children.forEach(props.children, el => {
|
||||
if (el) {
|
||||
hasChildren = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
const options = {
|
||||
...props,
|
||||
element: hasChildren ? document.createElement('div') : null
|
||||
};
|
||||
|
||||
mk.on('dragstart', e => {
|
||||
const evt = e as MarkerDragEvent<MarkerT>;
|
||||
evt.lngLat = marker.getLngLat();
|
||||
thisRef.current.props.onDragStart?.(evt);
|
||||
});
|
||||
mk.on('drag', e => {
|
||||
const evt = e as MarkerDragEvent<MarkerT>;
|
||||
evt.lngLat = marker.getLngLat();
|
||||
thisRef.current.props.onDrag?.(evt);
|
||||
});
|
||||
mk.on('dragend', e => {
|
||||
const evt = e as MarkerDragEvent<MarkerT>;
|
||||
evt.lngLat = marker.getLngLat();
|
||||
thisRef.current.props.onDragEnd?.(evt);
|
||||
});
|
||||
const mk = new mapLib.Marker(options);
|
||||
mk.setLngLat([props.longitude, props.latitude]);
|
||||
|
||||
return mk;
|
||||
}, []);
|
||||
mk.getElement().addEventListener('click', (e: MouseEvent) => {
|
||||
thisRef.current.props.onClick?.({
|
||||
type: 'click',
|
||||
target: mk,
|
||||
originalEvent: e
|
||||
});
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
marker.addTo(map.getMap());
|
||||
mk.on('dragstart', e => {
|
||||
const evt = e as MarkerDragEvent;
|
||||
evt.lngLat = marker.getLngLat();
|
||||
thisRef.current.props.onDragStart?.(evt);
|
||||
});
|
||||
mk.on('drag', e => {
|
||||
const evt = e as MarkerDragEvent;
|
||||
evt.lngLat = marker.getLngLat();
|
||||
thisRef.current.props.onDrag?.(evt);
|
||||
});
|
||||
mk.on('dragend', e => {
|
||||
const evt = e as MarkerDragEvent;
|
||||
evt.lngLat = marker.getLngLat();
|
||||
thisRef.current.props.onDragEnd?.(evt);
|
||||
});
|
||||
|
||||
return () => {
|
||||
marker.remove();
|
||||
};
|
||||
}, []);
|
||||
return mk;
|
||||
}, []);
|
||||
|
||||
const {
|
||||
longitude,
|
||||
latitude,
|
||||
offset,
|
||||
style,
|
||||
draggable = false,
|
||||
popup = null,
|
||||
rotation = 0,
|
||||
rotationAlignment = 'auto',
|
||||
pitchAlignment = 'auto'
|
||||
} = props;
|
||||
useEffect(() => {
|
||||
marker.addTo(map.getMap());
|
||||
|
||||
useEffect(() => {
|
||||
applyReactStyle(marker.getElement(), style);
|
||||
}, [style]);
|
||||
return () => {
|
||||
marker.remove();
|
||||
};
|
||||
}, []);
|
||||
|
||||
useImperativeHandle(ref, () => marker, []);
|
||||
const {
|
||||
longitude,
|
||||
latitude,
|
||||
offset,
|
||||
style,
|
||||
draggable = false,
|
||||
popup = null,
|
||||
rotation = 0,
|
||||
rotationAlignment = 'auto',
|
||||
pitchAlignment = 'auto'
|
||||
} = props;
|
||||
|
||||
if (marker.getLngLat().lng !== longitude || marker.getLngLat().lat !== latitude) {
|
||||
marker.setLngLat([longitude, latitude]);
|
||||
}
|
||||
if (offset && !arePointsEqual(marker.getOffset(), offset)) {
|
||||
marker.setOffset(offset);
|
||||
}
|
||||
if (marker.isDraggable() !== draggable) {
|
||||
marker.setDraggable(draggable);
|
||||
}
|
||||
if (marker.getRotation() !== rotation) {
|
||||
marker.setRotation(rotation);
|
||||
}
|
||||
if (marker.getRotationAlignment() !== rotationAlignment) {
|
||||
marker.setRotationAlignment(rotationAlignment);
|
||||
}
|
||||
if (marker.getPitchAlignment() !== pitchAlignment) {
|
||||
marker.setPitchAlignment(pitchAlignment);
|
||||
}
|
||||
if (marker.getPopup() !== popup) {
|
||||
marker.setPopup(popup);
|
||||
}
|
||||
useEffect(() => {
|
||||
applyReactStyle(marker.getElement(), style);
|
||||
}, [style]);
|
||||
|
||||
return createPortal(props.children, marker.getElement());
|
||||
}
|
||||
useImperativeHandle(ref, () => marker, []);
|
||||
|
||||
export default memo(forwardRef(Marker));
|
||||
if (marker.getLngLat().lng !== longitude || marker.getLngLat().lat !== latitude) {
|
||||
marker.setLngLat([longitude, latitude]);
|
||||
}
|
||||
if (offset && !arePointsEqual(marker.getOffset(), offset)) {
|
||||
marker.setOffset(offset);
|
||||
}
|
||||
if (marker.isDraggable() !== draggable) {
|
||||
marker.setDraggable(draggable);
|
||||
}
|
||||
if (marker.getRotation() !== rotation) {
|
||||
marker.setRotation(rotation);
|
||||
}
|
||||
if (marker.getRotationAlignment() !== rotationAlignment) {
|
||||
marker.setRotationAlignment(rotationAlignment);
|
||||
}
|
||||
if (marker.getPitchAlignment() !== pitchAlignment) {
|
||||
marker.setPitchAlignment(pitchAlignment);
|
||||
}
|
||||
if (marker.getPopup() !== popup) {
|
||||
marker.setPopup(popup);
|
||||
}
|
||||
|
||||
return createPortal(props.children, marker.getElement());
|
||||
})
|
||||
);
|
||||
|
||||
@ -1,29 +1,28 @@
|
||||
import * as React from 'react';
|
||||
import {useEffect, memo} from 'react';
|
||||
import {applyReactStyle} from '../utils/apply-react-style';
|
||||
import useControl from './use-control';
|
||||
import {useControl} from './use-control';
|
||||
|
||||
import type {ControlPosition, NavigationControlInstance} from '../types';
|
||||
import type {ControlPosition, NavigationControlOptions} from '../types/lib';
|
||||
|
||||
export type NavigationControlProps<OptionsT> = OptionsT & {
|
||||
export type NavigationControlProps = NavigationControlOptions & {
|
||||
/** Placement of the control relative to the map. */
|
||||
position?: ControlPosition;
|
||||
/** CSS style override, applied to the control's container */
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
|
||||
function NavigationControl<NavigationControlOptions, ControlT extends NavigationControlInstance>(
|
||||
props: NavigationControlProps<NavigationControlOptions>
|
||||
): null {
|
||||
const ctrl = useControl<ControlT>(({mapLib}) => new mapLib.NavigationControl(props) as ControlT, {
|
||||
function _NavigationControl(props: NavigationControlProps) {
|
||||
const ctrl = useControl(({mapLib}) => new mapLib.NavigationControl(props), {
|
||||
position: props.position
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// @ts-expect-error accessing private member
|
||||
applyReactStyle(ctrl._container, props.style);
|
||||
}, [props.style]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default memo(NavigationControl);
|
||||
export const NavigationControl = memo(_NavigationControl);
|
||||
|
||||
@ -4,28 +4,23 @@ import {createPortal} from 'react-dom';
|
||||
import {useImperativeHandle, useEffect, useMemo, useRef, useContext, forwardRef, memo} from 'react';
|
||||
import {applyReactStyle} from '../utils/apply-react-style';
|
||||
|
||||
import type {PopupEvent, PopupInstance} from '../types';
|
||||
import type {PopupInstance as _PopupInstance, PopupOptions} from '../types/lib';
|
||||
import type {PopupEvent} from '../types/events';
|
||||
|
||||
import {MapContext} from './map';
|
||||
import {deepEqual} from '../utils/deep-equal';
|
||||
|
||||
export type PopupProps<OptionsT, PopupT extends PopupInstance> = OptionsT & {
|
||||
export type PopupProps = PopupOptions & {
|
||||
/** Longitude of the anchor location */
|
||||
longitude: number;
|
||||
/** Latitude of the anchor location */
|
||||
latitude: number;
|
||||
|
||||
// These types will be further constraint by OptionsT
|
||||
anchor?: string;
|
||||
offset?: any;
|
||||
className?: string;
|
||||
maxWidth?: string;
|
||||
|
||||
/** CSS style override, applied to the control's container */
|
||||
style?: React.CSSProperties;
|
||||
|
||||
onOpen?: (e: PopupEvent<PopupT>) => void;
|
||||
onClose?: (e: PopupEvent<PopupT>) => void;
|
||||
onOpen?: (e: PopupEvent) => void;
|
||||
onClose?: (e: PopupEvent) => void;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
@ -34,83 +29,84 @@ function getClassList(className: string) {
|
||||
return new Set(className ? className.trim().split(/\s+/) : []);
|
||||
}
|
||||
|
||||
type PopupInstance = _PopupInstance & {
|
||||
options: PopupOptions;
|
||||
};
|
||||
|
||||
/* eslint-disable complexity,max-statements */
|
||||
function Popup<PopupOptions, PopupT extends PopupInstance>(
|
||||
props: PopupProps<PopupOptions, PopupT>,
|
||||
ref: React.Ref<PopupT>
|
||||
) {
|
||||
const {map, mapLib} = useContext(MapContext);
|
||||
const container = useMemo(() => {
|
||||
return document.createElement('div');
|
||||
}, []);
|
||||
const thisRef = useRef({props});
|
||||
thisRef.current.props = props;
|
||||
export const Popup = memo(
|
||||
forwardRef((props: PopupProps, ref: React.Ref<PopupInstance>) => {
|
||||
const {map, mapLib} = useContext(MapContext);
|
||||
const container = useMemo(() => {
|
||||
return document.createElement('div');
|
||||
}, []);
|
||||
const thisRef = useRef({props});
|
||||
thisRef.current.props = props;
|
||||
|
||||
const popup: PopupT = useMemo(() => {
|
||||
const options = {...props};
|
||||
const pp = new mapLib.Popup(options) as PopupT;
|
||||
pp.setLngLat([props.longitude, props.latitude]);
|
||||
pp.once('open', e => {
|
||||
thisRef.current.props.onOpen?.(e as PopupEvent<PopupT>);
|
||||
});
|
||||
return pp;
|
||||
}, []);
|
||||
const popup = useMemo(() => {
|
||||
const options = {...props};
|
||||
const pp = new mapLib.Popup(options);
|
||||
pp.setLngLat([props.longitude, props.latitude]);
|
||||
pp.once('open', e => {
|
||||
thisRef.current.props.onOpen?.(e as PopupEvent);
|
||||
});
|
||||
return pp as PopupInstance;
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const onClose = e => {
|
||||
thisRef.current.props.onClose?.(e as PopupEvent<PopupT>);
|
||||
};
|
||||
popup.on('close', onClose);
|
||||
popup.setDOMContent(container).addTo(map.getMap());
|
||||
useEffect(() => {
|
||||
const onClose = e => {
|
||||
thisRef.current.props.onClose?.(e as PopupEvent);
|
||||
};
|
||||
popup.on('close', onClose);
|
||||
popup.setDOMContent(container).addTo(map.getMap());
|
||||
|
||||
return () => {
|
||||
// https://github.com/visgl/react-map-gl/issues/1825
|
||||
// onClose should not be fired if the popup is removed by unmounting
|
||||
// When using React strict mode, the component is mounted twice.
|
||||
// Firing the onClose callback here would be a false signal to remove the component.
|
||||
popup.off('close', onClose);
|
||||
if (popup.isOpen()) {
|
||||
popup.remove();
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
applyReactStyle(popup.getElement(), props.style);
|
||||
}, [props.style]);
|
||||
|
||||
useImperativeHandle(ref, () => popup, []);
|
||||
|
||||
if (popup.isOpen()) {
|
||||
if (popup.getLngLat().lng !== props.longitude || popup.getLngLat().lat !== props.latitude) {
|
||||
popup.setLngLat([props.longitude, props.latitude]);
|
||||
}
|
||||
if (props.offset && !deepEqual(popup.options.offset, props.offset)) {
|
||||
popup.setOffset(props.offset);
|
||||
}
|
||||
if (popup.options.anchor !== props.anchor || popup.options.maxWidth !== props.maxWidth) {
|
||||
popup.options.anchor = props.anchor;
|
||||
popup.setMaxWidth(props.maxWidth);
|
||||
}
|
||||
if (popup.options.className !== props.className) {
|
||||
const prevClassList = getClassList(popup.options.className);
|
||||
const nextClassList = getClassList(props.className);
|
||||
|
||||
for (const c of prevClassList) {
|
||||
if (!nextClassList.has(c)) {
|
||||
popup.removeClassName(c);
|
||||
return () => {
|
||||
// https://github.com/visgl/react-map-gl/issues/1825
|
||||
// onClose should not be fired if the popup is removed by unmounting
|
||||
// When using React strict mode, the component is mounted twice.
|
||||
// Firing the onClose callback here would be a false signal to remove the component.
|
||||
popup.off('close', onClose);
|
||||
if (popup.isOpen()) {
|
||||
popup.remove();
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
applyReactStyle(popup.getElement(), props.style);
|
||||
}, [props.style]);
|
||||
|
||||
useImperativeHandle(ref, () => popup, []);
|
||||
|
||||
if (popup.isOpen()) {
|
||||
if (popup.getLngLat().lng !== props.longitude || popup.getLngLat().lat !== props.latitude) {
|
||||
popup.setLngLat([props.longitude, props.latitude]);
|
||||
}
|
||||
for (const c of nextClassList) {
|
||||
if (!prevClassList.has(c)) {
|
||||
popup.addClassName(c);
|
||||
if (props.offset && !deepEqual(popup.options.offset, props.offset)) {
|
||||
popup.setOffset(props.offset);
|
||||
}
|
||||
if (popup.options.anchor !== props.anchor || popup.options.maxWidth !== props.maxWidth) {
|
||||
popup.options.anchor = props.anchor;
|
||||
popup.setMaxWidth(props.maxWidth);
|
||||
}
|
||||
if (popup.options.className !== props.className) {
|
||||
const prevClassList = getClassList(popup.options.className);
|
||||
const nextClassList = getClassList(props.className);
|
||||
|
||||
for (const c of prevClassList) {
|
||||
if (!nextClassList.has(c)) {
|
||||
popup.removeClassName(c);
|
||||
}
|
||||
}
|
||||
for (const c of nextClassList) {
|
||||
if (!prevClassList.has(c)) {
|
||||
popup.addClassName(c);
|
||||
}
|
||||
}
|
||||
popup.options.className = props.className;
|
||||
}
|
||||
popup.options.className = props.className;
|
||||
}
|
||||
}
|
||||
|
||||
return createPortal(props.children, container);
|
||||
}
|
||||
|
||||
export default memo(forwardRef(Popup));
|
||||
return createPortal(props.children, container);
|
||||
})
|
||||
);
|
||||
|
||||
@ -1,28 +1,22 @@
|
||||
import * as React from 'react';
|
||||
import {useEffect, useRef, memo} from 'react';
|
||||
import {applyReactStyle} from '../utils/apply-react-style';
|
||||
import useControl from './use-control';
|
||||
import {useControl} from './use-control';
|
||||
|
||||
import type {ControlPosition, ScaleControlInstance} from '../types';
|
||||
|
||||
export type ScaleControlProps<OptionsT> = OptionsT & {
|
||||
// These props will be further constraint by OptionsT
|
||||
unit?: string;
|
||||
maxWidth?: number;
|
||||
import type {ControlPosition, ScaleControlOptions} from '../types/lib';
|
||||
|
||||
export type ScaleControlProps = ScaleControlOptions & {
|
||||
/** Placement of the control relative to the map. */
|
||||
position?: ControlPosition;
|
||||
/** CSS style override, applied to the control's container */
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
|
||||
function ScaleControl<ScaleControlOptions, ControlT extends ScaleControlInstance>(
|
||||
props: ScaleControlProps<ScaleControlOptions>
|
||||
): null {
|
||||
const ctrl = useControl<ControlT>(({mapLib}) => new mapLib.ScaleControl(props) as ControlT, {
|
||||
function _ScaleControl(props: ScaleControlProps) {
|
||||
const ctrl = useControl(({mapLib}) => new mapLib.ScaleControl(props), {
|
||||
position: props.position
|
||||
});
|
||||
const propsRef = useRef<ScaleControlProps<ScaleControlOptions>>(props);
|
||||
const propsRef = useRef<ScaleControlProps>(props);
|
||||
|
||||
const prevProps = propsRef.current;
|
||||
propsRef.current = props;
|
||||
@ -30,17 +24,19 @@ function ScaleControl<ScaleControlOptions, ControlT extends ScaleControlInstance
|
||||
const {style} = props;
|
||||
|
||||
if (props.maxWidth !== undefined && props.maxWidth !== prevProps.maxWidth) {
|
||||
// @ts-expect-error accessing private member
|
||||
ctrl.options.maxWidth = props.maxWidth;
|
||||
}
|
||||
if (props.unit !== undefined && props.unit !== prevProps.unit) {
|
||||
ctrl.setUnit(props.unit);
|
||||
ctrl.setUnit(props.unit as any);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// @ts-expect-error accessing private member
|
||||
applyReactStyle(ctrl._container, style);
|
||||
}, [style]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default memo(ScaleControl);
|
||||
export const ScaleControl = memo(_ScaleControl);
|
||||
|
||||
@ -5,27 +5,21 @@ import assert from '../utils/assert';
|
||||
import {deepEqual} from '../utils/deep-equal';
|
||||
|
||||
import type {
|
||||
MapInstance,
|
||||
ISource,
|
||||
CustomSource,
|
||||
GeoJSONSourceImplementation,
|
||||
ImageSourceImplemtation,
|
||||
AnySourceImplementation
|
||||
} from '../types';
|
||||
import type {GeoJSONSourceRaw, ImageSourceRaw, VectorSourceRaw} from '../types/style-spec-mapbox';
|
||||
} from '../types/internal';
|
||||
import type {AnySource, ImageSource, VectorSource} from '../types/style-spec';
|
||||
import type {MapInstance} from '../types/lib';
|
||||
|
||||
export type SourceProps<SourceT> = (SourceT | CustomSource) & {
|
||||
export type SourceProps = AnySource & {
|
||||
id?: string;
|
||||
children?: any;
|
||||
};
|
||||
|
||||
let sourceCounter = 0;
|
||||
|
||||
function createSource<SourceT extends ISource>(
|
||||
map: MapInstance,
|
||||
id: string,
|
||||
props: SourceProps<SourceT>
|
||||
) {
|
||||
function createSource(map: MapInstance, id: string, props: SourceProps) {
|
||||
// @ts-ignore
|
||||
if (map.style && map.style._loaded) {
|
||||
const options = {...props};
|
||||
@ -39,11 +33,7 @@ function createSource<SourceT extends ISource>(
|
||||
}
|
||||
|
||||
/* eslint-disable complexity */
|
||||
function updateSource<SourceT extends ISource>(
|
||||
source: AnySourceImplementation,
|
||||
props: SourceProps<SourceT>,
|
||||
prevProps: SourceProps<SourceT>
|
||||
) {
|
||||
function updateSource(source: AnySourceImplementation, props: SourceProps, prevProps: SourceProps) {
|
||||
assert(props.id === prevProps.id, 'source id changed');
|
||||
assert(props.type === prevProps.type, 'source type changed');
|
||||
|
||||
@ -64,20 +54,18 @@ function updateSource<SourceT extends ISource>(
|
||||
const type = props.type;
|
||||
|
||||
if (type === 'geojson') {
|
||||
(source as GeoJSONSourceImplementation).setData(
|
||||
(props as unknown as GeoJSONSourceRaw).data as any
|
||||
);
|
||||
(source as GeoJSONSourceImplementation).setData(props.data as any);
|
||||
} else if (type === 'image') {
|
||||
(source as ImageSourceImplemtation).updateImage({
|
||||
url: (props as unknown as ImageSourceRaw).url,
|
||||
coordinates: (props as unknown as ImageSourceRaw).coordinates
|
||||
url: props.url,
|
||||
coordinates: props.coordinates
|
||||
});
|
||||
} else if ('setCoordinates' in source && changedKeyCount === 1 && changedKey === 'coordinates') {
|
||||
source.setCoordinates((props as ImageSourceRaw).coordinates);
|
||||
source.setCoordinates((props as unknown as ImageSource).coordinates);
|
||||
} else if ('setUrl' in source && changedKey === 'url') {
|
||||
source.setUrl((props as VectorSourceRaw).url);
|
||||
source.setUrl((props as VectorSource).url);
|
||||
} else if ('setTiles' in source && changedKey === 'tiles') {
|
||||
source.setTiles((props as VectorSourceRaw).tiles);
|
||||
source.setTiles((props as VectorSource).tiles);
|
||||
} else {
|
||||
// eslint-disable-next-line
|
||||
console.warn(`Unable to update <Source> prop: ${changedKey}`);
|
||||
@ -85,7 +73,7 @@ function updateSource<SourceT extends ISource>(
|
||||
}
|
||||
/* eslint-enable complexity */
|
||||
|
||||
function Source<SourceT extends ISource>(props: SourceProps<SourceT>) {
|
||||
export function Source(props: SourceProps) {
|
||||
const map = useContext(MapContext).map.getMap();
|
||||
const propsRef = useRef(props);
|
||||
const [, setStyleLoaded] = useState(0);
|
||||
@ -144,5 +132,3 @@ function Source<SourceT extends ISource>(props: SourceProps<SourceT>) {
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
export default Source;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import {useContext, useMemo, useEffect} from 'react';
|
||||
import type {IControl, ControlPosition} from '../types';
|
||||
import type {IControl, ControlPosition} from '../types/lib';
|
||||
import {MapContext} from './map';
|
||||
import type {MapContextValue} from './map';
|
||||
|
||||
@ -7,25 +7,25 @@ type ControlOptions = {
|
||||
position?: ControlPosition;
|
||||
};
|
||||
|
||||
function useControl<T extends IControl>(
|
||||
export function useControl<T extends IControl>(
|
||||
onCreate: (context: MapContextValue) => T,
|
||||
opts?: ControlOptions
|
||||
): T;
|
||||
|
||||
function useControl<T extends IControl>(
|
||||
export function useControl<T extends IControl>(
|
||||
onCreate: (context: MapContextValue) => T,
|
||||
onRemove: (context: MapContextValue) => void,
|
||||
opts?: ControlOptions
|
||||
): T;
|
||||
|
||||
function useControl<T extends IControl>(
|
||||
export function useControl<T extends IControl>(
|
||||
onCreate: (context: MapContextValue) => T,
|
||||
onAdd: (context: MapContextValue) => void,
|
||||
onRemove: (context: MapContextValue) => void,
|
||||
opts?: ControlOptions
|
||||
): T;
|
||||
|
||||
function useControl<T extends IControl>(
|
||||
export function useControl<T extends IControl>(
|
||||
onCreate: (context: MapContextValue) => T,
|
||||
arg1?: ((context: MapContextValue) => void) | ControlOptions,
|
||||
arg2?: ((context: MapContextValue) => void) | ControlOptions,
|
||||
@ -60,5 +60,3 @@ function useControl<T extends IControl>(
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
export default useControl;
|
||||
|
||||
@ -3,20 +3,19 @@ import {useState, useCallback, useMemo, useContext} from 'react';
|
||||
|
||||
import {MapRef} from '../mapbox/create-ref';
|
||||
import {MapContext} from './map';
|
||||
import {MapInstance} from '../types';
|
||||
|
||||
type MountedMapsContextValue = {
|
||||
maps: {[id: string]: MapRef<MapInstance>};
|
||||
onMapMount: (map: MapRef<MapInstance>, id: string) => void;
|
||||
maps: {[id: string]: MapRef};
|
||||
onMapMount: (map: MapRef, id: string) => void;
|
||||
onMapUnmount: (id: string) => void;
|
||||
};
|
||||
|
||||
export const MountedMapsContext = React.createContext<MountedMapsContextValue>(null);
|
||||
|
||||
export const MapProvider: React.FC<{children?: React.ReactNode}> = props => {
|
||||
const [maps, setMaps] = useState<{[id: string]: MapRef<MapInstance>}>({});
|
||||
const [maps, setMaps] = useState<{[id: string]: MapRef}>({});
|
||||
|
||||
const onMapMount = useCallback((map: MapRef<MapInstance>, id: string = 'default') => {
|
||||
const onMapMount = useCallback((map: MapRef, id: string = 'default') => {
|
||||
setMaps(currMaps => {
|
||||
if (id === 'current') {
|
||||
throw new Error("'current' cannot be used as map id");
|
||||
@ -52,12 +51,12 @@ export const MapProvider: React.FC<{children?: React.ReactNode}> = props => {
|
||||
);
|
||||
};
|
||||
|
||||
export type MapCollection<MapT extends MapInstance> = {
|
||||
[id: string]: MapRef<MapT> | undefined;
|
||||
current?: MapRef<MapT>;
|
||||
export type MapCollection = {
|
||||
[id: string]: MapRef | undefined;
|
||||
current?: MapRef;
|
||||
};
|
||||
|
||||
export function useMap<MapT extends MapInstance>(): MapCollection<MapT> {
|
||||
export function useMap(): MapCollection {
|
||||
const maps = useContext(MountedMapsContext)?.maps;
|
||||
const currentMap = useContext(MapContext);
|
||||
|
||||
@ -65,5 +64,5 @@ export function useMap<MapT extends MapInstance>(): MapCollection<MapT> {
|
||||
return {...maps, current: currentMap?.map};
|
||||
}, [maps, currentMap]);
|
||||
|
||||
return mapsWithCurrent as MapCollection<MapT>;
|
||||
return mapsWithCurrent as MapCollection;
|
||||
}
|
||||
|
||||
@ -1,159 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import type {
|
||||
Map as MapboxMap,
|
||||
MapboxOptions,
|
||||
Marker as MapboxMarker,
|
||||
MarkerOptions,
|
||||
Popup as MapboxPopup,
|
||||
PopupOptions,
|
||||
AttributionControl as MapboxAttributionControl,
|
||||
FullscreenControl as MapboxFullscreenControl,
|
||||
GeolocateControl as MapboxGeolocateControl,
|
||||
NavigationControl as MapboxNavigationControl,
|
||||
ScaleControl as MapboxScaleControl
|
||||
} from 'mapbox-gl';
|
||||
import {MapStyle, AnyLayer, AnySource} from './types/style-spec-mapbox';
|
||||
|
||||
import {default as _Map, MapProps as _MapProps} from './components/map';
|
||||
import {default as _Marker, MarkerProps as _MarkerProps} from './components/marker';
|
||||
import {default as _Popup, PopupProps as _PopupProps} from './components/popup';
|
||||
import {
|
||||
default as _AttributionControl,
|
||||
AttributionControlProps as _AttributionControlProps
|
||||
} from './components/attribution-control';
|
||||
import {
|
||||
default as _FullscreenControl,
|
||||
FullscreenControlProps as _FullscreenControlProps
|
||||
} from './components/fullscreen-control';
|
||||
import {
|
||||
default as _GeolocateControl,
|
||||
GeolocateControlProps as _GeolocateControlProps
|
||||
} from './components/geolocate-control';
|
||||
import {
|
||||
default as _NavigationControl,
|
||||
NavigationControlProps as _NavigationControlProps
|
||||
} from './components/navigation-control';
|
||||
import {
|
||||
default as _ScaleControl,
|
||||
ScaleControlProps as _ScaleControlProps
|
||||
} from './components/scale-control';
|
||||
import {default as _Layer, LayerProps as _LayerProps} from './components/layer';
|
||||
import {default as _Source, SourceProps as _SourceProps} from './components/source';
|
||||
import {useMap as _useMap} from './components/use-map';
|
||||
import type {MapRef as _MapRef} from './mapbox/create-ref';
|
||||
import type * as events from './types/events';
|
||||
import type {MapCallbacks} from './types/events-mapbox';
|
||||
|
||||
export function useMap() {
|
||||
return _useMap<MapboxMap>();
|
||||
}
|
||||
|
||||
export type MapProps = _MapProps<MapboxOptions, MapStyle, MapCallbacks, MapboxMap>;
|
||||
export type MapRef = _MapRef<MapboxMap>;
|
||||
const mapLib = import('mapbox-gl');
|
||||
export const Map = (() => {
|
||||
return React.forwardRef(function Map(props: MapProps, ref: React.Ref<MapRef>) {
|
||||
return _Map<MapboxOptions, MapStyle, MapCallbacks, MapboxMap>(props, ref, mapLib);
|
||||
});
|
||||
})();
|
||||
|
||||
export type MarkerProps = _MarkerProps<MarkerOptions, MapboxMarker>;
|
||||
export const Marker = _Marker as (
|
||||
props: MarkerProps & React.RefAttributes<MapboxMarker>
|
||||
) => React.ReactElement | null;
|
||||
|
||||
export type PopupProps = _PopupProps<PopupOptions, MapboxPopup>;
|
||||
export const Popup = _Popup as (
|
||||
props: PopupProps & React.RefAttributes<MapboxPopup>
|
||||
) => React.ReactElement | null;
|
||||
|
||||
type AttributionControlOptions = ConstructorParameters<typeof MapboxAttributionControl>[0];
|
||||
export type AttributionControlProps = _AttributionControlProps<AttributionControlOptions>;
|
||||
export const AttributionControl = _AttributionControl as (
|
||||
props: AttributionControlProps
|
||||
) => React.ReactElement | null;
|
||||
|
||||
type FullscreenControlOptions = ConstructorParameters<typeof MapboxFullscreenControl>[0];
|
||||
export type FullscreenControlProps = _FullscreenControlProps<FullscreenControlOptions>;
|
||||
export const FullscreenControl = _FullscreenControl as (
|
||||
props: FullscreenControlProps
|
||||
) => React.ReactElement | null;
|
||||
|
||||
type NavigationControlOptions = ConstructorParameters<typeof MapboxNavigationControl>[0];
|
||||
export type NavigationControlProps = _NavigationControlProps<NavigationControlOptions>;
|
||||
export const NavigationControl = _NavigationControl as (
|
||||
props: NavigationControlProps
|
||||
) => React.ReactElement | null;
|
||||
|
||||
type GeolocateControlOptions = ConstructorParameters<typeof MapboxGeolocateControl>[0];
|
||||
export type GeolocateControlProps = _GeolocateControlProps<
|
||||
GeolocateControlOptions,
|
||||
MapboxGeolocateControl
|
||||
>;
|
||||
export const GeolocateControl = _GeolocateControl as (
|
||||
props: GeolocateControlProps & React.RefAttributes<MapboxGeolocateControl>
|
||||
) => React.ReactElement | null;
|
||||
|
||||
type ScaleControlOptions = ConstructorParameters<typeof MapboxScaleControl>[0];
|
||||
export type ScaleControlProps = _ScaleControlProps<ScaleControlOptions>;
|
||||
export const ScaleControl = _ScaleControl as (
|
||||
props: ScaleControlProps
|
||||
) => React.ReactElement | null;
|
||||
|
||||
export type LayerProps = _LayerProps<AnyLayer>;
|
||||
export const Layer = _Layer as (props: LayerProps) => React.ReactElement | null;
|
||||
|
||||
export type SourceProps = _SourceProps<AnySource>;
|
||||
export const Source = _Source as (props: SourceProps) => React.ReactElement | null;
|
||||
|
||||
export {default as useControl} from './components/use-control';
|
||||
export {MapProvider} from './components/use-map';
|
||||
|
||||
export default Map;
|
||||
|
||||
// Types
|
||||
export * from './types/public';
|
||||
export type {
|
||||
Point,
|
||||
PointLike,
|
||||
LngLat,
|
||||
LngLatLike,
|
||||
LngLatBounds,
|
||||
LngLatBoundsLike,
|
||||
PaddingOptions,
|
||||
MapboxGeoJSONFeature as MapGeoJSONFeature,
|
||||
GeoJSONSource,
|
||||
VideoSource,
|
||||
ImageSource,
|
||||
CanvasSource,
|
||||
VectorSourceImpl as VectorTileSource
|
||||
} from 'mapbox-gl';
|
||||
export * from './types/style-spec-mapbox';
|
||||
|
||||
// Events
|
||||
export type {
|
||||
MapEvent,
|
||||
MapMouseEvent,
|
||||
MapLayerMouseEvent,
|
||||
MapTouchEvent,
|
||||
MapLayerTouchEvent,
|
||||
MapStyleDataEvent,
|
||||
MapSourceDataEvent,
|
||||
MapWheelEvent,
|
||||
MapBoxZoomEvent,
|
||||
ErrorEvent,
|
||||
ViewStateChangeEvent
|
||||
} from './types/events-mapbox';
|
||||
export type PopupEvent = events.PopupEvent<MapboxPopup>;
|
||||
export type MarkerEvent = events.MarkerEvent<MapboxMarker>;
|
||||
export type MarkerDragEvent = events.MarkerDragEvent<MapboxMarker>;
|
||||
export type GeolocateEvent = events.GeolocateEvent<MapboxGeolocateControl>;
|
||||
export type GeolocateResultEvent = events.GeolocateResultEvent<MapboxGeolocateControl>;
|
||||
export type GeolocateErrorEvent = events.GeolocateErrorEvent<MapboxGeolocateControl>;
|
||||
|
||||
// v7.0 backward compatibility
|
||||
|
||||
/** @deprecated use `MapStyle` */
|
||||
export type MapboxStyle = MapStyle;
|
||||
|
||||
export type {Map as MapboxMap, MapboxEvent, MapboxGeoJSONFeature} from 'mapbox-gl';
|
||||
@ -1,2 +1,33 @@
|
||||
export * from './exports-mapbox';
|
||||
export {default as default} from './exports-mapbox';
|
||||
import {Map} from './components/map';
|
||||
export {Map};
|
||||
export default Map;
|
||||
|
||||
export {Marker} from './components/marker';
|
||||
export {Popup} from './components/popup';
|
||||
export {AttributionControl} from './components/attribution-control';
|
||||
export {FullscreenControl} from './components/fullscreen-control';
|
||||
export {GeolocateControl} from './components/geolocate-control';
|
||||
export {NavigationControl} from './components/navigation-control';
|
||||
export {ScaleControl} from './components/scale-control';
|
||||
export {Source} from './components/source';
|
||||
export {Layer} from './components/layer';
|
||||
export {useControl} from './components/use-control';
|
||||
export {MapProvider, useMap} from './components/use-map';
|
||||
|
||||
export type {MapProps} from './components/map';
|
||||
export type {MapRef} from './mapbox/create-ref';
|
||||
export type {MarkerProps} from './components/marker';
|
||||
export type {PopupProps} from './components/popup';
|
||||
export type {AttributionControlProps} from './components/attribution-control';
|
||||
export type {FullscreenControlProps} from './components/fullscreen-control';
|
||||
export type {GeolocateControlProps} from './components/geolocate-control';
|
||||
export type {NavigationControlProps} from './components/navigation-control';
|
||||
export type {ScaleControlProps} from './components/scale-control';
|
||||
export type {SourceProps} from './components/source';
|
||||
export type {LayerProps} from './components/layer';
|
||||
|
||||
// Types
|
||||
export * from './types/common';
|
||||
export * from './types/events';
|
||||
export * from './types/lib';
|
||||
export * from './types/style-spec';
|
||||
|
||||
@ -1,11 +1,7 @@
|
||||
import type {
|
||||
MapInstance,
|
||||
MapInstanceInternal,
|
||||
MapStyle,
|
||||
Callbacks,
|
||||
LngLatLike,
|
||||
PointLike
|
||||
} from '../types';
|
||||
import type {MapInstance} from '../types/lib';
|
||||
import type {MapInstanceInternal} from '../types/internal';
|
||||
import {LngLatLike, PointLike} from '../types/common';
|
||||
|
||||
import type Mapbox from './mapbox';
|
||||
|
||||
/** These methods may break the react binding if called directly */
|
||||
@ -32,22 +28,18 @@ const skipMethods = [
|
||||
'remove'
|
||||
] as const;
|
||||
|
||||
export type MapRef<MapT extends MapInstance> = {
|
||||
getMap(): MapT;
|
||||
} & Omit<MapT, (typeof skipMethods)[number]>;
|
||||
export type MapRef = {
|
||||
getMap(): MapInstance;
|
||||
} & Omit<MapInstance, (typeof skipMethods)[number]>;
|
||||
|
||||
export default function createRef<
|
||||
StyleT extends MapStyle,
|
||||
CallbacksT extends Callbacks,
|
||||
MapT extends MapInstance
|
||||
>(mapInstance: Mapbox<StyleT, CallbacksT, MapT>): MapRef<MapT> | null {
|
||||
export default function createRef(mapInstance: Mapbox): MapRef | null {
|
||||
if (!mapInstance) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const map = mapInstance.map as MapInstanceInternal<MapT>;
|
||||
const map = mapInstance.map as MapInstanceInternal;
|
||||
const ref: any = {
|
||||
getMap: () => map,
|
||||
getMap: () => mapInstance.map,
|
||||
|
||||
// Overwrite getters to use our shadow transform
|
||||
getCenter: () => mapInstance.transform.center,
|
||||
|
||||
@ -8,29 +8,27 @@ import {normalizeStyle} from '../utils/style-utils';
|
||||
import {deepEqual} from '../utils/deep-equal';
|
||||
|
||||
import type {
|
||||
Transform,
|
||||
ViewState,
|
||||
ViewStateChangeEvent,
|
||||
Point,
|
||||
PointLike,
|
||||
PaddingOptions,
|
||||
MapStyle,
|
||||
ImmutableLike,
|
||||
LngLatBoundsLike,
|
||||
Callbacks,
|
||||
MapGeoJSONFeature
|
||||
} from '../types/common';
|
||||
import type {MapStyle, Light, Terrain, Fog, Projection} from '../types/style-spec';
|
||||
import type {MapInstance} from '../types/lib';
|
||||
import type {Transform, MapInstanceInternal} from '../types/internal';
|
||||
import type {
|
||||
MapCallbacks,
|
||||
ViewStateChangeEvent,
|
||||
MapEvent,
|
||||
ErrorEvent,
|
||||
MapMouseEvent,
|
||||
MapGeoJSONFeature,
|
||||
MapInstance,
|
||||
MapInstanceInternal
|
||||
} from '../types';
|
||||
MapMouseEvent
|
||||
} from '../types/events';
|
||||
|
||||
export type MapboxProps<
|
||||
StyleT extends MapStyle = MapStyle,
|
||||
CallbacksT extends Callbacks = {}
|
||||
> = Partial<ViewState> &
|
||||
CallbacksT & {
|
||||
export type MapboxProps = Partial<ViewState> &
|
||||
MapCallbacks & {
|
||||
// Init options
|
||||
mapboxAccessToken?: string;
|
||||
|
||||
@ -59,19 +57,23 @@ export type MapboxProps<
|
||||
// Styling
|
||||
|
||||
/** Mapbox style */
|
||||
mapStyle?: string | StyleT | ImmutableLike<StyleT>;
|
||||
mapStyle?: string | MapStyle | ImmutableLike<MapStyle>;
|
||||
/** Enable diffing when the map style changes
|
||||
* @default true
|
||||
*/
|
||||
styleDiffing?: boolean;
|
||||
/** The projection property of the style. Must conform to the Projection Style Specification.
|
||||
* @default 'mercator'
|
||||
*/
|
||||
projection?: Projection;
|
||||
/** The fog property of the style. Must conform to the Fog Style Specification .
|
||||
* If `undefined` is provided, removes the fog from the map. */
|
||||
fog?: StyleT['fog'];
|
||||
fog?: Fog;
|
||||
/** Light properties of the map. */
|
||||
light?: StyleT['light'];
|
||||
light?: Light;
|
||||
/** Terrain property of the style. Must conform to the Terrain Style Specification .
|
||||
* If `undefined` is provided, removes terrain from the map. */
|
||||
terrain?: StyleT['terrain'];
|
||||
terrain?: Terrain;
|
||||
|
||||
/** Default layers to query on pointer events */
|
||||
interactiveLayerIds?: string[];
|
||||
@ -152,16 +154,12 @@ const handlerNames = [
|
||||
/**
|
||||
* A wrapper for mapbox-gl's Map class
|
||||
*/
|
||||
export default class Mapbox<
|
||||
StyleT extends MapStyle = MapStyle,
|
||||
CallbacksT extends Callbacks = {},
|
||||
MapT extends MapInstance = MapInstance
|
||||
> {
|
||||
export default class Mapbox {
|
||||
private _MapClass: {new (options: any): MapInstance};
|
||||
// mapboxgl.Map instance
|
||||
private _map: MapInstanceInternal<MapT> = null;
|
||||
private _map: MapInstanceInternal = null;
|
||||
// User-supplied props
|
||||
props: MapboxProps<StyleT, CallbacksT>;
|
||||
props: MapboxProps;
|
||||
|
||||
// Mapbox map is stateful.
|
||||
// During method calls/user interactions, map.transform is mutated and
|
||||
@ -191,7 +189,7 @@ export default class Mapbox<
|
||||
|
||||
constructor(
|
||||
MapClass: {new (options: any): MapInstance},
|
||||
props: MapboxProps<StyleT, CallbacksT>,
|
||||
props: MapboxProps,
|
||||
container: HTMLDivElement
|
||||
) {
|
||||
this._MapClass = MapClass;
|
||||
@ -199,7 +197,7 @@ export default class Mapbox<
|
||||
this._initialize(container);
|
||||
}
|
||||
|
||||
get map(): MapT {
|
||||
get map(): MapInstance {
|
||||
return this._map;
|
||||
}
|
||||
|
||||
@ -207,7 +205,7 @@ export default class Mapbox<
|
||||
return this._renderTransform;
|
||||
}
|
||||
|
||||
setProps(props: MapboxProps<StyleT, CallbacksT>) {
|
||||
setProps(props: MapboxProps) {
|
||||
const oldProps = this.props;
|
||||
this.props = props;
|
||||
|
||||
@ -229,11 +227,8 @@ export default class Mapbox<
|
||||
}
|
||||
}
|
||||
|
||||
static reuse<StyleT extends MapStyle, CallbacksT extends Callbacks, MapT extends MapInstance>(
|
||||
props: MapboxProps<StyleT, CallbacksT>,
|
||||
container: HTMLDivElement
|
||||
): Mapbox<StyleT, CallbacksT, MapT> {
|
||||
const that = Mapbox.savedMaps.pop() as Mapbox<StyleT, CallbacksT, MapT>;
|
||||
static reuse(props: MapboxProps, container: HTMLDivElement): Mapbox {
|
||||
const that = Mapbox.savedMaps.pop();
|
||||
if (!that) {
|
||||
return null;
|
||||
}
|
||||
@ -251,16 +246,6 @@ export default class Mapbox<
|
||||
// @ts-ignore
|
||||
map._container = container;
|
||||
|
||||
// With maplibre-gl as mapLib, map uses ResizeObserver to observe when its container resizes.
|
||||
// When reusing the saved map, we need to disconnect the observer and observe the new container.
|
||||
// Step 3: telling the ResizeObserver to disconnect and observe the new container
|
||||
// @ts-ignore
|
||||
const resizeObserver = map._resizeObserver;
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect();
|
||||
resizeObserver.observe(container);
|
||||
}
|
||||
|
||||
// Step 4: apply new props
|
||||
that.setProps({...props, styleDiffing: false});
|
||||
map.resize();
|
||||
@ -319,7 +304,7 @@ export default class Mapbox<
|
||||
};
|
||||
}
|
||||
|
||||
const map = new this._MapClass(mapOptions) as MapInstanceInternal<MapT>;
|
||||
const map = new this._MapClass(mapOptions) as MapInstanceInternal;
|
||||
// Props that are not part of constructor options
|
||||
if (viewState.padding) {
|
||||
map.setPadding(viewState.padding);
|
||||
@ -331,12 +316,14 @@ export default class Mapbox<
|
||||
|
||||
// Hack
|
||||
// Insert code into map's render cycle
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
const renderMap = map._render;
|
||||
map._render = (arg: number) => {
|
||||
this._inRender = true;
|
||||
renderMap.call(map, arg);
|
||||
this._inRender = false;
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
const runRenderTaskQueue = map._renderTaskQueue.run;
|
||||
map._renderTaskQueue.run = (arg: number) => {
|
||||
runRenderTaskQueue.call(map._renderTaskQueue, arg);
|
||||
@ -414,7 +401,7 @@ export default class Mapbox<
|
||||
@param {object} nextProps
|
||||
@returns {bool} true if size has changed
|
||||
*/
|
||||
_updateSize(nextProps: MapboxProps<StyleT>): boolean {
|
||||
_updateSize(nextProps: MapboxProps): boolean {
|
||||
// Check if size is controlled
|
||||
const {viewState} = nextProps;
|
||||
if (viewState) {
|
||||
@ -433,7 +420,7 @@ export default class Mapbox<
|
||||
@param {bool} triggerEvents - should fire camera events
|
||||
@returns {bool} true if anything is changed
|
||||
*/
|
||||
_updateViewState(nextProps: MapboxProps<StyleT>, triggerEvents: boolean): boolean {
|
||||
_updateViewState(nextProps: MapboxProps, triggerEvents: boolean): boolean {
|
||||
if (this._internalUpdate) {
|
||||
return false;
|
||||
}
|
||||
@ -480,7 +467,7 @@ export default class Mapbox<
|
||||
@param {object} currProps
|
||||
@returns {bool} true if anything is changed
|
||||
*/
|
||||
_updateSettings(nextProps: MapboxProps<StyleT>, currProps: MapboxProps<StyleT>): boolean {
|
||||
_updateSettings(nextProps: MapboxProps, currProps: MapboxProps): boolean {
|
||||
const map = this._map;
|
||||
let changed = false;
|
||||
for (const propName of settingNames) {
|
||||
@ -498,7 +485,7 @@ export default class Mapbox<
|
||||
@param {object} currProps
|
||||
@returns {bool} true if style is changed
|
||||
*/
|
||||
_updateStyle(nextProps: MapboxProps<StyleT>, currProps: MapboxProps<StyleT>): boolean {
|
||||
_updateStyle(nextProps: MapboxProps, currProps: MapboxProps): boolean {
|
||||
if (nextProps.cursor !== currProps.cursor) {
|
||||
this._map.getCanvas().style.cursor = nextProps.cursor || '';
|
||||
}
|
||||
@ -522,7 +509,7 @@ export default class Mapbox<
|
||||
@param {object} currProps
|
||||
@returns {bool} true if anything is changed
|
||||
*/
|
||||
_updateStyleComponents(nextProps: MapboxProps<StyleT>, currProps: MapboxProps<StyleT>): boolean {
|
||||
_updateStyleComponents(nextProps: MapboxProps, currProps: MapboxProps): boolean {
|
||||
const map = this._map;
|
||||
let changed = false;
|
||||
if (map.isStyleLoaded()) {
|
||||
@ -553,7 +540,7 @@ export default class Mapbox<
|
||||
@param {object} currProps
|
||||
@returns {bool} true if anything is changed
|
||||
*/
|
||||
_updateHandlers(nextProps: MapboxProps<StyleT>, currProps: MapboxProps<StyleT>): boolean {
|
||||
_updateHandlers(nextProps: MapboxProps, currProps: MapboxProps): boolean {
|
||||
const map = this._map;
|
||||
let changed = false;
|
||||
for (const propName of handlerNames) {
|
||||
@ -571,13 +558,13 @@ export default class Mapbox<
|
||||
return changed;
|
||||
}
|
||||
|
||||
_onEvent = (e: MapEvent<MapT>) => {
|
||||
_onEvent = (e: MapEvent) => {
|
||||
// @ts-ignore
|
||||
const cb = this.props[otherEvents[e.type]];
|
||||
if (cb) {
|
||||
cb(e);
|
||||
} else if (e.type === 'error') {
|
||||
console.error((e as ErrorEvent<MapT>).error); // eslint-disable-line
|
||||
console.error((e as ErrorEvent).error); // eslint-disable-line
|
||||
}
|
||||
};
|
||||
|
||||
@ -598,7 +585,7 @@ export default class Mapbox<
|
||||
}
|
||||
}
|
||||
|
||||
_updateHover(e: MapMouseEvent<MapT>) {
|
||||
_updateHover(e: MapMouseEvent) {
|
||||
const {props} = this;
|
||||
const shouldTrackHoveredFeatures =
|
||||
props.interactiveLayerIds && (props.onMouseMove || props.onMouseEnter || props.onMouseLeave);
|
||||
@ -624,7 +611,7 @@ export default class Mapbox<
|
||||
}
|
||||
}
|
||||
|
||||
_onPointerEvent = (e: MapMouseEvent<MapT>) => {
|
||||
_onPointerEvent = (e: MapMouseEvent) => {
|
||||
if (e.type === 'mousemove' || e.type === 'mouseout') {
|
||||
this._updateHover(e);
|
||||
}
|
||||
@ -640,7 +627,7 @@ export default class Mapbox<
|
||||
}
|
||||
};
|
||||
|
||||
_onCameraEvent = (e: ViewStateChangeEvent<MapT>) => {
|
||||
_onCameraEvent = (e: ViewStateChangeEvent) => {
|
||||
if (!this._internalUpdate) {
|
||||
// @ts-ignore
|
||||
const cb = this.props[cameraEvents[e.type]];
|
||||
@ -653,7 +640,7 @@ export default class Mapbox<
|
||||
}
|
||||
};
|
||||
|
||||
_fireEvent(baseFire: Function, event: string | MapEvent<MapT>, properties?: object) {
|
||||
_fireEvent(baseFire: Function, event: string | MapEvent, properties?: object) {
|
||||
const map = this._map;
|
||||
const tr = map.transform;
|
||||
|
||||
@ -663,7 +650,7 @@ export default class Mapbox<
|
||||
}
|
||||
if (eventType in cameraEvents) {
|
||||
if (typeof event === 'object') {
|
||||
(event as unknown as ViewStateChangeEvent<MapT>).viewState = transformToViewState(tr);
|
||||
(event as unknown as ViewStateChangeEvent).viewState = transformToViewState(tr);
|
||||
}
|
||||
if (this._map.isMoving()) {
|
||||
// Replace map.transform with ours during the callbacks
|
||||
|
||||
@ -1,73 +1,15 @@
|
||||
import type GeoJSON from 'geojson';
|
||||
import type {PaddingOptions} from 'mapbox-gl';
|
||||
|
||||
/* Data types that are compatible with both mapbox and maplibre. Not exposed to the end user. */
|
||||
|
||||
/** @mapbox/point-geometry */
|
||||
export interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
export type PointLike = Point | [number, number];
|
||||
|
||||
export interface LngLat {
|
||||
lng: number;
|
||||
lat: number;
|
||||
|
||||
wrap(): LngLat;
|
||||
/** Return a LngLat as an array */
|
||||
toArray(): number[];
|
||||
/** Return a LngLat as a string */
|
||||
toString(): string;
|
||||
/** Returns the approximate distance between a pair of coordinates in meters
|
||||
* Uses the Haversine Formula (from R.W. Sinnott, "Virtues of the Haversine", Sky and Telescope, vol. 68, no. 2, 1984, p. 159) */
|
||||
distanceTo(lngLat: LngLat): number;
|
||||
}
|
||||
export type LngLatLike =
|
||||
| [number, number]
|
||||
| LngLat
|
||||
| {lng: number; lat: number}
|
||||
| {lon: number; lat: number};
|
||||
|
||||
export interface LngLatBounds {
|
||||
contains(lnglat: LngLatLike): boolean;
|
||||
setNorthEast(ne: LngLatLike): this;
|
||||
setSouthWest(sw: LngLatLike): this;
|
||||
extend(obj: LngLatLike | LngLatBoundsLike): this;
|
||||
|
||||
getCenter(): LngLat;
|
||||
getSouthWest(): LngLat;
|
||||
getNorthEast(): LngLat;
|
||||
getNorthWest(): LngLat;
|
||||
getSouthEast(): LngLat;
|
||||
|
||||
getWest(): number;
|
||||
getSouth(): number;
|
||||
getEast(): number;
|
||||
getNorth(): number;
|
||||
|
||||
toArray(): number[][];
|
||||
toString(): string;
|
||||
isEmpty(): boolean;
|
||||
}
|
||||
export type LngLatBoundsLike =
|
||||
| LngLatBounds
|
||||
| [LngLatLike, LngLatLike]
|
||||
| [number, number, number, number]
|
||||
| LngLatLike;
|
||||
|
||||
export type MapGeoJSONFeature = GeoJSON.Feature<GeoJSON.Geometry> & {
|
||||
layer: any;
|
||||
source: string;
|
||||
sourceLayer: string;
|
||||
state: {[key: string]: any};
|
||||
};
|
||||
|
||||
export type PaddingOptions = {
|
||||
top: number;
|
||||
bottom: number;
|
||||
left: number;
|
||||
right: number;
|
||||
};
|
||||
export type {
|
||||
Point,
|
||||
PointLike,
|
||||
LngLat,
|
||||
LngLatLike,
|
||||
LngLatBounds,
|
||||
LngLatBoundsLike,
|
||||
PaddingOptions,
|
||||
MapboxGeoJSONFeature as MapGeoJSONFeature
|
||||
} from 'mapbox-gl';
|
||||
|
||||
/* Public */
|
||||
|
||||
@ -87,8 +29,6 @@ export type ViewState = {
|
||||
padding: PaddingOptions;
|
||||
};
|
||||
|
||||
export type ControlPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
|
||||
|
||||
export interface ImmutableLike<T> {
|
||||
toJS: () => T;
|
||||
}
|
||||
|
||||
@ -1,76 +0,0 @@
|
||||
import {
|
||||
Map,
|
||||
MapboxEvent as MapEvent,
|
||||
MapMouseEvent,
|
||||
MapLayerMouseEvent,
|
||||
MapTouchEvent,
|
||||
MapLayerTouchEvent,
|
||||
MapStyleDataEvent,
|
||||
MapSourceDataEvent,
|
||||
MapWheelEvent,
|
||||
MapBoxZoomEvent
|
||||
} from 'mapbox-gl';
|
||||
import {ErrorEvent as _ErrorEvent, ViewStateChangeEvent as _ViewStateChangeEvent} from './events';
|
||||
|
||||
export type {
|
||||
MapEvent,
|
||||
MapMouseEvent,
|
||||
MapLayerMouseEvent,
|
||||
MapTouchEvent,
|
||||
MapLayerTouchEvent,
|
||||
MapStyleDataEvent,
|
||||
MapSourceDataEvent,
|
||||
MapWheelEvent,
|
||||
MapBoxZoomEvent
|
||||
};
|
||||
|
||||
export type ErrorEvent = _ErrorEvent<Map>;
|
||||
export type ViewStateChangeEvent = _ViewStateChangeEvent<Map>;
|
||||
|
||||
export type MapCallbacks = {
|
||||
onMouseDown?: (e: MapLayerMouseEvent) => void;
|
||||
onMouseUp?: (e: MapLayerMouseEvent) => void;
|
||||
onMouseOver?: (e: MapLayerMouseEvent) => void;
|
||||
onMouseMove?: (e: MapLayerMouseEvent) => void;
|
||||
onClick?: (e: MapLayerMouseEvent) => void;
|
||||
onDblClick?: (e: MapLayerMouseEvent) => void;
|
||||
onMouseEnter?: (e: MapLayerMouseEvent) => void;
|
||||
onMouseLeave?: (e: MapLayerMouseEvent) => void;
|
||||
onMouseOut?: (e: MapLayerMouseEvent) => void;
|
||||
onContextMenu?: (e: MapLayerMouseEvent) => void;
|
||||
onTouchStart?: (e: MapLayerTouchEvent) => void;
|
||||
onTouchEnd?: (e: MapLayerTouchEvent) => void;
|
||||
onTouchMove?: (e: MapLayerTouchEvent) => void;
|
||||
onTouchCancel?: (e: MapLayerTouchEvent) => void;
|
||||
|
||||
onMoveStart?: (e: ViewStateChangeEvent) => void;
|
||||
onMove?: (e: ViewStateChangeEvent) => void;
|
||||
onMoveEnd?: (e: ViewStateChangeEvent) => void;
|
||||
onDragStart?: (e: ViewStateChangeEvent) => void;
|
||||
onDrag?: (e: ViewStateChangeEvent) => void;
|
||||
onDragEnd?: (e: ViewStateChangeEvent) => void;
|
||||
onZoomStart?: (e: ViewStateChangeEvent) => void;
|
||||
onZoom?: (e: ViewStateChangeEvent) => void;
|
||||
onZoomEnd?: (e: ViewStateChangeEvent) => void;
|
||||
onRotateStart?: (e: ViewStateChangeEvent) => void;
|
||||
onRotate?: (e: ViewStateChangeEvent) => void;
|
||||
onRotateEnd?: (e: ViewStateChangeEvent) => void;
|
||||
onPitchStart?: (e: ViewStateChangeEvent) => void;
|
||||
onPitch?: (e: ViewStateChangeEvent) => void;
|
||||
onPitchEnd?: (e: ViewStateChangeEvent) => void;
|
||||
|
||||
onWheel?: (e: MapWheelEvent) => void;
|
||||
onBoxZoomStart?: (e: MapBoxZoomEvent) => void;
|
||||
onBoxZoomEnd?: (e: MapBoxZoomEvent) => void;
|
||||
onBoxZoomCancel?: (e: MapBoxZoomEvent) => void;
|
||||
|
||||
onResize?: (e: MapEvent) => void;
|
||||
onLoad?: (e: MapEvent) => void;
|
||||
onRender?: (e: MapEvent) => void;
|
||||
onIdle?: (e: MapEvent) => void;
|
||||
onError?: (e: ErrorEvent) => void;
|
||||
onRemove?: (e: MapEvent) => void;
|
||||
onData?: (e: MapStyleDataEvent | MapSourceDataEvent) => void;
|
||||
onStyleData?: (e: MapStyleDataEvent) => void;
|
||||
onSourceData?: (e: MapSourceDataEvent) => void;
|
||||
};
|
||||
@ -1,73 +1,117 @@
|
||||
import type {ViewState, Point, LngLat, MapGeoJSONFeature} from './common';
|
||||
import type {
|
||||
MapInstance,
|
||||
Evented,
|
||||
MarkerInstance,
|
||||
PopupInstance,
|
||||
GeolocateControlInstance
|
||||
} from './lib';
|
||||
import type {ViewState, LngLat} from './common';
|
||||
import {
|
||||
MapboxEvent as MapEvent,
|
||||
MapLayerMouseEvent,
|
||||
MapLayerTouchEvent,
|
||||
MapStyleDataEvent,
|
||||
MapSourceDataEvent,
|
||||
MapWheelEvent,
|
||||
MapBoxZoomEvent,
|
||||
ErrorEvent,
|
||||
Marker,
|
||||
Popup,
|
||||
GeolocateControl
|
||||
} from 'mapbox-gl';
|
||||
|
||||
export interface Callbacks {
|
||||
[key: `on${string}`]: Function;
|
||||
}
|
||||
export type MapCallbacks = {
|
||||
onMouseDown?: (e: MapLayerMouseEvent) => void;
|
||||
onMouseUp?: (e: MapLayerMouseEvent) => void;
|
||||
onMouseOver?: (e: MapLayerMouseEvent) => void;
|
||||
onMouseMove?: (e: MapLayerMouseEvent) => void;
|
||||
onClick?: (e: MapLayerMouseEvent) => void;
|
||||
onDblClick?: (e: MapLayerMouseEvent) => void;
|
||||
onMouseEnter?: (e: MapLayerMouseEvent) => void;
|
||||
onMouseLeave?: (e: MapLayerMouseEvent) => void;
|
||||
onMouseOut?: (e: MapLayerMouseEvent) => void;
|
||||
onContextMenu?: (e: MapLayerMouseEvent) => void;
|
||||
onTouchStart?: (e: MapLayerTouchEvent) => void;
|
||||
onTouchEnd?: (e: MapLayerTouchEvent) => void;
|
||||
onTouchMove?: (e: MapLayerTouchEvent) => void;
|
||||
onTouchCancel?: (e: MapLayerTouchEvent) => void;
|
||||
|
||||
export interface MapEvent<SourceT extends Evented, OriginalEventT = undefined> {
|
||||
onMoveStart?: (e: ViewStateChangeEvent) => void;
|
||||
onMove?: (e: ViewStateChangeEvent) => void;
|
||||
onMoveEnd?: (e: ViewStateChangeEvent) => void;
|
||||
onDragStart?: (e: ViewStateChangeEvent) => void;
|
||||
onDrag?: (e: ViewStateChangeEvent) => void;
|
||||
onDragEnd?: (e: ViewStateChangeEvent) => void;
|
||||
onZoomStart?: (e: ViewStateChangeEvent) => void;
|
||||
onZoom?: (e: ViewStateChangeEvent) => void;
|
||||
onZoomEnd?: (e: ViewStateChangeEvent) => void;
|
||||
onRotateStart?: (e: ViewStateChangeEvent) => void;
|
||||
onRotate?: (e: ViewStateChangeEvent) => void;
|
||||
onRotateEnd?: (e: ViewStateChangeEvent) => void;
|
||||
onPitchStart?: (e: ViewStateChangeEvent) => void;
|
||||
onPitch?: (e: ViewStateChangeEvent) => void;
|
||||
onPitchEnd?: (e: ViewStateChangeEvent) => void;
|
||||
|
||||
onWheel?: (e: MapWheelEvent) => void;
|
||||
onBoxZoomStart?: (e: MapBoxZoomEvent) => void;
|
||||
onBoxZoomEnd?: (e: MapBoxZoomEvent) => void;
|
||||
onBoxZoomCancel?: (e: MapBoxZoomEvent) => void;
|
||||
|
||||
onResize?: (e: MapEvent) => void;
|
||||
onLoad?: (e: MapEvent) => void;
|
||||
onRender?: (e: MapEvent) => void;
|
||||
onIdle?: (e: MapEvent) => void;
|
||||
onError?: (e: ErrorEvent) => void;
|
||||
onRemove?: (e: MapEvent) => void;
|
||||
onData?: (e: MapStyleDataEvent | MapSourceDataEvent) => void;
|
||||
onStyleData?: (e: MapStyleDataEvent) => void;
|
||||
onSourceData?: (e: MapSourceDataEvent) => void;
|
||||
};
|
||||
|
||||
export type {
|
||||
MapEvent,
|
||||
ErrorEvent,
|
||||
MapLayerMouseEvent as MapMouseEvent,
|
||||
MapLayerTouchEvent as MapTouchEvent,
|
||||
MapStyleDataEvent,
|
||||
MapSourceDataEvent,
|
||||
MapWheelEvent,
|
||||
MapBoxZoomEvent
|
||||
};
|
||||
|
||||
interface IMapEvent<SourceT, OriginalEventT = undefined> {
|
||||
type: string;
|
||||
target: SourceT;
|
||||
originalEvent: OriginalEventT;
|
||||
}
|
||||
|
||||
export type ErrorEvent<MapT extends MapInstance> = MapEvent<MapT> & {
|
||||
type: 'error';
|
||||
error: Error;
|
||||
export type ViewStateChangeEvent = MapEvent<MouseEvent | TouchEvent | WheelEvent | undefined> & {
|
||||
type:
|
||||
| 'movestart'
|
||||
| 'move'
|
||||
| 'moveend'
|
||||
| 'zoomstart'
|
||||
| 'zoom'
|
||||
| 'zoomend'
|
||||
| 'rotatestart'
|
||||
| 'rotate'
|
||||
| 'rotateend'
|
||||
| 'dragstart'
|
||||
| 'drag'
|
||||
| 'dragend'
|
||||
| 'pitchstart'
|
||||
| 'pitch'
|
||||
| 'pitchend';
|
||||
viewState: ViewState;
|
||||
};
|
||||
|
||||
export type MapMouseEvent<MapT extends MapInstance> = MapEvent<MapT, MouseEvent> & {
|
||||
point: Point;
|
||||
lngLat: LngLat;
|
||||
features?: MapGeoJSONFeature[];
|
||||
};
|
||||
|
||||
export type ViewStateChangeEvent<MapT extends MapInstance> =
|
||||
| (MapEvent<MapT, MouseEvent | TouchEvent | WheelEvent | undefined> & {
|
||||
type: 'movestart' | 'move' | 'moveend' | 'zoomstart' | 'zoom' | 'zoomend';
|
||||
viewState: ViewState;
|
||||
})
|
||||
| (MapEvent<MapT, MouseEvent | TouchEvent | undefined> & {
|
||||
type:
|
||||
| 'rotatestart'
|
||||
| 'rotate'
|
||||
| 'rotateend'
|
||||
| 'dragstart'
|
||||
| 'drag'
|
||||
| 'dragend'
|
||||
| 'pitchstart'
|
||||
| 'pitch'
|
||||
| 'pitchend';
|
||||
viewState: ViewState;
|
||||
});
|
||||
|
||||
export type PopupEvent<PopupT extends PopupInstance> = {
|
||||
export type PopupEvent = {
|
||||
type: 'open' | 'close';
|
||||
target: PopupT;
|
||||
target: Popup;
|
||||
};
|
||||
|
||||
export type MarkerEvent<MarkerT extends MarkerInstance, OriginalEventT = undefined> = MapEvent<
|
||||
MarkerT,
|
||||
OriginalEventT
|
||||
>;
|
||||
export type MarkerEvent<OriginalEventT = undefined> = IMapEvent<Marker, OriginalEventT>;
|
||||
|
||||
export type MarkerDragEvent<MarkerT extends MarkerInstance> = MarkerEvent<MarkerT> & {
|
||||
export type MarkerDragEvent = MarkerEvent & {
|
||||
type: 'dragstart' | 'drag' | 'dragend';
|
||||
target: MarkerT;
|
||||
lngLat: LngLat;
|
||||
};
|
||||
|
||||
export type GeolocateEvent<GeolocateControlT extends GeolocateControlInstance> =
|
||||
MapEvent<GeolocateControlT>;
|
||||
export type GeolocateEvent = IMapEvent<GeolocateControl>;
|
||||
|
||||
export type GeolocateResultEvent<GeolocateControlT extends GeolocateControlInstance> =
|
||||
GeolocateEvent<GeolocateControlT> & GeolocationPosition;
|
||||
export type GeolocateResultEvent = GeolocateEvent & GeolocationPosition;
|
||||
|
||||
export type GeolocateErrorEvent<GeolocateControlT extends GeolocateControlInstance> =
|
||||
GeolocateEvent<GeolocateControlT> & GeolocationPositionError;
|
||||
export type GeolocateErrorEvent = GeolocateEvent & GeolocationPositionError;
|
||||
|
||||
@ -1,93 +0,0 @@
|
||||
export * from './common';
|
||||
export * from './lib';
|
||||
export * from './events';
|
||||
|
||||
import type GeoJSON from 'geojson';
|
||||
import type {CustomSourceImplementation} from './lib';
|
||||
|
||||
// Internal: source implementations
|
||||
|
||||
export interface ISource {
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface ILayer {
|
||||
id: string;
|
||||
type: string;
|
||||
|
||||
metadata?: any;
|
||||
source?: unknown;
|
||||
|
||||
minzoom?: number;
|
||||
maxzoom?: number;
|
||||
|
||||
filter?: any;
|
||||
layout?: {
|
||||
[property: string]: any;
|
||||
};
|
||||
paint?: {
|
||||
[property: string]: any;
|
||||
};
|
||||
}
|
||||
|
||||
export interface MapStyle {
|
||||
name?: string;
|
||||
metadata?: unknown;
|
||||
version: number;
|
||||
layers: ILayer[];
|
||||
sources: {
|
||||
[sourceName: string]: object;
|
||||
};
|
||||
|
||||
fog?: any;
|
||||
terrain?: any;
|
||||
light?: any;
|
||||
}
|
||||
|
||||
export interface GeoJSONSourceImplementation {
|
||||
type: 'geojson';
|
||||
setData(
|
||||
data: GeoJSON.Feature<GeoJSON.Geometry> | GeoJSON.FeatureCollection<GeoJSON.Geometry> | String
|
||||
): this;
|
||||
}
|
||||
|
||||
export interface ImageSourceImplemtation {
|
||||
type: 'image';
|
||||
updateImage(options: {url?: string; coordinates?: number[][]}): this;
|
||||
setCoordinates(coordinates: number[][]): this;
|
||||
}
|
||||
|
||||
export interface CanvasSourceImplemtation {
|
||||
type: 'canvas';
|
||||
play(): void;
|
||||
pause(): void;
|
||||
getCanvas(): HTMLCanvasElement;
|
||||
setCoordinates(coordinates: number[][]): this;
|
||||
}
|
||||
|
||||
export interface VectorSourceImplementation {
|
||||
type: 'vector';
|
||||
setTiles(tiles: ReadonlyArray<string>): this;
|
||||
setUrl(url: string): this;
|
||||
}
|
||||
|
||||
export interface RasterSourceImplementation {
|
||||
type: 'raster' | 'raster-dem';
|
||||
setTiles(tiles: ReadonlyArray<string>): this;
|
||||
setUrl(url: string): this;
|
||||
}
|
||||
|
||||
export interface VideoSourceImplementation {
|
||||
type: 'video';
|
||||
getVideo(): HTMLVideoElement;
|
||||
setCoordinates(coordinates: number[][]): this;
|
||||
}
|
||||
|
||||
export type AnySourceImplementation =
|
||||
| GeoJSONSourceImplementation
|
||||
| VideoSourceImplementation
|
||||
| ImageSourceImplemtation
|
||||
| CanvasSourceImplemtation
|
||||
| VectorSourceImplementation
|
||||
| RasterSourceImplementation
|
||||
| CustomSourceImplementation<HTMLImageElement | ImageData | ImageBitmap>;
|
||||
50
modules/main/src/mapbox-legacy/types/internal.ts
Normal file
50
modules/main/src/mapbox-legacy/types/internal.ts
Normal file
@ -0,0 +1,50 @@
|
||||
// Internal types
|
||||
import type {Map, LngLat, PaddingOptions, Point} from 'mapbox-gl';
|
||||
|
||||
export type {
|
||||
AnySourceImpl as AnySourceImplementation,
|
||||
GeoJSONSource as GeoJSONSourceImplementation,
|
||||
ImageSource as ImageSourceImplemtation,
|
||||
CanvasSource as CanvasSourceImplemtation,
|
||||
VectorSourceImpl as VectorSourceImplementation,
|
||||
RasterSourceImpl as RasterSourceImplementation,
|
||||
VideoSource as VideoSourceImplementation
|
||||
} from 'mapbox-gl';
|
||||
|
||||
/**
|
||||
* Stub for mapbox's Transform class
|
||||
* https://github.com/mapbox/mapbox-gl-js/blob/main/src/geo/transform.js
|
||||
*/
|
||||
export type Transform = {
|
||||
width: number;
|
||||
height: number;
|
||||
center: LngLat;
|
||||
zoom: number;
|
||||
bearing: number;
|
||||
pitch: number;
|
||||
padding: PaddingOptions;
|
||||
elevation: any;
|
||||
pixelsToGLUnits: [number, number];
|
||||
cameraElevationReference: 'ground' | 'sea';
|
||||
|
||||
clone: () => Transform;
|
||||
resize: (width: number, height: number) => void;
|
||||
isPaddingEqual: (value: PaddingOptions) => boolean;
|
||||
getBounds: () => any;
|
||||
locationPoint: (lngLat: LngLat) => Point;
|
||||
pointLocation: (p: Point) => LngLat;
|
||||
|
||||
// Mapbox only
|
||||
getProjection?: () => any;
|
||||
setProjection?: (projection: any) => void;
|
||||
};
|
||||
|
||||
export type MapInstanceInternal = Map & {
|
||||
transform: Transform;
|
||||
|
||||
_render: Function;
|
||||
|
||||
_renderTaskQueue: {
|
||||
run: Function;
|
||||
};
|
||||
};
|
||||
@ -1,293 +1,67 @@
|
||||
import type {PaddingOptions, LngLat, Point, LngLatLike, PointLike, ControlPosition} from './common';
|
||||
|
||||
export interface IControl<MapT extends MapInstance = MapInstance> {
|
||||
onAdd(map: MapT): HTMLElement;
|
||||
|
||||
onRemove(map: MapT): void;
|
||||
|
||||
getDefaultPosition?: (() => string) | undefined;
|
||||
}
|
||||
|
||||
type Listener = (event?: any) => any;
|
||||
|
||||
export interface Evented {
|
||||
on(type: string, listener: Listener);
|
||||
|
||||
off(type?: string | any, listener?: Listener);
|
||||
|
||||
once(type: string, listener: Listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* A user-facing type that represents the minimal intersection between Mapbox.Map and Maplibre.Map
|
||||
* User provided `mapLib.Map` is supposed to implement this interface
|
||||
* Only losely typed for compatibility
|
||||
*/
|
||||
export interface MapInstance extends Evented {
|
||||
// https://github.com/mapbox/mapbox-gl-js/issues/6522
|
||||
fire(type: string, properties?: {[key: string]: any});
|
||||
|
||||
addControl(control: IControl<this>, position?: ControlPosition);
|
||||
|
||||
removeControl(control: IControl<this>);
|
||||
|
||||
hasControl(control: IControl<this>): boolean;
|
||||
|
||||
resize(): this;
|
||||
|
||||
queryRenderedFeatures(geometry?: any, options?: any): any[];
|
||||
|
||||
setStyle(style: any, options?: any);
|
||||
|
||||
isMoving(): boolean;
|
||||
|
||||
getStyle(): any;
|
||||
|
||||
isStyleLoaded(): boolean | void;
|
||||
|
||||
addSource(id: string, source: any);
|
||||
|
||||
removeSource(id: string): this;
|
||||
|
||||
getSource(id: string): any;
|
||||
|
||||
addLayer(layer: any, before?: string);
|
||||
|
||||
moveLayer(id: string, beforeId?: string);
|
||||
|
||||
removeLayer(id: string);
|
||||
|
||||
getLayer(id: string): any;
|
||||
|
||||
setFilter(layer: string, filter?: any[] | boolean | null);
|
||||
|
||||
setLayerZoomRange(layerId: string, minzoom: number, maxzoom: number);
|
||||
|
||||
setPaintProperty(layer: string, name: string, value: any);
|
||||
|
||||
setLayoutProperty(layer: string, name: string, value: any);
|
||||
|
||||
project(lnglat: any): Point;
|
||||
|
||||
unproject(point: any): LngLat;
|
||||
|
||||
queryTerrainElevation?(lngLat: any, options?: any): number | null;
|
||||
|
||||
getContainer(): HTMLElement;
|
||||
|
||||
getCanvas(): HTMLCanvasElement;
|
||||
|
||||
getCanvasContainer(): HTMLElement;
|
||||
|
||||
remove(): void;
|
||||
|
||||
triggerRepaint(): void;
|
||||
|
||||
getCenter(): LngLat;
|
||||
|
||||
getZoom(): number;
|
||||
|
||||
getBearing(): number;
|
||||
|
||||
getPitch(): number;
|
||||
|
||||
getPadding(): PaddingOptions;
|
||||
|
||||
getRenderWorldCopies(): boolean;
|
||||
|
||||
setPadding(padding: PaddingOptions);
|
||||
|
||||
fitBounds(bounds: any, options?: any);
|
||||
|
||||
setFog?(fog: any);
|
||||
|
||||
setLight?(options: any, lightOptions?: any);
|
||||
|
||||
setTerrain?(terrain?: any);
|
||||
}
|
||||
|
||||
export interface MarkerInstance extends Evented {
|
||||
addTo(map: MapInstance): this;
|
||||
remove(): this;
|
||||
|
||||
getLngLat(): LngLat;
|
||||
setLngLat(lngLat: LngLatLike): this;
|
||||
|
||||
getElement(): HTMLElement;
|
||||
|
||||
setPopup(popup?: any): this;
|
||||
getPopup(): any;
|
||||
|
||||
getOffset(): PointLike;
|
||||
setOffset(offset: PointLike): this;
|
||||
|
||||
setDraggable(value: boolean): this;
|
||||
isDraggable(): boolean;
|
||||
|
||||
getRotation(): number;
|
||||
setRotation(rotation: number): this;
|
||||
|
||||
getRotationAlignment(): any;
|
||||
setRotationAlignment(alignment: any): this;
|
||||
|
||||
getPitchAlignment(): any;
|
||||
setPitchAlignment(alignment: any): this;
|
||||
}
|
||||
|
||||
export interface PopupInstance extends Evented {
|
||||
options?: any;
|
||||
|
||||
addTo(map: MapInstance): this;
|
||||
remove(): this;
|
||||
|
||||
isOpen(): boolean;
|
||||
|
||||
getLngLat(): LngLat;
|
||||
setLngLat(lnglat: LngLatLike): this;
|
||||
|
||||
getElement(): HTMLElement;
|
||||
|
||||
setDOMContent(htmlNode: any): this;
|
||||
|
||||
getMaxWidth(): any;
|
||||
setMaxWidth(maxWidth: any): this;
|
||||
|
||||
addClassName(className: string): void;
|
||||
removeClassName(className: string): void;
|
||||
|
||||
setOffset(offset?: any): this;
|
||||
}
|
||||
|
||||
export interface AttributionControlInstance extends IControl {
|
||||
_container?: HTMLElement;
|
||||
}
|
||||
|
||||
export interface FullscreenControlInstance extends IControl {
|
||||
_controlContainer?: HTMLElement;
|
||||
}
|
||||
|
||||
export interface GeolocateControlInstance extends IControl, Evented {
|
||||
_container?: HTMLElement;
|
||||
trigger();
|
||||
}
|
||||
|
||||
export interface NavigationControlInstance extends IControl {
|
||||
_container?: HTMLElement;
|
||||
}
|
||||
|
||||
export interface ScaleControlInstance extends IControl {
|
||||
_container?: HTMLElement;
|
||||
options?: any;
|
||||
setUnit(unit: any): void;
|
||||
}
|
||||
import type {
|
||||
Map as MapInstance,
|
||||
MapboxOptions as MapOptions,
|
||||
Marker as MarkerInstance,
|
||||
MarkerOptions,
|
||||
Popup as PopupInstance,
|
||||
PopupOptions,
|
||||
AttributionControl as AttributionControlInstance,
|
||||
FullscreenControl as FullscreenControlInstance,
|
||||
FullscreenControlOptions,
|
||||
GeolocateControl as GeolocateControlInstance,
|
||||
NavigationControl as NavigationControlInstance,
|
||||
ScaleControl as ScaleControlInstance
|
||||
} from 'mapbox-gl';
|
||||
|
||||
type AttributionControlOptions = ConstructorParameters<typeof AttributionControlInstance>[0];
|
||||
type GeolocateControlOptions = ConstructorParameters<typeof GeolocateControlInstance>[0];
|
||||
type NavigationControlOptions = ConstructorParameters<typeof NavigationControlInstance>[0];
|
||||
type ScaleControlOptions = ConstructorParameters<typeof ScaleControlInstance>[0];
|
||||
|
||||
export type {IControl, CustomLayerInterface} from 'mapbox-gl';
|
||||
|
||||
export type {
|
||||
MapInstance,
|
||||
MapOptions,
|
||||
MarkerInstance,
|
||||
MarkerOptions,
|
||||
PopupInstance,
|
||||
PopupOptions,
|
||||
AttributionControlInstance,
|
||||
AttributionControlOptions,
|
||||
FullscreenControlInstance,
|
||||
FullscreenControlOptions,
|
||||
GeolocateControlInstance,
|
||||
GeolocateControlOptions,
|
||||
NavigationControlInstance,
|
||||
NavigationControlOptions,
|
||||
ScaleControlInstance,
|
||||
ScaleControlOptions
|
||||
};
|
||||
|
||||
export type ControlPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
|
||||
|
||||
/**
|
||||
* A user-facing type that represents the minimal intersection between Mapbox and Maplibre
|
||||
* User provided `mapLib` is supposed to implement this interface
|
||||
* Only loosely typed for compatibility
|
||||
*/
|
||||
export interface MapLib<MapT extends MapInstance> {
|
||||
export interface MapLib {
|
||||
supported?: (options: any) => boolean;
|
||||
|
||||
Map: {new (options: any): MapT};
|
||||
Map: {new (options: MapOptions): MapInstance};
|
||||
|
||||
Marker: {new (...options: any[]): MarkerInstance};
|
||||
Marker: {new (options: MarkerOptions): MarkerInstance};
|
||||
|
||||
Popup: {new (options: any): PopupInstance};
|
||||
Popup: {new (options: PopupOptions): PopupInstance};
|
||||
|
||||
AttributionControl: {new (options: any): AttributionControlInstance};
|
||||
AttributionControl: {new (options: AttributionControlOptions): AttributionControlInstance};
|
||||
|
||||
FullscreenControl: {new (options: any): FullscreenControlInstance};
|
||||
FullscreenControl: {new (options: FullscreenControlOptions): FullscreenControlInstance};
|
||||
|
||||
GeolocateControl: {new (options: any): GeolocateControlInstance};
|
||||
GeolocateControl: {new (options: GeolocateControlOptions): GeolocateControlInstance};
|
||||
|
||||
NavigationControl: {new (options: any): NavigationControlInstance};
|
||||
NavigationControl: {new (options: NavigationControlOptions): NavigationControlInstance};
|
||||
|
||||
ScaleControl: {new (options: any): ScaleControlInstance};
|
||||
}
|
||||
|
||||
/**
|
||||
* Stub for mapbox's Transform class
|
||||
* https://github.com/mapbox/mapbox-gl-js/blob/main/src/geo/transform.js
|
||||
*/
|
||||
export type Transform = {
|
||||
width: number;
|
||||
height: number;
|
||||
center: LngLat;
|
||||
zoom: number;
|
||||
bearing: number;
|
||||
pitch: number;
|
||||
padding: PaddingOptions;
|
||||
elevation: any;
|
||||
pixelsToGLUnits: [number, number];
|
||||
cameraElevationReference: 'ground' | 'sea';
|
||||
|
||||
clone: () => Transform;
|
||||
resize: (width: number, height: number) => void;
|
||||
isPaddingEqual: (value: PaddingOptions) => boolean;
|
||||
getBounds: () => any;
|
||||
locationPoint: (lngLat: LngLat) => Point;
|
||||
pointLocation: (p: Point) => LngLat;
|
||||
|
||||
// Mapbox only
|
||||
getProjection?: () => any;
|
||||
setProjection?: (projection: any) => void;
|
||||
};
|
||||
|
||||
export type MapInstanceInternal<MapT extends MapInstance> = MapT & {
|
||||
transform: Transform;
|
||||
|
||||
_render: Function;
|
||||
|
||||
_renderTaskQueue: {
|
||||
run: Function;
|
||||
};
|
||||
};
|
||||
|
||||
// Custom layer
|
||||
export interface CustomLayerInterface {
|
||||
id: string;
|
||||
type: 'custom';
|
||||
renderingMode?: '2d' | '3d';
|
||||
|
||||
onRemove?(map: MapInstance, gl: WebGLRenderingContext): void;
|
||||
onAdd?(map: MapInstance, gl: WebGLRenderingContext): void;
|
||||
|
||||
prerender?(gl: WebGLRenderingContext, matrix: number[]): void;
|
||||
render(gl: WebGLRenderingContext, matrix: number[]): void;
|
||||
}
|
||||
|
||||
// Custom source
|
||||
|
||||
export interface CustomSourceImplementation<TileDataT> {
|
||||
id: string;
|
||||
type: 'custom';
|
||||
dataType: 'raster';
|
||||
minzoom?: number;
|
||||
maxzoom?: number;
|
||||
scheme?: string;
|
||||
tileSize?: number;
|
||||
attribution?: string;
|
||||
bounds?: [number, number, number, number];
|
||||
hasTile?: (tileID: {z: number; x: number; y: number}) => boolean;
|
||||
loadTile: (
|
||||
tileID: {z: number; x: number; y: number},
|
||||
options: {signal: AbortSignal}
|
||||
) => Promise<TileDataT>;
|
||||
prepareTile?: (tileID: {z: number; x: number; y: number}) => TileDataT | undefined;
|
||||
unloadTile?: (tileID: {z: number; x: number; y: number}) => void;
|
||||
onAdd?: (map: MapInstance) => void;
|
||||
onRemove?: (map: MapInstance) => void;
|
||||
}
|
||||
|
||||
export interface CustomSource<TileDataT = unknown> {
|
||||
id: string;
|
||||
type: 'custom';
|
||||
scheme: string;
|
||||
minzoom: number;
|
||||
maxzoom: number;
|
||||
tileSize: number;
|
||||
attribution: string;
|
||||
|
||||
_implementation: CustomSourceImplementation<TileDataT>;
|
||||
ScaleControl: {new (options: ScaleControlOptions): ScaleControlInstance};
|
||||
}
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
export type {ViewState, ControlPosition} from './common';
|
||||
export type {
|
||||
IControl,
|
||||
MapInstance,
|
||||
MapLib,
|
||||
CustomLayerInterface,
|
||||
CustomSource,
|
||||
CustomSourceImplementation
|
||||
} from './lib';
|
||||
@ -42,39 +42,36 @@ export type {
|
||||
|
||||
// Sources
|
||||
import type {
|
||||
GeoJSONSourceRaw,
|
||||
VideoSourceRaw,
|
||||
ImageSourceRaw,
|
||||
VectorSource as VectorSourceRaw,
|
||||
Projection as ProjectionSpecification,
|
||||
GeoJSONSourceRaw as GeoJSONSource,
|
||||
VideoSourceRaw as VideoSource,
|
||||
ImageSourceRaw as ImageSource,
|
||||
VectorSource,
|
||||
RasterSource,
|
||||
CanvasSourceRaw,
|
||||
CanvasSourceRaw as CanvasSource,
|
||||
RasterDemSource
|
||||
} from 'mapbox-gl';
|
||||
|
||||
export type AnySource =
|
||||
| GeoJSONSourceRaw
|
||||
| VideoSourceRaw
|
||||
| ImageSourceRaw
|
||||
| CanvasSourceRaw
|
||||
| VectorSourceRaw
|
||||
| GeoJSONSource
|
||||
| VideoSource
|
||||
| ImageSource
|
||||
| CanvasSource
|
||||
| VectorSource
|
||||
| RasterSource
|
||||
| RasterDemSource;
|
||||
|
||||
export type {
|
||||
GeoJSONSourceRaw,
|
||||
VideoSourceRaw,
|
||||
ImageSourceRaw,
|
||||
CanvasSourceRaw,
|
||||
VectorSourceRaw,
|
||||
GeoJSONSource,
|
||||
VideoSource,
|
||||
ImageSource,
|
||||
CanvasSource,
|
||||
VectorSource,
|
||||
RasterSource,
|
||||
RasterDemSource
|
||||
};
|
||||
|
||||
// Other
|
||||
export type {
|
||||
Style as MapStyle,
|
||||
Light,
|
||||
Fog,
|
||||
TerrainSpecification as Terrain,
|
||||
Projection
|
||||
} from 'mapbox-gl';
|
||||
export type {Style as MapStyle, Light, Fog, TerrainSpecification as Terrain} from 'mapbox-gl';
|
||||
|
||||
export type Projection = ProjectionSpecification | ProjectionSpecification['name'];
|
||||
@ -1,4 +1,4 @@
|
||||
import type {PointLike} from '../types';
|
||||
import type {PointLike} from '../types/common';
|
||||
|
||||
/**
|
||||
* Compare two points
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {ImmutableLike, MapStyle} from '../types';
|
||||
import {ImmutableLike} from '../types/common';
|
||||
import {MapStyle} from '../types/style-spec';
|
||||
|
||||
const refProps = ['type', 'source', 'source-layer', 'minzoom', 'maxzoom', 'filter', 'layout'];
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type {MapboxProps} from '../mapbox/mapbox';
|
||||
import type {Transform, ViewState} from '../types';
|
||||
import type {Transform} from '../types/internal';
|
||||
import type {ViewState} from '../types/common';
|
||||
import {deepEqual} from './deep-equal';
|
||||
|
||||
/**
|
||||
|
||||
@ -1 +1,3 @@
|
||||
export * from '@vis.gl/react-mapbox';
|
||||
|
||||
export {Map as default} from '@vis.gl/react-mapbox';
|
||||
|
||||
@ -1 +1,3 @@
|
||||
export * from '@vis.gl/react-maplibre';
|
||||
|
||||
export {Map as default} from '@vis.gl/react-maplibre';
|
||||
|
||||
@ -9,7 +9,7 @@ import type {
|
||||
ImageSourceImplemtation,
|
||||
AnySourceImplementation
|
||||
} from '../types/internal';
|
||||
import type {AnySource, ImageSourceRaw, VectorSourceRaw} from '../types/style-spec';
|
||||
import type {AnySource, ImageSource, VectorSource} from '../types/style-spec';
|
||||
import type {MapInstance} from '../types/lib';
|
||||
|
||||
export type SourceProps = AnySource & {
|
||||
@ -61,11 +61,11 @@ function updateSource(source: AnySourceImplementation, props: SourceProps, prevP
|
||||
coordinates: props.coordinates
|
||||
});
|
||||
} else if ('setCoordinates' in source && changedKeyCount === 1 && changedKey === 'coordinates') {
|
||||
source.setCoordinates((props as unknown as ImageSourceRaw).coordinates);
|
||||
source.setCoordinates((props as unknown as ImageSource).coordinates);
|
||||
} else if ('setUrl' in source && changedKey === 'url') {
|
||||
source.setUrl((props as VectorSourceRaw).url);
|
||||
source.setUrl((props as VectorSource).url);
|
||||
} else if ('setTiles' in source && changedKey === 'tiles') {
|
||||
source.setTiles((props as VectorSourceRaw).tiles);
|
||||
source.setTiles((props as VectorSource).tiles);
|
||||
} else {
|
||||
// eslint-disable-next-line
|
||||
console.warn(`Unable to update <Source> prop: ${changedKey}`);
|
||||
|
||||
@ -13,16 +13,16 @@ import type {
|
||||
LineLayerSpecification as LineLayer,
|
||||
RasterLayerSpecification as RasterLayer,
|
||||
SymbolLayerSpecification as SymbolLayer,
|
||||
GeoJSONSourceSpecification as GeoJSONSourceRaw,
|
||||
VideoSourceSpecification as VideoSourceRaw,
|
||||
ImageSourceSpecification as ImageSourceRaw,
|
||||
VectorSourceSpecification as VectorSourceRaw,
|
||||
GeoJSONSourceSpecification as GeoJSONSource,
|
||||
VideoSourceSpecification as VideoSource,
|
||||
ImageSourceSpecification as ImageSource,
|
||||
VectorSourceSpecification as VectorSource,
|
||||
RasterSourceSpecification as RasterSource,
|
||||
RasterDEMSourceSpecification as RasterDemSource,
|
||||
ProjectionSpecification
|
||||
} from 'mapbox-gl';
|
||||
|
||||
type CanvasSourceRaw = {
|
||||
type CanvasSource = {
|
||||
type: 'canvas';
|
||||
coordinates: [[number, number], [number, number], [number, number], [number, number]];
|
||||
animate?: boolean;
|
||||
@ -55,20 +55,20 @@ export type {
|
||||
};
|
||||
|
||||
export type AnySource =
|
||||
| GeoJSONSourceRaw
|
||||
| VideoSourceRaw
|
||||
| ImageSourceRaw
|
||||
| CanvasSourceRaw
|
||||
| VectorSourceRaw
|
||||
| GeoJSONSource
|
||||
| VideoSource
|
||||
| ImageSource
|
||||
| CanvasSource
|
||||
| VectorSource
|
||||
| RasterSource
|
||||
| RasterDemSource;
|
||||
|
||||
export type {
|
||||
GeoJSONSourceRaw,
|
||||
VideoSourceRaw,
|
||||
ImageSourceRaw,
|
||||
CanvasSourceRaw,
|
||||
VectorSourceRaw,
|
||||
GeoJSONSource,
|
||||
VideoSource,
|
||||
ImageSource,
|
||||
CanvasSource,
|
||||
VectorSource,
|
||||
RasterSource,
|
||||
RasterDemSource
|
||||
};
|
||||
|
||||
@ -12,13 +12,13 @@ import type {
|
||||
LineLayerSpecification as LineLayer,
|
||||
RasterLayerSpecification as RasterLayer,
|
||||
SymbolLayerSpecification as SymbolLayer,
|
||||
GeoJSONSourceSpecification as GeoJSONSourceRaw,
|
||||
VideoSourceSpecification as VideoSourceRaw,
|
||||
ImageSourceSpecification as ImageSourceRaw,
|
||||
VectorSourceSpecification as VectorSourceRaw,
|
||||
GeoJSONSourceSpecification as GeoJSONSource,
|
||||
VideoSourceSpecification as VideoSource,
|
||||
ImageSourceSpecification as ImageSource,
|
||||
VectorSourceSpecification as VectorSource,
|
||||
RasterSourceSpecification as RasterSource,
|
||||
RasterDEMSourceSpecification as RasterDemSource,
|
||||
CanvasSourceSpecification as CanvasSourceRaw,
|
||||
CanvasSourceSpecification as CanvasSource,
|
||||
ProjectionSpecification
|
||||
} from 'maplibre-gl';
|
||||
|
||||
@ -48,21 +48,21 @@ export type AnyLayer =
|
||||
|
||||
// Sources
|
||||
export type {
|
||||
GeoJSONSourceRaw,
|
||||
VideoSourceRaw,
|
||||
ImageSourceRaw,
|
||||
CanvasSourceRaw,
|
||||
VectorSourceRaw,
|
||||
GeoJSONSource,
|
||||
VideoSource,
|
||||
ImageSource,
|
||||
CanvasSource,
|
||||
VectorSource,
|
||||
RasterSource,
|
||||
RasterDemSource
|
||||
};
|
||||
|
||||
export type AnySource =
|
||||
| GeoJSONSourceRaw
|
||||
| VideoSourceRaw
|
||||
| ImageSourceRaw
|
||||
| CanvasSourceRaw
|
||||
| VectorSourceRaw
|
||||
| GeoJSONSource
|
||||
| VideoSource
|
||||
| ImageSource
|
||||
| CanvasSource
|
||||
| VectorSource
|
||||
| RasterSource
|
||||
| RasterDemSource;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user