feat(sources): add multiple sources
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
# Несколько source в стиле
|
||||||
|
|
||||||
|
`?source=central-fed-district,volga-fed-district` — сервер вешает отдельный vector source на каждый extract и клонирует слои (`water__volga-fed-district`). Один MapLibre style, несколько округов.
|
||||||
|
|
||||||
|
Кабинет: чекбоксы округов в редакторе. Инструкции обновлены.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# web-demo: чекбоксы округов
|
||||||
|
|
||||||
|
Селект источника заменён на чекбоксы. Стиль грузится с `?source=id1,id2`. Последний округ снять нельзя. Fit bounds объединяет выбранные extract.
|
||||||
@@ -6,6 +6,7 @@ using TileServer.Api.Http;
|
|||||||
using TileServer.Application.Accounts;
|
using TileServer.Application.Accounts;
|
||||||
using TileServer.Application.Configuration;
|
using TileServer.Application.Configuration;
|
||||||
using TileServer.Application.Extracts;
|
using TileServer.Application.Extracts;
|
||||||
|
using TileServer.Application.Styles;
|
||||||
using TileServer.Application.Tiles;
|
using TileServer.Application.Tiles;
|
||||||
using TileServer.Domain.Exceptions;
|
using TileServer.Domain.Exceptions;
|
||||||
using TileServer.Domain.Tiles;
|
using TileServer.Domain.Tiles;
|
||||||
@@ -72,17 +73,19 @@ public sealed class PersonalDeliveryController(
|
|||||||
{
|
{
|
||||||
var access = await ResolveAsync(slug, ct).ConfigureAwait(false);
|
var access = await ResolveAsync(slug, ct).ConfigureAwait(false);
|
||||||
var token = AccessToken.Read(Request) ?? string.Empty;
|
var token = AccessToken.Read(Request) ?? string.Empty;
|
||||||
var extract = string.IsNullOrWhiteSpace(source)
|
var selected = ExtractSourceQuery.Resolve(source, extracts);
|
||||||
? extracts.GetAll().FirstOrDefault(e => e.Enabled)
|
if (selected.Count == 0)
|
||||||
: extracts.Find(source);
|
|
||||||
if (extract is null)
|
|
||||||
{
|
{
|
||||||
throw new ResourceNotFoundException("Extract", source ?? "(none configured)");
|
throw new ResourceNotFoundException("Extract", source ?? "(none configured)");
|
||||||
}
|
}
|
||||||
|
|
||||||
var tilesUrl =
|
var root = PublicUrl.GetBase(Request, options);
|
||||||
$"{PublicUrl.GetBase(Request, options)}/u/{access.User.Slug}/tiles/{extract.Id}/{{z}}/{{x}}/{{y}}.pbf?v=3&token={Uri.EscapeDataString(token)}";
|
var bound = selected
|
||||||
var style = await styles.GetForDeliveryAsync(access.User.Slug, name, extract.Id, tilesUrl, ct)
|
.Select(extract => new BoundExtract(
|
||||||
|
extract.Id,
|
||||||
|
$"{root}/u/{access.User.Slug}/tiles/{extract.Id}/{{z}}/{{x}}/{{y}}.pbf?v=3&token={Uri.EscapeDataString(token)}"))
|
||||||
|
.ToArray();
|
||||||
|
var style = await styles.GetForDeliveryAsync(access.User.Slug, name, bound, ct)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
var json = style.ToJsonString();
|
var json = style.ToJsonString();
|
||||||
usage.RecordStyle(access.User.Id, access.Token.Id, Encoding.UTF8.GetByteCount(json));
|
usage.RecordStyle(access.User.Id, access.Token.Id, Encoding.UTF8.GetByteCount(json));
|
||||||
|
|||||||
@@ -17,5 +17,9 @@ public interface IUserStyleService
|
|||||||
|
|
||||||
Task<IReadOnlyList<StyleListItem>> ListForDeliveryAsync(string slug, string baseUrl, string token, CancellationToken ct);
|
Task<IReadOnlyList<StyleListItem>> ListForDeliveryAsync(string slug, string baseUrl, string token, CancellationToken ct);
|
||||||
|
|
||||||
Task<JsonObject> GetForDeliveryAsync(string slug, string name, string extractId, string tilesUrl, CancellationToken ct);
|
Task<JsonObject> GetForDeliveryAsync(
|
||||||
|
string slug,
|
||||||
|
string name,
|
||||||
|
IReadOnlyList<BoundExtract> extracts,
|
||||||
|
CancellationToken ct);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,8 +130,7 @@ public sealed class UserStyleService(
|
|||||||
public async Task<JsonObject> GetForDeliveryAsync(
|
public async Task<JsonObject> GetForDeliveryAsync(
|
||||||
string slug,
|
string slug,
|
||||||
string name,
|
string name,
|
||||||
string extractId,
|
IReadOnlyList<BoundExtract> extracts,
|
||||||
string tilesUrl,
|
|
||||||
CancellationToken ct)
|
CancellationToken ct)
|
||||||
{
|
{
|
||||||
var styleName = ResourceName.Require(name, nameof(name));
|
var styleName = ResourceName.Require(name, nameof(name));
|
||||||
@@ -139,7 +138,7 @@ public sealed class UserStyleService(
|
|||||||
?? throw new ResourceNotFoundException("User", slug);
|
?? throw new ResourceNotFoundException("User", slug);
|
||||||
var own = await styles.FindAsync(user.Id, styleName, ct).ConfigureAwait(false);
|
var own = await styles.FindAsync(user.Id, styleName, ct).ConfigureAwait(false);
|
||||||
var raw = own is null ? catalog.GetRequired(styleName) : Parse(own.Json, styleName);
|
var raw = own is null ? catalog.GetRequired(styleName) : Parse(own.Json, styleName);
|
||||||
return styleService.Bind(raw, extractId, tilesUrl);
|
return styleService.Bind(raw, extracts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JsonObject Parse(string json, string name)
|
private static JsonObject Parse(string json, string name)
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
using TileServer.Domain;
|
||||||
|
using TileServer.Domain.Exceptions;
|
||||||
|
using TileServer.Domain.Extracts;
|
||||||
|
|
||||||
|
namespace TileServer.Application.Extracts;
|
||||||
|
|
||||||
|
public static class ExtractSourceQuery
|
||||||
|
{
|
||||||
|
public const int MaxCount = 16;
|
||||||
|
|
||||||
|
public static IReadOnlyList<Extract> Resolve(string? source, IExtractCatalog catalog)
|
||||||
|
{
|
||||||
|
var ids = ParseIds(source, catalog);
|
||||||
|
var result = new List<Extract>(ids.Count);
|
||||||
|
foreach (var id in ids)
|
||||||
|
{
|
||||||
|
result.Add(catalog.Find(id) ?? throw new ResourceNotFoundException("Extract", id));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IReadOnlyList<string> ParseIds(string? source, IExtractCatalog catalog)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(source))
|
||||||
|
{
|
||||||
|
var first = catalog.GetAll().FirstOrDefault(item => item.Enabled);
|
||||||
|
return first is null ? [] : [first.Id];
|
||||||
|
}
|
||||||
|
|
||||||
|
var seen = new HashSet<string>(StringComparer.Ordinal);
|
||||||
|
var ids = new List<string>();
|
||||||
|
foreach (var part in source.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
|
||||||
|
{
|
||||||
|
var id = ResourceName.Require(part, nameof(source));
|
||||||
|
if (!seen.Add(id))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ids.Add(id);
|
||||||
|
if (ids.Count >= MaxCount)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ids.Count == 0)
|
||||||
|
{
|
||||||
|
throw new DomainValidationException("At least one source is required.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ namespace TileServer.Application.Styles;
|
|||||||
|
|
||||||
public sealed record StyleListItem(string Name, string Url);
|
public sealed record StyleListItem(string Name, string Url);
|
||||||
|
|
||||||
|
public sealed record BoundExtract(string ExtractId, string TilesUrl);
|
||||||
|
|
||||||
public interface IStyleService
|
public interface IStyleService
|
||||||
{
|
{
|
||||||
IReadOnlyList<StyleListItem> List(string baseUrl);
|
IReadOnlyList<StyleListItem> List(string baseUrl);
|
||||||
@@ -12,5 +14,7 @@ public interface IStyleService
|
|||||||
|
|
||||||
JsonObject Bind(JsonObject style, string extractId, string tilesUrl);
|
JsonObject Bind(JsonObject style, string extractId, string tilesUrl);
|
||||||
|
|
||||||
|
JsonObject Bind(JsonObject style, IReadOnlyList<BoundExtract> extracts);
|
||||||
|
|
||||||
Task SaveAsync(string name, JsonObject style, CancellationToken ct);
|
Task SaveAsync(string name, JsonObject style, CancellationToken ct);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,11 +31,26 @@ public sealed class StyleService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public JsonObject Bind(JsonObject style, string extractId, string tilesUrl)
|
public JsonObject Bind(JsonObject style, string extractId, string tilesUrl)
|
||||||
|
=> Bind(style, [new BoundExtract(extractId, tilesUrl)]);
|
||||||
|
|
||||||
|
public JsonObject Bind(JsonObject style, IReadOnlyList<BoundExtract> extracts)
|
||||||
{
|
{
|
||||||
var extract = ResolveExtract(extractId);
|
if (extracts.Count == 0)
|
||||||
|
{
|
||||||
|
throw new DomainValidationException("At least one extract is required.");
|
||||||
|
}
|
||||||
|
|
||||||
var clone = JsonNode.Parse(style.ToJsonString())?.AsObject()
|
var clone = JsonNode.Parse(style.ToJsonString())?.AsObject()
|
||||||
?? throw new DomainValidationException("Style must be a JSON object.");
|
?? throw new DomainValidationException("Style must be a JSON object.");
|
||||||
BindRuntimeUrls(clone, extract, tilesUrl);
|
var first = extracts[0];
|
||||||
|
BindRuntimeUrls(clone, ResolveExtract(first.ExtractId), first.TilesUrl);
|
||||||
|
var primaryKeys = VectorSourceKeys(clone);
|
||||||
|
for (var i = 1; i < extracts.Count; i++)
|
||||||
|
{
|
||||||
|
var extra = extracts[i];
|
||||||
|
AppendExtract(clone, ResolveExtract(extra.ExtractId), extra.TilesUrl, primaryKeys);
|
||||||
|
}
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +102,71 @@ public sealed class StyleService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AppendExtract(
|
||||||
|
JsonObject style,
|
||||||
|
Extract extract,
|
||||||
|
string tilesUrl,
|
||||||
|
IReadOnlyList<string> primarySourceKeys)
|
||||||
|
{
|
||||||
|
if (style["sources"] is not JsonObject sources || style["layers"] is not JsonArray layers)
|
||||||
|
{
|
||||||
|
throw new DomainValidationException("Style must have sources and layers.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var metadata = tileStore.GetMetadata(extract.Id);
|
||||||
|
var minZoom = metadata?.MinZoom ?? extract.MinZoom;
|
||||||
|
var maxZoom = metadata?.MaxZoom ?? extract.MaxZoom;
|
||||||
|
var suffix = "__" + extract.Id;
|
||||||
|
var primary = primarySourceKeys.ToHashSet(StringComparer.Ordinal);
|
||||||
|
|
||||||
|
foreach (var key in primarySourceKeys)
|
||||||
|
{
|
||||||
|
sources[key + suffix] = CreateVectorSource(tilesUrl, minZoom, maxZoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
var extras = new List<JsonNode>();
|
||||||
|
foreach (var node in layers)
|
||||||
|
{
|
||||||
|
if (node is not JsonObject layer)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sourceName = layer["source"]?.GetValue<string>();
|
||||||
|
if (sourceName is null || !primary.Contains(sourceName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var copy = JsonNode.Parse(layer.ToJsonString())?.AsObject()
|
||||||
|
?? throw new DomainValidationException("Layer clone failed.");
|
||||||
|
var id = layer["id"]?.GetValue<string>() ?? "layer";
|
||||||
|
copy["id"] = id + suffix;
|
||||||
|
copy["source"] = sourceName + suffix;
|
||||||
|
extras.Add(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var extra in extras)
|
||||||
|
{
|
||||||
|
layers.Add(extra);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IReadOnlyList<string> VectorSourceKeys(JsonObject style)
|
||||||
|
{
|
||||||
|
if (style["sources"] is not JsonObject sources)
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return sources
|
||||||
|
.Where(property =>
|
||||||
|
property.Value is JsonObject source &&
|
||||||
|
string.Equals(source["type"]?.GetValue<string>(), "vector", StringComparison.OrdinalIgnoreCase))
|
||||||
|
.Select(property => property.Key)
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
private static JsonObject CreateVectorSource(string tilesUrl, int minZoom, int maxZoom)
|
private static JsonObject CreateVectorSource(string tilesUrl, int minZoom, int maxZoom)
|
||||||
{
|
{
|
||||||
var source = new JsonObject
|
var source = new JsonObject
|
||||||
|
|||||||
@@ -131,6 +131,74 @@ public sealed class StyleServiceTests
|
|||||||
Assert.Contains("token=ts_abc", tile, StringComparison.Ordinal);
|
Assert.Contains("token=ts_abc", tile, StringComparison.Ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Bind_MultipleExtracts_AddsSourcesAndClonesLayers()
|
||||||
|
{
|
||||||
|
var central = SampleExtract("central-fed-district", 37.6, 55.7);
|
||||||
|
var volga = SampleExtract("volga-fed-district", 45, 57);
|
||||||
|
var template = new JsonObject
|
||||||
|
{
|
||||||
|
["version"] = 8,
|
||||||
|
["sources"] = new JsonObject
|
||||||
|
{
|
||||||
|
["openmaptiles"] = new JsonObject { ["type"] = "vector" }
|
||||||
|
},
|
||||||
|
["layers"] = new JsonArray
|
||||||
|
{
|
||||||
|
new JsonObject
|
||||||
|
{
|
||||||
|
["id"] = "background",
|
||||||
|
["type"] = "background",
|
||||||
|
["paint"] = new JsonObject { ["background-color"] = "#000" }
|
||||||
|
},
|
||||||
|
new JsonObject
|
||||||
|
{
|
||||||
|
["id"] = "water",
|
||||||
|
["type"] = "fill",
|
||||||
|
["source"] = "openmaptiles",
|
||||||
|
["source-layer"] = "water"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var service = new StyleService(
|
||||||
|
new MemoryStyleCatalog(template),
|
||||||
|
new MemoryExtractCatalog(central, volga),
|
||||||
|
new MemoryTileStore(SampleMetadata(central)),
|
||||||
|
Options.Create(new TileServerOptions()));
|
||||||
|
|
||||||
|
var style = service.Bind(template, [
|
||||||
|
new BoundExtract(central.Id, "https://tile-server.ru/u/alice/tiles/central-fed-district/{z}/{x}/{y}.pbf?token=ts"),
|
||||||
|
new BoundExtract(volga.Id, "https://tile-server.ru/u/alice/tiles/volga-fed-district/{z}/{x}/{y}.pbf?token=ts")
|
||||||
|
]);
|
||||||
|
|
||||||
|
var sources = style["sources"]!.AsObject();
|
||||||
|
Assert.True(sources.ContainsKey("openmaptiles"));
|
||||||
|
Assert.True(sources.ContainsKey("openmaptiles__volga-fed-district"));
|
||||||
|
Assert.Contains("volga-fed-district", sources["openmaptiles__volga-fed-district"]!["tiles"]![0]!.GetValue<string>(), StringComparison.Ordinal);
|
||||||
|
|
||||||
|
var layers = style["layers"]!.AsArray();
|
||||||
|
Assert.Equal(3, layers.Count);
|
||||||
|
Assert.Equal("water__volga-fed-district", layers[2]!["id"]!.GetValue<string>());
|
||||||
|
Assert.Equal("openmaptiles__volga-fed-district", layers[2]!["source"]!.GetValue<string>());
|
||||||
|
Assert.Null(layers[0]!["source"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Extract SampleExtract(string id, double lon, double lat)
|
||||||
|
=> new()
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
Name = id,
|
||||||
|
Url = new Uri($"https://download.geofabrik.de/russia/{id}-latest.osm.pbf"),
|
||||||
|
CenterLon = lon,
|
||||||
|
CenterLat = lat,
|
||||||
|
MinZoom = 0,
|
||||||
|
MaxZoom = 14
|
||||||
|
};
|
||||||
|
|
||||||
|
private static TilesetMetadata SampleMetadata(Extract extract)
|
||||||
|
=> new(extract.Id, extract.Name, "pbf", 0, 0, 1, 1, 0, 0, 5, 0, 14, []);
|
||||||
|
|
||||||
private sealed class MemoryStyleCatalog(JsonObject style) : IStyleCatalog
|
private sealed class MemoryStyleCatalog(JsonObject style) : IStyleCatalog
|
||||||
{
|
{
|
||||||
public IReadOnlyList<MapStyleInfo> List() => [new("osm-bright", DateTimeOffset.UnixEpoch)];
|
public IReadOnlyList<MapStyleInfo> List() => [new("osm-bright", DateTimeOffset.UnixEpoch)];
|
||||||
@@ -143,11 +211,11 @@ public sealed class StyleServiceTests
|
|||||||
public Task SeedDefaultsAsync(CancellationToken ct) => Task.CompletedTask;
|
public Task SeedDefaultsAsync(CancellationToken ct) => Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class MemoryExtractCatalog(Extract extract) : IExtractCatalog
|
private sealed class MemoryExtractCatalog(params Extract[] extracts) : IExtractCatalog
|
||||||
{
|
{
|
||||||
public IReadOnlyList<Extract> GetAll() => [extract];
|
public IReadOnlyList<Extract> GetAll() => extracts;
|
||||||
|
|
||||||
public Extract? Find(string id) => id == extract.Id ? extract : null;
|
public Extract? Find(string id) => extracts.FirstOrDefault(item => item.Id == id);
|
||||||
|
|
||||||
public Extract GetRequired(string id)
|
public Extract GetRequired(string id)
|
||||||
=> Find(id) ?? throw new InvalidOperationException(id);
|
=> Find(id) ?? throw new InvalidOperationException(id);
|
||||||
|
|||||||
+62
-46
@@ -62,7 +62,7 @@ export function App() {
|
|||||||
const [sources, setSources] = useState<SourceItem[]>([]);
|
const [sources, setSources] = useState<SourceItem[]>([]);
|
||||||
const [styles, setStyles] = useState<StyleItem[]>([]);
|
const [styles, setStyles] = useState<StyleItem[]>([]);
|
||||||
const [sync, setSync] = useState<SyncStatus | null>(null);
|
const [sync, setSync] = useState<SyncStatus | null>(null);
|
||||||
const [sourceId, setSourceId] = useState("");
|
const [selectedSourceIds, setSelectedSourceIds] = useState<string[]>([]);
|
||||||
const [styleName, setStyleName] = useState("osm-bright");
|
const [styleName, setStyleName] = useState("osm-bright");
|
||||||
const [coords, setCoords] = useState("—");
|
const [coords, setCoords] = useState("—");
|
||||||
const [gotoError, setGotoError] = useState("");
|
const [gotoError, setGotoError] = useState("");
|
||||||
@@ -79,7 +79,8 @@ export function App() {
|
|||||||
accessRef.current = access;
|
accessRef.current = access;
|
||||||
const personal = isPersonal(access);
|
const personal = isPersonal(access);
|
||||||
|
|
||||||
const source = sources.find((item) => item.id === sourceId) ?? sources[0];
|
const selectedSources = sources.filter((item) => selectedSourceIds.includes(item.id));
|
||||||
|
const source = selectedSources[0] ?? sources[0];
|
||||||
|
|
||||||
const updateHud = useCallback((map: MapLibreMap) => {
|
const updateHud = useCallback((map: MapLibreMap) => {
|
||||||
const center = map.getCenter();
|
const center = map.getCenter();
|
||||||
@@ -132,18 +133,18 @@ export function App() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!source || !styleName || !mapEl.current) {
|
if (selectedSourceIds.length === 0 || !styleName || !mapEl.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const styleKey = `${personal ? access.slug : "public"}|${source.id}|${styleName}|${source.status}|${source.builtAt ?? ""}`;
|
const styleKey = `${access.slug}|${selectedSourceIds.join(",")}|${styleName}|${selectedSources.map((item) => `${item.status}:${item.builtAt ?? ""}`).join(";")}`;
|
||||||
if (mapRef.current && styleKeyRef.current === styleKey) {
|
if (mapRef.current && styleKeyRef.current === styleKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const style = await fetchJson<StyleSpecification>(styleUrl(access, styleName, source.id));
|
const style = await fetchJson<StyleSpecification>(styleUrl(access, styleName, selectedSourceIds));
|
||||||
const hashed = cameraFromHash();
|
const hashed = cameraFromHash();
|
||||||
const center = hashed ? [hashed.lon, hashed.lat] : (source.center ?? [37.6173, 55.7558]);
|
const center = hashed ? [hashed.lon, hashed.lat] : (source?.center ?? [37.6173, 55.7558]);
|
||||||
const zoom = hashed ? hashed.zoom : 6;
|
const zoom = hashed ? hashed.zoom : 6;
|
||||||
|
|
||||||
if (!mapRef.current) {
|
if (!mapRef.current) {
|
||||||
@@ -177,13 +178,13 @@ export function App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
styleKeyRef.current = styleKey;
|
styleKeyRef.current = styleKey;
|
||||||
const ready = source.status === "Ready";
|
const pending = selectedSources.find((item) => item.status !== "Ready");
|
||||||
setBanner(
|
setBanner(
|
||||||
ready
|
pending
|
||||||
? ""
|
? `Тайлы источника «${pending.name}» ещё не готовы (${formatStatus(pending.status)}). Первый прогон может занять часы.`
|
||||||
: `Тайлы источника «${source.name}» ещё не готовы (${formatStatus(source.status)}). Первый прогон может занять часы.`
|
: ""
|
||||||
);
|
);
|
||||||
}, [access, personal, source, styleName, syncGotoFromMap, updateHud]);
|
}, [access, personal, selectedSourceIds, sources, source, styleName, syncGotoFromMap, updateHud]);
|
||||||
|
|
||||||
const refresh = useCallback(async () => {
|
const refresh = useCallback(async () => {
|
||||||
const [sourceList, syncStatus] = await Promise.all([
|
const [sourceList, syncStatus] = await Promise.all([
|
||||||
@@ -196,9 +197,10 @@ export function App() {
|
|||||||
setSources(sourceList);
|
setSources(sourceList);
|
||||||
setStyles(styleList);
|
setStyles(styleList);
|
||||||
setSync(syncStatus);
|
setSync(syncStatus);
|
||||||
setSourceId((current) =>
|
setSelectedSourceIds((current) => {
|
||||||
sourceList.some((item) => item.id === current) ? current : (sourceList[0]?.id ?? "")
|
const kept = current.filter((id) => sourceList.some((item) => item.id === id));
|
||||||
);
|
return kept.length > 0 ? kept : sourceList[0] ? [sourceList[0].id] : [];
|
||||||
|
});
|
||||||
setStyleName((current) =>
|
setStyleName((current) =>
|
||||||
styleList.some((item) => item.name === current)
|
styleList.some((item) => item.name === current)
|
||||||
? current
|
? current
|
||||||
@@ -254,16 +256,16 @@ export function App() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const fitBounds = () => {
|
const fitBounds = () => {
|
||||||
const bounds = source?.bounds;
|
const boxes = selectedSources.map((item) => item.bounds).filter((item): item is NonNullable<typeof item> => Boolean(item));
|
||||||
const map = mapRef.current;
|
const map = mapRef.current;
|
||||||
if (!map || !bounds) {
|
if (!map || boxes.length === 0) {
|
||||||
setGotoError("У источника ещё нет bounds.");
|
setGotoError("У выбранных источников ещё нет bounds.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
map.fitBounds(
|
map.fitBounds(
|
||||||
[
|
[
|
||||||
[bounds.minLon, bounds.minLat],
|
[Math.min(...boxes.map((b) => b.minLon)), Math.min(...boxes.map((b) => b.minLat))],
|
||||||
[bounds.maxLon, bounds.maxLat]
|
[Math.max(...boxes.map((b) => b.maxLon)), Math.max(...boxes.map((b) => b.maxLat))]
|
||||||
],
|
],
|
||||||
{ padding: 48, maxZoom: 10 }
|
{ padding: 48, maxZoom: 10 }
|
||||||
);
|
);
|
||||||
@@ -272,10 +274,13 @@ export function App() {
|
|||||||
const startSync = async () => {
|
const startSync = async () => {
|
||||||
setSyncing(true);
|
setSyncing(true);
|
||||||
try {
|
try {
|
||||||
const url = source
|
const ids = selectedSourceIds.length > 0 ? selectedSourceIds : source ? [source.id] : [];
|
||||||
? serviceUrl(`/api/v1/sync/${encodeURIComponent(source.id)}`)
|
for (const id of ids) {
|
||||||
: serviceUrl("/api/v1/sync");
|
await fetchJson(serviceUrl(`/api/v1/sync/${encodeURIComponent(id)}`), { method: "POST" });
|
||||||
await fetchJson(url, { method: "POST" });
|
}
|
||||||
|
if (ids.length === 0) {
|
||||||
|
await fetchJson(serviceUrl("/api/v1/sync"), { method: "POST" });
|
||||||
|
}
|
||||||
await refresh();
|
await refresh();
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
setBanner(err instanceof Error ? err.message : "Не удалось запустить синхронизацию");
|
setBanner(err instanceof Error ? err.message : "Не удалось запустить синхронизацию");
|
||||||
@@ -284,7 +289,12 @@ export function App() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const status = source?.status;
|
const mixedStatus = selectedSources.some((item) => item.status === "Failed")
|
||||||
|
? "Failed"
|
||||||
|
: selectedSources.every((item) => item.status === "Ready")
|
||||||
|
? "Ready"
|
||||||
|
: selectedSources[0]?.status;
|
||||||
|
const status = mixedStatus;
|
||||||
const pillClass =
|
const pillClass =
|
||||||
status === "Ready" ? "pill pill--ok" : status === "Failed" ? "pill pill--fail" : "pill pill--work";
|
status === "Ready" ? "pill pill--ok" : status === "Failed" ? "pill pill--fail" : "pill pill--work";
|
||||||
const workerClass = [
|
const workerClass = [
|
||||||
@@ -365,26 +375,32 @@ export function App() {
|
|||||||
</button>
|
</button>
|
||||||
) : null}
|
) : null}
|
||||||
<span className={personal ? "pill pill--ok" : "pill"}>{personal ? "личный" : "публичный"}</span>
|
<span className={personal ? "pill pill--ok" : "pill"}>{personal ? "личный" : "публичный"}</span>
|
||||||
<label className="field field--inline">
|
<fieldset className="field field--sources">
|
||||||
<span>Источник</span>
|
<legend>Округа</legend>
|
||||||
<select
|
<div className="source-checks">
|
||||||
value={sourceId}
|
{sources.map((item) => {
|
||||||
onChange={(e) => {
|
const checked = selectedSourceIds.includes(item.id);
|
||||||
const next = e.target.value;
|
return (
|
||||||
setSourceId(next);
|
<label key={item.id}>
|
||||||
const item = sources.find((s) => s.id === next);
|
<input
|
||||||
if (mapRef.current && item?.center) {
|
type="checkbox"
|
||||||
flyTo(item.center[1], item.center[0], Math.max(mapRef.current.getZoom(), 6));
|
checked={checked}
|
||||||
}
|
onChange={() => {
|
||||||
}}
|
setSelectedSourceIds((current) => {
|
||||||
>
|
if (checked) {
|
||||||
{sources.map((item) => (
|
const next = current.filter((id) => id !== item.id);
|
||||||
<option key={item.id} value={item.id}>
|
return next.length > 0 ? next : current;
|
||||||
{item.name}
|
}
|
||||||
</option>
|
return [...current, item.id];
|
||||||
))}
|
});
|
||||||
</select>
|
}}
|
||||||
</label>
|
/>
|
||||||
|
{item.name}
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
<label className="field field--inline">
|
<label className="field field--inline">
|
||||||
<span>Стиль</span>
|
<span>Стиль</span>
|
||||||
<select value={styleName} onChange={(e) => setStyleName(e.target.value)}>
|
<select value={styleName} onChange={(e) => setStyleName(e.target.value)}>
|
||||||
@@ -455,8 +471,8 @@ export function App() {
|
|||||||
<dd>{sync?.isRunning ? "идёт синхронизация" : "ожидание"}</dd>
|
<dd>{sync?.isRunning ? "идёт синхронизация" : "ожидание"}</dd>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<dt>Источник</dt>
|
<dt>Округа</dt>
|
||||||
<dd>{formatStatus(status)}</dd>
|
<dd>{selectedSources.length > 0 ? `${selectedSources.length}: ${formatStatus(status)}` : formatStatus(status)}</dd>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<dt>Скачан</dt>
|
<dt>Скачан</dt>
|
||||||
|
|||||||
@@ -54,13 +54,14 @@ export function stylesListUrl(access: Access): string {
|
|||||||
return serviceUrl("/api/v1/styles");
|
return serviceUrl("/api/v1/styles");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function styleUrl(access: Access, name: string, sourceId: string): string {
|
export function styleUrl(access: Access, name: string, sourceIds: string[]): string {
|
||||||
|
const source = sourceIds.join(",");
|
||||||
if (isPersonal(access)) {
|
if (isPersonal(access)) {
|
||||||
return serviceUrl(
|
return serviceUrl(
|
||||||
`/u/${encodeURIComponent(access.slug)}/styles/${encodeURIComponent(name)}?source=${encodeURIComponent(sourceId)}&token=${encodeURIComponent(access.token)}`
|
`/u/${encodeURIComponent(access.slug)}/styles/${encodeURIComponent(name)}?source=${encodeURIComponent(source)}&token=${encodeURIComponent(access.token)}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return serviceUrl(`/api/v1/styles/${encodeURIComponent(name)}?source=${encodeURIComponent(sourceId)}`);
|
return serviceUrl(`/api/v1/styles/${encodeURIComponent(name)}?source=${encodeURIComponent(source)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function rewriteServiceUrl(url: string, access: Access): string {
|
export function rewriteServiceUrl(url: string, access: Access): string {
|
||||||
|
|||||||
@@ -123,6 +123,55 @@ body {
|
|||||||
|
|
||||||
.field--inline { min-width: 10.5rem; }
|
.field--inline { min-width: 10.5rem; }
|
||||||
|
|
||||||
|
.field--sources {
|
||||||
|
min-width: 16rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field--sources legend {
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: 0.28rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-checks {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.35rem 0.75rem;
|
||||||
|
min-height: 2.75rem;
|
||||||
|
padding: 0.4rem 0.65rem;
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
border: 1px solid var(--line-strong);
|
||||||
|
background: rgba(8, 11, 16, 0.72);
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-checks label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
background: none;
|
||||||
|
min-height: 0;
|
||||||
|
color: var(--text);
|
||||||
|
font-size: 0.78rem;
|
||||||
|
letter-spacing: 0;
|
||||||
|
text-transform: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-checks input {
|
||||||
|
width: 0.95rem;
|
||||||
|
height: 0.95rem;
|
||||||
|
min-height: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
accent-color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
.field--token { min-width: 14rem; }
|
.field--token { min-width: 14rem; }
|
||||||
|
|
||||||
.field--token input {
|
.field--token input {
|
||||||
|
|||||||
@@ -0,0 +1,973 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@babel/code-frame@^7.29.7":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.7.tgz#f2fbbfea87c44a21590ec515b778b2c26d8866e7"
|
||||||
|
integrity sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-validator-identifier" "^7.29.7"
|
||||||
|
js-tokens "^4.0.0"
|
||||||
|
picocolors "^1.1.1"
|
||||||
|
|
||||||
|
"@babel/compat-data@^7.29.7":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.29.7.tgz#6f0237f0f36d2e51c0570a636faed9d2d0efe629"
|
||||||
|
integrity sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==
|
||||||
|
|
||||||
|
"@babel/core@^7.28.0":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.29.7.tgz#80c10b17248082968b57a857b91640971f2070f7"
|
||||||
|
integrity sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.29.7"
|
||||||
|
"@babel/generator" "^7.29.7"
|
||||||
|
"@babel/helper-compilation-targets" "^7.29.7"
|
||||||
|
"@babel/helper-module-transforms" "^7.29.7"
|
||||||
|
"@babel/helpers" "^7.29.7"
|
||||||
|
"@babel/parser" "^7.29.7"
|
||||||
|
"@babel/template" "^7.29.7"
|
||||||
|
"@babel/traverse" "^7.29.7"
|
||||||
|
"@babel/types" "^7.29.7"
|
||||||
|
"@jridgewell/remapping" "^2.3.5"
|
||||||
|
convert-source-map "^2.0.0"
|
||||||
|
debug "^4.1.0"
|
||||||
|
gensync "^1.0.0-beta.2"
|
||||||
|
json5 "^2.2.3"
|
||||||
|
semver "^6.3.1"
|
||||||
|
|
||||||
|
"@babel/generator@^7.29.7", "@babel/generator@^7.29.8":
|
||||||
|
version "7.29.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.29.8.tgz#4b0b887885422643339e09022148a4c4ebaa4979"
|
||||||
|
integrity sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/parser" "^7.29.8"
|
||||||
|
"@babel/types" "^7.29.8"
|
||||||
|
"@jridgewell/gen-mapping" "^0.3.12"
|
||||||
|
"@jridgewell/trace-mapping" "^0.3.28"
|
||||||
|
jsesc "^3.0.2"
|
||||||
|
|
||||||
|
"@babel/helper-compilation-targets@^7.29.7":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz#7a1def704302401c47f64fa85589e974ae217042"
|
||||||
|
integrity sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/compat-data" "^7.29.7"
|
||||||
|
"@babel/helper-validator-option" "^7.29.7"
|
||||||
|
browserslist "^4.24.0"
|
||||||
|
lru-cache "^5.1.1"
|
||||||
|
semver "^6.3.1"
|
||||||
|
|
||||||
|
"@babel/helper-globals@^7.29.7":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.29.7.tgz#f04a96fbd8473241b1079243f5b3f03a3010ab7b"
|
||||||
|
integrity sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==
|
||||||
|
|
||||||
|
"@babel/helper-module-imports@^7.29.7":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz#ef25048a518e828d7393fac5882ddd73921d7396"
|
||||||
|
integrity sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/traverse" "^7.29.7"
|
||||||
|
"@babel/types" "^7.29.7"
|
||||||
|
|
||||||
|
"@babel/helper-module-transforms@^7.29.7":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz#b062747a5997ba138637201328bbff77960574ae"
|
||||||
|
integrity sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-module-imports" "^7.29.7"
|
||||||
|
"@babel/helper-validator-identifier" "^7.29.7"
|
||||||
|
"@babel/traverse" "^7.29.7"
|
||||||
|
|
||||||
|
"@babel/helper-plugin-utils@^7.29.7":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz#c0a0766f1a13617d8a17407d7ab8f9d486225ea4"
|
||||||
|
integrity sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==
|
||||||
|
|
||||||
|
"@babel/helper-string-parser@^7.29.7":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz#7f0871d99824d23137d60f86fcf6130fd5a1b51f"
|
||||||
|
integrity sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==
|
||||||
|
|
||||||
|
"@babel/helper-validator-identifier@^7.29.7":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz#bd87084ced0c796ec46bda492de6e83d29e89fc2"
|
||||||
|
integrity sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==
|
||||||
|
|
||||||
|
"@babel/helper-validator-option@^7.29.7":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz#cf315be940213b354eb4abcc0bd01ebe3f73bc2a"
|
||||||
|
integrity sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==
|
||||||
|
|
||||||
|
"@babel/helpers@^7.29.7":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.29.7.tgz#45abfde7548997e34376c3e69feb475cffb4a607"
|
||||||
|
integrity sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/template" "^7.29.7"
|
||||||
|
"@babel/types" "^7.29.7"
|
||||||
|
|
||||||
|
"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.29.7", "@babel/parser@^7.29.8":
|
||||||
|
version "7.29.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.29.9.tgz#e7ee0a24f752c5296c6455855ccb72662e67ea96"
|
||||||
|
integrity sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.29.8"
|
||||||
|
|
||||||
|
"@babel/plugin-transform-react-jsx-self@^7.27.1":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz#c24424527858220624fd59a5b1eab4fa413c803a"
|
||||||
|
integrity sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-plugin-utils" "^7.29.7"
|
||||||
|
|
||||||
|
"@babel/plugin-transform-react-jsx-source@^7.27.1":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz#5cf25a3689906b58e2f0a2f2b374789e6627b15f"
|
||||||
|
integrity sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-plugin-utils" "^7.29.7"
|
||||||
|
|
||||||
|
"@babel/template@^7.29.7":
|
||||||
|
version "7.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.29.7.tgz#4d9d4004f645cdd304de958c725162784ecac700"
|
||||||
|
integrity sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.29.7"
|
||||||
|
"@babel/parser" "^7.29.7"
|
||||||
|
"@babel/types" "^7.29.7"
|
||||||
|
|
||||||
|
"@babel/traverse@^7.29.7":
|
||||||
|
version "7.29.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.29.8.tgz#4111014cdc71a0f95d9471907590baa0b8a6b28a"
|
||||||
|
integrity sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.29.7"
|
||||||
|
"@babel/generator" "^7.29.8"
|
||||||
|
"@babel/helper-globals" "^7.29.7"
|
||||||
|
"@babel/parser" "^7.29.8"
|
||||||
|
"@babel/template" "^7.29.7"
|
||||||
|
"@babel/types" "^7.29.8"
|
||||||
|
debug "^4.3.1"
|
||||||
|
|
||||||
|
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.28.2", "@babel/types@^7.29.7", "@babel/types@^7.29.8":
|
||||||
|
version "7.29.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.29.8.tgz#1229eef31d85156d70fa3f4cd859376d0eaf6863"
|
||||||
|
integrity sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-string-parser" "^7.29.7"
|
||||||
|
"@babel/helper-validator-identifier" "^7.29.7"
|
||||||
|
|
||||||
|
"@esbuild/aix-ppc64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz#80fcbe36130e58b7670511e888b8e88a259ed76c"
|
||||||
|
integrity sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==
|
||||||
|
|
||||||
|
"@esbuild/android-arm64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz#8aa4965f8d0a7982dc21734bf6601323a66da752"
|
||||||
|
integrity sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==
|
||||||
|
|
||||||
|
"@esbuild/android-arm@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz#300712101f7f50f1d2627a162e6e09b109b6767a"
|
||||||
|
integrity sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==
|
||||||
|
|
||||||
|
"@esbuild/android-x64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz#87dfb27161202bdc958ef48bb61b09c758faee16"
|
||||||
|
integrity sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==
|
||||||
|
|
||||||
|
"@esbuild/darwin-arm64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz#79197898ec1ff745d21c071e1c7cc3c802f0c1fd"
|
||||||
|
integrity sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==
|
||||||
|
|
||||||
|
"@esbuild/darwin-x64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz#146400a8562133f45c4d2eadcf37ddd09718079e"
|
||||||
|
integrity sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==
|
||||||
|
|
||||||
|
"@esbuild/freebsd-arm64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz#1c5f9ba7206e158fd2b24c59fa2d2c8bb47ca0fe"
|
||||||
|
integrity sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==
|
||||||
|
|
||||||
|
"@esbuild/freebsd-x64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz#ea631f4a36beaac4b9279fa0fcc6ca29eaeeb2b3"
|
||||||
|
integrity sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==
|
||||||
|
|
||||||
|
"@esbuild/linux-arm64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz#e1066bce58394f1b1141deec8557a5f0a22f5977"
|
||||||
|
integrity sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==
|
||||||
|
|
||||||
|
"@esbuild/linux-arm@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz#452cd66b20932d08bdc53a8b61c0e30baf4348b9"
|
||||||
|
integrity sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==
|
||||||
|
|
||||||
|
"@esbuild/linux-ia32@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz#b24f8acc45bcf54192c7f2f3be1b53e6551eafe0"
|
||||||
|
integrity sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==
|
||||||
|
|
||||||
|
"@esbuild/linux-loong64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz#f9cfffa7fc8322571fbc4c8b3268caf15bd81ad0"
|
||||||
|
integrity sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==
|
||||||
|
|
||||||
|
"@esbuild/linux-mips64el@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz#575a14bd74644ffab891adc7d7e60d275296f2cd"
|
||||||
|
integrity sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==
|
||||||
|
|
||||||
|
"@esbuild/linux-ppc64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz#75b99c70a95fbd5f7739d7692befe60601591869"
|
||||||
|
integrity sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==
|
||||||
|
|
||||||
|
"@esbuild/linux-riscv64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz#2e3259440321a44e79ddf7535c325057da875cd6"
|
||||||
|
integrity sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==
|
||||||
|
|
||||||
|
"@esbuild/linux-s390x@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz#17676cabbfe5928da5b2a0d6df5d58cd08db2663"
|
||||||
|
integrity sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==
|
||||||
|
|
||||||
|
"@esbuild/linux-x64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz#0583775685ca82066d04c3507f09524d3cd7a306"
|
||||||
|
integrity sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==
|
||||||
|
|
||||||
|
"@esbuild/netbsd-arm64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz#f04c4049cb2e252fe96b16fed90f70746b13f4a4"
|
||||||
|
integrity sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==
|
||||||
|
|
||||||
|
"@esbuild/netbsd-x64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz#77da0d0a0d826d7c921eea3d40292548b258a076"
|
||||||
|
integrity sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==
|
||||||
|
|
||||||
|
"@esbuild/openbsd-arm64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz#6296f5867aedef28a81b22ab2009c786a952dccd"
|
||||||
|
integrity sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==
|
||||||
|
|
||||||
|
"@esbuild/openbsd-x64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz#f8d23303360e27b16cf065b23bbff43c14142679"
|
||||||
|
integrity sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==
|
||||||
|
|
||||||
|
"@esbuild/openharmony-arm64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz#49e0b768744a3924be0d7fd97dd6ce9b2923d88d"
|
||||||
|
integrity sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==
|
||||||
|
|
||||||
|
"@esbuild/sunos-x64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz#a6ed7d6778d67e528c81fb165b23f4911b9b13d6"
|
||||||
|
integrity sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==
|
||||||
|
|
||||||
|
"@esbuild/win32-arm64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz#9ac14c378e1b653af17d08e7d3ce34caef587323"
|
||||||
|
integrity sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==
|
||||||
|
|
||||||
|
"@esbuild/win32-ia32@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz#918942dcbbb35cc14fca39afb91b5e6a3d127267"
|
||||||
|
integrity sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==
|
||||||
|
|
||||||
|
"@esbuild/win32-x64@0.25.12":
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz#9bdad8176be7811ad148d1f8772359041f46c6c5"
|
||||||
|
integrity sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==
|
||||||
|
|
||||||
|
"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5":
|
||||||
|
version "0.3.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f"
|
||||||
|
integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/sourcemap-codec" "^1.5.0"
|
||||||
|
"@jridgewell/trace-mapping" "^0.3.24"
|
||||||
|
|
||||||
|
"@jridgewell/remapping@^2.3.5":
|
||||||
|
version "2.3.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1"
|
||||||
|
integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/gen-mapping" "^0.3.5"
|
||||||
|
"@jridgewell/trace-mapping" "^0.3.24"
|
||||||
|
|
||||||
|
"@jridgewell/resolve-uri@^3.1.0":
|
||||||
|
version "3.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
|
||||||
|
integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
|
||||||
|
|
||||||
|
"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0":
|
||||||
|
version "1.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz#f4c663e862f06dc98ca4d453862c46902789a18d"
|
||||||
|
integrity sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==
|
||||||
|
|
||||||
|
"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.28":
|
||||||
|
version "0.3.31"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0"
|
||||||
|
integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/resolve-uri" "^3.1.0"
|
||||||
|
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||||
|
|
||||||
|
"@mapbox/jsonlint-lines-primitives@^2.0.2", "@mapbox/jsonlint-lines-primitives@~2.0.2":
|
||||||
|
version "2.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.3.tgz#7d7b0b971fbaf6d60953272db4df03020d3fb004"
|
||||||
|
integrity sha512-0SElaV0uMxEnxzBhhX9WTuPyUeMsAN/SS0i16tjuba4/mio63MG9khjC1a0JAiPGXAwvwm4UfHJURCN7nyudQg==
|
||||||
|
|
||||||
|
"@mapbox/point-geometry@^1.1.0", "@mapbox/point-geometry@~1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz#3328fb54b3a1273bc619bf0a6baad8de37181749"
|
||||||
|
integrity sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==
|
||||||
|
|
||||||
|
"@mapbox/tiny-sdf@^2.1.0":
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@mapbox/tiny-sdf/-/tiny-sdf-2.2.0.tgz#95dae0dc371b8c55c53d70f3e25d56823427f4c8"
|
||||||
|
integrity sha512-LVL4wgI9YAum5V+LNVQO6QgFBPw7/MIIY4XJPNsPDMrjEwcE+JfKk1LuIl8GnF197ejVdC9QdPaxrx5gfgdGXg==
|
||||||
|
|
||||||
|
"@mapbox/unitbezier@^0.0.1":
|
||||||
|
version "0.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz#d32deb66c7177e9e9dfc3bbd697083e2e657ff01"
|
||||||
|
integrity sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==
|
||||||
|
|
||||||
|
"@mapbox/unitbezier@^1.0.0":
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@mapbox/unitbezier/-/unitbezier-1.0.0.tgz#54319aff6c467bb1b909e04895c08cdb966bfbff"
|
||||||
|
integrity sha512-fqd515fjBmANKGGsQ286E2Wvj/XvDFpGzwJxq4CI6jMQue6Oy04uCKp+JWKF00xRTmk6cEu1jPJ9p3xqH8YWqQ==
|
||||||
|
|
||||||
|
"@mapbox/vector-tile@^2.0.4":
|
||||||
|
version "2.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@mapbox/vector-tile/-/vector-tile-2.0.5.tgz#d00d894c9ad9350068a4e697e114c47d67072b54"
|
||||||
|
integrity sha512-pXj8m7KTsqZt+1jsE0xIpGvqTSbblfkuEJL/NJmNePMtEwxO8V3XMDo9WMSfDeqHvCtBI9Lmt4mGcGR10zecmw==
|
||||||
|
dependencies:
|
||||||
|
"@mapbox/point-geometry" "~1.1.0"
|
||||||
|
"@types/geojson" "^7946.0.16"
|
||||||
|
pbf "^4.0.2"
|
||||||
|
|
||||||
|
"@mapbox/whoots-js@^3.1.0":
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe"
|
||||||
|
integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==
|
||||||
|
|
||||||
|
"@maplibre/geojson-vt@^6.1.0":
|
||||||
|
version "6.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@maplibre/geojson-vt/-/geojson-vt-6.1.1.tgz#25a032435b4ce2236ea0ba911aff5fb6d5454fc1"
|
||||||
|
integrity sha512-FVMOcmSP/yqol45t7StApEyTL5/vmqBCuFhH9n+fFuINenhaX+YgHHIt1yJ86S8kln3uJLcMvmEU2cfn6E2eCQ==
|
||||||
|
dependencies:
|
||||||
|
kdbush "^4.1.0"
|
||||||
|
|
||||||
|
"@maplibre/maplibre-gl-style-spec@^24.8.1":
|
||||||
|
version "24.10.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-24.10.0.tgz#ec1de19a468024749f0618d31bc9c7ff0641400e"
|
||||||
|
integrity sha512-lichxSiagMEBBrqHF0trtMQH9RKh+9jUlIJl0qW0QHvt2H/tbvUWdE+ZzI2Jd0/pT7j/iavLonlPu7EQ/ixTOw==
|
||||||
|
dependencies:
|
||||||
|
"@mapbox/jsonlint-lines-primitives" "~2.0.2"
|
||||||
|
"@mapbox/unitbezier" "^1.0.0"
|
||||||
|
json-stringify-pretty-compact "^4.0.0"
|
||||||
|
minimist "^1.2.8"
|
||||||
|
quickselect "^3.0.0"
|
||||||
|
tinyqueue "^3.0.0"
|
||||||
|
|
||||||
|
"@maplibre/mlt@^1.1.8":
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@maplibre/mlt/-/mlt-1.3.0.tgz#3a9467d12a0b6edfcdba429dd3a260ca48f11129"
|
||||||
|
integrity sha512-7M2O7ABM80Oi8XPkfkrjKB8mOBIxGoVgkA52Mu4RMWoBvvMdagQ522+WxVYujZsMpqIr3BpzrTbXrm4k8lCzCQ==
|
||||||
|
dependencies:
|
||||||
|
"@mapbox/point-geometry" "^1.1.0"
|
||||||
|
|
||||||
|
"@maplibre/vt-pbf@^4.3.0":
|
||||||
|
version "4.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@maplibre/vt-pbf/-/vt-pbf-4.3.2.tgz#cfcdbdadaf88b4cb8645e43c8eead77cd6546030"
|
||||||
|
integrity sha512-j6p0AdjvAR19Z3XaCysle7A4ZSo08tYOzxD0Y9NQylwPAkwJJeYub5b2eVucdeDh7erhv69DahoLOevDRERRUw==
|
||||||
|
dependencies:
|
||||||
|
"@mapbox/point-geometry" "^1.1.0"
|
||||||
|
"@types/geojson" "^7946.0.16"
|
||||||
|
pbf "^5.1.0"
|
||||||
|
|
||||||
|
"@napi-rs/lzma-linux-x64-gnu@1.5.1":
|
||||||
|
version "1.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz#e57d4306966078662038094fb38eb9146dc3aea9"
|
||||||
|
integrity sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==
|
||||||
|
|
||||||
|
"@rolldown/pluginutils@1.0.0-beta.27":
|
||||||
|
version "1.0.0-beta.27"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz#47d2bf4cef6d470b22f5831b420f8964e0bf755f"
|
||||||
|
integrity sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==
|
||||||
|
|
||||||
|
"@rollup/rollup-android-arm-eabi@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.63.4.tgz#e1d06062fb451578b3fb0bdea3360daaa1395f44"
|
||||||
|
integrity sha512-I+BSHzTAhKN2n7ZwGZsegGcZjDpLqFOMAtJz/u6uFGe0pUFbq56dEHjqJV/ZUdRJtNXNxA+hREUatZBvMR3Oiw==
|
||||||
|
|
||||||
|
"@rollup/rollup-android-arm64@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.63.4.tgz#2e81dec4e9e879c95c8266e30da67074c4998224"
|
||||||
|
integrity sha512-pu3BdjS2LtEzRu2elmGzS3fIeWSZy4BMDIaLNwjorO76+k2d0LMluijhsDx3KQyQBQ/lLUZCQA9/s6csvUfuhw==
|
||||||
|
|
||||||
|
"@rollup/rollup-darwin-arm64@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.63.4.tgz#f48f92f44454aed23d013f7cdb6da0dc2cb598ae"
|
||||||
|
integrity sha512-xfSrj9MHnWK9GaSqT9U0ImHtH/N8WZlHLx4cZHiuLcqs640hvZ3hLPd5UR2AZS57FaE8HrRUSpltbZdWRxHiDA==
|
||||||
|
|
||||||
|
"@rollup/rollup-darwin-x64@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.63.4.tgz#39b0b2ad27c49b40aec71fb20210e2e3be5fdbd0"
|
||||||
|
integrity sha512-bqU99PLJb/dqb3S0GIMdeuyAEETSUgZBoqXYd3Sd+WCsV+MmPhnN6JrotWyir31+QgH7EvvE5/mwGJlEoci8Fw==
|
||||||
|
|
||||||
|
"@rollup/rollup-freebsd-arm64@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.63.4.tgz#0c85d18f5b9228b7195adbbbc97c1adaf41b8106"
|
||||||
|
integrity sha512-JinsFZ5G40oXQb+sUuiA5x689vhr6dDYK0H0NL+rwKdL6CqnmYN8PE4ZwfRSoIjrCxqTQG/SLfTtSvHeGxoVlw==
|
||||||
|
|
||||||
|
"@rollup/rollup-freebsd-x64@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.63.4.tgz#0c6c27471ea950213aad76418f075c96f57e9533"
|
||||||
|
integrity sha512-GAdA4UxpiNm27cLHr2GqXBpAD0x9FqwYBY7/YSP0Ss0/PNi4k8gbviqpIpYbVSRBaS2ZcegXEzgTQMbRNCwxCw==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-arm-gnueabihf@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.63.4.tgz#28cba40d417fb3d2c1536941b02143a2bdda72be"
|
||||||
|
integrity sha512-qDd6NoA1znaLjp4jR5U/KWCdLAKDJNB8W9ChbbDaKbo0xA+Atln5HK6LFCZ4oJQpemtRZA288DCirFRjrspptw==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-arm-musleabihf@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.63.4.tgz#c9f06aa876d6d312012a2048d9e5533c581a7341"
|
||||||
|
integrity sha512-WtB5Tz5KTNINb8ZA+8sQ7bmjuS1JrRT7YverYIhUGdWWDlpzVWmIwuZE+jidkEXUn1l0zrEkaIMa8dHF3NGcsA==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-arm64-gnu@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.63.4.tgz#b26376804ca32b3dcc8f68930f765394fb4e4814"
|
||||||
|
integrity sha512-VcQ3L1tjnkKzWjryAVaFhHEWcqOfICX9uxVVoDzm2t0DpgKRHd2zOpVrJc0xsWeBZcBFyYROCIBdyR/fS174pg==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-arm64-musl@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.63.4.tgz#65f6f5deee9d30904b4d52ee3d45679055743cd1"
|
||||||
|
integrity sha512-6+ZQX6P5s0cMDN2Ypb8Lbm2+/sZYmZjdaYny992ujUU9UKi/4CWoJWsl1pNvjWJHNHGK51m+jKGLlh1ylb2ifQ==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-loong64-gnu@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.63.4.tgz#15d7e44538e967a3d6132f5b9f27f02346df6850"
|
||||||
|
integrity sha512-D72ZnvkFkBXOfzMMQLcwfPLyGkKb7HZ9/mf97B7v6/P5Lbv4oFOtSY/uHbS8lH6uKUOxoKiuokdb50XZSzzbJw==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-loong64-musl@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.63.4.tgz#7afad2b9e41941344883154f754b7f772ef16b01"
|
||||||
|
integrity sha512-piU6BxeqA3O9KSu3kRCIQQtNqFFaTu21SEV4FwaRZowpnj3bLaWPZHw+xFqCs0XlJ+aOH3PTRWGoglH+mKA/OA==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-ppc64-gnu@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.63.4.tgz#3f3131b1a9585851b2875c86a49f6e6deb9e68e0"
|
||||||
|
integrity sha512-/5PGpHwqt2EEEOUs1XwzubE/ucr0dWDQ+to3zqi4Ds7EWpwtQ79wXc4JBoxqj/OwpawTsKWzJxHfSuBOq3DrWA==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-ppc64-musl@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.63.4.tgz#463aeee26c62983c1fc235708d1b41baf4735f98"
|
||||||
|
integrity sha512-cX3beZDLWt7G2oJF+nhChiT+qtaihs+S2xi7ziGmVB+2pwPng6D0Ed0HmElQOgv2UsUmSJJLGwpBao/3TDx3VA==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-riscv64-gnu@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.63.4.tgz#cb495bd8cc978e17593e0d323b36fd95b5eab098"
|
||||||
|
integrity sha512-1uz2mGWHyptR7DgHHrlbdRAjXK7v7elGZ9lMja910/RP+ZYbX6xAmCiU9UZSX4hqmgtHMv6lr5l3kq1HIOpcag==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-riscv64-musl@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.63.4.tgz#655b69144b1e786e0bf8ac3b727f0d7fee590a08"
|
||||||
|
integrity sha512-nLS8topojxyz7SRpKR2IODRpQ0XPZ+xaOXvT3+hqK/Uy8Lo5HFgkkIBiIrCu5tL5YqzTvgovGw55PwpahTAGig==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-s390x-gnu@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.63.4.tgz#70b175b0361a7898acc294a6b14001e2c3ad99be"
|
||||||
|
integrity sha512-gs7DRKotr3l3q+jGPQBjH0ng1FjlEDm5ueQrkw5JtQvtLyEIcLASqAEaor56BhkKRzk+IcQzrcanBdb/bBQn8g==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-x64-gnu@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.63.4.tgz#0c68fa212df249f996b2d75e8fbb3766b1582ee8"
|
||||||
|
integrity sha512-791ET7W17NnScOZM7h4dX5hYspxE28htPFsb1awY/NRR8+PRNkS53e475rDdxXXDrP+kwnCcNWg9CX5ztn/Aqw==
|
||||||
|
|
||||||
|
"@rollup/rollup-linux-x64-musl@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.63.4.tgz#93af6206edf751469a43c3614164360136540838"
|
||||||
|
integrity sha512-iwZQRcmj7g88g3tzefIrQY7qvmuA/cfYwhrDtTBhsmukO4U2huVO5W+86XacUMRvdSFVAc6kZUZy21JaRwiB9w==
|
||||||
|
|
||||||
|
"@rollup/rollup-openbsd-x64@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.63.4.tgz#7c7680c4004fd602b59cd19f3294fa1b89d0c683"
|
||||||
|
integrity sha512-dVHFp9gRWrdTpnqQuGfCwd7hOQDatK1VCP2iWhLY/cGrOQs/ucFzJ6A5SRqbXX12ZDI8EUuejSM5kwg+ja7Png==
|
||||||
|
|
||||||
|
"@rollup/rollup-openharmony-arm64@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.63.4.tgz#f389ff4d8ee8a635ff51d76e8ff20b7db2292bce"
|
||||||
|
integrity sha512-t3NlauOW6gxZVVFcBEnO62Cb4wbyDFL416gTg1uFI/2tgqYQlf69FbSE115Ajre9I+c26Lk4mcmdFUsS/DGifQ==
|
||||||
|
|
||||||
|
"@rollup/rollup-win32-arm64-msvc@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.63.4.tgz#55a286f40f9d03c653ceb7183d6c6179ec312c75"
|
||||||
|
integrity sha512-xWuIaSye5FWZF8+UYtVEcHtRJDN5kN9Kfgxx3Kq8XIov9KSKbc1fiqQCm90SKrgQbUXZelbnUhnlUJmfSE7P9A==
|
||||||
|
|
||||||
|
"@rollup/rollup-win32-ia32-msvc@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.63.4.tgz#7eb577b64e2a39115182a87a2ea957608d8331f6"
|
||||||
|
integrity sha512-9ALJJUOg/ZflMJepVo2PlgsGxSaxN7SQ4Z8GoZfVlarWr6r3rkHUNsd/zAio7p4YMtChSMXPionxej4Hkf6CXQ==
|
||||||
|
|
||||||
|
"@rollup/rollup-win32-x64-gnu@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.63.4.tgz#0e7a7cd5f0db2f570fc312687d67baf21283a3f6"
|
||||||
|
integrity sha512-blj9z5qx/Pv4WU0W1NMFDB97e0JH5ed+aZGywW8WCvp/NhWX/4PFAq5uu6Q0AebNn+Vo6KzUYDT++JzTT5ojlQ==
|
||||||
|
|
||||||
|
"@rollup/rollup-win32-x64-msvc@4.63.4":
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.63.4.tgz#f8e11d8ac827db7695d50f1def4c00a7f3cd1510"
|
||||||
|
integrity sha512-Erx822VRBwLa124shbj+wNXe//BOgMEctDV0m1aqTQdNO1S69DgNUCFKC1RCeZfixs1J31l6igk1ziyXErbigQ==
|
||||||
|
|
||||||
|
"@types/babel__core@^7.20.5":
|
||||||
|
version "7.20.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017"
|
||||||
|
integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/parser" "^7.20.7"
|
||||||
|
"@babel/types" "^7.20.7"
|
||||||
|
"@types/babel__generator" "*"
|
||||||
|
"@types/babel__template" "*"
|
||||||
|
"@types/babel__traverse" "*"
|
||||||
|
|
||||||
|
"@types/babel__generator@*":
|
||||||
|
version "7.27.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.27.0.tgz#b5819294c51179957afaec341442f9341e4108a9"
|
||||||
|
integrity sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.0.0"
|
||||||
|
|
||||||
|
"@types/babel__template@*":
|
||||||
|
version "7.4.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f"
|
||||||
|
integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==
|
||||||
|
dependencies:
|
||||||
|
"@babel/parser" "^7.1.0"
|
||||||
|
"@babel/types" "^7.0.0"
|
||||||
|
|
||||||
|
"@types/babel__traverse@*":
|
||||||
|
version "7.28.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.28.0.tgz#07d713d6cce0d265c9849db0cbe62d3f61f36f74"
|
||||||
|
integrity sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.28.2"
|
||||||
|
|
||||||
|
"@types/estree@1.0.9":
|
||||||
|
version "1.0.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.9.tgz#cf3f0e876d7bee15a93ab925b82bf570a3904a24"
|
||||||
|
integrity sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==
|
||||||
|
|
||||||
|
"@types/geojson@^7946.0.16":
|
||||||
|
version "7946.0.16"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.16.tgz#8ebe53d69efada7044454e3305c19017d97ced2a"
|
||||||
|
integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==
|
||||||
|
|
||||||
|
"@types/prop-types@*":
|
||||||
|
version "15.7.15"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.15.tgz#e6e5a86d602beaca71ce5163fadf5f95d70931c7"
|
||||||
|
integrity sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==
|
||||||
|
|
||||||
|
"@types/react-dom@^18.3.5":
|
||||||
|
version "18.3.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.7.tgz#b89ddf2cd83b4feafcc4e2ea41afdfb95a0d194f"
|
||||||
|
integrity sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==
|
||||||
|
|
||||||
|
"@types/react@^18.3.18":
|
||||||
|
version "18.3.31"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.31.tgz#b5e95e28ffcceab8d982f33f2eb076e17653c2a4"
|
||||||
|
integrity sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==
|
||||||
|
dependencies:
|
||||||
|
"@types/prop-types" "*"
|
||||||
|
csstype "^3.2.2"
|
||||||
|
|
||||||
|
"@vitejs/plugin-react@^4.3.4":
|
||||||
|
version "4.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz#647af4e7bb75ad3add578e762ad984b90f4a24b9"
|
||||||
|
integrity sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/core" "^7.28.0"
|
||||||
|
"@babel/plugin-transform-react-jsx-self" "^7.27.1"
|
||||||
|
"@babel/plugin-transform-react-jsx-source" "^7.27.1"
|
||||||
|
"@rolldown/pluginutils" "1.0.0-beta.27"
|
||||||
|
"@types/babel__core" "^7.20.5"
|
||||||
|
react-refresh "^0.17.0"
|
||||||
|
|
||||||
|
baseline-browser-mapping@^2.11.23:
|
||||||
|
version "2.11.25"
|
||||||
|
resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.11.25.tgz#88b942ce372bdf2d6a2652136bbf7826c65c77be"
|
||||||
|
integrity sha512-gMmEShwwq7FJqMwvfRwvCl00v4kN+KOfJqXn+f4nrufak5gNHJOksd/60Dvjuz7sI8Y5WiSFBa8FEYr+zoyqCw==
|
||||||
|
|
||||||
|
browserslist@^4.24.0:
|
||||||
|
version "4.29.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.29.0.tgz#e50e72c30c4b5f7ec894c09feb6ed525167f5344"
|
||||||
|
integrity sha512-3GSvyjvDI4Dur1Meg2BekJquu5uF+9R9a1+5M1Mde192eZoXbeXjzgOsgqPS2V8D5wrrip0gR5Hf/GhWQ9ZzaA==
|
||||||
|
dependencies:
|
||||||
|
baseline-browser-mapping "^2.11.23"
|
||||||
|
caniuse-lite "^1.0.30001810"
|
||||||
|
electron-to-chromium "^1.5.427"
|
||||||
|
node-releases "^2.0.55"
|
||||||
|
update-browserslist-db "^1.3.3"
|
||||||
|
|
||||||
|
caniuse-lite@^1.0.30001810:
|
||||||
|
version "1.0.30001810"
|
||||||
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz#4970b477dea3278374de9bc43aa8f5d39fc3cda2"
|
||||||
|
integrity sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==
|
||||||
|
|
||||||
|
convert-source-map@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
|
||||||
|
integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
|
||||||
|
|
||||||
|
csstype@^3.2.2:
|
||||||
|
version "3.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.2.3.tgz#ec48c0f3e993e50648c86da559e2610995cf989a"
|
||||||
|
integrity sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==
|
||||||
|
|
||||||
|
debug@^4.1.0, debug@^4.3.1:
|
||||||
|
version "4.4.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a"
|
||||||
|
integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==
|
||||||
|
dependencies:
|
||||||
|
ms "^2.1.3"
|
||||||
|
|
||||||
|
earcut@^3.0.2:
|
||||||
|
version "3.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/earcut/-/earcut-3.2.3.tgz#74aec19555a7e28773429826729d2e4bfeb19022"
|
||||||
|
integrity sha512-vnS4AVwp1KHAF13i1vp1/2D5evWy3k5u/iW/B81QVsUZtV8cv2tU0b2VNFlqvh4kYwrFMDdjPCfAmfyJW9y14Q==
|
||||||
|
|
||||||
|
electron-to-chromium@^1.5.427:
|
||||||
|
version "1.5.433"
|
||||||
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.433.tgz#5c26b05c48030ff4a5566fcaa10dc452a1d1de3e"
|
||||||
|
integrity sha512-5lCAbyZBjtmUt/RAGHRqrL2q0oEFRThDAsZHHDn9XHa89Qw7gMYOeSicBTy+AHfvo0r6vwsZvqNJTQIQy1BLzA==
|
||||||
|
|
||||||
|
esbuild@^0.25.0:
|
||||||
|
version "0.25.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.12.tgz#97a1d041f4ab00c2fce2f838d2b9969a2d2a97a5"
|
||||||
|
integrity sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==
|
||||||
|
optionalDependencies:
|
||||||
|
"@esbuild/aix-ppc64" "0.25.12"
|
||||||
|
"@esbuild/android-arm" "0.25.12"
|
||||||
|
"@esbuild/android-arm64" "0.25.12"
|
||||||
|
"@esbuild/android-x64" "0.25.12"
|
||||||
|
"@esbuild/darwin-arm64" "0.25.12"
|
||||||
|
"@esbuild/darwin-x64" "0.25.12"
|
||||||
|
"@esbuild/freebsd-arm64" "0.25.12"
|
||||||
|
"@esbuild/freebsd-x64" "0.25.12"
|
||||||
|
"@esbuild/linux-arm" "0.25.12"
|
||||||
|
"@esbuild/linux-arm64" "0.25.12"
|
||||||
|
"@esbuild/linux-ia32" "0.25.12"
|
||||||
|
"@esbuild/linux-loong64" "0.25.12"
|
||||||
|
"@esbuild/linux-mips64el" "0.25.12"
|
||||||
|
"@esbuild/linux-ppc64" "0.25.12"
|
||||||
|
"@esbuild/linux-riscv64" "0.25.12"
|
||||||
|
"@esbuild/linux-s390x" "0.25.12"
|
||||||
|
"@esbuild/linux-x64" "0.25.12"
|
||||||
|
"@esbuild/netbsd-arm64" "0.25.12"
|
||||||
|
"@esbuild/netbsd-x64" "0.25.12"
|
||||||
|
"@esbuild/openbsd-arm64" "0.25.12"
|
||||||
|
"@esbuild/openbsd-x64" "0.25.12"
|
||||||
|
"@esbuild/openharmony-arm64" "0.25.12"
|
||||||
|
"@esbuild/sunos-x64" "0.25.12"
|
||||||
|
"@esbuild/win32-arm64" "0.25.12"
|
||||||
|
"@esbuild/win32-ia32" "0.25.12"
|
||||||
|
"@esbuild/win32-x64" "0.25.12"
|
||||||
|
|
||||||
|
escalade@^3.2.0:
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
|
||||||
|
integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
|
||||||
|
|
||||||
|
fdir@^6.4.4, fdir@^6.5.0:
|
||||||
|
version "6.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350"
|
||||||
|
integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==
|
||||||
|
|
||||||
|
fsevents@~2.3.2, fsevents@~2.3.3:
|
||||||
|
version "2.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||||
|
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||||
|
|
||||||
|
gensync@^1.0.0-beta.2:
|
||||||
|
version "1.0.0-beta.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||||
|
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
|
||||||
|
|
||||||
|
gl-matrix@^3.4.4:
|
||||||
|
version "3.4.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-3.4.4.tgz#7789ee4982f62c7a7af447ee488f3bd6b0c77003"
|
||||||
|
integrity sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==
|
||||||
|
|
||||||
|
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||||
|
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||||
|
|
||||||
|
jsesc@^3.0.2:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d"
|
||||||
|
integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==
|
||||||
|
|
||||||
|
json-stringify-pretty-compact@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz#cf4844770bddee3cb89a6170fe4b00eee5dbf1d4"
|
||||||
|
integrity sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==
|
||||||
|
|
||||||
|
json5@^2.2.3:
|
||||||
|
version "2.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
||||||
|
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
||||||
|
|
||||||
|
kdbush@^4.0.2, kdbush@^4.1.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-4.1.0.tgz#d504bc0447a59be4fb75533a5c25e316b3ed8859"
|
||||||
|
integrity sha512-e9vurzrXJQrFX6ckpHP3bvj5l+9CnYzkxDNnNQ1h2QTqdWsUAJgXiKdGNcOa1EY85dU8KbQ+z/FdQdB7P+9yfQ==
|
||||||
|
|
||||||
|
loose-envify@^1.1.0:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||||
|
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||||
|
dependencies:
|
||||||
|
js-tokens "^3.0.0 || ^4.0.0"
|
||||||
|
|
||||||
|
lru-cache@^5.1.1:
|
||||||
|
version "5.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
|
||||||
|
integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
|
||||||
|
dependencies:
|
||||||
|
yallist "^3.0.2"
|
||||||
|
|
||||||
|
maplibre-gl@^5.6.0:
|
||||||
|
version "5.24.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/maplibre-gl/-/maplibre-gl-5.24.0.tgz#a8059371cdbeb04a62850ccc22cb37783928a10d"
|
||||||
|
integrity sha512-ALyFxgtd5R+65UqZ/++lOqwWcC0SNho9c27fYSyLmG7AfnAul2o46F05aDJGPbFU57wos9dgcIySHs0Xe6ia3A==
|
||||||
|
dependencies:
|
||||||
|
"@mapbox/jsonlint-lines-primitives" "^2.0.2"
|
||||||
|
"@mapbox/point-geometry" "^1.1.0"
|
||||||
|
"@mapbox/tiny-sdf" "^2.1.0"
|
||||||
|
"@mapbox/unitbezier" "^0.0.1"
|
||||||
|
"@mapbox/vector-tile" "^2.0.4"
|
||||||
|
"@mapbox/whoots-js" "^3.1.0"
|
||||||
|
"@maplibre/geojson-vt" "^6.1.0"
|
||||||
|
"@maplibre/maplibre-gl-style-spec" "^24.8.1"
|
||||||
|
"@maplibre/mlt" "^1.1.8"
|
||||||
|
"@maplibre/vt-pbf" "^4.3.0"
|
||||||
|
"@types/geojson" "^7946.0.16"
|
||||||
|
earcut "^3.0.2"
|
||||||
|
gl-matrix "^3.4.4"
|
||||||
|
kdbush "^4.0.2"
|
||||||
|
murmurhash-js "^1.0.0"
|
||||||
|
pbf "^4.0.1"
|
||||||
|
potpack "^2.1.0"
|
||||||
|
quickselect "^3.0.0"
|
||||||
|
tinyqueue "^3.0.0"
|
||||||
|
|
||||||
|
minimist@^1.2.8:
|
||||||
|
version "1.2.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||||
|
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
||||||
|
|
||||||
|
ms@^2.1.3:
|
||||||
|
version "2.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||||
|
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||||
|
|
||||||
|
murmurhash-js@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/murmurhash-js/-/murmurhash-js-1.0.0.tgz#b06278e21fc6c37fa5313732b0412bcb6ae15f51"
|
||||||
|
integrity sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==
|
||||||
|
|
||||||
|
nanoid@^3.3.18:
|
||||||
|
version "3.3.19"
|
||||||
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.19.tgz#336d4aa4bcd4fb24d2cddede7ffeae40bec03f0a"
|
||||||
|
integrity sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==
|
||||||
|
|
||||||
|
node-releases@^2.0.55:
|
||||||
|
version "2.0.56"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.56.tgz#fff6a4093fe05d994a2a5e415eee5fcef874e6dc"
|
||||||
|
integrity sha512-x0InOIyzgdk+eyaWaRJFH5snEtiImgBgblZ2CyPrLmqqcuMQkEvcDPHbzqbD8eDsSeJbVOjn+crzyzHaM4D+/A==
|
||||||
|
|
||||||
|
pbf@^4.0.1, pbf@^4.0.2:
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/pbf/-/pbf-4.0.2.tgz#70f71a5c4df774438c1db482630146decb03e2d9"
|
||||||
|
integrity sha512-J0ajxARhZfpUEebxYs1vhMGMuLSXtBe1e+fFPDrf2uA2hgo+UshKfNUWOz92HJNz6/NFEXseQPddnHkTreWRqg==
|
||||||
|
dependencies:
|
||||||
|
resolve-protobuf-schema "^2.1.0"
|
||||||
|
|
||||||
|
pbf@^5.1.0:
|
||||||
|
version "5.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/pbf/-/pbf-5.1.2.tgz#07c427819eda32f02f1ec9741558f61444f2e1c0"
|
||||||
|
integrity sha512-mnvGdvOrIvJOBGUEdGkrVXjN8E/VkIJCkf2eS1DH2yv82ORUlLttmDt0rWY38yYZmVwciZwBUvHM20qxBZf40w==
|
||||||
|
dependencies:
|
||||||
|
resolve-protobuf-schema "^2.1.0"
|
||||||
|
|
||||||
|
picocolors@^1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
|
||||||
|
integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
|
||||||
|
|
||||||
|
picomatch@^4.0.2, picomatch@^4.0.4:
|
||||||
|
version "4.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.7.tgz#6313360034ccb36b3dc61ecbdff78121f90fe21f"
|
||||||
|
integrity sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==
|
||||||
|
|
||||||
|
postcss@^8.5.3:
|
||||||
|
version "8.5.28"
|
||||||
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.28.tgz#da4563a99a06e62d6c1cd1acae363224bcaed6e9"
|
||||||
|
integrity sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==
|
||||||
|
dependencies:
|
||||||
|
nanoid "^3.3.18"
|
||||||
|
picocolors "^1.1.1"
|
||||||
|
source-map-js "^1.2.1"
|
||||||
|
|
||||||
|
potpack@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/potpack/-/potpack-2.1.0.tgz#fe548e2f9061e9937f17191c1ab6dd98ca30e02f"
|
||||||
|
integrity sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ==
|
||||||
|
|
||||||
|
protocol-buffers-schema@^3.3.1:
|
||||||
|
version "3.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.6.1.tgz#fd9a58a5c4e96385b964808f3ddd58f9ef18c3c8"
|
||||||
|
integrity sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ==
|
||||||
|
|
||||||
|
quickselect@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-3.0.0.tgz#a37fc953867d56f095a20ac71c6d27063d2de603"
|
||||||
|
integrity sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==
|
||||||
|
|
||||||
|
react-dom@^18.3.1:
|
||||||
|
version "18.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4"
|
||||||
|
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
|
||||||
|
dependencies:
|
||||||
|
loose-envify "^1.1.0"
|
||||||
|
scheduler "^0.23.2"
|
||||||
|
|
||||||
|
react-refresh@^0.17.0:
|
||||||
|
version "0.17.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.17.0.tgz#b7e579c3657f23d04eccbe4ad2e58a8ed51e7e53"
|
||||||
|
integrity sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==
|
||||||
|
|
||||||
|
react@^18.3.1:
|
||||||
|
version "18.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
|
||||||
|
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
|
||||||
|
dependencies:
|
||||||
|
loose-envify "^1.1.0"
|
||||||
|
|
||||||
|
resolve-protobuf-schema@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz#9ca9a9e69cf192bbdaf1006ec1973948aa4a3758"
|
||||||
|
integrity sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==
|
||||||
|
dependencies:
|
||||||
|
protocol-buffers-schema "^3.3.1"
|
||||||
|
|
||||||
|
rollup@^4.34.9:
|
||||||
|
version "4.63.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.63.4.tgz#cff29b8d6d959aee7cb5e44b0dad70074493dbf8"
|
||||||
|
integrity sha512-4U0liVayNIoLp3GFl1FcI8561WepLnZ1rqfraGh7S9B3Ur5F9S283y8Futii7RUU2C/97tOBmBy7nYvhoiOpbQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/estree" "1.0.9"
|
||||||
|
optionalDependencies:
|
||||||
|
"@napi-rs/lzma-linux-x64-gnu" "1.5.1"
|
||||||
|
"@rollup/rollup-android-arm-eabi" "4.63.4"
|
||||||
|
"@rollup/rollup-android-arm64" "4.63.4"
|
||||||
|
"@rollup/rollup-darwin-arm64" "4.63.4"
|
||||||
|
"@rollup/rollup-darwin-x64" "4.63.4"
|
||||||
|
"@rollup/rollup-freebsd-arm64" "4.63.4"
|
||||||
|
"@rollup/rollup-freebsd-x64" "4.63.4"
|
||||||
|
"@rollup/rollup-linux-arm-gnueabihf" "4.63.4"
|
||||||
|
"@rollup/rollup-linux-arm-musleabihf" "4.63.4"
|
||||||
|
"@rollup/rollup-linux-arm64-gnu" "4.63.4"
|
||||||
|
"@rollup/rollup-linux-arm64-musl" "4.63.4"
|
||||||
|
"@rollup/rollup-linux-loong64-gnu" "4.63.4"
|
||||||
|
"@rollup/rollup-linux-loong64-musl" "4.63.4"
|
||||||
|
"@rollup/rollup-linux-ppc64-gnu" "4.63.4"
|
||||||
|
"@rollup/rollup-linux-ppc64-musl" "4.63.4"
|
||||||
|
"@rollup/rollup-linux-riscv64-gnu" "4.63.4"
|
||||||
|
"@rollup/rollup-linux-riscv64-musl" "4.63.4"
|
||||||
|
"@rollup/rollup-linux-s390x-gnu" "4.63.4"
|
||||||
|
"@rollup/rollup-linux-x64-gnu" "4.63.4"
|
||||||
|
"@rollup/rollup-linux-x64-musl" "4.63.4"
|
||||||
|
"@rollup/rollup-openbsd-x64" "4.63.4"
|
||||||
|
"@rollup/rollup-openharmony-arm64" "4.63.4"
|
||||||
|
"@rollup/rollup-win32-arm64-msvc" "4.63.4"
|
||||||
|
"@rollup/rollup-win32-ia32-msvc" "4.63.4"
|
||||||
|
"@rollup/rollup-win32-x64-gnu" "4.63.4"
|
||||||
|
"@rollup/rollup-win32-x64-msvc" "4.63.4"
|
||||||
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
|
scheduler@^0.23.2:
|
||||||
|
version "0.23.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3"
|
||||||
|
integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==
|
||||||
|
dependencies:
|
||||||
|
loose-envify "^1.1.0"
|
||||||
|
|
||||||
|
semver@^6.3.1:
|
||||||
|
version "6.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||||
|
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||||
|
|
||||||
|
source-map-js@^1.2.1:
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
|
||||||
|
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
||||||
|
|
||||||
|
tinyglobby@^0.2.13:
|
||||||
|
version "0.2.17"
|
||||||
|
resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.17.tgz#562a9a6c9eb2b3b123d39719f9af5bb44fcd7631"
|
||||||
|
integrity sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==
|
||||||
|
dependencies:
|
||||||
|
fdir "^6.5.0"
|
||||||
|
picomatch "^4.0.4"
|
||||||
|
|
||||||
|
tinyqueue@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-3.0.0.tgz#101ea761ccc81f979e29200929e78f1556e3661e"
|
||||||
|
integrity sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==
|
||||||
|
|
||||||
|
typescript@^5.7.3:
|
||||||
|
version "5.9.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f"
|
||||||
|
integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==
|
||||||
|
|
||||||
|
update-browserslist-db@^1.3.3:
|
||||||
|
version "1.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.3.3.tgz#197e21fb2561fa89f8b94fad605a2b296a18993a"
|
||||||
|
integrity sha512-pJ2sYawQS0R/WI928Gj5GlPhTGzbMelq0+4INtSYNDV9ErKJcX6xjGWkoG/VnB3dpUm00zALaqkrUD77pO5TDQ==
|
||||||
|
dependencies:
|
||||||
|
escalade "^3.2.0"
|
||||||
|
picocolors "^1.1.1"
|
||||||
|
|
||||||
|
vite@^6.0.7:
|
||||||
|
version "6.4.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/vite/-/vite-6.4.3.tgz#85a164db7ce706f2a776812efa2b340f1721858e"
|
||||||
|
integrity sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==
|
||||||
|
dependencies:
|
||||||
|
esbuild "^0.25.0"
|
||||||
|
fdir "^6.4.4"
|
||||||
|
picomatch "^4.0.2"
|
||||||
|
postcss "^8.5.3"
|
||||||
|
rollup "^4.34.9"
|
||||||
|
tinyglobby "^0.2.13"
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents "~2.3.3"
|
||||||
|
|
||||||
|
yallist@^3.0.2:
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
||||||
|
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
||||||
@@ -124,9 +124,20 @@ const map = new maplibregl.Map({
|
|||||||
<strong>3. URL</strong>
|
<strong>3. URL</strong>
|
||||||
<p>MapLibre просит style JSON. Сервер сам подставит тайлы с тем же токеном.</p>
|
<p>MapLibre просит style JSON. Сервер сам подставит тайлы с тем же токеном.</p>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>4. Несколько округов</strong>
|
||||||
|
<p>
|
||||||
|
В <code>source</code> перечислите id через запятую. Сервер добавит отдельный vector source на каждый extract и
|
||||||
|
скопирует слои. Один стиль — несколько округов на одной карте.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<CopyBlock label="Style JSON" value={styleUrl} />
|
<CopyBlock label="Style JSON" value={styleUrl} />
|
||||||
|
<CopyBlock
|
||||||
|
label="Несколько округов"
|
||||||
|
value={`${origin}/u/${slug}/styles/osm-bright?source=${sources.map((item) => item.id).join(",") || "central-fed-district,volga-fed-district"}${token ? `&token=${token}` : "&token=ts_…"}`}
|
||||||
|
/>
|
||||||
<CopyBlock label="Тайлы MVT" value={tilesUrl} />
|
<CopyBlock label="Тайлы MVT" value={tilesUrl} />
|
||||||
|
|
||||||
<h2 className="guides__h">HTML</h2>
|
<h2 className="guides__h">HTML</h2>
|
||||||
@@ -141,7 +152,13 @@ const map = new maplibregl.Map({
|
|||||||
<p>Живая карта с вашего аккаунта. Если токена нет — сначала шаг 1.</p>
|
<p>Живая карта с вашего аккаунта. Если токена нет — сначала шаг 1.</p>
|
||||||
</div>
|
</div>
|
||||||
{user && token ? (
|
{user && token ? (
|
||||||
<StylePreview slug={user.slug} name="osm-bright" source={source} token={token} nonce={0} />
|
<StylePreview
|
||||||
|
slug={user.slug}
|
||||||
|
name="osm-bright"
|
||||||
|
source={sources.map((item) => item.id).join(",") || source}
|
||||||
|
token={token}
|
||||||
|
nonce={0}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="guide-result__empty">Нужен токен, чтобы нарисовать карту.</div>
|
<div className="guide-result__empty">Нужен токен, чтобы нарисовать карту.</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,28 +1,35 @@
|
|||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import maplibregl, { type Map as MapLibreMap, type StyleSpecification } from "maplibre-gl";
|
import maplibregl, { type Map as MapLibreMap, type StyleSpecification } from "maplibre-gl";
|
||||||
import "maplibre-gl/dist/maplibre-gl.css";
|
import "maplibre-gl/dist/maplibre-gl.css";
|
||||||
import { bindStyleForPreview, type MapStyle, type StyleEdit } from "./styleModel";
|
import {
|
||||||
|
bindStyleForPreview,
|
||||||
|
primaryLayerId,
|
||||||
|
type ExtractBinding,
|
||||||
|
type MapStyle,
|
||||||
|
type StyleEdit
|
||||||
|
} from "./styleModel";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
style: MapStyle;
|
style: MapStyle;
|
||||||
tilesUrl: string;
|
bindings: ExtractBinding[];
|
||||||
selectedLayerId: string | null;
|
selectedLayerId: string | null;
|
||||||
lastEdit: StyleEdit | null;
|
lastEdit: StyleEdit | null;
|
||||||
styleEpoch: number;
|
styleEpoch: number;
|
||||||
onSelectLayer: (layerId: string) => void;
|
onSelectLayer: (layerId: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function LiveMap({ style, tilesUrl, selectedLayerId, lastEdit, styleEpoch, onSelectLayer }: Props) {
|
export function LiveMap({ style, bindings, selectedLayerId, lastEdit, styleEpoch, onSelectLayer }: Props) {
|
||||||
const el = useRef<HTMLDivElement | null>(null);
|
const el = useRef<HTMLDivElement | null>(null);
|
||||||
const mapRef = useRef<MapLibreMap | null>(null);
|
const mapRef = useRef<MapLibreMap | null>(null);
|
||||||
|
const extras = bindings.slice(1).map((item) => item.extractId);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!el.current || !tilesUrl) {
|
if (!el.current || bindings.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const map = new maplibregl.Map({
|
const map = new maplibregl.Map({
|
||||||
container: el.current,
|
container: el.current,
|
||||||
style: bindStyleForPreview(style, tilesUrl) as StyleSpecification,
|
style: bindStyleForPreview(style, bindings) as StyleSpecification,
|
||||||
center: [37.6173, 55.7558],
|
center: [37.6173, 55.7558],
|
||||||
zoom: 11,
|
zoom: 11,
|
||||||
maxZoom: 18,
|
maxZoom: 18,
|
||||||
@@ -33,7 +40,7 @@ export function LiveMap({ style, tilesUrl, selectedLayerId, lastEdit, styleEpoch
|
|||||||
map.on("click", (event) => {
|
map.on("click", (event) => {
|
||||||
const hit = map.queryRenderedFeatures(event.point)[0];
|
const hit = map.queryRenderedFeatures(event.point)[0];
|
||||||
if (hit?.layer?.id) {
|
if (hit?.layer?.id) {
|
||||||
onSelectLayer(hit.layer.id);
|
onSelectLayer(primaryLayerId(hit.layer.id, extras));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mapRef.current = map;
|
mapRef.current = map;
|
||||||
@@ -41,25 +48,31 @@ export function LiveMap({ style, tilesUrl, selectedLayerId, lastEdit, styleEpoch
|
|||||||
map.remove();
|
map.remove();
|
||||||
mapRef.current = null;
|
mapRef.current = null;
|
||||||
};
|
};
|
||||||
// Recreate only when tiles source changes.
|
// Recreate when extract set changes.
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [tilesUrl, styleEpoch]);
|
}, [bindings.map((item) => item.extractId).join(","), styleEpoch]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const map = mapRef.current;
|
const map = mapRef.current;
|
||||||
if (!map || !lastEdit || !map.isStyleLoaded() || !map.getLayer(lastEdit.layerId)) {
|
if (!map || !lastEdit || !map.isStyleLoaded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const ids = [lastEdit.layerId, ...extras.map((id) => `${lastEdit.layerId}__${id}`)];
|
||||||
try {
|
try {
|
||||||
if (lastEdit.target === "paint") {
|
for (const layerId of ids) {
|
||||||
map.setPaintProperty(lastEdit.layerId, lastEdit.property, lastEdit.value);
|
if (!map.getLayer(layerId)) {
|
||||||
} else {
|
continue;
|
||||||
map.setLayoutProperty(lastEdit.layerId, lastEdit.property, lastEdit.value);
|
}
|
||||||
|
if (lastEdit.target === "paint") {
|
||||||
|
map.setPaintProperty(layerId, lastEdit.property, lastEdit.value);
|
||||||
|
} else {
|
||||||
|
map.setLayoutProperty(layerId, lastEdit.property, lastEdit.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
map.setStyle(bindStyleForPreview(style, tilesUrl) as StyleSpecification, { diff: true });
|
map.setStyle(bindStyleForPreview(style, bindings) as StyleSpecification, { diff: true });
|
||||||
}
|
}
|
||||||
}, [lastEdit, style, tilesUrl]);
|
}, [lastEdit, style, bindings, extras]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
isMapStyle,
|
isMapStyle,
|
||||||
tilesTemplate,
|
tilesTemplate,
|
||||||
updateLayer,
|
updateLayer,
|
||||||
|
type ExtractBinding,
|
||||||
type MapStyle,
|
type MapStyle,
|
||||||
type StyleEdit,
|
type StyleEdit,
|
||||||
type StyleLayer
|
type StyleLayer
|
||||||
@@ -22,7 +23,7 @@ export function StyleEditorPage() {
|
|||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const [style, setStyle] = useState<MapStyle | null>(null);
|
const [style, setStyle] = useState<MapStyle | null>(null);
|
||||||
const [sources, setSources] = useState<SourceItem[]>([]);
|
const [sources, setSources] = useState<SourceItem[]>([]);
|
||||||
const [source, setSource] = useState("");
|
const [selectedSourceIds, setSelectedSourceIds] = useState<string[]>([]);
|
||||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||||
const [lastEdit, setLastEdit] = useState<StyleEdit | null>(null);
|
const [lastEdit, setLastEdit] = useState<StyleEdit | null>(null);
|
||||||
const [styleEpoch, setStyleEpoch] = useState(0);
|
const [styleEpoch, setStyleEpoch] = useState(0);
|
||||||
@@ -44,7 +45,7 @@ export function StyleEditorPage() {
|
|||||||
setIsPreset(list.find((item) => item.name === name)?.isPreset ?? true);
|
setIsPreset(list.find((item) => item.name === name)?.isPreset ?? true);
|
||||||
const enabled = sourceList.filter((item) => item.enabled);
|
const enabled = sourceList.filter((item) => item.enabled);
|
||||||
setSources(enabled);
|
setSources(enabled);
|
||||||
setSource((current) => current || enabled[0]?.id || "");
|
setSelectedSourceIds((current) => (current.length > 0 ? current : enabled[0] ? [enabled[0].id] : []));
|
||||||
const first = raw.layers?.[raw.layers.length - 1]?.id ?? null;
|
const first = raw.layers?.[raw.layers.length - 1]?.id ?? null;
|
||||||
setSelectedId(first);
|
setSelectedId(first);
|
||||||
setStyleEpoch((n) => n + 1);
|
setStyleEpoch((n) => n + 1);
|
||||||
@@ -54,12 +55,15 @@ export function StyleEditorPage() {
|
|||||||
|
|
||||||
const layers = style?.layers ?? [];
|
const layers = style?.layers ?? [];
|
||||||
const selected: StyleLayer | null = layers.find((layer) => layer.id === selectedId) ?? null;
|
const selected: StyleLayer | null = layers.find((layer) => layer.id === selectedId) ?? null;
|
||||||
const tilesUrl = useMemo(() => {
|
const bindings: ExtractBinding[] = useMemo(() => {
|
||||||
if (!user || !source || !token) {
|
if (!user || !token || selectedSourceIds.length === 0) {
|
||||||
return "";
|
return [];
|
||||||
}
|
}
|
||||||
return tilesTemplate(user.slug, source, token);
|
return selectedSourceIds.map((id) => ({
|
||||||
}, [user, source, token]);
|
extractId: id,
|
||||||
|
tilesUrl: tilesTemplate(user.slug, id, token)
|
||||||
|
}));
|
||||||
|
}, [user, token, selectedSourceIds]);
|
||||||
|
|
||||||
const apply = (edit: StyleEdit) => {
|
const apply = (edit: StyleEdit) => {
|
||||||
if (!style || isPreset) {
|
if (!style || isPreset) {
|
||||||
@@ -86,22 +90,31 @@ export function StyleEditorPage() {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="style-workspace__actions">
|
<div className="style-workspace__actions">
|
||||||
<label className="style-workspace__source">
|
<fieldset className="style-workspace__sources">
|
||||||
<span>Источник</span>
|
<legend>Округа</legend>
|
||||||
<select
|
{sources.map((item) => {
|
||||||
value={source}
|
const checked = selectedSourceIds.includes(item.id);
|
||||||
onChange={(e) => {
|
return (
|
||||||
setSource(e.target.value);
|
<label key={item.id}>
|
||||||
setStyleEpoch((n) => n + 1);
|
<input
|
||||||
}}
|
type="checkbox"
|
||||||
>
|
checked={checked}
|
||||||
{sources.map((item) => (
|
onChange={() => {
|
||||||
<option key={item.id} value={item.id}>
|
setSelectedSourceIds((current) => {
|
||||||
|
if (checked) {
|
||||||
|
const next = current.filter((id) => id !== item.id);
|
||||||
|
return next.length > 0 ? next : current;
|
||||||
|
}
|
||||||
|
return [...current, item.id];
|
||||||
|
});
|
||||||
|
setStyleEpoch((n) => n + 1);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
{item.name}
|
{item.name}
|
||||||
</option>
|
</label>
|
||||||
))}
|
);
|
||||||
</select>
|
})}
|
||||||
</label>
|
</fieldset>
|
||||||
{!isPreset ? (
|
{!isPreset ? (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
@@ -165,10 +178,10 @@ export function StyleEditorPage() {
|
|||||||
onLayout={(property, value) => selected && apply({ layerId: selected.id, target: "layout", property, value })}
|
onLayout={(property, value) => selected && apply({ layerId: selected.id, target: "layout", property, value })}
|
||||||
/>
|
/>
|
||||||
<section className="style-workspace__map">
|
<section className="style-workspace__map">
|
||||||
{style && tilesUrl ? (
|
{style && bindings.length > 0 ? (
|
||||||
<LiveMap
|
<LiveMap
|
||||||
style={style}
|
style={style}
|
||||||
tilesUrl={tilesUrl}
|
bindings={bindings}
|
||||||
selectedLayerId={selectedId}
|
selectedLayerId={selectedId}
|
||||||
lastEdit={lastEdit}
|
lastEdit={lastEdit}
|
||||||
styleEpoch={styleEpoch}
|
styleEpoch={styleEpoch}
|
||||||
|
|||||||
@@ -67,6 +67,31 @@
|
|||||||
color: var(--secondary-label);
|
color: var(--secondary-label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.style-workspace__sources {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px 12px;
|
||||||
|
max-width: 28rem;
|
||||||
|
font-size: var(--text-caption1);
|
||||||
|
color: var(--secondary-label);
|
||||||
|
}
|
||||||
|
|
||||||
|
.style-workspace__sources legend {
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.style-workspace__sources label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
color: var(--label);
|
||||||
|
font-size: var(--text-footnote);
|
||||||
|
}
|
||||||
|
|
||||||
.style-workspace__source select {
|
.style-workspace__source select {
|
||||||
min-height: 34px;
|
min-height: 34px;
|
||||||
min-width: 14rem;
|
min-width: 14rem;
|
||||||
|
|||||||
@@ -35,9 +35,35 @@ export function tilesTemplate(slug: string, source: string, token: string): stri
|
|||||||
return `/u/${encodeURIComponent(slug)}/tiles/${encodeURIComponent(source)}/{z}/{x}/{y}.pbf?v=3&token=${encodeURIComponent(token)}`;
|
return `/u/${encodeURIComponent(slug)}/tiles/${encodeURIComponent(source)}/{z}/{x}/{y}.pbf?v=3&token=${encodeURIComponent(token)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function bindStyleForPreview(style: MapStyle, tilesUrl: string): MapStyle {
|
export type ExtractBinding = {
|
||||||
|
extractId: string;
|
||||||
|
tilesUrl: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
function applyVectorSource(source: Record<string, unknown>, tilesUrl: string): void {
|
||||||
|
source.type = "vector";
|
||||||
|
source.tiles = [tilesUrl];
|
||||||
|
source.scheme = "xyz";
|
||||||
|
delete source.url;
|
||||||
|
delete source.bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
function vectorKeys(style: MapStyle): string[] {
|
||||||
|
const sources = style.sources ?? {};
|
||||||
|
return Object.keys(sources).filter((key) => {
|
||||||
|
const source = sources[key];
|
||||||
|
return Boolean(source && typeof source === "object" && (source as { type?: string }).type === "vector");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function bindStyleForPreview(style: MapStyle, bindings: ExtractBinding[]): MapStyle {
|
||||||
|
if (bindings.length === 0) {
|
||||||
|
return structuredClone(style);
|
||||||
|
}
|
||||||
|
|
||||||
const next = structuredClone(style);
|
const next = structuredClone(style);
|
||||||
const sources = { ...(next.sources ?? {}) };
|
const sources = { ...(next.sources ?? {}) };
|
||||||
|
const first = bindings[0];
|
||||||
for (const key of Object.keys(sources)) {
|
for (const key of Object.keys(sources)) {
|
||||||
const source = sources[key];
|
const source = sources[key];
|
||||||
if (!source || typeof source !== "object") {
|
if (!source || typeof source !== "object") {
|
||||||
@@ -47,19 +73,49 @@ export function bindStyleForPreview(style: MapStyle, tilesUrl: string): MapStyle
|
|||||||
if (vector.type !== "vector") {
|
if (vector.type !== "vector") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
vector.tiles = [tilesUrl];
|
applyVectorSource(vector, first.tilesUrl);
|
||||||
vector.scheme = "xyz";
|
|
||||||
delete vector.url;
|
|
||||||
delete vector.bounds;
|
|
||||||
sources[key] = vector;
|
sources[key] = vector;
|
||||||
}
|
}
|
||||||
next.sources = sources;
|
next.sources = sources;
|
||||||
if (!next.glyphs) {
|
if (!next.glyphs) {
|
||||||
next.glyphs = "https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf";
|
next.glyphs = "https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const primary = vectorKeys(next);
|
||||||
|
const layers = [...(next.layers ?? [])];
|
||||||
|
for (const extra of bindings.slice(1)) {
|
||||||
|
const suffix = `__${extra.extractId}`;
|
||||||
|
for (const key of primary) {
|
||||||
|
const clone: Record<string, unknown> = { type: "vector" };
|
||||||
|
applyVectorSource(clone, extra.tilesUrl);
|
||||||
|
sources[key + suffix] = clone;
|
||||||
|
}
|
||||||
|
for (const layer of next.layers ?? []) {
|
||||||
|
if (!layer.source || !primary.includes(layer.source)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
layers.push({
|
||||||
|
...structuredClone(layer),
|
||||||
|
id: `${layer.id}${suffix}`,
|
||||||
|
source: `${layer.source}${suffix}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next.sources = sources;
|
||||||
|
next.layers = layers;
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function primaryLayerId(layerId: string, extraExtractIds: string[]): string {
|
||||||
|
for (const extractId of extraExtractIds) {
|
||||||
|
const suffix = `__${extractId}`;
|
||||||
|
if (layerId.endsWith(suffix)) {
|
||||||
|
return layerId.slice(0, -suffix.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return layerId;
|
||||||
|
}
|
||||||
|
|
||||||
export function updateLayer(style: MapStyle, edit: StyleEdit): MapStyle {
|
export function updateLayer(style: MapStyle, edit: StyleEdit): MapStyle {
|
||||||
const next = structuredClone(style);
|
const next = structuredClone(style);
|
||||||
const layer = next.layers?.find((item) => item.id === edit.layerId);
|
const layer = next.layers?.find((item) => item.id === edit.layerId);
|
||||||
|
|||||||
Reference in New Issue
Block a user