zenit-sdk 0.0.3 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-R73LRYVJ.mjs → chunk-ITF7QCUZ.mjs} +523 -72
- package/dist/chunk-ITF7QCUZ.mjs.map +1 -0
- package/dist/{index-Da0hFqDL.d.mts → index-kGwfqTc_.d.mts} +5 -0
- package/dist/{index-Da0hFqDL.d.ts → index-kGwfqTc_.d.ts} +5 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +523 -72
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/react/index.d.mts +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +522 -71
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +1 -1
- package/package.json +7 -27
- package/dist/chunk-R73LRYVJ.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1403,7 +1403,7 @@ function normalizeBbox(input) {
|
|
|
1403
1403
|
}
|
|
1404
1404
|
|
|
1405
1405
|
// src/react/ZenitMap.tsx
|
|
1406
|
-
var import_react = require("react");
|
|
1406
|
+
var import_react = __toESM(require("react"));
|
|
1407
1407
|
var import_react_leaflet = require("react-leaflet");
|
|
1408
1408
|
var import_leaflet = __toESM(require("leaflet"));
|
|
1409
1409
|
|
|
@@ -1518,6 +1518,366 @@ function getFeatureLayerId(feature) {
|
|
|
1518
1518
|
function escapeHtml(value) {
|
|
1519
1519
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1520
1520
|
}
|
|
1521
|
+
var DESCRIPTION_KEYS = /* @__PURE__ */ new Set(["descripcion", "description"]);
|
|
1522
|
+
var POPUP_EXCLUDED_KEYS = /* @__PURE__ */ new Set(["geom", "geometry"]);
|
|
1523
|
+
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 };
|
|
1526
|
+
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 {
|
|
1531
|
+
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
|
+
padding: 0;
|
|
1537
|
+
background: #ffffff;
|
|
1538
|
+
overflow: hidden;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
/* Content area with scroll support */
|
|
1542
|
+
.zenit-leaflet-popup .leaflet-popup-content {
|
|
1543
|
+
margin: 0;
|
|
1544
|
+
padding: 0;
|
|
1545
|
+
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
|
+
line-height: 1.4;
|
|
1625
|
+
}
|
|
1626
|
+
|
|
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;
|
|
1671
|
+
}
|
|
1672
|
+
|
|
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;
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
/* Webkit scrollbar styling */
|
|
1683
|
+
.zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar {
|
|
1684
|
+
width: 6px;
|
|
1685
|
+
}
|
|
1686
|
+
|
|
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);
|
|
1698
|
+
}
|
|
1699
|
+
|
|
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 {
|
|
1706
|
+
background: transparent;
|
|
1707
|
+
}
|
|
1708
|
+
|
|
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
|
+
@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 {
|
|
1740
|
+
font-size: 12px;
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
.zenit-popup-row.zenit-popup-description {
|
|
1744
|
+
margin: 0 -12px;
|
|
1745
|
+
padding: 10px 12px;
|
|
1746
|
+
}
|
|
1747
|
+
|
|
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;
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
/* ===== Map tooltip styling ===== */
|
|
1765
|
+
.zenit-map-tooltip {
|
|
1766
|
+
background-color: rgba(31, 41, 55, 0.95);
|
|
1767
|
+
border: none;
|
|
1768
|
+
border-radius: 6px;
|
|
1769
|
+
color: #ffffff;
|
|
1770
|
+
font-size: 12px;
|
|
1771
|
+
font-weight: 500;
|
|
1772
|
+
padding: 6px 10px;
|
|
1773
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1776
|
+
.zenit-map-tooltip::before {
|
|
1777
|
+
border-top-color: rgba(31, 41, 55, 0.95);
|
|
1778
|
+
}
|
|
1779
|
+
`;
|
|
1780
|
+
function ensurePopupStyles() {
|
|
1781
|
+
if (typeof document === "undefined") return;
|
|
1782
|
+
if (document.getElementById(POPUP_STYLE_ID)) return;
|
|
1783
|
+
const styleTag = document.createElement("style");
|
|
1784
|
+
styleTag.id = POPUP_STYLE_ID;
|
|
1785
|
+
styleTag.textContent = ZENIT_LEAFLET_POPUP_STYLES;
|
|
1786
|
+
document.head.appendChild(styleTag);
|
|
1787
|
+
}
|
|
1788
|
+
function getPopupDimensions() {
|
|
1789
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
1790
|
+
return DESKTOP_POPUP_DIMENSIONS;
|
|
1791
|
+
}
|
|
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;
|
|
1804
|
+
}
|
|
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]);
|
|
1812
|
+
}
|
|
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);
|
|
1820
|
+
}
|
|
1821
|
+
function renderPopupValue(value) {
|
|
1822
|
+
if (value === null || value === void 0) {
|
|
1823
|
+
return '<span class="zenit-popup-empty">Sin datos</span>';
|
|
1824
|
+
}
|
|
1825
|
+
if (typeof value === "object") {
|
|
1826
|
+
const json = safeJsonStringify(value);
|
|
1827
|
+
return `<pre class="zenit-popup-pre">${escapeHtml(json)}</pre>`;
|
|
1828
|
+
}
|
|
1829
|
+
return `<span>${escapeHtml(String(value))}</span>`;
|
|
1830
|
+
}
|
|
1831
|
+
function shouldIncludePopupEntry(key, value) {
|
|
1832
|
+
if (!key) return false;
|
|
1833
|
+
const normalized = key.trim().toLowerCase();
|
|
1834
|
+
if (!normalized) return false;
|
|
1835
|
+
if (normalized.startsWith("_")) return false;
|
|
1836
|
+
if (POPUP_EXCLUDED_KEYS.has(normalized)) return false;
|
|
1837
|
+
if (value === null || value === void 0) return false;
|
|
1838
|
+
if (typeof value === "string" && !value.trim()) return false;
|
|
1839
|
+
return true;
|
|
1840
|
+
}
|
|
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
|
+
function createPopupContent(properties) {
|
|
1849
|
+
const entries = Object.entries(properties).filter(
|
|
1850
|
+
([key, value]) => shouldIncludePopupEntry(key, value)
|
|
1851
|
+
);
|
|
1852
|
+
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
|
+
`;
|
|
1868
|
+
}
|
|
1869
|
+
rowsHtml += otherEntries.map(([key, value]) => {
|
|
1870
|
+
const label = escapeHtml(formatLabel(key));
|
|
1871
|
+
const valueHtml = renderPopupValue(value);
|
|
1872
|
+
return `
|
|
1873
|
+
<div class="zenit-popup-row">
|
|
1874
|
+
<div class="zenit-popup-label">${label}</div>
|
|
1875
|
+
<div class="zenit-popup-value">${valueHtml}</div>
|
|
1876
|
+
</div>
|
|
1877
|
+
`;
|
|
1878
|
+
}).join("");
|
|
1879
|
+
return `<div class="zenit-popup-card">${rowsHtml}</div>`;
|
|
1880
|
+
}
|
|
1521
1881
|
function withAlpha(color, alpha) {
|
|
1522
1882
|
const trimmed = color.trim();
|
|
1523
1883
|
if (trimmed.startsWith("#")) {
|
|
@@ -1586,40 +1946,39 @@ function getFeatureStyleOverrides(feature) {
|
|
|
1586
1946
|
function buildFeaturePopupHtml(feature) {
|
|
1587
1947
|
const properties = feature?.properties;
|
|
1588
1948
|
if (!properties) return null;
|
|
1589
|
-
const
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
const
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
if (
|
|
1615
|
-
const
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
return `<div>${parts.join("")}</div>`;
|
|
1949
|
+
const rendered = createPopupContent(properties);
|
|
1950
|
+
return rendered ? rendered : null;
|
|
1951
|
+
}
|
|
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
|
+
function pickIntersectFeature(baseFeature, candidates) {
|
|
1972
|
+
if (!Array.isArray(candidates) || candidates.length === 0) return null;
|
|
1973
|
+
const baseId = baseFeature?.id;
|
|
1974
|
+
if (baseId !== void 0 && baseId !== null) {
|
|
1975
|
+
const matchById = candidates.find((candidate) => candidate?.id === baseId);
|
|
1976
|
+
if (matchById) return matchById;
|
|
1977
|
+
}
|
|
1978
|
+
const matchWithDescription = candidates.find(
|
|
1979
|
+
(candidate) => extractDescriptionValue(candidate?.properties)
|
|
1980
|
+
);
|
|
1981
|
+
return matchWithDescription ?? candidates[0];
|
|
1623
1982
|
}
|
|
1624
1983
|
function normalizeCenterTuple(center) {
|
|
1625
1984
|
if (!center) return null;
|
|
@@ -1740,6 +2099,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
1740
2099
|
const [loadingMap, setLoadingMap] = (0, import_react.useState)(false);
|
|
1741
2100
|
const [mapError, setMapError] = (0, import_react.useState)(null);
|
|
1742
2101
|
const [mapInstance, setMapInstance] = (0, import_react.useState)(null);
|
|
2102
|
+
const [panesReady, setPanesReady] = (0, import_react.useState)(false);
|
|
1743
2103
|
const [currentZoom, setCurrentZoom] = (0, import_react.useState)(initialZoom ?? DEFAULT_ZOOM);
|
|
1744
2104
|
const [isMobile, setIsMobile] = (0, import_react.useState)(() => {
|
|
1745
2105
|
if (typeof window === "undefined") return false;
|
|
@@ -1764,6 +2124,11 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
1764
2124
|
}
|
|
1765
2125
|
return;
|
|
1766
2126
|
}, []);
|
|
2127
|
+
(0, import_react.useEffect)(() => {
|
|
2128
|
+
if (featureInfoMode === "popup") {
|
|
2129
|
+
ensurePopupStyles();
|
|
2130
|
+
}
|
|
2131
|
+
}, [featureInfoMode]);
|
|
1767
2132
|
const layerStyleIndex = (0, import_react.useMemo)(() => {
|
|
1768
2133
|
const index = /* @__PURE__ */ new Map();
|
|
1769
2134
|
(map?.mapLayers ?? []).forEach((entry) => {
|
|
@@ -2054,16 +2419,23 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
2054
2419
|
(targetMap, targetLayers) => {
|
|
2055
2420
|
const baseZIndex = 400;
|
|
2056
2421
|
targetLayers.forEach((layer) => {
|
|
2057
|
-
const paneName = `zenit-layer-${layer.layerId}`;
|
|
2058
|
-
const pane = targetMap.getPane(paneName) ?? targetMap.createPane(paneName);
|
|
2059
2422
|
const order = Number.isFinite(layer.displayOrder) ? layer.displayOrder : 0;
|
|
2060
|
-
|
|
2423
|
+
const fillPaneName = `zenit-layer-${layer.layerId}-fill`;
|
|
2424
|
+
const pointPaneName = `zenit-layer-${layer.layerId}-points`;
|
|
2425
|
+
const labelPaneName = `zenit-layer-${layer.layerId}-labels`;
|
|
2426
|
+
const fillPane = targetMap.getPane(fillPaneName) ?? targetMap.createPane(fillPaneName);
|
|
2427
|
+
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);
|
|
2061
2432
|
});
|
|
2062
2433
|
},
|
|
2063
2434
|
[]
|
|
2064
2435
|
);
|
|
2065
2436
|
const handleMapReady = (0, import_react.useCallback)(
|
|
2066
2437
|
(instance) => {
|
|
2438
|
+
setPanesReady(false);
|
|
2067
2439
|
setMapInstance(instance);
|
|
2068
2440
|
onMapReady?.(instance);
|
|
2069
2441
|
},
|
|
@@ -2071,6 +2443,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
2071
2443
|
);
|
|
2072
2444
|
(0, import_react.useEffect)(() => {
|
|
2073
2445
|
if (!mapInstance) {
|
|
2446
|
+
setPanesReady(false);
|
|
2074
2447
|
return;
|
|
2075
2448
|
}
|
|
2076
2449
|
if (orderedLayers.length === 0) {
|
|
@@ -2081,6 +2454,11 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
2081
2454
|
displayOrder: layer.displayOrder
|
|
2082
2455
|
}));
|
|
2083
2456
|
ensureLayerPanes(mapInstance, layerTargets);
|
|
2457
|
+
const first = layerTargets[0];
|
|
2458
|
+
const testPane = mapInstance.getPane(`zenit-layer-${first.layerId}-labels`);
|
|
2459
|
+
if (testPane) {
|
|
2460
|
+
setPanesReady(true);
|
|
2461
|
+
}
|
|
2084
2462
|
}, [mapInstance, orderedLayers, ensureLayerPanes]);
|
|
2085
2463
|
const overlayOnEachFeature = (0, import_react.useMemo)(() => {
|
|
2086
2464
|
return (feature, layer) => {
|
|
@@ -2098,7 +2476,17 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
2098
2476
|
if (featureInfoMode === "popup") {
|
|
2099
2477
|
const content = buildFeaturePopupHtml(feature);
|
|
2100
2478
|
if (content) {
|
|
2101
|
-
|
|
2479
|
+
const { maxWidth, minWidth, maxHeight } = getPopupDimensions();
|
|
2480
|
+
layer.bindPopup(content, {
|
|
2481
|
+
maxWidth,
|
|
2482
|
+
minWidth,
|
|
2483
|
+
maxHeight,
|
|
2484
|
+
className: "zenit-leaflet-popup",
|
|
2485
|
+
autoPan: true,
|
|
2486
|
+
closeButton: true,
|
|
2487
|
+
keepInView: true,
|
|
2488
|
+
offset: import_leaflet.default.point(0, -24)
|
|
2489
|
+
});
|
|
2102
2490
|
}
|
|
2103
2491
|
}
|
|
2104
2492
|
if (isPointFeature && layer.bindTooltip) {
|
|
@@ -2109,7 +2497,37 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
2109
2497
|
className: "zenit-map-tooltip"
|
|
2110
2498
|
});
|
|
2111
2499
|
}
|
|
2112
|
-
layer.on("click", () =>
|
|
2500
|
+
layer.on("click", () => {
|
|
2501
|
+
if (featureInfoMode === "popup" && client && layerId !== void 0 && !extractDescriptionValue(feature?.properties) && feature?.geometry) {
|
|
2502
|
+
const trackedFeature = feature;
|
|
2503
|
+
if (!trackedFeature.__zenit_popup_loaded) {
|
|
2504
|
+
trackedFeature.__zenit_popup_loaded = true;
|
|
2505
|
+
client.layers.getLayerGeoJsonIntersect({
|
|
2506
|
+
id: layerId,
|
|
2507
|
+
geometry: feature.geometry
|
|
2508
|
+
}).then((response) => {
|
|
2509
|
+
const candidates = response.data?.features ?? [];
|
|
2510
|
+
const resolved = pickIntersectFeature(feature, candidates);
|
|
2511
|
+
if (!resolved?.properties) return;
|
|
2512
|
+
const mergedProperties = {
|
|
2513
|
+
...trackedFeature.properties ?? {},
|
|
2514
|
+
...resolved.properties
|
|
2515
|
+
};
|
|
2516
|
+
trackedFeature.properties = mergedProperties;
|
|
2517
|
+
const updatedHtml = buildFeaturePopupHtml({
|
|
2518
|
+
...feature,
|
|
2519
|
+
properties: mergedProperties
|
|
2520
|
+
});
|
|
2521
|
+
if (updatedHtml && layer.setPopupContent) {
|
|
2522
|
+
layer.setPopupContent(updatedHtml);
|
|
2523
|
+
}
|
|
2524
|
+
}).catch(() => {
|
|
2525
|
+
trackedFeature.__zenit_popup_loaded = false;
|
|
2526
|
+
});
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
onFeatureClick?.(feature, layerId);
|
|
2530
|
+
});
|
|
2113
2531
|
layer.on("mouseover", () => {
|
|
2114
2532
|
if (layer instanceof import_leaflet.default.Path && originalStyle) {
|
|
2115
2533
|
layer.setStyle({
|
|
@@ -2133,7 +2551,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
2133
2551
|
}
|
|
2134
2552
|
});
|
|
2135
2553
|
};
|
|
2136
|
-
}, [featureInfoMode, onFeatureClick, onFeatureHover]);
|
|
2554
|
+
}, [client, featureInfoMode, onFeatureClick, onFeatureHover]);
|
|
2137
2555
|
const buildLayerStyle = (layerId, baseOpacity, feature, layerType) => {
|
|
2138
2556
|
const style = resolveLayerStyle(layerId);
|
|
2139
2557
|
const featureStyleOverrides = getFeatureStyleOverrides(feature);
|
|
@@ -2314,22 +2732,50 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
2314
2732
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ZoomBasedOpacityHandler, { onZoomChange: handleZoomChange }),
|
|
2315
2733
|
orderedLayers.map((layerState) => {
|
|
2316
2734
|
const baseOpacity = layerState.effective?.baseOpacity ?? layerState.effective?.opacity ?? 1;
|
|
2317
|
-
const
|
|
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`;
|
|
2318
2738
|
const layerType = layerState.layer?.layerType ?? layerState.mapLayer.layerType ?? void 0;
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
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,
|
|
2747
|
+
{
|
|
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
|
|
2752
|
+
}
|
|
2753
|
+
),
|
|
2754
|
+
pointsData && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2755
|
+
import_react_leaflet.GeoJSON,
|
|
2756
|
+
{
|
|
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
|
|
2764
|
+
}
|
|
2765
|
+
),
|
|
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,
|
|
2770
|
+
{
|
|
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());
|
|
2333
2779
|
}),
|
|
2334
2780
|
overlayGeojson && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2335
2781
|
import_react_leaflet.GeoJSON,
|
|
@@ -2339,16 +2785,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
2339
2785
|
onEachFeature: overlayOnEachFeature
|
|
2340
2786
|
},
|
|
2341
2787
|
"zenit-overlay-geojson"
|
|
2342
|
-
)
|
|
2343
|
-
labelMarkers.map((marker) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2344
|
-
import_react_leaflet.Marker,
|
|
2345
|
-
{
|
|
2346
|
-
position: marker.position,
|
|
2347
|
-
icon: buildLabelIcon(marker.label, marker.opacity, marker.color),
|
|
2348
|
-
interactive: false
|
|
2349
|
-
},
|
|
2350
|
-
marker.key
|
|
2351
|
-
))
|
|
2788
|
+
)
|
|
2352
2789
|
]
|
|
2353
2790
|
},
|
|
2354
2791
|
String(mapId)
|
|
@@ -3630,9 +4067,19 @@ var FloatingChatBox = ({
|
|
|
3630
4067
|
getAccessToken,
|
|
3631
4068
|
onActionClick,
|
|
3632
4069
|
onOpenChange,
|
|
3633
|
-
hideButton
|
|
4070
|
+
hideButton,
|
|
4071
|
+
open: openProp
|
|
3634
4072
|
}) => {
|
|
3635
|
-
const
|
|
4073
|
+
const isControlled = openProp !== void 0;
|
|
4074
|
+
const [internalOpen, setInternalOpen] = (0, import_react4.useState)(false);
|
|
4075
|
+
const open = isControlled ? openProp : internalOpen;
|
|
4076
|
+
const setOpen = (0, import_react4.useCallback)((value) => {
|
|
4077
|
+
const newValue = typeof value === "function" ? value(open) : value;
|
|
4078
|
+
if (!isControlled) {
|
|
4079
|
+
setInternalOpen(newValue);
|
|
4080
|
+
}
|
|
4081
|
+
onOpenChange?.(newValue);
|
|
4082
|
+
}, [isControlled, open, onOpenChange]);
|
|
3636
4083
|
const [expanded, setExpanded] = (0, import_react4.useState)(false);
|
|
3637
4084
|
const [messages, setMessages] = (0, import_react4.useState)([]);
|
|
3638
4085
|
const [inputValue, setInputValue] = (0, import_react4.useState)("");
|
|
@@ -3649,9 +4096,6 @@ var FloatingChatBox = ({
|
|
|
3649
4096
|
}, [accessToken, baseUrl, getAccessToken]);
|
|
3650
4097
|
const { sendMessage: sendMessage2, isStreaming, streamingText, completeResponse } = useSendMessageStream(chatConfig);
|
|
3651
4098
|
const canSend = Boolean(mapId) && Boolean(baseUrl) && inputValue.trim().length > 0 && !isStreaming;
|
|
3652
|
-
(0, import_react4.useEffect)(() => {
|
|
3653
|
-
onOpenChange?.(open);
|
|
3654
|
-
}, [open, onOpenChange]);
|
|
3655
4099
|
(0, import_react4.useEffect)(() => {
|
|
3656
4100
|
if (open && isMobile) {
|
|
3657
4101
|
setExpanded(true);
|
|
@@ -3804,6 +4248,13 @@ var FloatingChatBox = ({
|
|
|
3804
4248
|
] }, index)) })
|
|
3805
4249
|
] });
|
|
3806
4250
|
};
|
|
4251
|
+
const handleActionClick = (0, import_react4.useCallback)((action) => {
|
|
4252
|
+
if (isStreaming) return;
|
|
4253
|
+
setOpen(false);
|
|
4254
|
+
requestAnimationFrame(() => {
|
|
4255
|
+
onActionClick?.(action);
|
|
4256
|
+
});
|
|
4257
|
+
}, [isStreaming, setOpen, onActionClick]);
|
|
3807
4258
|
const renderActions = (response) => {
|
|
3808
4259
|
if (!response?.suggestedActions?.length) return null;
|
|
3809
4260
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles.actionsSection, children: [
|
|
@@ -3817,7 +4268,7 @@ var FloatingChatBox = ({
|
|
|
3817
4268
|
opacity: isStreaming ? 0.5 : 1,
|
|
3818
4269
|
cursor: isStreaming ? "not-allowed" : "pointer"
|
|
3819
4270
|
},
|
|
3820
|
-
onClick: () =>
|
|
4271
|
+
onClick: () => handleActionClick(action),
|
|
3821
4272
|
disabled: isStreaming,
|
|
3822
4273
|
onMouseEnter: (e) => {
|
|
3823
4274
|
if (!isStreaming) {
|