diff --git a/docs/api/basemap.md b/docs/api/basemap.md index cc19a8e6..3a5acb04 100644 --- a/docs/api/basemap.md +++ b/docs/api/basemap.md @@ -1,3 +1,3 @@ # lonboard.basemap -::: lonboard.basemap.CartoBasemap +::: lonboard.basemap.CartoStyle diff --git a/lonboard/_layer.py b/lonboard/_layer.py index cc3453c2..2cf3599e 100644 --- a/lonboard/_layer.py +++ b/lonboard/_layer.py @@ -279,6 +279,14 @@ def _add_extension_traits(self, extensions: Sequence[BaseExtension]) -> None: for an example. """ + before_id = t.Unicode(None, allow_none=True).tag(sync=True) + """The ID of a layer in the Maplibre basemap layer stack. This deck.gl layer will be + rendered just before the layer with the given ID. + + This only has an effect when the map's `basemap` is a `MaplibreBasemap`, and the map + is rendering in `"interleaved"` mode. + """ + def default_geoarrow_viewport( table: Table, diff --git a/lonboard/_map.py b/lonboard/_map.py index 1e35eac5..579fa0fc 100644 --- a/lonboard/_map.py +++ b/lonboard/_map.py @@ -1,5 +1,6 @@ from __future__ import annotations +import warnings from pathlib import Path from typing import IO, TYPE_CHECKING, Any, TextIO, overload @@ -12,10 +13,9 @@ from lonboard._html_export import map_to_html from lonboard._layer import BaseLayer from lonboard._viewport import compute_view -from lonboard.basemap import CartoBasemap +from lonboard.basemap import CartoStyle, MaplibreBasemap from lonboard.traits import ( DEFAULT_INITIAL_VIEW_STATE, - BasemapUrl, HeightTrait, VariableLengthTuple, ViewStateTrait, @@ -69,6 +69,8 @@ class Map(BaseAnyWidget): def __init__( self, layers: BaseLayer | Sequence[BaseLayer], + *, + basemap_style: str | CartoStyle | None = None, **kwargs: Unpack[MapKwargs], ) -> None: """Create a new Map. @@ -80,12 +82,28 @@ def __init__( layers: One or more layers to render on this map. Keyword Args: + basemap_style: DEPRECATED. Use `basemap` instead. A URL to a MapLibre-compatible basemap style. + + Various styles are provided in [`lonboard.basemap`](https://developmentseed.org/lonboard/latest/api/basemap/). + kwargs: Passed on to class variables. Returns: A Map object. """ + if basemap_style is not None: + warnings.warn( + "`basemap_style` is deprecated and will be removed in 0.14. Use `basemap` instead.", + DeprecationWarning, + stacklevel=2, + ) + if "basemap" in kwargs: + raise ValueError( + "Cannot pass both `basemap_style` and `basemap`. Use only `basemap`.", + ) + kwargs["basemap"] = MaplibreBasemap(style=basemap_style) + if isinstance(layers, BaseLayer): layers = [layers] @@ -161,8 +179,6 @@ def on_click(self, callback: Callable, *, remove: bool = False) -> None: Indicates if a click handler has been registered. """ - render_mode = t.Unicode(default_value="deck-first").tag(sync=True) - height = HeightTrait().tag(sync=True) """Height of the map in pixels, or valid CSS height property. @@ -203,17 +219,43 @@ def on_click(self, callback: Callable, *, remove: bool = False) -> None: - Default: `5` """ - basemap_style = BasemapUrl(CartoBasemap.PositronNoLabels) - """ - A URL to a MapLibre-compatible basemap style. + basemap: t.Instance[MaplibreBasemap | None] = t.Instance( + MaplibreBasemap, + allow_none=True, + ).tag( + sync=True, + **ipywidgets.widget_serialization, + ) + """A basemap instance. - Various styles are provided in [`lonboard.basemap`](https://developmentseed.org/lonboard/latest/api/basemap/). + See [`lonboard.basemap.MaplibreBasemap`] for more information. - - Type: `str`, holding a URL hosting a basemap style. - - Default - [`lonboard.basemap.CartoBasemap.PositronNoLabels`][lonboard.basemap.CartoBasemap.PositronNoLabels] + Pass `None` to disable rendering a basemap. """ + @property + def basemap_style(self) -> str | None: + """The URL of the basemap style in use.""" + warnings.warn( + "`basemap_style` is deprecated and will be removed in 0.14. Use `basemap` instead.", + DeprecationWarning, + stacklevel=2, + ) + + if self.basemap is not None: + return self.basemap.style + + return None + + @basemap_style.setter + def basemap_style(self, value: str | CartoStyle) -> None: + warnings.warn( + "`basemap_style` is deprecated and will be removed in 0.14. Use `basemap` instead.", + DeprecationWarning, + stacklevel=2, + ) + self.basemap = MaplibreBasemap(style=value) + custom_attribution = t.Union( [ t.Unicode(allow_none=True), diff --git a/lonboard/_viz.py b/lonboard/_viz.py index 814fd50d..70c16758 100644 --- a/lonboard/_viz.py +++ b/lonboard/_viz.py @@ -26,7 +26,7 @@ split_mixed_gdf, split_mixed_shapely_array, ) -from lonboard.basemap import CartoBasemap +from lonboard.basemap import CartoStyle, MaplibreBasemap if TYPE_CHECKING: import duckdb @@ -212,8 +212,8 @@ def viz( map_kwargs = map_kwargs if map_kwargs else {} - if "basemap_style" not in map_kwargs: - map_kwargs["basemap_style"] = CartoBasemap.DarkMatter + if "basemap_style" not in map_kwargs and "basemap" not in map_kwargs: + map_kwargs["basemap"] = MaplibreBasemap(style=CartoStyle.DarkMatter) return Map(layers=layers, **map_kwargs) diff --git a/lonboard/basemap.py b/lonboard/basemap.py index 6eb1abcc..8fa2ff9e 100644 --- a/lonboard/basemap.py +++ b/lonboard/basemap.py @@ -1,10 +1,78 @@ """Basemap helpers.""" +from __future__ import annotations + from enum import Enum +from typing import TYPE_CHECKING + +import traitlets as t +from typing_extensions import deprecated + +from lonboard._base import BaseWidget +from lonboard.traits import BasemapUrl + +if TYPE_CHECKING: + from typing import Literal + + +class CartoStyle(str, Enum): + """Maplibre-supported vector basemap styles provided by Carto. + + Refer to [Carto + documentation](https://docs.carto.com/carto-for-developers/carto-for-react/guides/basemaps) + for information on styles. + """ + + DarkMatter = "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json" + """A dark map style with labels. + + ![](https://carto.com/help/images/building-maps/basemaps/dark_labels.png) + """ + + DarkMatterNoLabels = ( + "https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json" + ) + """A dark map style without labels. + + ![](https://carto.com/help/images/building-maps/basemaps/dark_no_labels.png) + """ + + Positron = "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json" + """A light map style with labels. + + ![](https://carto.com/help/images/building-maps/basemaps/positron_labels.png) + """ + PositronNoLabels = ( + "https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json" + ) + """A light map style without labels. + ![](https://carto.com/help/images/building-maps/basemaps/positron_no_labels.png) + """ + + Voyager = "https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json" + """A light, colored map style with labels. + + ![](https://carto.com/help/images/building-maps/basemaps/voyager_labels.png) + """ + + VoyagerNoLabels = ( + "https://basemaps.cartocdn.com/gl/voyager-nolabels-gl-style/style.json" + ) + """A light, colored map style without labels. + + ![](https://carto.com/help/images/building-maps/basemaps/voyager_no_labels.png) + """ + + +# NOTE: this is fully duplicated because you can't subclass enums, and I don't see any +# other way to provide a deprecation warning +@deprecated( + "CartoBasemap is deprecated, use CartoStyle instead. Will be removed in v0.14", +) class CartoBasemap(str, Enum): - """Basemap styles provided by Carto. + """Maplibre-supported vector basemap styles provided by Carto. Refer to [Carto documentation](https://docs.carto.com/carto-for-developers/carto-for-react/guides/basemaps) @@ -20,7 +88,10 @@ class CartoBasemap(str, Enum): DarkMatterNoLabels = ( "https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json" ) - """A dark map style without labels.""" + """A dark map style without labels. + + ![](https://carto.com/help/images/building-maps/basemaps/dark_no_labels.png) + """ Positron = "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json" """A light map style with labels. @@ -31,7 +102,10 @@ class CartoBasemap(str, Enum): PositronNoLabels = ( "https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json" ) - """A light map style without labels.""" + """A light map style without labels. + + ![](https://carto.com/help/images/building-maps/basemaps/positron_no_labels.png) + """ Voyager = "https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json" """A light, colored map style with labels. @@ -42,4 +116,62 @@ class CartoBasemap(str, Enum): VoyagerNoLabels = ( "https://basemaps.cartocdn.com/gl/voyager-nolabels-gl-style/style.json" ) - """A light, colored map style without labels.""" + """A light, colored map style without labels. + + ![](https://carto.com/help/images/building-maps/basemaps/voyager_no_labels.png) + """ + + +class MaplibreBasemap(BaseWidget): + """A MapLibre GL JS basemap.""" + + def __init__( + self, + *, + mode: Literal[ + "interleaved", + "overlaid", + "reverse-controlled", + ] = "reverse-controlled", + style: str | CartoStyle = CartoStyle.PositronNoLabels, + ) -> None: + """Create a MapLibre GL JS basemap.""" + super().__init__(mode=mode, style=style) + + mode = t.Enum( + [ + "interleaved", + "overlaid", + "reverse-controlled", + ], + default_value="reverse-controlled", + ).tag(sync=True) + """The basemap integration mode. + + - **`"interleaved"`**: + + The interleaved mode renders deck.gl layers into the same context created by MapLibre. If you need to mix deck.gl layers with MapLibre layers, e.g. having deck.gl surfaces below text labels, or objects occluding each other correctly in 3D, then you have to use this option. + + - **`"overlaid"`**: + + The overlaid mode renders deck.gl in a separate canvas inside the MapLibre's controls container. If your use case does not require interleaving, but you still want to use certain features of maplibre-gl, such as globe view, then you should use this option. + + - **`"reverse-controlled"`**: + + The reverse-controlled mode renders deck.gl above the MapLibre container and blocks any interaction to the base map. + + If you need to have multiple views, you should use this option. + + **Default**: `"reverse-controlled"` + """ + + style = BasemapUrl(CartoStyle.PositronNoLabels).tag(sync=True) + """ + A URL to a MapLibre-compatible basemap style. + + Various styles are provided in [`lonboard.basemap`](https://developmentseed.org/lonboard/latest/api/basemap/). + + - Type: `str`, holding a URL hosting a basemap style. + - Default + [`lonboard.basemap.CartoStyle.PositronNoLabels`][lonboard.basemap.CartoStyle.PositronNoLabels] + """ diff --git a/lonboard/traits.py b/lonboard/traits.py index a0a61862..fba25a4d 100644 --- a/lonboard/traits.py +++ b/lonboard/traits.py @@ -1078,7 +1078,6 @@ def __init__( **kwargs: Any, ) -> None: super().__init__(*args, **kwargs) - self.tag(sync=True) def validate(self, obj: HasTraits | None, value: Any) -> Any: value = super().validate(obj, value) diff --git a/lonboard/types/map.py b/lonboard/types/map.py index 66b80c57..57f7f89f 100644 --- a/lonboard/types/map.py +++ b/lonboard/types/map.py @@ -9,14 +9,14 @@ from typing_extensions import TypedDict if TYPE_CHECKING: - from lonboard.basemap import CartoBasemap + from lonboard.basemap import MaplibreBasemap class MapKwargs(TypedDict, total=False): """Kwargs to pass into map constructor.""" height: int | str - basemap_style: str | CartoBasemap + basemap: MaplibreBasemap parameters: dict[str, Any] picking_radius: int show_tooltip: bool diff --git a/package-lock.json b/package-lock.json index 268c6264..81c2f8f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -104,7 +104,8 @@ "version": "2.9.0", "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.9.0.tgz", "integrity": "sha512-rnJenoStJ8nvmt9Gzye8nkYd6V22xUAnu4086ER7h1zJ508vStko4pMvDeQ446ilDTFpV5wnoc5YS7XvMwwMqA==", - "license": "(Apache-2.0 AND BSD-3-Clause)" + "license": "(Apache-2.0 AND BSD-3-Clause)", + "peer": true }, "node_modules/@csstools/cascade-layer-name-parser": { "version": "2.0.5", @@ -218,7 +219,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -242,7 +242,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -1357,7 +1356,6 @@ "resolved": "https://registry.npmjs.org/@deck.gl/core/-/core-9.2.1.tgz", "integrity": "sha512-7aQ0jy/T5qc9Llr80XC5OQ/KDA38T0qi68QXuXEy5lZCrOyI4V0wZXgolHylEYisDB5fs+YTTKnzhOp9hrA9xg==", "license": "MIT", - "peer": true, "dependencies": { "@loaders.gl/core": "^4.2.0", "@loaders.gl/images": "^4.2.0", @@ -1383,7 +1381,6 @@ "resolved": "https://registry.npmjs.org/@deck.gl/extensions/-/extensions-9.2.1.tgz", "integrity": "sha512-bajeogSxX2GgloH7RIDK4YsY+2bj414593UfJzZW0Ol9w1xvLvR4SKE7CgctBW+EMZPJYgJfPth9ti2Q7xGlFQ==", "license": "MIT", - "peer": true, "dependencies": { "@luma.gl/constants": "^9.2.2", "@luma.gl/shadertools": "^9.2.2", @@ -1435,7 +1432,6 @@ "resolved": "https://registry.npmjs.org/@deck.gl/layers/-/layers-9.2.1.tgz", "integrity": "sha512-8PuWodigkNJQIdkL2XPwrvP1mD2dOt0WFE3VtVHUt/Vv/mzZ5BeV9M6nt1SADLkV6S5Do8IsC98YuLQ7TRQXEw==", "license": "MIT", - "peer": true, "dependencies": { "@loaders.gl/images": "^4.2.0", "@loaders.gl/schema": "^4.2.0", @@ -2454,6 +2450,7 @@ "resolved": "https://registry.npmjs.org/@loaders.gl/3d-tiles/-/3d-tiles-4.3.4.tgz", "integrity": "sha512-JQ3y3p/KlZP7lfobwON5t7H9WinXEYTvuo3SRQM8TBKhM+koEYZhvI2GwzoXx54MbBbY+s3fm1dq5UAAmaTsZw==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/compression": "4.3.4", "@loaders.gl/crypto": "4.3.4", @@ -2478,13 +2475,15 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" + "license": "Apache-2.0", + "peer": true }, "node_modules/@loaders.gl/compression": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/@loaders.gl/compression/-/compression-4.3.4.tgz", "integrity": "sha512-+o+5JqL9Sx8UCwdc2MTtjQiUHYQGJALHbYY/3CT+b9g/Emzwzez2Ggk9U9waRfdHiBCzEgRBivpWZEOAtkimXQ==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/loader-utils": "4.3.4", "@loaders.gl/worker-utils": "4.3.4", @@ -2509,7 +2508,6 @@ "resolved": "https://registry.npmjs.org/@loaders.gl/core/-/core-4.3.4.tgz", "integrity": "sha512-cG0C5fMZ1jyW6WCsf4LoHGvaIAJCEVA/ioqKoYRwoSfXkOf+17KupK1OUQyUCw5XoRn+oWA1FulJQOYlXnb9Gw==", "license": "MIT", - "peer": true, "dependencies": { "@loaders.gl/loader-utils": "4.3.4", "@loaders.gl/schema": "4.3.4", @@ -2522,6 +2520,7 @@ "resolved": "https://registry.npmjs.org/@loaders.gl/crypto/-/crypto-4.3.4.tgz", "integrity": "sha512-3VS5FgB44nLOlAB9Q82VOQnT1IltwfRa1miE0mpHCe1prYu1M/dMnEyynusbrsp+eDs3EKbxpguIS9HUsFu5dQ==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/loader-utils": "4.3.4", "@loaders.gl/worker-utils": "4.3.4", @@ -2536,6 +2535,7 @@ "resolved": "https://registry.npmjs.org/@loaders.gl/draco/-/draco-4.3.4.tgz", "integrity": "sha512-4Lx0rKmYENGspvcgV5XDpFD9o+NamXoazSSl9Oa3pjVVjo+HJuzCgrxTQYD/3JvRrolW/QRehZeWD/L/cEC6mw==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/loader-utils": "4.3.4", "@loaders.gl/schema": "4.3.4", @@ -2551,6 +2551,7 @@ "resolved": "https://registry.npmjs.org/@loaders.gl/gis/-/gis-4.3.4.tgz", "integrity": "sha512-8xub38lSWW7+ZXWuUcggk7agRHJUy6RdipLNKZ90eE0ZzLNGDstGD1qiBwkvqH0AkG+uz4B7Kkiptyl7w2Oa6g==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/loader-utils": "4.3.4", "@loaders.gl/schema": "4.3.4", @@ -2567,6 +2568,7 @@ "resolved": "https://registry.npmjs.org/@loaders.gl/gltf/-/gltf-4.3.4.tgz", "integrity": "sha512-EiUTiLGMfukLd9W98wMpKmw+hVRhQ0dJ37wdlXK98XPeGGB+zTQxCcQY+/BaMhsSpYt/OOJleHhTfwNr8RgzRg==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/draco": "4.3.4", "@loaders.gl/images": "4.3.4", @@ -2611,6 +2613,7 @@ "resolved": "https://registry.npmjs.org/@loaders.gl/math/-/math-4.3.4.tgz", "integrity": "sha512-UJrlHys1fp9EUO4UMnqTCqvKvUjJVCbYZ2qAKD7tdGzHJYT8w/nsP7f/ZOYFc//JlfC3nq+5ogvmdpq2pyu3TA==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/images": "4.3.4", "@loaders.gl/loader-utils": "4.3.4", @@ -2625,6 +2628,7 @@ "resolved": "https://registry.npmjs.org/@loaders.gl/mvt/-/mvt-4.3.4.tgz", "integrity": "sha512-9DrJX8RQf14htNtxsPIYvTso5dUce9WaJCWCIY/79KYE80Be6dhcEYMknxBS4w3+PAuImaAe66S5xo9B7Erm5A==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/gis": "4.3.4", "@loaders.gl/images": "4.3.4", @@ -2655,6 +2659,7 @@ "resolved": "https://registry.npmjs.org/@loaders.gl/terrain/-/terrain-4.3.4.tgz", "integrity": "sha512-JszbRJGnxL5Fh82uA2U8HgjlsIpzYoCNNjy3cFsgCaxi4/dvjz3BkLlBilR7JlbX8Ka+zlb4GAbDDChiXLMJ/g==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/images": "4.3.4", "@loaders.gl/loader-utils": "4.3.4", @@ -2670,6 +2675,7 @@ "resolved": "https://registry.npmjs.org/@loaders.gl/textures/-/textures-4.3.4.tgz", "integrity": "sha512-arWIDjlE7JaDS6v9by7juLfxPGGnjT9JjleaXx3wq/PTp+psLOpGUywHXm38BNECos3MFEQK3/GFShWI+/dWPw==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/images": "4.3.4", "@loaders.gl/loader-utils": "4.3.4", @@ -2688,6 +2694,7 @@ "resolved": "https://registry.npmjs.org/@loaders.gl/tiles/-/tiles-4.3.4.tgz", "integrity": "sha512-oC0zJfyvGox6Ag9ABF8fxOkx9yEFVyzTa9ryHXl2BqLiQoR1v3p+0tIJcEbh5cnzHfoTZzUis1TEAZluPRsHBQ==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/loader-utils": "4.3.4", "@loaders.gl/math": "4.3.4", @@ -2706,6 +2713,7 @@ "resolved": "https://registry.npmjs.org/@loaders.gl/wms/-/wms-4.3.4.tgz", "integrity": "sha512-yXF0wuYzJUdzAJQrhLIua6DnjOiBJusaY1j8gpvuH1VYs3mzvWlIRuZKeUd9mduQZKK88H2IzHZbj2RGOauq4w==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/images": "4.3.4", "@loaders.gl/loader-utils": "4.3.4", @@ -2732,6 +2740,7 @@ "resolved": "https://registry.npmjs.org/@loaders.gl/xml/-/xml-4.3.4.tgz", "integrity": "sha512-p+y/KskajsvyM3a01BwUgjons/j/dUhniqd5y1p6keLOuwoHlY/TfTKd+XluqfyP14vFrdAHCZTnFCWLblN10w==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/loader-utils": "4.3.4", "@loaders.gl/schema": "4.3.4", @@ -2746,6 +2755,7 @@ "resolved": "https://registry.npmjs.org/@loaders.gl/zip/-/zip-4.3.4.tgz", "integrity": "sha512-bHY4XdKYJm3vl9087GMoxnUqSURwTxPPh6DlAGOmz6X9Mp3JyWuA2gk3tQ1UIuInfjXKph3WAUfGe6XRIs1sfw==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/compression": "4.3.4", "@loaders.gl/crypto": "4.3.4", @@ -2761,15 +2771,13 @@ "version": "9.2.2", "resolved": "https://registry.npmjs.org/@luma.gl/constants/-/constants-9.2.2.tgz", "integrity": "sha512-XURMF0gSh0ImZltYa/PCe9KgmopQJiOA6y1m1PxDxJY8OCLma7ZJyvomLn7TQBvPtWTYZsibTW7blu7RwThsaQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@luma.gl/core": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/@luma.gl/core/-/core-9.2.2.tgz", "integrity": "sha512-X63BnXXDlC9AmoG4sUVsfxLn+DoNovbX/z5ZXxnhpxx47536Ss/SLzwnLvm/ZoDhK9/s5qdI95mSZKuqzKCkjw==", "license": "MIT", - "peer": true, "dependencies": { "@math.gl/types": "^4.1.0", "@probe.gl/env": "^4.0.8", @@ -2783,7 +2791,6 @@ "resolved": "https://registry.npmjs.org/@luma.gl/engine/-/engine-9.2.2.tgz", "integrity": "sha512-Upq/jVPvgi/rjwgSGYyW+jobJBotKR/aNTDwyHAubx6wXWluZqnR0ZBwctiO9i7w2RIzZGboMYs4dIgVw0ULaQ==", "license": "MIT", - "peer": true, "dependencies": { "@math.gl/core": "^4.1.0", "@math.gl/types": "^4.1.0", @@ -2800,6 +2807,7 @@ "resolved": "https://registry.npmjs.org/@luma.gl/gltf/-/gltf-9.2.2.tgz", "integrity": "sha512-OL5dZlgq99QZCmOAPq4J3wlEmVkDbBdpXlzUukyHqI/1UV1jonb6e41JykXn1WuOYcrtYM8PnygG3MQ8afRjvA==", "license": "MIT", + "peer": true, "dependencies": { "@loaders.gl/core": "^4.2.0", "@loaders.gl/gltf": "^4.2.0", @@ -2818,7 +2826,6 @@ "resolved": "https://registry.npmjs.org/@luma.gl/shadertools/-/shadertools-9.2.2.tgz", "integrity": "sha512-ChskCXE8Q+5/rC8zPR7pHBSfERGRui5qvw6bZnOZMVwTvGbW5tI5od5Wu9ytGi45kWus66M+M/o5LpP3hfc4Hg==", "license": "MIT", - "peer": true, "dependencies": { "@math.gl/core": "^4.1.0", "@math.gl/types": "^4.1.0", @@ -3016,13 +3023,15 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/@mapbox/martini/-/martini-0.2.0.tgz", "integrity": "sha512-7hFhtkb0KTLEls+TRw/rWayq5EeHtTaErgm/NskVoXmtgAQu/9D299aeyj6mzAR/6XUnYRp2lU+4IcrYRFjVsQ==", - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/@mapbox/point-geometry": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz", "integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==", - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/@mapbox/tiny-sdf": { "version": "2.0.7", @@ -3041,6 +3050,7 @@ "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz", "integrity": "sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==", "license": "BSD-3-Clause", + "peer": true, "dependencies": { "@mapbox/point-geometry": "~0.1.0" } @@ -3132,6 +3142,7 @@ "resolved": "https://registry.npmjs.org/@math.gl/culling/-/culling-4.1.0.tgz", "integrity": "sha512-jFmjFEACnP9kVl8qhZxFNhCyd47qPfSVmSvvjR0/dIL6R9oD5zhR1ub2gN16eKDO/UM7JF9OHKU3EBIfeR7gtg==", "license": "MIT", + "peer": true, "dependencies": { "@math.gl/core": "4.1.0", "@math.gl/types": "4.1.0" @@ -3142,6 +3153,7 @@ "resolved": "https://registry.npmjs.org/@math.gl/geospatial/-/geospatial-4.1.0.tgz", "integrity": "sha512-BzsUhpVvnmleyYF6qdqJIip6FtIzJmnWuPTGhlBuPzh7VBHLonCFSPtQpbkRuoyAlbSyaGXcVt6p6lm9eK2vtg==", "license": "MIT", + "peer": true, "dependencies": { "@math.gl/core": "4.1.0", "@math.gl/types": "4.1.0" @@ -3152,7 +3164,6 @@ "resolved": "https://registry.npmjs.org/@math.gl/polygon/-/polygon-4.1.0.tgz", "integrity": "sha512-YA/9PzaCRHbIP5/0E9uTYrqe+jsYTQoqoDWhf6/b0Ixz8bPZBaGDEafLg3z7ffBomZLacUty9U3TlPjqMtzPjA==", "license": "MIT", - "peer": true, "dependencies": { "@math.gl/core": "4.1.0" } @@ -4310,7 +4321,6 @@ "resolved": "https://registry.npmjs.org/@nextui-org/system/-/system-2.4.6.tgz", "integrity": "sha512-6ujAriBZMfQ16n6M6Ad9g32KJUa1CzqIVaHN/tymadr/3m8hrr7xDw6z50pVjpCRq2PaaA1hT8Hx7EFU3f2z3Q==", "license": "MIT", - "peer": true, "dependencies": { "@internationalized/date": "3.6.0", "@nextui-org/react-utils": "2.1.3", @@ -4405,7 +4415,6 @@ "resolved": "https://registry.npmjs.org/@nextui-org/theme/-/theme-2.4.5.tgz", "integrity": "sha512-c7Y17n+hBGiFedxMKfg7Qyv93iY5MteamLXV4Po4c1VF1qZJI6I+IKULFh3FxPWzAoz96r6NdYT7OLFjrAJdWg==", "license": "MIT", - "peer": true, "dependencies": { "@nextui-org/shared-utils": "2.1.2", "clsx": "^1.2.1", @@ -7397,6 +7406,7 @@ "resolved": "https://registry.npmjs.org/@turf/boolean-clockwise/-/boolean-clockwise-5.1.5.tgz", "integrity": "sha512-FqbmEEOJ4rU4/2t7FKx0HUWmjFEVqR+NJrFP7ymGSjja2SQ7Q91nnBihGuT+yuHHl6ElMjQ3ttsB/eTmyCycxA==", "license": "MIT", + "peer": true, "dependencies": { "@turf/helpers": "^5.1.5", "@turf/invariant": "^5.1.5" @@ -7407,6 +7417,7 @@ "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-5.1.5.tgz", "integrity": "sha512-//pITsQ8xUdcQ9pVb4JqXiSqG4dos5Q9N4sYFoWghX21tfOV2dhc5TGqYOhnHrQS7RiKQL1vQ48kIK34gQ5oRg==", "license": "MIT", + "peer": true, "dependencies": { "@turf/helpers": "^5.1.5" } @@ -7415,13 +7426,15 @@ "version": "5.1.5", "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-5.1.5.tgz", "integrity": "sha512-/lF+JR+qNDHZ8bF9d+Cp58nxtZWJ3sqFe6n3u3Vpj+/0cqkjk4nXKYBSY0azm+GIYB5mWKxUXvuP/m0ZnKj1bw==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@turf/invariant": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-5.2.0.tgz", "integrity": "sha512-28RCBGvCYsajVkw2EydpzLdcYyhSA77LovuOvgCJplJWaNVyJYH6BOR3HR9w50MEkPqb/Vc/jdo6I6ermlRtQA==", "license": "MIT", + "peer": true, "dependencies": { "@turf/helpers": "^5.1.5" } @@ -7431,6 +7444,7 @@ "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-5.2.0.tgz", "integrity": "sha512-ZjQ3Ii62X9FjnK4hhdsbT+64AYRpaI8XMBMcyftEOGSmPMUVnkbvuv3C9geuElAXfQU7Zk1oWGOcrGOD9zr78Q==", "license": "MIT", + "peer": true, "dependencies": { "@turf/helpers": "^5.1.5" } @@ -7440,6 +7454,7 @@ "resolved": "https://registry.npmjs.org/@turf/rewind/-/rewind-5.1.5.tgz", "integrity": "sha512-Gdem7JXNu+G4hMllQHXRFRihJl3+pNl7qY+l4qhQFxq+hiU1cQoVFnyoleIqWKIrdK/i2YubaSwc3SCM7N5mMw==", "license": "MIT", + "peer": true, "dependencies": { "@turf/boolean-clockwise": "^5.1.5", "@turf/clone": "^5.1.5", @@ -7464,6 +7479,7 @@ "resolved": "https://registry.npmjs.org/@types/brotli/-/brotli-1.3.4.tgz", "integrity": "sha512-cKYjgaS2DMdCKF7R0F5cgx1nfBYObN2ihIuPGQ4/dlIY6RpV7OWNwe9L8V4tTVKL2eZqOkNM9FM/rgTvLf4oXw==", "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*" } @@ -7484,7 +7500,8 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz", "integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/estree": { "version": "1.0.8", @@ -7576,14 +7593,14 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.7.tgz", "integrity": "sha512-YBtzT2ztNF6R/9+UXj2wTGFnC9NklAnASt3sC0h2m1bbH7G6FyBIkt4AN8ThZpNfxUo1b2iMVO0UawiJymEt8A==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/react": { "version": "19.2.2", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -7674,7 +7691,6 @@ "integrity": "sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.46.1", "@typescript-eslint/types": "8.46.1", @@ -8097,6 +8113,7 @@ "resolved": "https://registry.npmjs.org/a5-js/-/a5-js-0.5.0.tgz", "integrity": "sha512-VAw19sWdYadhdovb0ViOIi1SdKx6H6LwcGMRFKwMfgL5gcmL/1fKJHfgsNgNaJ7xC/eEyjs6VK+VVd4N0a+peg==", "license": "Apache-2.0", + "peer": true, "dependencies": { "gl-matrix": "^3.4.3" } @@ -8107,7 +8124,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -8193,7 +8209,6 @@ "resolved": "https://registry.npmjs.org/apache-arrow/-/apache-arrow-21.1.0.tgz", "integrity": "sha512-kQrYLxhC+NTVVZ4CCzGF6L/uPVOzJmD1T3XgbiUnP7oTeVFOFgEUu6IKNwCDkpFoBVqDKQivlX4RUFqqnWFlEA==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@swc/helpers": "^0.5.11", "@types/command-line-args": "^5.2.3", @@ -8518,7 +8533,8 @@ } ], "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/baseline-browser-mapping": { "version": "2.8.16", @@ -8571,6 +8587,7 @@ "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "base64-js": "^1.1.2" } @@ -8595,7 +8612,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -8615,6 +8631,7 @@ "resolved": "https://registry.npmjs.org/buf-compare/-/buf-compare-1.0.1.tgz", "integrity": "sha512-Bvx4xH00qweepGc43xFvMs5BKASXTbHaHm6+kDYIK9p/4iFwjATQkmPKHQSgJZzKbAymhztRbXUf1Nqhzl73/Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -8623,7 +8640,8 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", - "license": "MIT/X11" + "license": "MIT/X11", + "peer": true }, "node_modules/bytewise": { "version": "1.1.0", @@ -8796,6 +8814,7 @@ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", "license": "BSD-3-Clause", + "peer": true, "engines": { "node": "*" } @@ -8906,7 +8925,8 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz", "integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/command-line-args": { "version": "6.0.1", @@ -9012,6 +9032,7 @@ "resolved": "https://registry.npmjs.org/core-assert/-/core-assert-0.2.1.tgz", "integrity": "sha512-IG97qShIP+nrJCXMCgkNZgH7jZQ4n8RpPyPeXX++T6avR/KhLhgLiHKoEn5Rc1KjfycSfA9DMa6m+4C4eguHhw==", "license": "MIT", + "peer": true, "dependencies": { "buf-compare": "^1.0.0", "is-error": "^2.2.0" @@ -9024,7 +9045,8 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/cross-spawn": { "version": "7.0.6", @@ -9045,6 +9067,7 @@ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", "license": "BSD-3-Clause", + "peer": true, "engines": { "node": "*" } @@ -9165,7 +9188,8 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/d3-hexbin/-/d3-hexbin-0.2.2.tgz", "integrity": "sha512-KS3fUT2ReD4RlGCjvCEm1RgMtp2NFZumdMu4DBzQK8AZv3fXRM6Xm8I4fSU07UXvH4xxg03NwWKWdvxfS/yc4w==", - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/data-view-buffer": { "version": "1.0.2", @@ -9266,6 +9290,7 @@ "resolved": "https://registry.npmjs.org/deep-strict-equal/-/deep-strict-equal-0.2.0.tgz", "integrity": "sha512-3daSWyvZ/zwJvuMGlzG1O+Ow0YSadGfb3jsh9xoCutv2tWyB9dA4YvR9L9/fSdDZa2dByYQe+TqapSGUrjnkoA==", "license": "MIT", + "peer": true, "dependencies": { "core-assert": "^0.2.0" }, @@ -9373,7 +9398,8 @@ "version": "1.5.7", "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.7.tgz", "integrity": "sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==", - "license": "Apache-2.0" + "license": "Apache-2.0", + "peer": true }, "node_modules/dunder-proto": { "version": "1.0.1", @@ -9605,7 +9631,6 @@ "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -9685,7 +9710,6 @@ "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -10159,6 +10183,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "strnum": "^1.1.1" }, @@ -10179,7 +10204,8 @@ "version": "0.7.4", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz", "integrity": "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/file-entry-cache": { "version": "8.0.0", @@ -10327,7 +10353,6 @@ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.24.tgz", "integrity": "sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==", "license": "MIT", - "peer": true, "dependencies": { "motion-dom": "^12.23.23", "motion-utils": "^12.23.6", @@ -10625,6 +10650,7 @@ "resolved": "https://registry.npmjs.org/h3-js/-/h3-js-4.3.0.tgz", "integrity": "sha512-zgvyHZz5bEKeuyYGh0bF9/kYSxJ2SqroopkXHqKnD3lfjaZawcxulcI9nWbNC54gakl/2eObRLHWueTf1iLSaA==", "license": "Apache-2.0", + "peer": true, "engines": { "node": ">=4", "npm": ">=3", @@ -10754,7 +10780,8 @@ "url": "https://feross.org/support" } ], - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/ignore": { "version": "5.3.2", @@ -10778,6 +10805,7 @@ "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.7.5.tgz", "integrity": "sha512-Hiyv+mXHfFEP7LzUL/llg9RwFxxY+o9N3JVLIeG5E7iFIFAalxvRU9UZthBdYDEVnzHMgjnKJPPpay5BWf1g9g==", "license": "MIT", + "peer": true, "bin": { "image-size": "bin/image-size.js" }, @@ -10789,7 +10817,8 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/immutable": { "version": "5.1.4", @@ -10828,7 +10857,8 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/input-otp": { "version": "1.4.1", @@ -10960,7 +10990,8 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/is-callable": { "version": "1.2.7", @@ -11029,7 +11060,8 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-error/-/is-error-2.2.2.tgz", "integrity": "sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/is-extendable": { "version": "0.1.1", @@ -11344,7 +11376,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/isexe": { "version": "2.0.0", @@ -11420,7 +11453,6 @@ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "license": "MIT", - "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -11556,6 +11588,7 @@ "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", "license": "(MIT OR GPL-3.0-or-later)", + "peer": true, "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", @@ -11583,7 +11616,8 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/ktx-parse/-/ktx-parse-0.7.1.tgz", "integrity": "sha512-FeA3g56ksdFNwjXJJsc1CCc7co+AJYDp6ipIp878zZ2bU8kWROatLYf39TQEd4/XRSUvBXovQ8gaVKWPXsCLEQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/levn": { "version": "0.4.1", @@ -11626,6 +11660,7 @@ "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "license": "MIT", + "peer": true, "dependencies": { "immediate": "~3.0.5" } @@ -11718,6 +11753,7 @@ "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", "integrity": "sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg==", "license": "Apache-2.0", + "peer": true, "engines": { "node": ">=0.6" } @@ -11753,13 +11789,15 @@ "resolved": "https://registry.npmjs.org/lz4js/-/lz4js-0.2.0.tgz", "integrity": "sha512-gY2Ia9Lm7Ep8qMiuGRhvUq0Q7qUereeldZPP1PMEJxPtEWHJLqw9pgX68oHajBH0nzJK4MaZEA/YNV3jT8u8Bg==", "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/lzo-wasm": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/lzo-wasm/-/lzo-wasm-0.0.4.tgz", "integrity": "sha512-VKlnoJRFrB8SdJhlVKvW5vI1gGwcZ+mvChEXcSX6r2xDNc/Q2FD9esfBmGCuPZdrJ1feO+YcVFd2PTk0c137Gw==", - "license": "BSD-2-Clause" + "license": "BSD-2-Clause", + "peer": true }, "node_modules/magic-string": { "version": "0.30.19", @@ -11858,6 +11896,7 @@ "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", "license": "BSD-3-Clause", + "peer": true, "dependencies": { "charenc": "0.0.2", "crypt": "0.0.2", @@ -12311,7 +12350,8 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "license": "(MIT AND Zlib)" + "license": "(MIT AND Zlib)", + "peer": true }, "node_modules/parent-module": { "version": "1.0.1", @@ -12412,6 +12452,7 @@ "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.3.0.tgz", "integrity": "sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==", "license": "BSD-3-Clause", + "peer": true, "dependencies": { "ieee754": "^1.1.12", "resolve-protobuf-schema": "^2.1.0" @@ -12532,7 +12573,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -13456,7 +13496,6 @@ "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -13482,6 +13521,7 @@ "resolved": "https://registry.npmjs.org/preact/-/preact-10.27.2.tgz", "integrity": "sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==", "license": "MIT", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -13517,7 +13557,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/proj4": { "version": "2.19.10", @@ -13612,7 +13653,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -13622,7 +13662,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -13692,6 +13731,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "license": "MIT", + "peer": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -13900,6 +13940,7 @@ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", + "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -13935,7 +13976,8 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/safe-identifier": { "version": "0.4.2", @@ -14070,6 +14112,7 @@ ], "license": "MIT", "optional": true, + "peer": true, "dependencies": { "sass": "1.93.2" } @@ -14086,6 +14129,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14102,6 +14146,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14118,6 +14163,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14134,6 +14180,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14150,6 +14197,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14166,6 +14214,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14182,6 +14231,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14198,6 +14248,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14214,6 +14265,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14230,6 +14282,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14246,6 +14299,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14262,6 +14316,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14278,6 +14333,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14294,6 +14350,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14310,6 +14367,7 @@ "!linux", "!win32" ], + "peer": true, "dependencies": { "sass": "1.93.2" } @@ -14326,6 +14384,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14342,6 +14401,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14351,6 +14411,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "license": "MIT", + "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -14482,7 +14543,8 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/shebang-command": { "version": "2.0.0", @@ -14639,7 +14701,8 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/snappyjs/-/snappyjs-0.6.1.tgz", "integrity": "sha512-YIK6I2lsH072UE0aOFxxY1dPDCS43I5ktqHpeAsuLNYWkE5pGxRGWfDM4/vSUfNzXjC1Ivzt3qx31PCLmc9yqg==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/sort-asc": { "version": "0.2.0", @@ -14726,7 +14789,8 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/stackback": { "version": "0.0.2", @@ -14761,6 +14825,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "license": "MIT", + "peer": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -14999,7 +15064,8 @@ "url": "https://github.com/sponsors/NaturalIntelligence" } ], - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/sucrase": { "version": "3.35.0", @@ -15074,6 +15140,7 @@ "resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz", "integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==", "license": "MIT", + "peer": true, "dependencies": { "sync-message-port": "^1.0.0" }, @@ -15086,6 +15153,7 @@ "resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.1.3.tgz", "integrity": "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==", "license": "MIT", + "peer": true, "engines": { "node": ">=16.0.0" } @@ -15144,7 +15212,6 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.18.tgz", "integrity": "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==", "license": "MIT", - "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -15195,6 +15262,7 @@ "resolved": "https://registry.npmjs.org/texture-compressor/-/texture-compressor-1.0.2.tgz", "integrity": "sha512-dStVgoaQ11mA5htJ+RzZ51ZxIZqNOgWKAIvtjLrW1AliQQLCmrDqNzQZ8Jh91YealQ95DXt4MEduLzJmbs6lig==", "license": "MIT", + "peer": true, "dependencies": { "argparse": "^1.0.10", "image-size": "^0.7.4" @@ -15208,6 +15276,7 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "license": "MIT", + "peer": true, "dependencies": { "sprintf-js": "~1.0.2" } @@ -15481,7 +15550,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -15759,7 +15827,8 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/vite": { "version": "5.4.20", @@ -16593,7 +16662,6 @@ "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -16615,7 +16683,6 @@ "resolved": "https://registry.npmjs.org/xstate/-/xstate-5.23.0.tgz", "integrity": "sha512-jo126xWXkU6ySQ91n51+H2xcgnMuZcCQpQoD3FQ79d32a6RQvryRh8rrDHnH4WDdN/yg5xNjlIRol9ispMvzeg==", "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/xstate" @@ -16648,7 +16715,6 @@ "integrity": "sha512-OIDwaflOaq4wC6YlPBy2L6ceKeKuF7DeTxx+jPzv1FHn9tCZ0ZwSRnUBxD05E3yed46fv/FWJbvR+Ud7x0L7zw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "lib0": "^0.2.99" }, @@ -16679,7 +16745,8 @@ "resolved": "https://registry.npmjs.org/zstd-codec/-/zstd-codec-0.1.5.tgz", "integrity": "sha512-v3fyjpK8S/dpY/X5WxqTK3IoCnp/ZOLxn144GZVlNUjtwAchzrVo03h+oMATFhCIiJ5KTr4V3vDQQYz4RU684g==", "license": "MIT", - "optional": true + "optional": true, + "peer": true } } } diff --git a/src/index.tsx b/src/index.tsx index 3fa03e6d..5d8f20e3 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -10,15 +10,21 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { v4 as uuidv4 } from "uuid"; import { flyTo } from "./actions/fly-to.js"; +import { DEFAULT_MAP_STYLE, MaplibreBasemapModel } from "./model/basemap.js"; import { initializeLayer, type BaseLayerModel, initializeChildModels, } from "./model/index.js"; +import { loadModel } from "./model/initialize.js"; import { initParquetWasm } from "./parquet.js"; import DeckFirstRenderer from "./renderers/deck-first.js"; import OverlayRenderer from "./renderers/overlay.js"; -import { MapRendererProps } from "./renderers/types.js"; +import { + DeckFirstRendererProps, + MapRendererProps, + OverlayRendererProps, +} from "./renderers/types.js"; import SidePanel from "./sidepanel/index"; import { useViewStateDebounced } from "./state"; import Toolbar from "./toolbar.js"; @@ -41,9 +47,6 @@ const DEFAULT_INITIAL_VIEW_STATE = { pitch: 0, }; -const DEFAULT_MAP_STYLE = - "https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json"; - function App() { const actorRef = MachineContext.useActorRef(); const isDrawingBBoxSelection = MachineContext.useSelector( @@ -77,7 +80,7 @@ function App() { const model = useModel(); - const [mapStyle] = useModelState("basemap_style"); + const [basemapModelId] = useModelState("basemap"); const [mapHeight] = useModelState("height"); const [showTooltip] = useModelState("show_tooltip"); const [showSidePanel] = useModelState("show_side_panel"); @@ -87,7 +90,6 @@ function App() { ); const [parameters] = useModelState("parameters"); const [customAttribution] = useModelState("custom_attribution"); - const [renderMode] = useModelState("render_mode"); // initialViewState is the value of view_state on the Python side. This is // called `initial` here because it gets passed in to deck's @@ -120,11 +122,40 @@ function App() { const [childLayerIds] = useModelState("layers"); + const [basemapState, setBasemapState] = useState( + null, + ); + // Fake state just to get react to re-render when a model callback is called // eslint-disable-next-line @typescript-eslint/no-unused-vars const [stateCounter, setStateCounter] = useState(new Date()); const updateStateCallback = () => setStateCounter(new Date()); + useEffect(() => { + const loadBasemap = async () => { + try { + if (!basemapModelId) { + setBasemapState(null); + return; + } + + const basemapModel = await loadModel( + model.widget_manager as IWidgetManager, + basemapModelId, + ); + const basemap = new MaplibreBasemapModel( + basemapModel, + updateStateCallback, + ); + setBasemapState(basemap); + } catch (error) { + console.error("Error loading basemap model:", error); + } + }; + + loadBasemap(); + }, [basemapModelId]); + useEffect(() => { const loadAndUpdateLayers = async () => { try { @@ -194,7 +225,7 @@ function App() { ); const mapRenderProps: MapRendererProps = { - mapStyle: mapStyle || DEFAULT_MAP_STYLE, + mapStyle: basemapState?.style || DEFAULT_MAP_STYLE, customAttribution, deckRef, initialViewState: ["longitude", "latitude", "zoom"].every((key) => @@ -232,6 +263,14 @@ function App() { parameters: parameters || {}, }; + const overlayRenderProps: OverlayRendererProps = { + interleaved: basemapState?.mode === "interleaved", + }; + + const deckFirstRenderProps: DeckFirstRendererProps = { + renderBasemap: Boolean(basemapState), + }; + return (
actorRef.send({ type: "Close side panel" })} /> )} -
- {renderMode === "overlay" ? ( - +
+ {basemapState?.mode === "overlaid" || + basemapState?.mode === "interleaved" ? ( + ) : ( - + )}
diff --git a/src/model/base-layer.ts b/src/model/base-layer.ts index 810594eb..c533bdc0 100644 --- a/src/model/base-layer.ts +++ b/src/model/base-layer.ts @@ -20,6 +20,7 @@ export abstract class BaseLayerModel extends BaseModel { protected opacity: LayerProps["opacity"]; protected autoHighlight: LayerProps["autoHighlight"]; protected highlightColor: LayerProps["highlightColor"]; + protected beforeId?: string; protected extensions: Record; @@ -36,6 +37,7 @@ export abstract class BaseLayerModel extends BaseModel { this.initRegularAttribute("opacity", "opacity"); this.initRegularAttribute("auto_highlight", "autoHighlight"); this.initRegularAttribute("highlight_color", "highlightColor"); + this.initRegularAttribute("before_id", "beforeId"); this.initRegularAttribute("selected_bounds", "selectedBounds"); this.extensions = {}; @@ -81,6 +83,9 @@ export abstract class BaseLayerModel extends BaseModel { highlightColor: this.highlightColor, }), onClick: this.onClick.bind(this), + ...(isDefined(this.beforeId) && { + beforeId: this.beforeId, + }), }; } diff --git a/src/model/basemap.ts b/src/model/basemap.ts new file mode 100644 index 00000000..aede633a --- /dev/null +++ b/src/model/basemap.ts @@ -0,0 +1,18 @@ +import type { WidgetModel } from "@jupyter-widgets/base"; + +import { BaseModel } from "./base"; + +export const DEFAULT_MAP_STYLE = + "https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json"; + +export class MaplibreBasemapModel extends BaseModel { + mode?: "interleaved" | "overlaid" | "reverse-controlled"; + style?: string; + + constructor(model: WidgetModel, updateStateCallback: () => void) { + super(model, updateStateCallback); + + this.initRegularAttribute("mode", "mode"); + this.initRegularAttribute("style", "style"); + } +} diff --git a/src/model/initialize.ts b/src/model/initialize.ts index 2306e5ac..05eb3b7e 100644 --- a/src/model/initialize.ts +++ b/src/model/initialize.ts @@ -50,6 +50,15 @@ export async function initializeChildModels( return newSubModelState; } +export async function loadModel( + widget_manager: IWidgetManager, + childModelId: string, +): Promise { + // We need to slice off the "IPY_MODEL_" prefix to get the actual model ID + const modelId = childModelId.slice(IPY_MODEL_LENGTH); + return widget_manager.get_model(modelId); +} + /** * Load and resolve other widget models. * @@ -59,11 +68,9 @@ async function loadModels( widget_manager: IWidgetManager, childModelIds: string[], ): Promise> { - const promises = childModelIds.map((childModelId) => { - // We need to slice off the "IPY_MODEL_" prefix to get the actual model ID - const modelId = childModelId.slice(IPY_MODEL_LENGTH); - return widget_manager.get_model(modelId); - }); + const promises = childModelIds.map((childModelId) => + loadModel(widget_manager, childModelId), + ); const models = await Promise.all(promises); diff --git a/src/renderers/deck-first.tsx b/src/renderers/deck-first.tsx index f31f0470..dcf6cfc5 100644 --- a/src/renderers/deck-first.tsx +++ b/src/renderers/deck-first.tsx @@ -2,7 +2,7 @@ import DeckGL from "@deck.gl/react"; import React from "react"; import Map from "react-map-gl/maplibre"; -import type { MapRendererProps } from "./types"; +import type { DeckFirstRendererProps, MapRendererProps } from "./types"; /** * DeckFirst renderer: DeckGL wraps Map component @@ -12,9 +12,12 @@ import type { MapRendererProps } from "./types"; * This is the traditional approach where deck.gl has full control over * the rendering pipeline. */ -const DeckFirstRenderer: React.FC = (mapProps) => { +const DeckFirstRenderer: React.FC = ( + mapProps, +) => { // Remove maplibre-specific props before passing to DeckGL - const { mapStyle, customAttribution, deckRef, ...deckProps } = mapProps; + const { mapStyle, customAttribution, deckRef, renderBasemap, ...deckProps } = + mapProps; return ( = (mapProps) => { }} {...deckProps} > - + {renderBasemap && ( + + )} ); }; diff --git a/src/renderers/overlay.tsx b/src/renderers/overlay.tsx index 65cfbef7..5509e79a 100644 --- a/src/renderers/overlay.tsx +++ b/src/renderers/overlay.tsx @@ -2,7 +2,7 @@ import { MapboxOverlay, MapboxOverlayProps } from "@deck.gl/mapbox"; import React from "react"; import Map, { useControl } from "react-map-gl/maplibre"; -import type { MapRendererProps } from "./types"; +import type { MapRendererProps, OverlayRendererProps } from "./types"; /** * DeckGLOverlay component that integrates deck.gl with react-map-gl @@ -24,7 +24,9 @@ function DeckGLOverlay(props: MapboxOverlayProps) { * MapboxOverlay. This approach gives the base map more control and can * enable features like interleaved rendering between map and deck layers. */ -const OverlayRenderer: React.FC = (mapProps) => { +const OverlayRenderer: React.FC = ( + mapProps, +) => { // Remove maplibre-specific props before passing to DeckGL const { mapStyle, customAttribution, initialViewState, ...deckProps } = mapProps; diff --git a/src/renderers/types.ts b/src/renderers/types.ts index d6f806d8..b59044fb 100644 --- a/src/renderers/types.ts +++ b/src/renderers/types.ts @@ -20,3 +20,11 @@ export type MapRendererProps = Pick< customAttribution: string; deckRef?: RefObject; }; + +export type OverlayRendererProps = { + interleaved: boolean; +}; + +export type DeckFirstRendererProps = { + renderBasemap: boolean; +};