zenit-sdk 0.1.7 → 0.1.8

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.
@@ -505,6 +505,14 @@ var LayerGeoJson = ({
505
505
  onEachFeature,
506
506
  onPolygonLabel
507
507
  }) => {
508
+ const styleFnRef = (0, import_react.useRef)(styleFn);
509
+ const onEachFeatureRef = (0, import_react.useRef)(onEachFeature);
510
+ (0, import_react.useEffect)(() => {
511
+ styleFnRef.current = styleFn;
512
+ }, [styleFn]);
513
+ (0, import_react.useEffect)(() => {
514
+ onEachFeatureRef.current = onEachFeature;
515
+ }, [onEachFeature]);
508
516
  const safeData = (0, import_react.useMemo)(() => sanitizeGeoJson(data, String(layerId)), [data, layerId]);
509
517
  const features = (0, import_react.useMemo)(() => safeData.features ?? [], [safeData]);
510
518
  const fillFeatures = (0, import_react.useMemo)(() => features.filter(isNonPointGeometry), [features]);
@@ -548,14 +556,14 @@ var LayerGeoJson = ({
548
556
  if (!isValidLatLng(latlng)) {
549
557
  return createInvisibleFallbackClusterMarker();
550
558
  }
551
- const style = styleFn(feature, layerType, baseOpacity);
559
+ const style = styleFnRef.current(feature, layerType, baseOpacity);
552
560
  return import_leaflet.default.marker(latlng, {
553
561
  icon: createPointDivIcon(style, isMobile),
554
562
  pane: clusterPaneName,
555
563
  interactive: true
556
564
  });
557
565
  },
558
- onEachFeature
566
+ onEachFeature: (feature, layer) => onEachFeatureRef.current(feature, layer)
559
567
  });
560
568
  clusterLayer.addLayer(geoJsonLayer);
561
569
  return () => {
@@ -570,11 +578,9 @@ var LayerGeoJson = ({
570
578
  isMobile,
571
579
  layerType,
572
580
  mapInstance,
573
- onEachFeature,
574
581
  panesReady,
575
582
  pointsData,
576
- resolvedPointsPane,
577
- styleFn
583
+ resolvedPointsPane
578
584
  ]);
579
585
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
580
586
  fillData && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -1486,6 +1492,14 @@ function pickIntersectFeature(params) {
1486
1492
  selectedIdx: candidates.findIndex((candidate) => candidate === feature),
1487
1493
  reason
1488
1494
  });
1495
+ if (clickIntent === "point") {
1496
+ const anyPoint = candidates.find(
1497
+ (c) => isCandidateGeometryType(c, POINT_GEOMETRY_TYPES2)
1498
+ );
1499
+ if (anyPoint) {
1500
+ return getResult(anyPoint, "point:first-point-geometry");
1501
+ }
1502
+ }
1489
1503
  const sameLayer = candidates.filter(
1490
1504
  (candidate) => isLayerIdMatch(candidateLayerId(candidate), expectedLayerId)
1491
1505
  );
@@ -1922,7 +1936,7 @@ var ZenitMap = (0, import_react5.forwardRef)(({
1922
1936
  const ensureLayerPanes = (0, import_react5.useCallback)(
1923
1937
  (targetMap, targetLayers) => {
1924
1938
  const fillBaseZIndex = 400;
1925
- const pointsBaseZIndex = 700;
1939
+ const pointsBaseZIndex = 750;
1926
1940
  targetLayers.forEach((layer) => {
1927
1941
  const order = Number.isFinite(layer.displayOrder) ? layer.displayOrder : 0;
1928
1942
  const orderOffset = Math.max(0, Math.min(order, 150));
@@ -2006,7 +2020,10 @@ var ZenitMap = (0, import_react5.forwardRef)(({
2006
2020
  className: "zenit-map-tooltip"
2007
2021
  });
2008
2022
  }
2009
- layer.on("click", () => {
2023
+ layer.on("click", (e) => {
2024
+ if (clickIntent === "point") {
2025
+ import_leaflet4.default.DomEvent.stopPropagation(e);
2026
+ }
2010
2027
  if (featureInfoMode === "popup" && client && layerId !== void 0 && !extractDescriptionValue(feature?.properties) && feature?.geometry) {
2011
2028
  if (DEV_MODE2) {
2012
2029
  console.debug("[ZenitMap] click/intersect:start", {
@@ -2106,11 +2123,16 @@ var ZenitMap = (0, import_react5.forwardRef)(({
2106
2123
  properties: feature?.properties ?? void 0
2107
2124
  });
2108
2125
  }, [currentZoom, resolveLayerStyle]);
2109
- const makeStyleFnForLayer = (0, import_react5.useCallback)((layerId) => {
2110
- return (feature, layerType, baseOpacity) => {
2111
- return buildLayerStyle(layerId, baseOpacity ?? 1, feature, layerType);
2112
- };
2113
- }, [buildLayerStyle]);
2126
+ const styleFnByLayerId = (0, import_react5.useMemo)(() => {
2127
+ const next = /* @__PURE__ */ new Map();
2128
+ orderedLayers.forEach((layerState) => {
2129
+ const layerId = layerState.mapLayer.layerId;
2130
+ next.set(String(layerId), (feature, layerType, baseOpacity) => {
2131
+ return buildLayerStyle(layerId, baseOpacity ?? 1, feature, layerType);
2132
+ });
2133
+ });
2134
+ return next;
2135
+ }, [buildLayerStyle, orderedLayers]);
2114
2136
  (0, import_react5.useImperativeHandle)(ref, () => ({
2115
2137
  setLayerOpacity: (layerId, opacity) => {
2116
2138
  upsertUiOverride(layerId, { overrideOpacity: opacity });
@@ -2277,7 +2299,7 @@ var ZenitMap = (0, import_react5.forwardRef)(({
2277
2299
  fillPaneName,
2278
2300
  pointsPaneName,
2279
2301
  layerType,
2280
- styleFn: makeStyleFnForLayer(layerState.mapLayer.layerId),
2302
+ styleFn: styleFnByLayerId.get(String(layerState.mapLayer.layerId)) ?? ((feature, layerType2, baseOpacity2) => buildLayerStyle(layerState.mapLayer.layerId, baseOpacity2 ?? 1, feature, layerType2)),
2281
2303
  onEachFeature: overlayOnEachFeature,
2282
2304
  onPolygonLabel: labelKey ? (feature, layer) => {
2283
2305
  const geometryType = feature?.geometry?.type;
@@ -2421,7 +2443,7 @@ var ZenitMap = (0, import_react5.forwardRef)(({
2421
2443
  ZenitMap.displayName = "ZenitMap";
2422
2444
 
2423
2445
  // src/react/ZenitLayerManager.tsx
2424
- var import_react7 = __toESM(require("react"));
2446
+ var import_react8 = __toESM(require("react"));
2425
2447
 
2426
2448
  // src/react/icons.tsx
2427
2449
  var import_lucide_react = require("lucide-react");
@@ -2779,9 +2801,191 @@ var ZenitSelect = ({
2779
2801
  ] });
2780
2802
  };
2781
2803
 
2782
- // src/react/ZenitLayerManager.tsx
2804
+ // src/react/ui/ZenitCombobox.tsx
2805
+ var import_react7 = __toESM(require("react"));
2783
2806
  var import_jsx_runtime5 = require("react/jsx-runtime");
2807
+ var ZenitCombobox = ({
2808
+ options,
2809
+ value,
2810
+ onChange,
2811
+ placeholder = "Seleccionar\u2026",
2812
+ searchPlaceholder = "Buscar\u2026",
2813
+ disabled = false
2814
+ }) => {
2815
+ const rootRef = import_react7.default.useRef(null);
2816
+ const [isOpen, setIsOpen] = import_react7.default.useState(false);
2817
+ const [query, setQuery] = import_react7.default.useState("");
2818
+ const filteredOptions = import_react7.default.useMemo(() => {
2819
+ const normalized = query.trim().toLowerCase();
2820
+ if (!normalized) return options;
2821
+ return options.filter((option) => option.toLowerCase().includes(normalized));
2822
+ }, [options, query]);
2823
+ import_react7.default.useEffect(() => {
2824
+ if (!isOpen) return;
2825
+ const onClickOutside = (event) => {
2826
+ if (!rootRef.current?.contains(event.target)) {
2827
+ setIsOpen(false);
2828
+ }
2829
+ };
2830
+ const onEscape = (event) => {
2831
+ if (event.key === "Escape") {
2832
+ setIsOpen(false);
2833
+ }
2834
+ };
2835
+ document.addEventListener("mousedown", onClickOutside);
2836
+ document.addEventListener("keydown", onEscape);
2837
+ return () => {
2838
+ document.removeEventListener("mousedown", onClickOutside);
2839
+ document.removeEventListener("keydown", onEscape);
2840
+ };
2841
+ }, [isOpen]);
2842
+ import_react7.default.useEffect(() => {
2843
+ if (!isOpen) {
2844
+ setQuery("");
2845
+ }
2846
+ }, [isOpen]);
2847
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: rootRef, className: "zenit-combobox-root", style: { position: "relative" }, children: [
2848
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: `
2849
+ .zenit-combobox-trigger {
2850
+ width: 100%;
2851
+ min-height: 40px;
2852
+ height: 40px;
2853
+ border: 1px solid #cbd5e1;
2854
+ border-radius: 6px;
2855
+ background: #ffffff;
2856
+ color: #0f172a;
2857
+ display: inline-flex;
2858
+ align-items: center;
2859
+ padding: 0 12px;
2860
+ font-size: 14px;
2861
+ line-height: 1.25;
2862
+ cursor: pointer;
2863
+ text-align: left;
2864
+ }
2865
+ .zenit-combobox-trigger.is-placeholder {
2866
+ color: #64748b;
2867
+ }
2868
+ .zenit-combobox-trigger:disabled {
2869
+ opacity: 0.6;
2870
+ cursor: not-allowed;
2871
+ }
2872
+ .zenit-combobox-content {
2873
+ position: absolute;
2874
+ top: calc(100% + 6px);
2875
+ left: 0;
2876
+ right: 0;
2877
+ border: 1px solid #cbd5e1;
2878
+ border-radius: 6px;
2879
+ background: #ffffff;
2880
+ box-shadow: 0 10px 25px rgba(15, 23, 42, 0.18);
2881
+ padding: 8px;
2882
+ z-index: 4000;
2883
+ }
2884
+ .zenit-combobox-search {
2885
+ width: 100%;
2886
+ min-height: 36px;
2887
+ border: 1px solid #cbd5e1;
2888
+ border-radius: 6px;
2889
+ background: #ffffff;
2890
+ color: #0f172a;
2891
+ padding: 0 10px;
2892
+ font-size: 14px;
2893
+ margin-bottom: 8px;
2894
+ box-sizing: border-box;
2895
+ }
2896
+ .zenit-combobox-list {
2897
+ max-height: 220px;
2898
+ overflow-y: auto;
2899
+ }
2900
+ .zenit-combobox-item {
2901
+ width: 100%;
2902
+ border-radius: 4px;
2903
+ color: #0f172a;
2904
+ font-size: 14px;
2905
+ min-height: 34px;
2906
+ padding: 8px 10px;
2907
+ cursor: pointer;
2908
+ user-select: none;
2909
+ }
2910
+ .zenit-combobox-item:hover { background: #f1f5f9; }
2911
+ .zenit-combobox-item.is-selected { background: #e2e8f0; font-weight: 600; }
2912
+ ` }),
2913
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2914
+ "button",
2915
+ {
2916
+ type: "button",
2917
+ className: `zenit-combobox-trigger${!value ? " is-placeholder" : ""}`,
2918
+ disabled,
2919
+ onClick: () => !disabled && setIsOpen((prev) => !prev),
2920
+ children: value || placeholder
2921
+ }
2922
+ ),
2923
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "zenit-combobox-content", children: [
2924
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2925
+ "input",
2926
+ {
2927
+ className: "zenit-combobox-search",
2928
+ value: query,
2929
+ onChange: (event) => setQuery(event.target.value),
2930
+ placeholder: searchPlaceholder,
2931
+ autoFocus: true
2932
+ }
2933
+ ),
2934
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "zenit-combobox-list", children: [
2935
+ filteredOptions.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "zenit-combobox-item", style: { color: "#64748b", cursor: "default" }, children: "Sin coincidencias" }),
2936
+ filteredOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2937
+ "div",
2938
+ {
2939
+ className: `zenit-combobox-item${option === value ? " is-selected" : ""}`,
2940
+ onClick: () => {
2941
+ onChange(option);
2942
+ setIsOpen(false);
2943
+ },
2944
+ children: option
2945
+ },
2946
+ option
2947
+ ))
2948
+ ] })
2949
+ ] })
2950
+ ] });
2951
+ };
2952
+
2953
+ // src/react/ZenitLayerManager.tsx
2954
+ var import_jsx_runtime6 = require("react/jsx-runtime");
2784
2955
  var FLOAT_TOLERANCE = 1e-3;
2956
+ var CATALOG_FIELD_BLACKLIST = /* @__PURE__ */ new Set([
2957
+ "mapids",
2958
+ "mapId",
2959
+ "mapIDs",
2960
+ "mapId",
2961
+ "field",
2962
+ "Field",
2963
+ "objectid",
2964
+ "OBJECTID",
2965
+ "objectId",
2966
+ "gforms",
2967
+ "GFORMS",
2968
+ "nomina",
2969
+ "NOMINA",
2970
+ "shape_area",
2971
+ "SHAPE_AREA",
2972
+ "shape_leng",
2973
+ "SHAPE_LENG",
2974
+ "fid",
2975
+ "FID",
2976
+ "gid",
2977
+ "GID",
2978
+ "created_at",
2979
+ "updated_at",
2980
+ "created_user",
2981
+ "last_edited_user",
2982
+ "globalid",
2983
+ "GLOBALID"
2984
+ ]);
2985
+ function isFieldVisible(key) {
2986
+ return !CATALOG_FIELD_BLACKLIST.has(key) && !key.startsWith("_") && !key.startsWith("__");
2987
+ }
2988
+ var matchesWhitelist = (key, whitelist) => whitelist.some((w) => w.toUpperCase() === key.toUpperCase());
2785
2989
  function areEffectiveStatesEqual(a, b) {
2786
2990
  if (a.length !== b.length) return false;
2787
2991
  return a.every((state, index) => {
@@ -2820,26 +3024,29 @@ var ZenitLayerManager = ({
2820
3024
  layerFeatureCounts,
2821
3025
  mapLayers,
2822
3026
  onApplyLayerFilter,
2823
- onClearLayerFilter
3027
+ onClearLayerFilter,
3028
+ availableFilterLayers = [],
3029
+ filterFieldWhitelist = []
2824
3030
  }) => {
2825
- const [map, setMap] = (0, import_react7.useState)(null);
2826
- const [loadingMap, setLoadingMap] = (0, import_react7.useState)(false);
2827
- const [mapError, setMapError] = (0, import_react7.useState)(null);
2828
- const [layers, setLayers] = (0, import_react7.useState)([]);
2829
- const [activeTab, setActiveTab] = (0, import_react7.useState)("layers");
2830
- const [panelVisible, setPanelVisible] = (0, import_react7.useState)(true);
2831
- const [selectedFilterLayerId, setSelectedFilterLayerId] = (0, import_react7.useState)("");
2832
- const [selectedFilterField, setSelectedFilterField] = (0, import_react7.useState)("");
2833
- const [selectedFilterValue, setSelectedFilterValue] = (0, import_react7.useState)("");
2834
- const [catalogByLayerField, setCatalogByLayerField] = (0, import_react7.useState)({});
2835
- const [loadingCatalog, setLoadingCatalog] = (0, import_react7.useState)(false);
2836
- const [applyingFilter, setApplyingFilter] = (0, import_react7.useState)(false);
2837
- const [filterError, setFilterError] = (0, import_react7.useState)(null);
2838
- const [appliedFilter, setAppliedFilter] = (0, import_react7.useState)(null);
2839
- const catalogAbortRef = (0, import_react7.useRef)(null);
2840
- const lastEmittedStatesRef = (0, import_react7.useRef)(null);
3031
+ const [map, setMap] = (0, import_react8.useState)(null);
3032
+ const [loadingMap, setLoadingMap] = (0, import_react8.useState)(false);
3033
+ const [mapError, setMapError] = (0, import_react8.useState)(null);
3034
+ const [layers, setLayers] = (0, import_react8.useState)([]);
3035
+ const [activeTab, setActiveTab] = (0, import_react8.useState)("layers");
3036
+ const [panelVisible, setPanelVisible] = (0, import_react8.useState)(true);
3037
+ const [selectedFilterLayerId, setSelectedFilterLayerId] = (0, import_react8.useState)("");
3038
+ const [selectedFilterField, setSelectedFilterField] = (0, import_react8.useState)("");
3039
+ const [selectedFilterValue, setSelectedFilterValue] = (0, import_react8.useState)("");
3040
+ const [catalogByLayerField, setCatalogByLayerField] = (0, import_react8.useState)({});
3041
+ const [catalogFieldsByLayer, setCatalogFieldsByLayer] = (0, import_react8.useState)({});
3042
+ const [loadingCatalog, setLoadingCatalog] = (0, import_react8.useState)(false);
3043
+ const [applyingFilter, setApplyingFilter] = (0, import_react8.useState)(false);
3044
+ const [filterError, setFilterError] = (0, import_react8.useState)(null);
3045
+ const [appliedFilter, setAppliedFilter] = (0, import_react8.useState)(null);
3046
+ const catalogAbortRef = (0, import_react8.useRef)(null);
3047
+ const lastEmittedStatesRef = (0, import_react8.useRef)(null);
2841
3048
  const isControlled = Array.isArray(layerStates) && typeof onLayerStatesChange === "function";
2842
- const baseStates = (0, import_react7.useMemo)(
3049
+ const baseStates = (0, import_react8.useMemo)(
2843
3050
  () => initLayerStates(
2844
3051
  layers.map((entry) => ({
2845
3052
  ...entry.mapLayer,
@@ -2850,7 +3057,7 @@ var ZenitLayerManager = ({
2850
3057
  ),
2851
3058
  [layers]
2852
3059
  );
2853
- const overrideStates = (0, import_react7.useMemo)(
3060
+ const overrideStates = (0, import_react8.useMemo)(
2854
3061
  () => layers.map(
2855
3062
  (entry) => ({
2856
3063
  layerId: entry.mapLayer.layerId,
@@ -2860,11 +3067,11 @@ var ZenitLayerManager = ({
2860
3067
  ),
2861
3068
  [layers]
2862
3069
  );
2863
- const effectiveStates = (0, import_react7.useMemo)(
3070
+ const effectiveStates = (0, import_react8.useMemo)(
2864
3071
  () => layerStates ?? applyLayerOverrides(baseStates, overrideStates),
2865
3072
  [baseStates, layerStates, overrideStates]
2866
3073
  );
2867
- const layerMetaIndex = (0, import_react7.useMemo)(() => {
3074
+ const layerMetaIndex = (0, import_react8.useMemo)(() => {
2868
3075
  const index = /* @__PURE__ */ new Map();
2869
3076
  mapLayers?.forEach((entry) => {
2870
3077
  const key = String(entry.layerId);
@@ -2878,7 +3085,7 @@ var ZenitLayerManager = ({
2878
3085
  });
2879
3086
  return index;
2880
3087
  }, [map, mapLayers]);
2881
- const resolveUserOpacity = import_react7.default.useCallback((state) => {
3088
+ const resolveUserOpacity = import_react8.default.useCallback((state) => {
2882
3089
  if (typeof state.overrideOpacity === "number") return state.overrideOpacity;
2883
3090
  if (typeof state.overrideOpacity === "string") {
2884
3091
  const parsed = Number.parseFloat(state.overrideOpacity);
@@ -2886,7 +3093,7 @@ var ZenitLayerManager = ({
2886
3093
  }
2887
3094
  return state.opacity ?? 1;
2888
3095
  }, []);
2889
- const resolveEffectiveOpacity = import_react7.default.useCallback(
3096
+ const resolveEffectiveOpacity = import_react8.default.useCallback(
2890
3097
  (layerId, userOpacity) => {
2891
3098
  if (!autoOpacityOnZoom || typeof mapZoom !== "number") {
2892
3099
  return userOpacity;
@@ -2902,7 +3109,7 @@ var ZenitLayerManager = ({
2902
3109
  },
2903
3110
  [autoOpacityConfig, autoOpacityOnZoom, layerMetaIndex, mapZoom]
2904
3111
  );
2905
- const effectiveStatesWithZoom = (0, import_react7.useMemo)(() => {
3112
+ const effectiveStatesWithZoom = (0, import_react8.useMemo)(() => {
2906
3113
  if (!autoOpacityOnZoom || typeof mapZoom !== "number") {
2907
3114
  return effectiveStates;
2908
3115
  }
@@ -2916,7 +3123,7 @@ var ZenitLayerManager = ({
2916
3123
  };
2917
3124
  });
2918
3125
  }, [autoOpacityOnZoom, effectiveStates, mapZoom, resolveEffectiveOpacity, resolveUserOpacity]);
2919
- (0, import_react7.useEffect)(() => {
3126
+ (0, import_react8.useEffect)(() => {
2920
3127
  let cancelled = false;
2921
3128
  setLoadingMap(true);
2922
3129
  setMapError(null);
@@ -2948,12 +3155,12 @@ var ZenitLayerManager = ({
2948
3155
  cancelled = true;
2949
3156
  };
2950
3157
  }, [client.maps, mapId]);
2951
- (0, import_react7.useEffect)(() => {
3158
+ (0, import_react8.useEffect)(() => {
2952
3159
  if (!showUploadTab && activeTab === "upload") {
2953
3160
  setActiveTab("layers");
2954
3161
  }
2955
3162
  }, [activeTab, showUploadTab]);
2956
- (0, import_react7.useEffect)(() => {
3163
+ (0, import_react8.useEffect)(() => {
2957
3164
  if (isControlled) return;
2958
3165
  if (!onLayerStatesChange) return;
2959
3166
  const emitStates = autoOpacityOnZoom && typeof mapZoom === "number" ? effectiveStatesWithZoom : effectiveStates;
@@ -2971,7 +3178,7 @@ var ZenitLayerManager = ({
2971
3178
  mapZoom,
2972
3179
  onLayerStatesChange
2973
3180
  ]);
2974
- const updateLayerVisible = import_react7.default.useCallback(
3181
+ const updateLayerVisible = import_react8.default.useCallback(
2975
3182
  (layerId, visible) => {
2976
3183
  if (!onLayerStatesChange) return;
2977
3184
  const next = effectiveStates.map(
@@ -2981,7 +3188,7 @@ var ZenitLayerManager = ({
2981
3188
  },
2982
3189
  [effectiveStates, onLayerStatesChange]
2983
3190
  );
2984
- const updateLayerOpacity = import_react7.default.useCallback(
3191
+ const updateLayerOpacity = import_react8.default.useCallback(
2985
3192
  (layerId, opacity) => {
2986
3193
  if (!onLayerStatesChange) return;
2987
3194
  const adjustedOpacity = resolveEffectiveOpacity(layerId, opacity);
@@ -2992,7 +3199,7 @@ var ZenitLayerManager = ({
2992
3199
  },
2993
3200
  [effectiveStates, onLayerStatesChange, resolveEffectiveOpacity]
2994
3201
  );
2995
- const resolveFeatureCount = import_react7.default.useCallback(
3202
+ const resolveFeatureCount = import_react8.default.useCallback(
2996
3203
  (layerId, layer) => {
2997
3204
  const resolvedFeatureCount = layerFeatureCounts?.[layerId] ?? layerFeatureCounts?.[String(layerId)];
2998
3205
  if (typeof resolvedFeatureCount === "number") return resolvedFeatureCount;
@@ -3001,7 +3208,7 @@ var ZenitLayerManager = ({
3001
3208
  },
3002
3209
  [layerFeatureCounts]
3003
3210
  );
3004
- const decoratedLayers = (0, import_react7.useMemo)(() => {
3211
+ const decoratedLayers = (0, import_react8.useMemo)(() => {
3005
3212
  return layers.map((entry) => ({
3006
3213
  ...entry,
3007
3214
  effective: effectiveStates.find((state) => state.layerId === entry.mapLayer.layerId),
@@ -3030,7 +3237,7 @@ var ZenitLayerManager = ({
3030
3237
  return String(a.mapLayer.layerId).localeCompare(String(b.mapLayer.layerId));
3031
3238
  });
3032
3239
  }, [effectiveStates, layers, resolveFeatureCount]);
3033
- const hasPrefilters = (0, import_react7.useMemo)(() => {
3240
+ const hasPrefilters = (0, import_react8.useMemo)(() => {
3034
3241
  const candidates = [...mapLayers ?? [], ...map?.mapLayers ?? []];
3035
3242
  return candidates.some((layer) => {
3036
3243
  const record = layer;
@@ -3038,23 +3245,32 @@ var ZenitLayerManager = ({
3038
3245
  return !!applied && typeof applied === "object" && Object.keys(applied).length > 0;
3039
3246
  });
3040
3247
  }, [map?.mapLayers, mapLayers]);
3041
- const filterableLayers = (0, import_react7.useMemo)(() => {
3248
+ const filterableLayers = (0, import_react8.useMemo)(() => {
3249
+ const forcedLayerIds = new Set(availableFilterLayers.map((layerId) => String(layerId)));
3042
3250
  return decoratedLayers.filter((entry) => {
3043
3251
  const prefilters = entry.mapLayer.layerConfig?.prefilters;
3044
- return !!prefilters && Object.keys(prefilters).length > 0;
3252
+ if (prefilters && Object.keys(prefilters).length > 0) return true;
3253
+ if (forcedLayerIds.has(String(entry.mapLayer.layerId))) return true;
3254
+ const layerType = (entry.mapLayer.layerType ?? entry.layer?.layerType ?? "").toString().toLowerCase();
3255
+ return layerType === "multipolygon";
3045
3256
  });
3046
- }, [decoratedLayers]);
3047
- const selectedFilterLayer = (0, import_react7.useMemo)(
3257
+ }, [availableFilterLayers, decoratedLayers]);
3258
+ const selectedFilterLayer = (0, import_react8.useMemo)(
3048
3259
  () => filterableLayers.find((layer) => String(layer.mapLayer.layerId) === selectedFilterLayerId) ?? null,
3049
3260
  [filterableLayers, selectedFilterLayerId]
3050
3261
  );
3051
- const filterFields = (0, import_react7.useMemo)(() => {
3052
- const prefilters = selectedFilterLayer?.mapLayer.layerConfig?.prefilters;
3053
- return prefilters ? Object.keys(prefilters) : [];
3054
- }, [selectedFilterLayer]);
3262
+ const filterFields = (0, import_react8.useMemo)(() => {
3263
+ if (!selectedFilterLayer) return [];
3264
+ const prefilters = selectedFilterLayer.mapLayer.layerConfig?.prefilters;
3265
+ if (prefilters) {
3266
+ const keys = Object.keys(prefilters);
3267
+ if (keys.length > 0) return keys;
3268
+ }
3269
+ return catalogFieldsByLayer[String(selectedFilterLayer.mapLayer.layerId)] ?? [];
3270
+ }, [catalogFieldsByLayer, selectedFilterLayer]);
3055
3271
  const activeCatalogKey = selectedFilterLayer ? `${selectedFilterLayer.mapLayer.layerId}:${selectedFilterField}` : null;
3056
3272
  const activeCatalogValues = activeCatalogKey ? catalogByLayerField[activeCatalogKey] ?? [] : [];
3057
- const extractCatalogValues = import_react7.default.useCallback((catalogData, field) => {
3273
+ const extractCatalogValues = import_react8.default.useCallback((catalogData, field) => {
3058
3274
  const values = /* @__PURE__ */ new Set();
3059
3275
  const pushValue = (value) => {
3060
3276
  if (value === null || value === void 0) return;
@@ -3091,7 +3307,46 @@ var ZenitLayerManager = ({
3091
3307
  }
3092
3308
  return [...values].sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
3093
3309
  }, []);
3094
- (0, import_react7.useEffect)(() => {
3310
+ const extractCatalogFieldMap = import_react8.default.useCallback((catalogData, whitelist) => {
3311
+ if (!catalogData || typeof catalogData !== "object") return {};
3312
+ const maybeRecord = catalogData;
3313
+ const fieldNames = /* @__PURE__ */ new Set();
3314
+ Object.entries(maybeRecord).forEach(([key, value]) => {
3315
+ if (Array.isArray(value) && key !== "items" && key !== "features") {
3316
+ if (isFieldVisible(key)) fieldNames.add(key);
3317
+ }
3318
+ });
3319
+ const items = maybeRecord.items;
3320
+ if (Array.isArray(items)) {
3321
+ items.forEach((item) => {
3322
+ if (!item || typeof item !== "object") return;
3323
+ const row = item;
3324
+ if (row.field !== null && row.field !== void 0) {
3325
+ const fieldName = String(row.field).trim();
3326
+ if (fieldName && isFieldVisible(fieldName)) fieldNames.add(fieldName);
3327
+ }
3328
+ });
3329
+ }
3330
+ const features = maybeRecord.features;
3331
+ if (Array.isArray(features)) {
3332
+ features.forEach((feature) => {
3333
+ if (!feature || typeof feature !== "object") return;
3334
+ const properties = feature.properties;
3335
+ if (!properties || typeof properties !== "object") return;
3336
+ Object.keys(properties).forEach((key) => {
3337
+ if (isFieldVisible(key)) fieldNames.add(key);
3338
+ });
3339
+ });
3340
+ }
3341
+ const normalizedWhitelist = (whitelist ?? []).map((item) => String(item).trim()).filter(Boolean);
3342
+ const resolvedFieldNames = normalizedWhitelist.length > 0 ? [...fieldNames].filter((field) => matchesWhitelist(field, normalizedWhitelist)) : [...fieldNames];
3343
+ const next = {};
3344
+ resolvedFieldNames.forEach((field) => {
3345
+ next[field] = extractCatalogValues(catalogData, field);
3346
+ });
3347
+ return next;
3348
+ }, [extractCatalogValues]);
3349
+ (0, import_react8.useEffect)(() => {
3095
3350
  if (!filterableLayers.length) {
3096
3351
  setSelectedFilterLayerId("");
3097
3352
  return;
@@ -3100,7 +3355,7 @@ var ZenitLayerManager = ({
3100
3355
  setSelectedFilterLayerId(String(filterableLayers[0].mapLayer.layerId));
3101
3356
  }
3102
3357
  }, [filterableLayers, selectedFilterLayerId]);
3103
- (0, import_react7.useEffect)(() => {
3358
+ (0, import_react8.useEffect)(() => {
3104
3359
  if (!filterFields.length) {
3105
3360
  setSelectedFilterField("");
3106
3361
  return;
@@ -3110,24 +3365,42 @@ var ZenitLayerManager = ({
3110
3365
  setSelectedFilterValue("");
3111
3366
  }
3112
3367
  }, [filterFields, selectedFilterField]);
3113
- (0, import_react7.useEffect)(() => {
3368
+ (0, import_react8.useEffect)(() => {
3114
3369
  if (hasPrefilters && activeTab === "filters") {
3115
3370
  setActiveTab("layers");
3116
3371
  }
3117
3372
  }, [activeTab, hasPrefilters]);
3118
- (0, import_react7.useEffect)(() => {
3373
+ (0, import_react8.useEffect)(() => {
3119
3374
  if (activeTab !== "filters") return;
3120
- if (!selectedFilterLayer || !selectedFilterField || !activeCatalogKey) return;
3121
- if (catalogByLayerField[activeCatalogKey]) return;
3375
+ if (!selectedFilterLayer) return;
3376
+ const layerId = selectedFilterLayer.mapLayer.layerId;
3377
+ const layerKey = String(layerId);
3378
+ const prefilters = selectedFilterLayer.mapLayer.layerConfig?.prefilters;
3379
+ const requiresCatalogForFields = !prefilters || Object.keys(prefilters).length === 0;
3380
+ const hasFieldsLoaded = (catalogFieldsByLayer[layerKey]?.length ?? 0) > 0;
3381
+ const needsLayerCatalog = requiresCatalogForFields && !hasFieldsLoaded;
3382
+ const needsFieldCatalog = Boolean(activeCatalogKey && selectedFilterField && !catalogByLayerField[activeCatalogKey]);
3383
+ if (!needsLayerCatalog && !needsFieldCatalog) return;
3122
3384
  catalogAbortRef.current?.abort();
3123
3385
  const controller = new AbortController();
3124
3386
  catalogAbortRef.current = controller;
3125
3387
  setLoadingCatalog(true);
3126
3388
  setFilterError(null);
3127
- client.layers.getLayerFeaturesCatalog(selectedFilterLayer.mapLayer.layerId).then((response) => {
3389
+ client.layers.getLayerFeaturesCatalog(layerId).then((response) => {
3128
3390
  if (controller.signal.aborted) return;
3129
- const values = extractCatalogValues(response.data, selectedFilterField);
3130
- setCatalogByLayerField((prev) => ({ ...prev, [activeCatalogKey]: values }));
3391
+ const fieldMap = extractCatalogFieldMap(response.data, filterFieldWhitelist);
3392
+ const fields = Object.keys(fieldMap);
3393
+ setCatalogFieldsByLayer((prev) => ({ ...prev, [layerKey]: fields }));
3394
+ setCatalogByLayerField((prev) => {
3395
+ const next = { ...prev };
3396
+ fields.forEach((field) => {
3397
+ const key = `${layerKey}:${field}`;
3398
+ if (!next[key]) {
3399
+ next[key] = fieldMap[field] ?? [];
3400
+ }
3401
+ });
3402
+ return next;
3403
+ });
3131
3404
  }).catch((error) => {
3132
3405
  if (controller.signal.aborted) return;
3133
3406
  const message = error instanceof Error ? error.message : "No se pudo cargar el cat\xE1logo";
@@ -3138,8 +3411,8 @@ var ZenitLayerManager = ({
3138
3411
  return () => {
3139
3412
  controller.abort();
3140
3413
  };
3141
- }, [activeCatalogKey, activeTab, catalogByLayerField, client.layers, extractCatalogValues, selectedFilterField, selectedFilterLayer]);
3142
- const handleApplyFilter = import_react7.default.useCallback(async () => {
3414
+ }, [activeCatalogKey, activeTab, catalogByLayerField, catalogFieldsByLayer, client.layers, extractCatalogFieldMap, filterFieldWhitelist, selectedFilterField, selectedFilterLayer]);
3415
+ const handleApplyFilter = import_react8.default.useCallback(async () => {
3143
3416
  if (!selectedFilterLayer || !selectedFilterField || !selectedFilterValue || !onApplyLayerFilter) return;
3144
3417
  setApplyingFilter(true);
3145
3418
  setFilterError(null);
@@ -3161,7 +3434,7 @@ var ZenitLayerManager = ({
3161
3434
  setApplyingFilter(false);
3162
3435
  }
3163
3436
  }, [onApplyLayerFilter, selectedFilterField, selectedFilterLayer, selectedFilterValue]);
3164
- const handleClearFilter = import_react7.default.useCallback(async () => {
3437
+ const handleClearFilter = import_react8.default.useCallback(async () => {
3165
3438
  if (!selectedFilterLayer) return;
3166
3439
  setApplyingFilter(true);
3167
3440
  setFilterError(null);
@@ -3176,7 +3449,7 @@ var ZenitLayerManager = ({
3176
3449
  setApplyingFilter(false);
3177
3450
  }
3178
3451
  }, [onClearLayerFilter, selectedFilterField, selectedFilterLayer]);
3179
- const resolveLayerStyle = import_react7.default.useCallback(
3452
+ const resolveLayerStyle = import_react8.default.useCallback(
3180
3453
  (layerId) => {
3181
3454
  const layerKey = String(layerId);
3182
3455
  const fromProp = mapLayers?.find((entry) => String(entry.layerId) === layerKey)?.style;
@@ -3190,6 +3463,22 @@ var ZenitLayerManager = ({
3190
3463
  },
3191
3464
  [map, mapLayers]
3192
3465
  );
3466
+ const allVisible = decoratedLayers.every(
3467
+ (entry) => entry.effective?.visible ?? false
3468
+ );
3469
+ const anyVisible = decoratedLayers.some(
3470
+ (entry) => entry.effective?.visible ?? false
3471
+ );
3472
+ const handleToggleAllLayers = import_react8.default.useCallback(() => {
3473
+ if (!onLayerStatesChange) return;
3474
+ const nextVisible = !anyVisible;
3475
+ const next = effectiveStates.map((state) => ({
3476
+ ...state,
3477
+ visible: nextVisible,
3478
+ overrideVisible: nextVisible
3479
+ }));
3480
+ onLayerStatesChange(next);
3481
+ }, [anyVisible, effectiveStates, onLayerStatesChange]);
3193
3482
  const panelStyle = {
3194
3483
  width: 360,
3195
3484
  borderLeft: side === "right" ? "1px solid #e2e8f0" : void 0,
@@ -3206,10 +3495,10 @@ var ZenitLayerManager = ({
3206
3495
  ...height ? { height } : {}
3207
3496
  };
3208
3497
  if (loadingMap) {
3209
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className, style: panelStyle, children: "Cargando capas\u2026" });
3498
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className, style: panelStyle, children: "Cargando capas\u2026" });
3210
3499
  }
3211
3500
  if (mapError) {
3212
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className, style: { ...panelStyle, color: "#c53030" }, children: [
3501
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className, style: { ...panelStyle, color: "#c53030" }, children: [
3213
3502
  "Error al cargar mapa: ",
3214
3503
  mapError
3215
3504
  ] });
@@ -3227,7 +3516,7 @@ var ZenitLayerManager = ({
3227
3516
  boxShadow: "0 1px 0 rgba(148, 163, 184, 0.25)"
3228
3517
  };
3229
3518
  const renderLayerCards = () => {
3230
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: decoratedLayers.map((layerState) => {
3519
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: decoratedLayers.map((layerState) => {
3231
3520
  const layerId = layerState.mapLayer.layerId;
3232
3521
  const layerName = layerState.layerName ?? `Capa ${layerId}`;
3233
3522
  const visible = layerState.effective?.visible ?? false;
@@ -3237,7 +3526,7 @@ var ZenitLayerManager = ({
3237
3526
  const muted = !visible;
3238
3527
  const opacityPercent = Math.round(userOpacity * 100);
3239
3528
  const sliderBackground = `linear-gradient(to right, ${layerColor} 0%, ${layerColor} ${opacityPercent}%, #e5e7eb ${opacityPercent}%, #e5e7eb 100%)`;
3240
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3529
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3241
3530
  "div",
3242
3531
  {
3243
3532
  className: `zlm-card${muted ? " is-muted" : ""}`,
@@ -3252,9 +3541,9 @@ var ZenitLayerManager = ({
3252
3541
  width: "100%"
3253
3542
  },
3254
3543
  children: [
3255
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", gap: 12 }, children: [
3256
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", gap: 10, alignItems: "flex-start", minWidth: 0, flex: 1 }, children: [
3257
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3544
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", gap: 12 }, children: [
3545
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", gap: 10, alignItems: "flex-start", minWidth: 0, flex: 1 }, children: [
3546
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3258
3547
  "div",
3259
3548
  {
3260
3549
  style: {
@@ -3269,7 +3558,7 @@ var ZenitLayerManager = ({
3269
3558
  title: "Color de la capa"
3270
3559
  }
3271
3560
  ),
3272
- showLayerVisibilityIcon && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3561
+ showLayerVisibilityIcon && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3273
3562
  "button",
3274
3563
  {
3275
3564
  type: "button",
@@ -3280,11 +3569,11 @@ var ZenitLayerManager = ({
3280
3569
  )
3281
3570
  ),
3282
3571
  "aria-label": visible ? "Ocultar capa" : "Mostrar capa",
3283
- children: visible ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.Eye, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.EyeOff, { size: 16 })
3572
+ children: visible ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.Eye, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.EyeOff, { size: 16 })
3284
3573
  }
3285
3574
  ),
3286
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { minWidth: 0, flex: 1 }, children: [
3287
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3575
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { minWidth: 0, flex: 1 }, children: [
3576
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3288
3577
  "div",
3289
3578
  {
3290
3579
  className: "zlm-layer-name",
@@ -3302,26 +3591,26 @@ var ZenitLayerManager = ({
3302
3591
  children: layerName
3303
3592
  }
3304
3593
  ),
3305
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { color: muted ? "#94a3b8" : "#64748b", fontSize: 12 }, children: [
3594
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { color: muted ? "#94a3b8" : "#64748b", fontSize: 12 }, children: [
3306
3595
  "ID ",
3307
3596
  layerId
3308
3597
  ] })
3309
3598
  ] })
3310
3599
  ] }),
3311
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { display: "flex", alignItems: "flex-start", gap: 6, flexShrink: 0 }, children: typeof featureCount === "number" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "zlm-badge", children: [
3600
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { display: "flex", alignItems: "flex-start", gap: 6, flexShrink: 0 }, children: typeof featureCount === "number" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "zlm-badge", children: [
3312
3601
  featureCount.toLocaleString(),
3313
3602
  " features"
3314
3603
  ] }) })
3315
3604
  ] }),
3316
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { display: "flex", gap: 10, alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { flex: 1 }, children: [
3317
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 6, color: "#64748b", fontSize: 12 }, children: [
3318
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Opacidad" }),
3319
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
3605
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { display: "flex", gap: 10, alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { flex: 1 }, children: [
3606
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 6, color: "#64748b", fontSize: 12 }, children: [
3607
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Opacidad" }),
3608
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
3320
3609
  opacityPercent,
3321
3610
  "%"
3322
3611
  ] })
3323
3612
  ] }),
3324
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3613
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3325
3614
  "input",
3326
3615
  {
3327
3616
  className: "zlm-range",
@@ -3359,8 +3648,8 @@ var ZenitLayerManager = ({
3359
3648
  );
3360
3649
  }) });
3361
3650
  };
3362
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: ["zenit-layer-manager", className].filter(Boolean).join(" "), style: panelStyle, children: [
3363
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: `
3651
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: ["zenit-layer-manager", className].filter(Boolean).join(" "), style: panelStyle, children: [
3652
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `
3364
3653
  .zenit-layer-manager .zlm-card {
3365
3654
  transition: box-shadow 0.2s ease, transform 0.2s ease, opacity 0.2s ease;
3366
3655
  box-shadow: 0 6px 16px rgba(15, 23, 42, 0.08);
@@ -3455,16 +3744,16 @@ var ZenitLayerManager = ({
3455
3744
  outline-offset: 2px;
3456
3745
  }
3457
3746
  ` }),
3458
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: headerStyle, children: [
3459
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
3460
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
3461
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { fontWeight: 800, fontSize: 16, color: "#0f172a" }, children: "Gesti\xF3n de Capas" }),
3462
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { color: "#64748b", fontSize: 12 }, children: [
3747
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: headerStyle, children: [
3748
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
3749
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
3750
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontWeight: 800, fontSize: 16, color: "#0f172a" }, children: "Gesti\xF3n de Capas" }),
3751
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { color: "#64748b", fontSize: 12 }, children: [
3463
3752
  "Mapa #",
3464
3753
  map.id
3465
3754
  ] })
3466
3755
  ] }),
3467
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3756
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3468
3757
  "button",
3469
3758
  {
3470
3759
  type: "button",
@@ -3472,13 +3761,13 @@ var ZenitLayerManager = ({
3472
3761
  className: "zlm-panel-toggle",
3473
3762
  "aria-label": panelVisible ? "Ocultar panel de capas" : "Mostrar panel de capas",
3474
3763
  children: [
3475
- panelVisible ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.Eye, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.EyeOff, { size: 16 }),
3764
+ panelVisible ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.Eye, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.EyeOff, { size: 16 }),
3476
3765
  panelVisible ? "Ocultar" : "Mostrar"
3477
3766
  ]
3478
3767
  }
3479
3768
  )
3480
3769
  ] }),
3481
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3770
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3482
3771
  "div",
3483
3772
  {
3484
3773
  style: {
@@ -3491,38 +3780,38 @@ var ZenitLayerManager = ({
3491
3780
  background: "#f1f5f9"
3492
3781
  },
3493
3782
  children: [
3494
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3783
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3495
3784
  "button",
3496
3785
  {
3497
3786
  type: "button",
3498
3787
  className: `zlm-tab${activeTab === "layers" ? " is-active" : ""}`,
3499
3788
  onClick: () => setActiveTab("layers"),
3500
3789
  children: [
3501
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.Layers, { size: 16 }),
3790
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.Layers, { size: 16 }),
3502
3791
  "Capas"
3503
3792
  ]
3504
3793
  }
3505
3794
  ),
3506
- showUploadTab && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3795
+ showUploadTab && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3507
3796
  "button",
3508
3797
  {
3509
3798
  type: "button",
3510
3799
  className: `zlm-tab${activeTab === "upload" ? " is-active" : ""}`,
3511
3800
  onClick: () => setActiveTab("upload"),
3512
3801
  children: [
3513
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.Upload, { size: 16 }),
3802
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.Upload, { size: 16 }),
3514
3803
  "Subir"
3515
3804
  ]
3516
3805
  }
3517
3806
  ),
3518
- !hasPrefilters && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3807
+ !hasPrefilters && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3519
3808
  "button",
3520
3809
  {
3521
3810
  type: "button",
3522
3811
  className: `zlm-tab${activeTab === "filters" ? " is-active" : ""}`,
3523
3812
  onClick: () => setActiveTab("filters"),
3524
3813
  children: [
3525
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.Layers, { size: 16 }),
3814
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.Layers, { size: 16 }),
3526
3815
  "Filtros"
3527
3816
  ]
3528
3817
  }
@@ -3531,13 +3820,29 @@ var ZenitLayerManager = ({
3531
3820
  }
3532
3821
  )
3533
3822
  ] }),
3534
- panelVisible && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { padding: "12px 10px 18px", overflowY: "auto", flex: 1, minHeight: 0 }, children: [
3535
- hasPrefilters && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "zlm-badge", style: { marginBottom: 10 }, children: "Este mapa ya incluye filtros preaplicados" }),
3536
- activeTab === "layers" && renderLayerCards(),
3537
- !hasPrefilters && activeTab === "filters" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "zlm-filter-panel", style: { display: "flex", flexDirection: "column", gap: 12, background: "#fff", border: "1px solid #e2e8f0", borderRadius: 12, padding: 12 }, children: !filterableLayers.length ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { color: "#64748b", fontSize: 13 }, children: "No hay filtros disponibles para las capas de este mapa." }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
3538
- filterableLayers.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
3823
+ panelVisible && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { padding: "12px 10px 18px", overflowY: "auto", flex: 1, minHeight: 0 }, children: [
3824
+ hasPrefilters && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "zlm-badge", style: { marginBottom: 10 }, children: "Este mapa ya incluye filtros preaplicados" }),
3825
+ activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3826
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { marginBottom: 10 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3827
+ "button",
3828
+ {
3829
+ type: "button",
3830
+ className: "zlm-panel-toggle",
3831
+ onClick: handleToggleAllLayers,
3832
+ disabled: decoratedLayers.length === 0,
3833
+ "aria-label": anyVisible ? "Ocultar todas las capas" : "Mostrar todas las capas",
3834
+ children: [
3835
+ anyVisible ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.EyeOff, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.Eye, { size: 14 }),
3836
+ anyVisible ? "Ocultar todas" : "Mostrar todas"
3837
+ ]
3838
+ }
3839
+ ) }),
3840
+ renderLayerCards()
3841
+ ] }),
3842
+ !hasPrefilters && activeTab === "filters" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "zlm-filter-panel", style: { display: "flex", flexDirection: "column", gap: 12, background: "#fff", border: "1px solid #e2e8f0", borderRadius: 12, padding: 12 }, children: !filterableLayers.length ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { color: "#64748b", fontSize: 13 }, children: "No hay filtros disponibles para las capas de este mapa." }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3843
+ filterableLayers.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
3539
3844
  "Capa",
3540
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3845
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3541
3846
  ZenitSelect,
3542
3847
  {
3543
3848
  ariaLabel: "Seleccionar capa para filtrar",
@@ -3550,9 +3855,9 @@ var ZenitLayerManager = ({
3550
3855
  }
3551
3856
  )
3552
3857
  ] }),
3553
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
3858
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
3554
3859
  "Campo",
3555
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3860
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3556
3861
  ZenitSelect,
3557
3862
  {
3558
3863
  ariaLabel: "Seleccionar campo de filtrado",
@@ -3565,34 +3870,31 @@ var ZenitLayerManager = ({
3565
3870
  }
3566
3871
  )
3567
3872
  ] }),
3568
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
3873
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
3569
3874
  "Valor",
3570
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3571
- ZenitSelect,
3875
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3876
+ ZenitCombobox,
3572
3877
  {
3573
- ariaLabel: "Seleccionar valor de filtrado",
3574
3878
  value: selectedFilterValue,
3575
3879
  placeholder: "Seleccionar\u2026",
3576
- onValueChange: (nextValue) => setSelectedFilterValue(nextValue),
3577
- disabled: loadingCatalog || activeCatalogValues.length === 0,
3578
- options: activeCatalogValues.map((catalogValue) => ({
3579
- value: catalogValue,
3580
- label: catalogValue
3581
- }))
3880
+ searchPlaceholder: "Buscar valor\u2026",
3881
+ onChange: (nextValue) => setSelectedFilterValue(nextValue),
3882
+ options: activeCatalogValues,
3883
+ disabled: loadingCatalog || activeCatalogValues.length === 0
3582
3884
  }
3583
3885
  )
3584
3886
  ] }),
3585
- loadingCatalog && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { color: "#64748b", fontSize: 12 }, children: "Cargando cat\xE1logo\u2026" }),
3586
- !loadingCatalog && selectedFilterField && activeCatalogValues.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { color: "#64748b", fontSize: 12 }, children: "No hay cat\xE1logo disponible para este filtro." }),
3587
- filterError && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { color: "#b91c1c", fontSize: 12 }, children: filterError }),
3588
- appliedFilter && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "zlm-badge", style: { alignSelf: "flex-start" }, children: [
3887
+ loadingCatalog && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { color: "#64748b", fontSize: 12 }, children: "Cargando cat\xE1logo\u2026" }),
3888
+ !loadingCatalog && selectedFilterField && activeCatalogValues.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { color: "#64748b", fontSize: 12 }, children: "No hay cat\xE1logo disponible para este filtro." }),
3889
+ filterError && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { color: "#b91c1c", fontSize: 12 }, children: filterError }),
3890
+ appliedFilter && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "zlm-badge", style: { alignSelf: "flex-start" }, children: [
3589
3891
  "Activo: ",
3590
3892
  appliedFilter.field,
3591
3893
  " = ",
3592
3894
  appliedFilter.value
3593
3895
  ] }),
3594
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "zlm-filter-actions", style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
3595
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3896
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "zlm-filter-actions", style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
3897
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3596
3898
  "button",
3597
3899
  {
3598
3900
  type: "button",
@@ -3602,7 +3904,7 @@ var ZenitLayerManager = ({
3602
3904
  children: applyingFilter ? "Aplicando\u2026" : "Aplicar"
3603
3905
  }
3604
3906
  ),
3605
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3907
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3606
3908
  "button",
3607
3909
  {
3608
3910
  type: "button",
@@ -3614,13 +3916,13 @@ var ZenitLayerManager = ({
3614
3916
  )
3615
3917
  ] })
3616
3918
  ] }) }),
3617
- showUploadTab && activeTab === "upload" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { color: "#475569", fontSize: 13 }, children: "Pr\xF3ximamente podr\xE1s subir capas desde este panel." })
3919
+ showUploadTab && activeTab === "upload" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { color: "#475569", fontSize: 13 }, children: "Pr\xF3ximamente podr\xE1s subir capas desde este panel." })
3618
3920
  ] })
3619
3921
  ] });
3620
3922
  };
3621
3923
 
3622
3924
  // src/react/ZenitFeatureFilterPanel.tsx
3623
- var import_jsx_runtime6 = require("react/jsx-runtime");
3925
+ var import_jsx_runtime7 = require("react/jsx-runtime");
3624
3926
  var ZenitFeatureFilterPanel = ({
3625
3927
  title = "Filtros",
3626
3928
  description,
@@ -3628,7 +3930,7 @@ var ZenitFeatureFilterPanel = ({
3628
3930
  style,
3629
3931
  children
3630
3932
  }) => {
3631
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3933
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3632
3934
  "section",
3633
3935
  {
3634
3936
  className,
@@ -3641,22 +3943,22 @@ var ZenitFeatureFilterPanel = ({
3641
3943
  ...style
3642
3944
  },
3643
3945
  children: [
3644
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("header", { style: { marginBottom: 12 }, children: [
3645
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { style: { margin: 0, fontSize: 16 }, children: title }),
3646
- description && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: { margin: "6px 0 0", color: "#475569", fontSize: 13 }, children: description })
3946
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("header", { style: { marginBottom: 12 }, children: [
3947
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { style: { margin: 0, fontSize: 16 }, children: title }),
3948
+ description && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { style: { margin: "6px 0 0", color: "#475569", fontSize: 13 }, children: description })
3647
3949
  ] }),
3648
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { children })
3950
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { children })
3649
3951
  ]
3650
3952
  }
3651
3953
  );
3652
3954
  };
3653
3955
 
3654
3956
  // src/react/ai/FloatingChatBox.tsx
3655
- var import_react9 = require("react");
3957
+ var import_react10 = require("react");
3656
3958
  var import_react_dom3 = require("react-dom");
3657
3959
 
3658
3960
  // src/react/hooks/use-chat.ts
3659
- var import_react8 = require("react");
3961
+ var import_react9 = require("react");
3660
3962
 
3661
3963
  // src/ai/chat.service.ts
3662
3964
  var DEFAULT_ERROR_MESSAGE = "No fue posible completar la solicitud al asistente.";
@@ -3788,9 +4090,9 @@ var sendMessageStream = async (mapId, request, callbacks = {}, options, config)
3788
4090
 
3789
4091
  // src/react/hooks/use-chat.ts
3790
4092
  var useSendMessage = (config) => {
3791
- const [isLoading, setIsLoading] = (0, import_react8.useState)(false);
3792
- const [error, setError] = (0, import_react8.useState)(null);
3793
- const send = (0, import_react8.useCallback)(
4093
+ const [isLoading, setIsLoading] = (0, import_react9.useState)(false);
4094
+ const [error, setError] = (0, import_react9.useState)(null);
4095
+ const send = (0, import_react9.useCallback)(
3794
4096
  async (mapId, request, options) => {
3795
4097
  setIsLoading(true);
3796
4098
  setError(null);
@@ -3808,18 +4110,18 @@ var useSendMessage = (config) => {
3808
4110
  return { sendMessage: send, isLoading, error };
3809
4111
  };
3810
4112
  var useSendMessageStream = (config) => {
3811
- const [isStreaming, setIsStreaming] = (0, import_react8.useState)(false);
3812
- const [streamingText, setStreamingText] = (0, import_react8.useState)("");
3813
- const [completeResponse, setCompleteResponse] = (0, import_react8.useState)(null);
3814
- const [error, setError] = (0, import_react8.useState)(null);
3815
- const requestIdRef = (0, import_react8.useRef)(0);
3816
- const reset = (0, import_react8.useCallback)(() => {
4113
+ const [isStreaming, setIsStreaming] = (0, import_react9.useState)(false);
4114
+ const [streamingText, setStreamingText] = (0, import_react9.useState)("");
4115
+ const [completeResponse, setCompleteResponse] = (0, import_react9.useState)(null);
4116
+ const [error, setError] = (0, import_react9.useState)(null);
4117
+ const requestIdRef = (0, import_react9.useRef)(0);
4118
+ const reset = (0, import_react9.useCallback)(() => {
3817
4119
  setIsStreaming(false);
3818
4120
  setStreamingText("");
3819
4121
  setCompleteResponse(null);
3820
4122
  setError(null);
3821
4123
  }, []);
3822
- const send = (0, import_react8.useCallback)(
4124
+ const send = (0, import_react9.useCallback)(
3823
4125
  async (mapId, request, options) => {
3824
4126
  const requestId = requestIdRef.current + 1;
3825
4127
  requestIdRef.current = requestId;
@@ -3873,7 +4175,7 @@ var useSendMessageStream = (config) => {
3873
4175
  // src/react/components/MarkdownRenderer.tsx
3874
4176
  var import_react_markdown = __toESM(require("react-markdown"));
3875
4177
  var import_remark_gfm = __toESM(require("remark-gfm"));
3876
- var import_jsx_runtime7 = require("react/jsx-runtime");
4178
+ var import_jsx_runtime8 = require("react/jsx-runtime");
3877
4179
  function normalizeAssistantMarkdown(text) {
3878
4180
  if (!text || typeof text !== "string") return "";
3879
4181
  let normalized = text;
@@ -3889,28 +4191,28 @@ var MarkdownRenderer = ({ content, className }) => {
3889
4191
  if (!normalizedContent) {
3890
4192
  return null;
3891
4193
  }
3892
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className, style: { wordBreak: "break-word" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4194
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className, style: { wordBreak: "break-word" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3893
4195
  import_react_markdown.default,
3894
4196
  {
3895
4197
  remarkPlugins: [import_remark_gfm.default],
3896
4198
  components: {
3897
4199
  // Headings with proper spacing
3898
- h1: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { style: { fontSize: "1.5em", fontWeight: 700, marginTop: "1em", marginBottom: "0.5em" }, ...props, children }),
3899
- h2: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h2", { style: { fontSize: "1.3em", fontWeight: 700, marginTop: "0.9em", marginBottom: "0.45em" }, ...props, children }),
3900
- h3: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { style: { fontSize: "1.15em", fontWeight: 600, marginTop: "0.75em", marginBottom: "0.4em" }, ...props, children }),
3901
- h4: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h4", { style: { fontSize: "1.05em", fontWeight: 600, marginTop: "0.6em", marginBottom: "0.35em" }, ...props, children }),
3902
- h5: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h5", { style: { fontSize: "1em", fontWeight: 600, marginTop: "0.5em", marginBottom: "0.3em" }, ...props, children }),
3903
- h6: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h6", { style: { fontSize: "0.95em", fontWeight: 600, marginTop: "0.5em", marginBottom: "0.3em" }, ...props, children }),
4200
+ h1: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h1", { style: { fontSize: "1.5em", fontWeight: 700, marginTop: "1em", marginBottom: "0.5em" }, ...props, children }),
4201
+ h2: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h2", { style: { fontSize: "1.3em", fontWeight: 700, marginTop: "0.9em", marginBottom: "0.45em" }, ...props, children }),
4202
+ h3: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { style: { fontSize: "1.15em", fontWeight: 600, marginTop: "0.75em", marginBottom: "0.4em" }, ...props, children }),
4203
+ h4: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { style: { fontSize: "1.05em", fontWeight: 600, marginTop: "0.6em", marginBottom: "0.35em" }, ...props, children }),
4204
+ h5: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h5", { style: { fontSize: "1em", fontWeight: 600, marginTop: "0.5em", marginBottom: "0.3em" }, ...props, children }),
4205
+ h6: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h6", { style: { fontSize: "0.95em", fontWeight: 600, marginTop: "0.5em", marginBottom: "0.3em" }, ...props, children }),
3904
4206
  // Paragraphs with comfortable line height
3905
- p: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { style: { marginTop: "0.5em", marginBottom: "0.5em", lineHeight: 1.6 }, ...props, children }),
4207
+ p: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: { marginTop: "0.5em", marginBottom: "0.5em", lineHeight: 1.6 }, ...props, children }),
3906
4208
  // Lists with proper indentation
3907
- ul: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ul", { style: { paddingLeft: "1.5em", marginTop: "0.5em", marginBottom: "0.5em" }, ...props, children }),
3908
- ol: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ol", { style: { paddingLeft: "1.5em", marginTop: "0.5em", marginBottom: "0.5em" }, ...props, children }),
3909
- li: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("li", { style: { marginTop: "0.25em", marginBottom: "0.25em" }, ...props, children }),
4209
+ ul: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { style: { paddingLeft: "1.5em", marginTop: "0.5em", marginBottom: "0.5em" }, ...props, children }),
4210
+ ol: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ol", { style: { paddingLeft: "1.5em", marginTop: "0.5em", marginBottom: "0.5em" }, ...props, children }),
4211
+ li: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("li", { style: { marginTop: "0.25em", marginBottom: "0.25em" }, ...props, children }),
3910
4212
  // Code blocks
3911
4213
  code: ({ inline, children, ...props }) => {
3912
4214
  if (inline) {
3913
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4215
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3914
4216
  "code",
3915
4217
  {
3916
4218
  style: {
@@ -3925,7 +4227,7 @@ var MarkdownRenderer = ({ content, className }) => {
3925
4227
  }
3926
4228
  );
3927
4229
  }
3928
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4230
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3929
4231
  "code",
3930
4232
  {
3931
4233
  style: {
@@ -3945,9 +4247,9 @@ var MarkdownRenderer = ({ content, className }) => {
3945
4247
  );
3946
4248
  },
3947
4249
  // Pre (code block wrapper)
3948
- pre: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { style: { margin: 0 }, ...props, children }),
4250
+ pre: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { style: { margin: 0 }, ...props, children }),
3949
4251
  // Blockquotes
3950
- blockquote: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4252
+ blockquote: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3951
4253
  "blockquote",
3952
4254
  {
3953
4255
  style: {
@@ -3963,11 +4265,11 @@ var MarkdownRenderer = ({ content, className }) => {
3963
4265
  }
3964
4266
  ),
3965
4267
  // Strong/bold
3966
- strong: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("strong", { style: { fontWeight: 600 }, ...props, children }),
4268
+ strong: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("strong", { style: { fontWeight: 600 }, ...props, children }),
3967
4269
  // Emphasis/italic
3968
- em: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("em", { style: { fontStyle: "italic" }, ...props, children }),
4270
+ em: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("em", { style: { fontStyle: "italic" }, ...props, children }),
3969
4271
  // Horizontal rule
3970
- hr: (props) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4272
+ hr: (props) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3971
4273
  "hr",
3972
4274
  {
3973
4275
  style: {
@@ -3980,7 +4282,7 @@ var MarkdownRenderer = ({ content, className }) => {
3980
4282
  }
3981
4283
  ),
3982
4284
  // Tables (GFM)
3983
- table: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { overflowX: "auto", marginTop: "0.5em", marginBottom: "0.5em" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4285
+ table: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { overflowX: "auto", marginTop: "0.5em", marginBottom: "0.5em" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3984
4286
  "table",
3985
4287
  {
3986
4288
  style: {
@@ -3992,7 +4294,7 @@ var MarkdownRenderer = ({ content, className }) => {
3992
4294
  children
3993
4295
  }
3994
4296
  ) }),
3995
- th: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4297
+ th: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3996
4298
  "th",
3997
4299
  {
3998
4300
  style: {
@@ -4006,7 +4308,7 @@ var MarkdownRenderer = ({ content, className }) => {
4006
4308
  children
4007
4309
  }
4008
4310
  ),
4009
- td: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4311
+ td: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4010
4312
  "td",
4011
4313
  {
4012
4314
  style: {
@@ -4024,32 +4326,32 @@ var MarkdownRenderer = ({ content, className }) => {
4024
4326
  };
4025
4327
 
4026
4328
  // src/react/ai/FloatingChatBox.tsx
4027
- var import_jsx_runtime8 = require("react/jsx-runtime");
4028
- var ChatIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) });
4029
- var CloseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4030
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
4031
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
4329
+ var import_jsx_runtime9 = require("react/jsx-runtime");
4330
+ var ChatIcon = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) });
4331
+ var CloseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4332
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
4333
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
4032
4334
  ] });
4033
- var ExpandIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4034
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "15 3 21 3 21 9" }),
4035
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "9 21 3 21 3 15" }),
4036
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
4037
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
4335
+ var ExpandIcon = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4336
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "15 3 21 3 21 9" }),
4337
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "9 21 3 21 3 15" }),
4338
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
4339
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
4038
4340
  ] });
4039
- var CollapseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4040
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "4 14 10 14 10 20" }),
4041
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "20 10 14 10 14 4" }),
4042
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "14", y1: "10", x2: "21", y2: "3" }),
4043
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
4341
+ var CollapseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4342
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "4 14 10 14 10 20" }),
4343
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "20 10 14 10 14 4" }),
4344
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "14", y1: "10", x2: "21", y2: "3" }),
4345
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
4044
4346
  ] });
4045
- var SendIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4046
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
4047
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
4347
+ var SendIcon = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4348
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
4349
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
4048
4350
  ] });
4049
- var LayersIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4050
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }),
4051
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "2 17 12 22 22 17" }),
4052
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "2 12 12 17 22 12" })
4351
+ var LayersIcon = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4352
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }),
4353
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "2 17 12 22 22 17" }),
4354
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "2 12 12 17 22 12" })
4053
4355
  ] });
4054
4356
  var styles = {
4055
4357
  root: {
@@ -4354,42 +4656,42 @@ var FloatingChatBox = ({
4354
4656
  open: openProp
4355
4657
  }) => {
4356
4658
  const isControlled = openProp !== void 0;
4357
- const [internalOpen, setInternalOpen] = (0, import_react9.useState)(false);
4659
+ const [internalOpen, setInternalOpen] = (0, import_react10.useState)(false);
4358
4660
  const open = isControlled ? openProp : internalOpen;
4359
- const setOpen = (0, import_react9.useCallback)((value) => {
4661
+ const setOpen = (0, import_react10.useCallback)((value) => {
4360
4662
  const newValue = typeof value === "function" ? value(open) : value;
4361
4663
  if (!isControlled) {
4362
4664
  setInternalOpen(newValue);
4363
4665
  }
4364
4666
  onOpenChange?.(newValue);
4365
4667
  }, [isControlled, open, onOpenChange]);
4366
- const [expanded, setExpanded] = (0, import_react9.useState)(false);
4367
- const [messages, setMessages] = (0, import_react9.useState)([]);
4368
- const [inputValue, setInputValue] = (0, import_react9.useState)("");
4369
- const [conversationId, setConversationId] = (0, import_react9.useState)();
4370
- const [errorMessage, setErrorMessage] = (0, import_react9.useState)(null);
4371
- const [isFocused, setIsFocused] = (0, import_react9.useState)(false);
4372
- const [isMobile, setIsMobile] = (0, import_react9.useState)(false);
4373
- const messagesEndRef = (0, import_react9.useRef)(null);
4374
- const messagesContainerRef = (0, import_react9.useRef)(null);
4375
- const chatBoxRef = (0, import_react9.useRef)(null);
4376
- const chatConfig = (0, import_react9.useMemo)(() => {
4668
+ const [expanded, setExpanded] = (0, import_react10.useState)(false);
4669
+ const [messages, setMessages] = (0, import_react10.useState)([]);
4670
+ const [inputValue, setInputValue] = (0, import_react10.useState)("");
4671
+ const [conversationId, setConversationId] = (0, import_react10.useState)();
4672
+ const [errorMessage, setErrorMessage] = (0, import_react10.useState)(null);
4673
+ const [isFocused, setIsFocused] = (0, import_react10.useState)(false);
4674
+ const [isMobile, setIsMobile] = (0, import_react10.useState)(false);
4675
+ const messagesEndRef = (0, import_react10.useRef)(null);
4676
+ const messagesContainerRef = (0, import_react10.useRef)(null);
4677
+ const chatBoxRef = (0, import_react10.useRef)(null);
4678
+ const chatConfig = (0, import_react10.useMemo)(() => {
4377
4679
  if (!baseUrl) return void 0;
4378
4680
  return { baseUrl, accessToken, getAccessToken };
4379
4681
  }, [accessToken, baseUrl, getAccessToken]);
4380
4682
  const { sendMessage: sendMessage2, isStreaming, streamingText, completeResponse } = useSendMessageStream(chatConfig);
4381
4683
  const canSend = Boolean(mapId) && Boolean(baseUrl) && inputValue.trim().length > 0 && !isStreaming;
4382
- (0, import_react9.useEffect)(() => {
4684
+ (0, import_react10.useEffect)(() => {
4383
4685
  if (open && isMobile) {
4384
4686
  setExpanded(true);
4385
4687
  }
4386
4688
  }, [open, isMobile]);
4387
- const scrollToBottom = (0, import_react9.useCallback)(() => {
4689
+ const scrollToBottom = (0, import_react10.useCallback)(() => {
4388
4690
  if (messagesEndRef.current) {
4389
4691
  messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
4390
4692
  }
4391
4693
  }, []);
4392
- (0, import_react9.useEffect)(() => {
4694
+ (0, import_react10.useEffect)(() => {
4393
4695
  if (open && messages.length === 0) {
4394
4696
  setMessages([
4395
4697
  {
@@ -4400,10 +4702,10 @@ var FloatingChatBox = ({
4400
4702
  ]);
4401
4703
  }
4402
4704
  }, [open, messages.length]);
4403
- (0, import_react9.useEffect)(() => {
4705
+ (0, import_react10.useEffect)(() => {
4404
4706
  scrollToBottom();
4405
4707
  }, [messages, streamingText, scrollToBottom]);
4406
- (0, import_react9.useEffect)(() => {
4708
+ (0, import_react10.useEffect)(() => {
4407
4709
  if (!open) return;
4408
4710
  if (isMobile && expanded) return;
4409
4711
  const handleClickOutside = (event) => {
@@ -4416,7 +4718,7 @@ var FloatingChatBox = ({
4416
4718
  document.removeEventListener("mousedown", handleClickOutside);
4417
4719
  };
4418
4720
  }, [open, isMobile, expanded]);
4419
- (0, import_react9.useEffect)(() => {
4721
+ (0, import_react10.useEffect)(() => {
4420
4722
  if (typeof window === "undefined") return;
4421
4723
  const mediaQuery = window.matchMedia("(max-width: 768px)");
4422
4724
  const updateMobile = () => setIsMobile(mediaQuery.matches);
@@ -4434,7 +4736,7 @@ var FloatingChatBox = ({
4434
4736
  }
4435
4737
  };
4436
4738
  }, []);
4437
- (0, import_react9.useEffect)(() => {
4739
+ (0, import_react10.useEffect)(() => {
4438
4740
  if (typeof document === "undefined") return;
4439
4741
  if (!open || !isMobile) return;
4440
4742
  document.body.style.overflow = "hidden";
@@ -4442,10 +4744,10 @@ var FloatingChatBox = ({
4442
4744
  document.body.style.overflow = "";
4443
4745
  };
4444
4746
  }, [open, isMobile]);
4445
- const addMessage = (0, import_react9.useCallback)((message) => {
4747
+ const addMessage = (0, import_react10.useCallback)((message) => {
4446
4748
  setMessages((prev) => [...prev, message]);
4447
4749
  }, []);
4448
- const handleSend = (0, import_react9.useCallback)(async () => {
4750
+ const handleSend = (0, import_react10.useCallback)(async () => {
4449
4751
  if (!mapId) {
4450
4752
  setErrorMessage("Selecciona un mapa para usar el asistente.");
4451
4753
  return;
@@ -4498,7 +4800,7 @@ var FloatingChatBox = ({
4498
4800
  sendMessage2,
4499
4801
  userId
4500
4802
  ]);
4501
- const handleKeyDown = (0, import_react9.useCallback)(
4803
+ const handleKeyDown = (0, import_react10.useCallback)(
4502
4804
  (event) => {
4503
4805
  if (event.key === "Enter" && !event.shiftKey) {
4504
4806
  event.preventDefault();
@@ -4509,20 +4811,20 @@ var FloatingChatBox = ({
4509
4811
  },
4510
4812
  [canSend, handleSend]
4511
4813
  );
4512
- const handleFollowUpClick = (0, import_react9.useCallback)((question) => {
4814
+ const handleFollowUpClick = (0, import_react10.useCallback)((question) => {
4513
4815
  setInputValue(question);
4514
4816
  }, []);
4515
4817
  const renderMetadata = (response) => {
4516
4818
  if (!response?.metadata) return null;
4517
4819
  const referencedLayers = response.metadata.referencedLayers;
4518
4820
  if (!referencedLayers || referencedLayers.length === 0) return null;
4519
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.metadataSection, children: [
4520
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.metadataTitle, children: [
4521
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LayersIcon, {}),
4821
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.metadataSection, children: [
4822
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.metadataTitle, children: [
4823
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(LayersIcon, {}),
4522
4824
  "Capas Analizadas"
4523
4825
  ] }),
4524
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { style: styles.metadataList, children: referencedLayers.map((layer, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("li", { style: styles.metadataItem, children: [
4525
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("strong", { children: layer.layerName }),
4826
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("ul", { style: styles.metadataList, children: referencedLayers.map((layer, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("li", { style: styles.metadataItem, children: [
4827
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: layer.layerName }),
4526
4828
  " (",
4527
4829
  layer.featureCount,
4528
4830
  " ",
@@ -4531,7 +4833,7 @@ var FloatingChatBox = ({
4531
4833
  ] }, index)) })
4532
4834
  ] });
4533
4835
  };
4534
- const handleActionClick = (0, import_react9.useCallback)((action) => {
4836
+ const handleActionClick = (0, import_react10.useCallback)((action) => {
4535
4837
  if (isStreaming) return;
4536
4838
  setOpen(false);
4537
4839
  requestAnimationFrame(() => {
@@ -4540,9 +4842,9 @@ var FloatingChatBox = ({
4540
4842
  }, [isStreaming, setOpen, onActionClick]);
4541
4843
  const renderActions = (response) => {
4542
4844
  if (!response?.suggestedActions?.length) return null;
4543
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.actionsSection, children: [
4544
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.sectionLabel, children: "Acciones Sugeridas" }),
4545
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.actionsGrid, children: response.suggestedActions.map((action, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4845
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.actionsSection, children: [
4846
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.sectionLabel, children: "Acciones Sugeridas" }),
4847
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.actionsGrid, children: response.suggestedActions.map((action, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4546
4848
  "button",
4547
4849
  {
4548
4850
  type: "button",
@@ -4573,9 +4875,9 @@ var FloatingChatBox = ({
4573
4875
  };
4574
4876
  const renderFollowUps = (response) => {
4575
4877
  if (!response?.followUpQuestions?.length) return null;
4576
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.actionsSection, children: [
4577
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.sectionLabel, children: "Preguntas Relacionadas" }),
4578
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: response.followUpQuestions.map((question, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4878
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.actionsSection, children: [
4879
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.sectionLabel, children: "Preguntas Relacionadas" }),
4880
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: response.followUpQuestions.map((question, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4579
4881
  "button",
4580
4882
  {
4581
4883
  type: "button",
@@ -4604,8 +4906,8 @@ var FloatingChatBox = ({
4604
4906
  )) })
4605
4907
  ] });
4606
4908
  };
4607
- const chatContent = /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.root, children: [
4608
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `
4909
+ const chatContent = /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.root, children: [
4910
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `
4609
4911
  @keyframes zenitBlink {
4610
4912
  0%, 49% { opacity: 1; }
4611
4913
  50%, 100% { opacity: 0; }
@@ -4661,7 +4963,7 @@ var FloatingChatBox = ({
4661
4963
  }
4662
4964
  }
4663
4965
  ` }),
4664
- open && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
4966
+ open && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4665
4967
  "div",
4666
4968
  {
4667
4969
  ref: chatBoxRef,
@@ -4675,10 +4977,10 @@ var FloatingChatBox = ({
4675
4977
  };
4676
4978
  })(),
4677
4979
  children: [
4678
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("header", { style: styles.header, children: [
4679
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { style: styles.title, children: "Asistente Zenit AI" }),
4680
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.headerButtons, children: [
4681
- !isMobile && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4980
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("header", { style: styles.header, children: [
4981
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { style: styles.title, children: "Asistente Zenit AI" }),
4982
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.headerButtons, children: [
4983
+ !isMobile && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4682
4984
  "button",
4683
4985
  {
4684
4986
  type: "button",
@@ -4691,10 +4993,10 @@ var FloatingChatBox = ({
4691
4993
  e.currentTarget.style.background = "rgba(255, 255, 255, 0.15)";
4692
4994
  },
4693
4995
  "aria-label": expanded ? "Contraer" : "Expandir",
4694
- children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CollapseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ExpandIcon, {})
4996
+ children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CollapseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ExpandIcon, {})
4695
4997
  }
4696
4998
  ),
4697
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4999
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4698
5000
  "button",
4699
5001
  {
4700
5002
  type: "button",
@@ -4707,20 +5009,20 @@ var FloatingChatBox = ({
4707
5009
  e.currentTarget.style.background = "rgba(255, 255, 255, 0.15)";
4708
5010
  },
4709
5011
  "aria-label": "Cerrar",
4710
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CloseIcon, {})
5012
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CloseIcon, {})
4711
5013
  }
4712
5014
  )
4713
5015
  ] })
4714
5016
  ] }),
4715
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { ref: messagesContainerRef, className: "zenit-ai-body", style: styles.messages, children: [
4716
- messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5017
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { ref: messagesContainerRef, className: "zenit-ai-body", style: styles.messages, children: [
5018
+ messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4717
5019
  "div",
4718
5020
  {
4719
5021
  style: {
4720
5022
  ...styles.messageWrapper,
4721
5023
  alignItems: message.role === "user" ? "flex-end" : "flex-start"
4722
5024
  },
4723
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
5025
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4724
5026
  "div",
4725
5027
  {
4726
5028
  style: {
@@ -4728,7 +5030,7 @@ var FloatingChatBox = ({
4728
5030
  ...message.role === "user" ? styles.userMessage : styles.assistantMessage
4729
5031
  },
4730
5032
  children: [
4731
- message.role === "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(MarkdownRenderer, { content: message.content }) : message.content,
5033
+ message.role === "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(MarkdownRenderer, { content: message.content }) : message.content,
4732
5034
  message.role === "assistant" && renderMetadata(message.response),
4733
5035
  message.role === "assistant" && renderActions(message.response),
4734
5036
  message.role === "assistant" && renderFollowUps(message.response)
@@ -4738,39 +5040,39 @@ var FloatingChatBox = ({
4738
5040
  },
4739
5041
  message.id
4740
5042
  )),
4741
- isStreaming && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5043
+ isStreaming && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4742
5044
  "div",
4743
5045
  {
4744
5046
  style: {
4745
5047
  ...styles.messageWrapper,
4746
5048
  alignItems: "flex-start"
4747
5049
  },
4748
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5050
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4749
5051
  "div",
4750
5052
  {
4751
5053
  style: {
4752
5054
  ...styles.messageBubble,
4753
5055
  ...styles.assistantMessage
4754
5056
  },
4755
- children: streamingText ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
4756
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(MarkdownRenderer, { content: streamingText }),
4757
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: styles.cursor })
4758
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.thinkingText, children: [
4759
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Pensando" }),
4760
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.typingIndicator, children: [
4761
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot }),
4762
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot }),
4763
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot })
5057
+ children: streamingText ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
5058
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(MarkdownRenderer, { content: streamingText }),
5059
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: styles.cursor })
5060
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.thinkingText, children: [
5061
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: "Pensando" }),
5062
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.typingIndicator, children: [
5063
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot }),
5064
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot }),
5065
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot })
4764
5066
  ] })
4765
5067
  ] })
4766
5068
  }
4767
5069
  )
4768
5070
  }
4769
5071
  ),
4770
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ref: messagesEndRef })
5072
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { ref: messagesEndRef })
4771
5073
  ] }),
4772
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "zenit-ai-input-area", style: styles.inputWrapper, children: [
4773
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5074
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "zenit-ai-input-area", style: styles.inputWrapper, children: [
5075
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4774
5076
  "textarea",
4775
5077
  {
4776
5078
  style: {
@@ -4787,7 +5089,7 @@ var FloatingChatBox = ({
4787
5089
  disabled: !mapId || !baseUrl || isStreaming
4788
5090
  }
4789
5091
  ),
4790
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5092
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4791
5093
  "button",
4792
5094
  {
4793
5095
  type: "button",
@@ -4796,18 +5098,18 @@ var FloatingChatBox = ({
4796
5098
  onClick: () => void handleSend(),
4797
5099
  disabled: !canSend,
4798
5100
  "aria-label": "Enviar mensaje",
4799
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SendIcon, {})
5101
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SendIcon, {})
4800
5102
  }
4801
5103
  )
4802
5104
  ] }),
4803
- errorMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.errorText, children: errorMessage }),
4804
- isStreaming && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.statusNote, children: "Generando sugerencias..." }),
4805
- !mapId && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.statusNote, children: "Selecciona un mapa para usar el asistente" }),
4806
- !baseUrl && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.statusNote, children: "Configura la baseUrl del SDK" })
5105
+ errorMessage && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.errorText, children: errorMessage }),
5106
+ isStreaming && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.statusNote, children: "Generando sugerencias..." }),
5107
+ !mapId && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.statusNote, children: "Selecciona un mapa para usar el asistente" }),
5108
+ !baseUrl && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.statusNote, children: "Configura la baseUrl del SDK" })
4807
5109
  ]
4808
5110
  }
4809
5111
  ),
4810
- !(hideButton && !open) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5112
+ !(hideButton && !open) && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4811
5113
  "button",
4812
5114
  {
4813
5115
  type: "button",
@@ -4819,9 +5121,9 @@ var FloatingChatBox = ({
4819
5121
  },
4820
5122
  onClick: () => setOpen((prev) => !prev),
4821
5123
  "aria-label": open ? "Cerrar asistente" : "Abrir asistente Zenit AI",
4822
- children: open ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CloseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
4823
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ChatIcon, {}),
4824
- !isMobile && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Asistente IA" })
5124
+ children: open ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CloseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
5125
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ChatIcon, {}),
5126
+ !isMobile && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: "Asistente IA" })
4825
5127
  ] })
4826
5128
  }
4827
5129
  )