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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/react/ZenitMap.tsx
|
|
2
|
-
import { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, forwardRef } from "react";
|
|
2
|
+
import React, { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, forwardRef } from "react";
|
|
3
3
|
import { GeoJSON, MapContainer, Marker, TileLayer, ZoomControl, useMap } from "react-leaflet";
|
|
4
4
|
import L from "leaflet";
|
|
5
5
|
|
|
@@ -249,6 +249,7 @@ function getEffectiveLayerOpacity(baseOpacity, zoom, layerType, geometryType, op
|
|
|
249
249
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
250
250
|
var DEFAULT_CENTER = [0, 0];
|
|
251
251
|
var DEFAULT_ZOOM = 3;
|
|
252
|
+
var LABELS_PANE_NAME = "zenit-labels-pane";
|
|
252
253
|
function computeBBoxFromGeojson(geojson) {
|
|
253
254
|
if (!geojson) return null;
|
|
254
255
|
if (!Array.isArray(geojson.features) || geojson.features.length === 0) return null;
|
|
@@ -289,6 +290,23 @@ function mergeBBoxes(bboxes) {
|
|
|
289
290
|
{ ...first }
|
|
290
291
|
);
|
|
291
292
|
}
|
|
293
|
+
function isRecord(value) {
|
|
294
|
+
return typeof value === "object" && value !== null;
|
|
295
|
+
}
|
|
296
|
+
function isGeoJsonFeatureCollection(value) {
|
|
297
|
+
if (!isRecord(value)) return false;
|
|
298
|
+
const features = value.features;
|
|
299
|
+
if (!Array.isArray(features)) return false;
|
|
300
|
+
const type = value.type;
|
|
301
|
+
return type === void 0 || type === "FeatureCollection";
|
|
302
|
+
}
|
|
303
|
+
function extractGeoJsonFeatureCollection(value) {
|
|
304
|
+
if (isRecord(value) && "data" in value) {
|
|
305
|
+
const data = value.data;
|
|
306
|
+
return isGeoJsonFeatureCollection(data) ? data : null;
|
|
307
|
+
}
|
|
308
|
+
return isGeoJsonFeatureCollection(value) ? value : null;
|
|
309
|
+
}
|
|
292
310
|
function getFeatureLayerId(feature) {
|
|
293
311
|
const layerId = feature?.properties?.__zenit_layerId ?? feature?.properties?.layerId ?? feature?.properties?.layer_id;
|
|
294
312
|
if (layerId === void 0 || layerId === null) return null;
|
|
@@ -297,6 +315,459 @@ function getFeatureLayerId(feature) {
|
|
|
297
315
|
function escapeHtml(value) {
|
|
298
316
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
299
317
|
}
|
|
318
|
+
var DESCRIPTION_KEYS = /* @__PURE__ */ new Set(["descripcion", "description"]);
|
|
319
|
+
var POPUP_EXCLUDED_KEYS = /* @__PURE__ */ new Set(["geom", "geometry"]);
|
|
320
|
+
var POPUP_HEADER_KEYS = ["nombre", "name", "title", "titulo"];
|
|
321
|
+
var POPUP_STYLE_ID = "zenit-leaflet-popup-styles";
|
|
322
|
+
var DESKTOP_POPUP_DIMENSIONS = { maxWidth: 350, minWidth: 280, maxHeight: 480 };
|
|
323
|
+
var MOBILE_POPUP_DIMENSIONS = { maxWidth: 280, minWidth: 240, maxHeight: 380 };
|
|
324
|
+
var ZENIT_LEAFLET_POPUP_STYLES = `
|
|
325
|
+
/* ===== Zenit Leaflet Popup - Modern Professional Styling ===== */
|
|
326
|
+
|
|
327
|
+
/* Main popup wrapper */
|
|
328
|
+
.zenit-leaflet-popup .leaflet-popup-content-wrapper {
|
|
329
|
+
border-radius: 12px;
|
|
330
|
+
box-shadow:
|
|
331
|
+
0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
|
332
|
+
0 2px 4px -2px rgba(0, 0, 0, 0.1),
|
|
333
|
+
0 0 0 1px rgba(0, 0, 0, 0.05);
|
|
334
|
+
padding: 0;
|
|
335
|
+
background: #ffffff;
|
|
336
|
+
overflow: hidden;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/* Content area with scroll support */
|
|
340
|
+
.zenit-leaflet-popup .leaflet-popup-content {
|
|
341
|
+
margin: 0;
|
|
342
|
+
padding: 0;
|
|
343
|
+
font-size: 13px;
|
|
344
|
+
line-height: 1.5;
|
|
345
|
+
color: #374151;
|
|
346
|
+
min-width: 100%;
|
|
347
|
+
max-height: min(70vh, 480px);
|
|
348
|
+
overflow-y: auto;
|
|
349
|
+
overflow-x: hidden;
|
|
350
|
+
scrollbar-width: thin;
|
|
351
|
+
scrollbar-color: rgba(156, 163, 175, 0.5) transparent;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/* Popup tip/arrow shadow */
|
|
355
|
+
.zenit-leaflet-popup .leaflet-popup-tip-container {
|
|
356
|
+
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.zenit-leaflet-popup .leaflet-popup-tip {
|
|
360
|
+
background: #ffffff;
|
|
361
|
+
box-shadow: none;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/* Close button styling */
|
|
365
|
+
.zenit-leaflet-popup .leaflet-popup-close-button {
|
|
366
|
+
color: #9ca3af;
|
|
367
|
+
font-size: 18px;
|
|
368
|
+
font-weight: 400;
|
|
369
|
+
width: 28px;
|
|
370
|
+
height: 28px;
|
|
371
|
+
padding: 0;
|
|
372
|
+
margin: 8px 8px 0 0;
|
|
373
|
+
display: flex;
|
|
374
|
+
align-items: center;
|
|
375
|
+
justify-content: center;
|
|
376
|
+
border-radius: 6px;
|
|
377
|
+
transition: all 0.15s ease;
|
|
378
|
+
z-index: 10;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.zenit-leaflet-popup .leaflet-popup-close-button:hover {
|
|
382
|
+
color: #374151;
|
|
383
|
+
background-color: #f3f4f6;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
.zenit-leaflet-popup .leaflet-popup-close-button:active {
|
|
387
|
+
background-color: #e5e7eb;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/* Main card container */
|
|
391
|
+
.zenit-popup-card {
|
|
392
|
+
display: flex;
|
|
393
|
+
flex-direction: column;
|
|
394
|
+
gap: 0;
|
|
395
|
+
padding: 16px;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.zenit-popup-header {
|
|
399
|
+
padding-bottom: 12px;
|
|
400
|
+
border-bottom: 1px solid #e5e7eb;
|
|
401
|
+
margin-bottom: 4px;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.zenit-popup-title {
|
|
405
|
+
font-size: 14px;
|
|
406
|
+
font-weight: 700;
|
|
407
|
+
color: #111827;
|
|
408
|
+
letter-spacing: 0.01em;
|
|
409
|
+
line-height: 1.4;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/* Individual row styling with subtle separator */
|
|
413
|
+
.zenit-popup-row {
|
|
414
|
+
display: flex;
|
|
415
|
+
flex-direction: column;
|
|
416
|
+
gap: 2px;
|
|
417
|
+
padding: 10px 0;
|
|
418
|
+
border-bottom: 1px solid #f3f4f6;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.zenit-popup-row:first-child {
|
|
422
|
+
padding-top: 0;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.zenit-popup-row:last-child {
|
|
426
|
+
border-bottom: none;
|
|
427
|
+
padding-bottom: 0;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/* Label styling - small, gray, uppercase */
|
|
431
|
+
.zenit-popup-label {
|
|
432
|
+
font-size: 10px;
|
|
433
|
+
font-weight: 500;
|
|
434
|
+
color: #9ca3af;
|
|
435
|
+
text-transform: uppercase;
|
|
436
|
+
letter-spacing: 0.05em;
|
|
437
|
+
line-height: 1.4;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/* Value styling - darker, readable */
|
|
441
|
+
.zenit-popup-value {
|
|
442
|
+
font-size: 13px;
|
|
443
|
+
font-weight: 400;
|
|
444
|
+
color: #1f2937;
|
|
445
|
+
overflow-wrap: break-word;
|
|
446
|
+
word-break: break-word;
|
|
447
|
+
line-height: 1.5;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.zenit-popup-link {
|
|
451
|
+
color: #2563eb;
|
|
452
|
+
text-decoration: underline;
|
|
453
|
+
font-weight: 500;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.zenit-popup-link:hover {
|
|
457
|
+
color: #1d4ed8;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/* Special styling for description field */
|
|
461
|
+
.zenit-popup-row.zenit-popup-description {
|
|
462
|
+
background-color: #f9fafb;
|
|
463
|
+
margin: 0 -16px;
|
|
464
|
+
padding: 12px 16px;
|
|
465
|
+
border-bottom: 1px solid #e5e7eb;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
.zenit-popup-row.zenit-popup-description:first-child {
|
|
469
|
+
margin-top: 0;
|
|
470
|
+
border-radius: 0;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value {
|
|
474
|
+
font-size: 13px;
|
|
475
|
+
line-height: 1.6;
|
|
476
|
+
color: #374151;
|
|
477
|
+
max-height: 150px;
|
|
478
|
+
overflow-y: auto;
|
|
479
|
+
padding-right: 4px;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/* Preformatted text (JSON objects) */
|
|
483
|
+
.zenit-popup-pre {
|
|
484
|
+
margin: 0;
|
|
485
|
+
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
|
|
486
|
+
font-size: 11px;
|
|
487
|
+
white-space: pre-wrap;
|
|
488
|
+
word-break: break-word;
|
|
489
|
+
color: #4b5563;
|
|
490
|
+
background-color: #f9fafb;
|
|
491
|
+
padding: 8px;
|
|
492
|
+
border-radius: 6px;
|
|
493
|
+
border: 1px solid #e5e7eb;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/* Empty state styling */
|
|
497
|
+
.zenit-popup-empty {
|
|
498
|
+
font-size: 13px;
|
|
499
|
+
color: #9ca3af;
|
|
500
|
+
font-style: italic;
|
|
501
|
+
text-align: center;
|
|
502
|
+
padding: 20px 0;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/* Webkit scrollbar styling */
|
|
506
|
+
.zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar {
|
|
507
|
+
width: 6px;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
.zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar-track {
|
|
511
|
+
background: transparent;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
.zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar-thumb {
|
|
515
|
+
background-color: rgba(156, 163, 175, 0.4);
|
|
516
|
+
border-radius: 3px;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
.zenit-leaflet-popup .leaflet-popup-content::-webkit-scrollbar-thumb:hover {
|
|
520
|
+
background-color: rgba(107, 114, 128, 0.6);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/* Scrollbar for description field */
|
|
524
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value::-webkit-scrollbar {
|
|
525
|
+
width: 4px;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value::-webkit-scrollbar-track {
|
|
529
|
+
background: transparent;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value::-webkit-scrollbar-thumb {
|
|
533
|
+
background-color: rgba(156, 163, 175, 0.4);
|
|
534
|
+
border-radius: 2px;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/* ===== Responsive: Mobile (<640px) ===== */
|
|
538
|
+
@media (max-width: 640px) {
|
|
539
|
+
.zenit-leaflet-popup .leaflet-popup-content-wrapper {
|
|
540
|
+
border-radius: 10px;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
.zenit-leaflet-popup .leaflet-popup-close-button {
|
|
544
|
+
width: 26px;
|
|
545
|
+
height: 26px;
|
|
546
|
+
font-size: 16px;
|
|
547
|
+
margin: 6px 6px 0 0;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
.zenit-popup-card {
|
|
551
|
+
padding: 12px;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
.zenit-leaflet-popup .leaflet-popup-content {
|
|
555
|
+
max-height: min(65vh, 380px);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
.zenit-popup-header {
|
|
559
|
+
padding-bottom: 10px;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
.zenit-popup-title {
|
|
563
|
+
font-size: 13px;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
.zenit-popup-row {
|
|
567
|
+
padding: 8px 0;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
.zenit-popup-label {
|
|
571
|
+
font-size: 9px;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
.zenit-popup-value {
|
|
575
|
+
font-size: 12px;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
.zenit-popup-row.zenit-popup-description {
|
|
579
|
+
margin: 0 -12px;
|
|
580
|
+
padding: 10px 12px;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
.zenit-popup-row.zenit-popup-description .zenit-popup-value {
|
|
584
|
+
font-size: 12px;
|
|
585
|
+
max-height: 120px;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
.zenit-popup-pre {
|
|
589
|
+
font-size: 10px;
|
|
590
|
+
padding: 6px;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
.zenit-popup-empty {
|
|
594
|
+
font-size: 12px;
|
|
595
|
+
padding: 16px 0;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/* ===== Map tooltip styling ===== */
|
|
600
|
+
.zenit-map-tooltip {
|
|
601
|
+
background-color: rgba(31, 41, 55, 0.95);
|
|
602
|
+
border: none;
|
|
603
|
+
border-radius: 6px;
|
|
604
|
+
color: #ffffff;
|
|
605
|
+
font-size: 12px;
|
|
606
|
+
font-weight: 500;
|
|
607
|
+
padding: 6px 10px;
|
|
608
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
.zenit-map-tooltip::before {
|
|
612
|
+
border-top-color: rgba(31, 41, 55, 0.95);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
.polygon-label-tooltip {
|
|
616
|
+
z-index: 600 !important;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
.zenit-map-shell.popup-open .zenit-label-marker,
|
|
620
|
+
.zenit-map-shell.popup-open .polygon-label-tooltip,
|
|
621
|
+
.zenit-map-shell.popup-open .click-for-detail-hint,
|
|
622
|
+
.zenit-map-shell.popup-open .zenit-map-tooltip {
|
|
623
|
+
display: none !important;
|
|
624
|
+
}
|
|
625
|
+
`;
|
|
626
|
+
function ensurePopupStyles() {
|
|
627
|
+
if (typeof document === "undefined") return;
|
|
628
|
+
if (document.getElementById(POPUP_STYLE_ID)) return;
|
|
629
|
+
const styleTag = document.createElement("style");
|
|
630
|
+
styleTag.id = POPUP_STYLE_ID;
|
|
631
|
+
styleTag.textContent = ZENIT_LEAFLET_POPUP_STYLES;
|
|
632
|
+
document.head.appendChild(styleTag);
|
|
633
|
+
}
|
|
634
|
+
function getPopupDimensions() {
|
|
635
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
636
|
+
return DESKTOP_POPUP_DIMENSIONS;
|
|
637
|
+
}
|
|
638
|
+
return window.matchMedia("(max-width: 640px)").matches ? MOBILE_POPUP_DIMENSIONS : DESKTOP_POPUP_DIMENSIONS;
|
|
639
|
+
}
|
|
640
|
+
function normalizeDescriptionValue(value) {
|
|
641
|
+
if (value === void 0 || value === null) return null;
|
|
642
|
+
if (typeof value === "string") {
|
|
643
|
+
const trimmed = value.trim();
|
|
644
|
+
return trimmed ? trimmed : null;
|
|
645
|
+
}
|
|
646
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
647
|
+
return String(value);
|
|
648
|
+
}
|
|
649
|
+
return null;
|
|
650
|
+
}
|
|
651
|
+
function extractDescriptionValue(properties) {
|
|
652
|
+
if (!properties) return null;
|
|
653
|
+
const matches = Object.entries(properties).find(
|
|
654
|
+
([key]) => DESCRIPTION_KEYS.has(key.toLowerCase())
|
|
655
|
+
);
|
|
656
|
+
if (!matches) return null;
|
|
657
|
+
return normalizeDescriptionValue(matches[1]);
|
|
658
|
+
}
|
|
659
|
+
function safeJsonStringify(value) {
|
|
660
|
+
try {
|
|
661
|
+
const json = JSON.stringify(value, null, 2);
|
|
662
|
+
if (json !== void 0) return json;
|
|
663
|
+
} catch {
|
|
664
|
+
}
|
|
665
|
+
return String(value);
|
|
666
|
+
}
|
|
667
|
+
function renderPopupValue(value) {
|
|
668
|
+
if (value === null || value === void 0) {
|
|
669
|
+
return '<span class="zenit-popup-empty">Sin datos</span>';
|
|
670
|
+
}
|
|
671
|
+
if (value instanceof Date) {
|
|
672
|
+
return `<span>${escapeHtml(value.toLocaleDateString("es-GT"))}</span>`;
|
|
673
|
+
}
|
|
674
|
+
if (typeof value === "number") {
|
|
675
|
+
return `<span>${escapeHtml(value.toLocaleString("es-GT"))}</span>`;
|
|
676
|
+
}
|
|
677
|
+
if (typeof value === "string") {
|
|
678
|
+
const trimmed = value.trim();
|
|
679
|
+
const isLikelyDate = /^\d{4}-\d{2}-\d{2}/.test(trimmed) || trimmed.includes("T");
|
|
680
|
+
if (isLikelyDate) {
|
|
681
|
+
const parsed = Date.parse(trimmed);
|
|
682
|
+
if (!Number.isNaN(parsed)) {
|
|
683
|
+
return `<span>${escapeHtml(new Date(parsed).toLocaleDateString("es-GT"))}</span>`;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
try {
|
|
687
|
+
const parsedUrl = new URL(trimmed);
|
|
688
|
+
if (parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:") {
|
|
689
|
+
const safeHref = escapeHtml(parsedUrl.toString());
|
|
690
|
+
return `<a class="zenit-popup-link" href="${safeHref}" target="_blank" rel="noopener noreferrer">${safeHref}</a>`;
|
|
691
|
+
}
|
|
692
|
+
} catch {
|
|
693
|
+
}
|
|
694
|
+
return `<span>${escapeHtml(trimmed || value)}</span>`;
|
|
695
|
+
}
|
|
696
|
+
if (typeof value === "object") {
|
|
697
|
+
const json = safeJsonStringify(value);
|
|
698
|
+
return `<pre class="zenit-popup-pre">${escapeHtml(json)}</pre>`;
|
|
699
|
+
}
|
|
700
|
+
return `<span>${escapeHtml(String(value))}</span>`;
|
|
701
|
+
}
|
|
702
|
+
function shouldIncludePopupEntry(key, value) {
|
|
703
|
+
if (!key) return false;
|
|
704
|
+
const normalized = key.trim().toLowerCase();
|
|
705
|
+
if (!normalized) return false;
|
|
706
|
+
if (normalized.startsWith("_")) return false;
|
|
707
|
+
if (POPUP_EXCLUDED_KEYS.has(normalized)) return false;
|
|
708
|
+
if (value === null || value === void 0) return false;
|
|
709
|
+
if (typeof value === "string" && !value.trim()) return false;
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
712
|
+
function isDescriptionKey(key) {
|
|
713
|
+
const normalized = key.trim().toLowerCase();
|
|
714
|
+
return DESCRIPTION_KEYS.has(normalized);
|
|
715
|
+
}
|
|
716
|
+
function extractPopupHeader(properties) {
|
|
717
|
+
if (!properties) return null;
|
|
718
|
+
const entry = Object.entries(properties).find(
|
|
719
|
+
(candidate) => {
|
|
720
|
+
const [key, value] = candidate;
|
|
721
|
+
return POPUP_HEADER_KEYS.includes(key.trim().toLowerCase()) && typeof value === "string" && value.trim().length > 0;
|
|
722
|
+
}
|
|
723
|
+
);
|
|
724
|
+
if (!entry) return null;
|
|
725
|
+
return entry[1].trim();
|
|
726
|
+
}
|
|
727
|
+
function formatLabel(key) {
|
|
728
|
+
return key.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").trim();
|
|
729
|
+
}
|
|
730
|
+
function createPopupContent(properties) {
|
|
731
|
+
const headerText = extractPopupHeader(properties);
|
|
732
|
+
const entries = Object.entries(properties).filter(([key, value]) => {
|
|
733
|
+
if (!shouldIncludePopupEntry(key, value)) return false;
|
|
734
|
+
if (headerText && POPUP_HEADER_KEYS.includes(key.trim().toLowerCase())) {
|
|
735
|
+
return false;
|
|
736
|
+
}
|
|
737
|
+
return true;
|
|
738
|
+
});
|
|
739
|
+
if (entries.length === 0) {
|
|
740
|
+
return `<div class="zenit-popup-card"><div class="zenit-popup-empty">Sin datos disponibles</div></div>`;
|
|
741
|
+
}
|
|
742
|
+
const descriptionEntry = entries.find(([key]) => isDescriptionKey(key));
|
|
743
|
+
const otherEntries = entries.filter(([key]) => !isDescriptionKey(key));
|
|
744
|
+
let rowsHtml = "";
|
|
745
|
+
if (descriptionEntry) {
|
|
746
|
+
const [key, value] = descriptionEntry;
|
|
747
|
+
const label = escapeHtml(formatLabel(key));
|
|
748
|
+
const valueHtml = renderPopupValue(value);
|
|
749
|
+
rowsHtml += `
|
|
750
|
+
<div class="zenit-popup-row zenit-popup-description">
|
|
751
|
+
<div class="zenit-popup-label">${label}</div>
|
|
752
|
+
<div class="zenit-popup-value">${valueHtml}</div>
|
|
753
|
+
</div>
|
|
754
|
+
`;
|
|
755
|
+
}
|
|
756
|
+
rowsHtml += otherEntries.map(([key, value]) => {
|
|
757
|
+
const label = escapeHtml(formatLabel(key));
|
|
758
|
+
const valueHtml = renderPopupValue(value);
|
|
759
|
+
return `
|
|
760
|
+
<div class="zenit-popup-row">
|
|
761
|
+
<div class="zenit-popup-label">${label}</div>
|
|
762
|
+
<div class="zenit-popup-value">${valueHtml}</div>
|
|
763
|
+
</div>
|
|
764
|
+
`;
|
|
765
|
+
}).join("");
|
|
766
|
+
const headerHtml = headerText ? `<div class="zenit-popup-header"><div class="zenit-popup-title">${escapeHtml(
|
|
767
|
+
headerText
|
|
768
|
+
)}</div></div>` : "";
|
|
769
|
+
return `<div class="zenit-popup-card">${headerHtml}${rowsHtml}</div>`;
|
|
770
|
+
}
|
|
300
771
|
function withAlpha(color, alpha) {
|
|
301
772
|
const trimmed = color.trim();
|
|
302
773
|
if (trimmed.startsWith("#")) {
|
|
@@ -365,40 +836,39 @@ function getFeatureStyleOverrides(feature) {
|
|
|
365
836
|
function buildFeaturePopupHtml(feature) {
|
|
366
837
|
const properties = feature?.properties;
|
|
367
838
|
if (!properties) return null;
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
if (
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
return `<div>${parts.join("")}</div>`;
|
|
839
|
+
const rendered = createPopupContent(properties);
|
|
840
|
+
return rendered ? rendered : null;
|
|
841
|
+
}
|
|
842
|
+
var POINT_GEOMETRY_TYPES = /* @__PURE__ */ new Set(["Point", "MultiPoint"]);
|
|
843
|
+
function getGeometryType(feature) {
|
|
844
|
+
const t = feature?.geometry?.type;
|
|
845
|
+
return typeof t === "string" ? t : null;
|
|
846
|
+
}
|
|
847
|
+
function isPointGeometry(feature) {
|
|
848
|
+
const geometryType = getGeometryType(feature);
|
|
849
|
+
return geometryType !== null && POINT_GEOMETRY_TYPES.has(geometryType);
|
|
850
|
+
}
|
|
851
|
+
function isNonPointGeometry(feature) {
|
|
852
|
+
const geometryType = getGeometryType(feature);
|
|
853
|
+
return geometryType !== null && !POINT_GEOMETRY_TYPES.has(geometryType);
|
|
854
|
+
}
|
|
855
|
+
function buildFeatureCollection(features) {
|
|
856
|
+
return {
|
|
857
|
+
type: "FeatureCollection",
|
|
858
|
+
features
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
function pickIntersectFeature(baseFeature, candidates) {
|
|
862
|
+
if (!Array.isArray(candidates) || candidates.length === 0) return null;
|
|
863
|
+
const baseId = baseFeature?.id;
|
|
864
|
+
if (baseId !== void 0 && baseId !== null) {
|
|
865
|
+
const matchById = candidates.find((candidate) => candidate?.id === baseId);
|
|
866
|
+
if (matchById) return matchById;
|
|
867
|
+
}
|
|
868
|
+
const matchWithDescription = candidates.find(
|
|
869
|
+
(candidate) => extractDescriptionValue(candidate?.properties)
|
|
870
|
+
);
|
|
871
|
+
return matchWithDescription ?? candidates[0];
|
|
402
872
|
}
|
|
403
873
|
function normalizeCenterTuple(center) {
|
|
404
874
|
if (!center) return null;
|
|
@@ -519,7 +989,9 @@ var ZenitMap = forwardRef(({
|
|
|
519
989
|
const [loadingMap, setLoadingMap] = useState(false);
|
|
520
990
|
const [mapError, setMapError] = useState(null);
|
|
521
991
|
const [mapInstance, setMapInstance] = useState(null);
|
|
992
|
+
const [panesReady, setPanesReady] = useState(false);
|
|
522
993
|
const [currentZoom, setCurrentZoom] = useState(initialZoom ?? DEFAULT_ZOOM);
|
|
994
|
+
const [isPopupOpen, setIsPopupOpen] = useState(false);
|
|
523
995
|
const [isMobile, setIsMobile] = useState(() => {
|
|
524
996
|
if (typeof window === "undefined") return false;
|
|
525
997
|
return window.matchMedia("(max-width: 768px)").matches;
|
|
@@ -543,6 +1015,36 @@ var ZenitMap = forwardRef(({
|
|
|
543
1015
|
}
|
|
544
1016
|
return;
|
|
545
1017
|
}, []);
|
|
1018
|
+
useEffect(() => {
|
|
1019
|
+
if (featureInfoMode === "popup") {
|
|
1020
|
+
ensurePopupStyles();
|
|
1021
|
+
}
|
|
1022
|
+
}, [featureInfoMode]);
|
|
1023
|
+
useEffect(() => {
|
|
1024
|
+
if (featureInfoMode !== "popup") {
|
|
1025
|
+
setIsPopupOpen(false);
|
|
1026
|
+
}
|
|
1027
|
+
}, [featureInfoMode]);
|
|
1028
|
+
useEffect(() => {
|
|
1029
|
+
if (!mapInstance) return;
|
|
1030
|
+
const popupPane = mapInstance.getPane("popupPane");
|
|
1031
|
+
if (popupPane) {
|
|
1032
|
+
popupPane.style.zIndex = "800";
|
|
1033
|
+
}
|
|
1034
|
+
const labelsPane = mapInstance.getPane(LABELS_PANE_NAME) ?? mapInstance.createPane(LABELS_PANE_NAME);
|
|
1035
|
+
labelsPane.style.zIndex = "600";
|
|
1036
|
+
}, [mapInstance]);
|
|
1037
|
+
useEffect(() => {
|
|
1038
|
+
if (!mapInstance) return;
|
|
1039
|
+
const handlePopupOpen = () => setIsPopupOpen(true);
|
|
1040
|
+
const handlePopupClose = () => setIsPopupOpen(false);
|
|
1041
|
+
mapInstance.on("popupopen", handlePopupOpen);
|
|
1042
|
+
mapInstance.on("popupclose", handlePopupClose);
|
|
1043
|
+
return () => {
|
|
1044
|
+
mapInstance.off("popupopen", handlePopupOpen);
|
|
1045
|
+
mapInstance.off("popupclose", handlePopupClose);
|
|
1046
|
+
};
|
|
1047
|
+
}, [mapInstance]);
|
|
546
1048
|
const layerStyleIndex = useMemo(() => {
|
|
547
1049
|
const index = /* @__PURE__ */ new Map();
|
|
548
1050
|
(map?.mapLayers ?? []).forEach((entry) => {
|
|
@@ -833,16 +1335,21 @@ var ZenitMap = forwardRef(({
|
|
|
833
1335
|
(targetMap, targetLayers) => {
|
|
834
1336
|
const baseZIndex = 400;
|
|
835
1337
|
targetLayers.forEach((layer) => {
|
|
836
|
-
const paneName = `zenit-layer-${layer.layerId}`;
|
|
837
|
-
const pane = targetMap.getPane(paneName) ?? targetMap.createPane(paneName);
|
|
838
1338
|
const order = Number.isFinite(layer.displayOrder) ? layer.displayOrder : 0;
|
|
839
|
-
|
|
1339
|
+
const orderOffset = Math.max(0, Math.min(order, 150));
|
|
1340
|
+
const fillPaneName = `zenit-layer-${layer.layerId}-fill`;
|
|
1341
|
+
const pointPaneName = `zenit-layer-${layer.layerId}-points`;
|
|
1342
|
+
const fillPane = targetMap.getPane(fillPaneName) ?? targetMap.createPane(fillPaneName);
|
|
1343
|
+
const pointPane = targetMap.getPane(pointPaneName) ?? targetMap.createPane(pointPaneName);
|
|
1344
|
+
fillPane.style.zIndex = String(baseZIndex + orderOffset);
|
|
1345
|
+
pointPane.style.zIndex = String(baseZIndex + orderOffset + 100);
|
|
840
1346
|
});
|
|
841
1347
|
},
|
|
842
1348
|
[]
|
|
843
1349
|
);
|
|
844
1350
|
const handleMapReady = useCallback(
|
|
845
1351
|
(instance) => {
|
|
1352
|
+
setPanesReady(false);
|
|
846
1353
|
setMapInstance(instance);
|
|
847
1354
|
onMapReady?.(instance);
|
|
848
1355
|
},
|
|
@@ -850,6 +1357,7 @@ var ZenitMap = forwardRef(({
|
|
|
850
1357
|
);
|
|
851
1358
|
useEffect(() => {
|
|
852
1359
|
if (!mapInstance) {
|
|
1360
|
+
setPanesReady(false);
|
|
853
1361
|
return;
|
|
854
1362
|
}
|
|
855
1363
|
if (orderedLayers.length === 0) {
|
|
@@ -860,6 +1368,12 @@ var ZenitMap = forwardRef(({
|
|
|
860
1368
|
displayOrder: layer.displayOrder
|
|
861
1369
|
}));
|
|
862
1370
|
ensureLayerPanes(mapInstance, layerTargets);
|
|
1371
|
+
const first = layerTargets[0];
|
|
1372
|
+
const testPane = mapInstance.getPane(`zenit-layer-${first.layerId}-fill`);
|
|
1373
|
+
const labelsPane = mapInstance.getPane(LABELS_PANE_NAME);
|
|
1374
|
+
if (testPane && labelsPane) {
|
|
1375
|
+
setPanesReady(true);
|
|
1376
|
+
}
|
|
863
1377
|
}, [mapInstance, orderedLayers, ensureLayerPanes]);
|
|
864
1378
|
const overlayOnEachFeature = useMemo(() => {
|
|
865
1379
|
return (feature, layer) => {
|
|
@@ -877,7 +1391,17 @@ var ZenitMap = forwardRef(({
|
|
|
877
1391
|
if (featureInfoMode === "popup") {
|
|
878
1392
|
const content = buildFeaturePopupHtml(feature);
|
|
879
1393
|
if (content) {
|
|
880
|
-
|
|
1394
|
+
const { maxWidth, minWidth, maxHeight } = getPopupDimensions();
|
|
1395
|
+
layer.bindPopup(content, {
|
|
1396
|
+
maxWidth,
|
|
1397
|
+
minWidth,
|
|
1398
|
+
maxHeight,
|
|
1399
|
+
className: "zenit-leaflet-popup custom-leaflet-popup",
|
|
1400
|
+
autoPan: true,
|
|
1401
|
+
closeButton: true,
|
|
1402
|
+
keepInView: true,
|
|
1403
|
+
offset: L.point(0, -24)
|
|
1404
|
+
});
|
|
881
1405
|
}
|
|
882
1406
|
}
|
|
883
1407
|
if (isPointFeature && layer.bindTooltip) {
|
|
@@ -888,7 +1412,38 @@ var ZenitMap = forwardRef(({
|
|
|
888
1412
|
className: "zenit-map-tooltip"
|
|
889
1413
|
});
|
|
890
1414
|
}
|
|
891
|
-
layer.on("click", () =>
|
|
1415
|
+
layer.on("click", () => {
|
|
1416
|
+
if (featureInfoMode === "popup" && client && layerId !== void 0 && !extractDescriptionValue(feature?.properties) && feature?.geometry) {
|
|
1417
|
+
const trackedFeature = feature;
|
|
1418
|
+
if (!trackedFeature.__zenit_popup_loaded) {
|
|
1419
|
+
trackedFeature.__zenit_popup_loaded = true;
|
|
1420
|
+
client.layers.getLayerGeoJsonIntersect({
|
|
1421
|
+
id: layerId,
|
|
1422
|
+
geometry: feature.geometry
|
|
1423
|
+
}).then((response) => {
|
|
1424
|
+
const geo = extractGeoJsonFeatureCollection(response);
|
|
1425
|
+
const candidates = geo?.features ?? [];
|
|
1426
|
+
const resolved = pickIntersectFeature(feature, candidates);
|
|
1427
|
+
if (!resolved?.properties) return;
|
|
1428
|
+
const mergedProperties = {
|
|
1429
|
+
...trackedFeature.properties ?? {},
|
|
1430
|
+
...resolved.properties
|
|
1431
|
+
};
|
|
1432
|
+
trackedFeature.properties = mergedProperties;
|
|
1433
|
+
const updatedHtml = buildFeaturePopupHtml({
|
|
1434
|
+
...feature,
|
|
1435
|
+
properties: mergedProperties
|
|
1436
|
+
});
|
|
1437
|
+
if (updatedHtml && layer.setPopupContent) {
|
|
1438
|
+
layer.setPopupContent(updatedHtml);
|
|
1439
|
+
}
|
|
1440
|
+
}).catch(() => {
|
|
1441
|
+
trackedFeature.__zenit_popup_loaded = false;
|
|
1442
|
+
});
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
onFeatureClick?.(feature, layerId);
|
|
1446
|
+
});
|
|
892
1447
|
layer.on("mouseover", () => {
|
|
893
1448
|
if (layer instanceof L.Path && originalStyle) {
|
|
894
1449
|
layer.setStyle({
|
|
@@ -912,7 +1467,7 @@ var ZenitMap = forwardRef(({
|
|
|
912
1467
|
}
|
|
913
1468
|
});
|
|
914
1469
|
};
|
|
915
|
-
}, [featureInfoMode, onFeatureClick, onFeatureHover]);
|
|
1470
|
+
}, [client, featureInfoMode, onFeatureClick, onFeatureHover]);
|
|
916
1471
|
const buildLayerStyle = (layerId, baseOpacity, feature, layerType) => {
|
|
917
1472
|
const style = resolveLayerStyle(layerId);
|
|
918
1473
|
const featureStyleOverrides = getFeatureStyleOverrides(feature);
|
|
@@ -1070,68 +1625,93 @@ var ZenitMap = forwardRef(({
|
|
|
1070
1625
|
boxSizing: "border-box"
|
|
1071
1626
|
},
|
|
1072
1627
|
children: [
|
|
1073
|
-
/* @__PURE__ */ jsx(
|
|
1074
|
-
|
|
1628
|
+
/* @__PURE__ */ jsx(
|
|
1629
|
+
"div",
|
|
1075
1630
|
{
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1631
|
+
className: `zenit-map-shell${isPopupOpen ? " popup-open" : ""}`,
|
|
1632
|
+
style: { flex: 1, position: "relative" },
|
|
1633
|
+
children: /* @__PURE__ */ jsxs(
|
|
1634
|
+
MapContainer,
|
|
1635
|
+
{
|
|
1636
|
+
center,
|
|
1637
|
+
zoom,
|
|
1638
|
+
style: { height: "100%", width: "100%" },
|
|
1639
|
+
scrollWheelZoom: true,
|
|
1640
|
+
zoomControl: false,
|
|
1641
|
+
children: [
|
|
1642
|
+
/* @__PURE__ */ jsx(
|
|
1643
|
+
TileLayer,
|
|
1644
|
+
{
|
|
1645
|
+
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
|
|
1646
|
+
attribution: "\xA9 OpenStreetMap contributors"
|
|
1647
|
+
}
|
|
1648
|
+
),
|
|
1649
|
+
/* @__PURE__ */ jsx(ZoomControl, { position: "topright" }),
|
|
1650
|
+
/* @__PURE__ */ jsx(MapInstanceBridge, { onReady: handleMapReady }),
|
|
1651
|
+
/* @__PURE__ */ jsx(FitToBounds, { bbox: explicitZoomBBox ?? void 0 }),
|
|
1652
|
+
/* @__PURE__ */ jsx(AutoFitToBounds, { bbox: autoZoomBBox ?? void 0, enabled: !explicitZoomBBox }),
|
|
1653
|
+
/* @__PURE__ */ jsx(ZoomBasedOpacityHandler, { onZoomChange: handleZoomChange }),
|
|
1654
|
+
orderedLayers.map((layerState) => {
|
|
1655
|
+
const baseOpacity = layerState.effective?.baseOpacity ?? layerState.effective?.opacity ?? 1;
|
|
1656
|
+
const fillPaneName = `zenit-layer-${layerState.mapLayer.layerId}-fill`;
|
|
1657
|
+
const pointsPaneName = `zenit-layer-${layerState.mapLayer.layerId}-points`;
|
|
1658
|
+
const layerType = layerState.layer?.layerType ?? layerState.mapLayer.layerType ?? void 0;
|
|
1659
|
+
const data = layerState.data?.features ?? [];
|
|
1660
|
+
const fillFeatures = data.filter(isNonPointGeometry);
|
|
1661
|
+
const pointFeatures = data.filter(isPointGeometry);
|
|
1662
|
+
const fillData = fillFeatures.length > 0 ? buildFeatureCollection(fillFeatures) : null;
|
|
1663
|
+
const pointsData = pointFeatures.length > 0 ? buildFeatureCollection(pointFeatures) : null;
|
|
1664
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
1665
|
+
fillData && /* @__PURE__ */ jsx(
|
|
1666
|
+
GeoJSON,
|
|
1667
|
+
{
|
|
1668
|
+
data: fillData,
|
|
1669
|
+
pane: panesReady && mapInstance?.getPane(fillPaneName) ? fillPaneName : void 0,
|
|
1670
|
+
style: (feature) => buildLayerStyle(layerState.mapLayer.layerId, baseOpacity, feature, layerType),
|
|
1671
|
+
onEachFeature: overlayOnEachFeature
|
|
1672
|
+
}
|
|
1673
|
+
),
|
|
1674
|
+
pointsData && /* @__PURE__ */ jsx(
|
|
1675
|
+
GeoJSON,
|
|
1676
|
+
{
|
|
1677
|
+
data: pointsData,
|
|
1678
|
+
pane: panesReady && mapInstance?.getPane(pointsPaneName) ? pointsPaneName : void 0,
|
|
1679
|
+
pointToLayer: (feature, latlng) => L.circleMarker(latlng, {
|
|
1680
|
+
radius: isMobile ? 8 : 6,
|
|
1681
|
+
...buildLayerStyle(layerState.mapLayer.layerId, baseOpacity, feature, layerType)
|
|
1682
|
+
}),
|
|
1683
|
+
onEachFeature: overlayOnEachFeature
|
|
1684
|
+
}
|
|
1685
|
+
),
|
|
1686
|
+
panesReady && mapInstance?.getPane(LABELS_PANE_NAME) ? labelMarkers.filter(
|
|
1687
|
+
(marker) => String(marker.layerId) === String(layerState.mapLayer.layerId)
|
|
1688
|
+
).map((marker) => /* @__PURE__ */ jsx(
|
|
1689
|
+
Marker,
|
|
1690
|
+
{
|
|
1691
|
+
position: marker.position,
|
|
1692
|
+
icon: buildLabelIcon(marker.label, marker.opacity, marker.color),
|
|
1693
|
+
interactive: false,
|
|
1694
|
+
pane: LABELS_PANE_NAME
|
|
1695
|
+
},
|
|
1696
|
+
marker.key
|
|
1697
|
+
)) : null
|
|
1698
|
+
] }, layerState.mapLayer.layerId.toString());
|
|
1699
|
+
}),
|
|
1700
|
+
overlayGeojson && /* @__PURE__ */ jsx(
|
|
1701
|
+
GeoJSON,
|
|
1702
|
+
{
|
|
1703
|
+
data: overlayGeojson,
|
|
1704
|
+
style: overlayStyleFunction,
|
|
1705
|
+
onEachFeature: overlayOnEachFeature
|
|
1706
|
+
},
|
|
1707
|
+
"zenit-overlay-geojson"
|
|
1708
|
+
)
|
|
1709
|
+
]
|
|
1710
|
+
},
|
|
1711
|
+
String(mapId)
|
|
1712
|
+
)
|
|
1713
|
+
}
|
|
1714
|
+
),
|
|
1135
1715
|
showLayerPanel && decoratedLayers.length > 0 && /* @__PURE__ */ jsxs(
|
|
1136
1716
|
"div",
|
|
1137
1717
|
{
|
|
@@ -2543,9 +3123,19 @@ var FloatingChatBox = ({
|
|
|
2543
3123
|
getAccessToken,
|
|
2544
3124
|
onActionClick,
|
|
2545
3125
|
onOpenChange,
|
|
2546
|
-
hideButton
|
|
3126
|
+
hideButton,
|
|
3127
|
+
open: openProp
|
|
2547
3128
|
}) => {
|
|
2548
|
-
const
|
|
3129
|
+
const isControlled = openProp !== void 0;
|
|
3130
|
+
const [internalOpen, setInternalOpen] = useState4(false);
|
|
3131
|
+
const open = isControlled ? openProp : internalOpen;
|
|
3132
|
+
const setOpen = useCallback3((value) => {
|
|
3133
|
+
const newValue = typeof value === "function" ? value(open) : value;
|
|
3134
|
+
if (!isControlled) {
|
|
3135
|
+
setInternalOpen(newValue);
|
|
3136
|
+
}
|
|
3137
|
+
onOpenChange?.(newValue);
|
|
3138
|
+
}, [isControlled, open, onOpenChange]);
|
|
2549
3139
|
const [expanded, setExpanded] = useState4(false);
|
|
2550
3140
|
const [messages, setMessages] = useState4([]);
|
|
2551
3141
|
const [inputValue, setInputValue] = useState4("");
|
|
@@ -2562,9 +3152,6 @@ var FloatingChatBox = ({
|
|
|
2562
3152
|
}, [accessToken, baseUrl, getAccessToken]);
|
|
2563
3153
|
const { sendMessage: sendMessage2, isStreaming, streamingText, completeResponse } = useSendMessageStream(chatConfig);
|
|
2564
3154
|
const canSend = Boolean(mapId) && Boolean(baseUrl) && inputValue.trim().length > 0 && !isStreaming;
|
|
2565
|
-
useEffect3(() => {
|
|
2566
|
-
onOpenChange?.(open);
|
|
2567
|
-
}, [open, onOpenChange]);
|
|
2568
3155
|
useEffect3(() => {
|
|
2569
3156
|
if (open && isMobile) {
|
|
2570
3157
|
setExpanded(true);
|
|
@@ -2717,6 +3304,13 @@ var FloatingChatBox = ({
|
|
|
2717
3304
|
] }, index)) })
|
|
2718
3305
|
] });
|
|
2719
3306
|
};
|
|
3307
|
+
const handleActionClick = useCallback3((action) => {
|
|
3308
|
+
if (isStreaming) return;
|
|
3309
|
+
setOpen(false);
|
|
3310
|
+
requestAnimationFrame(() => {
|
|
3311
|
+
onActionClick?.(action);
|
|
3312
|
+
});
|
|
3313
|
+
}, [isStreaming, setOpen, onActionClick]);
|
|
2720
3314
|
const renderActions = (response) => {
|
|
2721
3315
|
if (!response?.suggestedActions?.length) return null;
|
|
2722
3316
|
return /* @__PURE__ */ jsxs4("div", { style: styles.actionsSection, children: [
|
|
@@ -2730,7 +3324,7 @@ var FloatingChatBox = ({
|
|
|
2730
3324
|
opacity: isStreaming ? 0.5 : 1,
|
|
2731
3325
|
cursor: isStreaming ? "not-allowed" : "pointer"
|
|
2732
3326
|
},
|
|
2733
|
-
onClick: () =>
|
|
3327
|
+
onClick: () => handleActionClick(action),
|
|
2734
3328
|
disabled: isStreaming,
|
|
2735
3329
|
onMouseEnter: (e) => {
|
|
2736
3330
|
if (!isStreaming) {
|
|
@@ -3057,4 +3651,4 @@ export {
|
|
|
3057
3651
|
useSendMessageStream,
|
|
3058
3652
|
FloatingChatBox
|
|
3059
3653
|
};
|
|
3060
|
-
//# sourceMappingURL=chunk-
|
|
3654
|
+
//# sourceMappingURL=chunk-52CLFD4L.mjs.map
|