zenit-sdk 0.0.7 → 0.0.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
@@ -75,12 +75,15 @@ __export(src_exports, {
75
75
  getZoomOpacityFactor: () => getZoomOpacityFactor,
76
76
  initLayerStates: () => initLayerStates,
77
77
  isPolygonLayer: () => isPolygonLayer,
78
+ mergeFilters: () => mergeFilters,
78
79
  normalizeBbox: () => normalizeBbox,
80
+ normalizeFilters: () => normalizeFilters,
79
81
  normalizeMapCenter: () => normalizeMapCenter,
80
82
  normalizeMapLayers: () => normalizeMapLayers,
81
83
  resetOverrides: () => resetOverrides,
82
84
  resolveLayerAccent: () => resolveLayerAccent,
83
85
  resolveLayerStrategy: () => resolveLayerStrategy,
86
+ resolveRuntimeConfig: () => resolveRuntimeConfig,
84
87
  sendMessage: () => sendMessage,
85
88
  sendMessageStream: () => sendMessageStream,
86
89
  shouldSkipGeojsonDownload: () => shouldSkipGeojsonDownload,
@@ -97,6 +100,12 @@ var HttpClient = class {
97
100
  this.resolveTokens = options.resolveTokens;
98
101
  this.resolveAuthorizationHeader = options.resolveAuthorizationHeader ?? (() => ({}));
99
102
  }
103
+ /**
104
+ * Update base URL at runtime (e.g. when a host injects config).
105
+ */
106
+ setBaseUrl(baseUrl) {
107
+ this.baseUrl = baseUrl.replace(/\/$/, "");
108
+ }
100
109
  async get(path, options = {}) {
101
110
  const headers = {
102
111
  ...options.headers,
@@ -923,6 +932,7 @@ var ZenitClient = class {
923
932
  this.accessToken = config.accessToken;
924
933
  this.refreshToken = config.refreshToken;
925
934
  this.sdkToken = config.sdkToken;
935
+ this.defaultFilters = config.defaultFilters;
926
936
  this.httpClient = new HttpClient({
927
937
  baseUrl: config.baseUrl,
928
938
  resolveTokens: () => ({ accessToken: this.accessToken, sdkToken: this.sdkToken }),
@@ -958,14 +968,78 @@ var ZenitClient = class {
958
968
  this.setAccessToken(token);
959
969
  }
960
970
  }
971
+ /**
972
+ * Update the access token at runtime.
973
+ */
961
974
  setAccessToken(token) {
962
975
  this.accessToken = token;
963
976
  this.config.accessToken = token;
964
977
  }
978
+ /**
979
+ * Update the refresh token at runtime.
980
+ */
965
981
  setRefreshToken(token) {
966
982
  this.refreshToken = token;
967
983
  this.config.refreshToken = token;
968
984
  }
985
+ /**
986
+ * Update the SDK token at runtime.
987
+ */
988
+ setSdkToken(token) {
989
+ this.sdkToken = token;
990
+ this.config.sdkToken = token;
991
+ }
992
+ /**
993
+ * Update both access token and SDK token at once.
994
+ */
995
+ setAuth(params) {
996
+ if ("accessToken" in params) {
997
+ this.setAccessToken(params.accessToken);
998
+ }
999
+ if ("sdkToken" in params) {
1000
+ this.setSdkToken(params.sdkToken);
1001
+ }
1002
+ }
1003
+ /**
1004
+ * Update base URL at runtime (e.g. injected config from a host app).
1005
+ */
1006
+ setBaseUrl(baseUrl) {
1007
+ this.config.baseUrl = baseUrl;
1008
+ this.httpClient.setBaseUrl(baseUrl);
1009
+ }
1010
+ /**
1011
+ * Store default filters for UI integrations.
1012
+ */
1013
+ setDefaultFilters(filters) {
1014
+ this.defaultFilters = filters;
1015
+ this.config.defaultFilters = filters;
1016
+ }
1017
+ /**
1018
+ * Return default filters for UI integrations.
1019
+ */
1020
+ getDefaultFilters() {
1021
+ return this.defaultFilters ? { ...this.defaultFilters } : void 0;
1022
+ }
1023
+ /**
1024
+ * Get a readonly snapshot of the current SDK config.
1025
+ */
1026
+ getConfig() {
1027
+ return { ...this.config };
1028
+ }
1029
+ /**
1030
+ * Get a readonly snapshot of runtime config for debugging or host integrations.
1031
+ */
1032
+ getRuntimeConfig() {
1033
+ return {
1034
+ baseUrl: this.config.baseUrl,
1035
+ accessToken: this.accessToken,
1036
+ sdkToken: this.sdkToken,
1037
+ defaultFilters: this.defaultFilters ? { ...this.defaultFilters } : void 0
1038
+ };
1039
+ }
1040
+ /**
1041
+ * Build an authorization header on demand using the current token values.
1042
+ */
969
1043
  getAuthorizationHeader() {
970
1044
  const header = {};
971
1045
  if (this.accessToken) {
@@ -978,6 +1052,50 @@ var ZenitClient = class {
978
1052
  }
979
1053
  };
980
1054
 
1055
+ // src/config/ZenitRuntimeConfig.ts
1056
+ var isPlainRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1057
+ var normalizeFilters = (filters) => {
1058
+ if (!isPlainRecord(filters)) {
1059
+ return {};
1060
+ }
1061
+ return { ...filters };
1062
+ };
1063
+ var mergeFilters = (base = {}, next = {}) => ({
1064
+ ...base,
1065
+ ...next
1066
+ });
1067
+ var resolveRuntimeConfig = (input) => {
1068
+ if (!isPlainRecord(input)) {
1069
+ return null;
1070
+ }
1071
+ const baseUrl = typeof input.baseUrl === "string" ? input.baseUrl : null;
1072
+ if (!baseUrl) {
1073
+ return null;
1074
+ }
1075
+ const accessToken = typeof input.accessToken === "string" ? input.accessToken : void 0;
1076
+ const sdkToken = typeof input.sdkToken === "string" ? input.sdkToken : void 0;
1077
+ let mapId;
1078
+ if (typeof input.mapId === "number" && !Number.isNaN(input.mapId)) {
1079
+ mapId = input.mapId;
1080
+ } else if (typeof input.mapId === "string" && input.mapId.trim() !== "") {
1081
+ const parsed = Number(input.mapId);
1082
+ if (!Number.isNaN(parsed)) {
1083
+ mapId = parsed;
1084
+ }
1085
+ }
1086
+ let defaultFilters;
1087
+ if (isPlainRecord(input.defaultFilters)) {
1088
+ defaultFilters = normalizeFilters(input.defaultFilters);
1089
+ }
1090
+ return {
1091
+ baseUrl,
1092
+ accessToken,
1093
+ sdkToken,
1094
+ mapId,
1095
+ defaultFilters
1096
+ };
1097
+ };
1098
+
981
1099
  // src/maps/helpers.ts
982
1100
  function toNumber(value) {
983
1101
  if (typeof value === "number" && Number.isFinite(value)) {
@@ -1403,9 +1521,9 @@ function normalizeBbox(input) {
1403
1521
  }
1404
1522
 
1405
1523
  // src/react/ZenitMap.tsx
1406
- var import_react = __toESM(require("react"));
1407
- var import_react_leaflet = require("react-leaflet");
1408
- var import_leaflet = __toESM(require("leaflet"));
1524
+ var import_react4 = __toESM(require("react"));
1525
+ var import_react_leaflet4 = require("react-leaflet");
1526
+ var import_leaflet4 = __toESM(require("leaflet"));
1409
1527
 
1410
1528
  // src/react/layerStyleHelpers.ts
1411
1529
  function resolveLayerAccent(style) {
@@ -1427,9 +1545,9 @@ function getAccentByLayerId(layerId, mapLayers) {
1427
1545
 
1428
1546
  // src/react/zoomOpacity.ts
1429
1547
  var DEFAULT_OPTIONS = {
1430
- minZoom: 10,
1431
- maxZoom: 17,
1432
- minFactor: 0.6,
1548
+ minZoom: 11,
1549
+ maxZoom: 15,
1550
+ minFactor: 0.3,
1433
1551
  maxFactor: 1,
1434
1552
  minOpacity: 0.1,
1435
1553
  maxOpacity: 0.92
@@ -1466,302 +1584,215 @@ function getEffectiveLayerOpacity(baseOpacity, zoom, layerType, geometryType, op
1466
1584
  return clampNumber(effective, settings.minOpacity, settings.maxOpacity);
1467
1585
  }
1468
1586
 
1469
- // src/react/ZenitMap.tsx
1587
+ // src/react/map/layer-geojson.tsx
1588
+ var import_react_leaflet = require("react-leaflet");
1589
+ var import_leaflet = __toESM(require("leaflet"));
1470
1590
  var import_jsx_runtime = require("react/jsx-runtime");
1471
- var DEFAULT_CENTER = [0, 0];
1472
- var DEFAULT_ZOOM = 3;
1473
- function computeBBoxFromGeojson(geojson) {
1474
- if (!geojson) return null;
1475
- if (!Array.isArray(geojson.features) || geojson.features.length === 0) return null;
1476
- const coords = [];
1477
- const collect = (candidate) => {
1478
- if (!Array.isArray(candidate)) return;
1479
- if (candidate.length === 2 && typeof candidate[0] === "number" && typeof candidate[1] === "number") {
1480
- coords.push([candidate[0], candidate[1]]);
1481
- return;
1482
- }
1483
- candidate.forEach((entry) => collect(entry));
1484
- };
1485
- geojson.features.forEach((feature) => {
1486
- collect(feature.geometry?.coordinates);
1487
- });
1488
- if (coords.length === 0) return null;
1489
- const [firstLon, firstLat] = coords[0];
1490
- const bbox = { minLon: firstLon, minLat: firstLat, maxLon: firstLon, maxLat: firstLat };
1491
- coords.forEach(([lon, lat]) => {
1492
- bbox.minLon = Math.min(bbox.minLon, lon);
1493
- bbox.minLat = Math.min(bbox.minLat, lat);
1494
- bbox.maxLon = Math.max(bbox.maxLon, lon);
1495
- bbox.maxLat = Math.max(bbox.maxLat, lat);
1496
- });
1497
- return bbox;
1591
+ var POINT_GEOMETRY_TYPES = /* @__PURE__ */ new Set(["Point", "MultiPoint"]);
1592
+ function getGeometryType(feature) {
1593
+ const t = feature?.geometry?.type;
1594
+ return typeof t === "string" ? t : null;
1498
1595
  }
1499
- function mergeBBoxes(bboxes) {
1500
- const valid = bboxes.filter((bbox) => !!bbox);
1501
- if (valid.length === 0) return null;
1502
- const first = valid[0];
1503
- return valid.slice(1).reduce(
1504
- (acc, bbox) => ({
1505
- minLon: Math.min(acc.minLon, bbox.minLon),
1506
- minLat: Math.min(acc.minLat, bbox.minLat),
1507
- maxLon: Math.max(acc.maxLon, bbox.maxLon),
1508
- maxLat: Math.max(acc.maxLat, bbox.maxLat)
1509
- }),
1510
- { ...first }
1511
- );
1596
+ function isPointGeometry(feature) {
1597
+ const geometryType = getGeometryType(feature);
1598
+ return geometryType !== null && POINT_GEOMETRY_TYPES.has(geometryType);
1512
1599
  }
1513
- function getFeatureLayerId(feature) {
1514
- const layerId = feature?.properties?.__zenit_layerId ?? feature?.properties?.layerId ?? feature?.properties?.layer_id;
1515
- if (layerId === void 0 || layerId === null) return null;
1516
- return layerId;
1600
+ function isNonPointGeometry(feature) {
1601
+ const geometryType = getGeometryType(feature);
1602
+ return geometryType !== null && !POINT_GEOMETRY_TYPES.has(geometryType);
1517
1603
  }
1518
- function escapeHtml(value) {
1519
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
1604
+ function buildFeatureCollection(features) {
1605
+ return {
1606
+ type: "FeatureCollection",
1607
+ features
1608
+ };
1520
1609
  }
1521
- var DESCRIPTION_KEYS = /* @__PURE__ */ new Set(["descripcion", "description"]);
1522
- var POPUP_EXCLUDED_KEYS = /* @__PURE__ */ new Set(["geom", "geometry"]);
1610
+ var LayerGeoJson = ({
1611
+ layerId,
1612
+ data,
1613
+ baseOpacity,
1614
+ isMobile,
1615
+ panesReady,
1616
+ mapInstance,
1617
+ fillPaneName,
1618
+ pointsPaneName,
1619
+ layerType,
1620
+ styleFn,
1621
+ onEachFeature,
1622
+ onPolygonLabel
1623
+ }) => {
1624
+ const features = data.features ?? [];
1625
+ const fillFeatures = features.filter(isNonPointGeometry);
1626
+ const pointFeatures = features.filter(isPointGeometry);
1627
+ const fillData = fillFeatures.length > 0 ? buildFeatureCollection(fillFeatures) : null;
1628
+ const pointsData = pointFeatures.length > 0 ? buildFeatureCollection(pointFeatures) : null;
1629
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1630
+ fillData && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1631
+ import_react_leaflet.GeoJSON,
1632
+ {
1633
+ data: fillData,
1634
+ pane: panesReady && mapInstance?.getPane(fillPaneName) ? fillPaneName : void 0,
1635
+ style: (feature) => styleFn(feature, layerType, baseOpacity),
1636
+ onEachFeature: (feature, layer) => {
1637
+ onEachFeature(feature, layer);
1638
+ onPolygonLabel?.(feature, layer);
1639
+ }
1640
+ },
1641
+ `fill-${layerId}`
1642
+ ),
1643
+ pointsData && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1644
+ import_react_leaflet.GeoJSON,
1645
+ {
1646
+ data: pointsData,
1647
+ pane: panesReady && mapInstance?.getPane(pointsPaneName) ? pointsPaneName : void 0,
1648
+ pointToLayer: (feature, latlng) => import_leaflet.default.circleMarker(latlng, {
1649
+ radius: isMobile ? 8 : 6,
1650
+ ...styleFn(feature, layerType, baseOpacity)
1651
+ }),
1652
+ onEachFeature
1653
+ },
1654
+ `points-${layerId}`
1655
+ )
1656
+ ] });
1657
+ };
1658
+
1659
+ // src/react/map/location-control.tsx
1660
+ var import_react2 = require("react");
1661
+ var import_react_dom = require("react-dom");
1662
+ var import_react_leaflet2 = require("react-leaflet");
1663
+ var import_leaflet3 = __toESM(require("leaflet"));
1664
+
1665
+ // src/react/hooks/use-geolocation.ts
1666
+ var import_react = require("react");
1667
+ function useGeolocation(options) {
1668
+ const [isTracking, setIsTracking] = (0, import_react.useState)(false);
1669
+ const [location, setLocation] = (0, import_react.useState)(null);
1670
+ const [error, setError] = (0, import_react.useState)(null);
1671
+ const watchIdRef = (0, import_react.useRef)(null);
1672
+ const stopTracking = (0, import_react.useCallback)(() => {
1673
+ if (watchIdRef.current !== null && typeof navigator !== "undefined" && navigator.geolocation) {
1674
+ navigator.geolocation.clearWatch(watchIdRef.current);
1675
+ }
1676
+ watchIdRef.current = null;
1677
+ setIsTracking(false);
1678
+ }, []);
1679
+ const startTracking = (0, import_react.useCallback)(() => {
1680
+ if (typeof navigator === "undefined" || !navigator.geolocation) {
1681
+ setError({ code: 0, message: "La geolocalizaci\xF3n no est\xE1 disponible en este navegador." });
1682
+ return;
1683
+ }
1684
+ setError(null);
1685
+ watchIdRef.current = navigator.geolocation.watchPosition(
1686
+ (position) => {
1687
+ setLocation({
1688
+ lat: position.coords.latitude,
1689
+ lon: position.coords.longitude,
1690
+ accuracy: position.coords.accuracy
1691
+ });
1692
+ setIsTracking(true);
1693
+ },
1694
+ (err) => {
1695
+ setError({ code: err.code, message: err.message });
1696
+ stopTracking();
1697
+ },
1698
+ {
1699
+ enableHighAccuracy: options?.enableHighAccuracy ?? true,
1700
+ timeout: options?.timeout ?? 12e3,
1701
+ maximumAge: options?.maximumAge ?? 0
1702
+ }
1703
+ );
1704
+ }, [options?.enableHighAccuracy, options?.maximumAge, options?.timeout, stopTracking]);
1705
+ const toggleTracking = (0, import_react.useCallback)(() => {
1706
+ if (isTracking) {
1707
+ stopTracking();
1708
+ } else {
1709
+ startTracking();
1710
+ }
1711
+ }, [isTracking, startTracking, stopTracking]);
1712
+ const clearError = (0, import_react.useCallback)(() => setError(null), []);
1713
+ (0, import_react.useEffect)(() => {
1714
+ return () => {
1715
+ stopTracking();
1716
+ };
1717
+ }, [stopTracking]);
1718
+ return {
1719
+ isTracking,
1720
+ location,
1721
+ error,
1722
+ startTracking,
1723
+ stopTracking,
1724
+ toggleTracking,
1725
+ clearError
1726
+ };
1727
+ }
1728
+
1729
+ // src/react/map/map-utils.ts
1730
+ var import_leaflet2 = __toESM(require("leaflet"));
1523
1731
  var POPUP_STYLE_ID = "zenit-leaflet-popup-styles";
1524
- var DESKTOP_POPUP_DIMENSIONS = { maxWidth: 350, minWidth: 280, maxHeight: 480 };
1525
- var MOBILE_POPUP_DIMENSIONS = { maxWidth: 280, minWidth: 240, maxHeight: 380 };
1732
+ var POPUP_EXCLUDED_KEYS = /* @__PURE__ */ new Set(["geom", "geometry", "_private"]);
1733
+ var POPUP_HEADER_KEYS = ["nombre", "name", "title", "titulo"];
1734
+ var DESKTOP_POPUP_DIMENSIONS = { maxWidth: 360, minWidth: 280, maxHeight: 520 };
1735
+ var MOBILE_POPUP_DIMENSIONS = { maxWidth: 300, minWidth: 240, maxHeight: 420 };
1526
1736
  var ZENIT_LEAFLET_POPUP_STYLES = `
1527
- /* ===== Zenit Leaflet Popup - Modern Professional Styling ===== */
1528
-
1529
- /* Main popup wrapper */
1530
- .zenit-leaflet-popup .leaflet-popup-content-wrapper {
1737
+ .custom-leaflet-popup .leaflet-popup-content-wrapper {
1531
1738
  border-radius: 12px;
1532
- box-shadow:
1533
- 0 4px 6px -1px rgba(0, 0, 0, 0.1),
1534
- 0 2px 4px -2px rgba(0, 0, 0, 0.1),
1535
- 0 0 0 1px rgba(0, 0, 0, 0.05);
1536
1739
  padding: 0;
1537
1740
  background: #ffffff;
1538
- overflow: hidden;
1741
+ box-shadow: 0 12px 24px rgba(15, 23, 42, 0.18);
1742
+ border: 1px solid rgba(15, 23, 42, 0.08);
1539
1743
  }
1540
1744
 
1541
- /* Content area with scroll support */
1542
- .zenit-leaflet-popup .leaflet-popup-content {
1745
+ .custom-leaflet-popup .leaflet-popup-content {
1543
1746
  margin: 0;
1544
- padding: 0;
1747
+ padding: 12px 14px;
1545
1748
  font-size: 13px;
1546
- line-height: 1.5;
1547
- color: #374151;
1548
- min-width: 100%;
1549
- overflow-y: auto;
1550
- overflow-x: hidden;
1551
- scrollbar-width: thin;
1552
- scrollbar-color: rgba(156, 163, 175, 0.5) transparent;
1553
- }
1554
-
1555
- /* Popup tip/arrow shadow */
1556
- .zenit-leaflet-popup .leaflet-popup-tip-container {
1557
- filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
1558
- }
1559
-
1560
- .zenit-leaflet-popup .leaflet-popup-tip {
1561
- background: #ffffff;
1562
- box-shadow: none;
1563
- }
1564
-
1565
- /* Close button styling */
1566
- .zenit-leaflet-popup .leaflet-popup-close-button {
1567
- color: #9ca3af;
1568
- font-size: 18px;
1569
- font-weight: 400;
1570
- width: 28px;
1571
- height: 28px;
1572
- padding: 0;
1573
- margin: 8px 8px 0 0;
1574
- display: flex;
1575
- align-items: center;
1576
- justify-content: center;
1577
- border-radius: 6px;
1578
- transition: all 0.15s ease;
1579
- z-index: 10;
1580
- }
1581
-
1582
- .zenit-leaflet-popup .leaflet-popup-close-button:hover {
1583
- color: #374151;
1584
- background-color: #f3f4f6;
1585
- }
1586
-
1587
- .zenit-leaflet-popup .leaflet-popup-close-button:active {
1588
- background-color: #e5e7eb;
1589
- }
1590
-
1591
- /* Main card container */
1592
- .zenit-popup-card {
1593
- display: flex;
1594
- flex-direction: column;
1595
- gap: 0;
1596
- padding: 16px;
1597
- }
1598
-
1599
- /* Individual row styling with subtle separator */
1600
- .zenit-popup-row {
1601
- display: flex;
1602
- flex-direction: column;
1603
- gap: 2px;
1604
- padding: 10px 0;
1605
- border-bottom: 1px solid #f3f4f6;
1606
- }
1607
-
1608
- .zenit-popup-row:first-child {
1609
- padding-top: 0;
1610
- }
1611
-
1612
- .zenit-popup-row:last-child {
1613
- border-bottom: none;
1614
- padding-bottom: 0;
1615
- }
1616
-
1617
- /* Label styling - small, gray, uppercase */
1618
- .zenit-popup-label {
1619
- font-size: 10px;
1620
- font-weight: 500;
1621
- color: #9ca3af;
1622
- text-transform: uppercase;
1623
- letter-spacing: 0.05em;
1624
1749
  line-height: 1.4;
1750
+ color: #0f172a;
1751
+ max-height: min(70vh, 520px);
1752
+ overflow: auto;
1753
+ scrollbar-width: thin;
1754
+ scrollbar-color: rgba(148, 163, 184, 0.6) transparent;
1625
1755
  }
1626
1756
 
1627
- /* Value styling - darker, readable */
1628
- .zenit-popup-value {
1629
- font-size: 13px;
1630
- font-weight: 400;
1631
- color: #1f2937;
1632
- overflow-wrap: break-word;
1633
- word-break: break-word;
1634
- line-height: 1.5;
1635
- }
1636
-
1637
- /* Special styling for description field */
1638
- .zenit-popup-row.zenit-popup-description {
1639
- background-color: #f9fafb;
1640
- margin: 0 -16px;
1641
- padding: 12px 16px;
1642
- border-bottom: 1px solid #e5e7eb;
1643
- }
1644
-
1645
- .zenit-popup-row.zenit-popup-description:first-child {
1646
- margin-top: 0;
1647
- border-radius: 0;
1648
- }
1649
-
1650
- .zenit-popup-row.zenit-popup-description .zenit-popup-value {
1651
- font-size: 13px;
1652
- line-height: 1.6;
1653
- color: #374151;
1654
- max-height: 150px;
1655
- overflow-y: auto;
1656
- padding-right: 4px;
1657
- }
1658
-
1659
- /* Preformatted text (JSON objects) */
1660
- .zenit-popup-pre {
1661
- margin: 0;
1662
- font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
1663
- font-size: 11px;
1664
- white-space: pre-wrap;
1665
- word-break: break-word;
1666
- color: #4b5563;
1667
- background-color: #f9fafb;
1668
- padding: 8px;
1669
- border-radius: 6px;
1670
- border: 1px solid #e5e7eb;
1757
+ .custom-leaflet-popup .leaflet-popup-close-button {
1758
+ color: #64748b;
1759
+ font-size: 16px;
1760
+ padding: 6px 8px;
1761
+ border-radius: 8px;
1762
+ transition: background-color 0.15s ease, color 0.15s ease;
1671
1763
  }
1672
1764
 
1673
- /* Empty state styling */
1674
- .zenit-popup-empty {
1675
- font-size: 13px;
1676
- color: #9ca3af;
1677
- font-style: italic;
1678
- text-align: center;
1679
- padding: 20px 0;
1765
+ .custom-leaflet-popup .leaflet-popup-close-button:hover {
1766
+ color: #0f172a;
1767
+ background: rgba(148, 163, 184, 0.2);
1680
1768
  }
1681
1769
 
1682
- /* Webkit scrollbar styling */
1683
- .zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar {
1770
+ .custom-leaflet-popup .leaflet-popup-content::-webkit-scrollbar {
1684
1771
  width: 6px;
1685
1772
  }
1686
1773
 
1687
- .zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar-track {
1688
- background: transparent;
1689
- }
1690
-
1691
- .zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar-thumb {
1692
- background-color: rgba(156, 163, 175, 0.4);
1693
- border-radius: 3px;
1694
- }
1695
-
1696
- .zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar-thumb:hover {
1697
- background-color: rgba(107, 114, 128, 0.6);
1774
+ .custom-leaflet-popup .leaflet-popup-content::-webkit-scrollbar-thumb {
1775
+ background: rgba(148, 163, 184, 0.5);
1776
+ border-radius: 999px;
1698
1777
  }
1699
1778
 
1700
- /* Scrollbar for description field */
1701
- .zenit-popup-row.zenit-popup-description .zenit-popup-value::-webkit-scrollbar {
1702
- width: 4px;
1703
- }
1704
-
1705
- .zenit-popup-row.zenit-popup-description .zenit-popup-value::-webkit-scrollbar-track {
1779
+ .custom-leaflet-popup .leaflet-popup-content::-webkit-scrollbar-track {
1706
1780
  background: transparent;
1707
1781
  }
1708
1782
 
1709
- .zenit-popup-row.zenit-popup-description .zenit-popup-value::-webkit-scrollbar-thumb {
1710
- background-color: rgba(156, 163, 175, 0.4);
1711
- border-radius: 2px;
1712
- }
1713
-
1714
- /* ===== Responsive: Mobile (<640px) ===== */
1715
1783
  @media (max-width: 640px) {
1716
- .zenit-leaflet-popup .leaflet-popup-content-wrapper {
1717
- border-radius: 10px;
1718
- }
1719
-
1720
- .zenit-leaflet-popup .leaflet-popup-close-button {
1721
- width: 26px;
1722
- height: 26px;
1723
- font-size: 16px;
1724
- margin: 6px 6px 0 0;
1725
- }
1726
-
1727
- .zenit-popup-card {
1728
- padding: 12px;
1729
- }
1730
-
1731
- .zenit-popup-row {
1732
- padding: 8px 0;
1733
- }
1734
-
1735
- .zenit-popup-label {
1736
- font-size: 9px;
1737
- }
1738
-
1739
- .zenit-popup-value {
1784
+ .custom-leaflet-popup .leaflet-popup-content {
1740
1785
  font-size: 12px;
1741
- }
1742
-
1743
- .zenit-popup-row.zenit-popup-description {
1744
- margin: 0 -12px;
1745
1786
  padding: 10px 12px;
1787
+ max-height: min(65vh, 420px);
1746
1788
  }
1747
1789
 
1748
- .zenit-popup-row.zenit-popup-description .zenit-popup-value {
1749
- font-size: 12px;
1750
- max-height: 120px;
1751
- }
1752
-
1753
- .zenit-popup-pre {
1754
- font-size: 10px;
1755
- padding: 6px;
1756
- }
1757
-
1758
- .zenit-popup-empty {
1759
- font-size: 12px;
1760
- padding: 16px 0;
1790
+ .custom-leaflet-popup .leaflet-popup-close-button {
1791
+ font-size: 14px;
1792
+ padding: 4px 6px;
1761
1793
  }
1762
1794
  }
1763
1795
 
1764
- /* ===== Map tooltip styling ===== */
1765
1796
  .zenit-map-tooltip {
1766
1797
  background-color: rgba(31, 41, 55, 0.95);
1767
1798
  border: none;
@@ -1776,7 +1807,23 @@ var ZENIT_LEAFLET_POPUP_STYLES = `
1776
1807
  .zenit-map-tooltip::before {
1777
1808
  border-top-color: rgba(31, 41, 55, 0.95);
1778
1809
  }
1810
+
1811
+ .polygon-label-tooltip {
1812
+ background: rgba(15, 23, 42, 0.92);
1813
+ border: none;
1814
+ border-radius: 6px;
1815
+ color: #f8fafc;
1816
+ font-weight: 600;
1817
+ font-size: 12px;
1818
+ padding: 4px 8px;
1819
+ }
1779
1820
  `;
1821
+ function clampNumber2(value, min, max) {
1822
+ return Math.min(max, Math.max(min, value));
1823
+ }
1824
+ function clampOpacity4(value) {
1825
+ return clampNumber2(value, 0, 1);
1826
+ }
1780
1827
  function ensurePopupStyles() {
1781
1828
  if (typeof document === "undefined") return;
1782
1829
  if (document.getElementById(POPUP_STYLE_ID)) return;
@@ -1786,47 +1833,52 @@ function ensurePopupStyles() {
1786
1833
  document.head.appendChild(styleTag);
1787
1834
  }
1788
1835
  function getPopupDimensions() {
1789
- if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
1836
+ if (typeof window === "undefined") {
1790
1837
  return DESKTOP_POPUP_DIMENSIONS;
1791
1838
  }
1792
- return window.matchMedia("(max-width: 640px)").matches ? MOBILE_POPUP_DIMENSIONS : DESKTOP_POPUP_DIMENSIONS;
1793
- }
1794
- function normalizeDescriptionValue(value) {
1795
- if (value === void 0 || value === null) return null;
1796
- if (typeof value === "string") {
1797
- const trimmed = value.trim();
1798
- return trimmed ? trimmed : null;
1799
- }
1800
- if (typeof value === "number" || typeof value === "boolean") {
1801
- return String(value);
1802
- }
1803
- return null;
1839
+ const isSmallWidth = window.innerWidth < 640;
1840
+ const isShortHeight = window.innerHeight < 768;
1841
+ const base = isSmallWidth ? MOBILE_POPUP_DIMENSIONS : DESKTOP_POPUP_DIMENSIONS;
1842
+ const maxHeight = isShortHeight ? Math.min(base.maxHeight, 360) : base.maxHeight;
1843
+ return { ...base, maxHeight };
1804
1844
  }
1805
- function extractDescriptionValue(properties) {
1806
- if (!properties) return null;
1807
- const matches = Object.entries(properties).find(
1808
- ([key]) => DESCRIPTION_KEYS.has(key.toLowerCase())
1809
- );
1810
- if (!matches) return null;
1811
- return normalizeDescriptionValue(matches[1]);
1845
+ function escapeHtml(value) {
1846
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
1812
1847
  }
1813
- function safeJsonStringify(value) {
1814
- try {
1815
- const json = JSON.stringify(value, null, 2);
1816
- if (json !== void 0) return json;
1817
- } catch {
1818
- }
1819
- return String(value);
1848
+ function formatLabel(key) {
1849
+ return key.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").trim();
1820
1850
  }
1821
1851
  function renderPopupValue(value) {
1822
- if (value === null || value === void 0) {
1823
- return '<span class="zenit-popup-empty">Sin datos</span>';
1852
+ if (value === null || value === void 0) return '<span style="color:#94a3b8;">Sin datos</span>';
1853
+ if (value instanceof Date) {
1854
+ return escapeHtml(value.toLocaleDateString("es-GT"));
1855
+ }
1856
+ if (typeof value === "number") {
1857
+ return escapeHtml(value.toLocaleString("es-GT"));
1858
+ }
1859
+ if (typeof value === "string") {
1860
+ const trimmed = value.trim();
1861
+ if (!trimmed) return '<span style="color:#94a3b8;">Sin datos</span>';
1862
+ return escapeHtml(trimmed);
1824
1863
  }
1825
1864
  if (typeof value === "object") {
1826
- const json = safeJsonStringify(value);
1827
- return `<pre class="zenit-popup-pre">${escapeHtml(json)}</pre>`;
1865
+ try {
1866
+ return `<pre style="margin:0; white-space:pre-wrap; font-size:11px; background:#f8fafc; border:1px solid #e2e8f0; padding:6px 8px; border-radius:6px;">${escapeHtml(
1867
+ JSON.stringify(value, null, 2)
1868
+ )}</pre>`;
1869
+ } catch {
1870
+ return escapeHtml(String(value));
1871
+ }
1828
1872
  }
1829
- return `<span>${escapeHtml(String(value))}</span>`;
1873
+ return escapeHtml(String(value));
1874
+ }
1875
+ function extractPopupHeader(properties) {
1876
+ const entry = Object.entries(properties).find(([key, value]) => {
1877
+ if (typeof value !== "string") return false;
1878
+ const normalized = key.trim().toLowerCase();
1879
+ return POPUP_HEADER_KEYS.includes(normalized) && value.trim().length > 0;
1880
+ });
1881
+ return entry ? entry[1].trim() : null;
1830
1882
  }
1831
1883
  function shouldIncludePopupEntry(key, value) {
1832
1884
  if (!key) return false;
@@ -1838,99 +1890,480 @@ function shouldIncludePopupEntry(key, value) {
1838
1890
  if (typeof value === "string" && !value.trim()) return false;
1839
1891
  return true;
1840
1892
  }
1841
- function isDescriptionKey(key) {
1842
- const normalized = key.trim().toLowerCase();
1843
- return DESCRIPTION_KEYS.has(normalized);
1844
- }
1845
- function formatLabel(key) {
1846
- return key.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").trim();
1847
- }
1848
1893
  function createPopupContent(properties) {
1849
- const entries = Object.entries(properties).filter(
1850
- ([key, value]) => shouldIncludePopupEntry(key, value)
1851
- );
1894
+ const headerText = extractPopupHeader(properties);
1895
+ const entries = Object.entries(properties).filter(([key, value]) => {
1896
+ if (!shouldIncludePopupEntry(key, value)) return false;
1897
+ if (headerText && POPUP_HEADER_KEYS.includes(key.trim().toLowerCase())) return false;
1898
+ return true;
1899
+ });
1852
1900
  if (entries.length === 0) {
1853
- return `<div class="zenit-popup-card"><div class="zenit-popup-empty">Sin datos disponibles</div></div>`;
1854
- }
1855
- const descriptionEntry = entries.find(([key]) => isDescriptionKey(key));
1856
- const otherEntries = entries.filter(([key]) => !isDescriptionKey(key));
1857
- let rowsHtml = "";
1858
- if (descriptionEntry) {
1859
- const [key, value] = descriptionEntry;
1860
- const label = escapeHtml(formatLabel(key));
1861
- const valueHtml = renderPopupValue(value);
1862
- rowsHtml += `
1863
- <div class="zenit-popup-row zenit-popup-description">
1864
- <div class="zenit-popup-label">${label}</div>
1865
- <div class="zenit-popup-value">${valueHtml}</div>
1866
- </div>
1867
- `;
1901
+ return '<div style="padding:8px 0; color:#64748b; text-align:center;">Sin datos disponibles</div>';
1868
1902
  }
1869
- rowsHtml += otherEntries.map(([key, value]) => {
1903
+ const headerHtml = headerText ? `<div style="font-weight:700; font-size:14px; margin-bottom:8px; color:#0f172a;">${escapeHtml(
1904
+ headerText
1905
+ )}</div>` : "";
1906
+ const rowsHtml = entries.map(([key, value]) => {
1870
1907
  const label = escapeHtml(formatLabel(key));
1871
1908
  const valueHtml = renderPopupValue(value);
1872
1909
  return `
1873
- <div class="zenit-popup-row">
1874
- <div class="zenit-popup-label">${label}</div>
1875
- <div class="zenit-popup-value">${valueHtml}</div>
1910
+ <div style="display:grid; grid-template-columns:minmax(90px, 35%) 1fr; gap:8px; padding:6px 0; border-bottom:1px solid #e2e8f0;">
1911
+ <div style="font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:0.04em; color:#64748b;">${label}</div>
1912
+ <div style="font-size:13px; color:#0f172a; word-break:break-word;">${valueHtml}</div>
1876
1913
  </div>
1877
1914
  `;
1878
1915
  }).join("");
1879
- return `<div class="zenit-popup-card">${rowsHtml}</div>`;
1916
+ return `<div>${headerHtml}${rowsHtml}</div>`;
1917
+ }
1918
+ function isPolygonType(layerType, geometryType) {
1919
+ const candidate = (layerType ?? geometryType ?? "").toLowerCase();
1920
+ return candidate === "polygon" || candidate === "multipolygon";
1921
+ }
1922
+ function calculateZoomBasedOpacity(zoom, baseOpacity, layerType, geometryType) {
1923
+ if (!isPolygonType(layerType, geometryType)) return clampOpacity4(baseOpacity);
1924
+ const minZoom = 11;
1925
+ const maxZoom = 15;
1926
+ const minFactor = 0.3;
1927
+ if (maxZoom <= minZoom) return clampOpacity4(baseOpacity * minFactor);
1928
+ const t = clampNumber2((zoom - minZoom) / (maxZoom - minZoom), 0, 1);
1929
+ const factor = 1 - (1 - minFactor) * t;
1930
+ return clampOpacity4(baseOpacity * factor);
1931
+ }
1932
+ function layerStyleToLeaflet(options) {
1933
+ const { baseOpacity, zoom, layerStyle, geometryType, layerType } = options;
1934
+ const sanitizedOpacity = clampOpacity4(baseOpacity);
1935
+ const zoomOpacity = calculateZoomBasedOpacity(zoom, sanitizedOpacity, layerType, geometryType);
1936
+ const styleFillOpacity = typeof layerStyle?.fillOpacity === "number" ? clampOpacity4(layerStyle.fillOpacity) : 0.8;
1937
+ return {
1938
+ color: layerStyle?.color ?? layerStyle?.fillColor ?? "#2563eb",
1939
+ weight: layerStyle?.weight ?? 2,
1940
+ fillColor: layerStyle?.fillColor ?? layerStyle?.color ?? "#2563eb",
1941
+ opacity: clampOpacity4(Math.max(0.35, zoomOpacity * 0.9)),
1942
+ fillOpacity: clampOpacity4(zoomOpacity * styleFillOpacity)
1943
+ };
1944
+ }
1945
+ function getRgbFromColor(color) {
1946
+ const trimmed = color.trim();
1947
+ if (trimmed.startsWith("#")) {
1948
+ const hex = trimmed.replace("#", "");
1949
+ const expanded = hex.length === 3 ? hex.split("").map((char) => `${char}${char}`).join("") : hex;
1950
+ if (expanded.length === 6) {
1951
+ const r = parseInt(expanded.slice(0, 2), 16);
1952
+ const g = parseInt(expanded.slice(2, 4), 16);
1953
+ const b = parseInt(expanded.slice(4, 6), 16);
1954
+ return { r, g, b };
1955
+ }
1956
+ }
1957
+ const rgbMatch = trimmed.match(/rgba?\(([^)]+)\)/i);
1958
+ if (rgbMatch) {
1959
+ const [r, g, b] = rgbMatch[1].split(",").map((value) => parseFloat(value.trim())).slice(0, 3);
1960
+ if ([r, g, b].every((value) => Number.isFinite(value))) {
1961
+ return { r, g, b };
1962
+ }
1963
+ }
1964
+ return null;
1965
+ }
1966
+ function getLabelTextStyles(color) {
1967
+ const rgb = getRgbFromColor(color);
1968
+ if (!rgb) {
1969
+ return { color: "#0f172a", shadow: "0 1px 2px rgba(255, 255, 255, 0.6)" };
1970
+ }
1971
+ const luminance = (0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b) / 255;
1972
+ if (luminance > 0.6) {
1973
+ return { color: "#0f172a", shadow: "0 1px 2px rgba(255, 255, 255, 0.7)" };
1974
+ }
1975
+ return { color: "#ffffff", shadow: "0 1px 2px rgba(0, 0, 0, 0.4)" };
1976
+ }
1977
+ function withAlpha(color, alpha) {
1978
+ const trimmed = color.trim();
1979
+ if (trimmed.startsWith("#")) {
1980
+ const hex = trimmed.replace("#", "");
1981
+ const expanded = hex.length === 3 ? hex.split("").map((char) => `${char}${char}`).join("") : hex;
1982
+ if (expanded.length === 6) {
1983
+ const r = parseInt(expanded.slice(0, 2), 16);
1984
+ const g = parseInt(expanded.slice(2, 4), 16);
1985
+ const b = parseInt(expanded.slice(4, 6), 16);
1986
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
1987
+ }
1988
+ }
1989
+ if (trimmed.startsWith("rgb(")) {
1990
+ const inner = trimmed.slice(4, -1);
1991
+ return `rgba(${inner}, ${alpha})`;
1992
+ }
1993
+ if (trimmed.startsWith("rgba(")) {
1994
+ const inner = trimmed.slice(5, -1).split(",").slice(0, 3).map((value) => value.trim());
1995
+ return `rgba(${inner.join(", ")}, ${alpha})`;
1996
+ }
1997
+ return color;
1998
+ }
1999
+ function createCustomIcon(label, opacity, color) {
2000
+ const size = 60;
2001
+ const innerSize = 44;
2002
+ const textStyles = getLabelTextStyles(color);
2003
+ const safeLabel = escapeHtml(label);
2004
+ const clampedOpacity = Math.min(1, Math.max(0.92, opacity));
2005
+ const innerBackground = withAlpha(color, 0.9);
2006
+ return import_leaflet2.default.divIcon({
2007
+ className: "zenit-label-marker",
2008
+ iconSize: [size, size],
2009
+ iconAnchor: [size / 2, size / 2],
2010
+ html: `
2011
+ <div
2012
+ title="${safeLabel}"
2013
+ style="
2014
+ width:${size}px;
2015
+ height:${size}px;
2016
+ border-radius:9999px;
2017
+ background:rgba(255, 255, 255, 0.95);
2018
+ border:3px solid rgba(255, 255, 255, 1);
2019
+ display:flex;
2020
+ align-items:center;
2021
+ justify-content:center;
2022
+ opacity:${clampedOpacity};
2023
+ box-shadow:0 2px 6px rgba(0, 0, 0, 0.25);
2024
+ pointer-events:none;
2025
+ "
2026
+ >
2027
+ <div
2028
+ style="
2029
+ width:${innerSize}px;
2030
+ height:${innerSize}px;
2031
+ border-radius:9999px;
2032
+ background:${innerBackground};
2033
+ display:flex;
2034
+ align-items:center;
2035
+ justify-content:center;
2036
+ box-shadow:inset 0 0 0 1px rgba(15, 23, 42, 0.12);
2037
+ "
2038
+ >
2039
+ <span
2040
+ style="
2041
+ color:${textStyles.color};
2042
+ font-size:20px;
2043
+ font-weight:800;
2044
+ text-shadow:${textStyles.shadow};
2045
+ "
2046
+ >
2047
+ ${safeLabel}
2048
+ </span>
2049
+ </div>
2050
+ </div>
2051
+ `
2052
+ });
2053
+ }
2054
+ function createLocationIcon() {
2055
+ return import_leaflet2.default.divIcon({
2056
+ className: "zenit-location-marker",
2057
+ iconSize: [18, 18],
2058
+ iconAnchor: [9, 9],
2059
+ html: `
2060
+ <div style="width:18px;height:18px;border-radius:9999px;background:#2563eb;border:2px solid #fff;box-shadow:0 0 0 4px rgba(37, 99, 235, 0.25);"></div>
2061
+ `
2062
+ });
2063
+ }
2064
+
2065
+ // src/react/map/location-control.tsx
2066
+ var import_jsx_runtime2 = require("react/jsx-runtime");
2067
+ var LOCATION_STYLE_ID = "zenit-location-control-styles";
2068
+ var LOCATION_STYLES = `
2069
+ .zenit-location-control {
2070
+ display: flex;
2071
+ flex-direction: column;
2072
+ gap: 8px;
2073
+ }
2074
+
2075
+ .zenit-location-button {
2076
+ width: 42px;
2077
+ height: 42px;
2078
+ border-radius: 12px;
2079
+ border: none;
2080
+ background: #ffffff;
2081
+ color: #0f172a;
2082
+ box-shadow: 0 8px 18px rgba(15, 23, 42, 0.2);
2083
+ display: inline-flex;
2084
+ align-items: center;
2085
+ justify-content: center;
2086
+ cursor: pointer;
2087
+ position: relative;
2088
+ }
2089
+
2090
+ .zenit-location-button.zenit-location-button--tracking {
2091
+ animation: zenitLocationPulse 1.8s infinite;
2092
+ }
2093
+
2094
+ .zenit-location-button:hover {
2095
+ background: #f8fafc;
2096
+ }
2097
+
2098
+ .zenit-location-badge {
2099
+ position: absolute;
2100
+ top: -6px;
2101
+ right: -6px;
2102
+ width: 18px;
2103
+ height: 18px;
2104
+ border-radius: 999px;
2105
+ background: #ef4444;
2106
+ color: #fff;
2107
+ font-size: 11px;
2108
+ font-weight: 700;
2109
+ display: inline-flex;
2110
+ align-items: center;
2111
+ justify-content: center;
2112
+ box-shadow: 0 4px 10px rgba(239, 68, 68, 0.35);
2113
+ }
2114
+
2115
+ .zenit-location-error {
2116
+ background: rgba(15, 23, 42, 0.92);
2117
+ color: #f8fafc;
2118
+ border-radius: 10px;
2119
+ padding: 8px 10px;
2120
+ font-size: 12px;
2121
+ max-width: 200px;
2122
+ box-shadow: 0 10px 24px rgba(15, 23, 42, 0.3);
2123
+ }
2124
+
2125
+ @keyframes zenitLocationPulse {
2126
+ 0% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.35); }
2127
+ 70% { box-shadow: 0 0 0 12px rgba(16, 185, 129, 0); }
2128
+ 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
2129
+ }
2130
+ `;
2131
+ var LocateIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2132
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "12", cy: "12", r: "3" }),
2133
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "12", y1: "2", x2: "12", y2: "5" }),
2134
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "22" }),
2135
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "2", y1: "12", x2: "5", y2: "12" }),
2136
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "19", y1: "12", x2: "22", y2: "12" })
2137
+ ] });
2138
+ var LocationControl = ({ position = "bottomleft", zoom = 16 }) => {
2139
+ const map = (0, import_react_leaflet2.useMap)();
2140
+ const controlRef = (0, import_react2.useRef)(null);
2141
+ const hasCenteredRef = (0, import_react2.useRef)(false);
2142
+ const { isTracking, location, error, toggleTracking, clearError } = useGeolocation();
2143
+ (0, import_react2.useEffect)(() => {
2144
+ if (typeof document === "undefined") return;
2145
+ if (document.getElementById(LOCATION_STYLE_ID)) return;
2146
+ const styleTag = document.createElement("style");
2147
+ styleTag.id = LOCATION_STYLE_ID;
2148
+ styleTag.textContent = LOCATION_STYLES;
2149
+ document.head.appendChild(styleTag);
2150
+ }, []);
2151
+ (0, import_react2.useEffect)(() => {
2152
+ const control = import_leaflet3.default.control({ position });
2153
+ control.onAdd = () => {
2154
+ const container = import_leaflet3.default.DomUtil.create("div", "zenit-location-control");
2155
+ import_leaflet3.default.DomEvent.disableClickPropagation(container);
2156
+ controlRef.current = container;
2157
+ return container;
2158
+ };
2159
+ control.addTo(map);
2160
+ return () => {
2161
+ control.remove();
2162
+ controlRef.current = null;
2163
+ };
2164
+ }, [map, position]);
2165
+ (0, import_react2.useEffect)(() => {
2166
+ if (!location || !isTracking) return;
2167
+ if (hasCenteredRef.current) return;
2168
+ hasCenteredRef.current = true;
2169
+ map.flyTo([location.lat, location.lon], zoom, { animate: true });
2170
+ }, [isTracking, location, map, zoom]);
2171
+ const markerIcon = (0, import_react2.useMemo)(() => createLocationIcon(), []);
2172
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2173
+ controlRef.current && (0, import_react_dom.createPortal)(
2174
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
2175
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2176
+ "button",
2177
+ {
2178
+ type: "button",
2179
+ className: `zenit-location-button${isTracking ? " zenit-location-button--tracking" : ""}`,
2180
+ onClick: () => {
2181
+ if (error) {
2182
+ clearError();
2183
+ }
2184
+ toggleTracking();
2185
+ },
2186
+ "aria-label": isTracking ? "Detener ubicaci\xF3n" : "Mostrar mi ubicaci\xF3n",
2187
+ children: [
2188
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LocateIcon, {}),
2189
+ error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "zenit-location-badge", children: "!" })
2190
+ ]
2191
+ }
2192
+ ),
2193
+ error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "zenit-location-error", children: error.message || "No se pudo acceder a tu ubicaci\xF3n." })
2194
+ ] }),
2195
+ controlRef.current
2196
+ ),
2197
+ location && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2198
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_leaflet2.Marker, { position: [location.lat, location.lon], icon: markerIcon }),
2199
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2200
+ import_react_leaflet2.Circle,
2201
+ {
2202
+ center: [location.lat, location.lon],
2203
+ radius: location.accuracy,
2204
+ pathOptions: { color: "#2563eb", fillColor: "#2563eb", fillOpacity: 0.15 }
2205
+ }
2206
+ )
2207
+ ] })
2208
+ ] });
2209
+ };
2210
+
2211
+ // src/react/map/map-handlers.tsx
2212
+ var import_react3 = require("react");
2213
+ var import_react_leaflet3 = require("react-leaflet");
2214
+ function computeBBoxFromGeojson(geojson) {
2215
+ if (!geojson || !Array.isArray(geojson.features)) return null;
2216
+ const coords = [];
2217
+ const collect = (candidate) => {
2218
+ if (!Array.isArray(candidate)) return;
2219
+ if (candidate.length === 2 && typeof candidate[0] === "number" && typeof candidate[1] === "number" && Number.isFinite(candidate[0]) && Number.isFinite(candidate[1])) {
2220
+ coords.push([candidate[0], candidate[1]]);
2221
+ return;
2222
+ }
2223
+ candidate.forEach((item) => collect(item));
2224
+ };
2225
+ geojson.features.forEach((feature) => {
2226
+ collect(feature.geometry?.coordinates);
2227
+ });
2228
+ if (coords.length === 0) return null;
2229
+ const [firstLon, firstLat] = coords[0];
2230
+ const bbox = { minLon: firstLon, minLat: firstLat, maxLon: firstLon, maxLat: firstLat };
2231
+ coords.forEach(([lon, lat]) => {
2232
+ bbox.minLon = Math.min(bbox.minLon, lon);
2233
+ bbox.minLat = Math.min(bbox.minLat, lat);
2234
+ bbox.maxLon = Math.max(bbox.maxLon, lon);
2235
+ bbox.maxLat = Math.max(bbox.maxLat, lat);
2236
+ });
2237
+ return bbox;
2238
+ }
2239
+ function mergeBBoxes(bboxes) {
2240
+ const valid = bboxes.filter((bbox) => !!bbox);
2241
+ if (valid.length === 0) return null;
2242
+ const first = valid[0];
2243
+ return valid.slice(1).reduce(
2244
+ (acc, bbox) => ({
2245
+ minLon: Math.min(acc.minLon, bbox.minLon),
2246
+ minLat: Math.min(acc.minLat, bbox.minLat),
2247
+ maxLon: Math.max(acc.maxLon, bbox.maxLon),
2248
+ maxLat: Math.max(acc.maxLat, bbox.maxLat)
2249
+ }),
2250
+ { ...first }
2251
+ );
2252
+ }
2253
+ var BBoxZoomHandler = ({
2254
+ bbox,
2255
+ geojson,
2256
+ autoGeojson = [],
2257
+ enabled = true
2258
+ }) => {
2259
+ const map = (0, import_react_leaflet3.useMap)();
2260
+ const lastAppliedBBox = (0, import_react3.useRef)(null);
2261
+ const lastUserInteracted = (0, import_react3.useRef)(false);
2262
+ (0, import_react3.useEffect)(() => {
2263
+ const handleInteraction = () => {
2264
+ lastUserInteracted.current = true;
2265
+ };
2266
+ map.on("dragstart", handleInteraction);
2267
+ map.on("zoomstart", handleInteraction);
2268
+ return () => {
2269
+ map.off("dragstart", handleInteraction);
2270
+ map.off("zoomstart", handleInteraction);
2271
+ };
2272
+ }, [map]);
2273
+ (0, import_react3.useEffect)(() => {
2274
+ if (!enabled) return;
2275
+ let resolvedBBox = bbox ?? null;
2276
+ if (!resolvedBBox && geojson) {
2277
+ resolvedBBox = computeBBoxFromGeojson(geojson);
2278
+ }
2279
+ if (!resolvedBBox && autoGeojson.length > 0) {
2280
+ const bboxes = autoGeojson.map((collection) => computeBBoxFromGeojson(collection));
2281
+ resolvedBBox = mergeBBoxes(bboxes);
2282
+ }
2283
+ if (!resolvedBBox) return;
2284
+ const serialized = JSON.stringify(resolvedBBox);
2285
+ if (lastAppliedBBox.current === serialized) return;
2286
+ if (lastUserInteracted.current && !bbox && !geojson) {
2287
+ lastUserInteracted.current = false;
2288
+ return;
2289
+ }
2290
+ const bounds = [
2291
+ [resolvedBBox.minLat, resolvedBBox.minLon],
2292
+ [resolvedBBox.maxLat, resolvedBBox.maxLon]
2293
+ ];
2294
+ map.fitBounds(bounds, { padding: [12, 12] });
2295
+ lastAppliedBBox.current = serialized;
2296
+ }, [autoGeojson, bbox, enabled, geojson, map]);
2297
+ return null;
2298
+ };
2299
+ var ZoomBasedOpacityHandler = ({ onZoomChange }) => {
2300
+ const map = (0, import_react_leaflet3.useMap)();
2301
+ (0, import_react3.useEffect)(() => {
2302
+ const handleZoom = () => {
2303
+ onZoomChange(map.getZoom());
2304
+ };
2305
+ map.on("zoomend", handleZoom);
2306
+ handleZoom();
2307
+ return () => {
2308
+ map.off("zoomend", handleZoom);
2309
+ };
2310
+ }, [map, onZoomChange]);
2311
+ return null;
2312
+ };
2313
+ var MapInstanceBridge = ({ onReady }) => {
2314
+ const map = (0, import_react_leaflet3.useMap)();
2315
+ (0, import_react3.useEffect)(() => {
2316
+ onReady(map);
2317
+ }, [map, onReady]);
2318
+ return null;
2319
+ };
2320
+
2321
+ // src/react/ZenitMap.tsx
2322
+ var import_jsx_runtime3 = require("react/jsx-runtime");
2323
+ var DEFAULT_CENTER = [0, 0];
2324
+ var DEFAULT_ZOOM = 3;
2325
+ var LABELS_PANE_NAME = "zenit-labels-pane";
2326
+ function isRecord(value) {
2327
+ return typeof value === "object" && value !== null;
1880
2328
  }
1881
- function withAlpha(color, alpha) {
1882
- const trimmed = color.trim();
1883
- if (trimmed.startsWith("#")) {
1884
- const hex = trimmed.replace("#", "");
1885
- const expanded = hex.length === 3 ? hex.split("").map((char) => `${char}${char}`).join("") : hex;
1886
- if (expanded.length === 6) {
1887
- const r = parseInt(expanded.slice(0, 2), 16);
1888
- const g = parseInt(expanded.slice(2, 4), 16);
1889
- const b = parseInt(expanded.slice(4, 6), 16);
1890
- return `rgba(${r}, ${g}, ${b}, ${alpha})`;
1891
- }
1892
- }
1893
- if (trimmed.startsWith("rgb(")) {
1894
- const inner = trimmed.slice(4, -1);
1895
- return `rgba(${inner}, ${alpha})`;
1896
- }
1897
- if (trimmed.startsWith("rgba(")) {
1898
- const inner = trimmed.slice(5, -1).split(",").slice(0, 3).map((value) => value.trim());
1899
- return `rgba(${inner.join(", ")}, ${alpha})`;
2329
+ function isGeoJsonFeatureCollection(value) {
2330
+ if (!isRecord(value)) return false;
2331
+ const features = value.features;
2332
+ if (!Array.isArray(features)) return false;
2333
+ const type = value.type;
2334
+ return type === void 0 || type === "FeatureCollection";
2335
+ }
2336
+ function extractGeoJsonFeatureCollection(value) {
2337
+ if (isRecord(value) && "data" in value) {
2338
+ const data = value.data;
2339
+ return isGeoJsonFeatureCollection(data) ? data : null;
1900
2340
  }
1901
- return color;
2341
+ return isGeoJsonFeatureCollection(value) ? value : null;
1902
2342
  }
1903
- function getRgbFromColor(color) {
1904
- const trimmed = color.trim();
1905
- if (trimmed.startsWith("#")) {
1906
- const hex = trimmed.replace("#", "");
1907
- const expanded = hex.length === 3 ? hex.split("").map((char) => `${char}${char}`).join("") : hex;
1908
- if (expanded.length === 6) {
1909
- const r = parseInt(expanded.slice(0, 2), 16);
1910
- const g = parseInt(expanded.slice(2, 4), 16);
1911
- const b = parseInt(expanded.slice(4, 6), 16);
1912
- return { r, g, b };
1913
- }
2343
+ function getFeatureLayerId(feature) {
2344
+ const layerId = feature?.properties?.__zenit_layerId ?? feature?.properties?.layerId ?? feature?.properties?.layer_id;
2345
+ if (layerId === void 0 || layerId === null) return null;
2346
+ return layerId;
2347
+ }
2348
+ var DESCRIPTION_KEYS = /* @__PURE__ */ new Set(["descripcion", "description"]);
2349
+ function normalizeDescriptionValue(value) {
2350
+ if (value === void 0 || value === null) return null;
2351
+ if (typeof value === "string") {
2352
+ const trimmed = value.trim();
2353
+ return trimmed ? trimmed : null;
1914
2354
  }
1915
- const rgbMatch = trimmed.match(/rgba?\(([^)]+)\)/i);
1916
- if (rgbMatch) {
1917
- const [r, g, b] = rgbMatch[1].split(",").map((value) => parseFloat(value.trim())).slice(0, 3);
1918
- if ([r, g, b].every((value) => Number.isFinite(value))) {
1919
- return { r, g, b };
1920
- }
2355
+ if (typeof value === "number" || typeof value === "boolean") {
2356
+ return String(value);
1921
2357
  }
1922
2358
  return null;
1923
2359
  }
1924
- function getLabelTextStyles(color) {
1925
- const rgb = getRgbFromColor(color);
1926
- if (!rgb) {
1927
- return { color: "#0f172a", shadow: "0 1px 2px rgba(255, 255, 255, 0.6)" };
1928
- }
1929
- const luminance = (0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b) / 255;
1930
- if (luminance > 0.6) {
1931
- return { color: "#0f172a", shadow: "0 1px 2px rgba(255, 255, 255, 0.7)" };
1932
- }
1933
- return { color: "#ffffff", shadow: "0 1px 2px rgba(0, 0, 0, 0.4)" };
2360
+ function extractDescriptionValue(properties) {
2361
+ if (!properties) return null;
2362
+ const matches = Object.entries(properties).find(
2363
+ ([key]) => DESCRIPTION_KEYS.has(key.toLowerCase())
2364
+ );
2365
+ if (!matches) return null;
2366
+ return normalizeDescriptionValue(matches[1]);
1934
2367
  }
1935
2368
  function getFeatureStyleOverrides(feature) {
1936
2369
  const candidate = feature?.properties?._style;
@@ -1949,25 +2382,6 @@ function buildFeaturePopupHtml(feature) {
1949
2382
  const rendered = createPopupContent(properties);
1950
2383
  return rendered ? rendered : null;
1951
2384
  }
1952
- var POINT_GEOMETRY_TYPES = /* @__PURE__ */ new Set(["Point", "MultiPoint"]);
1953
- function getGeometryType(feature) {
1954
- const t = feature?.geometry?.type;
1955
- return typeof t === "string" ? t : null;
1956
- }
1957
- function isPointGeometry(feature) {
1958
- const geometryType = getGeometryType(feature);
1959
- return geometryType !== null && POINT_GEOMETRY_TYPES.has(geometryType);
1960
- }
1961
- function isNonPointGeometry(feature) {
1962
- const geometryType = getGeometryType(feature);
1963
- return geometryType !== null && !POINT_GEOMETRY_TYPES.has(geometryType);
1964
- }
1965
- function buildFeatureCollection(features) {
1966
- return {
1967
- type: "FeatureCollection",
1968
- features
1969
- };
1970
- }
1971
2385
  function pickIntersectFeature(baseFeature, candidates) {
1972
2386
  if (!Array.isArray(candidates) || candidates.length === 0) return null;
1973
2387
  const baseId = baseFeature?.id;
@@ -1994,81 +2408,7 @@ function normalizeCenterTuple(center) {
1994
2408
  }
1995
2409
  return null;
1996
2410
  }
1997
- var FitToBounds = ({ bbox }) => {
1998
- const mapInstance = (0, import_react_leaflet.useMap)();
1999
- const lastAppliedBBox = (0, import_react.useRef)(null);
2000
- (0, import_react.useEffect)(() => {
2001
- const targetBBox = bbox;
2002
- if (!targetBBox) return;
2003
- const serialized = JSON.stringify(targetBBox);
2004
- if (lastAppliedBBox.current === serialized) return;
2005
- const bounds = [
2006
- [targetBBox.minLat, targetBBox.minLon],
2007
- [targetBBox.maxLat, targetBBox.maxLon]
2008
- ];
2009
- mapInstance.fitBounds(bounds, { padding: [12, 12] });
2010
- lastAppliedBBox.current = serialized;
2011
- }, [bbox, mapInstance]);
2012
- return null;
2013
- };
2014
- var AutoFitToBounds = ({
2015
- bbox,
2016
- enabled = true
2017
- }) => {
2018
- const mapInstance = (0, import_react_leaflet.useMap)();
2019
- const lastAutoBBoxApplied = (0, import_react.useRef)(null);
2020
- const lastUserInteracted = (0, import_react.useRef)(false);
2021
- (0, import_react.useEffect)(() => {
2022
- if (!enabled) return;
2023
- const handleInteraction = () => {
2024
- lastUserInteracted.current = true;
2025
- };
2026
- mapInstance.on("dragstart", handleInteraction);
2027
- mapInstance.on("zoomstart", handleInteraction);
2028
- return () => {
2029
- mapInstance.off("dragstart", handleInteraction);
2030
- mapInstance.off("zoomstart", handleInteraction);
2031
- };
2032
- }, [enabled, mapInstance]);
2033
- (0, import_react.useEffect)(() => {
2034
- if (!enabled) return;
2035
- if (!bbox) return;
2036
- const serialized = JSON.stringify(bbox);
2037
- if (lastAutoBBoxApplied.current === serialized) return;
2038
- if (lastUserInteracted.current) {
2039
- lastUserInteracted.current = false;
2040
- }
2041
- const bounds = [
2042
- [bbox.minLat, bbox.minLon],
2043
- [bbox.maxLat, bbox.maxLon]
2044
- ];
2045
- mapInstance.fitBounds(bounds, { padding: [12, 12] });
2046
- lastAutoBBoxApplied.current = serialized;
2047
- }, [bbox, enabled, mapInstance]);
2048
- return null;
2049
- };
2050
- var ZoomBasedOpacityHandler = ({ onZoomChange }) => {
2051
- const mapInstance = (0, import_react_leaflet.useMap)();
2052
- (0, import_react.useEffect)(() => {
2053
- const handleZoom = () => {
2054
- onZoomChange(mapInstance.getZoom());
2055
- };
2056
- mapInstance.on("zoomend", handleZoom);
2057
- handleZoom();
2058
- return () => {
2059
- mapInstance.off("zoomend", handleZoom);
2060
- };
2061
- }, [mapInstance, onZoomChange]);
2062
- return null;
2063
- };
2064
- var MapInstanceBridge = ({ onReady }) => {
2065
- const mapInstance = (0, import_react_leaflet.useMap)();
2066
- (0, import_react.useEffect)(() => {
2067
- onReady(mapInstance);
2068
- }, [mapInstance, onReady]);
2069
- return null;
2070
- };
2071
- var ZenitMap = (0, import_react.forwardRef)(({
2411
+ var ZenitMap = (0, import_react4.forwardRef)(({
2072
2412
  client,
2073
2413
  mapId,
2074
2414
  height = "500px",
@@ -2093,20 +2433,21 @@ var ZenitMap = (0, import_react.forwardRef)(({
2093
2433
  onZoomChange,
2094
2434
  onMapReady
2095
2435
  }, ref) => {
2096
- const [map, setMap] = (0, import_react.useState)(null);
2097
- const [layers, setLayers] = (0, import_react.useState)([]);
2098
- const [effectiveStates, setEffectiveStates] = (0, import_react.useState)([]);
2099
- const [loadingMap, setLoadingMap] = (0, import_react.useState)(false);
2100
- const [mapError, setMapError] = (0, import_react.useState)(null);
2101
- const [mapInstance, setMapInstance] = (0, import_react.useState)(null);
2102
- const [panesReady, setPanesReady] = (0, import_react.useState)(false);
2103
- const [currentZoom, setCurrentZoom] = (0, import_react.useState)(initialZoom ?? DEFAULT_ZOOM);
2104
- const [isMobile, setIsMobile] = (0, import_react.useState)(() => {
2436
+ const [map, setMap] = (0, import_react4.useState)(null);
2437
+ const [layers, setLayers] = (0, import_react4.useState)([]);
2438
+ const [effectiveStates, setEffectiveStates] = (0, import_react4.useState)([]);
2439
+ const [loadingMap, setLoadingMap] = (0, import_react4.useState)(false);
2440
+ const [mapError, setMapError] = (0, import_react4.useState)(null);
2441
+ const [mapInstance, setMapInstance] = (0, import_react4.useState)(null);
2442
+ const [panesReady, setPanesReady] = (0, import_react4.useState)(false);
2443
+ const [currentZoom, setCurrentZoom] = (0, import_react4.useState)(initialZoom ?? DEFAULT_ZOOM);
2444
+ const [isPopupOpen, setIsPopupOpen] = (0, import_react4.useState)(false);
2445
+ const [isMobile, setIsMobile] = (0, import_react4.useState)(() => {
2105
2446
  if (typeof window === "undefined") return false;
2106
2447
  return window.matchMedia("(max-width: 768px)").matches;
2107
2448
  });
2108
- const normalizedLayers = (0, import_react.useMemo)(() => normalizeMapLayers(map), [map]);
2109
- (0, import_react.useEffect)(() => {
2449
+ const normalizedLayers = (0, import_react4.useMemo)(() => normalizeMapLayers(map), [map]);
2450
+ (0, import_react4.useEffect)(() => {
2110
2451
  if (typeof window === "undefined") return;
2111
2452
  const mql = window.matchMedia("(max-width: 768px)");
2112
2453
  const onChange = (e) => {
@@ -2124,12 +2465,37 @@ var ZenitMap = (0, import_react.forwardRef)(({
2124
2465
  }
2125
2466
  return;
2126
2467
  }, []);
2127
- (0, import_react.useEffect)(() => {
2468
+ (0, import_react4.useEffect)(() => {
2128
2469
  if (featureInfoMode === "popup") {
2129
2470
  ensurePopupStyles();
2130
2471
  }
2131
2472
  }, [featureInfoMode]);
2132
- const layerStyleIndex = (0, import_react.useMemo)(() => {
2473
+ (0, import_react4.useEffect)(() => {
2474
+ if (featureInfoMode !== "popup") {
2475
+ setIsPopupOpen(false);
2476
+ }
2477
+ }, [featureInfoMode]);
2478
+ (0, import_react4.useEffect)(() => {
2479
+ if (!mapInstance) return;
2480
+ const popupPane = mapInstance.getPane("popupPane");
2481
+ if (popupPane) {
2482
+ popupPane.style.zIndex = "800";
2483
+ }
2484
+ const labelsPane = mapInstance.getPane(LABELS_PANE_NAME) ?? mapInstance.createPane(LABELS_PANE_NAME);
2485
+ labelsPane.style.zIndex = "600";
2486
+ }, [mapInstance]);
2487
+ (0, import_react4.useEffect)(() => {
2488
+ if (!mapInstance) return;
2489
+ const handlePopupOpen = () => setIsPopupOpen(true);
2490
+ const handlePopupClose = () => setIsPopupOpen(false);
2491
+ mapInstance.on("popupopen", handlePopupOpen);
2492
+ mapInstance.on("popupclose", handlePopupClose);
2493
+ return () => {
2494
+ mapInstance.off("popupopen", handlePopupOpen);
2495
+ mapInstance.off("popupclose", handlePopupClose);
2496
+ };
2497
+ }, [mapInstance]);
2498
+ const layerStyleIndex = (0, import_react4.useMemo)(() => {
2133
2499
  const index = /* @__PURE__ */ new Map();
2134
2500
  (map?.mapLayers ?? []).forEach((entry) => {
2135
2501
  const layerStyle = entry.layer?.style ?? entry.mapLayer?.layer?.style ?? entry.style ?? null;
@@ -2140,7 +2506,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
2140
2506
  });
2141
2507
  return index;
2142
2508
  }, [map]);
2143
- const labelKeyIndex = (0, import_react.useMemo)(() => {
2509
+ const labelKeyIndex = (0, import_react4.useMemo)(() => {
2144
2510
  const index = /* @__PURE__ */ new Map();
2145
2511
  normalizedLayers.forEach((entry) => {
2146
2512
  const label = entry.layer?.label ?? entry.mapLayer?.label ?? entry.mapLayer.layerConfig?.label;
@@ -2150,7 +2516,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
2150
2516
  });
2151
2517
  return index;
2152
2518
  }, [normalizedLayers]);
2153
- const layerMetaIndex = (0, import_react.useMemo)(() => {
2519
+ const layerMetaIndex = (0, import_react4.useMemo)(() => {
2154
2520
  const index = /* @__PURE__ */ new Map();
2155
2521
  normalizedLayers.forEach((entry) => {
2156
2522
  index.set(String(entry.layerId), {
@@ -2160,7 +2526,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
2160
2526
  });
2161
2527
  return index;
2162
2528
  }, [normalizedLayers]);
2163
- const overlayStyleFunction = (0, import_react.useMemo)(() => {
2529
+ const overlayStyleFunction = (0, import_react4.useMemo)(() => {
2164
2530
  return (feature) => {
2165
2531
  const featureLayerId = getFeatureLayerId(feature);
2166
2532
  const featureStyleOverrides = getFeatureStyleOverrides(feature);
@@ -2179,11 +2545,15 @@ var ZenitMap = (0, import_react.forwardRef)(({
2179
2545
  return defaultOptions;
2180
2546
  };
2181
2547
  }, [layerStyleIndex, mapLayers, overlayStyle]);
2182
- const [baseStates, setBaseStates] = (0, import_react.useState)([]);
2183
- const [mapOverrides, setMapOverrides] = (0, import_react.useState)([]);
2184
- const [controlOverrides, setControlOverrides] = (0, import_react.useState)([]);
2185
- const [uiOverrides, setUiOverrides] = (0, import_react.useState)([]);
2186
- (0, import_react.useEffect)(() => {
2548
+ const overlayStyleFn = (0, import_react4.useCallback)(
2549
+ (feature, _layerType, _baseOpacity) => overlayStyleFunction(feature),
2550
+ [overlayStyleFunction]
2551
+ );
2552
+ const [baseStates, setBaseStates] = (0, import_react4.useState)([]);
2553
+ const [mapOverrides, setMapOverrides] = (0, import_react4.useState)([]);
2554
+ const [controlOverrides, setControlOverrides] = (0, import_react4.useState)([]);
2555
+ const [uiOverrides, setUiOverrides] = (0, import_react4.useState)([]);
2556
+ (0, import_react4.useEffect)(() => {
2187
2557
  let isMounted = true;
2188
2558
  setLoadingMap(true);
2189
2559
  setMapError(null);
@@ -2206,7 +2576,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
2206
2576
  isMounted = false;
2207
2577
  };
2208
2578
  }, [client.maps, mapId, onError, onLoadingChange]);
2209
- (0, import_react.useEffect)(() => {
2579
+ (0, import_react4.useEffect)(() => {
2210
2580
  if (normalizedLayers.length === 0) {
2211
2581
  setLayers([]);
2212
2582
  setBaseStates([]);
@@ -2237,7 +2607,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
2237
2607
  setMapOverrides(initialOverrides);
2238
2608
  setUiOverrides([]);
2239
2609
  }, [normalizedLayers]);
2240
- (0, import_react.useEffect)(() => {
2610
+ (0, import_react4.useEffect)(() => {
2241
2611
  if (!layerControls) {
2242
2612
  setControlOverrides([]);
2243
2613
  return;
@@ -2249,7 +2619,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
2249
2619
  }));
2250
2620
  setControlOverrides(overrides);
2251
2621
  }, [layerControls]);
2252
- (0, import_react.useEffect)(() => {
2622
+ (0, import_react4.useEffect)(() => {
2253
2623
  if (layerStates) {
2254
2624
  return;
2255
2625
  }
@@ -2259,12 +2629,12 @@ var ZenitMap = (0, import_react.forwardRef)(({
2259
2629
  onLayerStateChange?.(reset);
2260
2630
  }
2261
2631
  }, [baseStates, effectiveStates.length, layerControls, layerStates, onLayerStateChange]);
2262
- (0, import_react.useEffect)(() => {
2632
+ (0, import_react4.useEffect)(() => {
2263
2633
  if (layerStates) {
2264
2634
  setEffectiveStates(layerStates);
2265
2635
  }
2266
2636
  }, [layerStates]);
2267
- (0, import_react.useEffect)(() => {
2637
+ (0, import_react4.useEffect)(() => {
2268
2638
  if (layerStates) {
2269
2639
  return;
2270
2640
  }
@@ -2277,11 +2647,11 @@ var ZenitMap = (0, import_react.forwardRef)(({
2277
2647
  setEffectiveStates(next);
2278
2648
  onLayerStateChange?.(next);
2279
2649
  }, [baseStates, controlOverrides, layerStates, mapOverrides, onLayerStateChange, uiOverrides]);
2280
- (0, import_react.useEffect)(() => {
2650
+ (0, import_react4.useEffect)(() => {
2281
2651
  if (!Array.isArray(layerControls) || layerControls.length > 0) return;
2282
2652
  setUiOverrides([]);
2283
2653
  }, [layerControls]);
2284
- (0, import_react.useEffect)(() => {
2654
+ (0, import_react4.useEffect)(() => {
2285
2655
  if (layerStates) {
2286
2656
  return;
2287
2657
  }
@@ -2301,18 +2671,13 @@ var ZenitMap = (0, import_react.forwardRef)(({
2301
2671
  return [...filtered, nextEntry];
2302
2672
  });
2303
2673
  };
2304
- const updateOpacityFromUi = (0, import_react.useCallback)(
2674
+ const updateOpacityFromUi = (0, import_react4.useCallback)(
2305
2675
  (layerId, uiOpacity) => {
2306
2676
  const meta = layerMetaIndex.get(String(layerId));
2307
- const zoomFactor = getLayerZoomOpacityFactor(
2677
+ const baseOpacity = clampOpacity3(uiOpacity);
2678
+ const effectiveOpacity = calculateZoomBasedOpacity(
2308
2679
  currentZoom,
2309
- meta?.layerType,
2310
- meta?.geometryType
2311
- );
2312
- const baseOpacity = clampOpacity3(uiOpacity / zoomFactor);
2313
- const effectiveOpacity = getEffectiveLayerOpacity(
2314
2680
  baseOpacity,
2315
- currentZoom,
2316
2681
  meta?.layerType,
2317
2682
  meta?.geometryType
2318
2683
  );
@@ -2345,7 +2710,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
2345
2710
  },
2346
2711
  [currentZoom, effectiveStates, layerMetaIndex, layerStates, onLayerStateChange]
2347
2712
  );
2348
- const center = (0, import_react.useMemo)(() => {
2713
+ const center = (0, import_react4.useMemo)(() => {
2349
2714
  if (initialCenter) {
2350
2715
  return initialCenter;
2351
2716
  }
@@ -2356,36 +2721,30 @@ var ZenitMap = (0, import_react.forwardRef)(({
2356
2721
  return DEFAULT_CENTER;
2357
2722
  }, [initialCenter, map?.settings?.center]);
2358
2723
  const zoom = initialZoom ?? map?.settings?.zoom ?? DEFAULT_ZOOM;
2359
- (0, import_react.useEffect)(() => {
2724
+ (0, import_react4.useEffect)(() => {
2360
2725
  setCurrentZoom(zoom);
2361
2726
  }, [zoom]);
2362
- const decoratedLayers = (0, import_react.useMemo)(() => {
2727
+ const decoratedLayers = (0, import_react4.useMemo)(() => {
2363
2728
  return layers.map((layer) => ({
2364
2729
  ...layer,
2365
2730
  effective: effectiveStates.find((state) => state.layerId === layer.mapLayer.layerId),
2366
2731
  data: layerGeojson?.[layer.mapLayer.layerId] ?? layerGeojson?.[String(layer.mapLayer.layerId)] ?? null
2367
2732
  }));
2368
2733
  }, [effectiveStates, layerGeojson, layers]);
2369
- const orderedLayers = (0, import_react.useMemo)(() => {
2734
+ const orderedLayers = (0, import_react4.useMemo)(() => {
2370
2735
  return [...decoratedLayers].filter((layer) => layer.effective?.visible && layer.data).sort((a, b) => a.displayOrder - b.displayOrder);
2371
2736
  }, [decoratedLayers]);
2372
- const explicitZoomBBox = (0, import_react.useMemo)(() => {
2373
- if (zoomToBbox) return zoomToBbox;
2374
- if (zoomToGeojson) return computeBBoxFromGeojson(zoomToGeojson);
2375
- return null;
2376
- }, [zoomToBbox, zoomToGeojson]);
2377
- const autoZoomBBox = (0, import_react.useMemo)(() => {
2378
- if (explicitZoomBBox) return null;
2379
- const visibleBBoxes = orderedLayers.map((layer) => computeBBoxFromGeojson(layer.data));
2380
- return mergeBBoxes(visibleBBoxes);
2381
- }, [explicitZoomBBox, orderedLayers]);
2382
- const resolveLayerStyle = (0, import_react.useCallback)(
2737
+ const autoZoomGeojson = (0, import_react4.useMemo)(
2738
+ () => orderedLayers.map((layer) => layer.data).filter((collection) => !!collection),
2739
+ [orderedLayers]
2740
+ );
2741
+ const resolveLayerStyle = (0, import_react4.useCallback)(
2383
2742
  (layerId) => {
2384
2743
  return getStyleByLayerId(layerId, mapLayers) ?? layerStyleIndex.get(String(layerId)) ?? null;
2385
2744
  },
2386
2745
  [layerStyleIndex, mapLayers]
2387
2746
  );
2388
- const labelMarkers = (0, import_react.useMemo)(() => {
2747
+ const labelMarkers = (0, import_react4.useMemo)(() => {
2389
2748
  const markers = [];
2390
2749
  decoratedLayers.forEach((layerState) => {
2391
2750
  if (!layerState.effective?.visible) return;
@@ -2395,7 +2754,14 @@ var ZenitMap = (0, import_react.forwardRef)(({
2395
2754
  if (!data) return;
2396
2755
  const resolvedStyle = resolveLayerStyle(layerState.mapLayer.layerId);
2397
2756
  const layerColor = resolvedStyle?.fillColor ?? resolvedStyle?.color ?? "rgba(37, 99, 235, 1)";
2398
- const opacity = layerState.effective?.opacity ?? 1;
2757
+ const meta = layerMetaIndex.get(String(layerState.mapLayer.layerId));
2758
+ const baseOpacity = layerState.effective?.baseOpacity ?? layerState.effective?.opacity ?? 1;
2759
+ const opacity = calculateZoomBasedOpacity(
2760
+ currentZoom,
2761
+ baseOpacity,
2762
+ meta?.layerType,
2763
+ meta?.geometryType
2764
+ );
2399
2765
  data.features.forEach((feature, index) => {
2400
2766
  const properties = feature.properties;
2401
2767
  const value = properties?.[labelKey];
@@ -2414,26 +2780,24 @@ var ZenitMap = (0, import_react.forwardRef)(({
2414
2780
  });
2415
2781
  });
2416
2782
  return markers;
2417
- }, [decoratedLayers, labelKeyIndex, resolveLayerStyle]);
2418
- const ensureLayerPanes = (0, import_react.useCallback)(
2783
+ }, [currentZoom, decoratedLayers, labelKeyIndex, layerMetaIndex, resolveLayerStyle]);
2784
+ const ensureLayerPanes = (0, import_react4.useCallback)(
2419
2785
  (targetMap, targetLayers) => {
2420
2786
  const baseZIndex = 400;
2421
2787
  targetLayers.forEach((layer) => {
2422
2788
  const order = Number.isFinite(layer.displayOrder) ? layer.displayOrder : 0;
2789
+ const orderOffset = Math.max(0, Math.min(order, 150));
2423
2790
  const fillPaneName = `zenit-layer-${layer.layerId}-fill`;
2424
2791
  const pointPaneName = `zenit-layer-${layer.layerId}-points`;
2425
- const labelPaneName = `zenit-layer-${layer.layerId}-labels`;
2426
2792
  const fillPane = targetMap.getPane(fillPaneName) ?? targetMap.createPane(fillPaneName);
2427
2793
  const pointPane = targetMap.getPane(pointPaneName) ?? targetMap.createPane(pointPaneName);
2428
- const labelPane = targetMap.getPane(labelPaneName) ?? targetMap.createPane(labelPaneName);
2429
- fillPane.style.zIndex = String(baseZIndex + order);
2430
- pointPane.style.zIndex = String(baseZIndex + order + 1e3);
2431
- labelPane.style.zIndex = String(baseZIndex + order + 2e3);
2794
+ fillPane.style.zIndex = String(baseZIndex + orderOffset);
2795
+ pointPane.style.zIndex = String(baseZIndex + orderOffset + 100);
2432
2796
  });
2433
2797
  },
2434
2798
  []
2435
2799
  );
2436
- const handleMapReady = (0, import_react.useCallback)(
2800
+ const handleMapReady = (0, import_react4.useCallback)(
2437
2801
  (instance) => {
2438
2802
  setPanesReady(false);
2439
2803
  setMapInstance(instance);
@@ -2441,7 +2805,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
2441
2805
  },
2442
2806
  [onMapReady]
2443
2807
  );
2444
- (0, import_react.useEffect)(() => {
2808
+ (0, import_react4.useEffect)(() => {
2445
2809
  if (!mapInstance) {
2446
2810
  setPanesReady(false);
2447
2811
  return;
@@ -2455,24 +2819,25 @@ var ZenitMap = (0, import_react.forwardRef)(({
2455
2819
  }));
2456
2820
  ensureLayerPanes(mapInstance, layerTargets);
2457
2821
  const first = layerTargets[0];
2458
- const testPane = mapInstance.getPane(`zenit-layer-${first.layerId}-labels`);
2459
- if (testPane) {
2822
+ const testPane = mapInstance.getPane(`zenit-layer-${first.layerId}-fill`);
2823
+ const labelsPane = mapInstance.getPane(LABELS_PANE_NAME);
2824
+ if (testPane && labelsPane) {
2460
2825
  setPanesReady(true);
2461
2826
  }
2462
2827
  }, [mapInstance, orderedLayers, ensureLayerPanes]);
2463
- const overlayOnEachFeature = (0, import_react.useMemo)(() => {
2828
+ const overlayOnEachFeature = (0, import_react4.useMemo)(() => {
2464
2829
  return (feature, layer) => {
2465
2830
  const layerId = getFeatureLayerId(feature) ?? void 0;
2466
2831
  const geometryType = feature?.geometry?.type;
2467
- const isPointFeature = geometryType === "Point" || geometryType === "MultiPoint" || layer instanceof import_leaflet.default.CircleMarker;
2468
- const originalStyle = layer instanceof import_leaflet.default.Path ? {
2832
+ const isPointFeature = geometryType === "Point" || geometryType === "MultiPoint" || layer instanceof import_leaflet4.default.CircleMarker;
2833
+ const originalStyle = layer instanceof import_leaflet4.default.Path ? {
2469
2834
  color: layer.options.color,
2470
2835
  weight: layer.options.weight,
2471
2836
  fillColor: layer.options.fillColor,
2472
2837
  opacity: layer.options.opacity,
2473
2838
  fillOpacity: layer.options.fillOpacity
2474
2839
  } : null;
2475
- const originalRadius = layer instanceof import_leaflet.default.CircleMarker ? layer.getRadius() : null;
2840
+ const originalRadius = layer instanceof import_leaflet4.default.CircleMarker ? layer.getRadius() : null;
2476
2841
  if (featureInfoMode === "popup") {
2477
2842
  const content = buildFeaturePopupHtml(feature);
2478
2843
  if (content) {
@@ -2481,11 +2846,10 @@ var ZenitMap = (0, import_react.forwardRef)(({
2481
2846
  maxWidth,
2482
2847
  minWidth,
2483
2848
  maxHeight,
2484
- className: "zenit-leaflet-popup",
2849
+ className: "custom-leaflet-popup",
2485
2850
  autoPan: true,
2486
2851
  closeButton: true,
2487
- keepInView: true,
2488
- offset: import_leaflet.default.point(0, -24)
2852
+ keepInView: true
2489
2853
  });
2490
2854
  }
2491
2855
  }
@@ -2506,7 +2870,8 @@ var ZenitMap = (0, import_react.forwardRef)(({
2506
2870
  id: layerId,
2507
2871
  geometry: feature.geometry
2508
2872
  }).then((response) => {
2509
- const candidates = response.data?.features ?? [];
2873
+ const geo = extractGeoJsonFeatureCollection(response);
2874
+ const candidates = geo?.features ?? [];
2510
2875
  const resolved = pickIntersectFeature(feature, candidates);
2511
2876
  if (!resolved?.properties) return;
2512
2877
  const mergedProperties = {
@@ -2529,7 +2894,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
2529
2894
  onFeatureClick?.(feature, layerId);
2530
2895
  });
2531
2896
  layer.on("mouseover", () => {
2532
- if (layer instanceof import_leaflet.default.Path && originalStyle) {
2897
+ if (layer instanceof import_leaflet4.default.Path && originalStyle) {
2533
2898
  layer.setStyle({
2534
2899
  ...originalStyle,
2535
2900
  weight: (originalStyle.weight ?? 2) + 1,
@@ -2537,16 +2902,16 @@ var ZenitMap = (0, import_react.forwardRef)(({
2537
2902
  fillOpacity: Math.min(1, (originalStyle.fillOpacity ?? 0.8) + 0.1)
2538
2903
  });
2539
2904
  }
2540
- if (layer instanceof import_leaflet.default.CircleMarker && typeof originalRadius === "number") {
2905
+ if (layer instanceof import_leaflet4.default.CircleMarker && typeof originalRadius === "number") {
2541
2906
  layer.setRadius(originalRadius + 1);
2542
2907
  }
2543
2908
  onFeatureHover?.(feature, layerId);
2544
2909
  });
2545
2910
  layer.on("mouseout", () => {
2546
- if (layer instanceof import_leaflet.default.Path && originalStyle) {
2911
+ if (layer instanceof import_leaflet4.default.Path && originalStyle) {
2547
2912
  layer.setStyle(originalStyle);
2548
2913
  }
2549
- if (layer instanceof import_leaflet.default.CircleMarker && typeof originalRadius === "number") {
2914
+ if (layer instanceof import_leaflet4.default.CircleMarker && typeof originalRadius === "number") {
2550
2915
  layer.setRadius(originalRadius);
2551
2916
  }
2552
2917
  });
@@ -2558,80 +2923,20 @@ var ZenitMap = (0, import_react.forwardRef)(({
2558
2923
  const resolvedStyle = featureStyleOverrides ? { ...style ?? {}, ...featureStyleOverrides } : style;
2559
2924
  const geometryType = feature?.geometry?.type;
2560
2925
  const resolvedLayerType = layerType ?? geometryType;
2561
- const sanitizedBaseOpacity = clampOpacity3(baseOpacity);
2562
- const normalizedStyleFill = typeof resolvedStyle?.fillOpacity === "number" ? clampOpacity3(resolvedStyle.fillOpacity) : 0.8;
2563
- const effectiveOpacity = getEffectiveLayerOpacity(
2564
- sanitizedBaseOpacity,
2565
- currentZoom,
2566
- resolvedLayerType,
2567
- geometryType
2568
- );
2569
- const fillOpacity = clampOpacity3(effectiveOpacity * normalizedStyleFill);
2570
- const strokeOpacity = clampOpacity3(Math.max(0.35, effectiveOpacity * 0.9));
2571
- return {
2572
- color: resolvedStyle?.color ?? resolvedStyle?.fillColor ?? "#2563eb",
2573
- weight: resolvedStyle?.weight ?? 2,
2574
- fillColor: resolvedStyle?.fillColor ?? resolvedStyle?.color ?? "#2563eb",
2575
- opacity: strokeOpacity,
2576
- fillOpacity
2926
+ return layerStyleToLeaflet({
2927
+ baseOpacity,
2928
+ zoom: currentZoom,
2929
+ layerStyle: resolvedStyle,
2930
+ geometryType,
2931
+ layerType: resolvedLayerType
2932
+ });
2933
+ };
2934
+ const makeStyleFnForLayer = (layerId) => {
2935
+ return (feature, layerType, baseOpacity) => {
2936
+ return buildLayerStyle(layerId, baseOpacity ?? 1, feature, layerType);
2577
2937
  };
2578
2938
  };
2579
- const buildLabelIcon = (0, import_react.useCallback)((label, opacity, color) => {
2580
- const size = 60;
2581
- const innerSize = 44;
2582
- const textStyles = getLabelTextStyles(color);
2583
- const safeLabel = escapeHtml(label);
2584
- const clampedOpacity = Math.min(1, Math.max(0.92, opacity));
2585
- const innerBackground = withAlpha(color, 0.9);
2586
- return import_leaflet.default.divIcon({
2587
- className: "zenit-label-marker",
2588
- iconSize: [size, size],
2589
- iconAnchor: [size / 2, size / 2],
2590
- html: `
2591
- <div
2592
- title="${safeLabel}"
2593
- style="
2594
- width:${size}px;
2595
- height:${size}px;
2596
- border-radius:9999px;
2597
- background:rgba(255, 255, 255, 0.95);
2598
- border:3px solid rgba(255, 255, 255, 1);
2599
- display:flex;
2600
- align-items:center;
2601
- justify-content:center;
2602
- opacity:${clampedOpacity};
2603
- box-shadow:0 2px 6px rgba(0, 0, 0, 0.25);
2604
- pointer-events:none;
2605
- "
2606
- >
2607
- <div
2608
- style="
2609
- width:${innerSize}px;
2610
- height:${innerSize}px;
2611
- border-radius:9999px;
2612
- background:${innerBackground};
2613
- display:flex;
2614
- align-items:center;
2615
- justify-content:center;
2616
- box-shadow:inset 0 0 0 1px rgba(15, 23, 42, 0.12);
2617
- "
2618
- >
2619
- <span
2620
- style="
2621
- color:${textStyles.color};
2622
- font-size:20px;
2623
- font-weight:800;
2624
- text-shadow:${textStyles.shadow};
2625
- "
2626
- >
2627
- ${safeLabel}
2628
- </span>
2629
- </div>
2630
- </div>
2631
- `
2632
- });
2633
- }, []);
2634
- (0, import_react.useImperativeHandle)(ref, () => ({
2939
+ (0, import_react4.useImperativeHandle)(ref, () => ({
2635
2940
  setLayerOpacity: (layerId, opacity) => {
2636
2941
  upsertUiOverride(layerId, { overrideOpacity: opacity });
2637
2942
  },
@@ -2681,10 +2986,10 @@ var ZenitMap = (0, import_react.forwardRef)(({
2681
2986
  getMapInstance: () => mapInstance
2682
2987
  }), [effectiveStates, mapInstance]);
2683
2988
  if (loadingMap) {
2684
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { padding: 16, height, width }, children: "Cargando mapa..." });
2989
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { padding: 16, height, width }, children: "Cargando mapa..." });
2685
2990
  }
2686
2991
  if (mapError) {
2687
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: 16, height, width, color: "red" }, children: [
2992
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { padding: 16, height, width, color: "red" }, children: [
2688
2993
  "Error al cargar mapa: ",
2689
2994
  mapError
2690
2995
  ] });
@@ -2696,7 +3001,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
2696
3001
  setCurrentZoom(zoomValue);
2697
3002
  onZoomChange?.(zoomValue);
2698
3003
  };
2699
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
3004
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2700
3005
  "div",
2701
3006
  {
2702
3007
  style: {
@@ -2709,88 +3014,111 @@ var ZenitMap = (0, import_react.forwardRef)(({
2709
3014
  boxSizing: "border-box"
2710
3015
  },
2711
3016
  children: [
2712
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1, position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2713
- import_react_leaflet.MapContainer,
3017
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3018
+ "div",
2714
3019
  {
2715
- center,
2716
- zoom,
2717
- style: { height: "100%", width: "100%" },
2718
- scrollWheelZoom: true,
2719
- zoomControl: false,
2720
- children: [
2721
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2722
- import_react_leaflet.TileLayer,
2723
- {
2724
- url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
2725
- attribution: "\xA9 OpenStreetMap contributors"
2726
- }
2727
- ),
2728
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_leaflet.ZoomControl, { position: "topright" }),
2729
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MapInstanceBridge, { onReady: handleMapReady }),
2730
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FitToBounds, { bbox: explicitZoomBBox ?? void 0 }),
2731
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AutoFitToBounds, { bbox: autoZoomBBox ?? void 0, enabled: !explicitZoomBBox }),
2732
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ZoomBasedOpacityHandler, { onZoomChange: handleZoomChange }),
2733
- orderedLayers.map((layerState) => {
2734
- const baseOpacity = layerState.effective?.baseOpacity ?? layerState.effective?.opacity ?? 1;
2735
- const fillPaneName = `zenit-layer-${layerState.mapLayer.layerId}-fill`;
2736
- const pointsPaneName = `zenit-layer-${layerState.mapLayer.layerId}-points`;
2737
- const labelPaneName = `zenit-layer-${layerState.mapLayer.layerId}-labels`;
2738
- const layerType = layerState.layer?.layerType ?? layerState.mapLayer.layerType ?? void 0;
2739
- const data = layerState.data?.features ?? [];
2740
- const fillFeatures = data.filter(isNonPointGeometry);
2741
- const pointFeatures = data.filter(isPointGeometry);
2742
- const fillData = fillFeatures.length > 0 ? buildFeatureCollection(fillFeatures) : null;
2743
- const pointsData = pointFeatures.length > 0 ? buildFeatureCollection(pointFeatures) : null;
2744
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [
2745
- fillData && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2746
- import_react_leaflet.GeoJSON,
3020
+ className: `zenit-map-shell${isPopupOpen ? " popup-open" : ""}`,
3021
+ style: { flex: 1, position: "relative" },
3022
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3023
+ import_react_leaflet4.MapContainer,
3024
+ {
3025
+ center,
3026
+ zoom,
3027
+ style: { height: "100%", width: "100%" },
3028
+ scrollWheelZoom: true,
3029
+ zoomControl: false,
3030
+ children: [
3031
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3032
+ import_react_leaflet4.TileLayer,
2747
3033
  {
2748
- data: fillData,
2749
- pane: panesReady && mapInstance?.getPane(fillPaneName) ? fillPaneName : void 0,
2750
- style: (feature) => buildLayerStyle(layerState.mapLayer.layerId, baseOpacity, feature, layerType),
2751
- onEachFeature: overlayOnEachFeature
3034
+ url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
3035
+ attribution: "\xA9 OpenStreetMap contributors"
2752
3036
  }
2753
3037
  ),
2754
- pointsData && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2755
- import_react_leaflet.GeoJSON,
3038
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_leaflet4.ZoomControl, { position: "topright" }),
3039
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MapInstanceBridge, { onReady: handleMapReady }),
3040
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3041
+ BBoxZoomHandler,
2756
3042
  {
2757
- data: pointsData,
2758
- pane: panesReady && mapInstance?.getPane(pointsPaneName) ? pointsPaneName : void 0,
2759
- pointToLayer: (feature, latlng) => import_leaflet.default.circleMarker(latlng, {
2760
- radius: isMobile ? 8 : 6,
2761
- ...buildLayerStyle(layerState.mapLayer.layerId, baseOpacity, feature, layerType)
2762
- }),
2763
- onEachFeature: overlayOnEachFeature
3043
+ bbox: zoomToBbox ?? void 0,
3044
+ geojson: zoomToGeojson ?? void 0,
3045
+ autoGeojson: autoZoomGeojson
2764
3046
  }
2765
3047
  ),
2766
- panesReady && mapInstance?.getPane(labelPaneName) ? labelMarkers.filter(
2767
- (marker) => String(marker.layerId) === String(layerState.mapLayer.layerId)
2768
- ).map((marker) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2769
- import_react_leaflet.Marker,
3048
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ZoomBasedOpacityHandler, { onZoomChange: handleZoomChange }),
3049
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LocationControl, {}),
3050
+ orderedLayers.map((layerState) => {
3051
+ const baseOpacity = layerState.effective?.baseOpacity ?? layerState.effective?.opacity ?? 1;
3052
+ const fillPaneName = `zenit-layer-${layerState.mapLayer.layerId}-fill`;
3053
+ const pointsPaneName = `zenit-layer-${layerState.mapLayer.layerId}-points`;
3054
+ const layerType = layerState.layer?.layerType ?? layerState.mapLayer.layerType ?? void 0;
3055
+ const labelKey = labelKeyIndex.get(String(layerState.mapLayer.layerId));
3056
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react4.default.Fragment, { children: [
3057
+ layerState.data && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3058
+ LayerGeoJson,
3059
+ {
3060
+ layerId: layerState.mapLayer.layerId,
3061
+ data: layerState.data,
3062
+ baseOpacity,
3063
+ isMobile,
3064
+ panesReady,
3065
+ mapInstance,
3066
+ fillPaneName,
3067
+ pointsPaneName,
3068
+ layerType,
3069
+ styleFn: makeStyleFnForLayer(layerState.mapLayer.layerId),
3070
+ onEachFeature: overlayOnEachFeature,
3071
+ onPolygonLabel: labelKey ? (feature, layer) => {
3072
+ const geometryType = feature?.geometry?.type;
3073
+ if (geometryType !== "Polygon" && geometryType !== "MultiPolygon") return;
3074
+ const properties = feature?.properties;
3075
+ const value = properties?.[labelKey];
3076
+ if (!value || !layer.bindTooltip) return;
3077
+ layer.bindTooltip(String(value), {
3078
+ sticky: true,
3079
+ direction: "center",
3080
+ opacity: 0.9,
3081
+ className: "polygon-label-tooltip"
3082
+ });
3083
+ } : void 0
3084
+ }
3085
+ ),
3086
+ panesReady && mapInstance?.getPane(LABELS_PANE_NAME) ? labelMarkers.filter(
3087
+ (marker) => String(marker.layerId) === String(layerState.mapLayer.layerId)
3088
+ ).map((marker) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3089
+ import_react_leaflet4.Marker,
3090
+ {
3091
+ position: marker.position,
3092
+ icon: createCustomIcon(marker.label, marker.opacity, marker.color),
3093
+ interactive: false,
3094
+ pane: LABELS_PANE_NAME
3095
+ },
3096
+ marker.key
3097
+ )) : null
3098
+ ] }, layerState.mapLayer.layerId.toString());
3099
+ }),
3100
+ overlayGeojson && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3101
+ LayerGeoJson,
2770
3102
  {
2771
- position: marker.position,
2772
- icon: buildLabelIcon(marker.label, marker.opacity, marker.color),
2773
- interactive: false,
2774
- pane: labelPaneName
2775
- },
2776
- marker.key
2777
- )) : null
2778
- ] }, layerState.mapLayer.layerId.toString());
2779
- }),
2780
- overlayGeojson && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2781
- import_react_leaflet.GeoJSON,
2782
- {
2783
- data: overlayGeojson,
2784
- style: overlayStyleFunction,
2785
- onEachFeature: overlayOnEachFeature
2786
- },
2787
- "zenit-overlay-geojson"
2788
- )
2789
- ]
2790
- },
2791
- String(mapId)
2792
- ) }),
2793
- showLayerPanel && decoratedLayers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
3103
+ layerId: "overlay-geojson",
3104
+ data: overlayGeojson,
3105
+ baseOpacity: 1,
3106
+ isMobile,
3107
+ panesReady,
3108
+ mapInstance,
3109
+ fillPaneName: "zenit-overlay-fill",
3110
+ pointsPaneName: "zenit-overlay-points",
3111
+ styleFn: overlayStyleFn,
3112
+ onEachFeature: overlayOnEachFeature
3113
+ }
3114
+ )
3115
+ ]
3116
+ },
3117
+ String(mapId)
3118
+ )
3119
+ }
3120
+ ),
3121
+ showLayerPanel && decoratedLayers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2794
3122
  "div",
2795
3123
  {
2796
3124
  style: {
@@ -2803,7 +3131,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
2803
3131
  overflowY: "auto"
2804
3132
  },
2805
3133
  children: [
2806
- overlayGeojson && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
3134
+ overlayGeojson && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2807
3135
  "div",
2808
3136
  {
2809
3137
  style: {
@@ -2815,8 +3143,8 @@ var ZenitMap = (0, import_react.forwardRef)(({
2815
3143
  marginBottom: 12
2816
3144
  },
2817
3145
  children: [
2818
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontWeight: 600, marginBottom: 4 }, children: "Overlay activo" }),
2819
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { fontSize: 13 }, children: [
3146
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontWeight: 600, marginBottom: 4 }, children: "Overlay activo" }),
3147
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { fontSize: 13 }, children: [
2820
3148
  "GeoJSON externo con ",
2821
3149
  (overlayGeojson.features?.length ?? 0).toLocaleString(),
2822
3150
  " elementos."
@@ -2824,14 +3152,14 @@ var ZenitMap = (0, import_react.forwardRef)(({
2824
3152
  ]
2825
3153
  }
2826
3154
  ),
2827
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontWeight: 600, marginBottom: 12 }, children: "Capas" }),
2828
- decoratedLayers.map((layerState) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
3155
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontWeight: 600, marginBottom: 12 }, children: "Capas" }),
3156
+ decoratedLayers.map((layerState) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2829
3157
  "div",
2830
3158
  {
2831
3159
  style: { borderBottom: "1px solid #e5e7eb", paddingBottom: 10, marginBottom: 10 },
2832
3160
  children: [
2833
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
2834
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3161
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
3162
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2835
3163
  "input",
2836
3164
  {
2837
3165
  type: "checkbox",
@@ -2842,17 +3170,17 @@ var ZenitMap = (0, import_react.forwardRef)(({
2842
3170
  }
2843
3171
  }
2844
3172
  ),
2845
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: layerState.layer?.name ?? `Capa ${layerState.mapLayer.layerId}` })
3173
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: layerState.layer?.name ?? `Capa ${layerState.mapLayer.layerId}` })
2846
3174
  ] }),
2847
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: 8 }, children: [
2848
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 4 }, children: [
2849
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "#4a5568" }, children: "Opacidad" }),
2850
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
3175
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { marginTop: 8 }, children: [
3176
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 4 }, children: [
3177
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "#4a5568" }, children: "Opacidad" }),
3178
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
2851
3179
  Math.round((layerState.effective?.opacity ?? 1) * 100),
2852
3180
  "%"
2853
3181
  ] })
2854
3182
  ] }),
2855
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3183
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2856
3184
  "input",
2857
3185
  {
2858
3186
  type: "range",
@@ -2882,13 +3210,13 @@ var ZenitMap = (0, import_react.forwardRef)(({
2882
3210
  ZenitMap.displayName = "ZenitMap";
2883
3211
 
2884
3212
  // src/react/ZenitLayerManager.tsx
2885
- var import_react2 = __toESM(require("react"));
3213
+ var import_react5 = __toESM(require("react"));
2886
3214
 
2887
3215
  // src/react/icons.tsx
2888
3216
  var import_lucide_react = require("lucide-react");
2889
3217
 
2890
3218
  // src/react/ZenitLayerManager.tsx
2891
- var import_jsx_runtime2 = require("react/jsx-runtime");
3219
+ var import_jsx_runtime4 = require("react/jsx-runtime");
2892
3220
  var FLOAT_TOLERANCE = 1e-3;
2893
3221
  function areEffectiveStatesEqual(a, b) {
2894
3222
  if (a.length !== b.length) return false;
@@ -2928,15 +3256,15 @@ var ZenitLayerManager = ({
2928
3256
  layerFeatureCounts,
2929
3257
  mapLayers
2930
3258
  }) => {
2931
- const [map, setMap] = (0, import_react2.useState)(null);
2932
- const [loadingMap, setLoadingMap] = (0, import_react2.useState)(false);
2933
- const [mapError, setMapError] = (0, import_react2.useState)(null);
2934
- const [layers, setLayers] = (0, import_react2.useState)([]);
2935
- const [activeTab, setActiveTab] = (0, import_react2.useState)("layers");
2936
- const [panelVisible, setPanelVisible] = (0, import_react2.useState)(true);
2937
- const lastEmittedStatesRef = (0, import_react2.useRef)(null);
3259
+ const [map, setMap] = (0, import_react5.useState)(null);
3260
+ const [loadingMap, setLoadingMap] = (0, import_react5.useState)(false);
3261
+ const [mapError, setMapError] = (0, import_react5.useState)(null);
3262
+ const [layers, setLayers] = (0, import_react5.useState)([]);
3263
+ const [activeTab, setActiveTab] = (0, import_react5.useState)("layers");
3264
+ const [panelVisible, setPanelVisible] = (0, import_react5.useState)(true);
3265
+ const lastEmittedStatesRef = (0, import_react5.useRef)(null);
2938
3266
  const isControlled = Array.isArray(layerStates) && typeof onLayerStatesChange === "function";
2939
- const baseStates = (0, import_react2.useMemo)(
3267
+ const baseStates = (0, import_react5.useMemo)(
2940
3268
  () => initLayerStates(
2941
3269
  layers.map((entry) => ({
2942
3270
  ...entry.mapLayer,
@@ -2947,7 +3275,7 @@ var ZenitLayerManager = ({
2947
3275
  ),
2948
3276
  [layers]
2949
3277
  );
2950
- const overrideStates = (0, import_react2.useMemo)(
3278
+ const overrideStates = (0, import_react5.useMemo)(
2951
3279
  () => layers.map(
2952
3280
  (entry) => ({
2953
3281
  layerId: entry.mapLayer.layerId,
@@ -2957,11 +3285,11 @@ var ZenitLayerManager = ({
2957
3285
  ),
2958
3286
  [layers]
2959
3287
  );
2960
- const effectiveStates = (0, import_react2.useMemo)(
3288
+ const effectiveStates = (0, import_react5.useMemo)(
2961
3289
  () => layerStates ?? applyLayerOverrides(baseStates, overrideStates),
2962
3290
  [baseStates, layerStates, overrideStates]
2963
3291
  );
2964
- const layerMetaIndex = (0, import_react2.useMemo)(() => {
3292
+ const layerMetaIndex = (0, import_react5.useMemo)(() => {
2965
3293
  const index = /* @__PURE__ */ new Map();
2966
3294
  mapLayers?.forEach((entry) => {
2967
3295
  const key = String(entry.layerId);
@@ -2975,7 +3303,7 @@ var ZenitLayerManager = ({
2975
3303
  });
2976
3304
  return index;
2977
3305
  }, [map, mapLayers]);
2978
- const resolveUserOpacity = import_react2.default.useCallback((state) => {
3306
+ const resolveUserOpacity = import_react5.default.useCallback((state) => {
2979
3307
  if (typeof state.overrideOpacity === "number") return state.overrideOpacity;
2980
3308
  if (typeof state.overrideOpacity === "string") {
2981
3309
  const parsed = Number.parseFloat(state.overrideOpacity);
@@ -2983,7 +3311,7 @@ var ZenitLayerManager = ({
2983
3311
  }
2984
3312
  return state.opacity ?? 1;
2985
3313
  }, []);
2986
- const resolveEffectiveOpacity = import_react2.default.useCallback(
3314
+ const resolveEffectiveOpacity = import_react5.default.useCallback(
2987
3315
  (layerId, userOpacity) => {
2988
3316
  if (!autoOpacityOnZoom || typeof mapZoom !== "number") {
2989
3317
  return userOpacity;
@@ -2999,7 +3327,7 @@ var ZenitLayerManager = ({
2999
3327
  },
3000
3328
  [autoOpacityConfig, autoOpacityOnZoom, layerMetaIndex, mapZoom]
3001
3329
  );
3002
- const effectiveStatesWithZoom = (0, import_react2.useMemo)(() => {
3330
+ const effectiveStatesWithZoom = (0, import_react5.useMemo)(() => {
3003
3331
  if (!autoOpacityOnZoom || typeof mapZoom !== "number") {
3004
3332
  return effectiveStates;
3005
3333
  }
@@ -3013,7 +3341,7 @@ var ZenitLayerManager = ({
3013
3341
  };
3014
3342
  });
3015
3343
  }, [autoOpacityOnZoom, effectiveStates, mapZoom, resolveEffectiveOpacity, resolveUserOpacity]);
3016
- (0, import_react2.useEffect)(() => {
3344
+ (0, import_react5.useEffect)(() => {
3017
3345
  let cancelled = false;
3018
3346
  setLoadingMap(true);
3019
3347
  setMapError(null);
@@ -3045,12 +3373,12 @@ var ZenitLayerManager = ({
3045
3373
  cancelled = true;
3046
3374
  };
3047
3375
  }, [client.maps, mapId]);
3048
- (0, import_react2.useEffect)(() => {
3376
+ (0, import_react5.useEffect)(() => {
3049
3377
  if (!showUploadTab && activeTab === "upload") {
3050
3378
  setActiveTab("layers");
3051
3379
  }
3052
3380
  }, [activeTab, showUploadTab]);
3053
- (0, import_react2.useEffect)(() => {
3381
+ (0, import_react5.useEffect)(() => {
3054
3382
  if (isControlled) return;
3055
3383
  if (!onLayerStatesChange) return;
3056
3384
  const emitStates = autoOpacityOnZoom && typeof mapZoom === "number" ? effectiveStatesWithZoom : effectiveStates;
@@ -3068,7 +3396,7 @@ var ZenitLayerManager = ({
3068
3396
  mapZoom,
3069
3397
  onLayerStatesChange
3070
3398
  ]);
3071
- const updateLayerVisible = import_react2.default.useCallback(
3399
+ const updateLayerVisible = import_react5.default.useCallback(
3072
3400
  (layerId, visible) => {
3073
3401
  if (!onLayerStatesChange) return;
3074
3402
  const next = effectiveStates.map(
@@ -3078,7 +3406,7 @@ var ZenitLayerManager = ({
3078
3406
  },
3079
3407
  [effectiveStates, onLayerStatesChange]
3080
3408
  );
3081
- const updateLayerOpacity = import_react2.default.useCallback(
3409
+ const updateLayerOpacity = import_react5.default.useCallback(
3082
3410
  (layerId, opacity) => {
3083
3411
  if (!onLayerStatesChange) return;
3084
3412
  const adjustedOpacity = resolveEffectiveOpacity(layerId, opacity);
@@ -3089,7 +3417,7 @@ var ZenitLayerManager = ({
3089
3417
  },
3090
3418
  [effectiveStates, onLayerStatesChange, resolveEffectiveOpacity]
3091
3419
  );
3092
- const resolveFeatureCount = import_react2.default.useCallback(
3420
+ const resolveFeatureCount = import_react5.default.useCallback(
3093
3421
  (layerId, layer) => {
3094
3422
  const resolvedFeatureCount = layerFeatureCounts?.[layerId] ?? layerFeatureCounts?.[String(layerId)];
3095
3423
  if (typeof resolvedFeatureCount === "number") return resolvedFeatureCount;
@@ -3098,7 +3426,7 @@ var ZenitLayerManager = ({
3098
3426
  },
3099
3427
  [layerFeatureCounts]
3100
3428
  );
3101
- const decoratedLayers = (0, import_react2.useMemo)(() => {
3429
+ const decoratedLayers = (0, import_react5.useMemo)(() => {
3102
3430
  return layers.map((entry) => ({
3103
3431
  ...entry,
3104
3432
  effective: effectiveStates.find((state) => state.layerId === entry.mapLayer.layerId),
@@ -3127,7 +3455,7 @@ var ZenitLayerManager = ({
3127
3455
  return String(a.mapLayer.layerId).localeCompare(String(b.mapLayer.layerId));
3128
3456
  });
3129
3457
  }, [effectiveStates, layers, resolveFeatureCount]);
3130
- const resolveLayerStyle = import_react2.default.useCallback(
3458
+ const resolveLayerStyle = import_react5.default.useCallback(
3131
3459
  (layerId) => {
3132
3460
  const layerKey = String(layerId);
3133
3461
  const fromProp = mapLayers?.find((entry) => String(entry.layerId) === layerKey)?.style;
@@ -3157,10 +3485,10 @@ var ZenitLayerManager = ({
3157
3485
  ...height ? { height } : {}
3158
3486
  };
3159
3487
  if (loadingMap) {
3160
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className, style: panelStyle, children: "Cargando capas\u2026" });
3488
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className, style: panelStyle, children: "Cargando capas\u2026" });
3161
3489
  }
3162
3490
  if (mapError) {
3163
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className, style: { ...panelStyle, color: "#c53030" }, children: [
3491
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className, style: { ...panelStyle, color: "#c53030" }, children: [
3164
3492
  "Error al cargar mapa: ",
3165
3493
  mapError
3166
3494
  ] });
@@ -3178,7 +3506,7 @@ var ZenitLayerManager = ({
3178
3506
  boxShadow: "0 1px 0 rgba(148, 163, 184, 0.25)"
3179
3507
  };
3180
3508
  const renderLayerCards = () => {
3181
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: decoratedLayers.map((layerState) => {
3509
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: decoratedLayers.map((layerState) => {
3182
3510
  const layerId = layerState.mapLayer.layerId;
3183
3511
  const layerName = layerState.layerName ?? `Capa ${layerId}`;
3184
3512
  const visible = layerState.effective?.visible ?? false;
@@ -3188,7 +3516,7 @@ var ZenitLayerManager = ({
3188
3516
  const muted = !visible;
3189
3517
  const opacityPercent = Math.round(userOpacity * 100);
3190
3518
  const sliderBackground = `linear-gradient(to right, ${layerColor} 0%, ${layerColor} ${opacityPercent}%, #e5e7eb ${opacityPercent}%, #e5e7eb 100%)`;
3191
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3519
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3192
3520
  "div",
3193
3521
  {
3194
3522
  className: `zlm-card${muted ? " is-muted" : ""}`,
@@ -3203,9 +3531,9 @@ var ZenitLayerManager = ({
3203
3531
  width: "100%"
3204
3532
  },
3205
3533
  children: [
3206
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", gap: 12 }, children: [
3207
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: 10, alignItems: "flex-start", minWidth: 0, flex: 1 }, children: [
3208
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3534
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", gap: 12 }, children: [
3535
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", gap: 10, alignItems: "flex-start", minWidth: 0, flex: 1 }, children: [
3536
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3209
3537
  "div",
3210
3538
  {
3211
3539
  style: {
@@ -3220,7 +3548,7 @@ var ZenitLayerManager = ({
3220
3548
  title: "Color de la capa"
3221
3549
  }
3222
3550
  ),
3223
- showLayerVisibilityIcon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3551
+ showLayerVisibilityIcon && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3224
3552
  "button",
3225
3553
  {
3226
3554
  type: "button",
@@ -3231,11 +3559,11 @@ var ZenitLayerManager = ({
3231
3559
  )
3232
3560
  ),
3233
3561
  "aria-label": visible ? "Ocultar capa" : "Mostrar capa",
3234
- children: visible ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Eye, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.EyeOff, { size: 16 })
3562
+ children: visible ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react.Eye, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react.EyeOff, { size: 16 })
3235
3563
  }
3236
3564
  ),
3237
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { minWidth: 0, flex: 1 }, children: [
3238
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3565
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { minWidth: 0, flex: 1 }, children: [
3566
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3239
3567
  "div",
3240
3568
  {
3241
3569
  className: "zlm-layer-name",
@@ -3253,26 +3581,26 @@ var ZenitLayerManager = ({
3253
3581
  children: layerName
3254
3582
  }
3255
3583
  ),
3256
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { color: muted ? "#94a3b8" : "#64748b", fontSize: 12 }, children: [
3584
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { color: muted ? "#94a3b8" : "#64748b", fontSize: 12 }, children: [
3257
3585
  "ID ",
3258
3586
  layerId
3259
3587
  ] })
3260
3588
  ] })
3261
3589
  ] }),
3262
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", alignItems: "flex-start", gap: 6, flexShrink: 0 }, children: typeof featureCount === "number" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "zlm-badge", children: [
3590
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { display: "flex", alignItems: "flex-start", gap: 6, flexShrink: 0 }, children: typeof featureCount === "number" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "zlm-badge", children: [
3263
3591
  featureCount.toLocaleString(),
3264
3592
  " features"
3265
3593
  ] }) })
3266
3594
  ] }),
3267
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", gap: 10, alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { flex: 1 }, children: [
3268
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 6, color: "#64748b", fontSize: 12 }, children: [
3269
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Opacidad" }),
3270
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
3595
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { display: "flex", gap: 10, alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { flex: 1 }, children: [
3596
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 6, color: "#64748b", fontSize: 12 }, children: [
3597
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Opacidad" }),
3598
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { children: [
3271
3599
  opacityPercent,
3272
3600
  "%"
3273
3601
  ] })
3274
3602
  ] }),
3275
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3603
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3276
3604
  "input",
3277
3605
  {
3278
3606
  className: "zlm-range",
@@ -3310,8 +3638,8 @@ var ZenitLayerManager = ({
3310
3638
  );
3311
3639
  }) });
3312
3640
  };
3313
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: ["zenit-layer-manager", className].filter(Boolean).join(" "), style: panelStyle, children: [
3314
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: `
3641
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: ["zenit-layer-manager", className].filter(Boolean).join(" "), style: panelStyle, children: [
3642
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: `
3315
3643
  .zenit-layer-manager .zlm-card {
3316
3644
  transition: box-shadow 0.2s ease, transform 0.2s ease, opacity 0.2s ease;
3317
3645
  box-shadow: 0 6px 16px rgba(15, 23, 42, 0.08);
@@ -3406,16 +3734,16 @@ var ZenitLayerManager = ({
3406
3734
  outline-offset: 2px;
3407
3735
  }
3408
3736
  ` }),
3409
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: headerStyle, children: [
3410
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
3411
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
3412
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontWeight: 800, fontSize: 16, color: "#0f172a" }, children: "Gesti\xF3n de Capas" }),
3413
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { color: "#64748b", fontSize: 12 }, children: [
3737
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: headerStyle, children: [
3738
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
3739
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
3740
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontWeight: 800, fontSize: 16, color: "#0f172a" }, children: "Gesti\xF3n de Capas" }),
3741
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { color: "#64748b", fontSize: 12 }, children: [
3414
3742
  "Mapa #",
3415
3743
  map.id
3416
3744
  ] })
3417
3745
  ] }),
3418
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3746
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3419
3747
  "button",
3420
3748
  {
3421
3749
  type: "button",
@@ -3423,13 +3751,13 @@ var ZenitLayerManager = ({
3423
3751
  className: "zlm-panel-toggle",
3424
3752
  "aria-label": panelVisible ? "Ocultar panel de capas" : "Mostrar panel de capas",
3425
3753
  children: [
3426
- panelVisible ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Eye, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.EyeOff, { size: 16 }),
3754
+ panelVisible ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react.Eye, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react.EyeOff, { size: 16 }),
3427
3755
  panelVisible ? "Ocultar" : "Mostrar"
3428
3756
  ]
3429
3757
  }
3430
3758
  )
3431
3759
  ] }),
3432
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3760
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3433
3761
  "div",
3434
3762
  {
3435
3763
  style: {
@@ -3442,26 +3770,26 @@ var ZenitLayerManager = ({
3442
3770
  background: "#f1f5f9"
3443
3771
  },
3444
3772
  children: [
3445
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3773
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3446
3774
  "button",
3447
3775
  {
3448
3776
  type: "button",
3449
3777
  className: `zlm-tab${activeTab === "layers" ? " is-active" : ""}`,
3450
3778
  onClick: () => setActiveTab("layers"),
3451
3779
  children: [
3452
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Layers, { size: 16 }),
3780
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react.Layers, { size: 16 }),
3453
3781
  "Capas"
3454
3782
  ]
3455
3783
  }
3456
3784
  ),
3457
- showUploadTab && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3785
+ showUploadTab && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3458
3786
  "button",
3459
3787
  {
3460
3788
  type: "button",
3461
3789
  className: `zlm-tab${activeTab === "upload" ? " is-active" : ""}`,
3462
3790
  onClick: () => setActiveTab("upload"),
3463
3791
  children: [
3464
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Upload, { size: 16 }),
3792
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react.Upload, { size: 16 }),
3465
3793
  "Subir"
3466
3794
  ]
3467
3795
  }
@@ -3470,15 +3798,15 @@ var ZenitLayerManager = ({
3470
3798
  }
3471
3799
  )
3472
3800
  ] }),
3473
- panelVisible && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { padding: "12px 10px 18px", overflowY: "auto", flex: 1, minHeight: 0 }, children: [
3801
+ panelVisible && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { padding: "12px 10px 18px", overflowY: "auto", flex: 1, minHeight: 0 }, children: [
3474
3802
  activeTab === "layers" && renderLayerCards(),
3475
- showUploadTab && activeTab === "upload" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: "#475569", fontSize: 13 }, children: "Pr\xF3ximamente podr\xE1s subir capas desde este panel." })
3803
+ showUploadTab && activeTab === "upload" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { color: "#475569", fontSize: 13 }, children: "Pr\xF3ximamente podr\xE1s subir capas desde este panel." })
3476
3804
  ] })
3477
3805
  ] });
3478
3806
  };
3479
3807
 
3480
3808
  // src/react/ZenitFeatureFilterPanel.tsx
3481
- var import_jsx_runtime3 = require("react/jsx-runtime");
3809
+ var import_jsx_runtime5 = require("react/jsx-runtime");
3482
3810
  var ZenitFeatureFilterPanel = ({
3483
3811
  title = "Filtros",
3484
3812
  description,
@@ -3486,7 +3814,7 @@ var ZenitFeatureFilterPanel = ({
3486
3814
  style,
3487
3815
  children
3488
3816
  }) => {
3489
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3817
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3490
3818
  "section",
3491
3819
  {
3492
3820
  className,
@@ -3499,26 +3827,26 @@ var ZenitFeatureFilterPanel = ({
3499
3827
  ...style
3500
3828
  },
3501
3829
  children: [
3502
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { style: { marginBottom: 12 }, children: [
3503
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { style: { margin: 0, fontSize: 16 }, children: title }),
3504
- description && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: { margin: "6px 0 0", color: "#475569", fontSize: 13 }, children: description })
3830
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("header", { style: { marginBottom: 12 }, children: [
3831
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { style: { margin: 0, fontSize: 16 }, children: title }),
3832
+ description && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { style: { margin: "6px 0 0", color: "#475569", fontSize: 13 }, children: description })
3505
3833
  ] }),
3506
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children })
3834
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { children })
3507
3835
  ]
3508
3836
  }
3509
3837
  );
3510
3838
  };
3511
3839
 
3512
3840
  // src/react/ai/FloatingChatBox.tsx
3513
- var import_react4 = require("react");
3514
- var import_react_dom = require("react-dom");
3841
+ var import_react7 = require("react");
3842
+ var import_react_dom2 = require("react-dom");
3515
3843
 
3516
3844
  // src/react/hooks/use-chat.ts
3517
- var import_react3 = require("react");
3845
+ var import_react6 = require("react");
3518
3846
  var useSendMessage = (config) => {
3519
- const [isLoading, setIsLoading] = (0, import_react3.useState)(false);
3520
- const [error, setError] = (0, import_react3.useState)(null);
3521
- const send = (0, import_react3.useCallback)(
3847
+ const [isLoading, setIsLoading] = (0, import_react6.useState)(false);
3848
+ const [error, setError] = (0, import_react6.useState)(null);
3849
+ const send = (0, import_react6.useCallback)(
3522
3850
  async (mapId, request, options) => {
3523
3851
  setIsLoading(true);
3524
3852
  setError(null);
@@ -3536,18 +3864,18 @@ var useSendMessage = (config) => {
3536
3864
  return { sendMessage: send, isLoading, error };
3537
3865
  };
3538
3866
  var useSendMessageStream = (config) => {
3539
- const [isStreaming, setIsStreaming] = (0, import_react3.useState)(false);
3540
- const [streamingText, setStreamingText] = (0, import_react3.useState)("");
3541
- const [completeResponse, setCompleteResponse] = (0, import_react3.useState)(null);
3542
- const [error, setError] = (0, import_react3.useState)(null);
3543
- const requestIdRef = (0, import_react3.useRef)(0);
3544
- const reset = (0, import_react3.useCallback)(() => {
3867
+ const [isStreaming, setIsStreaming] = (0, import_react6.useState)(false);
3868
+ const [streamingText, setStreamingText] = (0, import_react6.useState)("");
3869
+ const [completeResponse, setCompleteResponse] = (0, import_react6.useState)(null);
3870
+ const [error, setError] = (0, import_react6.useState)(null);
3871
+ const requestIdRef = (0, import_react6.useRef)(0);
3872
+ const reset = (0, import_react6.useCallback)(() => {
3545
3873
  setIsStreaming(false);
3546
3874
  setStreamingText("");
3547
3875
  setCompleteResponse(null);
3548
3876
  setError(null);
3549
3877
  }, []);
3550
- const send = (0, import_react3.useCallback)(
3878
+ const send = (0, import_react6.useCallback)(
3551
3879
  async (mapId, request, options) => {
3552
3880
  const requestId = requestIdRef.current + 1;
3553
3881
  requestIdRef.current = requestId;
@@ -3601,7 +3929,7 @@ var useSendMessageStream = (config) => {
3601
3929
  // src/react/components/MarkdownRenderer.tsx
3602
3930
  var import_react_markdown = __toESM(require("react-markdown"));
3603
3931
  var import_remark_gfm = __toESM(require("remark-gfm"));
3604
- var import_jsx_runtime4 = require("react/jsx-runtime");
3932
+ var import_jsx_runtime6 = require("react/jsx-runtime");
3605
3933
  function normalizeAssistantMarkdown(text) {
3606
3934
  if (!text || typeof text !== "string") return "";
3607
3935
  let normalized = text;
@@ -3617,28 +3945,28 @@ var MarkdownRenderer = ({ content, className }) => {
3617
3945
  if (!normalizedContent) {
3618
3946
  return null;
3619
3947
  }
3620
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className, style: { wordBreak: "break-word" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3948
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className, style: { wordBreak: "break-word" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3621
3949
  import_react_markdown.default,
3622
3950
  {
3623
3951
  remarkPlugins: [import_remark_gfm.default],
3624
3952
  components: {
3625
3953
  // Headings with proper spacing
3626
- h1: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { style: { fontSize: "1.5em", fontWeight: 700, marginTop: "1em", marginBottom: "0.5em" }, ...props, children }),
3627
- h2: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { style: { fontSize: "1.3em", fontWeight: 700, marginTop: "0.9em", marginBottom: "0.45em" }, ...props, children }),
3628
- h3: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { style: { fontSize: "1.15em", fontWeight: 600, marginTop: "0.75em", marginBottom: "0.4em" }, ...props, children }),
3629
- h4: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h4", { style: { fontSize: "1.05em", fontWeight: 600, marginTop: "0.6em", marginBottom: "0.35em" }, ...props, children }),
3630
- h5: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h5", { style: { fontSize: "1em", fontWeight: 600, marginTop: "0.5em", marginBottom: "0.3em" }, ...props, children }),
3631
- h6: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h6", { style: { fontSize: "0.95em", fontWeight: 600, marginTop: "0.5em", marginBottom: "0.3em" }, ...props, children }),
3954
+ h1: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h1", { style: { fontSize: "1.5em", fontWeight: 700, marginTop: "1em", marginBottom: "0.5em" }, ...props, children }),
3955
+ h2: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { style: { fontSize: "1.3em", fontWeight: 700, marginTop: "0.9em", marginBottom: "0.45em" }, ...props, children }),
3956
+ h3: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { style: { fontSize: "1.15em", fontWeight: 600, marginTop: "0.75em", marginBottom: "0.4em" }, ...props, children }),
3957
+ h4: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h4", { style: { fontSize: "1.05em", fontWeight: 600, marginTop: "0.6em", marginBottom: "0.35em" }, ...props, children }),
3958
+ h5: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h5", { style: { fontSize: "1em", fontWeight: 600, marginTop: "0.5em", marginBottom: "0.3em" }, ...props, children }),
3959
+ h6: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h6", { style: { fontSize: "0.95em", fontWeight: 600, marginTop: "0.5em", marginBottom: "0.3em" }, ...props, children }),
3632
3960
  // Paragraphs with comfortable line height
3633
- p: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: { marginTop: "0.5em", marginBottom: "0.5em", lineHeight: 1.6 }, ...props, children }),
3961
+ p: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: { marginTop: "0.5em", marginBottom: "0.5em", lineHeight: 1.6 }, ...props, children }),
3634
3962
  // Lists with proper indentation
3635
- ul: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { style: { paddingLeft: "1.5em", marginTop: "0.5em", marginBottom: "0.5em" }, ...props, children }),
3636
- ol: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ol", { style: { paddingLeft: "1.5em", marginTop: "0.5em", marginBottom: "0.5em" }, ...props, children }),
3637
- li: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { style: { marginTop: "0.25em", marginBottom: "0.25em" }, ...props, children }),
3963
+ ul: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { style: { paddingLeft: "1.5em", marginTop: "0.5em", marginBottom: "0.5em" }, ...props, children }),
3964
+ ol: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ol", { style: { paddingLeft: "1.5em", marginTop: "0.5em", marginBottom: "0.5em" }, ...props, children }),
3965
+ li: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { style: { marginTop: "0.25em", marginBottom: "0.25em" }, ...props, children }),
3638
3966
  // Code blocks
3639
3967
  code: ({ inline, children, ...props }) => {
3640
3968
  if (inline) {
3641
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3969
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3642
3970
  "code",
3643
3971
  {
3644
3972
  style: {
@@ -3653,7 +3981,7 @@ var MarkdownRenderer = ({ content, className }) => {
3653
3981
  }
3654
3982
  );
3655
3983
  }
3656
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3984
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3657
3985
  "code",
3658
3986
  {
3659
3987
  style: {
@@ -3673,9 +4001,9 @@ var MarkdownRenderer = ({ content, className }) => {
3673
4001
  );
3674
4002
  },
3675
4003
  // Pre (code block wrapper)
3676
- pre: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("pre", { style: { margin: 0 }, ...props, children }),
4004
+ pre: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { style: { margin: 0 }, ...props, children }),
3677
4005
  // Blockquotes
3678
- blockquote: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4006
+ blockquote: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3679
4007
  "blockquote",
3680
4008
  {
3681
4009
  style: {
@@ -3691,11 +4019,11 @@ var MarkdownRenderer = ({ content, className }) => {
3691
4019
  }
3692
4020
  ),
3693
4021
  // Strong/bold
3694
- strong: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { style: { fontWeight: 600 }, ...props, children }),
4022
+ strong: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { style: { fontWeight: 600 }, ...props, children }),
3695
4023
  // Emphasis/italic
3696
- em: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("em", { style: { fontStyle: "italic" }, ...props, children }),
4024
+ em: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("em", { style: { fontStyle: "italic" }, ...props, children }),
3697
4025
  // Horizontal rule
3698
- hr: (props) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4026
+ hr: (props) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3699
4027
  "hr",
3700
4028
  {
3701
4029
  style: {
@@ -3708,7 +4036,7 @@ var MarkdownRenderer = ({ content, className }) => {
3708
4036
  }
3709
4037
  ),
3710
4038
  // Tables (GFM)
3711
- table: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { overflowX: "auto", marginTop: "0.5em", marginBottom: "0.5em" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4039
+ table: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { overflowX: "auto", marginTop: "0.5em", marginBottom: "0.5em" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3712
4040
  "table",
3713
4041
  {
3714
4042
  style: {
@@ -3720,7 +4048,7 @@ var MarkdownRenderer = ({ content, className }) => {
3720
4048
  children
3721
4049
  }
3722
4050
  ) }),
3723
- th: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4051
+ th: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3724
4052
  "th",
3725
4053
  {
3726
4054
  style: {
@@ -3734,7 +4062,7 @@ var MarkdownRenderer = ({ content, className }) => {
3734
4062
  children
3735
4063
  }
3736
4064
  ),
3737
- td: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4065
+ td: ({ children, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3738
4066
  "td",
3739
4067
  {
3740
4068
  style: {
@@ -3752,32 +4080,32 @@ var MarkdownRenderer = ({ content, className }) => {
3752
4080
  };
3753
4081
 
3754
4082
  // src/react/ai/FloatingChatBox.tsx
3755
- var import_jsx_runtime5 = require("react/jsx-runtime");
3756
- var ChatIcon = () => /* @__PURE__ */ (0, import_jsx_runtime5.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_runtime5.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" }) });
3757
- var CloseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3758
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
3759
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
4083
+ var import_jsx_runtime7 = require("react/jsx-runtime");
4084
+ var ChatIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.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_runtime7.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" }) });
4085
+ var CloseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4086
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
4087
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
3760
4088
  ] });
3761
- var ExpandIcon = () => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3762
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "15 3 21 3 21 9" }),
3763
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "9 21 3 21 3 15" }),
3764
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
3765
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
4089
+ var ExpandIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4090
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("polyline", { points: "15 3 21 3 21 9" }),
4091
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("polyline", { points: "9 21 3 21 3 15" }),
4092
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
4093
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
3766
4094
  ] });
3767
- var CollapseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3768
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "4 14 10 14 10 20" }),
3769
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "20 10 14 10 14 4" }),
3770
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "14", y1: "10", x2: "21", y2: "3" }),
3771
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
4095
+ var CollapseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4096
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("polyline", { points: "4 14 10 14 10 20" }),
4097
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("polyline", { points: "20 10 14 10 14 4" }),
4098
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "14", y1: "10", x2: "21", y2: "3" }),
4099
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
3772
4100
  ] });
3773
- var SendIcon = () => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3774
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
3775
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
4101
+ var SendIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4102
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
4103
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
3776
4104
  ] });
3777
- var LayersIcon = () => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3778
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }),
3779
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "2 17 12 22 22 17" }),
3780
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "2 12 12 17 22 12" })
4105
+ var LayersIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4106
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }),
4107
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("polyline", { points: "2 17 12 22 22 17" }),
4108
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("polyline", { points: "2 12 12 17 22 12" })
3781
4109
  ] });
3782
4110
  var styles = {
3783
4111
  root: {
@@ -3786,8 +4114,8 @@ var styles = {
3786
4114
  // Floating button (closed state - wide with text, open state - circular with X)
3787
4115
  floatingButton: {
3788
4116
  position: "fixed",
3789
- bottom: 24,
3790
- right: 24,
4117
+ bottom: 16,
4118
+ right: 16,
3791
4119
  borderRadius: "999px",
3792
4120
  border: "none",
3793
4121
  cursor: "pointer",
@@ -3797,30 +4125,30 @@ var styles = {
3797
4125
  display: "flex",
3798
4126
  alignItems: "center",
3799
4127
  justifyContent: "center",
3800
- fontSize: 15,
4128
+ fontSize: 14,
3801
4129
  fontWeight: 600,
3802
4130
  zIndex: 99999,
3803
4131
  transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
3804
4132
  },
3805
4133
  floatingButtonClosed: {
3806
- padding: "14px 24px",
4134
+ padding: "12px 20px",
3807
4135
  gap: 8
3808
4136
  },
3809
4137
  floatingButtonOpen: {
3810
- width: 56,
3811
- height: 56,
4138
+ width: 52,
4139
+ height: 52,
3812
4140
  padding: 0
3813
4141
  },
3814
4142
  floatingButtonMobile: {
3815
- width: 56,
3816
- height: 56,
4143
+ width: 52,
4144
+ height: 52,
3817
4145
  padding: 0
3818
4146
  },
3819
4147
  // Panel (expandable)
3820
4148
  panel: {
3821
4149
  position: "fixed",
3822
- bottom: 92,
3823
- right: 24,
4150
+ bottom: 80,
4151
+ right: 16,
3824
4152
  background: "#fff",
3825
4153
  borderRadius: 16,
3826
4154
  boxShadow: "0 20px 60px rgba(15, 23, 42, 0.3), 0 0 0 1px rgba(15, 23, 42, 0.05)",
@@ -3831,16 +4159,16 @@ var styles = {
3831
4159
  transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
3832
4160
  },
3833
4161
  panelNormal: {
3834
- width: 400,
3835
- height: 550
4162
+ width: 360,
4163
+ height: 520
3836
4164
  },
3837
4165
  panelExpanded: {
3838
- width: 520,
3839
- height: 700
4166
+ width: 480,
4167
+ height: 640
3840
4168
  },
3841
4169
  // Header with green gradient
3842
4170
  header: {
3843
- padding: "16px 18px",
4171
+ padding: "14px 16px",
3844
4172
  background: "linear-gradient(135deg, #10b981, #059669)",
3845
4173
  color: "#fff",
3846
4174
  display: "flex",
@@ -3849,7 +4177,7 @@ var styles = {
3849
4177
  },
3850
4178
  title: {
3851
4179
  margin: 0,
3852
- fontSize: 16,
4180
+ fontSize: 15,
3853
4181
  fontWeight: 600,
3854
4182
  letterSpacing: "-0.01em"
3855
4183
  },
@@ -3862,8 +4190,8 @@ var styles = {
3862
4190
  border: "none",
3863
4191
  background: "rgba(255, 255, 255, 0.15)",
3864
4192
  color: "#fff",
3865
- width: 32,
3866
- height: 32,
4193
+ width: 30,
4194
+ height: 30,
3867
4195
  borderRadius: 8,
3868
4196
  cursor: "pointer",
3869
4197
  display: "flex",
@@ -3874,7 +4202,7 @@ var styles = {
3874
4202
  // Messages area
3875
4203
  messages: {
3876
4204
  flex: 1,
3877
- padding: "20px 18px",
4205
+ padding: "16px",
3878
4206
  overflowY: "auto",
3879
4207
  background: "#f8fafc",
3880
4208
  display: "flex",
@@ -3889,10 +4217,10 @@ var styles = {
3889
4217
  },
3890
4218
  messageBubble: {
3891
4219
  maxWidth: "85%",
3892
- padding: "12px 14px",
4220
+ padding: "10px 12px",
3893
4221
  borderRadius: 16,
3894
4222
  lineHeight: 1.5,
3895
- fontSize: 14,
4223
+ fontSize: 13,
3896
4224
  whiteSpace: "pre-wrap",
3897
4225
  wordBreak: "break-word"
3898
4226
  },
@@ -4006,7 +4334,7 @@ var styles = {
4006
4334
  // Input area
4007
4335
  inputWrapper: {
4008
4336
  borderTop: "1px solid #e2e8f0",
4009
- padding: "14px 16px",
4337
+ padding: "10px 14px",
4010
4338
  display: "flex",
4011
4339
  gap: 10,
4012
4340
  alignItems: "flex-end",
@@ -4017,8 +4345,8 @@ var styles = {
4017
4345
  resize: "none",
4018
4346
  borderRadius: 12,
4019
4347
  border: "1.5px solid #cbd5e1",
4020
- padding: "10px 12px",
4021
- fontSize: 14,
4348
+ padding: "8px 10px",
4349
+ fontSize: 13,
4022
4350
  fontFamily: "inherit",
4023
4351
  lineHeight: 1.4,
4024
4352
  transition: "border-color 0.2s"
@@ -4030,18 +4358,18 @@ var styles = {
4030
4358
  sendButton: {
4031
4359
  borderRadius: 12,
4032
4360
  border: "none",
4033
- padding: "10px 14px",
4361
+ padding: "8px 12px",
4034
4362
  background: "linear-gradient(135deg, #10b981, #059669)",
4035
4363
  color: "#fff",
4036
4364
  cursor: "pointer",
4037
- fontSize: 14,
4365
+ fontSize: 13,
4038
4366
  fontWeight: 600,
4039
4367
  display: "flex",
4040
4368
  alignItems: "center",
4041
4369
  justifyContent: "center",
4042
4370
  transition: "opacity 0.2s, transform 0.2s",
4043
- minWidth: 44,
4044
- height: 44
4371
+ minWidth: 40,
4372
+ height: 40
4045
4373
  },
4046
4374
  // Status messages
4047
4375
  statusNote: {
@@ -4071,42 +4399,42 @@ var FloatingChatBox = ({
4071
4399
  open: openProp
4072
4400
  }) => {
4073
4401
  const isControlled = openProp !== void 0;
4074
- const [internalOpen, setInternalOpen] = (0, import_react4.useState)(false);
4402
+ const [internalOpen, setInternalOpen] = (0, import_react7.useState)(false);
4075
4403
  const open = isControlled ? openProp : internalOpen;
4076
- const setOpen = (0, import_react4.useCallback)((value) => {
4404
+ const setOpen = (0, import_react7.useCallback)((value) => {
4077
4405
  const newValue = typeof value === "function" ? value(open) : value;
4078
4406
  if (!isControlled) {
4079
4407
  setInternalOpen(newValue);
4080
4408
  }
4081
4409
  onOpenChange?.(newValue);
4082
4410
  }, [isControlled, open, onOpenChange]);
4083
- const [expanded, setExpanded] = (0, import_react4.useState)(false);
4084
- const [messages, setMessages] = (0, import_react4.useState)([]);
4085
- const [inputValue, setInputValue] = (0, import_react4.useState)("");
4086
- const [conversationId, setConversationId] = (0, import_react4.useState)();
4087
- const [errorMessage, setErrorMessage] = (0, import_react4.useState)(null);
4088
- const [isFocused, setIsFocused] = (0, import_react4.useState)(false);
4089
- const [isMobile, setIsMobile] = (0, import_react4.useState)(false);
4090
- const messagesEndRef = (0, import_react4.useRef)(null);
4091
- const messagesContainerRef = (0, import_react4.useRef)(null);
4092
- const chatBoxRef = (0, import_react4.useRef)(null);
4093
- const chatConfig = (0, import_react4.useMemo)(() => {
4411
+ const [expanded, setExpanded] = (0, import_react7.useState)(false);
4412
+ const [messages, setMessages] = (0, import_react7.useState)([]);
4413
+ const [inputValue, setInputValue] = (0, import_react7.useState)("");
4414
+ const [conversationId, setConversationId] = (0, import_react7.useState)();
4415
+ const [errorMessage, setErrorMessage] = (0, import_react7.useState)(null);
4416
+ const [isFocused, setIsFocused] = (0, import_react7.useState)(false);
4417
+ const [isMobile, setIsMobile] = (0, import_react7.useState)(false);
4418
+ const messagesEndRef = (0, import_react7.useRef)(null);
4419
+ const messagesContainerRef = (0, import_react7.useRef)(null);
4420
+ const chatBoxRef = (0, import_react7.useRef)(null);
4421
+ const chatConfig = (0, import_react7.useMemo)(() => {
4094
4422
  if (!baseUrl) return void 0;
4095
4423
  return { baseUrl, accessToken, getAccessToken };
4096
4424
  }, [accessToken, baseUrl, getAccessToken]);
4097
4425
  const { sendMessage: sendMessage2, isStreaming, streamingText, completeResponse } = useSendMessageStream(chatConfig);
4098
4426
  const canSend = Boolean(mapId) && Boolean(baseUrl) && inputValue.trim().length > 0 && !isStreaming;
4099
- (0, import_react4.useEffect)(() => {
4427
+ (0, import_react7.useEffect)(() => {
4100
4428
  if (open && isMobile) {
4101
4429
  setExpanded(true);
4102
4430
  }
4103
4431
  }, [open, isMobile]);
4104
- const scrollToBottom = (0, import_react4.useCallback)(() => {
4432
+ const scrollToBottom = (0, import_react7.useCallback)(() => {
4105
4433
  if (messagesEndRef.current) {
4106
4434
  messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
4107
4435
  }
4108
4436
  }, []);
4109
- (0, import_react4.useEffect)(() => {
4437
+ (0, import_react7.useEffect)(() => {
4110
4438
  if (open && messages.length === 0) {
4111
4439
  setMessages([
4112
4440
  {
@@ -4117,10 +4445,10 @@ var FloatingChatBox = ({
4117
4445
  ]);
4118
4446
  }
4119
4447
  }, [open, messages.length]);
4120
- (0, import_react4.useEffect)(() => {
4448
+ (0, import_react7.useEffect)(() => {
4121
4449
  scrollToBottom();
4122
4450
  }, [messages, streamingText, scrollToBottom]);
4123
- (0, import_react4.useEffect)(() => {
4451
+ (0, import_react7.useEffect)(() => {
4124
4452
  if (!open) return;
4125
4453
  if (isMobile && expanded) return;
4126
4454
  const handleClickOutside = (event) => {
@@ -4133,7 +4461,7 @@ var FloatingChatBox = ({
4133
4461
  document.removeEventListener("mousedown", handleClickOutside);
4134
4462
  };
4135
4463
  }, [open, isMobile, expanded]);
4136
- (0, import_react4.useEffect)(() => {
4464
+ (0, import_react7.useEffect)(() => {
4137
4465
  if (typeof window === "undefined") return;
4138
4466
  const mediaQuery = window.matchMedia("(max-width: 768px)");
4139
4467
  const updateMobile = () => setIsMobile(mediaQuery.matches);
@@ -4151,7 +4479,7 @@ var FloatingChatBox = ({
4151
4479
  }
4152
4480
  };
4153
4481
  }, []);
4154
- (0, import_react4.useEffect)(() => {
4482
+ (0, import_react7.useEffect)(() => {
4155
4483
  if (typeof document === "undefined") return;
4156
4484
  if (!open || !isMobile) return;
4157
4485
  document.body.style.overflow = "hidden";
@@ -4159,10 +4487,10 @@ var FloatingChatBox = ({
4159
4487
  document.body.style.overflow = "";
4160
4488
  };
4161
4489
  }, [open, isMobile]);
4162
- const addMessage = (0, import_react4.useCallback)((message) => {
4490
+ const addMessage = (0, import_react7.useCallback)((message) => {
4163
4491
  setMessages((prev) => [...prev, message]);
4164
4492
  }, []);
4165
- const handleSend = (0, import_react4.useCallback)(async () => {
4493
+ const handleSend = (0, import_react7.useCallback)(async () => {
4166
4494
  if (!mapId) {
4167
4495
  setErrorMessage("Selecciona un mapa para usar el asistente.");
4168
4496
  return;
@@ -4197,11 +4525,11 @@ var FloatingChatBox = ({
4197
4525
  response
4198
4526
  });
4199
4527
  } catch (error) {
4200
- setErrorMessage(error instanceof Error ? error.message : "Ocurri\xF3 un error inesperado.");
4528
+ setErrorMessage("Ocurri\xF3 un error al generar la respuesta.");
4201
4529
  addMessage({
4202
4530
  id: `error-${Date.now()}`,
4203
4531
  role: "assistant",
4204
- content: `\u274C Error: ${error instanceof Error ? error.message : "Ocurri\xF3 un error inesperado."}`
4532
+ content: "\u274C Ocurri\xF3 un error al generar la respuesta."
4205
4533
  });
4206
4534
  }
4207
4535
  }, [
@@ -4215,7 +4543,7 @@ var FloatingChatBox = ({
4215
4543
  sendMessage2,
4216
4544
  userId
4217
4545
  ]);
4218
- const handleKeyDown = (0, import_react4.useCallback)(
4546
+ const handleKeyDown = (0, import_react7.useCallback)(
4219
4547
  (event) => {
4220
4548
  if (event.key === "Enter" && !event.shiftKey) {
4221
4549
  event.preventDefault();
@@ -4226,20 +4554,20 @@ var FloatingChatBox = ({
4226
4554
  },
4227
4555
  [canSend, handleSend]
4228
4556
  );
4229
- const handleFollowUpClick = (0, import_react4.useCallback)((question) => {
4557
+ const handleFollowUpClick = (0, import_react7.useCallback)((question) => {
4230
4558
  setInputValue(question);
4231
4559
  }, []);
4232
4560
  const renderMetadata = (response) => {
4233
4561
  if (!response?.metadata) return null;
4234
4562
  const referencedLayers = response.metadata.referencedLayers;
4235
4563
  if (!referencedLayers || referencedLayers.length === 0) return null;
4236
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles.metadataSection, children: [
4237
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles.metadataTitle, children: [
4238
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(LayersIcon, {}),
4564
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.metadataSection, children: [
4565
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.metadataTitle, children: [
4566
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LayersIcon, {}),
4239
4567
  "Capas Analizadas"
4240
4568
  ] }),
4241
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { style: styles.metadataList, children: referencedLayers.map((layer, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("li", { style: styles.metadataItem, children: [
4242
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: layer.layerName }),
4569
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ul", { style: styles.metadataList, children: referencedLayers.map((layer, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("li", { style: styles.metadataItem, children: [
4570
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("strong", { children: layer.layerName }),
4243
4571
  " (",
4244
4572
  layer.featureCount,
4245
4573
  " ",
@@ -4248,7 +4576,7 @@ var FloatingChatBox = ({
4248
4576
  ] }, index)) })
4249
4577
  ] });
4250
4578
  };
4251
- const handleActionClick = (0, import_react4.useCallback)((action) => {
4579
+ const handleActionClick = (0, import_react7.useCallback)((action) => {
4252
4580
  if (isStreaming) return;
4253
4581
  setOpen(false);
4254
4582
  requestAnimationFrame(() => {
@@ -4257,9 +4585,9 @@ var FloatingChatBox = ({
4257
4585
  }, [isStreaming, setOpen, onActionClick]);
4258
4586
  const renderActions = (response) => {
4259
4587
  if (!response?.suggestedActions?.length) return null;
4260
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles.actionsSection, children: [
4261
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.sectionLabel, children: "Acciones Sugeridas" }),
4262
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.actionsGrid, children: response.suggestedActions.map((action, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4588
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.actionsSection, children: [
4589
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.sectionLabel, children: "Acciones Sugeridas" }),
4590
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.actionsGrid, children: response.suggestedActions.map((action, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4263
4591
  "button",
4264
4592
  {
4265
4593
  type: "button",
@@ -4290,9 +4618,9 @@ var FloatingChatBox = ({
4290
4618
  };
4291
4619
  const renderFollowUps = (response) => {
4292
4620
  if (!response?.followUpQuestions?.length) return null;
4293
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles.actionsSection, children: [
4294
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.sectionLabel, children: "Preguntas Relacionadas" }),
4295
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: response.followUpQuestions.map((question, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4621
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.actionsSection, children: [
4622
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.sectionLabel, children: "Preguntas Relacionadas" }),
4623
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: response.followUpQuestions.map((question, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4296
4624
  "button",
4297
4625
  {
4298
4626
  type: "button",
@@ -4321,8 +4649,8 @@ var FloatingChatBox = ({
4321
4649
  )) })
4322
4650
  ] });
4323
4651
  };
4324
- const chatContent = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles.root, children: [
4325
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: `
4652
+ const chatContent = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.root, children: [
4653
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `
4326
4654
  @keyframes zenitBlink {
4327
4655
  0%, 49% { opacity: 1; }
4328
4656
  50%, 100% { opacity: 0; }
@@ -4365,11 +4693,13 @@ var FloatingChatBox = ({
4365
4693
  @media (max-width: 768px) {
4366
4694
  .zenit-chat-panel.zenit-chat-panel--fullscreen {
4367
4695
  position: fixed !important;
4368
- inset: 0 !important;
4369
- width: 100vw !important;
4370
- max-width: 100vw !important;
4371
- height: 100vh !important;
4372
- height: 100dvh !important;
4696
+ left: 0 !important;
4697
+ right: 0 !important;
4698
+ top: 4rem !important;
4699
+ bottom: 0 !important;
4700
+ width: 100% !important;
4701
+ max-width: 100% !important;
4702
+ height: auto !important;
4373
4703
  border-radius: 0 !important;
4374
4704
  display: flex !important;
4375
4705
  flex-direction: column !important;
@@ -4392,7 +4722,7 @@ var FloatingChatBox = ({
4392
4722
  }
4393
4723
  }
4394
4724
  ` }),
4395
- open && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
4725
+ open && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4396
4726
  "div",
4397
4727
  {
4398
4728
  ref: chatBoxRef,
@@ -4402,10 +4732,10 @@ var FloatingChatBox = ({
4402
4732
  ...expanded ? styles.panelExpanded : styles.panelNormal
4403
4733
  },
4404
4734
  children: [
4405
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("header", { style: styles.header, children: [
4406
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { style: styles.title, children: "Asistente Zenit AI" }),
4407
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles.headerButtons, children: [
4408
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4735
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("header", { style: styles.header, children: [
4736
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { style: styles.title, children: "Asistente Zenit AI" }),
4737
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.headerButtons, children: [
4738
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4409
4739
  "button",
4410
4740
  {
4411
4741
  type: "button",
@@ -4418,10 +4748,10 @@ var FloatingChatBox = ({
4418
4748
  e.currentTarget.style.background = "rgba(255, 255, 255, 0.15)";
4419
4749
  },
4420
4750
  "aria-label": expanded ? "Contraer" : "Expandir",
4421
- children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CollapseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ExpandIcon, {})
4751
+ children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CollapseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ExpandIcon, {})
4422
4752
  }
4423
4753
  ),
4424
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4754
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4425
4755
  "button",
4426
4756
  {
4427
4757
  type: "button",
@@ -4434,20 +4764,20 @@ var FloatingChatBox = ({
4434
4764
  e.currentTarget.style.background = "rgba(255, 255, 255, 0.15)";
4435
4765
  },
4436
4766
  "aria-label": "Cerrar",
4437
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CloseIcon, {})
4767
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CloseIcon, {})
4438
4768
  }
4439
4769
  )
4440
4770
  ] })
4441
4771
  ] }),
4442
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: messagesContainerRef, className: "zenit-ai-body", style: styles.messages, children: [
4443
- messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4772
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { ref: messagesContainerRef, className: "zenit-ai-body", style: styles.messages, children: [
4773
+ messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4444
4774
  "div",
4445
4775
  {
4446
4776
  style: {
4447
4777
  ...styles.messageWrapper,
4448
4778
  alignItems: message.role === "user" ? "flex-end" : "flex-start"
4449
4779
  },
4450
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
4780
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4451
4781
  "div",
4452
4782
  {
4453
4783
  style: {
@@ -4455,7 +4785,7 @@ var FloatingChatBox = ({
4455
4785
  ...message.role === "user" ? styles.userMessage : styles.assistantMessage
4456
4786
  },
4457
4787
  children: [
4458
- message.role === "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MarkdownRenderer, { content: message.content }) : message.content,
4788
+ message.role === "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MarkdownRenderer, { content: message.content }) : message.content,
4459
4789
  message.role === "assistant" && renderMetadata(message.response),
4460
4790
  message.role === "assistant" && renderActions(message.response),
4461
4791
  message.role === "assistant" && renderFollowUps(message.response)
@@ -4465,39 +4795,39 @@ var FloatingChatBox = ({
4465
4795
  },
4466
4796
  message.id
4467
4797
  )),
4468
- isStreaming && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4798
+ isStreaming && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4469
4799
  "div",
4470
4800
  {
4471
4801
  style: {
4472
4802
  ...styles.messageWrapper,
4473
4803
  alignItems: "flex-start"
4474
4804
  },
4475
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4805
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4476
4806
  "div",
4477
4807
  {
4478
4808
  style: {
4479
4809
  ...styles.messageBubble,
4480
4810
  ...styles.assistantMessage
4481
4811
  },
4482
- children: streamingText ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
4483
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MarkdownRenderer, { content: streamingText }),
4484
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles.cursor })
4485
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles.thinkingText, children: [
4486
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Analizando" }),
4487
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles.typingIndicator, children: [
4488
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot }),
4489
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot }),
4490
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot })
4812
+ children: streamingText ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4813
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MarkdownRenderer, { content: streamingText }),
4814
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: styles.cursor })
4815
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.thinkingText, children: [
4816
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Pensando" }),
4817
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.typingIndicator, children: [
4818
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot }),
4819
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot }),
4820
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "zenit-typing-dot", style: styles.typingDot })
4491
4821
  ] })
4492
4822
  ] })
4493
4823
  }
4494
4824
  )
4495
4825
  }
4496
4826
  ),
4497
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ref: messagesEndRef })
4827
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { ref: messagesEndRef })
4498
4828
  ] }),
4499
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "zenit-ai-input-area", style: styles.inputWrapper, children: [
4500
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4829
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "zenit-ai-input-area", style: styles.inputWrapper, children: [
4830
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4501
4831
  "textarea",
4502
4832
  {
4503
4833
  style: {
@@ -4514,7 +4844,7 @@ var FloatingChatBox = ({
4514
4844
  disabled: !mapId || !baseUrl || isStreaming
4515
4845
  }
4516
4846
  ),
4517
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4847
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4518
4848
  "button",
4519
4849
  {
4520
4850
  type: "button",
@@ -4523,36 +4853,38 @@ var FloatingChatBox = ({
4523
4853
  onClick: () => void handleSend(),
4524
4854
  disabled: !canSend,
4525
4855
  "aria-label": "Enviar mensaje",
4526
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SendIcon, {})
4856
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SendIcon, {})
4527
4857
  }
4528
4858
  )
4529
4859
  ] }),
4530
- errorMessage && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.errorText, children: errorMessage }),
4531
- !mapId && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.statusNote, children: "Selecciona un mapa para usar el asistente" }),
4532
- !baseUrl && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.statusNote, children: "Configura la baseUrl del SDK" })
4860
+ errorMessage && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.errorText, children: errorMessage }),
4861
+ isStreaming && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.statusNote, children: "Generando sugerencias..." }),
4862
+ !mapId && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.statusNote, children: "Selecciona un mapa para usar el asistente" }),
4863
+ !baseUrl && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.statusNote, children: "Configura la baseUrl del SDK" })
4533
4864
  ]
4534
4865
  }
4535
4866
  ),
4536
- !(hideButton && !open) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4867
+ !(hideButton && !open) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4537
4868
  "button",
4538
4869
  {
4539
4870
  type: "button",
4540
4871
  className: `zenit-ai-button ${open ? "open" : ""}${open && isMobile ? " zenit-ai-button--hidden-mobile" : ""}`,
4541
4872
  style: {
4542
4873
  ...styles.floatingButton,
4543
- ...open ? styles.floatingButtonOpen : isMobile ? styles.floatingButtonMobile : styles.floatingButtonClosed
4874
+ ...open ? styles.floatingButtonOpen : isMobile ? styles.floatingButtonMobile : styles.floatingButtonClosed,
4875
+ zIndex: open ? 100001 : 99999
4544
4876
  },
4545
4877
  onClick: () => setOpen((prev) => !prev),
4546
4878
  "aria-label": open ? "Cerrar asistente" : "Abrir asistente Zenit AI",
4547
- children: open ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CloseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
4548
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChatIcon, {}),
4549
- !isMobile && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Asistente IA" })
4879
+ children: open ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CloseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4880
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChatIcon, {}),
4881
+ !isMobile && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Asistente IA" })
4550
4882
  ] })
4551
4883
  }
4552
4884
  )
4553
4885
  ] });
4554
4886
  if (typeof document !== "undefined") {
4555
- return (0, import_react_dom.createPortal)(chatContent, document.body);
4887
+ return (0, import_react_dom2.createPortal)(chatContent, document.body);
4556
4888
  }
4557
4889
  return chatContent;
4558
4890
  };
@@ -4603,12 +4935,15 @@ var FloatingChatBox = ({
4603
4935
  getZoomOpacityFactor,
4604
4936
  initLayerStates,
4605
4937
  isPolygonLayer,
4938
+ mergeFilters,
4606
4939
  normalizeBbox,
4940
+ normalizeFilters,
4607
4941
  normalizeMapCenter,
4608
4942
  normalizeMapLayers,
4609
4943
  resetOverrides,
4610
4944
  resolveLayerAccent,
4611
4945
  resolveLayerStrategy,
4946
+ resolveRuntimeConfig,
4612
4947
  sendMessage,
4613
4948
  sendMessageStream,
4614
4949
  shouldSkipGeojsonDownload,