diff --git a/__tests__/components/Style.test.js b/__tests__/components/Style.test.js
deleted file mode 100644
index 54a789433..000000000
--- a/__tests__/components/Style.test.js
+++ /dev/null
@@ -1,261 +0,0 @@
-import { render } from "@testing-library/react-native";
-import React from "react";
-
-import BackgroundLayer from "../../src/components/BackgroundLayer";
-import CircleLayer from "../../src/components/CircleLayer";
-import FillExtrusionLayer from "../../src/components/FillExtrusionLayer";
-import FillLayer from "../../src/components/FillLayer";
-import HeatmapLayer from "../../src/components/HeatmapLayer";
-import ImageSource from "../../src/components/ImageSource";
-import LineLayer from "../../src/components/LineLayer";
-import RasterLayer from "../../src/components/RasterLayer";
-import RasterSource from "../../src/components/RasterSource";
-import ShapeSource from "../../src/components/ShapeSource";
-import Style from "../../src/components/Style";
-import SymbolLayer from "../../src/components/SymbolLayer";
-import VectorSource from "../../src/components/VectorSource";
-
-describe("Style", () => {
- test("renders vectory source correctly", () => {
- const vectorSource = {
- type: "vector",
- url: "https://demotiles.maplibre.org/tiles/tiles.json",
- tiles: ["http://host1", "http://host2"],
- minzoom: 1,
- maxzoom: 22,
- attribution: "Copyright",
- scheme: "tms",
- };
-
- const json = {
- layers: [],
- sources: {
- vectorSource,
- },
- };
-
- const { UNSAFE_getByType } = render();
- const component = UNSAFE_getByType(VectorSource);
- const { props } = component;
-
- expect(props.id).toStrictEqual(Object.keys(json.sources)[0]);
- expect(props.url).toStrictEqual(vectorSource.url);
- expect(props.tileUrlTemplates).toStrictEqual(vectorSource.tiles);
- expect(props.minZoomLevel).toStrictEqual(vectorSource.minzoom);
- expect(props.maxZoomLevel).toStrictEqual(vectorSource.maxzoom);
- expect(props.attribution).toStrictEqual(vectorSource.attribution);
- expect(props.tms).toBe(true);
- });
-
- test("renders raster source correctly", () => {
- const rasterSource = {
- type: "raster",
- url: "https://demotiles.maplibre.org/tiles/tiles.json",
- tiles: ["http://host1", "http://host2"],
- minzoom: 1,
- maxzoom: 22,
- attribution: "Copyright",
- scheme: "tms",
- tileSize: 256,
- };
-
- const json = {
- layers: [],
- sources: {
- rasterSource,
- },
- };
-
- const { UNSAFE_getByType } = render();
- const component = UNSAFE_getByType(RasterSource);
- const { props } = component;
-
- expect(props.id).toStrictEqual(Object.keys(json.sources)[0]);
- expect(props.url).toStrictEqual(rasterSource.url);
- expect(props.tileUrlTemplates).toStrictEqual(rasterSource.tiles);
- expect(props.minZoomLevel).toStrictEqual(rasterSource.minzoom);
- expect(props.maxZoomLevel).toStrictEqual(rasterSource.maxzoom);
- expect(props.attribution).toStrictEqual(rasterSource.attribution);
- expect(props.tms).toBe(true);
- expect(props.tileSize).toStrictEqual(rasterSource.tileSize);
- });
-
- test("renders image source correctly", () => {
- const imageSource = {
- type: "image",
- url: "https://docs.mapbox.com/mapbox-gl-js/assets/radar.gif",
- coordinates: [
- [-80.425, 46.437],
- [-71.516, 46.437],
- [-71.516, 37.936],
- [-80.425, 37.936],
- ],
- };
-
- const json = {
- layers: [],
- sources: {
- imageSource,
- },
- };
-
- const { UNSAFE_getByType } = render();
- const component = UNSAFE_getByType(ImageSource);
- const { props } = component;
-
- expect(props.id).toStrictEqual(Object.keys(json.sources)[0]);
- expect(props.url).toStrictEqual(imageSource.url);
- expect(props.coordinates).toStrictEqual(imageSource.coordinates);
- });
-
- test("renders shape source correctly", () => {
- const shapeSource = {
- type: "geojson",
- data: "https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson",
- cluster: true,
- clusterRadius: 80,
- clusterMaxZoom: 10,
- maxzoom: 22,
- minzoom: 1,
- buffer: 128,
- tolerance: 0.5,
- };
-
- const json = {
- layers: [],
- sources: {
- imageSource: shapeSource,
- },
- };
-
- const { UNSAFE_getByType } = render();
- const component = UNSAFE_getByType(ShapeSource);
- const { props } = component;
-
- expect(props.id).toStrictEqual(Object.keys(json.sources)[0]);
- expect(props.url).toStrictEqual(shapeSource.data);
- expect(props.shape).toBeUndefined();
- expect(props.clusterRadius).toStrictEqual(shapeSource.clusterRadius);
- expect(props.clusterMaxZoomLevel).toStrictEqual(shapeSource.clusterMaxZoom);
- expect(props.maxZoomLevel).toStrictEqual(shapeSource.maxzoom);
- expect(props.buffer).toStrictEqual(shapeSource.buffer);
- expect(props.tolerance).toStrictEqual(shapeSource.tolerance);
- });
-
- test("renders shape source with json data correctly", () => {
- const shapeSource = {
- type: "geojson",
- data: {
- type: "FeatureCollection",
- features: [],
- },
- };
-
- const json = {
- layers: [],
- sources: {
- imageSource: shapeSource,
- },
- };
-
- const { UNSAFE_getByType } = render();
- const component = UNSAFE_getByType(ShapeSource);
- const { props } = component;
-
- expect(props.id).toStrictEqual(Object.keys(json.sources)[0]);
- expect(props.shape).toStrictEqual(shapeSource.data);
- expect(props.url).toBeUndefined();
- });
-
- test("renders supported layer types correctly", () => {
- const json = {
- layers: [
- {
- id: "circle",
- type: "circle",
- },
- {
- id: "symbol",
- type: "symbol",
- },
- {
- id: "raster",
- type: "raster",
- },
- {
- id: "line",
- type: "line",
- },
- {
- id: "fill",
- type: "fill",
- },
- {
- id: "fill-extrusion",
- type: "fill-extrusion",
- },
- {
- id: "background",
- type: "background",
- },
- {
- id: "heatmap",
- type: "heatmap",
- },
- ],
- };
-
- const { UNSAFE_getByType } = render();
- const circleLayer = UNSAFE_getByType(CircleLayer);
- const symbolLayer = UNSAFE_getByType(SymbolLayer);
- const rasterLayer = UNSAFE_getByType(RasterLayer);
- const lineLayer = UNSAFE_getByType(LineLayer);
- const fillLayer = UNSAFE_getByType(FillLayer);
- const fillExtrusionLayer = UNSAFE_getByType(FillExtrusionLayer);
- const backgroundLayer = UNSAFE_getByType(BackgroundLayer);
- const heatmapLayer = UNSAFE_getByType(HeatmapLayer);
-
- expect(circleLayer.props.id).toStrictEqual("circle");
- expect(symbolLayer.props.id).toStrictEqual("symbol");
- expect(rasterLayer.props.id).toStrictEqual("raster");
- expect(lineLayer.props.id).toStrictEqual("line");
- expect(fillLayer.props.id).toStrictEqual("fill");
- expect(fillExtrusionLayer.props.id).toStrictEqual("fill-extrusion");
- expect(backgroundLayer.props.id).toStrictEqual("background");
- expect(heatmapLayer.props.id).toStrictEqual("heatmap");
- });
-
- test("renders layer props correctly", () => {
- const circleLayer = {
- id: "circle",
- type: "circle",
- source: "population",
- "source-layer": "state_county_population",
- filter: ["==", "isState", true],
- minzoom: 1,
- maxzoom: 22,
- paint: {
- "circle-opacity": 0.75,
- },
- layout: {
- visibility: "visible",
- },
- };
- const json = {
- layers: [circleLayer],
- };
-
- const { UNSAFE_getByType } = render();
- const layerComponent = UNSAFE_getByType(CircleLayer);
- const { props } = layerComponent;
- expect(props.sourceID).toStrictEqual(circleLayer.source);
- expect(props.sourceLayerID).toStrictEqual(circleLayer["source-layer"]);
- expect(props.filter).toStrictEqual(circleLayer.filter);
- expect(props.minZoomLevel).toStrictEqual(circleLayer.minzoom);
- expect(props.maxZoomLevel).toStrictEqual(circleLayer.maxzoom);
- expect(props.style.circleOpacity).toStrictEqual(
- circleLayer.paint["circle-opacity"],
- );
- expect(props.style.visibility).toStrictEqual(circleLayer.layout.visibility);
- });
-});
diff --git a/docs/components/Style.md b/docs/components/Style.md
deleted file mode 100644
index 0da87dd42..000000000
--- a/docs/components/Style.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-# ``
-Style is a component that automatically adds sources / layers to the map using MapLibre Style Spec.
Only [`sources`](https://maplibre.org/maplibre-gl-js-docs/style-spec/sources/) & [`layers`](https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/) are supported.
Other fields such as `sprites`, `glyphs` etc. will be ignored. Not all layer / source attributes from the style spec are supported, in general the supported attributes will be mentioned under https://github.com/maplibre/maplibre-react-native/tree/main/docs.
TODO: Maintainer forking this project does not understand the above comment regarding what is supported.
-
-## Props
-| Prop | Type | Default | Required | Description |
-| ---- | :--: | :-----: | :------: | :----------: |
-| json | `MapLibreJSON \| URL` | `none` | `false` | A JSON object conforming to the schema described in the MapLibre Style Specification, or a URL to such JSON. |
-
-
diff --git a/docs/docs.json b/docs/docs.json
index 0921d57bf..49dd675b4 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -3355,23 +3355,6 @@
"filePath": "src/components/ShapeSource.tsx",
"name": "ShapeSource"
},
- "Style": {
- "description": "Style is a component that automatically adds sources / layers to the map using MapLibre Style Spec.\nOnly [`sources`](https://maplibre.org/maplibre-gl-js-docs/style-spec/sources/) & [`layers`](https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/) are supported.\nOther fields such as `sprites`, `glyphs` etc. will be ignored. Not all layer / source attributes from the style spec are supported, in general the supported attributes will be mentioned under https://github.com/maplibre/maplibre-react-native/tree/main/docs.\n\nTODO: Maintainer forking this project does not understand the above comment regarding what is supported.",
- "displayName": "Style",
- "methods": [],
- "props": [
- {
- "name": "json",
- "required": false,
- "type": "MapLibreJSON \\| URL",
- "default": "none",
- "description": "A JSON object conforming to the schema described in the MapLibre Style Specification, or a URL to such JSON."
- }
- ],
- "type": "component",
- "filePath": "src/components/Style.tsx",
- "name": "Style"
- },
"SymbolLayer": {
"description": "SymbolLayer is a style layer that renders icon and text labels at points or along lines on the map.",
"displayName": "SymbolLayer",
diff --git a/packages/examples/src/Examples.tsx b/packages/examples/src/Examples.tsx
index fa6666ea1..1a02835a8 100644
--- a/packages/examples/src/Examples.tsx
+++ b/packages/examples/src/Examples.tsx
@@ -59,10 +59,7 @@ const Examples = new ExampleGroup(
new ExampleItem("Bug Report", MapLibreExamples.BugReport),
new ExampleGroup("Map", [
new ExampleItem("Show Map", MapLibreExamples.ShowMap),
- new ExampleItem(
- "Show Map with Local Style.JSON",
- MapLibreExamples.ShowMapLocalStyle,
- ),
+ new ExampleItem("Local Style from JSON", MapLibreExamples.LocalStyleJSON),
new ExampleItem("Show Click", MapLibreExamples.ShowClick),
new ExampleItem(
"Show Region did Change",
@@ -86,7 +83,6 @@ const Examples = new ExampleGroup(
"Source Layer Visiblity",
MapLibreExamples.SourceLayerVisibility,
),
- new ExampleItem("Style JSON", MapLibreExamples.StyleJson),
new ExampleItem("Set Tint Color", MapLibreExamples.SetTintColor),
]),
new ExampleGroup("Camera", [
diff --git a/packages/examples/src/examples/Map/LocalStyleJSON.tsx b/packages/examples/src/examples/Map/LocalStyleJSON.tsx
new file mode 100644
index 000000000..b83eba854
--- /dev/null
+++ b/packages/examples/src/examples/Map/LocalStyleJSON.tsx
@@ -0,0 +1,33 @@
+import { MapView } from "@maplibre/maplibre-react-native";
+import { useState } from "react";
+import { Text } from "react-native";
+
+import MapLibreDemoTilesBlue from "../../assets/styles/maplibre-demo-tiles-blue.json";
+import MapLibreDemoTilesWhite from "../../assets/styles/maplibre-demo-tiles-white.json";
+import Bubble from "../../components/Bubble";
+import { sheet } from "../../styles/sheet";
+
+const STYLE_BLUE = JSON.stringify(MapLibreDemoTilesBlue);
+const STYLE_WHITE = JSON.stringify(MapLibreDemoTilesWhite);
+
+export default function LocalStyleJSON() {
+ const [color, setColor] = useState<"blue" | "white">("blue");
+
+ return (
+ <>
+
+
+ setColor((prevState) => {
+ return ({ blue: "white", white: "blue" } as const)[prevState];
+ })
+ }
+ >
+ Switch Style JSON
+
+ >
+ );
+}
diff --git a/packages/examples/src/examples/Map/ShowMapLocalStyle.tsx b/packages/examples/src/examples/Map/ShowMapLocalStyle.tsx
deleted file mode 100644
index 69d302f3e..000000000
--- a/packages/examples/src/examples/Map/ShowMapLocalStyle.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import MapLibreGL from "@maplibre/maplibre-react-native";
-
-import MapLibreDemoTilesBlue from "../../assets/styles/maplibre-demo-tiles-blue.json";
-import { sheet } from "../../styles/sheet";
-
-const STYLE = JSON.stringify(MapLibreDemoTilesBlue);
-
-export default function ShowMap() {
- return ;
-}
diff --git a/packages/examples/src/examples/Map/StyleJson.js b/packages/examples/src/examples/Map/StyleJson.js
deleted file mode 100755
index 5dc256dbb..000000000
--- a/packages/examples/src/examples/Map/StyleJson.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import MapLibreGL from "@maplibre/maplibre-react-native";
-import React from "react";
-import { StyleSheet, Text } from "react-native";
-
-import MapLibreDemoTilesBlue from "../../assets/styles/maplibre-demo-tiles-blue.json";
-import MapLibreDemoTilesWhite from "../../assets/styles/maplibre-demo-tiles-white.json";
-import Bubble from "../../components/Bubble";
-
-const styles = StyleSheet.create({
- map: {
- flex: 1,
- },
-});
-
-const defaultCamera = {
- centerCoordinate: [-78.54382, 40.446947],
- zoomLevel: 3,
- minZoomLevel: 3,
-};
-
-class StyleJson extends React.Component {
- state = {
- showAltStyle: false,
- };
-
- onPress = () => {
- this.setState((prevState) => ({
- showAltStyle: !prevState.showAltStyle,
- }));
- };
-
- render() {
- return (
- <>
-
-
-
-
-
- {this.state.showAltStyle ? "Style 2" : "Style 1"}
-
- >
- );
- }
-}
-
-export default StyleJson;
diff --git a/packages/examples/src/examples/index.ts b/packages/examples/src/examples/index.ts
index 09d322e01..bf11827db 100644
--- a/packages/examples/src/examples/index.ts
+++ b/packages/examples/src/examples/index.ts
@@ -37,10 +37,9 @@ export { default as PointInMapView } from "./Map/PointInMapView";
export { default as ShowAndHideLayer } from "./Map/ShowAndHideLayer";
export { default as ShowClick } from "./Map/ShowClick";
export { default as ShowMap } from "./Map/ShowMap";
-export { default as ShowMapLocalStyle } from "./Map/ShowMapLocalStyle";
+export { default as LocalStyleJSON } from "./Map/LocalStyleJSON";
export { default as ShowRegionDidChange } from "./Map/ShowRegionDidChange";
export { default as SourceLayerVisibility } from "./Map/SourceLayerVisibility";
-export { default as StyleJson } from "./Map/StyleJson";
export { default as TwoMapViews } from "./Map/TwoMapViews";
export { default as SetTintColor } from "./Map/SetTintColor";
// SYMBOLCIRCLELAYER
diff --git a/src/MapLibreRN.ts b/src/MapLibreRN.ts
index 7cbd1a9cd..9886dcd38 100644
--- a/src/MapLibreRN.ts
+++ b/src/MapLibreRN.ts
@@ -38,7 +38,6 @@ export { default as SymbolLayer } from "./components/SymbolLayer";
export { default as RasterLayer } from "./components/RasterLayer";
export { default as BackgroundLayer } from "./components/BackgroundLayer";
export { default as MarkerView } from "./components/MarkerView";
-export { default as Style } from "./components/Style";
export {
default as locationManager,
diff --git a/src/components/Style.tsx b/src/components/Style.tsx
deleted file mode 100644
index b48f10f31..000000000
--- a/src/components/Style.tsx
+++ /dev/null
@@ -1,371 +0,0 @@
-import {
- useMemo,
- useState,
- useEffect,
- type ReactElement,
- type ComponentType,
-} from "react";
-
-import BackgroundLayer, { type BackgroundLayerProps } from "./BackgroundLayer";
-import CircleLayer, { type CircleLayerProps } from "./CircleLayer";
-import FillExtrusionLayer, {
- type FillExtrusionLayerProps,
-} from "./FillExtrusionLayer";
-import FillLayer, { type FillLayerProps } from "./FillLayer";
-import HeatmapLayer, { type HeatmapLayerProps } from "./HeatmapLayer";
-import ImageSource from "./ImageSource";
-import LineLayer, { type LineLayerProps } from "./LineLayer";
-import RasterLayer, { type RasterLayerProps } from "./RasterLayer";
-import RasterSource from "./RasterSource";
-import ShapeSource from "./ShapeSource";
-import SymbolLayer, { type SymbolLayerProps } from "./SymbolLayer";
-import VectorSource from "./VectorSource";
-import {
- type ExpressionField,
- type FilterExpression,
-} from "../utils/MapLibreRNStyles";
-
-function toCamelCase(s: string): string {
- return s.replace(/([-_][a-z])/gi, ($1) => {
- return $1.toUpperCase().replace("-", "").replace("_", "");
- });
-}
-
-// Patches the Mapbox Style Specification keys into the style props attributes:
-// icon-allow-overlap -> iconAllowOverlap
-function toCamelCaseKeys(
- oldObj: Record,
-): Record {
- if (!oldObj) {
- return {};
- }
- const newObj: Record = {};
- Object.keys(oldObj).forEach((key) => {
- const value = oldObj[key];
- if (key.includes("-")) {
- newObj[toCamelCase(key)] = value;
- } else {
- newObj[key] = value;
- }
- });
- return newObj;
-}
-
-type LayerProps =
- | CircleLayerProps
- | SymbolLayerProps
- | RasterLayerProps
- | LineLayerProps
- | FillLayerProps
- | FillExtrusionLayerProps
- | BackgroundLayerProps
- | HeatmapLayerProps;
-
-function getLayerComponentType(
- layer: MapLibreJSONLayer,
-): ComponentType | null {
- const { type } = layer;
-
- switch (type) {
- case "circle":
- return CircleLayer;
- case "symbol":
- return SymbolLayer;
- case "raster":
- return RasterLayer;
- case "line":
- return LineLayer;
- case "fill":
- return FillLayer;
- case "fill-extrusion":
- return FillExtrusionLayer;
- case "background":
- return BackgroundLayer;
- case "heatmap":
- return HeatmapLayer;
- }
-
- console.warn(`Mapbox layer type '${type}' is not supported/`);
-
- return null;
-}
-
-interface MapLibreJSONLayer {
- type: string;
- paint: { [k: string]: unknown };
- layout: { [k: string]: unknown };
- source?: string;
- "source-layer"?: string;
- minzoom?: number;
- maxzoom?: number;
- filter?: FilterExpression;
- id: string;
-}
-
-function asLayerComponent(
- layer: MapLibreJSONLayer,
-): ReactElement | null {
- const LayerComponent = getLayerComponentType(layer);
-
- if (!LayerComponent) {
- return null;
- }
-
- const style = {
- ...toCamelCaseKeys(layer.paint),
- ...toCamelCaseKeys(layer.layout),
- };
-
- const layerProps: Partial = {};
-
- if (layer.source) {
- layerProps.sourceID = layer.source;
- }
- if (layer["source-layer"]) {
- layerProps.sourceLayerID = layer["source-layer"];
- }
- if (layer.minzoom) {
- layerProps.minZoomLevel = layer.minzoom;
- }
- if (layer.maxzoom) {
- layerProps.maxZoomLevel = layer.maxzoom;
- }
- if (layer.filter) {
- layerProps.filter = layer.filter;
- }
- if (Object.keys(style).length) {
- layerProps.style = style;
- }
-
- return ;
-}
-
-interface MapLibreJSONSource {
- type: string;
- url?: string;
- tiles?: string[];
- minzoom?: number;
- maxzoom?: number;
- attribution?: string;
- scheme?: "xyz" | "tms";
- bounds?: number[];
- buffer?: number;
- tileSize?: number;
- coordinates?: [
- [number, number],
- [number, number],
- [number, number],
- [number, number],
- ];
- cluster?: boolean;
- clusterMaxZoom?: number;
- clusterMinPoints?: number;
- clusterRadius?: number;
- clusterProperties?: { [propertyName: string]: ExpressionField };
- data?: string | object;
- filter?: FilterExpression;
- generateId?: boolean;
- lineMetrics?: boolean;
- tolerance?: number;
-}
-
-type SourceProps = {
- url?: string;
- tileUrlTemplates?: string[];
- minZoomLevel?: number;
- maxZoomLevel?: number;
- attribution?: string;
- tms?: boolean;
-};
-
-function getTileSourceProps(source: MapLibreJSONSource): SourceProps {
- const sourceProps: Partial = {};
- if (source.url) {
- sourceProps.url = source.url;
- }
- if (source.tiles) {
- sourceProps.tileUrlTemplates = source.tiles;
- }
- if (source.minzoom !== undefined) {
- sourceProps.minZoomLevel = source.minzoom;
- }
- if (source.maxzoom !== undefined) {
- sourceProps.maxZoomLevel = source.maxzoom;
- }
- if (source.attribution) {
- sourceProps.attribution = source.attribution;
- }
- if (source.scheme && source.scheme === "tms") {
- sourceProps.tms = true;
- }
- return sourceProps;
-}
-
-function getVectorSource(id: string, source: MapLibreJSONSource): ReactElement {
- const sourceProps = { ...getTileSourceProps(source) };
- return ;
-}
-
-function getRasterSource(id: string, source: MapLibreJSONSource): ReactElement {
- const sourceProps: SourceProps & { tileSize?: number } = {
- ...getTileSourceProps(source),
- };
- if (source.tileSize) {
- sourceProps.tileSize = source.tileSize;
- }
- return ;
-}
-
-function getImageSource(id: string, source: MapLibreJSONSource): ReactElement {
- const sourceProps = {
- url: source.url,
- coordinates: source.coordinates,
- };
- return ;
-}
-
-type ShapeSourceShape = (typeof ShapeSource.prototype.props)["shape"];
-
-function getShapeSource(id: string, source: MapLibreJSONSource): ReactElement {
- const sourceProps: SourceProps & {
- shape?: ShapeSourceShape;
- cluster?: boolean;
- clusterRadius?: number;
- clusterMaxZoomLevel?: number;
- clusterProperties?: { [propertyName: string]: ExpressionField };
- buffer?: number;
- tolerance?: number;
- lineMetrics?: boolean;
- } = {};
- if (source.data && typeof source.data === "string") {
- sourceProps.url = source.data;
- } else if (source.data && typeof source.data === "object") {
- sourceProps.shape = source.data as ShapeSourceShape;
- }
- if (source.cluster !== undefined) {
- sourceProps.cluster = source.cluster;
- }
- if (source.clusterRadius !== undefined) {
- sourceProps.clusterRadius = source.clusterRadius;
- }
- if (source.maxzoom !== undefined) {
- sourceProps.maxZoomLevel = source.maxzoom;
- }
- if (source.clusterMaxZoom !== undefined) {
- sourceProps.clusterMaxZoomLevel = source.clusterMaxZoom;
- }
- if (source.clusterProperties !== undefined) {
- sourceProps.clusterProperties = source.clusterProperties;
- }
- if (source.buffer !== undefined) {
- sourceProps.buffer = source.buffer;
- }
- if (source.tolerance !== undefined) {
- sourceProps.tolerance = source.tolerance;
- }
- if (source.lineMetrics !== undefined) {
- sourceProps.lineMetrics = source.lineMetrics;
- }
- return ;
-}
-
-function asSourceComponent(
- id: string,
- source: MapLibreJSONSource,
-): ReactElement | null {
- switch (source.type) {
- case "vector":
- return getVectorSource(id, source);
- case "raster":
- return getRasterSource(id, source);
- case "image":
- return getImageSource(id, source);
- case "geojson":
- return getShapeSource(id, source);
- }
-
- console.warn(`MapLibre source type '${source.type}' is not supported`);
-
- return null;
-}
-
-interface MapLibreJSON {
- layers?: MapLibreJSONLayer[];
- sources?: { [key: string]: MapLibreJSONSource };
-}
-
-interface StyleProps {
- /**
- * A JSON object conforming to the schema described in the MapLibre Style Specification, or a URL to such JSON.
- */
- json?: MapLibreJSON | URL;
-}
-
-/**
- * Style is a component that automatically adds sources / layers to the map using MapLibre Style Spec.
- * Only [`sources`](https://maplibre.org/maplibre-gl-js-docs/style-spec/sources/) & [`layers`](https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/) are supported.
- * Other fields such as `sprites`, `glyphs` etc. will be ignored. Not all layer / source attributes from the style spec are supported, in general the supported attributes will be mentioned under https://github.com/maplibre/maplibre-react-native/tree/main/docs.
- *
- * TODO: Maintainer forking this project does not understand the above comment regarding what is supported.
- */
-const Style = (props: StyleProps): ReactElement => {
- const [fetchedJson, setFetchedJson] = useState({});
- const json: MapLibreJSON =
- typeof props.json === "object" ? props.json : fetchedJson;
-
- // Fetch style when props.json is a URL
- useEffect(() => {
- const abortController = new AbortController();
- const fetchStyleJson = async (url: string): Promise => {
- try {
- const response = await fetch(url, {
- signal: abortController.signal,
- });
- const responseJson = await response.json();
- setFetchedJson(responseJson);
- } catch (error: unknown) {
- const e = error as { name?: string };
- if (e.name === "AbortError") {
- return;
- }
- throw e;
- }
- };
- if (typeof props.json === "string") {
- fetchStyleJson(props.json);
- }
- return function cleanup(): void {
- abortController.abort();
- };
- }, [props.json]);
-
- // Extract layer components from json
- const layerComponents = useMemo(() => {
- if (!json.layers) {
- return [];
- }
- return json.layers
- .map(asLayerComponent)
- .filter((x: ReactElement | null) => !!x);
- }, [json.layers]);
-
- // Extract source components from json
- const sourceComponents = useMemo(() => {
- const { sources } = json;
- if (!sources || !Object.keys(sources)) {
- return [];
- }
- return Object.entries(sources)
- .map(([id, source]) => asSourceComponent(id, source))
- .filter((x) => !!x);
- }, [json]);
-
- return (
- <>
- {sourceComponents}
- {layerComponents}
- >
- );
-};
-
-export default Style;