Add TileLayer Presets configuration
This commit is contained in:
parent
31406d48e3
commit
134f72948c
@ -5,7 +5,12 @@ import type { Preview } from '@storybook/react';
|
|||||||
window.process = {
|
window.process = {
|
||||||
...window.process,
|
...window.process,
|
||||||
env:{
|
env:{
|
||||||
...window.process?.env
|
...window.process?.env,
|
||||||
|
|
||||||
|
NEXT_PUBLIC_MAP_TILE_LAYER_NAME:'MapBox',
|
||||||
|
NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_accessToken: 'pk.eyJ1Ijoid2lsbHktcGFsbWFyZWpvIiwiYSI6ImNqNzk5NmRpNDFzb2cyeG9sc2luMHNjajUifQ.lkoVRFSI8hOLH4uJeOzwXw',
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -8,14 +8,36 @@ import {
|
|||||||
TileLayer,
|
TileLayer,
|
||||||
GeoJSON as GeoJSONLayer,
|
GeoJSON as GeoJSONLayer,
|
||||||
LayersControl,
|
LayersControl,
|
||||||
TileLayerProps,
|
|
||||||
} from 'react-leaflet';
|
} from 'react-leaflet';
|
||||||
|
|
||||||
import 'leaflet/dist/leaflet.css';
|
import 'leaflet/dist/leaflet.css';
|
||||||
import * as L from 'leaflet';
|
import * as L from 'leaflet';
|
||||||
|
import providers from '../lib/tileLayerPresets';
|
||||||
|
|
||||||
|
type VariantKeys<T> = T extends { variants: infer V }
|
||||||
|
? {
|
||||||
|
[K in keyof V]: K extends string
|
||||||
|
? `${K}` | `${K}.${VariantKeys<V[K]>}`
|
||||||
|
: never;
|
||||||
|
}[keyof V]
|
||||||
|
: never;
|
||||||
|
|
||||||
|
type ProviderVariantKeys<T> = {
|
||||||
|
[K in keyof T]: K extends string
|
||||||
|
? `${K}` | `${K}.${VariantKeys<T[K]>}`
|
||||||
|
: never;
|
||||||
|
}[keyof T];
|
||||||
|
|
||||||
|
type TileLayerPreset = ProviderVariantKeys<typeof providers> | 'custom';
|
||||||
|
|
||||||
|
interface TileLayerSettings extends L.TileLayerOptions {
|
||||||
|
url?: string;
|
||||||
|
variant?: string | any;
|
||||||
|
}
|
||||||
|
|
||||||
export type MapProps = {
|
export type MapProps = {
|
||||||
tile?: TileLayerProps;
|
tileLayerName: TileLayerPreset;
|
||||||
|
tileLayerOptions?: TileLayerSettings | undefined;
|
||||||
layers: {
|
layers: {
|
||||||
data: GeospatialData;
|
data: GeospatialData;
|
||||||
name: string;
|
name: string;
|
||||||
@ -38,8 +60,19 @@ export type MapProps = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const tileLayerDefaultName = process?.env
|
||||||
|
.NEXT_PUBLIC_MAP_TILE_LAYER_NAME as TileLayerPreset;
|
||||||
|
|
||||||
|
const tileLayerDefaultOptions = Object.keys(process?.env)
|
||||||
|
.filter((key) => key.startsWith('NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_'))
|
||||||
|
.reduce((obj, key) => {
|
||||||
|
obj[key.split('NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_')[1]] = process.env[key];
|
||||||
|
return obj;
|
||||||
|
}, {}) as TileLayerSettings;
|
||||||
|
|
||||||
export function Map({
|
export function Map({
|
||||||
tile = undefined,
|
tileLayerName = tileLayerDefaultName || 'OpenStreetMap',
|
||||||
|
tileLayerOptions,
|
||||||
layers = [
|
layers = [
|
||||||
{
|
{
|
||||||
data: null,
|
data: null,
|
||||||
@ -58,36 +91,94 @@ export function Map({
|
|||||||
const [layersData, setLayersData] = useState<any>([]);
|
const [layersData, setLayersData] = useState<any>([]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
tileEnvVars
|
tileLayerDefaultOptions
|
||||||
extract all environment variables thats starts with NEXT_PUBLIC_MAP_TILE_PROVIDER_.
|
extract all environment variables thats starts with NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_.
|
||||||
the variables names are the same as the TileLayer object properties:
|
the variables names are the same as the TileLayer object properties:
|
||||||
- url:
|
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_url:
|
||||||
- attribution
|
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_attribution
|
||||||
- accessToken
|
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_accessToken
|
||||||
- id
|
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_id
|
||||||
- ext
|
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_ext
|
||||||
- bounds
|
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_bounds
|
||||||
- maxZoom
|
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_maxZoom
|
||||||
- minZoom
|
- NEXT_PUBLIC_MAP_TILE_LAYER_OPTION_minZoom
|
||||||
see TileLayerOptions inteface
|
see TileLayerOptions inteface
|
||||||
*/
|
*/
|
||||||
const tileEnvVars = Object.keys(process?.env)
|
|
||||||
.filter((key) => key.startsWith('NEXT_PUBLIC_MAP_TILE_PROVIDER_'))
|
|
||||||
.reduce((obj, key) => {
|
|
||||||
obj[key.split('NEXT_PUBLIC_MAP_TILE_PROVIDER_')[1]] = process.env[key];
|
|
||||||
return obj;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
//tileData prioritizes properties passed through component over those passed through .env variables
|
//tileLayerData prioritizes properties passed through component over those passed through .env variables
|
||||||
let tileData = Object.assign(tileEnvVars, tile);
|
tileLayerOptions = Object.assign(tileLayerDefaultOptions, tileLayerOptions);
|
||||||
|
|
||||||
tileData = tileData.url
|
let provider = {
|
||||||
? tileData
|
url: tileLayerOptions.url,
|
||||||
: {
|
options: tileLayerOptions,
|
||||||
url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
};
|
||||||
attribution:
|
|
||||||
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
if (tileLayerName != 'custom') {
|
||||||
|
var parts = tileLayerName.split('.');
|
||||||
|
var providerName = parts[0];
|
||||||
|
var variantName: string = parts[1];
|
||||||
|
|
||||||
|
//make sure to declare a variant if url depends on a variant: assume first
|
||||||
|
if (providers[providerName].url?.includes('{variant}') && !variantName)
|
||||||
|
variantName = Object.keys(providers[providerName].variants)[0];
|
||||||
|
|
||||||
|
console.log(variantName);
|
||||||
|
|
||||||
|
if (!providers[providerName]) {
|
||||||
|
throw 'No such provider (' + providerName + ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
provider = {
|
||||||
|
url: providers[providerName].url,
|
||||||
|
options: providers[providerName].options,
|
||||||
|
};
|
||||||
|
|
||||||
|
// overwrite values in provider from variant.
|
||||||
|
if (variantName && 'variants' in providers[providerName]) {
|
||||||
|
if (!(variantName in providers[providerName].variants)) {
|
||||||
|
throw 'No such variant of ' + providerName + ' (' + variantName + ')';
|
||||||
|
}
|
||||||
|
var variant = providers[providerName].variants[variantName];
|
||||||
|
var variantOptions;
|
||||||
|
if (typeof variant === 'string') {
|
||||||
|
variantOptions = {
|
||||||
|
variant: variant,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
variantOptions = variant.options;
|
||||||
|
}
|
||||||
|
provider = {
|
||||||
|
url: variant.url || provider.url,
|
||||||
|
options: L.Util.extend({}, provider.options, variantOptions),
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var attributionReplacer = function (attr) {
|
||||||
|
if (attr.indexOf('{attribution.') === -1) {
|
||||||
|
return attr;
|
||||||
|
}
|
||||||
|
return attr.replace(
|
||||||
|
/\{attribution.(\w*)\}/g,
|
||||||
|
function (match, attributionName) {
|
||||||
|
return attributionReplacer(
|
||||||
|
providers[attributionName].options.attribution
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
provider.options.attribution = attributionReplacer(
|
||||||
|
provider.options.attribution
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tileLayerData = L.Util.extend(
|
||||||
|
{
|
||||||
|
url: provider.url,
|
||||||
|
},
|
||||||
|
provider.options,
|
||||||
|
tileLayerOptions
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadDataPromises = layers.map(async (layer) => {
|
const loadDataPromises = layers.map(async (layer) => {
|
||||||
@ -179,7 +270,7 @@ export function Map({
|
|||||||
map.target.fitBounds(layerToZoomBounds);
|
map.target.fitBounds(layerToZoomBounds);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{tileData.url && <TileLayer {...tileData} />}
|
{tileLayerData.url && <TileLayer {...tileLayerData} />}
|
||||||
|
|
||||||
<LayersControl position="bottomright">
|
<LayersControl position="bottomright">
|
||||||
{layers.map((layer) => {
|
{layers.map((layer) => {
|
||||||
|
|||||||
1211
packages/components/src/lib/tileLayerPresets.tsx
Normal file
1211
packages/components/src/lib/tileLayerPresets.tsx
Normal file
File diff suppressed because it is too large
Load Diff
@ -43,11 +43,9 @@ type Story = StoryObj<MapProps>;
|
|||||||
export const GeoJSONPolygons: Story = {
|
export const GeoJSONPolygons: Story = {
|
||||||
name: 'GeoJSON polygons map',
|
name: 'GeoJSON polygons map',
|
||||||
args: {
|
args: {
|
||||||
tile : {
|
tileLayerName:'OpenStreetMap',
|
||||||
url : 'https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}',
|
tileLayerOptions:{
|
||||||
attribution:'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://www.mapbox.com/about/maps/">Mapbox</a>',
|
|
||||||
accessToken : 'pk.eyJ1Ijoid2lsbHktcGFsbWFyZWpvIiwiYSI6ImNqNzk5NmRpNDFzb2cyeG9sc2luMHNjajUifQ.lkoVRFSI8hOLH4uJeOzwXw',
|
accessToken : 'pk.eyJ1Ijoid2lsbHktcGFsbWFyZWpvIiwiYSI6ImNqNzk5NmRpNDFzb2cyeG9sc2luMHNjajUifQ.lkoVRFSI8hOLH4uJeOzwXw',
|
||||||
id: 'mapbox/streets-v10'
|
|
||||||
},
|
},
|
||||||
layers: [
|
layers: [
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user