@mapka/maplibre-gl-sdk 0.16.0 → 0.16.3

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.
Files changed (124) hide show
  1. package/README.md +10 -5
  2. package/lib/.buildInfo.json +1 -1
  3. package/lib/components/ImageCarousel.d.ts +7 -0
  4. package/lib/components/ImageCarousel.d.ts.map +1 -0
  5. package/lib/components/ImageCarousel.js +22 -0
  6. package/lib/components/PopupContent.d.ts +5 -1
  7. package/lib/components/PopupContent.d.ts.map +1 -1
  8. package/lib/components/PopupContent.js +15 -37
  9. package/lib/components/PopupDataRows.d.ts +7 -0
  10. package/lib/components/PopupDataRows.d.ts.map +1 -0
  11. package/lib/components/PopupDataRows.js +22 -0
  12. package/lib/components/PopupList.d.ts +10 -0
  13. package/lib/components/PopupList.d.ts.map +1 -0
  14. package/lib/components/PopupList.js +8 -0
  15. package/lib/components/PopupListItem.d.ts +13 -0
  16. package/lib/components/PopupListItem.d.ts.map +1 -0
  17. package/lib/components/PopupListItem.js +11 -0
  18. package/lib/components/icons/ChevronLeftIcon.d.ts +2 -0
  19. package/lib/components/icons/ChevronLeftIcon.d.ts.map +1 -0
  20. package/lib/components/icons/ChevronLeftIcon.js +4 -0
  21. package/lib/components/icons/ChevronRightIcon.d.ts +2 -0
  22. package/lib/components/icons/ChevronRightIcon.d.ts.map +1 -0
  23. package/lib/components/icons/ChevronRightIcon.js +4 -0
  24. package/lib/components/icons/CircleIcon.d.ts.map +1 -0
  25. package/lib/components/icons/CloseIcon.d.ts +2 -0
  26. package/lib/components/icons/CloseIcon.d.ts.map +1 -0
  27. package/lib/components/icons/CloseIcon.js +4 -0
  28. package/lib/components/icons/DownloadIcon.d.ts.map +1 -0
  29. package/lib/components/icons/FreehandIcon.d.ts.map +1 -0
  30. package/lib/components/icons/HeartIcon.d.ts +4 -0
  31. package/lib/components/icons/HeartIcon.d.ts.map +1 -0
  32. package/lib/components/icons/HeartIcon.js +4 -0
  33. package/lib/components/icons/LineIcon.d.ts.map +1 -0
  34. package/lib/components/icons/PencilIcon.d.ts.map +1 -0
  35. package/lib/components/icons/PolygonIcon.d.ts.map +1 -0
  36. package/lib/components/icons/ProgressDownIcon.d.ts +2 -0
  37. package/lib/components/icons/ProgressDownIcon.d.ts.map +1 -0
  38. package/lib/components/icons/RectangleIcon.d.ts.map +1 -0
  39. package/lib/components/icons/SelectIcon.d.ts.map +1 -0
  40. package/lib/components/icons/TrashIcon.d.ts.map +1 -0
  41. package/lib/controls/MapkaDrawControl.js +7 -7
  42. package/lib/controls/MapkaExportControl.js +2 -2
  43. package/lib/map.d.ts +8 -7
  44. package/lib/map.d.ts.map +1 -1
  45. package/lib/map.js +15 -9
  46. package/lib/modules/layerPopup.d.ts +2 -1
  47. package/lib/modules/layerPopup.d.ts.map +1 -1
  48. package/lib/modules/layerPopup.js +22 -15
  49. package/lib/modules/markers.d.ts +5 -0
  50. package/lib/modules/markers.d.ts.map +1 -1
  51. package/lib/modules/markers.js +21 -16
  52. package/lib/modules/popup.d.ts +3 -10
  53. package/lib/modules/popup.d.ts.map +1 -1
  54. package/lib/modules/popup.js +116 -100
  55. package/lib/modules/popupGroups.d.ts +14 -0
  56. package/lib/modules/popupGroups.d.ts.map +1 -0
  57. package/lib/modules/popupGroups.js +130 -0
  58. package/lib/styles.css +1 -0
  59. package/lib/types/popup.d.ts +10 -1
  60. package/lib/types/popup.d.ts.map +1 -1
  61. package/package.json +26 -7
  62. package/src/components/ImageCarousel.css +73 -0
  63. package/src/components/ImageCarousel.tsx +76 -0
  64. package/src/components/PopupContent.css +64 -174
  65. package/src/components/PopupContent.tsx +32 -202
  66. package/src/components/PopupDataRows.css +41 -0
  67. package/src/components/PopupDataRows.tsx +39 -0
  68. package/src/components/PopupList.css +24 -0
  69. package/src/components/PopupList.tsx +27 -0
  70. package/src/components/PopupListItem.css +61 -0
  71. package/src/components/PopupListItem.tsx +40 -0
  72. package/src/components/icons/ChevronLeftIcon.tsx +20 -0
  73. package/src/components/icons/ChevronRightIcon.tsx +20 -0
  74. package/src/components/icons/CloseIcon.tsx +13 -0
  75. package/src/components/icons/HeartIcon.tsx +18 -0
  76. package/src/components/{ProgressDownIcon.tsx → icons/ProgressDownIcon.tsx} +0 -3
  77. package/src/controls/MapkaDrawControl.tsx +7 -7
  78. package/src/controls/MapkaExportControl.tsx +2 -2
  79. package/src/map.ts +22 -20
  80. package/src/modules/layerPopup.ts +32 -21
  81. package/src/modules/markers.ts +26 -16
  82. package/src/modules/popup.tsx +129 -112
  83. package/src/modules/popupGroups.ts +190 -0
  84. package/src/styles.css +4 -0
  85. package/src/types/popup.ts +12 -1
  86. package/lib/components/CircleIcon.d.ts.map +0 -1
  87. package/lib/components/DownloadIcon.d.ts.map +0 -1
  88. package/lib/components/FreehandIcon.d.ts.map +0 -1
  89. package/lib/components/LineIcon.d.ts.map +0 -1
  90. package/lib/components/PencilIcon.d.ts.map +0 -1
  91. package/lib/components/PolygonIcon.d.ts.map +0 -1
  92. package/lib/components/ProgressDownIcon.d.ts +0 -4
  93. package/lib/components/ProgressDownIcon.d.ts.map +0 -1
  94. package/lib/components/RectangleIcon.d.ts.map +0 -1
  95. package/lib/components/SelectIcon.d.ts.map +0 -1
  96. package/lib/components/TrashIcon.d.ts.map +0 -1
  97. /package/lib/components/{CircleIcon.d.ts → icons/CircleIcon.d.ts} +0 -0
  98. /package/lib/components/{CircleIcon.js → icons/CircleIcon.js} +0 -0
  99. /package/lib/components/{DownloadIcon.d.ts → icons/DownloadIcon.d.ts} +0 -0
  100. /package/lib/components/{DownloadIcon.js → icons/DownloadIcon.js} +0 -0
  101. /package/lib/components/{FreehandIcon.d.ts → icons/FreehandIcon.d.ts} +0 -0
  102. /package/lib/components/{FreehandIcon.js → icons/FreehandIcon.js} +0 -0
  103. /package/lib/components/{LineIcon.d.ts → icons/LineIcon.d.ts} +0 -0
  104. /package/lib/components/{LineIcon.js → icons/LineIcon.js} +0 -0
  105. /package/lib/components/{PencilIcon.d.ts → icons/PencilIcon.d.ts} +0 -0
  106. /package/lib/components/{PencilIcon.js → icons/PencilIcon.js} +0 -0
  107. /package/lib/components/{PolygonIcon.d.ts → icons/PolygonIcon.d.ts} +0 -0
  108. /package/lib/components/{PolygonIcon.js → icons/PolygonIcon.js} +0 -0
  109. /package/lib/components/{ProgressDownIcon.js → icons/ProgressDownIcon.js} +0 -0
  110. /package/lib/components/{RectangleIcon.d.ts → icons/RectangleIcon.d.ts} +0 -0
  111. /package/lib/components/{RectangleIcon.js → icons/RectangleIcon.js} +0 -0
  112. /package/lib/components/{SelectIcon.d.ts → icons/SelectIcon.d.ts} +0 -0
  113. /package/lib/components/{SelectIcon.js → icons/SelectIcon.js} +0 -0
  114. /package/lib/components/{TrashIcon.d.ts → icons/TrashIcon.d.ts} +0 -0
  115. /package/lib/components/{TrashIcon.js → icons/TrashIcon.js} +0 -0
  116. /package/src/components/{CircleIcon.tsx → icons/CircleIcon.tsx} +0 -0
  117. /package/src/components/{DownloadIcon.tsx → icons/DownloadIcon.tsx} +0 -0
  118. /package/src/components/{FreehandIcon.tsx → icons/FreehandIcon.tsx} +0 -0
  119. /package/src/components/{LineIcon.tsx → icons/LineIcon.tsx} +0 -0
  120. /package/src/components/{PencilIcon.tsx → icons/PencilIcon.tsx} +0 -0
  121. /package/src/components/{PolygonIcon.tsx → icons/PolygonIcon.tsx} +0 -0
  122. /package/src/components/{RectangleIcon.tsx → icons/RectangleIcon.tsx} +0 -0
  123. /package/src/components/{SelectIcon.tsx → icons/SelectIcon.tsx} +0 -0
  124. /package/src/components/{TrashIcon.tsx → icons/TrashIcon.tsx} +0 -0
@@ -1,212 +1,102 @@
1
-
2
- /* Mapka Tooltip Styles */
3
- .mapka-tooltip {
4
- border-radius: 12px;
5
- overflow: hidden;
6
- background: #fff;
7
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
8
- }
9
-
10
- .mapka-popup-icon {
11
- display: block;
12
- fill: none;
13
- height: 16px;
14
- width: 16px;
15
- stroke: currentColor;
16
- overflow: visible;
17
- }
18
-
19
- .mapka-popup-icon-sm {
20
- height: 12px;
21
- width: 12px;
22
- }
23
-
24
- .mapka-popup-icon-star {
25
- height: 12px;
26
- width: 12px;
27
- fill: currentColor;
28
- stroke: none;
1
+ /* Mapka Popup Styles */
2
+ .mapka-popup-container {
3
+ margin-top: -15px;
4
+ margin-bottom: -15px;
5
+ margin-left: -10px;
6
+ margin-right: -10px;
29
7
  }
30
8
 
31
- /* Carousel */
32
- .mapka-popup-carousel {
9
+ .mapka-popup {
33
10
  position: relative;
34
- width: 100%;
35
- height: 200px;
36
- overflow: hidden;
37
- border-radius: 12px 12px 0 0;
38
- }
39
-
40
- .mapka-popup-carousel-track {
41
11
  display: flex;
42
- height: 100%;
43
- transition: transform 0.3s ease;
44
- }
45
-
46
- .mapka-popup-carousel-image {
47
- min-width: 100%;
48
- height: 100%;
49
- object-fit: cover;
50
- flex-shrink: 0;
51
- }
52
-
53
- .mapka-popup-carousel-actions {
54
- position: absolute;
55
- top: 12px;
56
- right: 12px;
57
- display: flex;
58
- gap: 8px;
59
- z-index: 3;
60
- }
61
-
62
- .mapka-popup-action-btn {
63
- background: rgba(255, 255, 255, 0.95);
64
- border: none;
65
- border-radius: 50%;
66
- width: 32px;
67
- height: 32px;
68
- cursor: pointer;
69
- display: flex;
70
- align-items: center;
71
- justify-content: center;
72
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.18);
73
- transition: background 0.2s ease, transform 0.2s ease;
74
- color: #222;
75
- }
76
-
77
- .mapka-popup-action-btn:hover {
12
+ flex-direction: column;
13
+ align-items: flex-start;
78
14
  background: #fff;
79
- transform: scale(1.05);
15
+ border: 1px solid #dcdfe3;
16
+ border-radius: 12px;
17
+ overflow: hidden;
18
+ box-shadow:
19
+ 0px 4px 32px -4px rgba(69, 72, 76, 0.12),
20
+ 0px 3px 12px -2px rgba(173, 181, 189, 0.06);
80
21
  }
81
22
 
82
- .mapka-popup-carousel-btn {
23
+ .mapka-popup-close-btn {
83
24
  position: absolute;
84
- top: 50%;
85
- transform: translateY(-50%);
86
- background: rgba(255, 255, 255, 0.95);
87
- border: none;
88
- border-radius: 50%;
89
- width: 28px;
90
- height: 28px;
91
- cursor: pointer;
25
+ top: 10px;
26
+ right: 10px;
27
+ z-index: 2;
92
28
  display: flex;
93
29
  align-items: center;
94
30
  justify-content: center;
95
- z-index: 2;
96
- transition: background 0.2s ease, transform 0.2s ease;
97
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.18);
98
- color: #222;
99
- }
100
-
101
- .mapka-popup-carousel-btn:hover {
102
- background: #fff;
103
- transform: translateY(-50%) scale(1.05);
104
- }
105
-
106
- .mapka-popup-carousel-prev {
107
- left: 12px;
108
- }
109
-
110
- .mapka-popup-carousel-next {
111
- right: 12px;
112
- }
113
-
114
- .mapka-popup-dots {
115
- position: absolute;
116
- bottom: 12px;
117
- left: 50%;
118
- transform: translateX(-50%);
119
- display: flex;
120
- gap: 6px;
121
- z-index: 2;
122
- }
123
-
124
- .mapka-popup-dot {
125
- width: 6px;
126
- height: 6px;
127
- border-radius: 50%;
128
- background: rgba(255, 255, 255, 0.6);
31
+ width: 24px;
32
+ height: 24px;
33
+ border-radius: 6px;
129
34
  border: none;
35
+ background: rgba(255, 255, 255, 0.8);
130
36
  cursor: pointer;
131
37
  padding: 0;
132
- transition: background 0.2s ease, transform 0.2s ease;
38
+ color: #4f4f4f;
133
39
  }
134
40
 
135
- .mapka-popup-dot:hover {
136
- background: rgba(255, 255, 255, 0.8);
137
- transform: scale(1.2);
41
+ .mapka-popup-close-btn .mapka-popup-icon {
42
+ width: 16px;
43
+ height: 16px;
138
44
  }
139
45
 
140
- .mapka-popup-dot-active {
141
- background: #fff;
46
+ .mapka-popup-close-btn:hover {
47
+ background: rgba(255, 255, 255, 0.95);
142
48
  }
143
49
 
144
- /* Content */
145
50
  .mapka-popup-content {
146
- padding: 12px 16px 16px;
147
- }
148
-
149
- .mapka-popup-header {
150
51
  display: flex;
151
- justify-content: space-between;
52
+ flex-direction: column;
152
53
  align-items: flex-start;
153
- gap: 8px;
154
- margin-bottom: 4px;
54
+ gap: 12px;
55
+ padding: 16px;
56
+ width: 100%;
57
+ box-sizing: border-box;
155
58
  }
156
59
 
157
60
  .mapka-popup-title {
158
61
  margin: 0;
159
- font-size: 15px;
160
- font-weight: 600;
161
- color: #222;
162
- line-height: 1.3;
163
- flex: 1;
62
+ font-weight: 700;
63
+ font-size: 20px;
64
+ line-height: 28px;
65
+ color: #4f4f4f;
164
66
  }
165
67
 
166
-
167
68
  .mapka-popup-description {
168
- margin: 0 0 4px 0;
69
+ margin: 0;
70
+ font-weight: 400;
169
71
  font-size: 14px;
170
- color: #717171;
171
- line-height: 1.4;
172
- overflow: hidden;
173
- text-overflow: ellipsis;
174
- display: -webkit-box;
175
- -webkit-line-clamp: 2;
176
- -webkit-box-orient: vertical;
177
- }
178
-
179
- /* Rows */
180
- .mapka-popup-rows {
181
- margin: 12px 0 0 0;
182
- padding: 12px 0 0 0;
183
- border-top: 1px solid #ebebeb;
184
- display: grid;
185
- grid-template-columns: 1fr 1fr;
186
- gap: 8px 16px;
72
+ line-height: 18px;
73
+ color: #4f4f4f;
187
74
  }
188
75
 
189
- .mapka-popup-row {
190
- display: contents;
76
+ .mapka-popup-actions {
77
+ display: flex;
78
+ gap: 8px;
79
+ align-items: flex-start;
80
+ width: 100%;
191
81
  }
192
82
 
193
- .mapka-popup-row-label {
194
- font-size: 13px;
83
+ .mapka-popup-button-primary {
84
+ display: flex;
85
+ align-items: center;
86
+ justify-content: center;
87
+ gap: 8px;
88
+ flex: 1;
89
+ padding: 10px 16px;
90
+ background: #4f4f4f;
91
+ border: none;
92
+ border-radius: 6px;
93
+ cursor: pointer;
195
94
  font-weight: 500;
196
- color: #717171;
197
- margin: 0;
198
- white-space: nowrap;
199
- overflow: hidden;
200
- text-overflow: ellipsis;
95
+ font-size: 14px;
96
+ line-height: 18px;
97
+ color: #fff;
201
98
  }
202
99
 
203
- .mapka-popup-row-value {
204
- font-size: 13px;
205
- font-weight: 400;
206
- color: #222;
207
- margin: 0;
208
- text-align: right;
209
- white-space: nowrap;
210
- overflow: hidden;
211
- text-overflow: ellipsis;
212
- }
100
+ .mapka-popup-button-primary:hover {
101
+ background: #3a3a3a;
102
+ }
@@ -1,197 +1,32 @@
1
- import { Fragment } from "preact";
2
- import { useState } from "preact/hooks";
1
+ import type { MouseEventHandler } from "preact";
3
2
  import type { MapkaPopupContent } from "../types/popup.js";
3
+ import { CloseIcon } from "./icons/CloseIcon.js";
4
+ import { PopupDataRows } from "./PopupDataRows.js";
5
+ import { ImageCarousel } from "./ImageCarousel.js";
4
6
 
5
7
  interface PopupProps extends MapkaPopupContent {
6
8
  onClose?: () => void;
7
9
  closeButton?: boolean;
8
10
  }
9
11
 
10
- function HeartIcon({ filled }: { filled?: boolean }) {
11
- return (
12
- <svg
13
- viewBox="0 0 32 32"
14
- xmlns="http://www.w3.org/2000/svg"
15
- aria-hidden="true"
16
- focusable="false"
17
- class="mapka-popup-icon"
18
- >
19
- <path
20
- d="M16 28c7-4.73 14-10 14-17a6.98 6.98 0 0 0-7-7c-1.8 0-3.58.68-4.95 2.05L16 8.1l-2.05-2.05a6.98 6.98 0 0 0-9.9 0A6.98 6.98 0 0 0 2 11c0 7 7 12.27 14 17z"
21
- fill={filled ? "currentColor" : "none"}
22
- stroke="currentColor"
23
- stroke-width="2"
24
- />
25
- </svg>
26
- );
27
- }
28
-
29
- function CloseIcon() {
30
- return (
31
- <svg
32
- viewBox="0 0 32 32"
33
- xmlns="http://www.w3.org/2000/svg"
34
- aria-hidden="true"
35
- focusable="false"
36
- class="mapka-popup-icon"
37
- >
38
- <path d="m6 6 20 20M26 6 6 26" fill="none" stroke="currentColor" stroke-width="3" />
39
- </svg>
40
- );
41
- }
12
+ function PrimaryButton({ label, onClick }: { label: string; onClick?: () => void }) {
13
+ const handleClick = (e: Event) => {
14
+ e.stopPropagation();
15
+ onClick?.();
16
+ };
42
17
 
43
- function ChevronLeftIcon() {
44
18
  return (
45
- <svg
46
- viewBox="0 0 32 32"
47
- xmlns="http://www.w3.org/2000/svg"
48
- aria-hidden="true"
49
- focusable="false"
50
- class="mapka-popup-icon mapka-popup-icon-sm"
51
- >
52
- <path
53
- d="M20 28 8.7 16.7a1 1 0 0 1 0-1.4L20 4"
54
- fill="none"
55
- stroke="currentColor"
56
- stroke-width="4"
57
- />
58
- </svg>
19
+ <button type="button" class="mapka-popup-button-primary" onClick={handleClick}>
20
+ {label}
21
+ </button>
59
22
  );
60
23
  }
61
24
 
62
- function ChevronRightIcon() {
25
+ export function CloseButton({ onClose }: { onClose?: MouseEventHandler<HTMLButtonElement> }) {
63
26
  return (
64
- <svg
65
- viewBox="0 0 32 32"
66
- xmlns="http://www.w3.org/2000/svg"
67
- aria-hidden="true"
68
- focusable="false"
69
- class="mapka-popup-icon mapka-popup-icon-sm"
70
- >
71
- <path
72
- d="m12 4 11.3 11.3a1 1 0 0 1 0 1.4L12 28"
73
- fill="none"
74
- stroke="currentColor"
75
- stroke-width="4"
76
- />
77
- </svg>
78
- );
79
- }
80
-
81
- function ImageCarousel({
82
- imageUrls,
83
- title,
84
- onFavorite,
85
- id,
86
- closeButton,
87
- onClose,
88
- }: {
89
- imageUrls: string[];
90
- title?: string;
91
- closeButton?: boolean;
92
- onFavorite?: (id: string) => void;
93
- id?: string;
94
- onClose?: () => void;
95
- }) {
96
- const [currentIndex, setCurrentIndex] = useState(0);
97
-
98
- const handlePrev = (e: Event) => {
99
- e.stopPropagation();
100
- setCurrentIndex((prev) => (prev === 0 ? imageUrls.length - 1 : prev - 1));
101
- };
102
-
103
- const handleNext = (e: Event) => {
104
- e.stopPropagation();
105
- setCurrentIndex((prev) => (prev + 1) % imageUrls.length);
106
- };
107
-
108
- const handleFavoriteClick = (e: Event) => {
109
- e.stopPropagation();
110
- if (onFavorite && id) {
111
- onFavorite(id);
112
- }
113
- };
114
-
115
- const handleCloseClick = (e: Event) => {
116
- e.stopPropagation();
117
- onClose?.();
118
- };
119
-
120
- return (
121
- <div class="mapka-popup-carousel">
122
- <div
123
- class="mapka-popup-carousel-track"
124
- style={{ transform: `translateX(-${currentIndex * 100}%)` }}
125
- >
126
- {imageUrls.map((url, index) => (
127
- <img
128
- key={index}
129
- src={url}
130
- alt={title || `Image ${index + 1}`}
131
- class="mapka-popup-carousel-image"
132
- />
133
- ))}
134
- </div>
135
-
136
- <div class="mapka-popup-carousel-actions">
137
- {onFavorite && (
138
- <button
139
- type="button"
140
- class="mapka-popup-action-btn"
141
- onClick={handleFavoriteClick}
142
- aria-label="Add to favorites"
143
- >
144
- <HeartIcon />
145
- </button>
146
- )}
147
- {closeButton && (
148
- <button
149
- type="button"
150
- class="mapka-popup-action-btn"
151
- onClick={handleCloseClick}
152
- aria-label="Close"
153
- >
154
- <CloseIcon />
155
- </button>
156
- )}
157
- </div>
158
-
159
- {imageUrls.length > 1 && (
160
- <Fragment>
161
- <button
162
- type="button"
163
- class="mapka-popup-carousel-btn mapka-popup-carousel-prev"
164
- onClick={handlePrev}
165
- aria-label="Previous image"
166
- >
167
- <ChevronLeftIcon />
168
- </button>
169
- <button
170
- type="button"
171
- class="mapka-popup-carousel-btn mapka-popup-carousel-next"
172
- onClick={handleNext}
173
- aria-label="Next image"
174
- >
175
- <ChevronRightIcon />
176
- </button>
177
-
178
- <div class="mapka-popup-dots">
179
- {imageUrls.map((_, index) => (
180
- <button
181
- key={index}
182
- type="button"
183
- class={`mapka-popup-dot ${index === currentIndex ? "mapka-popup-dot-active" : ""}`}
184
- onClick={(e) => {
185
- e.stopPropagation();
186
- setCurrentIndex(index);
187
- }}
188
- aria-label={`Go to image ${index + 1}`}
189
- />
190
- ))}
191
- </div>
192
- </Fragment>
193
- )}
194
- </div>
27
+ <button type="button" class="mapka-popup-close-btn" onClick={onClose} aria-label="Close">
28
+ <CloseIcon />
29
+ </button>
195
30
  );
196
31
  }
197
32
 
@@ -200,38 +35,33 @@ export function PopupContent({
200
35
  description,
201
36
  rows,
202
37
  closeButton,
203
- imageUrls,
204
- onFavorite,
38
+ imageUrls = [],
39
+ primaryAction,
205
40
  onClose,
206
41
  }: PopupProps) {
207
42
  const hasImages = imageUrls && imageUrls.length > 0;
208
43
  const hasRows = rows && rows.length > 0;
209
44
 
45
+ const handleCloseClick = (e: Event) => {
46
+ e.stopPropagation();
47
+ onClose?.();
48
+ };
49
+
210
50
  return (
211
- <div class="mapka-tooltip">
212
- {hasImages && (
213
- <ImageCarousel
214
- imageUrls={imageUrls}
215
- title={title}
216
- closeButton={closeButton}
217
- onFavorite={onFavorite}
218
- onClose={onClose}
219
- />
220
- )}
51
+ <div class="mapka-popup">
52
+ {closeButton && <CloseButton onClose={handleCloseClick} />}
53
+ {hasImages && <ImageCarousel imageUrls={imageUrls} title={title} />}
221
54
 
222
55
  <div class="mapka-popup-content">
223
56
  {title && <h3 class="mapka-popup-title">{title}</h3>}
224
57
  {description && <p class="mapka-popup-description">{description}</p>}
225
58
 
226
- {hasRows && (
227
- <dl class="mapka-popup-rows">
228
- {rows.map((row, index) => (
229
- <div key={index} class="mapka-popup-row">
230
- <dt class="mapka-popup-row-label">{row.name}</dt>
231
- <dd class="mapka-popup-row-value">{row.value != null ? String(row.value) : "—"}</dd>
232
- </div>
233
- ))}
234
- </dl>
59
+ {hasRows && <PopupDataRows rows={rows} />}
60
+
61
+ {primaryAction && (
62
+ <div class="mapka-popup-actions">
63
+ <PrimaryButton label={primaryAction.label} onClick={primaryAction.onClick} />
64
+ </div>
235
65
  )}
236
66
  </div>
237
67
  </div>
@@ -0,0 +1,41 @@
1
+ .mapka-popup-rows {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: 2px;
5
+ margin: 0;
6
+ width: 100%;
7
+ }
8
+
9
+ .mapka-popup-row {
10
+ display: flex;
11
+ flex-direction: row;
12
+ align-items: center;
13
+ gap: 16px;
14
+ height: 30px;
15
+ padding: 0 8px;
16
+ border-radius: 6px;
17
+ }
18
+
19
+ .mapka-popup-row-label {
20
+ flex: 1;
21
+ margin: 0;
22
+ font-weight: 400;
23
+ font-size: 12px;
24
+ line-height: 16px;
25
+ color: #4f4f4f;
26
+ }
27
+
28
+ .mapka-popup-row-value {
29
+ flex: 1;
30
+ margin: 0;
31
+ font-weight: 400;
32
+ font-size: 12px;
33
+ line-height: 16px;
34
+ color: #4f4f4f;
35
+ }
36
+
37
+ .mapka-popup-row-divider {
38
+ height: 0;
39
+ border-bottom: 1px solid #e0e0e0;
40
+ width: 100%;
41
+ }
@@ -0,0 +1,39 @@
1
+ import type { MapkaPopupRow } from "../types/popup.js";
2
+
3
+ export function displayRowValue(value: unknown) {
4
+ if (value == null) {
5
+ return "-";
6
+ }
7
+
8
+ if (typeof value === "number") {
9
+ return value.toLocaleString();
10
+ }
11
+ if (typeof value === "boolean") {
12
+ return value ? "true" : "false";
13
+ }
14
+ if (typeof value === "object") {
15
+ return JSON.stringify(value);
16
+ }
17
+
18
+ return value;
19
+ }
20
+
21
+ export function displayRowName(name: string) {
22
+ return name;
23
+ }
24
+
25
+ export function PopupDataRows({ rows }: { rows: MapkaPopupRow[] }) {
26
+ return (
27
+ <dl class="mapka-popup-rows">
28
+ {rows.map((row, index) => (
29
+ <>
30
+ {index > 0 && <div class="mapka-popup-row-divider" />}
31
+ <div key={index} class="mapka-popup-row">
32
+ <dt class="mapka-popup-row-label">{displayRowName(row.name)}</dt>
33
+ <dd class="mapka-popup-row-value">{displayRowValue(row.value)}</dd>
34
+ </div>
35
+ </>
36
+ ))}
37
+ </dl>
38
+ );
39
+ }
@@ -0,0 +1,24 @@
1
+ .mapka-popup-list-wrapper {
2
+ width: 100%;
3
+ overflow-y: auto;
4
+ }
5
+
6
+ .mapka-popup-list {
7
+ display: flex;
8
+ flex-direction: column;
9
+ gap: 8px;
10
+ overflow-y: auto;
11
+ max-height: 265px;
12
+ padding: 8px 8px 24px;
13
+ box-sizing: border-box;
14
+ }
15
+
16
+ .mapka-popup-list-gradient {
17
+ position: absolute;
18
+ bottom: 0;
19
+ left: 0;
20
+ right: 0;
21
+ height: 54px;
22
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #fff 100%);
23
+ pointer-events: none;
24
+ }
@@ -0,0 +1,27 @@
1
+ import type { MapkaPopupOptionsResolved } from "../types/popup.js";
2
+ import { PopupListItem } from "./PopupListItem.js";
3
+
4
+ interface PopupCollectionProps {
5
+ items: MapkaPopupOptionsResolved[];
6
+ }
7
+
8
+ export function PopupCustomElement({ popup }: { popup: HTMLElement }) {
9
+ return popup;
10
+ }
11
+
12
+ export function PopupList({ items }: PopupCollectionProps) {
13
+ return (
14
+ <div class="mapka-popup-list-wrapper">
15
+ <div class="mapka-popup-list">
16
+ {items.map(({ content, id }) =>
17
+ content instanceof HTMLElement ? (
18
+ <PopupCustomElement key={id} popup={content} />
19
+ ) : (
20
+ <PopupListItem key={id} popup={content} />
21
+ ),
22
+ )}
23
+ </div>
24
+ <div class="mapka-popup-list-gradient" />
25
+ </div>
26
+ );
27
+ }