zenit-sdk 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1824,6 +1824,14 @@ var LayerGeoJson = ({
1824
1824
  onEachFeature,
1825
1825
  onPolygonLabel
1826
1826
  }) => {
1827
+ const styleFnRef = (0, import_react.useRef)(styleFn);
1828
+ const onEachFeatureRef = (0, import_react.useRef)(onEachFeature);
1829
+ (0, import_react.useEffect)(() => {
1830
+ styleFnRef.current = styleFn;
1831
+ }, [styleFn]);
1832
+ (0, import_react.useEffect)(() => {
1833
+ onEachFeatureRef.current = onEachFeature;
1834
+ }, [onEachFeature]);
1827
1835
  const safeData = (0, import_react.useMemo)(() => sanitizeGeoJson(data, String(layerId)), [data, layerId]);
1828
1836
  const features = (0, import_react.useMemo)(() => safeData.features ?? [], [safeData]);
1829
1837
  const fillFeatures = (0, import_react.useMemo)(() => features.filter(isNonPointGeometry), [features]);
@@ -1867,14 +1875,14 @@ var LayerGeoJson = ({
1867
1875
  if (!isValidLatLng(latlng)) {
1868
1876
  return createInvisibleFallbackClusterMarker();
1869
1877
  }
1870
- const style = styleFn(feature, layerType, baseOpacity);
1878
+ const style = styleFnRef.current(feature, layerType, baseOpacity);
1871
1879
  return import_leaflet.default.marker(latlng, {
1872
1880
  icon: createPointDivIcon(style, isMobile),
1873
1881
  pane: clusterPaneName,
1874
1882
  interactive: true
1875
1883
  });
1876
1884
  },
1877
- onEachFeature
1885
+ onEachFeature: (feature, layer) => onEachFeatureRef.current(feature, layer)
1878
1886
  });
1879
1887
  clusterLayer.addLayer(geoJsonLayer);
1880
1888
  return () => {
@@ -1889,11 +1897,9 @@ var LayerGeoJson = ({
1889
1897
  isMobile,
1890
1898
  layerType,
1891
1899
  mapInstance,
1892
- onEachFeature,
1893
1900
  panesReady,
1894
1901
  pointsData,
1895
- resolvedPointsPane,
1896
- styleFn
1902
+ resolvedPointsPane
1897
1903
  ]);
1898
1904
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1899
1905
  fillData && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -2002,6 +2008,55 @@ function useGeolocation(options) {
2002
2008
 
2003
2009
  // src/react/map/map-utils.ts
2004
2010
  var import_leaflet2 = __toESM(require("leaflet"));
2011
+
2012
+ // src/config/modalWhitelist.ts
2013
+ var SECTOR_MODAL_WHITELIST = [
2014
+ { key: "Sector", label: "Sector" },
2015
+ { key: "Promotor", label: "Promotor" },
2016
+ { key: "Capital Total", label: "Capital Total" },
2017
+ { key: "Total Capital Mora", label: "Capital en Mora" },
2018
+ { key: "Tendencia Mora", label: "Tendencia de Mora", hint: "trend_icon" },
2019
+ { key: "Tendencia Capital", label: "Tendencia de Capital", hint: "trend_icon" },
2020
+ { key: "Tendencia Castigos", label: "Tendencia de Castigos", hint: "trend_icon" },
2021
+ { key: "Impacto Sector", label: "Impacto del Sector" },
2022
+ { key: "Total Clientes Sector", label: "Total de Clientes" },
2023
+ { key: "Total Clientes Sanos", label: "Clientes Sanos" },
2024
+ { key: "Total Clientes Morosos", label: "Clientes en Mora" },
2025
+ { key: "Total Clientes Castigados", label: "Clientes Castigados" },
2026
+ { key: "Total Clientes Nuevos", label: "Clientes Nuevos" },
2027
+ { key: "Total Clientes Salidos", label: "Clientes Salidos" },
2028
+ { key: "Insights", label: "An\xE1lisis IA", hint: "collapsible" },
2029
+ { key: "Recomendaciones", label: "Recomendaciones IA", hint: "collapsible" }
2030
+ ];
2031
+ var CLIENTE_MODAL_WHITELIST = [
2032
+ { key: "nombre del cliente", label: "Nombre del Cliente" },
2033
+ { key: "dpi", label: "DPI" },
2034
+ { key: "kpi", label: "Estado", hint: "kpi_badge" },
2035
+ { key: "tel principal", label: "Tel\xE9fono", hint: "phone_link" },
2036
+ { key: "capital concedido", label: "Capital Concedido" },
2037
+ { key: "mora", label: "Monto en Mora", hint: "mora_alert" },
2038
+ { key: "etapa", label: "Etapa del Cr\xE9dito" },
2039
+ { key: "prestamo", label: "No. de Pr\xE9stamo" },
2040
+ { key: "sucursal", label: "Sucursal", aliases: ["nombre sucursal"] }
2041
+ ];
2042
+ function applyModalWhitelist(rawData, whitelist) {
2043
+ const keys = Object.keys(rawData ?? {});
2044
+ return whitelist.map(({ key, label, hint, aliases = [] }) => {
2045
+ const keysToTry = [key, ...aliases];
2046
+ let value = void 0;
2047
+ for (const k of keysToTry) {
2048
+ const match = keys.find((rawKey) => rawKey.toLowerCase() === k.toLowerCase());
2049
+ if (match !== void 0 && rawData[match] !== null && rawData[match] !== void 0) {
2050
+ value = rawData[match];
2051
+ break;
2052
+ }
2053
+ }
2054
+ if (value === void 0) return null;
2055
+ return { label, value, hint: hint ?? null };
2056
+ }).filter((entry) => Boolean(entry));
2057
+ }
2058
+
2059
+ // src/react/map/map-utils.ts
2005
2060
  var POPUP_STYLE_ID = "zenit-leaflet-popup-styles";
2006
2061
  var POPUP_EXCLUDED_KEYS = /* @__PURE__ */ new Set(["geom", "geometry", "_private"]);
2007
2062
  var POPUP_TITLE_KEYS = ["id", "nombre", "name", "title", "titulo", "cluster"];
@@ -2238,6 +2293,10 @@ function shouldIncludePopupEntry(key, value) {
2238
2293
  return true;
2239
2294
  }
2240
2295
  function createPopupContent(properties) {
2296
+ const whitelistedRows = buildWhitelistedRows(properties);
2297
+ if (whitelistedRows) {
2298
+ return whitelistedRows;
2299
+ }
2241
2300
  const header = findHeaderProperties(properties);
2242
2301
  const headerText = header.title?.value ?? extractPopupHeader(properties);
2243
2302
  const usedKeys = new Set([header.title?.key, header.badge?.key, header.description?.key].filter(Boolean));
@@ -2277,6 +2336,37 @@ function createPopupContent(properties) {
2277
2336
  }).join("");
2278
2337
  return `<div>${colorBar}${headerHtml}${descriptionHtml}${rowsHtml}</div>`;
2279
2338
  }
2339
+ function buildWhitelistedRows(properties) {
2340
+ const whitelist = selectModalWhitelist(properties);
2341
+ if (!whitelist) return null;
2342
+ const entries = applyModalWhitelist(properties, whitelist);
2343
+ if (entries.length === 0) {
2344
+ return '<div style="padding:8px 0; color:#64748b; text-align:center;">Sin datos disponibles</div>';
2345
+ }
2346
+ const rowsHtml = entries.map(({ label, value }) => {
2347
+ const valueHtml = renderPopupValue(value);
2348
+ return `
2349
+ <div style="display:grid; grid-template-columns:minmax(90px, 35%) 1fr; gap:8px; padding:6px 0; border-bottom:1px solid #e2e8f0;">
2350
+ <div style="font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:0.04em; color:#64748b;">${escapeHtml(label)}</div>
2351
+ <div style="font-size:13px; color:#0f172a; word-break:break-word;">${valueHtml}</div>
2352
+ </div>
2353
+ `;
2354
+ }).join("");
2355
+ return `<div>${rowsHtml}</div>`;
2356
+ }
2357
+ function countWhitelistMatches(properties, whitelist) {
2358
+ const keys = Object.keys(properties).map((key) => key.toLowerCase());
2359
+ return whitelist.reduce((count, item) => {
2360
+ const candidates = [item.key, ...item.aliases ?? []].map((candidate) => candidate.toLowerCase());
2361
+ return candidates.some((candidate) => keys.includes(candidate)) ? count + 1 : count;
2362
+ }, 0);
2363
+ }
2364
+ function selectModalWhitelist(properties) {
2365
+ const sectorMatches = countWhitelistMatches(properties, SECTOR_MODAL_WHITELIST);
2366
+ const clienteMatches = countWhitelistMatches(properties, CLIENTE_MODAL_WHITELIST);
2367
+ if (sectorMatches === 0 && clienteMatches === 0) return null;
2368
+ return sectorMatches >= clienteMatches ? SECTOR_MODAL_WHITELIST : CLIENTE_MODAL_WHITELIST;
2369
+ }
2280
2370
  function isPolygonType(layerType, geometryType) {
2281
2371
  const candidate = (layerType ?? geometryType ?? "").toLowerCase();
2282
2372
  return candidate === "polygon" || candidate === "multipolygon";
@@ -2805,6 +2895,14 @@ function pickIntersectFeature(params) {
2805
2895
  selectedIdx: candidates.findIndex((candidate) => candidate === feature),
2806
2896
  reason
2807
2897
  });
2898
+ if (clickIntent === "point") {
2899
+ const anyPoint = candidates.find(
2900
+ (c) => isCandidateGeometryType(c, POINT_GEOMETRY_TYPES2)
2901
+ );
2902
+ if (anyPoint) {
2903
+ return getResult(anyPoint, "point:first-point-geometry");
2904
+ }
2905
+ }
2808
2906
  const sameLayer = candidates.filter(
2809
2907
  (candidate) => isLayerIdMatch(candidateLayerId(candidate), expectedLayerId)
2810
2908
  );
@@ -3241,7 +3339,7 @@ var ZenitMap = (0, import_react5.forwardRef)(({
3241
3339
  const ensureLayerPanes = (0, import_react5.useCallback)(
3242
3340
  (targetMap, targetLayers) => {
3243
3341
  const fillBaseZIndex = 400;
3244
- const pointsBaseZIndex = 700;
3342
+ const pointsBaseZIndex = 750;
3245
3343
  targetLayers.forEach((layer) => {
3246
3344
  const order = Number.isFinite(layer.displayOrder) ? layer.displayOrder : 0;
3247
3345
  const orderOffset = Math.max(0, Math.min(order, 150));
@@ -3325,7 +3423,10 @@ var ZenitMap = (0, import_react5.forwardRef)(({
3325
3423
  className: "zenit-map-tooltip"
3326
3424
  });
3327
3425
  }
3328
- layer.on("click", () => {
3426
+ layer.on("click", (e) => {
3427
+ if (clickIntent === "point") {
3428
+ import_leaflet4.default.DomEvent.stopPropagation(e);
3429
+ }
3329
3430
  if (featureInfoMode === "popup" && client && layerId !== void 0 && !extractDescriptionValue(feature?.properties) && feature?.geometry) {
3330
3431
  if (DEV_MODE2) {
3331
3432
  console.debug("[ZenitMap] click/intersect:start", {
@@ -3425,11 +3526,16 @@ var ZenitMap = (0, import_react5.forwardRef)(({
3425
3526
  properties: feature?.properties ?? void 0
3426
3527
  });
3427
3528
  }, [currentZoom, resolveLayerStyle]);
3428
- const makeStyleFnForLayer = (0, import_react5.useCallback)((layerId) => {
3429
- return (feature, layerType, baseOpacity) => {
3430
- return buildLayerStyle(layerId, baseOpacity ?? 1, feature, layerType);
3431
- };
3432
- }, [buildLayerStyle]);
3529
+ const styleFnByLayerId = (0, import_react5.useMemo)(() => {
3530
+ const next = /* @__PURE__ */ new Map();
3531
+ orderedLayers.forEach((layerState) => {
3532
+ const layerId = layerState.mapLayer.layerId;
3533
+ next.set(String(layerId), (feature, layerType, baseOpacity) => {
3534
+ return buildLayerStyle(layerId, baseOpacity ?? 1, feature, layerType);
3535
+ });
3536
+ });
3537
+ return next;
3538
+ }, [buildLayerStyle, orderedLayers]);
3433
3539
  (0, import_react5.useImperativeHandle)(ref, () => ({
3434
3540
  setLayerOpacity: (layerId, opacity) => {
3435
3541
  upsertUiOverride(layerId, { overrideOpacity: opacity });
@@ -3596,7 +3702,7 @@ var ZenitMap = (0, import_react5.forwardRef)(({
3596
3702
  fillPaneName,
3597
3703
  pointsPaneName,
3598
3704
  layerType,
3599
- styleFn: makeStyleFnForLayer(layerState.mapLayer.layerId),
3705
+ styleFn: styleFnByLayerId.get(String(layerState.mapLayer.layerId)) ?? ((feature, layerType2, baseOpacity2) => buildLayerStyle(layerState.mapLayer.layerId, baseOpacity2 ?? 1, feature, layerType2)),
3600
3706
  onEachFeature: overlayOnEachFeature,
3601
3707
  onPolygonLabel: labelKey ? (feature, layer) => {
3602
3708
  const geometryType = feature?.geometry?.type;
@@ -3740,7 +3846,7 @@ var ZenitMap = (0, import_react5.forwardRef)(({
3740
3846
  ZenitMap.displayName = "ZenitMap";
3741
3847
 
3742
3848
  // src/react/ZenitLayerManager.tsx
3743
- var import_react7 = __toESM(require("react"));
3849
+ var import_react8 = __toESM(require("react"));
3744
3850
 
3745
3851
  // src/react/icons.tsx
3746
3852
  var import_lucide_react = require("lucide-react");
@@ -4098,9 +4204,191 @@ var ZenitSelect = ({
4098
4204
  ] });
4099
4205
  };
4100
4206
 
4101
- // src/react/ZenitLayerManager.tsx
4207
+ // src/react/ui/ZenitCombobox.tsx
4208
+ var import_react7 = __toESM(require("react"));
4102
4209
  var import_jsx_runtime5 = require("react/jsx-runtime");
4210
+ var ZenitCombobox = ({
4211
+ options,
4212
+ value,
4213
+ onChange,
4214
+ placeholder = "Seleccionar\u2026",
4215
+ searchPlaceholder = "Buscar\u2026",
4216
+ disabled = false
4217
+ }) => {
4218
+ const rootRef = import_react7.default.useRef(null);
4219
+ const [isOpen, setIsOpen] = import_react7.default.useState(false);
4220
+ const [query, setQuery] = import_react7.default.useState("");
4221
+ const filteredOptions = import_react7.default.useMemo(() => {
4222
+ const normalized = query.trim().toLowerCase();
4223
+ if (!normalized) return options;
4224
+ return options.filter((option) => option.toLowerCase().includes(normalized));
4225
+ }, [options, query]);
4226
+ import_react7.default.useEffect(() => {
4227
+ if (!isOpen) return;
4228
+ const onClickOutside = (event) => {
4229
+ if (!rootRef.current?.contains(event.target)) {
4230
+ setIsOpen(false);
4231
+ }
4232
+ };
4233
+ const onEscape = (event) => {
4234
+ if (event.key === "Escape") {
4235
+ setIsOpen(false);
4236
+ }
4237
+ };
4238
+ document.addEventListener("mousedown", onClickOutside);
4239
+ document.addEventListener("keydown", onEscape);
4240
+ return () => {
4241
+ document.removeEventListener("mousedown", onClickOutside);
4242
+ document.removeEventListener("keydown", onEscape);
4243
+ };
4244
+ }, [isOpen]);
4245
+ import_react7.default.useEffect(() => {
4246
+ if (!isOpen) {
4247
+ setQuery("");
4248
+ }
4249
+ }, [isOpen]);
4250
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: rootRef, className: "zenit-combobox-root", style: { position: "relative" }, children: [
4251
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: `
4252
+ .zenit-combobox-trigger {
4253
+ width: 100%;
4254
+ min-height: 40px;
4255
+ height: 40px;
4256
+ border: 1px solid #cbd5e1;
4257
+ border-radius: 6px;
4258
+ background: #ffffff;
4259
+ color: #0f172a;
4260
+ display: inline-flex;
4261
+ align-items: center;
4262
+ padding: 0 12px;
4263
+ font-size: 14px;
4264
+ line-height: 1.25;
4265
+ cursor: pointer;
4266
+ text-align: left;
4267
+ }
4268
+ .zenit-combobox-trigger.is-placeholder {
4269
+ color: #64748b;
4270
+ }
4271
+ .zenit-combobox-trigger:disabled {
4272
+ opacity: 0.6;
4273
+ cursor: not-allowed;
4274
+ }
4275
+ .zenit-combobox-content {
4276
+ position: absolute;
4277
+ top: calc(100% + 6px);
4278
+ left: 0;
4279
+ right: 0;
4280
+ border: 1px solid #cbd5e1;
4281
+ border-radius: 6px;
4282
+ background: #ffffff;
4283
+ box-shadow: 0 10px 25px rgba(15, 23, 42, 0.18);
4284
+ padding: 8px;
4285
+ z-index: 4000;
4286
+ }
4287
+ .zenit-combobox-search {
4288
+ width: 100%;
4289
+ min-height: 36px;
4290
+ border: 1px solid #cbd5e1;
4291
+ border-radius: 6px;
4292
+ background: #ffffff;
4293
+ color: #0f172a;
4294
+ padding: 0 10px;
4295
+ font-size: 14px;
4296
+ margin-bottom: 8px;
4297
+ box-sizing: border-box;
4298
+ }
4299
+ .zenit-combobox-list {
4300
+ max-height: 220px;
4301
+ overflow-y: auto;
4302
+ }
4303
+ .zenit-combobox-item {
4304
+ width: 100%;
4305
+ border-radius: 4px;
4306
+ color: #0f172a;
4307
+ font-size: 14px;
4308
+ min-height: 34px;
4309
+ padding: 8px 10px;
4310
+ cursor: pointer;
4311
+ user-select: none;
4312
+ }
4313
+ .zenit-combobox-item:hover { background: #f1f5f9; }
4314
+ .zenit-combobox-item.is-selected { background: #e2e8f0; font-weight: 600; }
4315
+ ` }),
4316
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4317
+ "button",
4318
+ {
4319
+ type: "button",
4320
+ className: `zenit-combobox-trigger${!value ? " is-placeholder" : ""}`,
4321
+ disabled,
4322
+ onClick: () => !disabled && setIsOpen((prev) => !prev),
4323
+ children: value || placeholder
4324
+ }
4325
+ ),
4326
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "zenit-combobox-content", children: [
4327
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4328
+ "input",
4329
+ {
4330
+ className: "zenit-combobox-search",
4331
+ value: query,
4332
+ onChange: (event) => setQuery(event.target.value),
4333
+ placeholder: searchPlaceholder,
4334
+ autoFocus: true
4335
+ }
4336
+ ),
4337
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "zenit-combobox-list", children: [
4338
+ filteredOptions.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "zenit-combobox-item", style: { color: "#64748b", cursor: "default" }, children: "Sin coincidencias" }),
4339
+ filteredOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4340
+ "div",
4341
+ {
4342
+ className: `zenit-combobox-item${option === value ? " is-selected" : ""}`,
4343
+ onClick: () => {
4344
+ onChange(option);
4345
+ setIsOpen(false);
4346
+ },
4347
+ children: option
4348
+ },
4349
+ option
4350
+ ))
4351
+ ] })
4352
+ ] })
4353
+ ] });
4354
+ };
4355
+
4356
+ // src/react/ZenitLayerManager.tsx
4357
+ var import_jsx_runtime6 = require("react/jsx-runtime");
4103
4358
  var FLOAT_TOLERANCE = 1e-3;
4359
+ var CATALOG_FIELD_BLACKLIST = /* @__PURE__ */ new Set([
4360
+ "mapids",
4361
+ "mapId",
4362
+ "mapIDs",
4363
+ "mapId",
4364
+ "field",
4365
+ "Field",
4366
+ "objectid",
4367
+ "OBJECTID",
4368
+ "objectId",
4369
+ "gforms",
4370
+ "GFORMS",
4371
+ "nomina",
4372
+ "NOMINA",
4373
+ "shape_area",
4374
+ "SHAPE_AREA",
4375
+ "shape_leng",
4376
+ "SHAPE_LENG",
4377
+ "fid",
4378
+ "FID",
4379
+ "gid",
4380
+ "GID",
4381
+ "created_at",
4382
+ "updated_at",
4383
+ "created_user",
4384
+ "last_edited_user",
4385
+ "globalid",
4386
+ "GLOBALID"
4387
+ ]);
4388
+ function isFieldVisible(key) {
4389
+ return !CATALOG_FIELD_BLACKLIST.has(key) && !key.startsWith("_") && !key.startsWith("__");
4390
+ }
4391
+ var matchesWhitelist = (key, whitelist) => whitelist.some((w) => w.toUpperCase() === key.toUpperCase());
4104
4392
  function areEffectiveStatesEqual(a, b) {
4105
4393
  if (a.length !== b.length) return false;
4106
4394
  return a.every((state, index) => {
@@ -4139,26 +4427,29 @@ var ZenitLayerManager = ({
4139
4427
  layerFeatureCounts,
4140
4428
  mapLayers,
4141
4429
  onApplyLayerFilter,
4142
- onClearLayerFilter
4430
+ onClearLayerFilter,
4431
+ availableFilterLayers = [],
4432
+ filterFieldWhitelist = []
4143
4433
  }) => {
4144
- const [map, setMap] = (0, import_react7.useState)(null);
4145
- const [loadingMap, setLoadingMap] = (0, import_react7.useState)(false);
4146
- const [mapError, setMapError] = (0, import_react7.useState)(null);
4147
- const [layers, setLayers] = (0, import_react7.useState)([]);
4148
- const [activeTab, setActiveTab] = (0, import_react7.useState)("layers");
4149
- const [panelVisible, setPanelVisible] = (0, import_react7.useState)(true);
4150
- const [selectedFilterLayerId, setSelectedFilterLayerId] = (0, import_react7.useState)("");
4151
- const [selectedFilterField, setSelectedFilterField] = (0, import_react7.useState)("");
4152
- const [selectedFilterValue, setSelectedFilterValue] = (0, import_react7.useState)("");
4153
- const [catalogByLayerField, setCatalogByLayerField] = (0, import_react7.useState)({});
4154
- const [loadingCatalog, setLoadingCatalog] = (0, import_react7.useState)(false);
4155
- const [applyingFilter, setApplyingFilter] = (0, import_react7.useState)(false);
4156
- const [filterError, setFilterError] = (0, import_react7.useState)(null);
4157
- const [appliedFilter, setAppliedFilter] = (0, import_react7.useState)(null);
4158
- const catalogAbortRef = (0, import_react7.useRef)(null);
4159
- const lastEmittedStatesRef = (0, import_react7.useRef)(null);
4434
+ const [map, setMap] = (0, import_react8.useState)(null);
4435
+ const [loadingMap, setLoadingMap] = (0, import_react8.useState)(false);
4436
+ const [mapError, setMapError] = (0, import_react8.useState)(null);
4437
+ const [layers, setLayers] = (0, import_react8.useState)([]);
4438
+ const [activeTab, setActiveTab] = (0, import_react8.useState)("layers");
4439
+ const [panelVisible, setPanelVisible] = (0, import_react8.useState)(true);
4440
+ const [selectedFilterLayerId, setSelectedFilterLayerId] = (0, import_react8.useState)("");
4441
+ const [selectedFilterField, setSelectedFilterField] = (0, import_react8.useState)("");
4442
+ const [selectedFilterValue, setSelectedFilterValue] = (0, import_react8.useState)("");
4443
+ const [catalogByLayerField, setCatalogByLayerField] = (0, import_react8.useState)({});
4444
+ const [catalogFieldsByLayer, setCatalogFieldsByLayer] = (0, import_react8.useState)({});
4445
+ const [loadingCatalog, setLoadingCatalog] = (0, import_react8.useState)(false);
4446
+ const [applyingFilter, setApplyingFilter] = (0, import_react8.useState)(false);
4447
+ const [filterError, setFilterError] = (0, import_react8.useState)(null);
4448
+ const [appliedFilter, setAppliedFilter] = (0, import_react8.useState)(null);
4449
+ const catalogAbortRef = (0, import_react8.useRef)(null);
4450
+ const lastEmittedStatesRef = (0, import_react8.useRef)(null);
4160
4451
  const isControlled = Array.isArray(layerStates) && typeof onLayerStatesChange === "function";
4161
- const baseStates = (0, import_react7.useMemo)(
4452
+ const baseStates = (0, import_react8.useMemo)(
4162
4453
  () => initLayerStates(
4163
4454
  layers.map((entry) => ({
4164
4455
  ...entry.mapLayer,
@@ -4169,7 +4460,7 @@ var ZenitLayerManager = ({
4169
4460
  ),
4170
4461
  [layers]
4171
4462
  );
4172
- const overrideStates = (0, import_react7.useMemo)(
4463
+ const overrideStates = (0, import_react8.useMemo)(
4173
4464
  () => layers.map(
4174
4465
  (entry) => ({
4175
4466
  layerId: entry.mapLayer.layerId,
@@ -4179,11 +4470,11 @@ var ZenitLayerManager = ({
4179
4470
  ),
4180
4471
  [layers]
4181
4472
  );
4182
- const effectiveStates = (0, import_react7.useMemo)(
4473
+ const effectiveStates = (0, import_react8.useMemo)(
4183
4474
  () => layerStates ?? applyLayerOverrides(baseStates, overrideStates),
4184
4475
  [baseStates, layerStates, overrideStates]
4185
4476
  );
4186
- const layerMetaIndex = (0, import_react7.useMemo)(() => {
4477
+ const layerMetaIndex = (0, import_react8.useMemo)(() => {
4187
4478
  const index = /* @__PURE__ */ new Map();
4188
4479
  mapLayers?.forEach((entry) => {
4189
4480
  const key = String(entry.layerId);
@@ -4197,7 +4488,7 @@ var ZenitLayerManager = ({
4197
4488
  });
4198
4489
  return index;
4199
4490
  }, [map, mapLayers]);
4200
- const resolveUserOpacity = import_react7.default.useCallback((state) => {
4491
+ const resolveUserOpacity = import_react8.default.useCallback((state) => {
4201
4492
  if (typeof state.overrideOpacity === "number") return state.overrideOpacity;
4202
4493
  if (typeof state.overrideOpacity === "string") {
4203
4494
  const parsed = Number.parseFloat(state.overrideOpacity);
@@ -4205,7 +4496,7 @@ var ZenitLayerManager = ({
4205
4496
  }
4206
4497
  return state.opacity ?? 1;
4207
4498
  }, []);
4208
- const resolveEffectiveOpacity = import_react7.default.useCallback(
4499
+ const resolveEffectiveOpacity = import_react8.default.useCallback(
4209
4500
  (layerId, userOpacity) => {
4210
4501
  if (!autoOpacityOnZoom || typeof mapZoom !== "number") {
4211
4502
  return userOpacity;
@@ -4221,7 +4512,7 @@ var ZenitLayerManager = ({
4221
4512
  },
4222
4513
  [autoOpacityConfig, autoOpacityOnZoom, layerMetaIndex, mapZoom]
4223
4514
  );
4224
- const effectiveStatesWithZoom = (0, import_react7.useMemo)(() => {
4515
+ const effectiveStatesWithZoom = (0, import_react8.useMemo)(() => {
4225
4516
  if (!autoOpacityOnZoom || typeof mapZoom !== "number") {
4226
4517
  return effectiveStates;
4227
4518
  }
@@ -4235,7 +4526,7 @@ var ZenitLayerManager = ({
4235
4526
  };
4236
4527
  });
4237
4528
  }, [autoOpacityOnZoom, effectiveStates, mapZoom, resolveEffectiveOpacity, resolveUserOpacity]);
4238
- (0, import_react7.useEffect)(() => {
4529
+ (0, import_react8.useEffect)(() => {
4239
4530
  let cancelled = false;
4240
4531
  setLoadingMap(true);
4241
4532
  setMapError(null);
@@ -4267,12 +4558,12 @@ var ZenitLayerManager = ({
4267
4558
  cancelled = true;
4268
4559
  };
4269
4560
  }, [client.maps, mapId]);
4270
- (0, import_react7.useEffect)(() => {
4561
+ (0, import_react8.useEffect)(() => {
4271
4562
  if (!showUploadTab && activeTab === "upload") {
4272
4563
  setActiveTab("layers");
4273
4564
  }
4274
4565
  }, [activeTab, showUploadTab]);
4275
- (0, import_react7.useEffect)(() => {
4566
+ (0, import_react8.useEffect)(() => {
4276
4567
  if (isControlled) return;
4277
4568
  if (!onLayerStatesChange) return;
4278
4569
  const emitStates = autoOpacityOnZoom && typeof mapZoom === "number" ? effectiveStatesWithZoom : effectiveStates;
@@ -4290,7 +4581,7 @@ var ZenitLayerManager = ({
4290
4581
  mapZoom,
4291
4582
  onLayerStatesChange
4292
4583
  ]);
4293
- const updateLayerVisible = import_react7.default.useCallback(
4584
+ const updateLayerVisible = import_react8.default.useCallback(
4294
4585
  (layerId, visible) => {
4295
4586
  if (!onLayerStatesChange) return;
4296
4587
  const next = effectiveStates.map(
@@ -4300,7 +4591,7 @@ var ZenitLayerManager = ({
4300
4591
  },
4301
4592
  [effectiveStates, onLayerStatesChange]
4302
4593
  );
4303
- const updateLayerOpacity = import_react7.default.useCallback(
4594
+ const updateLayerOpacity = import_react8.default.useCallback(
4304
4595
  (layerId, opacity) => {
4305
4596
  if (!onLayerStatesChange) return;
4306
4597
  const adjustedOpacity = resolveEffectiveOpacity(layerId, opacity);
@@ -4311,7 +4602,7 @@ var ZenitLayerManager = ({
4311
4602
  },
4312
4603
  [effectiveStates, onLayerStatesChange, resolveEffectiveOpacity]
4313
4604
  );
4314
- const resolveFeatureCount = import_react7.default.useCallback(
4605
+ const resolveFeatureCount = import_react8.default.useCallback(
4315
4606
  (layerId, layer) => {
4316
4607
  const resolvedFeatureCount = layerFeatureCounts?.[layerId] ?? layerFeatureCounts?.[String(layerId)];
4317
4608
  if (typeof resolvedFeatureCount === "number") return resolvedFeatureCount;
@@ -4320,7 +4611,7 @@ var ZenitLayerManager = ({
4320
4611
  },
4321
4612
  [layerFeatureCounts]
4322
4613
  );
4323
- const decoratedLayers = (0, import_react7.useMemo)(() => {
4614
+ const decoratedLayers = (0, import_react8.useMemo)(() => {
4324
4615
  return layers.map((entry) => ({
4325
4616
  ...entry,
4326
4617
  effective: effectiveStates.find((state) => state.layerId === entry.mapLayer.layerId),
@@ -4349,7 +4640,7 @@ var ZenitLayerManager = ({
4349
4640
  return String(a.mapLayer.layerId).localeCompare(String(b.mapLayer.layerId));
4350
4641
  });
4351
4642
  }, [effectiveStates, layers, resolveFeatureCount]);
4352
- const hasPrefilters = (0, import_react7.useMemo)(() => {
4643
+ const hasPrefilters = (0, import_react8.useMemo)(() => {
4353
4644
  const candidates = [...mapLayers ?? [], ...map?.mapLayers ?? []];
4354
4645
  return candidates.some((layer) => {
4355
4646
  const record = layer;
@@ -4357,23 +4648,32 @@ var ZenitLayerManager = ({
4357
4648
  return !!applied && typeof applied === "object" && Object.keys(applied).length > 0;
4358
4649
  });
4359
4650
  }, [map?.mapLayers, mapLayers]);
4360
- const filterableLayers = (0, import_react7.useMemo)(() => {
4651
+ const filterableLayers = (0, import_react8.useMemo)(() => {
4652
+ const forcedLayerIds = new Set(availableFilterLayers.map((layerId) => String(layerId)));
4361
4653
  return decoratedLayers.filter((entry) => {
4362
4654
  const prefilters = entry.mapLayer.layerConfig?.prefilters;
4363
- return !!prefilters && Object.keys(prefilters).length > 0;
4655
+ if (prefilters && Object.keys(prefilters).length > 0) return true;
4656
+ if (forcedLayerIds.has(String(entry.mapLayer.layerId))) return true;
4657
+ const layerType = (entry.mapLayer.layerType ?? entry.layer?.layerType ?? "").toString().toLowerCase();
4658
+ return layerType === "multipolygon";
4364
4659
  });
4365
- }, [decoratedLayers]);
4366
- const selectedFilterLayer = (0, import_react7.useMemo)(
4660
+ }, [availableFilterLayers, decoratedLayers]);
4661
+ const selectedFilterLayer = (0, import_react8.useMemo)(
4367
4662
  () => filterableLayers.find((layer) => String(layer.mapLayer.layerId) === selectedFilterLayerId) ?? null,
4368
4663
  [filterableLayers, selectedFilterLayerId]
4369
4664
  );
4370
- const filterFields = (0, import_react7.useMemo)(() => {
4371
- const prefilters = selectedFilterLayer?.mapLayer.layerConfig?.prefilters;
4372
- return prefilters ? Object.keys(prefilters) : [];
4373
- }, [selectedFilterLayer]);
4665
+ const filterFields = (0, import_react8.useMemo)(() => {
4666
+ if (!selectedFilterLayer) return [];
4667
+ const prefilters = selectedFilterLayer.mapLayer.layerConfig?.prefilters;
4668
+ if (prefilters) {
4669
+ const keys = Object.keys(prefilters);
4670
+ if (keys.length > 0) return keys;
4671
+ }
4672
+ return catalogFieldsByLayer[String(selectedFilterLayer.mapLayer.layerId)] ?? [];
4673
+ }, [catalogFieldsByLayer, selectedFilterLayer]);
4374
4674
  const activeCatalogKey = selectedFilterLayer ? `${selectedFilterLayer.mapLayer.layerId}:${selectedFilterField}` : null;
4375
4675
  const activeCatalogValues = activeCatalogKey ? catalogByLayerField[activeCatalogKey] ?? [] : [];
4376
- const extractCatalogValues = import_react7.default.useCallback((catalogData, field) => {
4676
+ const extractCatalogValues = import_react8.default.useCallback((catalogData, field) => {
4377
4677
  const values = /* @__PURE__ */ new Set();
4378
4678
  const pushValue = (value) => {
4379
4679
  if (value === null || value === void 0) return;
@@ -4410,7 +4710,46 @@ var ZenitLayerManager = ({
4410
4710
  }
4411
4711
  return [...values].sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
4412
4712
  }, []);
4413
- (0, import_react7.useEffect)(() => {
4713
+ const extractCatalogFieldMap = import_react8.default.useCallback((catalogData, whitelist) => {
4714
+ if (!catalogData || typeof catalogData !== "object") return {};
4715
+ const maybeRecord = catalogData;
4716
+ const fieldNames = /* @__PURE__ */ new Set();
4717
+ Object.entries(maybeRecord).forEach(([key, value]) => {
4718
+ if (Array.isArray(value) && key !== "items" && key !== "features") {
4719
+ if (isFieldVisible(key)) fieldNames.add(key);
4720
+ }
4721
+ });
4722
+ const items = maybeRecord.items;
4723
+ if (Array.isArray(items)) {
4724
+ items.forEach((item) => {
4725
+ if (!item || typeof item !== "object") return;
4726
+ const row = item;
4727
+ if (row.field !== null && row.field !== void 0) {
4728
+ const fieldName = String(row.field).trim();
4729
+ if (fieldName && isFieldVisible(fieldName)) fieldNames.add(fieldName);
4730
+ }
4731
+ });
4732
+ }
4733
+ const features = maybeRecord.features;
4734
+ if (Array.isArray(features)) {
4735
+ features.forEach((feature) => {
4736
+ if (!feature || typeof feature !== "object") return;
4737
+ const properties = feature.properties;
4738
+ if (!properties || typeof properties !== "object") return;
4739
+ Object.keys(properties).forEach((key) => {
4740
+ if (isFieldVisible(key)) fieldNames.add(key);
4741
+ });
4742
+ });
4743
+ }
4744
+ const normalizedWhitelist = (whitelist ?? []).map((item) => String(item).trim()).filter(Boolean);
4745
+ const resolvedFieldNames = normalizedWhitelist.length > 0 ? [...fieldNames].filter((field) => matchesWhitelist(field, normalizedWhitelist)) : [...fieldNames];
4746
+ const next = {};
4747
+ resolvedFieldNames.forEach((field) => {
4748
+ next[field] = extractCatalogValues(catalogData, field);
4749
+ });
4750
+ return next;
4751
+ }, [extractCatalogValues]);
4752
+ (0, import_react8.useEffect)(() => {
4414
4753
  if (!filterableLayers.length) {
4415
4754
  setSelectedFilterLayerId("");
4416
4755
  return;
@@ -4419,7 +4758,7 @@ var ZenitLayerManager = ({
4419
4758
  setSelectedFilterLayerId(String(filterableLayers[0].mapLayer.layerId));
4420
4759
  }
4421
4760
  }, [filterableLayers, selectedFilterLayerId]);
4422
- (0, import_react7.useEffect)(() => {
4761
+ (0, import_react8.useEffect)(() => {
4423
4762
  if (!filterFields.length) {
4424
4763
  setSelectedFilterField("");
4425
4764
  return;
@@ -4429,24 +4768,42 @@ var ZenitLayerManager = ({
4429
4768
  setSelectedFilterValue("");
4430
4769
  }
4431
4770
  }, [filterFields, selectedFilterField]);
4432
- (0, import_react7.useEffect)(() => {
4771
+ (0, import_react8.useEffect)(() => {
4433
4772
  if (hasPrefilters && activeTab === "filters") {
4434
4773
  setActiveTab("layers");
4435
4774
  }
4436
4775
  }, [activeTab, hasPrefilters]);
4437
- (0, import_react7.useEffect)(() => {
4776
+ (0, import_react8.useEffect)(() => {
4438
4777
  if (activeTab !== "filters") return;
4439
- if (!selectedFilterLayer || !selectedFilterField || !activeCatalogKey) return;
4440
- if (catalogByLayerField[activeCatalogKey]) return;
4778
+ if (!selectedFilterLayer) return;
4779
+ const layerId = selectedFilterLayer.mapLayer.layerId;
4780
+ const layerKey = String(layerId);
4781
+ const prefilters = selectedFilterLayer.mapLayer.layerConfig?.prefilters;
4782
+ const requiresCatalogForFields = !prefilters || Object.keys(prefilters).length === 0;
4783
+ const hasFieldsLoaded = (catalogFieldsByLayer[layerKey]?.length ?? 0) > 0;
4784
+ const needsLayerCatalog = requiresCatalogForFields && !hasFieldsLoaded;
4785
+ const needsFieldCatalog = Boolean(activeCatalogKey && selectedFilterField && !catalogByLayerField[activeCatalogKey]);
4786
+ if (!needsLayerCatalog && !needsFieldCatalog) return;
4441
4787
  catalogAbortRef.current?.abort();
4442
4788
  const controller = new AbortController();
4443
4789
  catalogAbortRef.current = controller;
4444
4790
  setLoadingCatalog(true);
4445
4791
  setFilterError(null);
4446
- client.layers.getLayerFeaturesCatalog(selectedFilterLayer.mapLayer.layerId).then((response) => {
4792
+ client.layers.getLayerFeaturesCatalog(layerId).then((response) => {
4447
4793
  if (controller.signal.aborted) return;
4448
- const values = extractCatalogValues(response.data, selectedFilterField);
4449
- setCatalogByLayerField((prev) => ({ ...prev, [activeCatalogKey]: values }));
4794
+ const fieldMap = extractCatalogFieldMap(response.data, filterFieldWhitelist);
4795
+ const fields = Object.keys(fieldMap);
4796
+ setCatalogFieldsByLayer((prev) => ({ ...prev, [layerKey]: fields }));
4797
+ setCatalogByLayerField((prev) => {
4798
+ const next = { ...prev };
4799
+ fields.forEach((field) => {
4800
+ const key = `${layerKey}:${field}`;
4801
+ if (!next[key]) {
4802
+ next[key] = fieldMap[field] ?? [];
4803
+ }
4804
+ });
4805
+ return next;
4806
+ });
4450
4807
  }).catch((error) => {
4451
4808
  if (controller.signal.aborted) return;
4452
4809
  const message = error instanceof Error ? error.message : "No se pudo cargar el cat\xE1logo";
@@ -4457,8 +4814,8 @@ var ZenitLayerManager = ({
4457
4814
  return () => {
4458
4815
  controller.abort();
4459
4816
  };
4460
- }, [activeCatalogKey, activeTab, catalogByLayerField, client.layers, extractCatalogValues, selectedFilterField, selectedFilterLayer]);
4461
- const handleApplyFilter = import_react7.default.useCallback(async () => {
4817
+ }, [activeCatalogKey, activeTab, catalogByLayerField, catalogFieldsByLayer, client.layers, extractCatalogFieldMap, filterFieldWhitelist, selectedFilterField, selectedFilterLayer]);
4818
+ const handleApplyFilter = import_react8.default.useCallback(async () => {
4462
4819
  if (!selectedFilterLayer || !selectedFilterField || !selectedFilterValue || !onApplyLayerFilter) return;
4463
4820
  setApplyingFilter(true);
4464
4821
  setFilterError(null);
@@ -4480,7 +4837,7 @@ var ZenitLayerManager = ({
4480
4837
  setApplyingFilter(false);
4481
4838
  }
4482
4839
  }, [onApplyLayerFilter, selectedFilterField, selectedFilterLayer, selectedFilterValue]);
4483
- const handleClearFilter = import_react7.default.useCallback(async () => {
4840
+ const handleClearFilter = import_react8.default.useCallback(async () => {
4484
4841
  if (!selectedFilterLayer) return;
4485
4842
  setApplyingFilter(true);
4486
4843
  setFilterError(null);
@@ -4495,7 +4852,7 @@ var ZenitLayerManager = ({
4495
4852
  setApplyingFilter(false);
4496
4853
  }
4497
4854
  }, [onClearLayerFilter, selectedFilterField, selectedFilterLayer]);
4498
- const resolveLayerStyle = import_react7.default.useCallback(
4855
+ const resolveLayerStyle = import_react8.default.useCallback(
4499
4856
  (layerId) => {
4500
4857
  const layerKey = String(layerId);
4501
4858
  const fromProp = mapLayers?.find((entry) => String(entry.layerId) === layerKey)?.style;
@@ -4509,6 +4866,22 @@ var ZenitLayerManager = ({
4509
4866
  },
4510
4867
  [map, mapLayers]
4511
4868
  );
4869
+ const allVisible = decoratedLayers.every(
4870
+ (entry) => entry.effective?.visible ?? false
4871
+ );
4872
+ const anyVisible = decoratedLayers.some(
4873
+ (entry) => entry.effective?.visible ?? false
4874
+ );
4875
+ const handleToggleAllLayers = import_react8.default.useCallback(() => {
4876
+ if (!onLayerStatesChange) return;
4877
+ const nextVisible = !anyVisible;
4878
+ const next = effectiveStates.map((state) => ({
4879
+ ...state,
4880
+ visible: nextVisible,
4881
+ overrideVisible: nextVisible
4882
+ }));
4883
+ onLayerStatesChange(next);
4884
+ }, [anyVisible, effectiveStates, onLayerStatesChange]);
4512
4885
  const panelStyle = {
4513
4886
  width: 360,
4514
4887
  borderLeft: side === "right" ? "1px solid #e2e8f0" : void 0,
@@ -4525,10 +4898,10 @@ var ZenitLayerManager = ({
4525
4898
  ...height ? { height } : {}
4526
4899
  };
4527
4900
  if (loadingMap) {
4528
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className, style: panelStyle, children: "Cargando capas\u2026" });
4901
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className, style: panelStyle, children: "Cargando capas\u2026" });
4529
4902
  }
4530
4903
  if (mapError) {
4531
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className, style: { ...panelStyle, color: "#c53030" }, children: [
4904
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className, style: { ...panelStyle, color: "#c53030" }, children: [
4532
4905
  "Error al cargar mapa: ",
4533
4906
  mapError
4534
4907
  ] });
@@ -4546,7 +4919,7 @@ var ZenitLayerManager = ({
4546
4919
  boxShadow: "0 1px 0 rgba(148, 163, 184, 0.25)"
4547
4920
  };
4548
4921
  const renderLayerCards = () => {
4549
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: decoratedLayers.map((layerState) => {
4922
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: decoratedLayers.map((layerState) => {
4550
4923
  const layerId = layerState.mapLayer.layerId;
4551
4924
  const layerName = layerState.layerName ?? `Capa ${layerId}`;
4552
4925
  const visible = layerState.effective?.visible ?? false;
@@ -4556,7 +4929,7 @@ var ZenitLayerManager = ({
4556
4929
  const muted = !visible;
4557
4930
  const opacityPercent = Math.round(userOpacity * 100);
4558
4931
  const sliderBackground = `linear-gradient(to right, ${layerColor} 0%, ${layerColor} ${opacityPercent}%, #e5e7eb ${opacityPercent}%, #e5e7eb 100%)`;
4559
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
4932
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4560
4933
  "div",
4561
4934
  {
4562
4935
  className: `zlm-card${muted ? " is-muted" : ""}`,
@@ -4571,9 +4944,9 @@ var ZenitLayerManager = ({
4571
4944
  width: "100%"
4572
4945
  },
4573
4946
  children: [
4574
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", gap: 12 }, children: [
4575
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", gap: 10, alignItems: "flex-start", minWidth: 0, flex: 1 }, children: [
4576
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4947
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", gap: 12 }, children: [
4948
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", gap: 10, alignItems: "flex-start", minWidth: 0, flex: 1 }, children: [
4949
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4577
4950
  "div",
4578
4951
  {
4579
4952
  style: {
@@ -4588,7 +4961,7 @@ var ZenitLayerManager = ({
4588
4961
  title: "Color de la capa"
4589
4962
  }
4590
4963
  ),
4591
- showLayerVisibilityIcon && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4964
+ showLayerVisibilityIcon && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4592
4965
  "button",
4593
4966
  {
4594
4967
  type: "button",
@@ -4599,11 +4972,11 @@ var ZenitLayerManager = ({
4599
4972
  )
4600
4973
  ),
4601
4974
  "aria-label": visible ? "Ocultar capa" : "Mostrar capa",
4602
- 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 })
4975
+ 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 })
4603
4976
  }
4604
4977
  ),
4605
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { minWidth: 0, flex: 1 }, children: [
4606
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4978
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { minWidth: 0, flex: 1 }, children: [
4979
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4607
4980
  "div",
4608
4981
  {
4609
4982
  className: "zlm-layer-name",
@@ -4621,26 +4994,26 @@ var ZenitLayerManager = ({
4621
4994
  children: layerName
4622
4995
  }
4623
4996
  ),
4624
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { color: muted ? "#94a3b8" : "#64748b", fontSize: 12 }, children: [
4997
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { color: muted ? "#94a3b8" : "#64748b", fontSize: 12 }, children: [
4625
4998
  "ID ",
4626
4999
  layerId
4627
5000
  ] })
4628
5001
  ] })
4629
5002
  ] }),
4630
- /* @__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: [
5003
+ /* @__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: [
4631
5004
  featureCount.toLocaleString(),
4632
5005
  " features"
4633
5006
  ] }) })
4634
5007
  ] }),
4635
- /* @__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: [
4636
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 6, color: "#64748b", fontSize: 12 }, children: [
4637
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Opacidad" }),
4638
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
5008
+ /* @__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: [
5009
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 6, color: "#64748b", fontSize: 12 }, children: [
5010
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Opacidad" }),
5011
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
4639
5012
  opacityPercent,
4640
5013
  "%"
4641
5014
  ] })
4642
5015
  ] }),
4643
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5016
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4644
5017
  "input",
4645
5018
  {
4646
5019
  className: "zlm-range",
@@ -4678,8 +5051,8 @@ var ZenitLayerManager = ({
4678
5051
  );
4679
5052
  }) });
4680
5053
  };
4681
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: ["zenit-layer-manager", className].filter(Boolean).join(" "), style: panelStyle, children: [
4682
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: `
5054
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: ["zenit-layer-manager", className].filter(Boolean).join(" "), style: panelStyle, children: [
5055
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `
4683
5056
  .zenit-layer-manager .zlm-card {
4684
5057
  transition: box-shadow 0.2s ease, transform 0.2s ease, opacity 0.2s ease;
4685
5058
  box-shadow: 0 6px 16px rgba(15, 23, 42, 0.08);
@@ -4774,16 +5147,16 @@ var ZenitLayerManager = ({
4774
5147
  outline-offset: 2px;
4775
5148
  }
4776
5149
  ` }),
4777
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: headerStyle, children: [
4778
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
4779
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
4780
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { fontWeight: 800, fontSize: 16, color: "#0f172a" }, children: "Gesti\xF3n de Capas" }),
4781
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { color: "#64748b", fontSize: 12 }, children: [
5150
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: headerStyle, children: [
5151
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
5152
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
5153
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontWeight: 800, fontSize: 16, color: "#0f172a" }, children: "Gesti\xF3n de Capas" }),
5154
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { color: "#64748b", fontSize: 12 }, children: [
4782
5155
  "Mapa #",
4783
5156
  map.id
4784
5157
  ] })
4785
5158
  ] }),
4786
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
5159
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4787
5160
  "button",
4788
5161
  {
4789
5162
  type: "button",
@@ -4791,13 +5164,13 @@ var ZenitLayerManager = ({
4791
5164
  className: "zlm-panel-toggle",
4792
5165
  "aria-label": panelVisible ? "Ocultar panel de capas" : "Mostrar panel de capas",
4793
5166
  children: [
4794
- 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 }),
5167
+ 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 }),
4795
5168
  panelVisible ? "Ocultar" : "Mostrar"
4796
5169
  ]
4797
5170
  }
4798
5171
  )
4799
5172
  ] }),
4800
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
5173
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4801
5174
  "div",
4802
5175
  {
4803
5176
  style: {
@@ -4810,38 +5183,38 @@ var ZenitLayerManager = ({
4810
5183
  background: "#f1f5f9"
4811
5184
  },
4812
5185
  children: [
4813
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
5186
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4814
5187
  "button",
4815
5188
  {
4816
5189
  type: "button",
4817
5190
  className: `zlm-tab${activeTab === "layers" ? " is-active" : ""}`,
4818
5191
  onClick: () => setActiveTab("layers"),
4819
5192
  children: [
4820
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.Layers, { size: 16 }),
5193
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.Layers, { size: 16 }),
4821
5194
  "Capas"
4822
5195
  ]
4823
5196
  }
4824
5197
  ),
4825
- showUploadTab && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
5198
+ showUploadTab && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4826
5199
  "button",
4827
5200
  {
4828
5201
  type: "button",
4829
5202
  className: `zlm-tab${activeTab === "upload" ? " is-active" : ""}`,
4830
5203
  onClick: () => setActiveTab("upload"),
4831
5204
  children: [
4832
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.Upload, { size: 16 }),
5205
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.Upload, { size: 16 }),
4833
5206
  "Subir"
4834
5207
  ]
4835
5208
  }
4836
5209
  ),
4837
- !hasPrefilters && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
5210
+ !hasPrefilters && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4838
5211
  "button",
4839
5212
  {
4840
5213
  type: "button",
4841
5214
  className: `zlm-tab${activeTab === "filters" ? " is-active" : ""}`,
4842
5215
  onClick: () => setActiveTab("filters"),
4843
5216
  children: [
4844
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.Layers, { size: 16 }),
5217
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.Layers, { size: 16 }),
4845
5218
  "Filtros"
4846
5219
  ]
4847
5220
  }
@@ -4850,13 +5223,29 @@ var ZenitLayerManager = ({
4850
5223
  }
4851
5224
  )
4852
5225
  ] }),
4853
- panelVisible && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { padding: "12px 10px 18px", overflowY: "auto", flex: 1, minHeight: 0 }, children: [
4854
- hasPrefilters && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "zlm-badge", style: { marginBottom: 10 }, children: "Este mapa ya incluye filtros preaplicados" }),
4855
- activeTab === "layers" && renderLayerCards(),
4856
- !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: [
4857
- filterableLayers.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
5226
+ panelVisible && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { padding: "12px 10px 18px", overflowY: "auto", flex: 1, minHeight: 0 }, children: [
5227
+ hasPrefilters && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "zlm-badge", style: { marginBottom: 10 }, children: "Este mapa ya incluye filtros preaplicados" }),
5228
+ activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
5229
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { marginBottom: 10 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
5230
+ "button",
5231
+ {
5232
+ type: "button",
5233
+ className: "zlm-panel-toggle",
5234
+ onClick: handleToggleAllLayers,
5235
+ disabled: decoratedLayers.length === 0,
5236
+ "aria-label": anyVisible ? "Ocultar todas las capas" : "Mostrar todas las capas",
5237
+ children: [
5238
+ 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 }),
5239
+ anyVisible ? "Ocultar todas" : "Mostrar todas"
5240
+ ]
5241
+ }
5242
+ ) }),
5243
+ renderLayerCards()
5244
+ ] }),
5245
+ !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: [
5246
+ filterableLayers.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
4858
5247
  "Capa",
4859
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5248
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4860
5249
  ZenitSelect,
4861
5250
  {
4862
5251
  ariaLabel: "Seleccionar capa para filtrar",
@@ -4869,9 +5258,9 @@ var ZenitLayerManager = ({
4869
5258
  }
4870
5259
  )
4871
5260
  ] }),
4872
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
5261
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
4873
5262
  "Campo",
4874
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5263
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4875
5264
  ZenitSelect,
4876
5265
  {
4877
5266
  ariaLabel: "Seleccionar campo de filtrado",
@@ -4884,34 +5273,31 @@ var ZenitLayerManager = ({
4884
5273
  }
4885
5274
  )
4886
5275
  ] }),
4887
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
5276
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "#475569" }, children: [
4888
5277
  "Valor",
4889
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4890
- ZenitSelect,
5278
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5279
+ ZenitCombobox,
4891
5280
  {
4892
- ariaLabel: "Seleccionar valor de filtrado",
4893
5281
  value: selectedFilterValue,
4894
5282
  placeholder: "Seleccionar\u2026",
4895
- onValueChange: (nextValue) => setSelectedFilterValue(nextValue),
4896
- disabled: loadingCatalog || activeCatalogValues.length === 0,
4897
- options: activeCatalogValues.map((catalogValue) => ({
4898
- value: catalogValue,
4899
- label: catalogValue
4900
- }))
5283
+ searchPlaceholder: "Buscar valor\u2026",
5284
+ onChange: (nextValue) => setSelectedFilterValue(nextValue),
5285
+ options: activeCatalogValues,
5286
+ disabled: loadingCatalog || activeCatalogValues.length === 0
4901
5287
  }
4902
5288
  )
4903
5289
  ] }),
4904
- loadingCatalog && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { color: "#64748b", fontSize: 12 }, children: "Cargando cat\xE1logo\u2026" }),
4905
- !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." }),
4906
- filterError && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { color: "#b91c1c", fontSize: 12 }, children: filterError }),
4907
- appliedFilter && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "zlm-badge", style: { alignSelf: "flex-start" }, children: [
5290
+ loadingCatalog && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { color: "#64748b", fontSize: 12 }, children: "Cargando cat\xE1logo\u2026" }),
5291
+ !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." }),
5292
+ filterError && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { color: "#b91c1c", fontSize: 12 }, children: filterError }),
5293
+ appliedFilter && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "zlm-badge", style: { alignSelf: "flex-start" }, children: [
4908
5294
  "Activo: ",
4909
5295
  appliedFilter.field,
4910
5296
  " = ",
4911
5297
  appliedFilter.value
4912
5298
  ] }),
4913
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "zlm-filter-actions", style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
4914
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5299
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "zlm-filter-actions", style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
5300
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4915
5301
  "button",
4916
5302
  {
4917
5303
  type: "button",
@@ -4921,7 +5307,7 @@ var ZenitLayerManager = ({
4921
5307
  children: applyingFilter ? "Aplicando\u2026" : "Aplicar"
4922
5308
  }
4923
5309
  ),
4924
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5310
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4925
5311
  "button",
4926
5312
  {
4927
5313
  type: "button",
@@ -4933,13 +5319,13 @@ var ZenitLayerManager = ({
4933
5319
  )
4934
5320
  ] })
4935
5321
  ] }) }),
4936
- 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." })
5322
+ 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." })
4937
5323
  ] })
4938
5324
  ] });
4939
5325
  };
4940
5326
 
4941
5327
  // src/react/ZenitFeatureFilterPanel.tsx
4942
- var import_jsx_runtime6 = require("react/jsx-runtime");
5328
+ var import_jsx_runtime7 = require("react/jsx-runtime");
4943
5329
  var ZenitFeatureFilterPanel = ({
4944
5330
  title = "Filtros",
4945
5331
  description,
@@ -4947,7 +5333,7 @@ var ZenitFeatureFilterPanel = ({
4947
5333
  style,
4948
5334
  children
4949
5335
  }) => {
4950
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
5336
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4951
5337
  "section",
4952
5338
  {
4953
5339
  className,
@@ -4960,26 +5346,26 @@ var ZenitFeatureFilterPanel = ({
4960
5346
  ...style
4961
5347
  },
4962
5348
  children: [
4963
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("header", { style: { marginBottom: 12 }, children: [
4964
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { style: { margin: 0, fontSize: 16 }, children: title }),
4965
- description && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: { margin: "6px 0 0", color: "#475569", fontSize: 13 }, children: description })
5349
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("header", { style: { marginBottom: 12 }, children: [
5350
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { style: { margin: 0, fontSize: 16 }, children: title }),
5351
+ description && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { style: { margin: "6px 0 0", color: "#475569", fontSize: 13 }, children: description })
4966
5352
  ] }),
4967
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { children })
5353
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { children })
4968
5354
  ]
4969
5355
  }
4970
5356
  );
4971
5357
  };
4972
5358
 
4973
5359
  // src/react/ai/FloatingChatBox.tsx
4974
- var import_react9 = require("react");
5360
+ var import_react10 = require("react");
4975
5361
  var import_react_dom3 = require("react-dom");
4976
5362
 
4977
5363
  // src/react/hooks/use-chat.ts
4978
- var import_react8 = require("react");
5364
+ var import_react9 = require("react");
4979
5365
  var useSendMessage = (config) => {
4980
- const [isLoading, setIsLoading] = (0, import_react8.useState)(false);
4981
- const [error, setError] = (0, import_react8.useState)(null);
4982
- const send = (0, import_react8.useCallback)(
5366
+ const [isLoading, setIsLoading] = (0, import_react9.useState)(false);
5367
+ const [error, setError] = (0, import_react9.useState)(null);
5368
+ const send = (0, import_react9.useCallback)(
4983
5369
  async (mapId, request, options) => {
4984
5370
  setIsLoading(true);
4985
5371
  setError(null);
@@ -4997,18 +5383,18 @@ var useSendMessage = (config) => {
4997
5383
  return { sendMessage: send, isLoading, error };
4998
5384
  };
4999
5385
  var useSendMessageStream = (config) => {
5000
- const [isStreaming, setIsStreaming] = (0, import_react8.useState)(false);
5001
- const [streamingText, setStreamingText] = (0, import_react8.useState)("");
5002
- const [completeResponse, setCompleteResponse] = (0, import_react8.useState)(null);
5003
- const [error, setError] = (0, import_react8.useState)(null);
5004
- const requestIdRef = (0, import_react8.useRef)(0);
5005
- const reset = (0, import_react8.useCallback)(() => {
5386
+ const [isStreaming, setIsStreaming] = (0, import_react9.useState)(false);
5387
+ const [streamingText, setStreamingText] = (0, import_react9.useState)("");
5388
+ const [completeResponse, setCompleteResponse] = (0, import_react9.useState)(null);
5389
+ const [error, setError] = (0, import_react9.useState)(null);
5390
+ const requestIdRef = (0, import_react9.useRef)(0);
5391
+ const reset = (0, import_react9.useCallback)(() => {
5006
5392
  setIsStreaming(false);
5007
5393
  setStreamingText("");
5008
5394
  setCompleteResponse(null);
5009
5395
  setError(null);
5010
5396
  }, []);
5011
- const send = (0, import_react8.useCallback)(
5397
+ const send = (0, import_react9.useCallback)(
5012
5398
  async (mapId, request, options) => {
5013
5399
  const requestId = requestIdRef.current + 1;
5014
5400
  requestIdRef.current = requestId;
@@ -5062,7 +5448,7 @@ var useSendMessageStream = (config) => {
5062
5448
  // src/react/components/MarkdownRenderer.tsx
5063
5449
  var import_react_markdown = __toESM(require("react-markdown"));
5064
5450
  var import_remark_gfm = __toESM(require("remark-gfm"));
5065
- var import_jsx_runtime7 = require("react/jsx-runtime");
5451
+ var import_jsx_runtime8 = require("react/jsx-runtime");
5066
5452
  function normalizeAssistantMarkdown(text) {
5067
5453
  if (!text || typeof text !== "string") return "";
5068
5454
  let normalized = text;
@@ -5078,28 +5464,28 @@ var MarkdownRenderer = ({ content, className }) => {
5078
5464
  if (!normalizedContent) {
5079
5465
  return null;
5080
5466
  }
5081
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className, style: { wordBreak: "break-word" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5467
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className, style: { wordBreak: "break-word" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5082
5468
  import_react_markdown.default,
5083
5469
  {
5084
5470
  remarkPlugins: [import_remark_gfm.default],
5085
5471
  components: {
5086
5472
  // Headings with proper spacing
5087
- h1: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { style: { fontSize: "1.5em", fontWeight: 700, marginTop: "1em", marginBottom: "0.5em" }, ...props, children }),
5088
- h2: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h2", { style: { fontSize: "1.3em", fontWeight: 700, marginTop: "0.9em", marginBottom: "0.45em" }, ...props, children }),
5089
- h3: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { style: { fontSize: "1.15em", fontWeight: 600, marginTop: "0.75em", marginBottom: "0.4em" }, ...props, children }),
5090
- h4: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h4", { style: { fontSize: "1.05em", fontWeight: 600, marginTop: "0.6em", marginBottom: "0.35em" }, ...props, children }),
5091
- h5: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h5", { style: { fontSize: "1em", fontWeight: 600, marginTop: "0.5em", marginBottom: "0.3em" }, ...props, children }),
5092
- h6: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h6", { style: { fontSize: "0.95em", fontWeight: 600, marginTop: "0.5em", marginBottom: "0.3em" }, ...props, children }),
5473
+ h1: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h1", { style: { fontSize: "1.5em", fontWeight: 700, marginTop: "1em", marginBottom: "0.5em" }, ...props, children }),
5474
+ h2: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h2", { style: { fontSize: "1.3em", fontWeight: 700, marginTop: "0.9em", marginBottom: "0.45em" }, ...props, children }),
5475
+ h3: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { style: { fontSize: "1.15em", fontWeight: 600, marginTop: "0.75em", marginBottom: "0.4em" }, ...props, children }),
5476
+ h4: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { style: { fontSize: "1.05em", fontWeight: 600, marginTop: "0.6em", marginBottom: "0.35em" }, ...props, children }),
5477
+ h5: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h5", { style: { fontSize: "1em", fontWeight: 600, marginTop: "0.5em", marginBottom: "0.3em" }, ...props, children }),
5478
+ h6: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h6", { style: { fontSize: "0.95em", fontWeight: 600, marginTop: "0.5em", marginBottom: "0.3em" }, ...props, children }),
5093
5479
  // Paragraphs with comfortable line height
5094
- p: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { style: { marginTop: "0.5em", marginBottom: "0.5em", lineHeight: 1.6 }, ...props, children }),
5480
+ p: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: { marginTop: "0.5em", marginBottom: "0.5em", lineHeight: 1.6 }, ...props, children }),
5095
5481
  // Lists with proper indentation
5096
- ul: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ul", { style: { paddingLeft: "1.5em", marginTop: "0.5em", marginBottom: "0.5em" }, ...props, children }),
5097
- ol: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ol", { style: { paddingLeft: "1.5em", marginTop: "0.5em", marginBottom: "0.5em" }, ...props, children }),
5098
- li: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("li", { style: { marginTop: "0.25em", marginBottom: "0.25em" }, ...props, children }),
5482
+ ul: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { style: { paddingLeft: "1.5em", marginTop: "0.5em", marginBottom: "0.5em" }, ...props, children }),
5483
+ ol: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ol", { style: { paddingLeft: "1.5em", marginTop: "0.5em", marginBottom: "0.5em" }, ...props, children }),
5484
+ li: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("li", { style: { marginTop: "0.25em", marginBottom: "0.25em" }, ...props, children }),
5099
5485
  // Code blocks
5100
5486
  code: ({ inline, children, ...props }) => {
5101
5487
  if (inline) {
5102
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5488
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5103
5489
  "code",
5104
5490
  {
5105
5491
  style: {
@@ -5114,7 +5500,7 @@ var MarkdownRenderer = ({ content, className }) => {
5114
5500
  }
5115
5501
  );
5116
5502
  }
5117
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5503
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5118
5504
  "code",
5119
5505
  {
5120
5506
  style: {
@@ -5134,9 +5520,9 @@ var MarkdownRenderer = ({ content, className }) => {
5134
5520
  );
5135
5521
  },
5136
5522
  // Pre (code block wrapper)
5137
- pre: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { style: { margin: 0 }, ...props, children }),
5523
+ pre: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { style: { margin: 0 }, ...props, children }),
5138
5524
  // Blockquotes
5139
- blockquote: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5525
+ blockquote: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5140
5526
  "blockquote",
5141
5527
  {
5142
5528
  style: {
@@ -5152,11 +5538,11 @@ var MarkdownRenderer = ({ content, className }) => {
5152
5538
  }
5153
5539
  ),
5154
5540
  // Strong/bold
5155
- strong: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("strong", { style: { fontWeight: 600 }, ...props, children }),
5541
+ strong: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("strong", { style: { fontWeight: 600 }, ...props, children }),
5156
5542
  // Emphasis/italic
5157
- em: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("em", { style: { fontStyle: "italic" }, ...props, children }),
5543
+ em: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("em", { style: { fontStyle: "italic" }, ...props, children }),
5158
5544
  // Horizontal rule
5159
- hr: (props) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5545
+ hr: (props) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5160
5546
  "hr",
5161
5547
  {
5162
5548
  style: {
@@ -5169,7 +5555,7 @@ var MarkdownRenderer = ({ content, className }) => {
5169
5555
  }
5170
5556
  ),
5171
5557
  // Tables (GFM)
5172
- 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)(
5558
+ 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)(
5173
5559
  "table",
5174
5560
  {
5175
5561
  style: {
@@ -5181,7 +5567,7 @@ var MarkdownRenderer = ({ content, className }) => {
5181
5567
  children
5182
5568
  }
5183
5569
  ) }),
5184
- th: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5570
+ th: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5185
5571
  "th",
5186
5572
  {
5187
5573
  style: {
@@ -5195,7 +5581,7 @@ var MarkdownRenderer = ({ content, className }) => {
5195
5581
  children
5196
5582
  }
5197
5583
  ),
5198
- td: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5584
+ td: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5199
5585
  "td",
5200
5586
  {
5201
5587
  style: {
@@ -5213,32 +5599,32 @@ var MarkdownRenderer = ({ content, className }) => {
5213
5599
  };
5214
5600
 
5215
5601
  // src/react/ai/FloatingChatBox.tsx
5216
- var import_jsx_runtime8 = require("react/jsx-runtime");
5217
- 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" }) });
5218
- 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: [
5219
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
5220
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
5602
+ var import_jsx_runtime9 = require("react/jsx-runtime");
5603
+ 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" }) });
5604
+ 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: [
5605
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
5606
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
5221
5607
  ] });
5222
- 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: [
5223
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "15 3 21 3 21 9" }),
5224
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "9 21 3 21 3 15" }),
5225
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
5226
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
5608
+ 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: [
5609
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "15 3 21 3 21 9" }),
5610
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "9 21 3 21 3 15" }),
5611
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
5612
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
5227
5613
  ] });
5228
- 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: [
5229
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "4 14 10 14 10 20" }),
5230
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "20 10 14 10 14 4" }),
5231
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "14", y1: "10", x2: "21", y2: "3" }),
5232
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
5614
+ 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: [
5615
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "4 14 10 14 10 20" }),
5616
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "20 10 14 10 14 4" }),
5617
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "14", y1: "10", x2: "21", y2: "3" }),
5618
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
5233
5619
  ] });
5234
- 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: [
5235
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
5236
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
5620
+ 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: [
5621
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
5622
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
5237
5623
  ] });
5238
- 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: [
5239
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }),
5240
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "2 17 12 22 22 17" }),
5241
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "2 12 12 17 22 12" })
5624
+ 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: [
5625
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }),
5626
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "2 17 12 22 22 17" }),
5627
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "2 12 12 17 22 12" })
5242
5628
  ] });
5243
5629
  var styles = {
5244
5630
  root: {
@@ -5543,42 +5929,42 @@ var FloatingChatBox = ({
5543
5929
  open: openProp
5544
5930
  }) => {
5545
5931
  const isControlled = openProp !== void 0;
5546
- const [internalOpen, setInternalOpen] = (0, import_react9.useState)(false);
5932
+ const [internalOpen, setInternalOpen] = (0, import_react10.useState)(false);
5547
5933
  const open = isControlled ? openProp : internalOpen;
5548
- const setOpen = (0, import_react9.useCallback)((value) => {
5934
+ const setOpen = (0, import_react10.useCallback)((value) => {
5549
5935
  const newValue = typeof value === "function" ? value(open) : value;
5550
5936
  if (!isControlled) {
5551
5937
  setInternalOpen(newValue);
5552
5938
  }
5553
5939
  onOpenChange?.(newValue);
5554
5940
  }, [isControlled, open, onOpenChange]);
5555
- const [expanded, setExpanded] = (0, import_react9.useState)(false);
5556
- const [messages, setMessages] = (0, import_react9.useState)([]);
5557
- const [inputValue, setInputValue] = (0, import_react9.useState)("");
5558
- const [conversationId, setConversationId] = (0, import_react9.useState)();
5559
- const [errorMessage, setErrorMessage] = (0, import_react9.useState)(null);
5560
- const [isFocused, setIsFocused] = (0, import_react9.useState)(false);
5561
- const [isMobile, setIsMobile] = (0, import_react9.useState)(false);
5562
- const messagesEndRef = (0, import_react9.useRef)(null);
5563
- const messagesContainerRef = (0, import_react9.useRef)(null);
5564
- const chatBoxRef = (0, import_react9.useRef)(null);
5565
- const chatConfig = (0, import_react9.useMemo)(() => {
5941
+ const [expanded, setExpanded] = (0, import_react10.useState)(false);
5942
+ const [messages, setMessages] = (0, import_react10.useState)([]);
5943
+ const [inputValue, setInputValue] = (0, import_react10.useState)("");
5944
+ const [conversationId, setConversationId] = (0, import_react10.useState)();
5945
+ const [errorMessage, setErrorMessage] = (0, import_react10.useState)(null);
5946
+ const [isFocused, setIsFocused] = (0, import_react10.useState)(false);
5947
+ const [isMobile, setIsMobile] = (0, import_react10.useState)(false);
5948
+ const messagesEndRef = (0, import_react10.useRef)(null);
5949
+ const messagesContainerRef = (0, import_react10.useRef)(null);
5950
+ const chatBoxRef = (0, import_react10.useRef)(null);
5951
+ const chatConfig = (0, import_react10.useMemo)(() => {
5566
5952
  if (!baseUrl) return void 0;
5567
5953
  return { baseUrl, accessToken, getAccessToken };
5568
5954
  }, [accessToken, baseUrl, getAccessToken]);
5569
5955
  const { sendMessage: sendMessage2, isStreaming, streamingText, completeResponse } = useSendMessageStream(chatConfig);
5570
5956
  const canSend = Boolean(mapId) && Boolean(baseUrl) && inputValue.trim().length > 0 && !isStreaming;
5571
- (0, import_react9.useEffect)(() => {
5957
+ (0, import_react10.useEffect)(() => {
5572
5958
  if (open && isMobile) {
5573
5959
  setExpanded(true);
5574
5960
  }
5575
5961
  }, [open, isMobile]);
5576
- const scrollToBottom = (0, import_react9.useCallback)(() => {
5962
+ const scrollToBottom = (0, import_react10.useCallback)(() => {
5577
5963
  if (messagesEndRef.current) {
5578
5964
  messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
5579
5965
  }
5580
5966
  }, []);
5581
- (0, import_react9.useEffect)(() => {
5967
+ (0, import_react10.useEffect)(() => {
5582
5968
  if (open && messages.length === 0) {
5583
5969
  setMessages([
5584
5970
  {
@@ -5589,10 +5975,10 @@ var FloatingChatBox = ({
5589
5975
  ]);
5590
5976
  }
5591
5977
  }, [open, messages.length]);
5592
- (0, import_react9.useEffect)(() => {
5978
+ (0, import_react10.useEffect)(() => {
5593
5979
  scrollToBottom();
5594
5980
  }, [messages, streamingText, scrollToBottom]);
5595
- (0, import_react9.useEffect)(() => {
5981
+ (0, import_react10.useEffect)(() => {
5596
5982
  if (!open) return;
5597
5983
  if (isMobile && expanded) return;
5598
5984
  const handleClickOutside = (event) => {
@@ -5605,7 +5991,7 @@ var FloatingChatBox = ({
5605
5991
  document.removeEventListener("mousedown", handleClickOutside);
5606
5992
  };
5607
5993
  }, [open, isMobile, expanded]);
5608
- (0, import_react9.useEffect)(() => {
5994
+ (0, import_react10.useEffect)(() => {
5609
5995
  if (typeof window === "undefined") return;
5610
5996
  const mediaQuery = window.matchMedia("(max-width: 768px)");
5611
5997
  const updateMobile = () => setIsMobile(mediaQuery.matches);
@@ -5623,7 +6009,7 @@ var FloatingChatBox = ({
5623
6009
  }
5624
6010
  };
5625
6011
  }, []);
5626
- (0, import_react9.useEffect)(() => {
6012
+ (0, import_react10.useEffect)(() => {
5627
6013
  if (typeof document === "undefined") return;
5628
6014
  if (!open || !isMobile) return;
5629
6015
  document.body.style.overflow = "hidden";
@@ -5631,10 +6017,10 @@ var FloatingChatBox = ({
5631
6017
  document.body.style.overflow = "";
5632
6018
  };
5633
6019
  }, [open, isMobile]);
5634
- const addMessage = (0, import_react9.useCallback)((message) => {
6020
+ const addMessage = (0, import_react10.useCallback)((message) => {
5635
6021
  setMessages((prev) => [...prev, message]);
5636
6022
  }, []);
5637
- const handleSend = (0, import_react9.useCallback)(async () => {
6023
+ const handleSend = (0, import_react10.useCallback)(async () => {
5638
6024
  if (!mapId) {
5639
6025
  setErrorMessage("Selecciona un mapa para usar el asistente.");
5640
6026
  return;
@@ -5687,7 +6073,7 @@ var FloatingChatBox = ({
5687
6073
  sendMessage2,
5688
6074
  userId
5689
6075
  ]);
5690
- const handleKeyDown = (0, import_react9.useCallback)(
6076
+ const handleKeyDown = (0, import_react10.useCallback)(
5691
6077
  (event) => {
5692
6078
  if (event.key === "Enter" && !event.shiftKey) {
5693
6079
  event.preventDefault();
@@ -5698,20 +6084,20 @@ var FloatingChatBox = ({
5698
6084
  },
5699
6085
  [canSend, handleSend]
5700
6086
  );
5701
- const handleFollowUpClick = (0, import_react9.useCallback)((question) => {
6087
+ const handleFollowUpClick = (0, import_react10.useCallback)((question) => {
5702
6088
  setInputValue(question);
5703
6089
  }, []);
5704
6090
  const renderMetadata = (response) => {
5705
6091
  if (!response?.metadata) return null;
5706
6092
  const referencedLayers = response.metadata.referencedLayers;
5707
6093
  if (!referencedLayers || referencedLayers.length === 0) return null;
5708
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.metadataSection, children: [
5709
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.metadataTitle, children: [
5710
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LayersIcon, {}),
6094
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.metadataSection, children: [
6095
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.metadataTitle, children: [
6096
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(LayersIcon, {}),
5711
6097
  "Capas Analizadas"
5712
6098
  ] }),
5713
- /* @__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: [
5714
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("strong", { children: layer.layerName }),
6099
+ /* @__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: [
6100
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: layer.layerName }),
5715
6101
  " (",
5716
6102
  layer.featureCount,
5717
6103
  " ",
@@ -5720,7 +6106,7 @@ var FloatingChatBox = ({
5720
6106
  ] }, index)) })
5721
6107
  ] });
5722
6108
  };
5723
- const handleActionClick = (0, import_react9.useCallback)((action) => {
6109
+ const handleActionClick = (0, import_react10.useCallback)((action) => {
5724
6110
  if (isStreaming) return;
5725
6111
  setOpen(false);
5726
6112
  requestAnimationFrame(() => {
@@ -5729,9 +6115,9 @@ var FloatingChatBox = ({
5729
6115
  }, [isStreaming, setOpen, onActionClick]);
5730
6116
  const renderActions = (response) => {
5731
6117
  if (!response?.suggestedActions?.length) return null;
5732
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.actionsSection, children: [
5733
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.sectionLabel, children: "Acciones Sugeridas" }),
5734
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.actionsGrid, children: response.suggestedActions.map((action, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6118
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.actionsSection, children: [
6119
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.sectionLabel, children: "Acciones Sugeridas" }),
6120
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.actionsGrid, children: response.suggestedActions.map((action, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
5735
6121
  "button",
5736
6122
  {
5737
6123
  type: "button",
@@ -5762,9 +6148,9 @@ var FloatingChatBox = ({
5762
6148
  };
5763
6149
  const renderFollowUps = (response) => {
5764
6150
  if (!response?.followUpQuestions?.length) return null;
5765
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.actionsSection, children: [
5766
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.sectionLabel, children: "Preguntas Relacionadas" }),
5767
- /* @__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)(
6151
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.actionsSection, children: [
6152
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.sectionLabel, children: "Preguntas Relacionadas" }),
6153
+ /* @__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)(
5768
6154
  "button",
5769
6155
  {
5770
6156
  type: "button",
@@ -5793,8 +6179,8 @@ var FloatingChatBox = ({
5793
6179
  )) })
5794
6180
  ] });
5795
6181
  };
5796
- const chatContent = /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.root, children: [
5797
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `
6182
+ const chatContent = /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.root, children: [
6183
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `
5798
6184
  @keyframes zenitBlink {
5799
6185
  0%, 49% { opacity: 1; }
5800
6186
  50%, 100% { opacity: 0; }
@@ -5850,7 +6236,7 @@ var FloatingChatBox = ({
5850
6236
  }
5851
6237
  }
5852
6238
  ` }),
5853
- open && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
6239
+ open && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
5854
6240
  "div",
5855
6241
  {
5856
6242
  ref: chatBoxRef,
@@ -5864,10 +6250,10 @@ var FloatingChatBox = ({
5864
6250
  };
5865
6251
  })(),
5866
6252
  children: [
5867
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("header", { style: styles.header, children: [
5868
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { style: styles.title, children: "Asistente Zenit AI" }),
5869
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.headerButtons, children: [
5870
- !isMobile && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6253
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("header", { style: styles.header, children: [
6254
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { style: styles.title, children: "Asistente Zenit AI" }),
6255
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.headerButtons, children: [
6256
+ !isMobile && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
5871
6257
  "button",
5872
6258
  {
5873
6259
  type: "button",
@@ -5880,10 +6266,10 @@ var FloatingChatBox = ({
5880
6266
  e.currentTarget.style.background = "rgba(255, 255, 255, 0.15)";
5881
6267
  },
5882
6268
  "aria-label": expanded ? "Contraer" : "Expandir",
5883
- children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CollapseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ExpandIcon, {})
6269
+ children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CollapseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ExpandIcon, {})
5884
6270
  }
5885
6271
  ),
5886
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6272
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
5887
6273
  "button",
5888
6274
  {
5889
6275
  type: "button",
@@ -5896,20 +6282,20 @@ var FloatingChatBox = ({
5896
6282
  e.currentTarget.style.background = "rgba(255, 255, 255, 0.15)";
5897
6283
  },
5898
6284
  "aria-label": "Cerrar",
5899
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CloseIcon, {})
6285
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CloseIcon, {})
5900
6286
  }
5901
6287
  )
5902
6288
  ] })
5903
6289
  ] }),
5904
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { ref: messagesContainerRef, className: "zenit-ai-body", style: styles.messages, children: [
5905
- messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6290
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { ref: messagesContainerRef, className: "zenit-ai-body", style: styles.messages, children: [
6291
+ messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
5906
6292
  "div",
5907
6293
  {
5908
6294
  style: {
5909
6295
  ...styles.messageWrapper,
5910
6296
  alignItems: message.role === "user" ? "flex-end" : "flex-start"
5911
6297
  },
5912
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
6298
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
5913
6299
  "div",
5914
6300
  {
5915
6301
  style: {
@@ -5917,7 +6303,7 @@ var FloatingChatBox = ({
5917
6303
  ...message.role === "user" ? styles.userMessage : styles.assistantMessage
5918
6304
  },
5919
6305
  children: [
5920
- message.role === "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(MarkdownRenderer, { content: message.content }) : message.content,
6306
+ message.role === "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(MarkdownRenderer, { content: message.content }) : message.content,
5921
6307
  message.role === "assistant" && renderMetadata(message.response),
5922
6308
  message.role === "assistant" && renderActions(message.response),
5923
6309
  message.role === "assistant" && renderFollowUps(message.response)
@@ -5927,39 +6313,39 @@ var FloatingChatBox = ({
5927
6313
  },
5928
6314
  message.id
5929
6315
  )),
5930
- isStreaming && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6316
+ isStreaming && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
5931
6317
  "div",
5932
6318
  {
5933
6319
  style: {
5934
6320
  ...styles.messageWrapper,
5935
6321
  alignItems: "flex-start"
5936
6322
  },
5937
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6323
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
5938
6324
  "div",
5939
6325
  {
5940
6326
  style: {
5941
6327
  ...styles.messageBubble,
5942
6328
  ...styles.assistantMessage
5943
6329
  },
5944
- children: streamingText ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
5945
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(MarkdownRenderer, { content: streamingText }),
5946
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: styles.cursor })
5947
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.thinkingText, children: [
5948
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Pensando" }),
5949
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.typingIndicator, children: [
5950
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot }),
5951
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot }),
5952
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot })
6330
+ children: streamingText ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
6331
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(MarkdownRenderer, { content: streamingText }),
6332
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: styles.cursor })
6333
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.thinkingText, children: [
6334
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: "Pensando" }),
6335
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.typingIndicator, children: [
6336
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot }),
6337
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot }),
6338
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot })
5953
6339
  ] })
5954
6340
  ] })
5955
6341
  }
5956
6342
  )
5957
6343
  }
5958
6344
  ),
5959
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ref: messagesEndRef })
6345
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { ref: messagesEndRef })
5960
6346
  ] }),
5961
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "zenit-ai-input-area", style: styles.inputWrapper, children: [
5962
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6347
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "zenit-ai-input-area", style: styles.inputWrapper, children: [
6348
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
5963
6349
  "textarea",
5964
6350
  {
5965
6351
  style: {
@@ -5976,7 +6362,7 @@ var FloatingChatBox = ({
5976
6362
  disabled: !mapId || !baseUrl || isStreaming
5977
6363
  }
5978
6364
  ),
5979
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6365
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
5980
6366
  "button",
5981
6367
  {
5982
6368
  type: "button",
@@ -5985,18 +6371,18 @@ var FloatingChatBox = ({
5985
6371
  onClick: () => void handleSend(),
5986
6372
  disabled: !canSend,
5987
6373
  "aria-label": "Enviar mensaje",
5988
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SendIcon, {})
6374
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SendIcon, {})
5989
6375
  }
5990
6376
  )
5991
6377
  ] }),
5992
- errorMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.errorText, children: errorMessage }),
5993
- isStreaming && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.statusNote, children: "Generando sugerencias..." }),
5994
- !mapId && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.statusNote, children: "Selecciona un mapa para usar el asistente" }),
5995
- !baseUrl && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.statusNote, children: "Configura la baseUrl del SDK" })
6378
+ errorMessage && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.errorText, children: errorMessage }),
6379
+ isStreaming && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.statusNote, children: "Generando sugerencias..." }),
6380
+ !mapId && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.statusNote, children: "Selecciona un mapa para usar el asistente" }),
6381
+ !baseUrl && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.statusNote, children: "Configura la baseUrl del SDK" })
5996
6382
  ]
5997
6383
  }
5998
6384
  ),
5999
- !(hideButton && !open) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6385
+ !(hideButton && !open) && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
6000
6386
  "button",
6001
6387
  {
6002
6388
  type: "button",
@@ -6008,9 +6394,9 @@ var FloatingChatBox = ({
6008
6394
  },
6009
6395
  onClick: () => setOpen((prev) => !prev),
6010
6396
  "aria-label": open ? "Cerrar asistente" : "Abrir asistente Zenit AI",
6011
- children: open ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CloseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6012
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ChatIcon, {}),
6013
- !isMobile && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Asistente IA" })
6397
+ children: open ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CloseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
6398
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ChatIcon, {}),
6399
+ !isMobile && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: "Asistente IA" })
6014
6400
  ] })
6015
6401
  }
6016
6402
  )