svgmap 2.20.0 → 2.21.0

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "svgmap",
3
3
  "description": "svgMap is a JavaScript library that lets you easily create an interactable world map comparing customizable data for each country.",
4
- "version": "2.20.0",
4
+ "version": "2.21.0",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "keywords": [
@@ -43,12 +43,12 @@
43
43
  "prepublishOnly": "npm run build && node test/assets.js"
44
44
  },
45
45
  "devDependencies": {
46
- "@rollup/plugin-commonjs": "^29.0.2",
46
+ "@rollup/plugin-commonjs": "^29.0.3",
47
47
  "@rollup/plugin-node-resolve": "^16.0.3",
48
48
  "@rollup/plugin-terser": "^1.0.0",
49
49
  "csso": "^5.0.5",
50
- "rollup": "^4.60.2",
50
+ "rollup": "^4.61.0",
51
51
  "rollup-plugin-postcss": "^4.0.2",
52
- "sass": "^1.99.0"
52
+ "sass": "^1.100.0"
53
53
  }
54
54
  }
@@ -101,7 +101,34 @@ export default class svgMap {
101
101
  showContinentSelector: false,
102
102
 
103
103
  // Reset zoom on resize
104
- resetZoomOnResize: false
104
+ resetZoomOnResize: false,
105
+
106
+ // Static pins: false | string[] | function(countryID, countryValues) => boolean
107
+ staticPins: false,
108
+
109
+ // Default pin fill color
110
+ pinColor: '#000000',
111
+
112
+ // Default pin stroke color and width (circle pins; width is in screen pixels with non-scaling stroke)
113
+ pinStrokeColor: '#ffffff',
114
+ pinStrokeWidth: 1.5,
115
+
116
+ // Default pin radius in SVG units (viewBox is 2000 × 1001)
117
+ pinSize: 8,
118
+
119
+ // Custom pin element: function(countryID, countryValues) => SVGElement | null
120
+ onGetPin: null,
121
+
122
+ // Image URL to use as a pin instead of the default circle (can also be set per-country via values[id].pinImage)
123
+ pinImage: null,
124
+
125
+ // Width and height of the pin image in SVG units (viewBox is 2000 × 1001)
126
+ pinImageWidth: 20,
127
+ pinImageHeight: 20,
128
+
129
+ // Offset from computed pin position, in SVG units (added after auto center or pinX/pinY)
130
+ pinOffsetX: 0,
131
+ pinOffsetY: 0
105
132
  };
106
133
 
107
134
  this.options = Object.assign({}, defaultOptions, options);
@@ -953,6 +980,102 @@ export default class svgMap {
953
980
 
954
981
  // Add map elements
955
982
  var countryElements = [];
983
+
984
+ const clearActive = function clearActive() {
985
+ this.mapImage
986
+ .querySelectorAll('.svgMap-active')
987
+ .forEach((el) => el.classList.remove('svgMap-active'));
988
+ }.bind(this);
989
+
990
+ const isClickTooltip =
991
+ this.options.showTooltips && this.options.tooltipTrigger === 'click';
992
+
993
+ const getCountryFromEvent = function (e) {
994
+ return e.target && e.target.closest
995
+ ? e.target.closest('.svgMap-country')
996
+ : null;
997
+ };
998
+
999
+ const raiseCountry = function (countryElement, setActive) {
1000
+ if (setActive) {
1001
+ clearActive();
1002
+ }
1003
+ countryElement.parentNode.insertBefore(
1004
+ countryElement,
1005
+ this.persistentTooltipGroup || this.pinGroup || null
1006
+ );
1007
+ if (setActive) {
1008
+ countryElement.classList.add('svgMap-active');
1009
+ }
1010
+ }.bind(this);
1011
+
1012
+ const showCountryTooltip = function (countryElement, e, setActive) {
1013
+ raiseCountry(countryElement, setActive);
1014
+ this.setTooltipContent(this.getTooltipContent(countryElement.dataset.id));
1015
+ this.showTooltip(e);
1016
+ }.bind(this);
1017
+
1018
+ // Touch only: preview tooltip on finger down without marking country active
1019
+ // (active is set on pointerup so link countries keep two-tap navigation)
1020
+ this.mapImage.addEventListener(
1021
+ 'pointerdown',
1022
+ (e) => {
1023
+ if (!this.options.showTooltips || e.pointerType !== 'touch') {
1024
+ return;
1025
+ }
1026
+
1027
+ const countryElement = getCountryFromEvent(e);
1028
+ if (!countryElement) {
1029
+ this.hideTooltip();
1030
+ return;
1031
+ }
1032
+
1033
+ showCountryTooltip(countryElement, e, false);
1034
+ this.moveTooltip(e);
1035
+ },
1036
+ { passive: true }
1037
+ );
1038
+
1039
+ this.mapImage.addEventListener(
1040
+ 'pointercancel',
1041
+ (e) => {
1042
+ if (e.pointerType === 'touch') {
1043
+ this.hideTooltip();
1044
+ }
1045
+ },
1046
+ { passive: true }
1047
+ );
1048
+
1049
+ // Hover (mouse/pen) and touch drag: raise country + optional floating tooltip
1050
+ this.mapImage.addEventListener(
1051
+ 'pointermove',
1052
+ (e) => {
1053
+ const countryElement = getCountryFromEvent(e);
1054
+ if (!countryElement) {
1055
+ clearActive();
1056
+ if (this.options.showTooltips) {
1057
+ this.hideTooltip();
1058
+ }
1059
+ return;
1060
+ }
1061
+
1062
+ const mouseClickMode = e.pointerType === 'mouse' && isClickTooltip;
1063
+
1064
+ // Always raise hovered country (SVG paint order + .svgMap-active stroke)
1065
+ if (!this.options.showTooltips || mouseClickMode) {
1066
+ raiseCountry(countryElement, true);
1067
+ return;
1068
+ }
1069
+
1070
+ showCountryTooltip(countryElement, e, true);
1071
+
1072
+ if (e.pointerType === 'touch') {
1073
+ this.moveTooltip(e);
1074
+ }
1075
+ },
1076
+ { passive: true }
1077
+ );
1078
+
956
1079
  Object.keys(mapPaths).forEach(
957
1080
  function (countryID) {
958
1081
  var countryData = this.mapPaths[countryID];
@@ -970,166 +1093,22 @@ export default class svgMap {
970
1093
  'id',
971
1094
  this.id + '-map-country-' + countryID
972
1095
  );
973
- countryElement.setAttribute('data-id', countryID);
1096
+ countryElement.dataset.id = countryID;
974
1097
  countryElement.classList.add('svgMap-country');
975
1098
 
976
1099
  this.mapImage.appendChild(countryElement);
977
1100
  countryElements.push(countryElement);
978
1101
 
979
- // Add tooltip when touch is used
980
- function handlePointerMove(e) {
981
- if (e.pointerType === 'touch') return;
982
-
983
- const target = document.elementFromPoint(e.clientX, e.clientY);
984
-
985
- if (
986
- !target ||
987
- (!target.closest('.svgMap-country') &&
988
- !target.closest('.svgMap-tooltip'))
989
- ) {
990
- this.hideTooltip();
991
- document
992
- .querySelectorAll('.svgMap-active')
993
- .forEach((el) => el.classList.remove('svgMap-active'));
994
- }
995
- }
996
-
997
- const handlePointerMoveBound = handlePointerMove.bind(this);
998
-
999
- countryElement.addEventListener(
1000
- 'pointerenter',
1001
- function (e) {
1002
- if (
1003
- e.pointerType === 'mouse' &&
1004
- this.options.showTooltips &&
1005
- this.options.tooltipTrigger === 'click'
1006
- ) {
1007
- return;
1008
- }
1009
-
1010
- // Only add pointermove listener for non-touch pointers
1011
- if (e.pointerType !== 'touch') {
1012
- document.addEventListener('pointermove', handlePointerMoveBound, {
1013
- passive: true
1014
- });
1015
- }
1016
-
1017
- document
1018
- .querySelectorAll('.svgMap-active')
1019
- .forEach((el) => el.classList.remove('svgMap-active'));
1020
-
1021
- countryElement.parentNode.insertBefore(
1022
- countryElement,
1023
- this.persistentTooltipGroup || null
1024
- );
1025
- countryElement.classList.add('svgMap-active');
1026
-
1027
- const countryID = countryElement.getAttribute('data-id');
1028
- if (this.options.showTooltips) {
1029
- this.setTooltipContent(this.getTooltipContent(countryID));
1030
- this.showTooltip(e);
1031
-
1032
- // For touch, move tooltip to the touch position and keep it there
1033
- if (e.pointerType === 'touch') {
1034
- this.moveTooltip(e);
1035
- }
1036
- }
1037
- }.bind(this)
1038
- );
1039
-
1040
- // Handle touch move - update tooltip position while panning
1041
- countryElement.addEventListener(
1042
- 'touchmove',
1043
- function (e) {
1044
- this.moveTooltip(e);
1045
- }.bind(this),
1046
- { passive: true }
1047
- );
1048
-
1049
- // Handle touch end - remove active state and hide tooltip
1050
- countryElement.addEventListener(
1051
- 'touchend',
1052
- function (e) {
1053
- const touch = e.changedTouches[0];
1054
- const elementAtEnd = document.elementFromPoint(
1055
- touch.clientX,
1056
- touch.clientY
1057
- );
1058
-
1059
- // Only hide if touch ended outside the country or tooltip
1060
- if (
1061
- !elementAtEnd ||
1062
- (!elementAtEnd.closest('.svgMap-country') &&
1063
- !elementAtEnd.closest('.svgMap-tooltip'))
1064
- ) {
1065
- this.hideTooltip();
1066
- document
1067
- .querySelectorAll('.svgMap-active')
1068
- .forEach((el) => el.classList.remove('svgMap-active'));
1069
- }
1070
- }.bind(this),
1071
- { passive: true }
1072
- );
1073
-
1074
- // Remove pointermove listener when leaving non-touch pointer
1075
- countryElement.addEventListener(
1076
- 'pointerleave',
1077
- function (e) {
1078
- if (e.pointerType !== 'touch') {
1079
- document.removeEventListener(
1080
- 'pointermove',
1081
- handlePointerMoveBound
1082
- );
1083
- if (
1084
- !(
1085
- e.pointerType === 'mouse' &&
1086
- this.options.showTooltips &&
1087
- this.options.tooltipTrigger === 'click'
1088
- )
1089
- ) {
1090
- this.hideTooltip();
1091
- document
1092
- .querySelectorAll('.svgMap-active')
1093
- .forEach((el) => el.classList.remove('svgMap-active'));
1094
- }
1095
- }
1096
- }.bind(this)
1097
- );
1098
-
1099
- document.addEventListener(
1100
- 'pointerover',
1101
- function (e) {
1102
- if (e.pointerType !== 'touch') return;
1103
-
1104
- if (
1105
- e.target.closest('.svgMap-country') ||
1106
- e.target.closest('.svgMap-tooltip')
1107
- ) {
1108
- return;
1109
- }
1110
-
1111
- this.hideTooltip();
1112
- document
1113
- .querySelectorAll('.svgMap-active')
1114
- .forEach((el) => el.classList.remove('svgMap-active'));
1115
- }.bind(this),
1116
- { passive: true }
1117
- );
1118
-
1119
1102
  if (
1120
1103
  this.options.data.values &&
1121
1104
  this.options.data.values[countryID] &&
1122
1105
  this.options.data.values[countryID]['link']
1123
1106
  ) {
1124
- countryElement.setAttribute(
1125
- 'data-link',
1126
- this.options.data.values[countryID]['link']
1127
- );
1107
+ countryElement.dataset.link =
1108
+ this.options.data.values[countryID]['link'];
1128
1109
  if (this.options.data.values[countryID]['linkTarget']) {
1129
- countryElement.setAttribute(
1130
- 'data-link-target',
1131
- this.options.data.values[countryID]['linkTarget']
1132
- );
1110
+ countryElement.dataset.linkTarget =
1111
+ this.options.data.values[countryID]['linkTarget'];
1133
1112
  }
1134
1113
  }
1135
1114
  }.bind(this)
@@ -1143,6 +1122,10 @@ export default class svgMap {
1143
1122
  this.createPersistentTooltips(countryElements);
1144
1123
  }
1145
1124
 
1125
+ if (this.options.staticPins) {
1126
+ this.createStaticPins(countryElements);
1127
+ }
1128
+
1146
1129
  let pointerStart = null;
1147
1130
  let activeCountry = null;
1148
1131
 
@@ -1175,21 +1158,18 @@ export default class svgMap {
1175
1158
  const countryElement = e.target.closest('.svgMap-country');
1176
1159
  if (!countryElement) return;
1177
1160
 
1178
- const countryID = countryElement.getAttribute('data-id');
1179
- const link = countryElement.getAttribute('data-link');
1180
- const linkTarget = countryElement.getAttribute('data-link-target');
1161
+ const countryID = countryElement.dataset.id;
1162
+ const link = countryElement.dataset.link;
1163
+ const linkTarget = countryElement.dataset.linkTarget;
1181
1164
  const hasCallback = typeof this.options.onCountryClick === 'function';
1182
1165
  const hasLink = !!link;
1183
1166
  const isTouch = e.pointerType === 'touch' || e.pointerType === 'pen';
1184
1167
 
1185
- const isClickTooltipMouse =
1186
- e.pointerType === 'mouse' &&
1187
- this.options.showTooltips &&
1188
- this.options.tooltipTrigger === 'click';
1168
+ const isClickTooltipMouse = e.pointerType === 'mouse' && isClickTooltip;
1189
1169
 
1190
1170
  if (!hasLink && !hasCallback && !isClickTooltipMouse) return;
1191
1171
 
1192
- if (isClickTooltipMouse && this.options.showTooltips) {
1172
+ if (isClickTooltipMouse) {
1193
1173
  const willNavigate =
1194
1174
  hasLink && countryElement.classList.contains('svgMap-active');
1195
1175
  const shouldFireCallback = hasCallback && (!hasLink || willNavigate);
@@ -1205,12 +1185,10 @@ export default class svgMap {
1205
1185
  if (linkTarget) window.open(link, linkTarget);
1206
1186
  else window.location.href = link;
1207
1187
  } else {
1208
- this.mapImage
1209
- .querySelectorAll('.svgMap-country.svgMap-active')
1210
- .forEach((el) => el.classList.remove('svgMap-active'));
1188
+ clearActive();
1211
1189
  countryElement.parentNode.insertBefore(
1212
1190
  countryElement,
1213
- this.persistentTooltipGroup || null
1191
+ this.persistentTooltipGroup || this.pinGroup || null
1214
1192
  );
1215
1193
  countryElement.classList.add('svgMap-active');
1216
1194
  this.setTooltipContent(this.getTooltipContent(countryID));
@@ -1221,12 +1199,10 @@ export default class svgMap {
1221
1199
 
1222
1200
  if (callbackResultClick === false) return;
1223
1201
 
1224
- this.mapImage
1225
- .querySelectorAll('.svgMap-country.svgMap-active')
1226
- .forEach((el) => el.classList.remove('svgMap-active'));
1202
+ clearActive();
1227
1203
  countryElement.parentNode.insertBefore(
1228
1204
  countryElement,
1229
- this.persistentTooltipGroup || null
1205
+ this.persistentTooltipGroup || this.pinGroup || null
1230
1206
  );
1231
1207
  countryElement.classList.add('svgMap-active');
1232
1208
  this.setTooltipContent(this.getTooltipContent(countryID));
@@ -1276,15 +1252,9 @@ export default class svgMap {
1276
1252
  });
1277
1253
 
1278
1254
  this._clickTooltipOutsideHandler = function (ev) {
1279
- if (ev.pointerType !== 'mouse') return;
1280
- if (
1281
- !this.options.showTooltips ||
1282
- this.options.tooltipTrigger !== 'click' ||
1283
- !this.tooltip
1284
- ) {
1255
+ if (!this.tooltip || !this.tooltip.classList.contains('svgMap-active')) {
1285
1256
  return;
1286
1257
  }
1287
- if (!this.tooltip.classList.contains('svgMap-active')) return;
1288
1258
  var node = ev.target;
1289
1259
  if (
1290
1260
  node &&
@@ -1302,11 +1272,6 @@ export default class svgMap {
1302
1272
  });
1303
1273
  }
1304
1274
  }.bind(this);
1305
- document.addEventListener(
1306
- 'pointerdown',
1307
- this._clickTooltipOutsideHandler,
1308
- true
1309
- );
1310
1275
 
1311
1276
  // Expose instance
1312
1277
  var me = this;
@@ -1389,7 +1354,7 @@ export default class svgMap {
1389
1354
 
1390
1355
  countryElements.forEach(
1391
1356
  function (countryElement) {
1392
- var countryID = countryElement.getAttribute('data-id');
1357
+ var countryID = countryElement.dataset.id;
1393
1358
  if (!this.shouldShowTooltipOnLoad(countryID)) {
1394
1359
  return;
1395
1360
  }
@@ -1425,6 +1390,157 @@ export default class svgMap {
1425
1390
  );
1426
1391
  }
1427
1392
 
1393
+ // Create static pins on the map
1394
+
1395
+ createStaticPins(countryElements) {
1396
+ if (this.pinGroup) {
1397
+ this.pinGroup.remove();
1398
+ }
1399
+
1400
+ this.pinGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');
1401
+ this.pinGroup.classList.add('svgMap-pin-group');
1402
+ this.mapImage.appendChild(this.pinGroup);
1403
+
1404
+ countryElements.forEach(
1405
+ function (countryElement) {
1406
+ var countryID = countryElement.getAttribute('data-id');
1407
+ if (!this.shouldShowPin(countryID)) {
1408
+ return;
1409
+ }
1410
+
1411
+ var countryValues = this.options.data.values[countryID];
1412
+ var cx, cy;
1413
+
1414
+ if (
1415
+ countryValues &&
1416
+ countryValues.pinX != null &&
1417
+ countryValues.pinY != null
1418
+ ) {
1419
+ cx = countryValues.pinX;
1420
+ cy = countryValues.pinY;
1421
+ } else {
1422
+ // Split the path at absolute M commands and use the largest sub-path
1423
+ // to avoid overseas territories (islands, colonies) skewing the center.
1424
+ var d = countryElement.getAttribute('d');
1425
+ var subPaths = d.split(/(?=M)/).filter((s) => s.trim().length > 0);
1426
+ var largestBB = null;
1427
+ var largestArea = -1;
1428
+
1429
+ subPaths.forEach(
1430
+ function (subPath) {
1431
+ var tmp = document.createElementNS(
1432
+ 'http://www.w3.org/2000/svg',
1433
+ 'path'
1434
+ );
1435
+ tmp.setAttribute('d', subPath);
1436
+ this.mapImage.appendChild(tmp);
1437
+ var bb = tmp.getBBox();
1438
+ var area = bb.width * bb.height;
1439
+ if (area > largestArea) {
1440
+ largestArea = area;
1441
+ largestBB = bb;
1442
+ }
1443
+ this.mapImage.removeChild(tmp);
1444
+ }.bind(this)
1445
+ );
1446
+
1447
+ cx = largestBB.x + largestBB.width / 2;
1448
+ cy = largestBB.y + largestBB.height / 2;
1449
+ }
1450
+
1451
+ var offsetX =
1452
+ countryValues && countryValues.pinOffsetX != null
1453
+ ? countryValues.pinOffsetX
1454
+ : this.options.pinOffsetX;
1455
+ var offsetY =
1456
+ countryValues && countryValues.pinOffsetY != null
1457
+ ? countryValues.pinOffsetY
1458
+ : this.options.pinOffsetY;
1459
+ cx += offsetX;
1460
+ cy += offsetY;
1461
+
1462
+ var color =
1463
+ (countryValues && countryValues.pinColor) || this.options.pinColor;
1464
+ var size =
1465
+ (countryValues && countryValues.pinSize) || this.options.pinSize;
1466
+ var strokeColor =
1467
+ (countryValues && countryValues.pinStrokeColor) ||
1468
+ this.options.pinStrokeColor;
1469
+ var strokeWidth =
1470
+ (countryValues && countryValues.pinStrokeWidth) ||
1471
+ this.options.pinStrokeWidth;
1472
+
1473
+ if (typeof this.options.onGetPin === 'function') {
1474
+ var custom = this.options.onGetPin(countryID, countryValues);
1475
+ if (custom) {
1476
+ custom.setAttribute(
1477
+ 'transform',
1478
+ 'translate(' + cx + ',' + cy + ')'
1479
+ );
1480
+ this.pinGroup.appendChild(custom);
1481
+ return;
1482
+ }
1483
+ }
1484
+
1485
+ var pinImage =
1486
+ (countryValues && countryValues.pinImage) || this.options.pinImage;
1487
+
1488
+ if (pinImage) {
1489
+ var pinW =
1490
+ (countryValues && countryValues.pinImageWidth) ||
1491
+ this.options.pinImageWidth;
1492
+ var pinH =
1493
+ (countryValues && countryValues.pinImageHeight) ||
1494
+ this.options.pinImageHeight;
1495
+ var img = document.createElementNS(
1496
+ 'http://www.w3.org/2000/svg',
1497
+ 'image'
1498
+ );
1499
+ img.setAttribute('href', pinImage);
1500
+ img.setAttribute('x', cx - pinW / 2);
1501
+ img.setAttribute('y', cy - pinH / 2);
1502
+ img.setAttribute('width', pinW);
1503
+ img.setAttribute('height', pinH);
1504
+ img.setAttribute('data-id', countryID);
1505
+ img.classList.add('svgMap-pin');
1506
+ this.pinGroup.appendChild(img);
1507
+ return;
1508
+ }
1509
+
1510
+ var circle = document.createElementNS(
1511
+ 'http://www.w3.org/2000/svg',
1512
+ 'circle'
1513
+ );
1514
+ circle.setAttribute('cx', cx);
1515
+ circle.setAttribute('cy', cy);
1516
+ circle.setAttribute('r', size);
1517
+ circle.setAttribute('fill', color);
1518
+ if (strokeWidth > 0) {
1519
+ circle.setAttribute('stroke', strokeColor);
1520
+ circle.setAttribute('stroke-width', strokeWidth);
1521
+ circle.setAttribute('vector-effect', 'non-scaling-stroke');
1522
+ }
1523
+ circle.setAttribute('data-id', countryID);
1524
+ circle.classList.add('svgMap-pin');
1525
+ this.pinGroup.appendChild(circle);
1526
+ }.bind(this)
1527
+ );
1528
+ }
1529
+
1530
+ // Check if a static pin should be shown for a country
1531
+
1532
+ shouldShowPin(countryID) {
1533
+ var pins = this.options.staticPins;
1534
+ var countryValues = this.options.data.values[countryID];
1535
+ if (Array.isArray(pins)) {
1536
+ return pins.indexOf(countryID) !== -1;
1537
+ }
1538
+ if (typeof pins === 'function') {
1539
+ return pins(countryID, countryValues);
1540
+ }
1541
+ return false;
1542
+ }
1543
+
1428
1544
  // Check if a persistent tooltip should be shown on load
1429
1545
 
1430
1546
  shouldShowTooltipOnLoad(countryID) {
@@ -2434,6 +2550,23 @@ export default class svgMap {
2434
2550
  return;
2435
2551
  }
2436
2552
  this.tooltip.classList.add('svgMap-active');
2553
+
2554
+ if (
2555
+ this.options.showTooltips &&
2556
+ this.options.tooltipTrigger === 'click' &&
2557
+ e.pointerType === 'mouse'
2558
+ ) {
2559
+ // don't register event listener in the same frame
2560
+ // to prevent it from being triggered immediately
2561
+ requestAnimationFrame(() => {
2562
+ document.addEventListener(
2563
+ 'pointerdown',
2564
+ this._clickTooltipOutsideHandler,
2565
+ { once: true, passive: true }
2566
+ );
2567
+ });
2568
+ }
2569
+
2437
2570
  this.moveTooltip(e);
2438
2571
  }
2439
2572
 
@@ -2443,7 +2576,12 @@ export default class svgMap {
2443
2576
  if (!this.tooltip) {
2444
2577
  return;
2445
2578
  }
2579
+
2446
2580
  this.tooltip.classList.remove('svgMap-active');
2581
+ document.removeEventListener(
2582
+ 'pointerdown',
2583
+ this._clickTooltipOutsideHandler
2584
+ );
2447
2585
  }
2448
2586
 
2449
2587
  // Move the tooltip
package/src/scss/map.scss CHANGED
@@ -259,3 +259,14 @@
259
259
  .svgMap-wrapper.svgMap-country-click-callback .svgMap-map-wrapper .svgMap-country {
260
260
  cursor: pointer;
261
261
  }
262
+
263
+ // Static pins
264
+
265
+ .svgMap-pin-group {
266
+ pointer-events: none;
267
+ }
268
+
269
+ .svgMap-pin {
270
+ vector-effect: non-scaling-stroke;
271
+ transition: r 250ms;
272
+ }