zenit-sdk 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-OOK4DBG5.mjs → chunk-URDEEWUZ.mjs} +330 -16
- package/dist/chunk-URDEEWUZ.mjs.map +1 -0
- package/dist/{index-DvcYGhqj.d.mts → index-BSljZaYk.d.mts} +13 -0
- package/dist/{index-DvcYGhqj.d.ts → index-BSljZaYk.d.ts} +13 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +333 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10 -5
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +324 -10
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-OOK4DBG5.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/react/ZenitMap.tsx
|
|
2
|
-
import React4, { useCallback as useCallback2, useEffect as useEffect5, useImperativeHandle, useMemo as useMemo2, useState as useState2, forwardRef } from "react";
|
|
2
|
+
import React4, { useCallback as useCallback2, useEffect as useEffect5, useImperativeHandle, useMemo as useMemo2, useRef as useRef5, useState as useState2, forwardRef } from "react";
|
|
3
3
|
import { MapContainer, Marker as Marker2, TileLayer, ZoomControl } from "react-leaflet";
|
|
4
4
|
import L4 from "leaflet";
|
|
5
5
|
|
|
@@ -251,6 +251,26 @@ import { GeoJSON } from "react-leaflet";
|
|
|
251
251
|
import L from "leaflet";
|
|
252
252
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
253
253
|
var POINT_GEOMETRY_TYPES = /* @__PURE__ */ new Set(["Point", "MultiPoint"]);
|
|
254
|
+
function normalizeBboxFromData(data) {
|
|
255
|
+
const bboxCandidate = data.bbox;
|
|
256
|
+
if (!Array.isArray(bboxCandidate) || bboxCandidate.length < 4) return null;
|
|
257
|
+
const [minLon, minLat, maxLon, maxLat] = bboxCandidate;
|
|
258
|
+
const values = [minLon, minLat, maxLon, maxLat].map((value) => Number(value));
|
|
259
|
+
if (values.every((value) => Number.isFinite(value))) {
|
|
260
|
+
return values;
|
|
261
|
+
}
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
function buildIdsSample(features) {
|
|
265
|
+
return features.slice(0, 10).map((feature) => {
|
|
266
|
+
const typedFeature = feature;
|
|
267
|
+
if (typedFeature.id !== void 0 && typedFeature.id !== null) {
|
|
268
|
+
return String(typedFeature.id);
|
|
269
|
+
}
|
|
270
|
+
const featureId = typedFeature.properties?.featureId;
|
|
271
|
+
return featureId !== void 0 && featureId !== null ? String(featureId) : "";
|
|
272
|
+
}).join(",");
|
|
273
|
+
}
|
|
254
274
|
function getGeometryType(feature) {
|
|
255
275
|
const t = feature?.geometry?.type;
|
|
256
276
|
return typeof t === "string" ? t : null;
|
|
@@ -286,6 +306,18 @@ var LayerGeoJson = ({
|
|
|
286
306
|
const features = data.features ?? [];
|
|
287
307
|
const fillFeatures = features.filter(isNonPointGeometry);
|
|
288
308
|
const pointFeatures = features.filter(isPointGeometry);
|
|
309
|
+
const dataVersionRef = useRef(0);
|
|
310
|
+
const prevSignatureRef = useRef("");
|
|
311
|
+
const firstId = features.length > 0 ? String(features[0]?.id ?? "") : "";
|
|
312
|
+
const lastId = features.length > 0 ? String(features[features.length - 1]?.id ?? "") : "";
|
|
313
|
+
const bbox = normalizeBboxFromData(data);
|
|
314
|
+
const idsSample = buildIdsSample(features);
|
|
315
|
+
const signature = bbox ? `${layerId}|${features.length}|${firstId}|${lastId}|${idsSample}|${bbox[0]}|${bbox[1]}|${bbox[2]}|${bbox[3]}` : `${layerId}|${features.length}|${firstId}|${lastId}|${idsSample}`;
|
|
316
|
+
const signatureToken = signature.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
317
|
+
if (prevSignatureRef.current !== signature) {
|
|
318
|
+
dataVersionRef.current += 1;
|
|
319
|
+
prevSignatureRef.current = signature;
|
|
320
|
+
}
|
|
289
321
|
const fillData = fillFeatures.length > 0 ? buildFeatureCollection(fillFeatures) : null;
|
|
290
322
|
const pointsData = pointFeatures.length > 0 ? buildFeatureCollection(pointFeatures) : null;
|
|
291
323
|
const clusterLayerRef = useRef(null);
|
|
@@ -338,7 +370,7 @@ var LayerGeoJson = ({
|
|
|
338
370
|
onPolygonLabel?.(feature, layer);
|
|
339
371
|
}
|
|
340
372
|
},
|
|
341
|
-
`fill-${layerId}`
|
|
373
|
+
`fill-${layerId}-${signatureToken}-v${dataVersionRef.current}`
|
|
342
374
|
),
|
|
343
375
|
pointsData && !canCluster && /* @__PURE__ */ jsx(
|
|
344
376
|
GeoJSON,
|
|
@@ -351,7 +383,7 @@ var LayerGeoJson = ({
|
|
|
351
383
|
}),
|
|
352
384
|
onEachFeature
|
|
353
385
|
},
|
|
354
|
-
`points-${layerId}`
|
|
386
|
+
`points-${layerId}-${signatureToken}-v${dataVersionRef.current}`
|
|
355
387
|
)
|
|
356
388
|
] });
|
|
357
389
|
};
|
|
@@ -911,6 +943,18 @@ var LocationControl = ({ position = "bottomleft", zoom = 16 }) => {
|
|
|
911
943
|
// src/react/map/map-handlers.tsx
|
|
912
944
|
import { useEffect as useEffect4, useRef as useRef4 } from "react";
|
|
913
945
|
import { useMap as useMap2 } from "react-leaflet";
|
|
946
|
+
var MapInvalidator = ({ trigger }) => {
|
|
947
|
+
const map = useMap2();
|
|
948
|
+
const lastTrigger = useRef4(void 0);
|
|
949
|
+
useEffect4(() => {
|
|
950
|
+
if (lastTrigger.current === trigger) return;
|
|
951
|
+
lastTrigger.current = trigger;
|
|
952
|
+
requestAnimationFrame(() => {
|
|
953
|
+
map.invalidateSize();
|
|
954
|
+
});
|
|
955
|
+
}, [map, trigger]);
|
|
956
|
+
return null;
|
|
957
|
+
};
|
|
914
958
|
function computeBBoxFromGeojson(geojson) {
|
|
915
959
|
if (!geojson || !Array.isArray(geojson.features)) return null;
|
|
916
960
|
const coords = [];
|
|
@@ -1139,6 +1183,8 @@ var ZenitMap = forwardRef(({
|
|
|
1139
1183
|
const [loadingMap, setLoadingMap] = useState2(false);
|
|
1140
1184
|
const [mapError, setMapError] = useState2(null);
|
|
1141
1185
|
const [mapInstance, setMapInstance] = useState2(null);
|
|
1186
|
+
const [layerGeojsonOverrides, setLayerGeojsonOverrides] = useState2({});
|
|
1187
|
+
const originalGeojsonByLayerIdRef = useRef5({});
|
|
1142
1188
|
const [panesReady, setPanesReady] = useState2(false);
|
|
1143
1189
|
const [currentZoom, setCurrentZoom] = useState2(initialZoom ?? DEFAULT_ZOOM);
|
|
1144
1190
|
const [isPopupOpen, setIsPopupOpen] = useState2(false);
|
|
@@ -1424,13 +1470,27 @@ var ZenitMap = forwardRef(({
|
|
|
1424
1470
|
useEffect5(() => {
|
|
1425
1471
|
setCurrentZoom(zoom);
|
|
1426
1472
|
}, [zoom]);
|
|
1473
|
+
useEffect5(() => {
|
|
1474
|
+
if (!layerGeojson) return;
|
|
1475
|
+
layers.forEach((layer) => {
|
|
1476
|
+
const layerKey = String(layer.mapLayer.layerId);
|
|
1477
|
+
const incoming = layerGeojson[layer.mapLayer.layerId] ?? layerGeojson[layerKey] ?? null;
|
|
1478
|
+
if (incoming && !originalGeojsonByLayerIdRef.current[layerKey]) {
|
|
1479
|
+
originalGeojsonByLayerIdRef.current[layerKey] = incoming;
|
|
1480
|
+
}
|
|
1481
|
+
});
|
|
1482
|
+
}, [layerGeojson, layers]);
|
|
1427
1483
|
const decoratedLayers = useMemo2(() => {
|
|
1428
|
-
return layers.map((layer) =>
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1484
|
+
return layers.map((layer) => {
|
|
1485
|
+
const layerKey = String(layer.mapLayer.layerId);
|
|
1486
|
+
const override = layerGeojsonOverrides[layerKey];
|
|
1487
|
+
return {
|
|
1488
|
+
...layer,
|
|
1489
|
+
effective: effectiveStates.find((state) => state.layerId === layer.mapLayer.layerId),
|
|
1490
|
+
data: override ?? layerGeojson?.[layer.mapLayer.layerId] ?? layerGeojson?.[layerKey] ?? null
|
|
1491
|
+
};
|
|
1492
|
+
});
|
|
1493
|
+
}, [effectiveStates, layerGeojson, layerGeojsonOverrides, layers]);
|
|
1434
1494
|
const orderedLayers = useMemo2(() => {
|
|
1435
1495
|
return [...decoratedLayers].filter((layer) => layer.effective?.visible && layer.data).sort((a, b) => a.displayOrder - b.displayOrder);
|
|
1436
1496
|
}, [decoratedLayers]);
|
|
@@ -1659,6 +1719,24 @@ var ZenitMap = forwardRef(({
|
|
|
1659
1719
|
};
|
|
1660
1720
|
mapInstance.fitBounds(bounds, fitOptions);
|
|
1661
1721
|
},
|
|
1722
|
+
fitToBbox: (bbox, padding) => {
|
|
1723
|
+
if (!mapInstance) return;
|
|
1724
|
+
if (typeof bbox.minLat !== "number" || typeof bbox.minLon !== "number" || typeof bbox.maxLat !== "number" || typeof bbox.maxLon !== "number" || !Number.isFinite(bbox.minLat) || !Number.isFinite(bbox.minLon) || !Number.isFinite(bbox.maxLat) || !Number.isFinite(bbox.maxLon)) {
|
|
1725
|
+
console.warn("[ZenitMap.fitToBbox] Invalid bbox", bbox);
|
|
1726
|
+
return;
|
|
1727
|
+
}
|
|
1728
|
+
const resolvedPadding = padding ?? (isMobile ? 40 : 24);
|
|
1729
|
+
const bounds = L4.latLngBounds([bbox.minLat, bbox.minLon], [bbox.maxLat, bbox.maxLon]);
|
|
1730
|
+
mapInstance.fitBounds(bounds, { padding: [resolvedPadding, resolvedPadding], animate: true });
|
|
1731
|
+
},
|
|
1732
|
+
fitToGeoJson: (fc, padding) => {
|
|
1733
|
+
if (!mapInstance) return;
|
|
1734
|
+
if (!fc?.features?.length) return;
|
|
1735
|
+
const bounds = L4.geoJSON(fc).getBounds();
|
|
1736
|
+
if (!bounds.isValid()) return;
|
|
1737
|
+
const resolvedPadding = padding ?? (isMobile ? 40 : 24);
|
|
1738
|
+
mapInstance.fitBounds(bounds, { padding: [resolvedPadding, resolvedPadding], animate: true });
|
|
1739
|
+
},
|
|
1662
1740
|
setView: (coordinates, zoom2) => {
|
|
1663
1741
|
if (!mapInstance) return;
|
|
1664
1742
|
mapInstance.setView([coordinates.lat, coordinates.lon], zoom2 ?? mapInstance.getZoom(), {
|
|
@@ -1683,8 +1761,25 @@ var ZenitMap = forwardRef(({
|
|
|
1683
1761
|
highlightFeature: (layerId, featureId) => {
|
|
1684
1762
|
upsertUiOverride(layerId, { overrideVisible: true, overrideOpacity: 1 });
|
|
1685
1763
|
},
|
|
1764
|
+
updateLayerGeoJson: (layerId, featureCollection) => {
|
|
1765
|
+
const layerKey = String(layerId);
|
|
1766
|
+
setLayerGeojsonOverrides((prev) => ({ ...prev, [layerKey]: featureCollection }));
|
|
1767
|
+
},
|
|
1768
|
+
restoreLayerGeoJson: (layerId) => {
|
|
1769
|
+
const layerKey = String(layerId);
|
|
1770
|
+
const original = originalGeojsonByLayerIdRef.current[layerKey];
|
|
1771
|
+
setLayerGeojsonOverrides((prev) => {
|
|
1772
|
+
const next = { ...prev };
|
|
1773
|
+
if (original) {
|
|
1774
|
+
next[layerKey] = original;
|
|
1775
|
+
} else {
|
|
1776
|
+
delete next[layerKey];
|
|
1777
|
+
}
|
|
1778
|
+
return next;
|
|
1779
|
+
});
|
|
1780
|
+
},
|
|
1686
1781
|
getMapInstance: () => mapInstance
|
|
1687
|
-
}), [effectiveStates, mapInstance]);
|
|
1782
|
+
}), [effectiveStates, isMobile, mapInstance]);
|
|
1688
1783
|
if (loadingMap) {
|
|
1689
1784
|
return /* @__PURE__ */ jsx3("div", { style: { padding: 16, height, width }, children: "Cargando mapa..." });
|
|
1690
1785
|
}
|
|
@@ -1737,6 +1832,7 @@ var ZenitMap = forwardRef(({
|
|
|
1737
1832
|
),
|
|
1738
1833
|
/* @__PURE__ */ jsx3(ZoomControl, { position: "topright" }),
|
|
1739
1834
|
/* @__PURE__ */ jsx3(MapInstanceBridge, { onReady: handleMapReady }),
|
|
1835
|
+
/* @__PURE__ */ jsx3(MapInvalidator, { trigger: mapId }),
|
|
1740
1836
|
/* @__PURE__ */ jsx3(
|
|
1741
1837
|
BBoxZoomHandler,
|
|
1742
1838
|
{
|
|
@@ -1916,7 +2012,7 @@ import React5, { useEffect as useEffect6, useMemo as useMemo3, useRef as useRef6
|
|
|
1916
2012
|
import { Eye, EyeOff, ChevronLeft, ChevronRight, Layers, Upload, X, ZoomIn } from "lucide-react";
|
|
1917
2013
|
|
|
1918
2014
|
// src/react/ZenitLayerManager.tsx
|
|
1919
|
-
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2015
|
+
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1920
2016
|
var FLOAT_TOLERANCE = 1e-3;
|
|
1921
2017
|
function areEffectiveStatesEqual(a, b) {
|
|
1922
2018
|
if (a.length !== b.length) return false;
|
|
@@ -1954,7 +2050,9 @@ var ZenitLayerManager = ({
|
|
|
1954
2050
|
showUploadTab = true,
|
|
1955
2051
|
showLayerVisibilityIcon = true,
|
|
1956
2052
|
layerFeatureCounts,
|
|
1957
|
-
mapLayers
|
|
2053
|
+
mapLayers,
|
|
2054
|
+
onApplyLayerFilter,
|
|
2055
|
+
onClearLayerFilter
|
|
1958
2056
|
}) => {
|
|
1959
2057
|
const [map, setMap] = useState3(null);
|
|
1960
2058
|
const [loadingMap, setLoadingMap] = useState3(false);
|
|
@@ -1962,6 +2060,15 @@ var ZenitLayerManager = ({
|
|
|
1962
2060
|
const [layers, setLayers] = useState3([]);
|
|
1963
2061
|
const [activeTab, setActiveTab] = useState3("layers");
|
|
1964
2062
|
const [panelVisible, setPanelVisible] = useState3(true);
|
|
2063
|
+
const [selectedFilterLayerId, setSelectedFilterLayerId] = useState3("");
|
|
2064
|
+
const [selectedFilterField, setSelectedFilterField] = useState3("");
|
|
2065
|
+
const [selectedFilterValue, setSelectedFilterValue] = useState3("");
|
|
2066
|
+
const [catalogByLayerField, setCatalogByLayerField] = useState3({});
|
|
2067
|
+
const [loadingCatalog, setLoadingCatalog] = useState3(false);
|
|
2068
|
+
const [applyingFilter, setApplyingFilter] = useState3(false);
|
|
2069
|
+
const [filterError, setFilterError] = useState3(null);
|
|
2070
|
+
const [appliedFilter, setAppliedFilter] = useState3(null);
|
|
2071
|
+
const catalogAbortRef = useRef6(null);
|
|
1965
2072
|
const lastEmittedStatesRef = useRef6(null);
|
|
1966
2073
|
const isControlled = Array.isArray(layerStates) && typeof onLayerStatesChange === "function";
|
|
1967
2074
|
const baseStates = useMemo3(
|
|
@@ -2155,6 +2262,139 @@ var ZenitLayerManager = ({
|
|
|
2155
2262
|
return String(a.mapLayer.layerId).localeCompare(String(b.mapLayer.layerId));
|
|
2156
2263
|
});
|
|
2157
2264
|
}, [effectiveStates, layers, resolveFeatureCount]);
|
|
2265
|
+
const filterableLayers = useMemo3(() => {
|
|
2266
|
+
return decoratedLayers.filter((entry) => {
|
|
2267
|
+
const prefilters = entry.mapLayer.layerConfig?.prefilters;
|
|
2268
|
+
return !!prefilters && Object.keys(prefilters).length > 0;
|
|
2269
|
+
});
|
|
2270
|
+
}, [decoratedLayers]);
|
|
2271
|
+
const selectedFilterLayer = useMemo3(
|
|
2272
|
+
() => filterableLayers.find((layer) => String(layer.mapLayer.layerId) === selectedFilterLayerId) ?? null,
|
|
2273
|
+
[filterableLayers, selectedFilterLayerId]
|
|
2274
|
+
);
|
|
2275
|
+
const filterFields = useMemo3(() => {
|
|
2276
|
+
const prefilters = selectedFilterLayer?.mapLayer.layerConfig?.prefilters;
|
|
2277
|
+
return prefilters ? Object.keys(prefilters) : [];
|
|
2278
|
+
}, [selectedFilterLayer]);
|
|
2279
|
+
const activeCatalogKey = selectedFilterLayer ? `${selectedFilterLayer.mapLayer.layerId}:${selectedFilterField}` : null;
|
|
2280
|
+
const activeCatalogValues = activeCatalogKey ? catalogByLayerField[activeCatalogKey] ?? [] : [];
|
|
2281
|
+
const extractCatalogValues = React5.useCallback((catalogData, field) => {
|
|
2282
|
+
const values = /* @__PURE__ */ new Set();
|
|
2283
|
+
const pushValue = (value) => {
|
|
2284
|
+
if (value === null || value === void 0) return;
|
|
2285
|
+
const normalized = String(value).trim();
|
|
2286
|
+
if (normalized) values.add(normalized);
|
|
2287
|
+
};
|
|
2288
|
+
if (catalogData && typeof catalogData === "object") {
|
|
2289
|
+
const maybeRecord = catalogData;
|
|
2290
|
+
const directField = maybeRecord[field];
|
|
2291
|
+
if (Array.isArray(directField)) {
|
|
2292
|
+
directField.forEach(pushValue);
|
|
2293
|
+
}
|
|
2294
|
+
const items = maybeRecord.items;
|
|
2295
|
+
if (Array.isArray(items)) {
|
|
2296
|
+
items.forEach((item) => {
|
|
2297
|
+
if (!item || typeof item !== "object") return;
|
|
2298
|
+
const row = item;
|
|
2299
|
+
const rowField = row.field;
|
|
2300
|
+
if (String(rowField ?? "").toUpperCase() === field.toUpperCase() && Array.isArray(row.values)) {
|
|
2301
|
+
row.values.forEach(pushValue);
|
|
2302
|
+
}
|
|
2303
|
+
});
|
|
2304
|
+
}
|
|
2305
|
+
const features = maybeRecord.features;
|
|
2306
|
+
if (Array.isArray(features)) {
|
|
2307
|
+
features.forEach((feature) => {
|
|
2308
|
+
if (!feature || typeof feature !== "object") return;
|
|
2309
|
+
const properties = feature.properties;
|
|
2310
|
+
if (properties && field in properties) {
|
|
2311
|
+
pushValue(properties[field]);
|
|
2312
|
+
}
|
|
2313
|
+
});
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
return [...values].sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
|
|
2317
|
+
}, []);
|
|
2318
|
+
useEffect6(() => {
|
|
2319
|
+
if (!filterableLayers.length) {
|
|
2320
|
+
setSelectedFilterLayerId("");
|
|
2321
|
+
return;
|
|
2322
|
+
}
|
|
2323
|
+
if (!selectedFilterLayerId || !filterableLayers.some((layer) => String(layer.mapLayer.layerId) === selectedFilterLayerId)) {
|
|
2324
|
+
setSelectedFilterLayerId(String(filterableLayers[0].mapLayer.layerId));
|
|
2325
|
+
}
|
|
2326
|
+
}, [filterableLayers, selectedFilterLayerId]);
|
|
2327
|
+
useEffect6(() => {
|
|
2328
|
+
if (!filterFields.length) {
|
|
2329
|
+
setSelectedFilterField("");
|
|
2330
|
+
return;
|
|
2331
|
+
}
|
|
2332
|
+
if (!selectedFilterField || !filterFields.includes(selectedFilterField)) {
|
|
2333
|
+
setSelectedFilterField(filterFields[0]);
|
|
2334
|
+
setSelectedFilterValue("");
|
|
2335
|
+
}
|
|
2336
|
+
}, [filterFields, selectedFilterField]);
|
|
2337
|
+
useEffect6(() => {
|
|
2338
|
+
if (activeTab !== "filters") return;
|
|
2339
|
+
if (!selectedFilterLayer || !selectedFilterField || !activeCatalogKey) return;
|
|
2340
|
+
if (catalogByLayerField[activeCatalogKey]) return;
|
|
2341
|
+
catalogAbortRef.current?.abort();
|
|
2342
|
+
const controller = new AbortController();
|
|
2343
|
+
catalogAbortRef.current = controller;
|
|
2344
|
+
setLoadingCatalog(true);
|
|
2345
|
+
setFilterError(null);
|
|
2346
|
+
client.layers.getLayerFeaturesCatalog(selectedFilterLayer.mapLayer.layerId).then((response) => {
|
|
2347
|
+
if (controller.signal.aborted) return;
|
|
2348
|
+
const values = extractCatalogValues(response.data, selectedFilterField);
|
|
2349
|
+
setCatalogByLayerField((prev) => ({ ...prev, [activeCatalogKey]: values }));
|
|
2350
|
+
}).catch((error) => {
|
|
2351
|
+
if (controller.signal.aborted) return;
|
|
2352
|
+
const message = error instanceof Error ? error.message : "No se pudo cargar el cat\xE1logo";
|
|
2353
|
+
setFilterError(message);
|
|
2354
|
+
}).finally(() => {
|
|
2355
|
+
if (!controller.signal.aborted) setLoadingCatalog(false);
|
|
2356
|
+
});
|
|
2357
|
+
return () => {
|
|
2358
|
+
controller.abort();
|
|
2359
|
+
};
|
|
2360
|
+
}, [activeCatalogKey, activeTab, catalogByLayerField, client.layers, extractCatalogValues, selectedFilterField, selectedFilterLayer]);
|
|
2361
|
+
const handleApplyFilter = React5.useCallback(async () => {
|
|
2362
|
+
if (!selectedFilterLayer || !selectedFilterField || !selectedFilterValue || !onApplyLayerFilter) return;
|
|
2363
|
+
setApplyingFilter(true);
|
|
2364
|
+
setFilterError(null);
|
|
2365
|
+
try {
|
|
2366
|
+
await onApplyLayerFilter({
|
|
2367
|
+
layerId: selectedFilterLayer.mapLayer.layerId,
|
|
2368
|
+
field: selectedFilterField,
|
|
2369
|
+
value: selectedFilterValue
|
|
2370
|
+
});
|
|
2371
|
+
setAppliedFilter({
|
|
2372
|
+
layerId: selectedFilterLayer.mapLayer.layerId,
|
|
2373
|
+
field: selectedFilterField,
|
|
2374
|
+
value: selectedFilterValue
|
|
2375
|
+
});
|
|
2376
|
+
} catch (error) {
|
|
2377
|
+
const message = error instanceof Error ? error.message : "No se pudo aplicar el filtro";
|
|
2378
|
+
setFilterError(message);
|
|
2379
|
+
} finally {
|
|
2380
|
+
setApplyingFilter(false);
|
|
2381
|
+
}
|
|
2382
|
+
}, [onApplyLayerFilter, selectedFilterField, selectedFilterLayer, selectedFilterValue]);
|
|
2383
|
+
const handleClearFilter = React5.useCallback(async () => {
|
|
2384
|
+
if (!selectedFilterLayer) return;
|
|
2385
|
+
setApplyingFilter(true);
|
|
2386
|
+
setFilterError(null);
|
|
2387
|
+
try {
|
|
2388
|
+
await onClearLayerFilter?.({ layerId: selectedFilterLayer.mapLayer.layerId, field: selectedFilterField || void 0 });
|
|
2389
|
+
setSelectedFilterValue("");
|
|
2390
|
+
setAppliedFilter(null);
|
|
2391
|
+
} catch (error) {
|
|
2392
|
+
const message = error instanceof Error ? error.message : "No se pudo limpiar el filtro";
|
|
2393
|
+
setFilterError(message);
|
|
2394
|
+
} finally {
|
|
2395
|
+
setApplyingFilter(false);
|
|
2396
|
+
}
|
|
2397
|
+
}, [onClearLayerFilter, selectedFilterField, selectedFilterLayer]);
|
|
2158
2398
|
const resolveLayerStyle = React5.useCallback(
|
|
2159
2399
|
(layerId) => {
|
|
2160
2400
|
const layerKey = String(layerId);
|
|
@@ -2493,6 +2733,18 @@ var ZenitLayerManager = ({
|
|
|
2493
2733
|
"Subir"
|
|
2494
2734
|
]
|
|
2495
2735
|
}
|
|
2736
|
+
),
|
|
2737
|
+
/* @__PURE__ */ jsxs4(
|
|
2738
|
+
"button",
|
|
2739
|
+
{
|
|
2740
|
+
type: "button",
|
|
2741
|
+
className: `zlm-tab${activeTab === "filters" ? " is-active" : ""}`,
|
|
2742
|
+
onClick: () => setActiveTab("filters"),
|
|
2743
|
+
children: [
|
|
2744
|
+
/* @__PURE__ */ jsx4(Layers, { size: 16 }),
|
|
2745
|
+
"Filtros"
|
|
2746
|
+
]
|
|
2747
|
+
}
|
|
2496
2748
|
)
|
|
2497
2749
|
]
|
|
2498
2750
|
}
|
|
@@ -2500,6 +2752,68 @@ var ZenitLayerManager = ({
|
|
|
2500
2752
|
] }),
|
|
2501
2753
|
panelVisible && /* @__PURE__ */ jsxs4("div", { style: { padding: "12px 10px 18px", overflowY: "auto", flex: 1, minHeight: 0 }, children: [
|
|
2502
2754
|
activeTab === "layers" && renderLayerCards(),
|
|
2755
|
+
activeTab === "filters" && /* @__PURE__ */ jsx4("div", { className: "zlm-filter-panel", style: { display: "flex", flexDirection: "column", gap: 10, background: "#fff", border: "1px solid #e2e8f0", borderRadius: 12, padding: 12 }, children: !filterableLayers.length ? /* @__PURE__ */ jsx4("div", { style: { color: "#64748b", fontSize: 13 }, children: "No hay filtros disponibles para las capas de este mapa." }) : /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
2756
|
+
filterableLayers.length > 1 && /* @__PURE__ */ jsxs4("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
|
|
2757
|
+
"Capa",
|
|
2758
|
+
/* @__PURE__ */ jsx4("select", { className: "zlm-filter-select", value: selectedFilterLayerId, onChange: (e) => setSelectedFilterLayerId(e.target.value), children: filterableLayers.map((layer) => /* @__PURE__ */ jsx4("option", { value: String(layer.mapLayer.layerId), children: layer.layerName ?? `Capa ${layer.mapLayer.layerId}` }, String(layer.mapLayer.layerId))) })
|
|
2759
|
+
] }),
|
|
2760
|
+
/* @__PURE__ */ jsxs4("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
|
|
2761
|
+
"Campo",
|
|
2762
|
+
/* @__PURE__ */ jsx4("select", { className: "zlm-filter-select", value: selectedFilterField, onChange: (e) => {
|
|
2763
|
+
setSelectedFilterField(e.target.value);
|
|
2764
|
+
setSelectedFilterValue("");
|
|
2765
|
+
}, children: filterFields.map((field) => /* @__PURE__ */ jsx4("option", { value: field, children: field }, field)) })
|
|
2766
|
+
] }),
|
|
2767
|
+
/* @__PURE__ */ jsxs4("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
|
|
2768
|
+
"Valor",
|
|
2769
|
+
/* @__PURE__ */ jsxs4(
|
|
2770
|
+
"select",
|
|
2771
|
+
{
|
|
2772
|
+
className: "zlm-filter-select",
|
|
2773
|
+
value: selectedFilterValue,
|
|
2774
|
+
onChange: (e) => {
|
|
2775
|
+
const value = e.target.value;
|
|
2776
|
+
setSelectedFilterValue(value);
|
|
2777
|
+
},
|
|
2778
|
+
children: [
|
|
2779
|
+
/* @__PURE__ */ jsx4("option", { value: "", children: "Seleccionar\u2026" }),
|
|
2780
|
+
activeCatalogValues.map((value) => /* @__PURE__ */ jsx4("option", { value, children: value }, value))
|
|
2781
|
+
]
|
|
2782
|
+
}
|
|
2783
|
+
)
|
|
2784
|
+
] }),
|
|
2785
|
+
loadingCatalog && /* @__PURE__ */ jsx4("div", { style: { color: "#64748b", fontSize: 12 }, children: "Cargando cat\xE1logo\u2026" }),
|
|
2786
|
+
!loadingCatalog && selectedFilterField && activeCatalogValues.length === 0 && /* @__PURE__ */ jsx4("div", { style: { color: "#64748b", fontSize: 12 }, children: "No hay cat\xE1logo disponible para este filtro." }),
|
|
2787
|
+
filterError && /* @__PURE__ */ jsx4("div", { style: { color: "#b91c1c", fontSize: 12 }, children: filterError }),
|
|
2788
|
+
appliedFilter && /* @__PURE__ */ jsxs4("div", { className: "zlm-badge", style: { alignSelf: "flex-start" }, children: [
|
|
2789
|
+
"Activo: ",
|
|
2790
|
+
appliedFilter.field,
|
|
2791
|
+
" = ",
|
|
2792
|
+
appliedFilter.value
|
|
2793
|
+
] }),
|
|
2794
|
+
/* @__PURE__ */ jsxs4("div", { className: "zlm-filter-actions", style: { display: "flex", gap: 8 }, children: [
|
|
2795
|
+
/* @__PURE__ */ jsx4(
|
|
2796
|
+
"button",
|
|
2797
|
+
{
|
|
2798
|
+
type: "button",
|
|
2799
|
+
className: "zlm-panel-toggle",
|
|
2800
|
+
disabled: !selectedFilterValue || applyingFilter || !onApplyLayerFilter,
|
|
2801
|
+
onClick: handleApplyFilter,
|
|
2802
|
+
children: applyingFilter ? "Aplicando\u2026" : "Aplicar"
|
|
2803
|
+
}
|
|
2804
|
+
),
|
|
2805
|
+
/* @__PURE__ */ jsx4(
|
|
2806
|
+
"button",
|
|
2807
|
+
{
|
|
2808
|
+
type: "button",
|
|
2809
|
+
className: "zlm-panel-toggle",
|
|
2810
|
+
disabled: applyingFilter,
|
|
2811
|
+
onClick: handleClearFilter,
|
|
2812
|
+
children: "Limpiar"
|
|
2813
|
+
}
|
|
2814
|
+
)
|
|
2815
|
+
] })
|
|
2816
|
+
] }) }),
|
|
2503
2817
|
showUploadTab && activeTab === "upload" && /* @__PURE__ */ jsx4("div", { style: { color: "#475569", fontSize: 13 }, children: "Pr\xF3ximamente podr\xE1s subir capas desde este panel." })
|
|
2504
2818
|
] })
|
|
2505
2819
|
] });
|
|
@@ -2914,7 +3228,7 @@ var MarkdownRenderer = ({ content, className }) => {
|
|
|
2914
3228
|
};
|
|
2915
3229
|
|
|
2916
3230
|
// src/react/ai/FloatingChatBox.tsx
|
|
2917
|
-
import { Fragment as
|
|
3231
|
+
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2918
3232
|
var ChatIcon = () => /* @__PURE__ */ jsx7("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx7("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) });
|
|
2919
3233
|
var CloseIcon = () => /* @__PURE__ */ jsxs6("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2920
3234
|
/* @__PURE__ */ jsx7("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
@@ -3642,7 +3956,7 @@ var FloatingChatBox = ({
|
|
|
3642
3956
|
...styles.messageBubble,
|
|
3643
3957
|
...styles.assistantMessage
|
|
3644
3958
|
},
|
|
3645
|
-
children: streamingText ? /* @__PURE__ */ jsxs6(
|
|
3959
|
+
children: streamingText ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
3646
3960
|
/* @__PURE__ */ jsx7(MarkdownRenderer, { content: streamingText }),
|
|
3647
3961
|
/* @__PURE__ */ jsx7("span", { style: styles.cursor })
|
|
3648
3962
|
] }) : /* @__PURE__ */ jsxs6("div", { style: styles.thinkingText, children: [
|
|
@@ -3709,7 +4023,7 @@ var FloatingChatBox = ({
|
|
|
3709
4023
|
},
|
|
3710
4024
|
onClick: () => setOpen((prev) => !prev),
|
|
3711
4025
|
"aria-label": open ? "Cerrar asistente" : "Abrir asistente Zenit AI",
|
|
3712
|
-
children: open ? /* @__PURE__ */ jsx7(CloseIcon, {}) : /* @__PURE__ */ jsxs6(
|
|
4026
|
+
children: open ? /* @__PURE__ */ jsx7(CloseIcon, {}) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
3713
4027
|
/* @__PURE__ */ jsx7(ChatIcon, {}),
|
|
3714
4028
|
!isMobile && /* @__PURE__ */ jsx7("span", { children: "Asistente IA" })
|
|
3715
4029
|
] })
|
|
@@ -3760,4 +4074,4 @@ export {
|
|
|
3760
4074
|
useSendMessageStream,
|
|
3761
4075
|
FloatingChatBox
|
|
3762
4076
|
};
|
|
3763
|
-
//# sourceMappingURL=chunk-
|
|
4077
|
+
//# sourceMappingURL=chunk-URDEEWUZ.mjs.map
|