@mapka/maplibre-gl-sdk 0.16.1 → 0.16.4

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