mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2026-03-01 12:44:17 +00:00
maplibre
This commit is contained in:
parent
d10f924fa0
commit
ebe7197078
@ -86,6 +86,8 @@ function MapContainer({ layers, map }: { layers: LayerProps[]; map: any }) {
|
||||
expandLayerControl={map.expand_layer_control}
|
||||
tileServerUrl={map.tile_server_url}
|
||||
tileServerAttribution={map.tile_server_attribution}
|
||||
tilesType={map.tiles_type}
|
||||
maplibreStyle={map.maplibre_style}
|
||||
showFullscreenControl={map.show_fullscreen_control}
|
||||
>
|
||||
{layers &&
|
||||
|
||||
@ -0,0 +1,46 @@
|
||||
{
|
||||
"collection": "maps",
|
||||
"field": "maplibre",
|
||||
"type": "alias",
|
||||
"meta": {
|
||||
"collection": "maps",
|
||||
"conditions": [
|
||||
{
|
||||
"hidden": false,
|
||||
"name": "Show when maplibre tiles selected",
|
||||
"options": null,
|
||||
"rule": {
|
||||
"_and": [
|
||||
{
|
||||
"tiles_type": {
|
||||
"_eq": "maplibre"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"display": null,
|
||||
"display_options": null,
|
||||
"field": "maplibre",
|
||||
"group": "tile_server",
|
||||
"hidden": true,
|
||||
"interface": "group-detail",
|
||||
"note": "Configuration for MapLibre GL vector tiles",
|
||||
"options": {
|
||||
"start": "open"
|
||||
},
|
||||
"readonly": false,
|
||||
"required": false,
|
||||
"sort": 3,
|
||||
"special": [
|
||||
"alias",
|
||||
"no-data",
|
||||
"group"
|
||||
],
|
||||
"translations": null,
|
||||
"validation": null,
|
||||
"validation_message": null,
|
||||
"width": "full"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
{
|
||||
"collection": "maps",
|
||||
"field": "maplibre_style",
|
||||
"type": "string",
|
||||
"meta": {
|
||||
"collection": "maps",
|
||||
"conditions": null,
|
||||
"display": null,
|
||||
"display_options": null,
|
||||
"field": "maplibre_style",
|
||||
"group": "maplibre",
|
||||
"hidden": false,
|
||||
"interface": "input",
|
||||
"note": "MapLibre style URL (default: OpenFreeMap Liberty style)",
|
||||
"options": {
|
||||
"placeholder": "https://tiles.openfreemap.org/styles/liberty"
|
||||
},
|
||||
"readonly": false,
|
||||
"required": false,
|
||||
"sort": 1,
|
||||
"special": null,
|
||||
"translations": null,
|
||||
"validation": null,
|
||||
"validation_message": null,
|
||||
"width": "full"
|
||||
},
|
||||
"schema": {
|
||||
"name": "maplibre_style",
|
||||
"table": "maps",
|
||||
"data_type": "character varying",
|
||||
"default_value": null,
|
||||
"max_length": 255,
|
||||
"numeric_precision": null,
|
||||
"numeric_scale": null,
|
||||
"is_nullable": true,
|
||||
"is_unique": false,
|
||||
"is_indexed": false,
|
||||
"is_primary_key": false,
|
||||
"is_generated": false,
|
||||
"generation_expression": null,
|
||||
"has_auto_increment": false,
|
||||
"foreign_key_table": null,
|
||||
"foreign_key_column": null
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
{
|
||||
"collection": "maps",
|
||||
"field": "raster_tiles",
|
||||
"type": "alias",
|
||||
"meta": {
|
||||
"collection": "maps",
|
||||
"conditions": [
|
||||
{
|
||||
"hidden": false,
|
||||
"name": "Show when raster tiles selected",
|
||||
"options": null,
|
||||
"rule": {
|
||||
"_and": [
|
||||
{
|
||||
"tiles_type": {
|
||||
"_eq": "raster"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"display": null,
|
||||
"display_options": null,
|
||||
"field": "raster_tiles",
|
||||
"group": "tile_server",
|
||||
"hidden": true,
|
||||
"interface": "group-detail",
|
||||
"note": "Configuration for raster tile layers",
|
||||
"options": {
|
||||
"start": "open"
|
||||
},
|
||||
"readonly": false,
|
||||
"required": false,
|
||||
"sort": 2,
|
||||
"special": [
|
||||
"alias",
|
||||
"no-data",
|
||||
"group"
|
||||
],
|
||||
"translations": null,
|
||||
"validation": null,
|
||||
"validation_message": null,
|
||||
"width": "full"
|
||||
}
|
||||
}
|
||||
@ -8,11 +8,13 @@
|
||||
"display": null,
|
||||
"display_options": null,
|
||||
"field": "tile_server_attribution",
|
||||
"group": "tile_server",
|
||||
"group": "raster_tiles",
|
||||
"hidden": false,
|
||||
"interface": "input",
|
||||
"note": null,
|
||||
"options": null,
|
||||
"note": "Attribution text for raster tiles",
|
||||
"options": {
|
||||
"placeholder": "© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a>"
|
||||
},
|
||||
"readonly": false,
|
||||
"required": false,
|
||||
"sort": 2,
|
||||
|
||||
@ -8,11 +8,13 @@
|
||||
"display": null,
|
||||
"display_options": null,
|
||||
"field": "tile_server_url",
|
||||
"group": "tile_server",
|
||||
"group": "raster_tiles",
|
||||
"hidden": false,
|
||||
"interface": "input",
|
||||
"note": null,
|
||||
"options": null,
|
||||
"note": "Raster tile server URL template (e.g., https://tile.osmand.net/hd/{z}/{x}/{y}.png)",
|
||||
"options": {
|
||||
"placeholder": "https://tile.osmand.net/hd/{z}/{x}/{y}.png"
|
||||
},
|
||||
"readonly": false,
|
||||
"required": false,
|
||||
"sort": 1,
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
{
|
||||
"collection": "maps",
|
||||
"field": "tiles_type",
|
||||
"type": "string",
|
||||
"meta": {
|
||||
"collection": "maps",
|
||||
"conditions": null,
|
||||
"display": null,
|
||||
"display_options": null,
|
||||
"field": "tiles_type",
|
||||
"group": "tile_server",
|
||||
"hidden": false,
|
||||
"interface": "select-dropdown",
|
||||
"note": "Choose between raster tiles or vector tiles (MapLibre GL)",
|
||||
"options": {
|
||||
"choices": [
|
||||
{
|
||||
"text": "Raster Tiles",
|
||||
"value": "raster"
|
||||
},
|
||||
{
|
||||
"text": "Vector Tiles (MapLibre GL)",
|
||||
"value": "maplibre"
|
||||
}
|
||||
]
|
||||
},
|
||||
"readonly": false,
|
||||
"required": false,
|
||||
"sort": 1,
|
||||
"special": null,
|
||||
"translations": null,
|
||||
"validation": null,
|
||||
"validation_message": null,
|
||||
"width": "full"
|
||||
},
|
||||
"schema": {
|
||||
"name": "tiles_type",
|
||||
"table": "maps",
|
||||
"data_type": "character varying",
|
||||
"default_value": "raster",
|
||||
"max_length": 255,
|
||||
"numeric_precision": null,
|
||||
"numeric_scale": null,
|
||||
"is_nullable": true,
|
||||
"is_unique": false,
|
||||
"is_indexed": false,
|
||||
"is_primary_key": false,
|
||||
"is_generated": false,
|
||||
"generation_expression": null,
|
||||
"has_auto_increment": false,
|
||||
"foreign_key_table": null,
|
||||
"foreign_key_column": null
|
||||
}
|
||||
}
|
||||
@ -77,7 +77,7 @@
|
||||
"eslint-plugin-react-refresh": "^0.4.18",
|
||||
"eslint-plugin-security": "^3.0.1",
|
||||
"eslint-plugin-yml": "^1.14.0",
|
||||
"happy-dom": "^16.8.1",
|
||||
"happy-dom": "^20.0.0",
|
||||
"postcss": "^8.4.21",
|
||||
"prettier": "^3.3.3",
|
||||
"react": "^18.3.1",
|
||||
@ -102,6 +102,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@heroicons/react": "^2.0.17",
|
||||
"@maplibre/maplibre-gl-leaflet": "^0.1.3",
|
||||
"@tanstack/react-query": "^5.17.8",
|
||||
"@tiptap/core": "^3.6.5",
|
||||
"@tiptap/extension-bubble-menu": "^3.6.5",
|
||||
@ -119,6 +120,7 @@
|
||||
"date-fns": "^3.3.1",
|
||||
"leaflet": "^1.9.4",
|
||||
"leaflet.locatecontrol": "^0.79.0",
|
||||
"maplibre-gl": "^5.9.0",
|
||||
"radash": "^12.1.0",
|
||||
"react-colorful": "^5.6.1",
|
||||
"react-dropzone": "^14.3.8",
|
||||
|
||||
53
lib/src/Components/Map/Subcomponents/MapLibreLayer.tsx
Normal file
53
lib/src/Components/Map/Subcomponents/MapLibreLayer.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
/* eslint-disable import/no-unassigned-import */
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
import L from 'leaflet'
|
||||
import { useEffect } from 'react'
|
||||
import { useMap } from 'react-leaflet'
|
||||
|
||||
import '@maplibre/maplibre-gl-leaflet'
|
||||
import 'maplibre-gl/dist/maplibre-gl.css'
|
||||
|
||||
// Augment Leaflet namespace with MapLibre GL types
|
||||
declare module 'leaflet' {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function maplibreGL(options: { style: string; attribution?: string }): any
|
||||
}
|
||||
|
||||
/**
|
||||
* MapLibreLayer component for rendering vector tiles with MapLibre GL
|
||||
* Integrates MapLibre GL with Leaflet using the maplibre-gl-leaflet bridge
|
||||
*
|
||||
* @param styleUrl - URL to the MapLibre style JSON (default: OpenFreeMap Liberty style)
|
||||
* @param attribution - Attribution text for the map tiles
|
||||
*/
|
||||
export function MapLibreLayer({
|
||||
styleUrl = 'https://tiles.openfreemap.org/styles/liberty',
|
||||
attribution = '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
||||
}: {
|
||||
styleUrl?: string
|
||||
attribution?: string
|
||||
}) {
|
||||
const map = useMap()
|
||||
|
||||
useEffect(() => {
|
||||
// Create MapLibre GL layer
|
||||
const mapLibreLayer = L.maplibreGL({
|
||||
style: styleUrl,
|
||||
attribution,
|
||||
})
|
||||
|
||||
// Add layer to map
|
||||
mapLibreLayer.addTo(map)
|
||||
|
||||
// Cleanup function to remove layer when component unmounts
|
||||
return () => {
|
||||
map.removeLayer(mapLibreLayer)
|
||||
}
|
||||
}, [map, styleUrl, attribution])
|
||||
|
||||
return null
|
||||
}
|
||||
@ -59,6 +59,8 @@ function UtopiaMap({
|
||||
expandLayerControl,
|
||||
tileServerUrl,
|
||||
tileServerAttribution,
|
||||
tilesType = 'raster',
|
||||
maplibreStyle,
|
||||
}: {
|
||||
/** height of the map (default '500px') */
|
||||
height?: string
|
||||
@ -94,6 +96,10 @@ function UtopiaMap({
|
||||
tileServerUrl?: string
|
||||
/** configure a custom tile server attribution */
|
||||
tileServerAttribution?: string
|
||||
/** tiles type: 'raster' or 'maplibre' (default 'raster') */
|
||||
tilesType?: 'raster' | 'maplibre'
|
||||
/** MapLibre style URL for vector tiles (default: OpenFreeMap Liberty) */
|
||||
maplibreStyle?: string
|
||||
}) {
|
||||
return (
|
||||
<ContextWrapper>
|
||||
@ -116,6 +122,8 @@ function UtopiaMap({
|
||||
expandLayerControl={expandLayerControl}
|
||||
tileServerUrl={tileServerUrl}
|
||||
tileServerAttribution={tileServerAttribution}
|
||||
tilesType={tilesType}
|
||||
maplibreStyle={maplibreStyle}
|
||||
>
|
||||
{children}
|
||||
</UtopiaMapInner>
|
||||
|
||||
@ -42,6 +42,7 @@ import { LayerControl } from './Subcomponents/Controls/LayerControl'
|
||||
import { SearchControl } from './Subcomponents/Controls/SearchControl'
|
||||
import { TagsControl } from './Subcomponents/Controls/TagsControl'
|
||||
import { TextView } from './Subcomponents/ItemPopupComponents/TextView'
|
||||
import { MapLibreLayer } from './Subcomponents/MapLibreLayer'
|
||||
import { SelectPosition } from './Subcomponents/SelectPosition'
|
||||
|
||||
import type { Feature, Geometry as GeoJSONGeometry, GeoJsonObject } from 'geojson'
|
||||
@ -59,6 +60,8 @@ export function UtopiaMapInner({
|
||||
expandLayerControl,
|
||||
tileServerUrl,
|
||||
tileServerAttribution,
|
||||
tilesType,
|
||||
maplibreStyle,
|
||||
}: {
|
||||
children?: React.ReactNode
|
||||
geo?: GeoJsonObject
|
||||
@ -72,6 +75,8 @@ export function UtopiaMapInner({
|
||||
expandLayerControl?: boolean
|
||||
tileServerUrl?: string
|
||||
tileServerAttribution?: string
|
||||
tilesType?: 'raster' | 'maplibre'
|
||||
maplibreStyle?: string
|
||||
}) {
|
||||
const selectNewItemPosition = useSelectPosition()
|
||||
const setSelectNewItemPosition = useSetSelectPosition()
|
||||
@ -284,14 +289,18 @@ export function UtopiaMapInner({
|
||||
{showLayerControl && <LayerControl expandLayerControl={expandLayerControl ?? false} />}
|
||||
{showGratitudeControl && <GratitudeControl />}
|
||||
</Control>
|
||||
<TileLayer
|
||||
maxZoom={19}
|
||||
attribution={
|
||||
tileServerAttribution ??
|
||||
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
}
|
||||
url={tileServerUrl ?? 'https://tile.osmand.net/hd/{z}/{x}/{y}.png'}
|
||||
/>
|
||||
{tilesType === 'raster' ? (
|
||||
<TileLayer
|
||||
maxZoom={19}
|
||||
attribution={
|
||||
tileServerAttribution ??
|
||||
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
}
|
||||
url={tileServerUrl ?? 'https://tile.osmand.net/hd/{z}/{x}/{y}.png'}
|
||||
/>
|
||||
) : (
|
||||
<MapLibreLayer styleUrl={maplibreStyle} attribution={tileServerAttribution ?? ''} />
|
||||
)}
|
||||
<MarkerClusterGroup
|
||||
ref={(r) => setClusterRef(r as any)}
|
||||
showCoverageOnHover
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user