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/react/index.js
CHANGED
|
@@ -58,7 +58,7 @@ __export(react_exports, {
|
|
|
58
58
|
module.exports = __toCommonJS(react_exports);
|
|
59
59
|
|
|
60
60
|
// src/react/ZenitMap.tsx
|
|
61
|
-
var import_react = require("react");
|
|
61
|
+
var import_react = __toESM(require("react"));
|
|
62
62
|
var import_react_leaflet = require("react-leaflet");
|
|
63
63
|
var import_leaflet = __toESM(require("leaflet"));
|
|
64
64
|
|
|
@@ -344,6 +344,366 @@ function getFeatureLayerId(feature) {
|
|
|
344
344
|
function escapeHtml(value) {
|
|
345
345
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
346
346
|
}
|
|
347
|
+
var DESCRIPTION_KEYS = /* @__PURE__ */ new Set(["descripcion", "description"]);
|
|
348
|
+
var POPUP_EXCLUDED_KEYS = /* @__PURE__ */ new Set(["geom", "geometry"]);
|
|
349
|
+
var POPUP_STYLE_ID = "zenit-leaflet-popup-styles";
|
|
350
|
+
var DESKTOP_POPUP_DIMENSIONS = { maxWidth: 350, minWidth: 280, maxHeight: 480 };
|
|
351
|
+
var MOBILE_POPUP_DIMENSIONS = { maxWidth: 280, minWidth: 240, maxHeight: 380 };
|
|
352
|
+
var ZENIT_LEAFLET_POPUP_STYLES = `
|
|
353
|
+
/* ===== Zenit Leaflet Popup - Modern Professional Styling ===== */
|
|
354
|
+
|
|
355
|
+
/* Main popup wrapper */
|
|
356
|
+
.zenit-leaflet-popup .leaflet-popup-content-wrapper {
|
|
357
|
+
border-radius: 12px;
|
|
358
|
+
box-shadow:
|
|
359
|
+
0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
|
360
|
+
0 2px 4px -2px rgba(0, 0, 0, 0.1),
|
|
361
|
+
0 0 0 1px rgba(0, 0, 0, 0.05);
|
|
362
|
+
padding: 0;
|
|
363
|
+
background: #ffffff;
|
|
364
|
+
overflow: hidden;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/* Content area with scroll support */
|
|
368
|
+
.zenit-leaflet-popup .leaflet-popup-content {
|
|
369
|
+
margin: 0;
|
|
370
|
+
padding: 0;
|
|
371
|
+
font-size: 13px;
|
|
372
|
+
line-height: 1.5;
|
|
373
|
+
color: #374151;
|
|
374
|
+
min-width: 100%;
|
|
375
|
+
overflow-y: auto;
|
|
376
|
+
overflow-x: hidden;
|
|
377
|
+
scrollbar-width: thin;
|
|
378
|
+
scrollbar-color: rgba(156, 163, 175, 0.5) transparent;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/* Popup tip/arrow shadow */
|
|
382
|
+
.zenit-leaflet-popup .leaflet-popup-tip-container {
|
|
383
|
+
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
.zenit-leaflet-popup .leaflet-popup-tip {
|
|
387
|
+
background: #ffffff;
|
|
388
|
+
box-shadow: none;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/* Close button styling */
|
|
392
|
+
.zenit-leaflet-popup .leaflet-popup-close-button {
|
|
393
|
+
color: #9ca3af;
|
|
394
|
+
font-size: 18px;
|
|
395
|
+
font-weight: 400;
|
|
396
|
+
width: 28px;
|
|
397
|
+
height: 28px;
|
|
398
|
+
padding: 0;
|
|
399
|
+
margin: 8px 8px 0 0;
|
|
400
|
+
display: flex;
|
|
401
|
+
align-items: center;
|
|
402
|
+
justify-content: center;
|
|
403
|
+
border-radius: 6px;
|
|
404
|
+
transition: all 0.15s ease;
|
|
405
|
+
z-index: 10;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.zenit-leaflet-popup .leaflet-popup-close-button:hover {
|
|
409
|
+
color: #374151;
|
|
410
|
+
background-color: #f3f4f6;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.zenit-leaflet-popup .leaflet-popup-close-button:active {
|
|
414
|
+
background-color: #e5e7eb;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/* Main card container */
|
|
418
|
+
.zenit-popup-card {
|
|
419
|
+
display: flex;
|
|
420
|
+
flex-direction: column;
|
|
421
|
+
gap: 0;
|
|
422
|
+
padding: 16px;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/* Individual row styling with subtle separator */
|
|
426
|
+
.zenit-popup-row {
|
|
427
|
+
display: flex;
|
|
428
|
+
flex-direction: column;
|
|
429
|
+
gap: 2px;
|
|
430
|
+
padding: 10px 0;
|
|
431
|
+
border-bottom: 1px solid #f3f4f6;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.zenit-popup-row:first-child {
|
|
435
|
+
padding-top: 0;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.zenit-popup-row:last-child {
|
|
439
|
+
border-bottom: none;
|
|
440
|
+
padding-bottom: 0;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/* Label styling - small, gray, uppercase */
|
|
444
|
+
.zenit-popup-label {
|
|
445
|
+
font-size: 10px;
|
|
446
|
+
font-weight: 500;
|
|
447
|
+
color: #9ca3af;
|
|
448
|
+
text-transform: uppercase;
|
|
449
|
+
letter-spacing: 0.05em;
|
|
450
|
+
line-height: 1.4;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/* Value styling - darker, readable */
|
|
454
|
+
.zenit-popup-value {
|
|
455
|
+
font-size: 13px;
|
|
456
|
+
font-weight: 400;
|
|
457
|
+
color: #1f2937;
|
|
458
|
+
overflow-wrap: break-word;
|
|
459
|
+
word-break: break-word;
|
|
460
|
+
line-height: 1.5;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/* Special styling for description field */
|
|
464
|
+
.zenit-popup-row.zenit-popup-description {
|
|
465
|
+
background-color: #f9fafb;
|
|
466
|
+
margin: 0 -16px;
|
|
467
|
+
padding: 12px 16px;
|
|
468
|
+
border-bottom: 1px solid #e5e7eb;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
.zenit-popup-row.zenit-popup-description:first-child {
|
|
472
|
+
margin-top: 0;
|
|
473
|
+
border-radius: 0;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value {
|
|
477
|
+
font-size: 13px;
|
|
478
|
+
line-height: 1.6;
|
|
479
|
+
color: #374151;
|
|
480
|
+
max-height: 150px;
|
|
481
|
+
overflow-y: auto;
|
|
482
|
+
padding-right: 4px;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/* Preformatted text (JSON objects) */
|
|
486
|
+
.zenit-popup-pre {
|
|
487
|
+
margin: 0;
|
|
488
|
+
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
|
|
489
|
+
font-size: 11px;
|
|
490
|
+
white-space: pre-wrap;
|
|
491
|
+
word-break: break-word;
|
|
492
|
+
color: #4b5563;
|
|
493
|
+
background-color: #f9fafb;
|
|
494
|
+
padding: 8px;
|
|
495
|
+
border-radius: 6px;
|
|
496
|
+
border: 1px solid #e5e7eb;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/* Empty state styling */
|
|
500
|
+
.zenit-popup-empty {
|
|
501
|
+
font-size: 13px;
|
|
502
|
+
color: #9ca3af;
|
|
503
|
+
font-style: italic;
|
|
504
|
+
text-align: center;
|
|
505
|
+
padding: 20px 0;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/* Webkit scrollbar styling */
|
|
509
|
+
.zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar {
|
|
510
|
+
width: 6px;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
.zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar-track {
|
|
514
|
+
background: transparent;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
.zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar-thumb {
|
|
518
|
+
background-color: rgba(156, 163, 175, 0.4);
|
|
519
|
+
border-radius: 3px;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
.zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar-thumb:hover {
|
|
523
|
+
background-color: rgba(107, 114, 128, 0.6);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/* Scrollbar for description field */
|
|
527
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value::-webkit-scrollbar {
|
|
528
|
+
width: 4px;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value::-webkit-scrollbar-track {
|
|
532
|
+
background: transparent;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value::-webkit-scrollbar-thumb {
|
|
536
|
+
background-color: rgba(156, 163, 175, 0.4);
|
|
537
|
+
border-radius: 2px;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/* ===== Responsive: Mobile (<640px) ===== */
|
|
541
|
+
@media (max-width: 640px) {
|
|
542
|
+
.zenit-leaflet-popup .leaflet-popup-content-wrapper {
|
|
543
|
+
border-radius: 10px;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
.zenit-leaflet-popup .leaflet-popup-close-button {
|
|
547
|
+
width: 26px;
|
|
548
|
+
height: 26px;
|
|
549
|
+
font-size: 16px;
|
|
550
|
+
margin: 6px 6px 0 0;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
.zenit-popup-card {
|
|
554
|
+
padding: 12px;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
.zenit-popup-row {
|
|
558
|
+
padding: 8px 0;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.zenit-popup-label {
|
|
562
|
+
font-size: 9px;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
.zenit-popup-value {
|
|
566
|
+
font-size: 12px;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
.zenit-popup-row.zenit-popup-description {
|
|
570
|
+
margin: 0 -12px;
|
|
571
|
+
padding: 10px 12px;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value {
|
|
575
|
+
font-size: 12px;
|
|
576
|
+
max-height: 120px;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
.zenit-popup-pre {
|
|
580
|
+
font-size: 10px;
|
|
581
|
+
padding: 6px;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
.zenit-popup-empty {
|
|
585
|
+
font-size: 12px;
|
|
586
|
+
padding: 16px 0;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/* ===== Map tooltip styling ===== */
|
|
591
|
+
.zenit-map-tooltip {
|
|
592
|
+
background-color: rgba(31, 41, 55, 0.95);
|
|
593
|
+
border: none;
|
|
594
|
+
border-radius: 6px;
|
|
595
|
+
color: #ffffff;
|
|
596
|
+
font-size: 12px;
|
|
597
|
+
font-weight: 500;
|
|
598
|
+
padding: 6px 10px;
|
|
599
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
.zenit-map-tooltip::before {
|
|
603
|
+
border-top-color: rgba(31, 41, 55, 0.95);
|
|
604
|
+
}
|
|
605
|
+
`;
|
|
606
|
+
function ensurePopupStyles() {
|
|
607
|
+
if (typeof document === "undefined") return;
|
|
608
|
+
if (document.getElementById(POPUP_STYLE_ID)) return;
|
|
609
|
+
const styleTag = document.createElement("style");
|
|
610
|
+
styleTag.id = POPUP_STYLE_ID;
|
|
611
|
+
styleTag.textContent = ZENIT_LEAFLET_POPUP_STYLES;
|
|
612
|
+
document.head.appendChild(styleTag);
|
|
613
|
+
}
|
|
614
|
+
function getPopupDimensions() {
|
|
615
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
616
|
+
return DESKTOP_POPUP_DIMENSIONS;
|
|
617
|
+
}
|
|
618
|
+
return window.matchMedia("(max-width: 640px)").matches ? MOBILE_POPUP_DIMENSIONS : DESKTOP_POPUP_DIMENSIONS;
|
|
619
|
+
}
|
|
620
|
+
function normalizeDescriptionValue(value) {
|
|
621
|
+
if (value === void 0 || value === null) return null;
|
|
622
|
+
if (typeof value === "string") {
|
|
623
|
+
const trimmed = value.trim();
|
|
624
|
+
return trimmed ? trimmed : null;
|
|
625
|
+
}
|
|
626
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
627
|
+
return String(value);
|
|
628
|
+
}
|
|
629
|
+
return null;
|
|
630
|
+
}
|
|
631
|
+
function extractDescriptionValue(properties) {
|
|
632
|
+
if (!properties) return null;
|
|
633
|
+
const matches = Object.entries(properties).find(
|
|
634
|
+
([key]) => DESCRIPTION_KEYS.has(key.toLowerCase())
|
|
635
|
+
);
|
|
636
|
+
if (!matches) return null;
|
|
637
|
+
return normalizeDescriptionValue(matches[1]);
|
|
638
|
+
}
|
|
639
|
+
function safeJsonStringify(value) {
|
|
640
|
+
try {
|
|
641
|
+
const json = JSON.stringify(value, null, 2);
|
|
642
|
+
if (json !== void 0) return json;
|
|
643
|
+
} catch {
|
|
644
|
+
}
|
|
645
|
+
return String(value);
|
|
646
|
+
}
|
|
647
|
+
function renderPopupValue(value) {
|
|
648
|
+
if (value === null || value === void 0) {
|
|
649
|
+
return '<span class="zenit-popup-empty">Sin datos</span>';
|
|
650
|
+
}
|
|
651
|
+
if (typeof value === "object") {
|
|
652
|
+
const json = safeJsonStringify(value);
|
|
653
|
+
return `<pre class="zenit-popup-pre">${escapeHtml(json)}</pre>`;
|
|
654
|
+
}
|
|
655
|
+
return `<span>${escapeHtml(String(value))}</span>`;
|
|
656
|
+
}
|
|
657
|
+
function shouldIncludePopupEntry(key, value) {
|
|
658
|
+
if (!key) return false;
|
|
659
|
+
const normalized = key.trim().toLowerCase();
|
|
660
|
+
if (!normalized) return false;
|
|
661
|
+
if (normalized.startsWith("_")) return false;
|
|
662
|
+
if (POPUP_EXCLUDED_KEYS.has(normalized)) return false;
|
|
663
|
+
if (value === null || value === void 0) return false;
|
|
664
|
+
if (typeof value === "string" && !value.trim()) return false;
|
|
665
|
+
return true;
|
|
666
|
+
}
|
|
667
|
+
function isDescriptionKey(key) {
|
|
668
|
+
const normalized = key.trim().toLowerCase();
|
|
669
|
+
return DESCRIPTION_KEYS.has(normalized);
|
|
670
|
+
}
|
|
671
|
+
function formatLabel(key) {
|
|
672
|
+
return key.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").trim();
|
|
673
|
+
}
|
|
674
|
+
function createPopupContent(properties) {
|
|
675
|
+
const entries = Object.entries(properties).filter(
|
|
676
|
+
([key, value]) => shouldIncludePopupEntry(key, value)
|
|
677
|
+
);
|
|
678
|
+
if (entries.length === 0) {
|
|
679
|
+
return `<div class="zenit-popup-card"><div class="zenit-popup-empty">Sin datos disponibles</div></div>`;
|
|
680
|
+
}
|
|
681
|
+
const descriptionEntry = entries.find(([key]) => isDescriptionKey(key));
|
|
682
|
+
const otherEntries = entries.filter(([key]) => !isDescriptionKey(key));
|
|
683
|
+
let rowsHtml = "";
|
|
684
|
+
if (descriptionEntry) {
|
|
685
|
+
const [key, value] = descriptionEntry;
|
|
686
|
+
const label = escapeHtml(formatLabel(key));
|
|
687
|
+
const valueHtml = renderPopupValue(value);
|
|
688
|
+
rowsHtml += `
|
|
689
|
+
<div class="zenit-popup-row zenit-popup-description">
|
|
690
|
+
<div class="zenit-popup-label">${label}</div>
|
|
691
|
+
<div class="zenit-popup-value">${valueHtml}</div>
|
|
692
|
+
</div>
|
|
693
|
+
`;
|
|
694
|
+
}
|
|
695
|
+
rowsHtml += otherEntries.map(([key, value]) => {
|
|
696
|
+
const label = escapeHtml(formatLabel(key));
|
|
697
|
+
const valueHtml = renderPopupValue(value);
|
|
698
|
+
return `
|
|
699
|
+
<div class="zenit-popup-row">
|
|
700
|
+
<div class="zenit-popup-label">${label}</div>
|
|
701
|
+
<div class="zenit-popup-value">${valueHtml}</div>
|
|
702
|
+
</div>
|
|
703
|
+
`;
|
|
704
|
+
}).join("");
|
|
705
|
+
return `<div class="zenit-popup-card">${rowsHtml}</div>`;
|
|
706
|
+
}
|
|
347
707
|
function withAlpha(color, alpha) {
|
|
348
708
|
const trimmed = color.trim();
|
|
349
709
|
if (trimmed.startsWith("#")) {
|
|
@@ -412,40 +772,39 @@ function getFeatureStyleOverrides(feature) {
|
|
|
412
772
|
function buildFeaturePopupHtml(feature) {
|
|
413
773
|
const properties = feature?.properties;
|
|
414
774
|
if (!properties) return null;
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
const
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
if (
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
const val = escapeHtml(String(value));
|
|
444
|
-
return `<div><strong>${label}:</strong> ${val}</div>`;
|
|
445
|
-
}).join("");
|
|
446
|
-
parts.push(`<div style="font-size:12px;line-height:1.4;">${rows}</div>`);
|
|
775
|
+
const rendered = createPopupContent(properties);
|
|
776
|
+
return rendered ? rendered : null;
|
|
777
|
+
}
|
|
778
|
+
var POINT_GEOMETRY_TYPES = /* @__PURE__ */ new Set(["Point", "MultiPoint"]);
|
|
779
|
+
function getGeometryType(feature) {
|
|
780
|
+
const t = feature?.geometry?.type;
|
|
781
|
+
return typeof t === "string" ? t : null;
|
|
782
|
+
}
|
|
783
|
+
function isPointGeometry(feature) {
|
|
784
|
+
const geometryType = getGeometryType(feature);
|
|
785
|
+
return geometryType !== null && POINT_GEOMETRY_TYPES.has(geometryType);
|
|
786
|
+
}
|
|
787
|
+
function isNonPointGeometry(feature) {
|
|
788
|
+
const geometryType = getGeometryType(feature);
|
|
789
|
+
return geometryType !== null && !POINT_GEOMETRY_TYPES.has(geometryType);
|
|
790
|
+
}
|
|
791
|
+
function buildFeatureCollection(features) {
|
|
792
|
+
return {
|
|
793
|
+
type: "FeatureCollection",
|
|
794
|
+
features
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
function pickIntersectFeature(baseFeature, candidates) {
|
|
798
|
+
if (!Array.isArray(candidates) || candidates.length === 0) return null;
|
|
799
|
+
const baseId = baseFeature?.id;
|
|
800
|
+
if (baseId !== void 0 && baseId !== null) {
|
|
801
|
+
const matchById = candidates.find((candidate) => candidate?.id === baseId);
|
|
802
|
+
if (matchById) return matchById;
|
|
447
803
|
}
|
|
448
|
-
|
|
804
|
+
const matchWithDescription = candidates.find(
|
|
805
|
+
(candidate) => extractDescriptionValue(candidate?.properties)
|
|
806
|
+
);
|
|
807
|
+
return matchWithDescription ?? candidates[0];
|
|
449
808
|
}
|
|
450
809
|
function normalizeCenterTuple(center) {
|
|
451
810
|
if (!center) return null;
|
|
@@ -566,6 +925,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
566
925
|
const [loadingMap, setLoadingMap] = (0, import_react.useState)(false);
|
|
567
926
|
const [mapError, setMapError] = (0, import_react.useState)(null);
|
|
568
927
|
const [mapInstance, setMapInstance] = (0, import_react.useState)(null);
|
|
928
|
+
const [panesReady, setPanesReady] = (0, import_react.useState)(false);
|
|
569
929
|
const [currentZoom, setCurrentZoom] = (0, import_react.useState)(initialZoom ?? DEFAULT_ZOOM);
|
|
570
930
|
const [isMobile, setIsMobile] = (0, import_react.useState)(() => {
|
|
571
931
|
if (typeof window === "undefined") return false;
|
|
@@ -590,6 +950,11 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
590
950
|
}
|
|
591
951
|
return;
|
|
592
952
|
}, []);
|
|
953
|
+
(0, import_react.useEffect)(() => {
|
|
954
|
+
if (featureInfoMode === "popup") {
|
|
955
|
+
ensurePopupStyles();
|
|
956
|
+
}
|
|
957
|
+
}, [featureInfoMode]);
|
|
593
958
|
const layerStyleIndex = (0, import_react.useMemo)(() => {
|
|
594
959
|
const index = /* @__PURE__ */ new Map();
|
|
595
960
|
(map?.mapLayers ?? []).forEach((entry) => {
|
|
@@ -880,16 +1245,23 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
880
1245
|
(targetMap, targetLayers) => {
|
|
881
1246
|
const baseZIndex = 400;
|
|
882
1247
|
targetLayers.forEach((layer) => {
|
|
883
|
-
const paneName = `zenit-layer-${layer.layerId}`;
|
|
884
|
-
const pane = targetMap.getPane(paneName) ?? targetMap.createPane(paneName);
|
|
885
1248
|
const order = Number.isFinite(layer.displayOrder) ? layer.displayOrder : 0;
|
|
886
|
-
|
|
1249
|
+
const fillPaneName = `zenit-layer-${layer.layerId}-fill`;
|
|
1250
|
+
const pointPaneName = `zenit-layer-${layer.layerId}-points`;
|
|
1251
|
+
const labelPaneName = `zenit-layer-${layer.layerId}-labels`;
|
|
1252
|
+
const fillPane = targetMap.getPane(fillPaneName) ?? targetMap.createPane(fillPaneName);
|
|
1253
|
+
const pointPane = targetMap.getPane(pointPaneName) ?? targetMap.createPane(pointPaneName);
|
|
1254
|
+
const labelPane = targetMap.getPane(labelPaneName) ?? targetMap.createPane(labelPaneName);
|
|
1255
|
+
fillPane.style.zIndex = String(baseZIndex + order);
|
|
1256
|
+
pointPane.style.zIndex = String(baseZIndex + order + 1e3);
|
|
1257
|
+
labelPane.style.zIndex = String(baseZIndex + order + 2e3);
|
|
887
1258
|
});
|
|
888
1259
|
},
|
|
889
1260
|
[]
|
|
890
1261
|
);
|
|
891
1262
|
const handleMapReady = (0, import_react.useCallback)(
|
|
892
1263
|
(instance) => {
|
|
1264
|
+
setPanesReady(false);
|
|
893
1265
|
setMapInstance(instance);
|
|
894
1266
|
onMapReady?.(instance);
|
|
895
1267
|
},
|
|
@@ -897,6 +1269,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
897
1269
|
);
|
|
898
1270
|
(0, import_react.useEffect)(() => {
|
|
899
1271
|
if (!mapInstance) {
|
|
1272
|
+
setPanesReady(false);
|
|
900
1273
|
return;
|
|
901
1274
|
}
|
|
902
1275
|
if (orderedLayers.length === 0) {
|
|
@@ -907,6 +1280,11 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
907
1280
|
displayOrder: layer.displayOrder
|
|
908
1281
|
}));
|
|
909
1282
|
ensureLayerPanes(mapInstance, layerTargets);
|
|
1283
|
+
const first = layerTargets[0];
|
|
1284
|
+
const testPane = mapInstance.getPane(`zenit-layer-${first.layerId}-labels`);
|
|
1285
|
+
if (testPane) {
|
|
1286
|
+
setPanesReady(true);
|
|
1287
|
+
}
|
|
910
1288
|
}, [mapInstance, orderedLayers, ensureLayerPanes]);
|
|
911
1289
|
const overlayOnEachFeature = (0, import_react.useMemo)(() => {
|
|
912
1290
|
return (feature, layer) => {
|
|
@@ -924,7 +1302,17 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
924
1302
|
if (featureInfoMode === "popup") {
|
|
925
1303
|
const content = buildFeaturePopupHtml(feature);
|
|
926
1304
|
if (content) {
|
|
927
|
-
|
|
1305
|
+
const { maxWidth, minWidth, maxHeight } = getPopupDimensions();
|
|
1306
|
+
layer.bindPopup(content, {
|
|
1307
|
+
maxWidth,
|
|
1308
|
+
minWidth,
|
|
1309
|
+
maxHeight,
|
|
1310
|
+
className: "zenit-leaflet-popup",
|
|
1311
|
+
autoPan: true,
|
|
1312
|
+
closeButton: true,
|
|
1313
|
+
keepInView: true,
|
|
1314
|
+
offset: import_leaflet.default.point(0, -24)
|
|
1315
|
+
});
|
|
928
1316
|
}
|
|
929
1317
|
}
|
|
930
1318
|
if (isPointFeature && layer.bindTooltip) {
|
|
@@ -935,7 +1323,37 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
935
1323
|
className: "zenit-map-tooltip"
|
|
936
1324
|
});
|
|
937
1325
|
}
|
|
938
|
-
layer.on("click", () =>
|
|
1326
|
+
layer.on("click", () => {
|
|
1327
|
+
if (featureInfoMode === "popup" && client && layerId !== void 0 && !extractDescriptionValue(feature?.properties) && feature?.geometry) {
|
|
1328
|
+
const trackedFeature = feature;
|
|
1329
|
+
if (!trackedFeature.__zenit_popup_loaded) {
|
|
1330
|
+
trackedFeature.__zenit_popup_loaded = true;
|
|
1331
|
+
client.layers.getLayerGeoJsonIntersect({
|
|
1332
|
+
id: layerId,
|
|
1333
|
+
geometry: feature.geometry
|
|
1334
|
+
}).then((response) => {
|
|
1335
|
+
const candidates = response.data?.features ?? [];
|
|
1336
|
+
const resolved = pickIntersectFeature(feature, candidates);
|
|
1337
|
+
if (!resolved?.properties) return;
|
|
1338
|
+
const mergedProperties = {
|
|
1339
|
+
...trackedFeature.properties ?? {},
|
|
1340
|
+
...resolved.properties
|
|
1341
|
+
};
|
|
1342
|
+
trackedFeature.properties = mergedProperties;
|
|
1343
|
+
const updatedHtml = buildFeaturePopupHtml({
|
|
1344
|
+
...feature,
|
|
1345
|
+
properties: mergedProperties
|
|
1346
|
+
});
|
|
1347
|
+
if (updatedHtml && layer.setPopupContent) {
|
|
1348
|
+
layer.setPopupContent(updatedHtml);
|
|
1349
|
+
}
|
|
1350
|
+
}).catch(() => {
|
|
1351
|
+
trackedFeature.__zenit_popup_loaded = false;
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
onFeatureClick?.(feature, layerId);
|
|
1356
|
+
});
|
|
939
1357
|
layer.on("mouseover", () => {
|
|
940
1358
|
if (layer instanceof import_leaflet.default.Path && originalStyle) {
|
|
941
1359
|
layer.setStyle({
|
|
@@ -959,7 +1377,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
959
1377
|
}
|
|
960
1378
|
});
|
|
961
1379
|
};
|
|
962
|
-
}, [featureInfoMode, onFeatureClick, onFeatureHover]);
|
|
1380
|
+
}, [client, featureInfoMode, onFeatureClick, onFeatureHover]);
|
|
963
1381
|
const buildLayerStyle = (layerId, baseOpacity, feature, layerType) => {
|
|
964
1382
|
const style = resolveLayerStyle(layerId);
|
|
965
1383
|
const featureStyleOverrides = getFeatureStyleOverrides(feature);
|
|
@@ -1140,22 +1558,50 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
1140
1558
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ZoomBasedOpacityHandler, { onZoomChange: handleZoomChange }),
|
|
1141
1559
|
orderedLayers.map((layerState) => {
|
|
1142
1560
|
const baseOpacity = layerState.effective?.baseOpacity ?? layerState.effective?.opacity ?? 1;
|
|
1143
|
-
const
|
|
1561
|
+
const fillPaneName = `zenit-layer-${layerState.mapLayer.layerId}-fill`;
|
|
1562
|
+
const pointsPaneName = `zenit-layer-${layerState.mapLayer.layerId}-points`;
|
|
1563
|
+
const labelPaneName = `zenit-layer-${layerState.mapLayer.layerId}-labels`;
|
|
1144
1564
|
const layerType = layerState.layer?.layerType ?? layerState.mapLayer.layerType ?? void 0;
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1565
|
+
const data = layerState.data?.features ?? [];
|
|
1566
|
+
const fillFeatures = data.filter(isNonPointGeometry);
|
|
1567
|
+
const pointFeatures = data.filter(isPointGeometry);
|
|
1568
|
+
const fillData = fillFeatures.length > 0 ? buildFeatureCollection(fillFeatures) : null;
|
|
1569
|
+
const pointsData = pointFeatures.length > 0 ? buildFeatureCollection(pointFeatures) : null;
|
|
1570
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [
|
|
1571
|
+
fillData && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1572
|
+
import_react_leaflet.GeoJSON,
|
|
1573
|
+
{
|
|
1574
|
+
data: fillData,
|
|
1575
|
+
pane: panesReady && mapInstance?.getPane(fillPaneName) ? fillPaneName : void 0,
|
|
1576
|
+
style: (feature) => buildLayerStyle(layerState.mapLayer.layerId, baseOpacity, feature, layerType),
|
|
1577
|
+
onEachFeature: overlayOnEachFeature
|
|
1578
|
+
}
|
|
1579
|
+
),
|
|
1580
|
+
pointsData && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1581
|
+
import_react_leaflet.GeoJSON,
|
|
1582
|
+
{
|
|
1583
|
+
data: pointsData,
|
|
1584
|
+
pane: panesReady && mapInstance?.getPane(pointsPaneName) ? pointsPaneName : void 0,
|
|
1585
|
+
pointToLayer: (feature, latlng) => import_leaflet.default.circleMarker(latlng, {
|
|
1586
|
+
radius: isMobile ? 8 : 6,
|
|
1587
|
+
...buildLayerStyle(layerState.mapLayer.layerId, baseOpacity, feature, layerType)
|
|
1588
|
+
}),
|
|
1589
|
+
onEachFeature: overlayOnEachFeature
|
|
1590
|
+
}
|
|
1591
|
+
),
|
|
1592
|
+
panesReady && mapInstance?.getPane(labelPaneName) ? labelMarkers.filter(
|
|
1593
|
+
(marker) => String(marker.layerId) === String(layerState.mapLayer.layerId)
|
|
1594
|
+
).map((marker) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1595
|
+
import_react_leaflet.Marker,
|
|
1596
|
+
{
|
|
1597
|
+
position: marker.position,
|
|
1598
|
+
icon: buildLabelIcon(marker.label, marker.opacity, marker.color),
|
|
1599
|
+
interactive: false,
|
|
1600
|
+
pane: labelPaneName
|
|
1601
|
+
},
|
|
1602
|
+
marker.key
|
|
1603
|
+
)) : null
|
|
1604
|
+
] }, layerState.mapLayer.layerId.toString());
|
|
1159
1605
|
}),
|
|
1160
1606
|
overlayGeojson && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1161
1607
|
import_react_leaflet.GeoJSON,
|
|
@@ -1165,16 +1611,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
1165
1611
|
onEachFeature: overlayOnEachFeature
|
|
1166
1612
|
},
|
|
1167
1613
|
"zenit-overlay-geojson"
|
|
1168
|
-
)
|
|
1169
|
-
labelMarkers.map((marker) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1170
|
-
import_react_leaflet.Marker,
|
|
1171
|
-
{
|
|
1172
|
-
position: marker.position,
|
|
1173
|
-
icon: buildLabelIcon(marker.label, marker.opacity, marker.color),
|
|
1174
|
-
interactive: false
|
|
1175
|
-
},
|
|
1176
|
-
marker.key
|
|
1177
|
-
))
|
|
1614
|
+
)
|
|
1178
1615
|
]
|
|
1179
1616
|
},
|
|
1180
1617
|
String(mapId)
|
|
@@ -2586,9 +3023,19 @@ var FloatingChatBox = ({
|
|
|
2586
3023
|
getAccessToken,
|
|
2587
3024
|
onActionClick,
|
|
2588
3025
|
onOpenChange,
|
|
2589
|
-
hideButton
|
|
3026
|
+
hideButton,
|
|
3027
|
+
open: openProp
|
|
2590
3028
|
}) => {
|
|
2591
|
-
const
|
|
3029
|
+
const isControlled = openProp !== void 0;
|
|
3030
|
+
const [internalOpen, setInternalOpen] = (0, import_react4.useState)(false);
|
|
3031
|
+
const open = isControlled ? openProp : internalOpen;
|
|
3032
|
+
const setOpen = (0, import_react4.useCallback)((value) => {
|
|
3033
|
+
const newValue = typeof value === "function" ? value(open) : value;
|
|
3034
|
+
if (!isControlled) {
|
|
3035
|
+
setInternalOpen(newValue);
|
|
3036
|
+
}
|
|
3037
|
+
onOpenChange?.(newValue);
|
|
3038
|
+
}, [isControlled, open, onOpenChange]);
|
|
2592
3039
|
const [expanded, setExpanded] = (0, import_react4.useState)(false);
|
|
2593
3040
|
const [messages, setMessages] = (0, import_react4.useState)([]);
|
|
2594
3041
|
const [inputValue, setInputValue] = (0, import_react4.useState)("");
|
|
@@ -2605,9 +3052,6 @@ var FloatingChatBox = ({
|
|
|
2605
3052
|
}, [accessToken, baseUrl, getAccessToken]);
|
|
2606
3053
|
const { sendMessage: sendMessage2, isStreaming, streamingText, completeResponse } = useSendMessageStream(chatConfig);
|
|
2607
3054
|
const canSend = Boolean(mapId) && Boolean(baseUrl) && inputValue.trim().length > 0 && !isStreaming;
|
|
2608
|
-
(0, import_react4.useEffect)(() => {
|
|
2609
|
-
onOpenChange?.(open);
|
|
2610
|
-
}, [open, onOpenChange]);
|
|
2611
3055
|
(0, import_react4.useEffect)(() => {
|
|
2612
3056
|
if (open && isMobile) {
|
|
2613
3057
|
setExpanded(true);
|
|
@@ -2760,6 +3204,13 @@ var FloatingChatBox = ({
|
|
|
2760
3204
|
] }, index)) })
|
|
2761
3205
|
] });
|
|
2762
3206
|
};
|
|
3207
|
+
const handleActionClick = (0, import_react4.useCallback)((action) => {
|
|
3208
|
+
if (isStreaming) return;
|
|
3209
|
+
setOpen(false);
|
|
3210
|
+
requestAnimationFrame(() => {
|
|
3211
|
+
onActionClick?.(action);
|
|
3212
|
+
});
|
|
3213
|
+
}, [isStreaming, setOpen, onActionClick]);
|
|
2763
3214
|
const renderActions = (response) => {
|
|
2764
3215
|
if (!response?.suggestedActions?.length) return null;
|
|
2765
3216
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles.actionsSection, children: [
|
|
@@ -2773,7 +3224,7 @@ var FloatingChatBox = ({
|
|
|
2773
3224
|
opacity: isStreaming ? 0.5 : 1,
|
|
2774
3225
|
cursor: isStreaming ? "not-allowed" : "pointer"
|
|
2775
3226
|
},
|
|
2776
|
-
onClick: () =>
|
|
3227
|
+
onClick: () => handleActionClick(action),
|
|
2777
3228
|
disabled: isStreaming,
|
|
2778
3229
|
onMouseEnter: (e) => {
|
|
2779
3230
|
if (!isStreaming) {
|