zenit-sdk 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-R73LRYVJ.mjs → chunk-52CLFD4L.mjs} +703 -109
- package/dist/chunk-52CLFD4L.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 +702 -108
- 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 +702 -108
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +1 -1
- package/package.json +1 -1
- 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
|
|
|
@@ -296,6 +296,7 @@ function getEffectiveLayerOpacity(baseOpacity, zoom, layerType, geometryType, op
|
|
|
296
296
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
297
297
|
var DEFAULT_CENTER = [0, 0];
|
|
298
298
|
var DEFAULT_ZOOM = 3;
|
|
299
|
+
var LABELS_PANE_NAME = "zenit-labels-pane";
|
|
299
300
|
function computeBBoxFromGeojson(geojson) {
|
|
300
301
|
if (!geojson) return null;
|
|
301
302
|
if (!Array.isArray(geojson.features) || geojson.features.length === 0) return null;
|
|
@@ -336,6 +337,23 @@ function mergeBBoxes(bboxes) {
|
|
|
336
337
|
{ ...first }
|
|
337
338
|
);
|
|
338
339
|
}
|
|
340
|
+
function isRecord(value) {
|
|
341
|
+
return typeof value === "object" && value !== null;
|
|
342
|
+
}
|
|
343
|
+
function isGeoJsonFeatureCollection(value) {
|
|
344
|
+
if (!isRecord(value)) return false;
|
|
345
|
+
const features = value.features;
|
|
346
|
+
if (!Array.isArray(features)) return false;
|
|
347
|
+
const type = value.type;
|
|
348
|
+
return type === void 0 || type === "FeatureCollection";
|
|
349
|
+
}
|
|
350
|
+
function extractGeoJsonFeatureCollection(value) {
|
|
351
|
+
if (isRecord(value) && "data" in value) {
|
|
352
|
+
const data = value.data;
|
|
353
|
+
return isGeoJsonFeatureCollection(data) ? data : null;
|
|
354
|
+
}
|
|
355
|
+
return isGeoJsonFeatureCollection(value) ? value : null;
|
|
356
|
+
}
|
|
339
357
|
function getFeatureLayerId(feature) {
|
|
340
358
|
const layerId = feature?.properties?.__zenit_layerId ?? feature?.properties?.layerId ?? feature?.properties?.layer_id;
|
|
341
359
|
if (layerId === void 0 || layerId === null) return null;
|
|
@@ -344,6 +362,459 @@ function getFeatureLayerId(feature) {
|
|
|
344
362
|
function escapeHtml(value) {
|
|
345
363
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
346
364
|
}
|
|
365
|
+
var DESCRIPTION_KEYS = /* @__PURE__ */ new Set(["descripcion", "description"]);
|
|
366
|
+
var POPUP_EXCLUDED_KEYS = /* @__PURE__ */ new Set(["geom", "geometry"]);
|
|
367
|
+
var POPUP_HEADER_KEYS = ["nombre", "name", "title", "titulo"];
|
|
368
|
+
var POPUP_STYLE_ID = "zenit-leaflet-popup-styles";
|
|
369
|
+
var DESKTOP_POPUP_DIMENSIONS = { maxWidth: 350, minWidth: 280, maxHeight: 480 };
|
|
370
|
+
var MOBILE_POPUP_DIMENSIONS = { maxWidth: 280, minWidth: 240, maxHeight: 380 };
|
|
371
|
+
var ZENIT_LEAFLET_POPUP_STYLES = `
|
|
372
|
+
/* ===== Zenit Leaflet Popup - Modern Professional Styling ===== */
|
|
373
|
+
|
|
374
|
+
/* Main popup wrapper */
|
|
375
|
+
.zenit-leaflet-popup .leaflet-popup-content-wrapper {
|
|
376
|
+
border-radius: 12px;
|
|
377
|
+
box-shadow:
|
|
378
|
+
0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
|
379
|
+
0 2px 4px -2px rgba(0, 0, 0, 0.1),
|
|
380
|
+
0 0 0 1px rgba(0, 0, 0, 0.05);
|
|
381
|
+
padding: 0;
|
|
382
|
+
background: #ffffff;
|
|
383
|
+
overflow: hidden;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/* Content area with scroll support */
|
|
387
|
+
.zenit-leaflet-popup .leaflet-popup-content {
|
|
388
|
+
margin: 0;
|
|
389
|
+
padding: 0;
|
|
390
|
+
font-size: 13px;
|
|
391
|
+
line-height: 1.5;
|
|
392
|
+
color: #374151;
|
|
393
|
+
min-width: 100%;
|
|
394
|
+
max-height: min(70vh, 480px);
|
|
395
|
+
overflow-y: auto;
|
|
396
|
+
overflow-x: hidden;
|
|
397
|
+
scrollbar-width: thin;
|
|
398
|
+
scrollbar-color: rgba(156, 163, 175, 0.5) transparent;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/* Popup tip/arrow shadow */
|
|
402
|
+
.zenit-leaflet-popup .leaflet-popup-tip-container {
|
|
403
|
+
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.zenit-leaflet-popup .leaflet-popup-tip {
|
|
407
|
+
background: #ffffff;
|
|
408
|
+
box-shadow: none;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/* Close button styling */
|
|
412
|
+
.zenit-leaflet-popup .leaflet-popup-close-button {
|
|
413
|
+
color: #9ca3af;
|
|
414
|
+
font-size: 18px;
|
|
415
|
+
font-weight: 400;
|
|
416
|
+
width: 28px;
|
|
417
|
+
height: 28px;
|
|
418
|
+
padding: 0;
|
|
419
|
+
margin: 8px 8px 0 0;
|
|
420
|
+
display: flex;
|
|
421
|
+
align-items: center;
|
|
422
|
+
justify-content: center;
|
|
423
|
+
border-radius: 6px;
|
|
424
|
+
transition: all 0.15s ease;
|
|
425
|
+
z-index: 10;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
.zenit-leaflet-popup .leaflet-popup-close-button:hover {
|
|
429
|
+
color: #374151;
|
|
430
|
+
background-color: #f3f4f6;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
.zenit-leaflet-popup .leaflet-popup-close-button:active {
|
|
434
|
+
background-color: #e5e7eb;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/* Main card container */
|
|
438
|
+
.zenit-popup-card {
|
|
439
|
+
display: flex;
|
|
440
|
+
flex-direction: column;
|
|
441
|
+
gap: 0;
|
|
442
|
+
padding: 16px;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
.zenit-popup-header {
|
|
446
|
+
padding-bottom: 12px;
|
|
447
|
+
border-bottom: 1px solid #e5e7eb;
|
|
448
|
+
margin-bottom: 4px;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.zenit-popup-title {
|
|
452
|
+
font-size: 14px;
|
|
453
|
+
font-weight: 700;
|
|
454
|
+
color: #111827;
|
|
455
|
+
letter-spacing: 0.01em;
|
|
456
|
+
line-height: 1.4;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/* Individual row styling with subtle separator */
|
|
460
|
+
.zenit-popup-row {
|
|
461
|
+
display: flex;
|
|
462
|
+
flex-direction: column;
|
|
463
|
+
gap: 2px;
|
|
464
|
+
padding: 10px 0;
|
|
465
|
+
border-bottom: 1px solid #f3f4f6;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
.zenit-popup-row:first-child {
|
|
469
|
+
padding-top: 0;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.zenit-popup-row:last-child {
|
|
473
|
+
border-bottom: none;
|
|
474
|
+
padding-bottom: 0;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/* Label styling - small, gray, uppercase */
|
|
478
|
+
.zenit-popup-label {
|
|
479
|
+
font-size: 10px;
|
|
480
|
+
font-weight: 500;
|
|
481
|
+
color: #9ca3af;
|
|
482
|
+
text-transform: uppercase;
|
|
483
|
+
letter-spacing: 0.05em;
|
|
484
|
+
line-height: 1.4;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/* Value styling - darker, readable */
|
|
488
|
+
.zenit-popup-value {
|
|
489
|
+
font-size: 13px;
|
|
490
|
+
font-weight: 400;
|
|
491
|
+
color: #1f2937;
|
|
492
|
+
overflow-wrap: break-word;
|
|
493
|
+
word-break: break-word;
|
|
494
|
+
line-height: 1.5;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
.zenit-popup-link {
|
|
498
|
+
color: #2563eb;
|
|
499
|
+
text-decoration: underline;
|
|
500
|
+
font-weight: 500;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
.zenit-popup-link:hover {
|
|
504
|
+
color: #1d4ed8;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/* Special styling for description field */
|
|
508
|
+
.zenit-popup-row.zenit-popup-description {
|
|
509
|
+
background-color: #f9fafb;
|
|
510
|
+
margin: 0 -16px;
|
|
511
|
+
padding: 12px 16px;
|
|
512
|
+
border-bottom: 1px solid #e5e7eb;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.zenit-popup-row.zenit-popup-description:first-child {
|
|
516
|
+
margin-top: 0;
|
|
517
|
+
border-radius: 0;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value {
|
|
521
|
+
font-size: 13px;
|
|
522
|
+
line-height: 1.6;
|
|
523
|
+
color: #374151;
|
|
524
|
+
max-height: 150px;
|
|
525
|
+
overflow-y: auto;
|
|
526
|
+
padding-right: 4px;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/* Preformatted text (JSON objects) */
|
|
530
|
+
.zenit-popup-pre {
|
|
531
|
+
margin: 0;
|
|
532
|
+
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
|
|
533
|
+
font-size: 11px;
|
|
534
|
+
white-space: pre-wrap;
|
|
535
|
+
word-break: break-word;
|
|
536
|
+
color: #4b5563;
|
|
537
|
+
background-color: #f9fafb;
|
|
538
|
+
padding: 8px;
|
|
539
|
+
border-radius: 6px;
|
|
540
|
+
border: 1px solid #e5e7eb;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/* Empty state styling */
|
|
544
|
+
.zenit-popup-empty {
|
|
545
|
+
font-size: 13px;
|
|
546
|
+
color: #9ca3af;
|
|
547
|
+
font-style: italic;
|
|
548
|
+
text-align: center;
|
|
549
|
+
padding: 20px 0;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/* Webkit scrollbar styling */
|
|
553
|
+
.zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar {
|
|
554
|
+
width: 6px;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
.zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar-track {
|
|
558
|
+
background: transparent;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar-thumb {
|
|
562
|
+
background-color: rgba(156, 163, 175, 0.4);
|
|
563
|
+
border-radius: 3px;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
.zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar-thumb:hover {
|
|
567
|
+
background-color: rgba(107, 114, 128, 0.6);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/* Scrollbar for description field */
|
|
571
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value::-webkit-scrollbar {
|
|
572
|
+
width: 4px;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value::-webkit-scrollbar-track {
|
|
576
|
+
background: transparent;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value::-webkit-scrollbar-thumb {
|
|
580
|
+
background-color: rgba(156, 163, 175, 0.4);
|
|
581
|
+
border-radius: 2px;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/* ===== Responsive: Mobile (<640px) ===== */
|
|
585
|
+
@media (max-width: 640px) {
|
|
586
|
+
.zenit-leaflet-popup .leaflet-popup-content-wrapper {
|
|
587
|
+
border-radius: 10px;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
.zenit-leaflet-popup .leaflet-popup-close-button {
|
|
591
|
+
width: 26px;
|
|
592
|
+
height: 26px;
|
|
593
|
+
font-size: 16px;
|
|
594
|
+
margin: 6px 6px 0 0;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
.zenit-popup-card {
|
|
598
|
+
padding: 12px;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
.zenit-leaflet-popup .leaflet-popup-content {
|
|
602
|
+
max-height: min(65vh, 380px);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
.zenit-popup-header {
|
|
606
|
+
padding-bottom: 10px;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
.zenit-popup-title {
|
|
610
|
+
font-size: 13px;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
.zenit-popup-row {
|
|
614
|
+
padding: 8px 0;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
.zenit-popup-label {
|
|
618
|
+
font-size: 9px;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
.zenit-popup-value {
|
|
622
|
+
font-size: 12px;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
.zenit-popup-row.zenit-popup-description {
|
|
626
|
+
margin: 0 -12px;
|
|
627
|
+
padding: 10px 12px;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value {
|
|
631
|
+
font-size: 12px;
|
|
632
|
+
max-height: 120px;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
.zenit-popup-pre {
|
|
636
|
+
font-size: 10px;
|
|
637
|
+
padding: 6px;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
.zenit-popup-empty {
|
|
641
|
+
font-size: 12px;
|
|
642
|
+
padding: 16px 0;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/* ===== Map tooltip styling ===== */
|
|
647
|
+
.zenit-map-tooltip {
|
|
648
|
+
background-color: rgba(31, 41, 55, 0.95);
|
|
649
|
+
border: none;
|
|
650
|
+
border-radius: 6px;
|
|
651
|
+
color: #ffffff;
|
|
652
|
+
font-size: 12px;
|
|
653
|
+
font-weight: 500;
|
|
654
|
+
padding: 6px 10px;
|
|
655
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
.zenit-map-tooltip::before {
|
|
659
|
+
border-top-color: rgba(31, 41, 55, 0.95);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
.polygon-label-tooltip {
|
|
663
|
+
z-index: 600 !important;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
.zenit-map-shell.popup-open .zenit-label-marker,
|
|
667
|
+
.zenit-map-shell.popup-open .polygon-label-tooltip,
|
|
668
|
+
.zenit-map-shell.popup-open .click-for-detail-hint,
|
|
669
|
+
.zenit-map-shell.popup-open .zenit-map-tooltip {
|
|
670
|
+
display: none !important;
|
|
671
|
+
}
|
|
672
|
+
`;
|
|
673
|
+
function ensurePopupStyles() {
|
|
674
|
+
if (typeof document === "undefined") return;
|
|
675
|
+
if (document.getElementById(POPUP_STYLE_ID)) return;
|
|
676
|
+
const styleTag = document.createElement("style");
|
|
677
|
+
styleTag.id = POPUP_STYLE_ID;
|
|
678
|
+
styleTag.textContent = ZENIT_LEAFLET_POPUP_STYLES;
|
|
679
|
+
document.head.appendChild(styleTag);
|
|
680
|
+
}
|
|
681
|
+
function getPopupDimensions() {
|
|
682
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
683
|
+
return DESKTOP_POPUP_DIMENSIONS;
|
|
684
|
+
}
|
|
685
|
+
return window.matchMedia("(max-width: 640px)").matches ? MOBILE_POPUP_DIMENSIONS : DESKTOP_POPUP_DIMENSIONS;
|
|
686
|
+
}
|
|
687
|
+
function normalizeDescriptionValue(value) {
|
|
688
|
+
if (value === void 0 || value === null) return null;
|
|
689
|
+
if (typeof value === "string") {
|
|
690
|
+
const trimmed = value.trim();
|
|
691
|
+
return trimmed ? trimmed : null;
|
|
692
|
+
}
|
|
693
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
694
|
+
return String(value);
|
|
695
|
+
}
|
|
696
|
+
return null;
|
|
697
|
+
}
|
|
698
|
+
function extractDescriptionValue(properties) {
|
|
699
|
+
if (!properties) return null;
|
|
700
|
+
const matches = Object.entries(properties).find(
|
|
701
|
+
([key]) => DESCRIPTION_KEYS.has(key.toLowerCase())
|
|
702
|
+
);
|
|
703
|
+
if (!matches) return null;
|
|
704
|
+
return normalizeDescriptionValue(matches[1]);
|
|
705
|
+
}
|
|
706
|
+
function safeJsonStringify(value) {
|
|
707
|
+
try {
|
|
708
|
+
const json = JSON.stringify(value, null, 2);
|
|
709
|
+
if (json !== void 0) return json;
|
|
710
|
+
} catch {
|
|
711
|
+
}
|
|
712
|
+
return String(value);
|
|
713
|
+
}
|
|
714
|
+
function renderPopupValue(value) {
|
|
715
|
+
if (value === null || value === void 0) {
|
|
716
|
+
return '<span class="zenit-popup-empty">Sin datos</span>';
|
|
717
|
+
}
|
|
718
|
+
if (value instanceof Date) {
|
|
719
|
+
return `<span>${escapeHtml(value.toLocaleDateString("es-GT"))}</span>`;
|
|
720
|
+
}
|
|
721
|
+
if (typeof value === "number") {
|
|
722
|
+
return `<span>${escapeHtml(value.toLocaleString("es-GT"))}</span>`;
|
|
723
|
+
}
|
|
724
|
+
if (typeof value === "string") {
|
|
725
|
+
const trimmed = value.trim();
|
|
726
|
+
const isLikelyDate = /^\d{4}-\d{2}-\d{2}/.test(trimmed) || trimmed.includes("T");
|
|
727
|
+
if (isLikelyDate) {
|
|
728
|
+
const parsed = Date.parse(trimmed);
|
|
729
|
+
if (!Number.isNaN(parsed)) {
|
|
730
|
+
return `<span>${escapeHtml(new Date(parsed).toLocaleDateString("es-GT"))}</span>`;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
try {
|
|
734
|
+
const parsedUrl = new URL(trimmed);
|
|
735
|
+
if (parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:") {
|
|
736
|
+
const safeHref = escapeHtml(parsedUrl.toString());
|
|
737
|
+
return `<a class="zenit-popup-link" href="${safeHref}" target="_blank" rel="noopener noreferrer">${safeHref}</a>`;
|
|
738
|
+
}
|
|
739
|
+
} catch {
|
|
740
|
+
}
|
|
741
|
+
return `<span>${escapeHtml(trimmed || value)}</span>`;
|
|
742
|
+
}
|
|
743
|
+
if (typeof value === "object") {
|
|
744
|
+
const json = safeJsonStringify(value);
|
|
745
|
+
return `<pre class="zenit-popup-pre">${escapeHtml(json)}</pre>`;
|
|
746
|
+
}
|
|
747
|
+
return `<span>${escapeHtml(String(value))}</span>`;
|
|
748
|
+
}
|
|
749
|
+
function shouldIncludePopupEntry(key, value) {
|
|
750
|
+
if (!key) return false;
|
|
751
|
+
const normalized = key.trim().toLowerCase();
|
|
752
|
+
if (!normalized) return false;
|
|
753
|
+
if (normalized.startsWith("_")) return false;
|
|
754
|
+
if (POPUP_EXCLUDED_KEYS.has(normalized)) return false;
|
|
755
|
+
if (value === null || value === void 0) return false;
|
|
756
|
+
if (typeof value === "string" && !value.trim()) return false;
|
|
757
|
+
return true;
|
|
758
|
+
}
|
|
759
|
+
function isDescriptionKey(key) {
|
|
760
|
+
const normalized = key.trim().toLowerCase();
|
|
761
|
+
return DESCRIPTION_KEYS.has(normalized);
|
|
762
|
+
}
|
|
763
|
+
function extractPopupHeader(properties) {
|
|
764
|
+
if (!properties) return null;
|
|
765
|
+
const entry = Object.entries(properties).find(
|
|
766
|
+
(candidate) => {
|
|
767
|
+
const [key, value] = candidate;
|
|
768
|
+
return POPUP_HEADER_KEYS.includes(key.trim().toLowerCase()) && typeof value === "string" && value.trim().length > 0;
|
|
769
|
+
}
|
|
770
|
+
);
|
|
771
|
+
if (!entry) return null;
|
|
772
|
+
return entry[1].trim();
|
|
773
|
+
}
|
|
774
|
+
function formatLabel(key) {
|
|
775
|
+
return key.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").trim();
|
|
776
|
+
}
|
|
777
|
+
function createPopupContent(properties) {
|
|
778
|
+
const headerText = extractPopupHeader(properties);
|
|
779
|
+
const entries = Object.entries(properties).filter(([key, value]) => {
|
|
780
|
+
if (!shouldIncludePopupEntry(key, value)) return false;
|
|
781
|
+
if (headerText && POPUP_HEADER_KEYS.includes(key.trim().toLowerCase())) {
|
|
782
|
+
return false;
|
|
783
|
+
}
|
|
784
|
+
return true;
|
|
785
|
+
});
|
|
786
|
+
if (entries.length === 0) {
|
|
787
|
+
return `<div class="zenit-popup-card"><div class="zenit-popup-empty">Sin datos disponibles</div></div>`;
|
|
788
|
+
}
|
|
789
|
+
const descriptionEntry = entries.find(([key]) => isDescriptionKey(key));
|
|
790
|
+
const otherEntries = entries.filter(([key]) => !isDescriptionKey(key));
|
|
791
|
+
let rowsHtml = "";
|
|
792
|
+
if (descriptionEntry) {
|
|
793
|
+
const [key, value] = descriptionEntry;
|
|
794
|
+
const label = escapeHtml(formatLabel(key));
|
|
795
|
+
const valueHtml = renderPopupValue(value);
|
|
796
|
+
rowsHtml += `
|
|
797
|
+
<div class="zenit-popup-row zenit-popup-description">
|
|
798
|
+
<div class="zenit-popup-label">${label}</div>
|
|
799
|
+
<div class="zenit-popup-value">${valueHtml}</div>
|
|
800
|
+
</div>
|
|
801
|
+
`;
|
|
802
|
+
}
|
|
803
|
+
rowsHtml += otherEntries.map(([key, value]) => {
|
|
804
|
+
const label = escapeHtml(formatLabel(key));
|
|
805
|
+
const valueHtml = renderPopupValue(value);
|
|
806
|
+
return `
|
|
807
|
+
<div class="zenit-popup-row">
|
|
808
|
+
<div class="zenit-popup-label">${label}</div>
|
|
809
|
+
<div class="zenit-popup-value">${valueHtml}</div>
|
|
810
|
+
</div>
|
|
811
|
+
`;
|
|
812
|
+
}).join("");
|
|
813
|
+
const headerHtml = headerText ? `<div class="zenit-popup-header"><div class="zenit-popup-title">${escapeHtml(
|
|
814
|
+
headerText
|
|
815
|
+
)}</div></div>` : "";
|
|
816
|
+
return `<div class="zenit-popup-card">${headerHtml}${rowsHtml}</div>`;
|
|
817
|
+
}
|
|
347
818
|
function withAlpha(color, alpha) {
|
|
348
819
|
const trimmed = color.trim();
|
|
349
820
|
if (trimmed.startsWith("#")) {
|
|
@@ -412,40 +883,39 @@ function getFeatureStyleOverrides(feature) {
|
|
|
412
883
|
function buildFeaturePopupHtml(feature) {
|
|
413
884
|
const properties = feature?.properties;
|
|
414
885
|
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
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
return `<div>${parts.join("")}</div>`;
|
|
886
|
+
const rendered = createPopupContent(properties);
|
|
887
|
+
return rendered ? rendered : null;
|
|
888
|
+
}
|
|
889
|
+
var POINT_GEOMETRY_TYPES = /* @__PURE__ */ new Set(["Point", "MultiPoint"]);
|
|
890
|
+
function getGeometryType(feature) {
|
|
891
|
+
const t = feature?.geometry?.type;
|
|
892
|
+
return typeof t === "string" ? t : null;
|
|
893
|
+
}
|
|
894
|
+
function isPointGeometry(feature) {
|
|
895
|
+
const geometryType = getGeometryType(feature);
|
|
896
|
+
return geometryType !== null && POINT_GEOMETRY_TYPES.has(geometryType);
|
|
897
|
+
}
|
|
898
|
+
function isNonPointGeometry(feature) {
|
|
899
|
+
const geometryType = getGeometryType(feature);
|
|
900
|
+
return geometryType !== null && !POINT_GEOMETRY_TYPES.has(geometryType);
|
|
901
|
+
}
|
|
902
|
+
function buildFeatureCollection(features) {
|
|
903
|
+
return {
|
|
904
|
+
type: "FeatureCollection",
|
|
905
|
+
features
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
function pickIntersectFeature(baseFeature, candidates) {
|
|
909
|
+
if (!Array.isArray(candidates) || candidates.length === 0) return null;
|
|
910
|
+
const baseId = baseFeature?.id;
|
|
911
|
+
if (baseId !== void 0 && baseId !== null) {
|
|
912
|
+
const matchById = candidates.find((candidate) => candidate?.id === baseId);
|
|
913
|
+
if (matchById) return matchById;
|
|
914
|
+
}
|
|
915
|
+
const matchWithDescription = candidates.find(
|
|
916
|
+
(candidate) => extractDescriptionValue(candidate?.properties)
|
|
917
|
+
);
|
|
918
|
+
return matchWithDescription ?? candidates[0];
|
|
449
919
|
}
|
|
450
920
|
function normalizeCenterTuple(center) {
|
|
451
921
|
if (!center) return null;
|
|
@@ -566,7 +1036,9 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
566
1036
|
const [loadingMap, setLoadingMap] = (0, import_react.useState)(false);
|
|
567
1037
|
const [mapError, setMapError] = (0, import_react.useState)(null);
|
|
568
1038
|
const [mapInstance, setMapInstance] = (0, import_react.useState)(null);
|
|
1039
|
+
const [panesReady, setPanesReady] = (0, import_react.useState)(false);
|
|
569
1040
|
const [currentZoom, setCurrentZoom] = (0, import_react.useState)(initialZoom ?? DEFAULT_ZOOM);
|
|
1041
|
+
const [isPopupOpen, setIsPopupOpen] = (0, import_react.useState)(false);
|
|
570
1042
|
const [isMobile, setIsMobile] = (0, import_react.useState)(() => {
|
|
571
1043
|
if (typeof window === "undefined") return false;
|
|
572
1044
|
return window.matchMedia("(max-width: 768px)").matches;
|
|
@@ -590,6 +1062,36 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
590
1062
|
}
|
|
591
1063
|
return;
|
|
592
1064
|
}, []);
|
|
1065
|
+
(0, import_react.useEffect)(() => {
|
|
1066
|
+
if (featureInfoMode === "popup") {
|
|
1067
|
+
ensurePopupStyles();
|
|
1068
|
+
}
|
|
1069
|
+
}, [featureInfoMode]);
|
|
1070
|
+
(0, import_react.useEffect)(() => {
|
|
1071
|
+
if (featureInfoMode !== "popup") {
|
|
1072
|
+
setIsPopupOpen(false);
|
|
1073
|
+
}
|
|
1074
|
+
}, [featureInfoMode]);
|
|
1075
|
+
(0, import_react.useEffect)(() => {
|
|
1076
|
+
if (!mapInstance) return;
|
|
1077
|
+
const popupPane = mapInstance.getPane("popupPane");
|
|
1078
|
+
if (popupPane) {
|
|
1079
|
+
popupPane.style.zIndex = "800";
|
|
1080
|
+
}
|
|
1081
|
+
const labelsPane = mapInstance.getPane(LABELS_PANE_NAME) ?? mapInstance.createPane(LABELS_PANE_NAME);
|
|
1082
|
+
labelsPane.style.zIndex = "600";
|
|
1083
|
+
}, [mapInstance]);
|
|
1084
|
+
(0, import_react.useEffect)(() => {
|
|
1085
|
+
if (!mapInstance) return;
|
|
1086
|
+
const handlePopupOpen = () => setIsPopupOpen(true);
|
|
1087
|
+
const handlePopupClose = () => setIsPopupOpen(false);
|
|
1088
|
+
mapInstance.on("popupopen", handlePopupOpen);
|
|
1089
|
+
mapInstance.on("popupclose", handlePopupClose);
|
|
1090
|
+
return () => {
|
|
1091
|
+
mapInstance.off("popupopen", handlePopupOpen);
|
|
1092
|
+
mapInstance.off("popupclose", handlePopupClose);
|
|
1093
|
+
};
|
|
1094
|
+
}, [mapInstance]);
|
|
593
1095
|
const layerStyleIndex = (0, import_react.useMemo)(() => {
|
|
594
1096
|
const index = /* @__PURE__ */ new Map();
|
|
595
1097
|
(map?.mapLayers ?? []).forEach((entry) => {
|
|
@@ -880,16 +1382,21 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
880
1382
|
(targetMap, targetLayers) => {
|
|
881
1383
|
const baseZIndex = 400;
|
|
882
1384
|
targetLayers.forEach((layer) => {
|
|
883
|
-
const paneName = `zenit-layer-${layer.layerId}`;
|
|
884
|
-
const pane = targetMap.getPane(paneName) ?? targetMap.createPane(paneName);
|
|
885
1385
|
const order = Number.isFinite(layer.displayOrder) ? layer.displayOrder : 0;
|
|
886
|
-
|
|
1386
|
+
const orderOffset = Math.max(0, Math.min(order, 150));
|
|
1387
|
+
const fillPaneName = `zenit-layer-${layer.layerId}-fill`;
|
|
1388
|
+
const pointPaneName = `zenit-layer-${layer.layerId}-points`;
|
|
1389
|
+
const fillPane = targetMap.getPane(fillPaneName) ?? targetMap.createPane(fillPaneName);
|
|
1390
|
+
const pointPane = targetMap.getPane(pointPaneName) ?? targetMap.createPane(pointPaneName);
|
|
1391
|
+
fillPane.style.zIndex = String(baseZIndex + orderOffset);
|
|
1392
|
+
pointPane.style.zIndex = String(baseZIndex + orderOffset + 100);
|
|
887
1393
|
});
|
|
888
1394
|
},
|
|
889
1395
|
[]
|
|
890
1396
|
);
|
|
891
1397
|
const handleMapReady = (0, import_react.useCallback)(
|
|
892
1398
|
(instance) => {
|
|
1399
|
+
setPanesReady(false);
|
|
893
1400
|
setMapInstance(instance);
|
|
894
1401
|
onMapReady?.(instance);
|
|
895
1402
|
},
|
|
@@ -897,6 +1404,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
897
1404
|
);
|
|
898
1405
|
(0, import_react.useEffect)(() => {
|
|
899
1406
|
if (!mapInstance) {
|
|
1407
|
+
setPanesReady(false);
|
|
900
1408
|
return;
|
|
901
1409
|
}
|
|
902
1410
|
if (orderedLayers.length === 0) {
|
|
@@ -907,6 +1415,12 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
907
1415
|
displayOrder: layer.displayOrder
|
|
908
1416
|
}));
|
|
909
1417
|
ensureLayerPanes(mapInstance, layerTargets);
|
|
1418
|
+
const first = layerTargets[0];
|
|
1419
|
+
const testPane = mapInstance.getPane(`zenit-layer-${first.layerId}-fill`);
|
|
1420
|
+
const labelsPane = mapInstance.getPane(LABELS_PANE_NAME);
|
|
1421
|
+
if (testPane && labelsPane) {
|
|
1422
|
+
setPanesReady(true);
|
|
1423
|
+
}
|
|
910
1424
|
}, [mapInstance, orderedLayers, ensureLayerPanes]);
|
|
911
1425
|
const overlayOnEachFeature = (0, import_react.useMemo)(() => {
|
|
912
1426
|
return (feature, layer) => {
|
|
@@ -924,7 +1438,17 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
924
1438
|
if (featureInfoMode === "popup") {
|
|
925
1439
|
const content = buildFeaturePopupHtml(feature);
|
|
926
1440
|
if (content) {
|
|
927
|
-
|
|
1441
|
+
const { maxWidth, minWidth, maxHeight } = getPopupDimensions();
|
|
1442
|
+
layer.bindPopup(content, {
|
|
1443
|
+
maxWidth,
|
|
1444
|
+
minWidth,
|
|
1445
|
+
maxHeight,
|
|
1446
|
+
className: "zenit-leaflet-popup custom-leaflet-popup",
|
|
1447
|
+
autoPan: true,
|
|
1448
|
+
closeButton: true,
|
|
1449
|
+
keepInView: true,
|
|
1450
|
+
offset: import_leaflet.default.point(0, -24)
|
|
1451
|
+
});
|
|
928
1452
|
}
|
|
929
1453
|
}
|
|
930
1454
|
if (isPointFeature && layer.bindTooltip) {
|
|
@@ -935,7 +1459,38 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
935
1459
|
className: "zenit-map-tooltip"
|
|
936
1460
|
});
|
|
937
1461
|
}
|
|
938
|
-
layer.on("click", () =>
|
|
1462
|
+
layer.on("click", () => {
|
|
1463
|
+
if (featureInfoMode === "popup" && client && layerId !== void 0 && !extractDescriptionValue(feature?.properties) && feature?.geometry) {
|
|
1464
|
+
const trackedFeature = feature;
|
|
1465
|
+
if (!trackedFeature.__zenit_popup_loaded) {
|
|
1466
|
+
trackedFeature.__zenit_popup_loaded = true;
|
|
1467
|
+
client.layers.getLayerGeoJsonIntersect({
|
|
1468
|
+
id: layerId,
|
|
1469
|
+
geometry: feature.geometry
|
|
1470
|
+
}).then((response) => {
|
|
1471
|
+
const geo = extractGeoJsonFeatureCollection(response);
|
|
1472
|
+
const candidates = geo?.features ?? [];
|
|
1473
|
+
const resolved = pickIntersectFeature(feature, candidates);
|
|
1474
|
+
if (!resolved?.properties) return;
|
|
1475
|
+
const mergedProperties = {
|
|
1476
|
+
...trackedFeature.properties ?? {},
|
|
1477
|
+
...resolved.properties
|
|
1478
|
+
};
|
|
1479
|
+
trackedFeature.properties = mergedProperties;
|
|
1480
|
+
const updatedHtml = buildFeaturePopupHtml({
|
|
1481
|
+
...feature,
|
|
1482
|
+
properties: mergedProperties
|
|
1483
|
+
});
|
|
1484
|
+
if (updatedHtml && layer.setPopupContent) {
|
|
1485
|
+
layer.setPopupContent(updatedHtml);
|
|
1486
|
+
}
|
|
1487
|
+
}).catch(() => {
|
|
1488
|
+
trackedFeature.__zenit_popup_loaded = false;
|
|
1489
|
+
});
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
onFeatureClick?.(feature, layerId);
|
|
1493
|
+
});
|
|
939
1494
|
layer.on("mouseover", () => {
|
|
940
1495
|
if (layer instanceof import_leaflet.default.Path && originalStyle) {
|
|
941
1496
|
layer.setStyle({
|
|
@@ -959,7 +1514,7 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
959
1514
|
}
|
|
960
1515
|
});
|
|
961
1516
|
};
|
|
962
|
-
}, [featureInfoMode, onFeatureClick, onFeatureHover]);
|
|
1517
|
+
}, [client, featureInfoMode, onFeatureClick, onFeatureHover]);
|
|
963
1518
|
const buildLayerStyle = (layerId, baseOpacity, feature, layerType) => {
|
|
964
1519
|
const style = resolveLayerStyle(layerId);
|
|
965
1520
|
const featureStyleOverrides = getFeatureStyleOverrides(feature);
|
|
@@ -1117,68 +1672,93 @@ var ZenitMap = (0, import_react.forwardRef)(({
|
|
|
1117
1672
|
boxSizing: "border-box"
|
|
1118
1673
|
},
|
|
1119
1674
|
children: [
|
|
1120
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1121
|
-
|
|
1675
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1676
|
+
"div",
|
|
1122
1677
|
{
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1678
|
+
className: `zenit-map-shell${isPopupOpen ? " popup-open" : ""}`,
|
|
1679
|
+
style: { flex: 1, position: "relative" },
|
|
1680
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1681
|
+
import_react_leaflet.MapContainer,
|
|
1682
|
+
{
|
|
1683
|
+
center,
|
|
1684
|
+
zoom,
|
|
1685
|
+
style: { height: "100%", width: "100%" },
|
|
1686
|
+
scrollWheelZoom: true,
|
|
1687
|
+
zoomControl: false,
|
|
1688
|
+
children: [
|
|
1689
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1690
|
+
import_react_leaflet.TileLayer,
|
|
1691
|
+
{
|
|
1692
|
+
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
|
|
1693
|
+
attribution: "\xA9 OpenStreetMap contributors"
|
|
1694
|
+
}
|
|
1695
|
+
),
|
|
1696
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_leaflet.ZoomControl, { position: "topright" }),
|
|
1697
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MapInstanceBridge, { onReady: handleMapReady }),
|
|
1698
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FitToBounds, { bbox: explicitZoomBBox ?? void 0 }),
|
|
1699
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AutoFitToBounds, { bbox: autoZoomBBox ?? void 0, enabled: !explicitZoomBBox }),
|
|
1700
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ZoomBasedOpacityHandler, { onZoomChange: handleZoomChange }),
|
|
1701
|
+
orderedLayers.map((layerState) => {
|
|
1702
|
+
const baseOpacity = layerState.effective?.baseOpacity ?? layerState.effective?.opacity ?? 1;
|
|
1703
|
+
const fillPaneName = `zenit-layer-${layerState.mapLayer.layerId}-fill`;
|
|
1704
|
+
const pointsPaneName = `zenit-layer-${layerState.mapLayer.layerId}-points`;
|
|
1705
|
+
const layerType = layerState.layer?.layerType ?? layerState.mapLayer.layerType ?? void 0;
|
|
1706
|
+
const data = layerState.data?.features ?? [];
|
|
1707
|
+
const fillFeatures = data.filter(isNonPointGeometry);
|
|
1708
|
+
const pointFeatures = data.filter(isPointGeometry);
|
|
1709
|
+
const fillData = fillFeatures.length > 0 ? buildFeatureCollection(fillFeatures) : null;
|
|
1710
|
+
const pointsData = pointFeatures.length > 0 ? buildFeatureCollection(pointFeatures) : null;
|
|
1711
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [
|
|
1712
|
+
fillData && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1713
|
+
import_react_leaflet.GeoJSON,
|
|
1714
|
+
{
|
|
1715
|
+
data: fillData,
|
|
1716
|
+
pane: panesReady && mapInstance?.getPane(fillPaneName) ? fillPaneName : void 0,
|
|
1717
|
+
style: (feature) => buildLayerStyle(layerState.mapLayer.layerId, baseOpacity, feature, layerType),
|
|
1718
|
+
onEachFeature: overlayOnEachFeature
|
|
1719
|
+
}
|
|
1720
|
+
),
|
|
1721
|
+
pointsData && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1722
|
+
import_react_leaflet.GeoJSON,
|
|
1723
|
+
{
|
|
1724
|
+
data: pointsData,
|
|
1725
|
+
pane: panesReady && mapInstance?.getPane(pointsPaneName) ? pointsPaneName : void 0,
|
|
1726
|
+
pointToLayer: (feature, latlng) => import_leaflet.default.circleMarker(latlng, {
|
|
1727
|
+
radius: isMobile ? 8 : 6,
|
|
1728
|
+
...buildLayerStyle(layerState.mapLayer.layerId, baseOpacity, feature, layerType)
|
|
1729
|
+
}),
|
|
1730
|
+
onEachFeature: overlayOnEachFeature
|
|
1731
|
+
}
|
|
1732
|
+
),
|
|
1733
|
+
panesReady && mapInstance?.getPane(LABELS_PANE_NAME) ? labelMarkers.filter(
|
|
1734
|
+
(marker) => String(marker.layerId) === String(layerState.mapLayer.layerId)
|
|
1735
|
+
).map((marker) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1736
|
+
import_react_leaflet.Marker,
|
|
1737
|
+
{
|
|
1738
|
+
position: marker.position,
|
|
1739
|
+
icon: buildLabelIcon(marker.label, marker.opacity, marker.color),
|
|
1740
|
+
interactive: false,
|
|
1741
|
+
pane: LABELS_PANE_NAME
|
|
1742
|
+
},
|
|
1743
|
+
marker.key
|
|
1744
|
+
)) : null
|
|
1745
|
+
] }, layerState.mapLayer.layerId.toString());
|
|
1746
|
+
}),
|
|
1747
|
+
overlayGeojson && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1748
|
+
import_react_leaflet.GeoJSON,
|
|
1749
|
+
{
|
|
1750
|
+
data: overlayGeojson,
|
|
1751
|
+
style: overlayStyleFunction,
|
|
1752
|
+
onEachFeature: overlayOnEachFeature
|
|
1753
|
+
},
|
|
1754
|
+
"zenit-overlay-geojson"
|
|
1755
|
+
)
|
|
1756
|
+
]
|
|
1757
|
+
},
|
|
1758
|
+
String(mapId)
|
|
1759
|
+
)
|
|
1760
|
+
}
|
|
1761
|
+
),
|
|
1182
1762
|
showLayerPanel && decoratedLayers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1183
1763
|
"div",
|
|
1184
1764
|
{
|
|
@@ -2586,9 +3166,19 @@ var FloatingChatBox = ({
|
|
|
2586
3166
|
getAccessToken,
|
|
2587
3167
|
onActionClick,
|
|
2588
3168
|
onOpenChange,
|
|
2589
|
-
hideButton
|
|
3169
|
+
hideButton,
|
|
3170
|
+
open: openProp
|
|
2590
3171
|
}) => {
|
|
2591
|
-
const
|
|
3172
|
+
const isControlled = openProp !== void 0;
|
|
3173
|
+
const [internalOpen, setInternalOpen] = (0, import_react4.useState)(false);
|
|
3174
|
+
const open = isControlled ? openProp : internalOpen;
|
|
3175
|
+
const setOpen = (0, import_react4.useCallback)((value) => {
|
|
3176
|
+
const newValue = typeof value === "function" ? value(open) : value;
|
|
3177
|
+
if (!isControlled) {
|
|
3178
|
+
setInternalOpen(newValue);
|
|
3179
|
+
}
|
|
3180
|
+
onOpenChange?.(newValue);
|
|
3181
|
+
}, [isControlled, open, onOpenChange]);
|
|
2592
3182
|
const [expanded, setExpanded] = (0, import_react4.useState)(false);
|
|
2593
3183
|
const [messages, setMessages] = (0, import_react4.useState)([]);
|
|
2594
3184
|
const [inputValue, setInputValue] = (0, import_react4.useState)("");
|
|
@@ -2605,9 +3195,6 @@ var FloatingChatBox = ({
|
|
|
2605
3195
|
}, [accessToken, baseUrl, getAccessToken]);
|
|
2606
3196
|
const { sendMessage: sendMessage2, isStreaming, streamingText, completeResponse } = useSendMessageStream(chatConfig);
|
|
2607
3197
|
const canSend = Boolean(mapId) && Boolean(baseUrl) && inputValue.trim().length > 0 && !isStreaming;
|
|
2608
|
-
(0, import_react4.useEffect)(() => {
|
|
2609
|
-
onOpenChange?.(open);
|
|
2610
|
-
}, [open, onOpenChange]);
|
|
2611
3198
|
(0, import_react4.useEffect)(() => {
|
|
2612
3199
|
if (open && isMobile) {
|
|
2613
3200
|
setExpanded(true);
|
|
@@ -2760,6 +3347,13 @@ var FloatingChatBox = ({
|
|
|
2760
3347
|
] }, index)) })
|
|
2761
3348
|
] });
|
|
2762
3349
|
};
|
|
3350
|
+
const handleActionClick = (0, import_react4.useCallback)((action) => {
|
|
3351
|
+
if (isStreaming) return;
|
|
3352
|
+
setOpen(false);
|
|
3353
|
+
requestAnimationFrame(() => {
|
|
3354
|
+
onActionClick?.(action);
|
|
3355
|
+
});
|
|
3356
|
+
}, [isStreaming, setOpen, onActionClick]);
|
|
2763
3357
|
const renderActions = (response) => {
|
|
2764
3358
|
if (!response?.suggestedActions?.length) return null;
|
|
2765
3359
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles.actionsSection, children: [
|
|
@@ -2773,7 +3367,7 @@ var FloatingChatBox = ({
|
|
|
2773
3367
|
opacity: isStreaming ? 0.5 : 1,
|
|
2774
3368
|
cursor: isStreaming ? "not-allowed" : "pointer"
|
|
2775
3369
|
},
|
|
2776
|
-
onClick: () =>
|
|
3370
|
+
onClick: () => handleActionClick(action),
|
|
2777
3371
|
disabled: isStreaming,
|
|
2778
3372
|
onMouseEnter: (e) => {
|
|
2779
3373
|
if (!isStreaming) {
|