world-map-svg 0.5.0 → 0.5.1
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/README.md +194 -194
- package/dist/world-map-svg.cjs.js +1 -1
- package/dist/world-map-svg.es.js +34 -37
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,194 +1,194 @@
|
|
|
1
|
-
# world-map-svg
|
|
2
|
-
|
|
3
|
-
Interactive SVG world map React component with zoom, pan, and country selection.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install world-map-svg
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Usage
|
|
12
|
-
|
|
13
|
-
```tsx
|
|
14
|
-
import { WorldMap } from 'world-map-svg'
|
|
15
|
-
import 'world-map-svg/style.css'
|
|
16
|
-
|
|
17
|
-
function App() {
|
|
18
|
-
return (
|
|
19
|
-
<div style={{ width: '100%', height: '500px' }}>
|
|
20
|
-
<WorldMap
|
|
21
|
-
countryColor="#093C5D"
|
|
22
|
-
/>
|
|
23
|
-
</div>
|
|
24
|
-
)
|
|
25
|
-
}
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Demo Usage
|
|
29
|
-
|
|
30
|
-
```tsx
|
|
31
|
-
import { useState } from 'react'
|
|
32
|
-
import { WorldMap } from 'world-map-svg'
|
|
33
|
-
import 'world-map-svg/style.css'
|
|
34
|
-
|
|
35
|
-
export function MapDemo() {
|
|
36
|
-
const [hover, setHover] = useState<{ name: string; x: number; y: number } | null>(null)
|
|
37
|
-
const [modal, setModal] = useState<{ code: string; name: string } | null>(null)
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<div style={{ position: 'relative', width: '100%', height: 600 }}>
|
|
41
|
-
<WorldMap
|
|
42
|
-
onCountryHover={(code, name, x, y) => setHover({ name, x, y })}
|
|
43
|
-
onCountryClick={(code, name) => setModal({ code, name })}
|
|
44
|
-
/>
|
|
45
|
-
|
|
46
|
-
{hover && (
|
|
47
|
-
<div style={{ position: 'absolute', left: hover.x + 12, top: hover.y + 12 }}>
|
|
48
|
-
{hover.name}
|
|
49
|
-
</div>
|
|
50
|
-
)}
|
|
51
|
-
|
|
52
|
-
{modal && (
|
|
53
|
-
<div>
|
|
54
|
-
<h3>{modal.name}</h3>
|
|
55
|
-
<p>{modal.code}</p>
|
|
56
|
-
</div>
|
|
57
|
-
)}
|
|
58
|
-
</div>
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Hover gets the country name and pointer position. Click gets the country name and code, so your app can open a modal and load any extra data you need.
|
|
64
|
-
|
|
65
|
-
## Full Props Setup
|
|
66
|
-
|
|
67
|
-
```tsx
|
|
68
|
-
import { useState } from 'react'
|
|
69
|
-
import { WorldMap } from 'world-map-svg'
|
|
70
|
-
import 'world-map-svg/style.css'
|
|
71
|
-
|
|
72
|
-
export function FullMapSetup() {
|
|
73
|
-
const [hover, setHover] = useState<{ name: string; x: number; y: number } | null>(null)
|
|
74
|
-
const [selected, setSelected] = useState<{ code: string; name: string } | null>(null)
|
|
75
|
-
|
|
76
|
-
return (
|
|
77
|
-
<div style={{ position: 'relative', width: '100%', height: 600 }}>
|
|
78
|
-
<WorldMap
|
|
79
|
-
backgroundColor="#f8fbff"
|
|
80
|
-
countryColor="#093C5D"
|
|
81
|
-
className="my-map"
|
|
82
|
-
showConnections
|
|
83
|
-
connectionBase="BD"
|
|
84
|
-
connectedCountries={['US', 'IN', 'GB', 'AE']}
|
|
85
|
-
onCountryHover={(code, name, x, y) => setHover({ name: `${name} (${code})`, x, y })}
|
|
86
|
-
onCountryClick={(code, name) => setSelected({ code, name })}
|
|
87
|
-
onConnectionDotHover={(code, name) => {
|
|
88
|
-
// Optional: show dot-specific tooltip
|
|
89
|
-
console.log('dot hover', code, name)
|
|
90
|
-
}}
|
|
91
|
-
onConnectionDotClick={(code, name) => {
|
|
92
|
-
// Optional: open modal or route to a detail page
|
|
93
|
-
console.log('dot click', code, name)
|
|
94
|
-
}}
|
|
95
|
-
/>
|
|
96
|
-
|
|
97
|
-
{hover && (
|
|
98
|
-
<div style={{ position: 'absolute', left: hover.x + 12, top: hover.y + 12 }}>
|
|
99
|
-
{hover.name}
|
|
100
|
-
</div>
|
|
101
|
-
)}
|
|
102
|
-
|
|
103
|
-
{selected && (
|
|
104
|
-
<div>
|
|
105
|
-
<h3>{selected.name}</h3>
|
|
106
|
-
<p>Country code: {selected.code}</p>
|
|
107
|
-
</div>
|
|
108
|
-
)}
|
|
109
|
-
</div>
|
|
110
|
-
)
|
|
111
|
-
}
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
If you pass `onCountryHover` or `onCountryClick`, your app controls the hover/click UI (popover/modal). If you do not pass them, the built-in tooltip behavior is used.
|
|
115
|
-
|
|
116
|
-
### Connection country names
|
|
117
|
-
|
|
118
|
-
`connectionBase` and `connectedCountries` accept **ISO 3166-1 alpha-2 codes** (e.g. `BD`, `US`) or **country names** from the bundled map (e.g. `Bangladesh`, `United States`). Matching is case-insensitive and ignores extra whitespace, accents, and most punctuation.
|
|
119
|
-
|
|
120
|
-
Common abbreviations also work: `USA`, `UK`, `UAE`, `DRC`, `Brunei`, `Laos`, `Burma`, etc.
|
|
121
|
-
|
|
122
|
-
**Coverage:** All **250** countries on the bundled map are supported by ISO code and by their SVG country name (normalization handles accents, spacing, and punctuation). Common abbreviations (`USA`, `UK`, `UAE`, `Brunei`, `Laos`, etc.) are also supported. Run `npm run verify` to validate data integrity before every build.
|
|
123
|
-
|
|
124
|
-
```tsx
|
|
125
|
-
<WorldMap
|
|
126
|
-
connectionBase="Bangladesh"
|
|
127
|
-
connectedCountries={['United States', 'India', 'United Kingdom']}
|
|
128
|
-
/>
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
Use `normalizeCountryName` from the package if you need the same normalization in your app:
|
|
132
|
-
|
|
133
|
-
```tsx
|
|
134
|
-
import { normalizeCountryName } from 'world-map-svg'
|
|
135
|
-
|
|
136
|
-
normalizeCountryName(" Côte d'Ivoire ") // "
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
## Props
|
|
140
|
-
|
|
141
|
-
| Prop | Type | Default | Description |
|
|
142
|
-
|------|------|---------|-------------|
|
|
143
|
-
| `backgroundColor` | `string` | `transparent` | Map background color |
|
|
144
|
-
| `countryColor` | `string` | `#093C5D` | Base fill color for countries |
|
|
145
|
-
| `svgUrl` | `string` | bundled SVG | Custom SVG URL to override the default world map |
|
|
146
|
-
| `showConnections` | `boolean` | `true` | Show carved connection lines |
|
|
147
|
-
| `connectionBase` | `string` | `BD` | Hub country — ISO code (e.g. `BD`) or name (e.g. `Bangladesh`) |
|
|
148
|
-
| `connectedCountries` | `string[]` | `['US', 'IN']` | Connected endpoints — ISO codes and/or names (e.g. `['United States', 'India']`) |
|
|
149
|
-
| `onCountryHover` | `(code, name, x, y) => void` | - | Fires when hovering a country path. Suppresses built-in tooltip. |
|
|
150
|
-
| `onCountryClick` | `(code, name, x, y) => void` | - | Fires when clicking a country path. Suppresses built-in click tooltip. |
|
|
151
|
-
| `onConnectionDotHover` | `(code, name, x, y) => void` | - | Fires when hovering a connection dot. |
|
|
152
|
-
| `onConnectionDotClick` | `(code, name, x, y) => void` | - | Fires when clicking a connection dot. |
|
|
153
|
-
| `className` | `string` | - | Additional CSS class for the container |
|
|
154
|
-
|
|
155
|
-
## Development
|
|
156
|
-
|
|
157
|
-
```bash
|
|
158
|
-
npm install
|
|
159
|
-
npm run dev # Start playground dev server
|
|
160
|
-
npm run build # Build library for publishing
|
|
161
|
-
npm run lint
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
The default SVG map data is bundled with the package. You can override it via the `svgUrl` prop.
|
|
165
|
-
|
|
166
|
-
## Publish Checklist
|
|
167
|
-
|
|
168
|
-
1. Confirm package name availability:
|
|
169
|
-
|
|
170
|
-
```bash
|
|
171
|
-
npm view world-map-svg
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
If taken, rename to a scoped package in `package.json` (for example `@yourname/world-map-svg`).
|
|
175
|
-
|
|
176
|
-
2. Update package metadata in `package.json`:
|
|
177
|
-
- `repository.url`
|
|
178
|
-
- `bugs.url`
|
|
179
|
-
- `homepage`
|
|
180
|
-
|
|
181
|
-
3. Run release checks:
|
|
182
|
-
|
|
183
|
-
```bash
|
|
184
|
-
npm run build
|
|
185
|
-
npm run lint
|
|
186
|
-
npm pack --dry-run
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
4. Login and publish:
|
|
190
|
-
|
|
191
|
-
```bash
|
|
192
|
-
npm login
|
|
193
|
-
npm publish --access public
|
|
194
|
-
```
|
|
1
|
+
# world-map-svg
|
|
2
|
+
|
|
3
|
+
Interactive SVG world map React component with zoom, pan, and country selection.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install world-map-svg
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { WorldMap } from 'world-map-svg'
|
|
15
|
+
import 'world-map-svg/style.css'
|
|
16
|
+
|
|
17
|
+
function App() {
|
|
18
|
+
return (
|
|
19
|
+
<div style={{ width: '100%', height: '500px' }}>
|
|
20
|
+
<WorldMap
|
|
21
|
+
countryColor="#093C5D"
|
|
22
|
+
/>
|
|
23
|
+
</div>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Demo Usage
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import { useState } from 'react'
|
|
32
|
+
import { WorldMap } from 'world-map-svg'
|
|
33
|
+
import 'world-map-svg/style.css'
|
|
34
|
+
|
|
35
|
+
export function MapDemo() {
|
|
36
|
+
const [hover, setHover] = useState<{ name: string; x: number; y: number } | null>(null)
|
|
37
|
+
const [modal, setModal] = useState<{ code: string; name: string } | null>(null)
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div style={{ position: 'relative', width: '100%', height: 600 }}>
|
|
41
|
+
<WorldMap
|
|
42
|
+
onCountryHover={(code, name, x, y) => setHover({ name, x, y })}
|
|
43
|
+
onCountryClick={(code, name) => setModal({ code, name })}
|
|
44
|
+
/>
|
|
45
|
+
|
|
46
|
+
{hover && (
|
|
47
|
+
<div style={{ position: 'absolute', left: hover.x + 12, top: hover.y + 12 }}>
|
|
48
|
+
{hover.name}
|
|
49
|
+
</div>
|
|
50
|
+
)}
|
|
51
|
+
|
|
52
|
+
{modal && (
|
|
53
|
+
<div>
|
|
54
|
+
<h3>{modal.name}</h3>
|
|
55
|
+
<p>{modal.code}</p>
|
|
56
|
+
</div>
|
|
57
|
+
)}
|
|
58
|
+
</div>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Hover gets the country name and pointer position. Click gets the country name and code, so your app can open a modal and load any extra data you need.
|
|
64
|
+
|
|
65
|
+
## Full Props Setup
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { useState } from 'react'
|
|
69
|
+
import { WorldMap } from 'world-map-svg'
|
|
70
|
+
import 'world-map-svg/style.css'
|
|
71
|
+
|
|
72
|
+
export function FullMapSetup() {
|
|
73
|
+
const [hover, setHover] = useState<{ name: string; x: number; y: number } | null>(null)
|
|
74
|
+
const [selected, setSelected] = useState<{ code: string; name: string } | null>(null)
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<div style={{ position: 'relative', width: '100%', height: 600 }}>
|
|
78
|
+
<WorldMap
|
|
79
|
+
backgroundColor="#f8fbff"
|
|
80
|
+
countryColor="#093C5D"
|
|
81
|
+
className="my-map"
|
|
82
|
+
showConnections
|
|
83
|
+
connectionBase="BD"
|
|
84
|
+
connectedCountries={['US', 'IN', 'GB', 'AE']}
|
|
85
|
+
onCountryHover={(code, name, x, y) => setHover({ name: `${name} (${code})`, x, y })}
|
|
86
|
+
onCountryClick={(code, name) => setSelected({ code, name })}
|
|
87
|
+
onConnectionDotHover={(code, name) => {
|
|
88
|
+
// Optional: show dot-specific tooltip
|
|
89
|
+
console.log('dot hover', code, name)
|
|
90
|
+
}}
|
|
91
|
+
onConnectionDotClick={(code, name) => {
|
|
92
|
+
// Optional: open modal or route to a detail page
|
|
93
|
+
console.log('dot click', code, name)
|
|
94
|
+
}}
|
|
95
|
+
/>
|
|
96
|
+
|
|
97
|
+
{hover && (
|
|
98
|
+
<div style={{ position: 'absolute', left: hover.x + 12, top: hover.y + 12 }}>
|
|
99
|
+
{hover.name}
|
|
100
|
+
</div>
|
|
101
|
+
)}
|
|
102
|
+
|
|
103
|
+
{selected && (
|
|
104
|
+
<div>
|
|
105
|
+
<h3>{selected.name}</h3>
|
|
106
|
+
<p>Country code: {selected.code}</p>
|
|
107
|
+
</div>
|
|
108
|
+
)}
|
|
109
|
+
</div>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
If you pass `onCountryHover` or `onCountryClick`, your app controls the hover/click UI (popover/modal). If you do not pass them, the built-in tooltip behavior is used.
|
|
115
|
+
|
|
116
|
+
### Connection country names
|
|
117
|
+
|
|
118
|
+
`connectionBase` and `connectedCountries` accept **ISO 3166-1 alpha-2 codes** (e.g. `BD`, `US`) or **country names** from the bundled map (e.g. `Bangladesh`, `United States`). Matching is case-insensitive and ignores extra whitespace, accents, and most punctuation.
|
|
119
|
+
|
|
120
|
+
Common abbreviations also work: `USA`, `UK`, `UAE`, `DRC`, `Brunei`, `Laos`, `Burma`, etc.
|
|
121
|
+
|
|
122
|
+
**Coverage:** All **250** countries on the bundled map are supported by ISO code and by their SVG country name (normalization handles accents, spacing, and punctuation). Common abbreviations (`USA`, `UK`, `UAE`, `Brunei`, `Laos`, etc.) are also supported. Run `npm run verify` to validate data integrity before every build.
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
<WorldMap
|
|
126
|
+
connectionBase="Bangladesh"
|
|
127
|
+
connectedCountries={['United States', 'India', 'United Kingdom']}
|
|
128
|
+
/>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Use `normalizeCountryName` from the package if you need the same normalization in your app:
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
import { normalizeCountryName } from 'world-map-svg'
|
|
135
|
+
|
|
136
|
+
normalizeCountryName(" Côte d'Ivoire ") // "cotedivoire"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Props
|
|
140
|
+
|
|
141
|
+
| Prop | Type | Default | Description |
|
|
142
|
+
|------|------|---------|-------------|
|
|
143
|
+
| `backgroundColor` | `string` | `transparent` | Map background color |
|
|
144
|
+
| `countryColor` | `string` | `#093C5D` | Base fill color for countries |
|
|
145
|
+
| `svgUrl` | `string` | bundled SVG | Custom SVG URL to override the default world map |
|
|
146
|
+
| `showConnections` | `boolean` | `true` | Show carved connection lines |
|
|
147
|
+
| `connectionBase` | `string` | `BD` | Hub country — ISO code (e.g. `BD`) or name (e.g. `Bangladesh`) |
|
|
148
|
+
| `connectedCountries` | `string[]` | `['US', 'IN']` | Connected endpoints — ISO codes and/or names (e.g. `['United States', 'India']`) |
|
|
149
|
+
| `onCountryHover` | `(code, name, x, y) => void` | - | Fires when hovering a country path. Suppresses built-in tooltip. |
|
|
150
|
+
| `onCountryClick` | `(code, name, x, y) => void` | - | Fires when clicking a country path. Suppresses built-in click tooltip. |
|
|
151
|
+
| `onConnectionDotHover` | `(code, name, x, y) => void` | - | Fires when hovering a connection dot. |
|
|
152
|
+
| `onConnectionDotClick` | `(code, name, x, y) => void` | - | Fires when clicking a connection dot. |
|
|
153
|
+
| `className` | `string` | - | Additional CSS class for the container |
|
|
154
|
+
|
|
155
|
+
## Development
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
npm install
|
|
159
|
+
npm run dev # Start playground dev server
|
|
160
|
+
npm run build # Build library for publishing
|
|
161
|
+
npm run lint
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The default SVG map data is bundled with the package. You can override it via the `svgUrl` prop.
|
|
165
|
+
|
|
166
|
+
## Publish Checklist
|
|
167
|
+
|
|
168
|
+
1. Confirm package name availability:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
npm view world-map-svg
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
If taken, rename to a scoped package in `package.json` (for example `@yourname/world-map-svg`).
|
|
175
|
+
|
|
176
|
+
2. Update package metadata in `package.json`:
|
|
177
|
+
- `repository.url`
|
|
178
|
+
- `bugs.url`
|
|
179
|
+
- `homepage`
|
|
180
|
+
|
|
181
|
+
3. Run release checks:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
npm run build
|
|
185
|
+
npm run lint
|
|
186
|
+
npm pack --dry-run
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
4. Login and publish:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
npm login
|
|
193
|
+
npm publish --access public
|
|
194
|
+
```
|
|
@@ -1035,4 +1035,4 @@ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{val
|
|
|
1035
1035
|
title="Zimbabwe"
|
|
1036
1036
|
id="ZW" />
|
|
1037
1037
|
</svg>
|
|
1038
|
-
`,r={AD:{x:479.3,y:331.5},AE:{x:626.4,y:392.9},AF:{x:664.9,y:361.8},AG:{x:301.5,y:413.8},AI:{x:297.9,y:411.2},AL:{x:531.5,y:336.6},AM:{x:601.2,y:340.6},AO:{x:525.1,y:494.6},AR:{x:296.3,y:586.5},AS:{x:1006.2,y:503.2},AT:{x:512.3,y:310.9},AU:{x:856.4,y:568.8},AW:{x:278.5,y:427.7},AX:{x:531.2,y:250.9},AZ:{x:608.4,y:340.3},BA:{x:524.5,y:326.1},BB:{x:307.8,y:425.8},BD:{x:728.4,y:394.8},BE:{x:487.4,y:299},BF:{x:470.5,y:428.5},BG:{x:546.4,y:330.7},BH:{x:616.7,y:387.7},BI:{x:558.8,y:472.4},BJ:{x:481.3,y:436.8},BL:{x:298.5,y:412.2},BN:{x:796.8,y:450.3},BO:{x:296.5,y:509.3},BM:{x:293.1,y:367.5},BQ:{x:290.6,y:421},BR:{x:322.2,y:505.6},BS:{x:262,y:394},BT:{x:728.6,y:383.1},BV:{x:484.5,y:644.8},BW:{x:544.1,y:527},BY:{x:553.3,y:284.1},BZ:{x:226.5,y:414.3},CA:{x:203.1,y:173.2},CC:{x:746.8,y:497.1},CD:{x:535.9,y:474.4},CF:{x:533.6,y:444.3},CG:{x:516.6,y:464.8},CH:{x:497.9,y:314.7},CI:{x:459.3,y:441.8},CK:{x:26.4,y:523.5},CL:{x:228.1,y:582.3},CM:{x:509.6,y:442.2},CN:{x:767.3,y:348.2},CO:{x:270.2,y:451.4},CR:{x:238.5,y:435.9},CU:{x:251.7,y:401.4},CV:{x:407.5,y:417.7},CW:{x:281.4,y:428.6},CX:{x:771.4,y:492.4},CY:{x:568.7,y:358.2},CZ:{x:518.3,y:302},DE:{x:504.2,y:295.3},DJ:{x:594.4,y:429.7},DK:{x:507.5,y:272.2},DM:{x:302.7,y:419.4},DO:{x:278,y:409.6},DZ:{x:479.5,y:380.2},EC:{x:240.7,y:467.9},EG:{x:561.3,y:384.9},EE:{x:545.1,y:259.8},EH:{x:438.7,y:393.1},ER:{x:586.5,y:420},ES:{x:455.5,y:354.7},ET:{x:588.5,y:437.2},FI:{x:548.1,y:218.7},FJ:{x:974.9,y:511.5},FK:{x:308,y:632.6},FM:{x:897.3,y:442.1},FO:{x:455.5,y:241.2},FR:{x:481.6,y:316.1},GA:{x:507.4,y:465.2},GB:{x:465.9,y:274.3},GE:{x:596.5,y:332.3},GD:{x:301.8,y:428.9},GF:{x:325.8,y:451.9},GG:{x:467.7,y:303.5},GH:{x:472,y:440.6},GI:{x:459.9,y:354.7},GL:{x:356.7,y:126.7},GM:{x:431.9,y:425.1},GN:{x:443,y:435},GO:{x:607.6,y:495.4},GP:{x:302.3,y:417.1},GQ:{x:502.6,y:456.3},GR:{x:542.1,y:346.6},GS:{x:384.7,y:654.1},GT:{x:221.7,y:418.3},GU:{x:881.3,y:425.1},GW:{x:432.3,y:429.8},GY:{x:309.5,y:449.3},HK:{x:795.1,y:398.9},HM:{x:681.3,y:638.5},HN:{x:232.8,y:421.3},HR:{x:521.1,y:323.9},HT:{x:269.8,y:408.7},HU:{x:529.6,y:313.2},ID:{x:806.3,y:470},IE:{x:451.9,y:285.6},IL:{x:573.3,y:370.3},IM:{x:462.1,y:281.9},IN:{x:707.1,y:400.5},IO:{x:678.2,y:483.4},IQ:{x:597.4,y:364.2},IR:{x:625.5,y:366.2},IS:{x:421.5,y:221.6},IT:{x:510.1,y:333.2},JE:{x:468.9,y:304.6},JM:{x:258,y:411.5},JO:{x:579.1,y:370.9},JP:{x:853.1,y:356.5},JU:{x:594.9,y:511.2},KE:{x:581.2,y:461.8},KG:{x:684.6,y:336.3},KH:{x:769.5,y:427.6},KI:{x:516.3,y:473.5},KM:{x:598,y:496.3},KN:{x:299,y:414.1},KP:{x:832.8,y:339.4},KR:{x:835.4,y:355.3},XK:{x:533.5,y:331.4},KW:{x:608.2,y:377.3},KY:{x:248.7,y:407.4},KZ:{x:662.8,y:307.5},LA:{x:766.4,y:411.1},LB:{x:575.5,y:362.4},LC:{x:303.8,y:423.8},LI:{x:501.7,y:313.2},LK:{x:701.6,y:440.9},LR:{x:448.4,y:444.9},LS:{x:554.1,y:549.5},LT:{x:541.8,y:277.4},LU:{x:492,y:302.1},LV:{x:544,y:268.8},LY:{x:523.3,y:386.1},MA:{x:454.9,y:369},MC:{x:495.7,y:326.8},MD:{x:554.5,y:314},MG:{x:606.4,y:516.8},ME:{x:529.3,y:330.8},MF:{x:297.9,y:411.6},MH:{x:950,y:439.2},MK:{x:535.9,y:335},ML:{x:463.6,y:412.7},MO:{x:793.5,y:399.3},MM:{x:746.2,y:407.6},MN:{x:766.3,y:313.4},MP:{x:883.2,y:416.3},MQ:{x:303.6,y:421.6},MR:{x:444.2,y:402.6},MS:{x:300.4,y:415.6},MT:{x:515.2,y:355.3},MU:{x:636.4,y:520.6},MV:{x:681,y:452.5},MW:{x:571.1,y:500.3},MX:{x:187.1,y:394.1},MY:{x:782.1,y:451.4},MZ:{x:574.6,y:516.5},NA:{x:526.8,y:529.1},NC:{x:935.3,y:522.5},NE:{x:497.5,y:412.7},NF:{x:946.2,y:547.7},NG:{x:499.2,y:437.4},NI:{x:235.2,y:426.7},NL:{x:489.7,y:291.4},NO:{x:525.1,y:219.1},NP:{x:710.9,y:380.3},NR:{x:943.4,y:464.4},NU:{x:1008.5,y:517.1},NZ:{x:965.7,y:600.7},OM:{x:631.8,y:401.3},PA:{x:250.1,y:439.4},PE:{x:264.4,y:489},PF:{x:71,y:505},PG:{x:891.4,y:481.1},PH:{x:816.7,y:426.1},PK:{x:669.4,y:373.1},PL:{x:528.5,y:292.2},PM:{x:317,y:314.2},PN:{x:114.8,y:533},PR:{x:287.9,y:411.2},PS:{x:572.8,y:369},PT:{x:422.3,y:349.7},PW:{x:847.9,y:447.9},PY:{x:310.9,y:530.3},QA:{x:618.5,y:389.8},RE:{x:630.8,y:523.2},RO:{x:545,y:317.9},RS:{x:533.6,y:325},RU:{x:769.4,y:187.8},RW:{x:558.7,y:468.3},SA:{x:601.5,y:392.4},SB:{x:927.6,y:488.8},SC:{x:630.6,y:476},SD:{x:559.7,y:419},SE:{x:524.4,y:234.6},SG:{x:766.3,y:459.1},SH:{x:446.7,y:496.6},SI:{x:516.8,y:317.4},SJ:{x:509.3,y:121.1},SK:{x:530.2,y:306.9},SL:{x:441.8,y:439.3},SM:{x:509.9,y:326.1},SN:{x:434.3,y:422},SO:{x:604.5,y:448.5},SR:{x:317.7,y:452},SS:{x:558.3,y:440.9},ST:{x:494.4,y:460.5},SV:{x:225.4,y:424.1},SX:{x:297.9,y:411.8},SY:{x:584.5,y:359.1},SZ:{x:563.2,y:539.7},TC:{x:272.9,y:400.5},TD:{x:527.4,y:418.8},TF:{x:646.4,y:616.3},TG:{x:477.3,y:438.8},TH:{x:759.8,y:425.9},TJ:{x:674.8,y:344.9},TK:{x:1003,y:488},TL:{x:827.6,y:487.6},TM:{x:642.1,y:344.3},TN:{x:501.6,y:362.4},TO:{x:995.1,y:519.9},TR:{x:573.8,y:344.4},TT:{x:303.1,y:432.9},TV:{x:973.8,y:483.4},TW:{x:812,y:395.1},TZ:{x:572.8,y:480.8},UA:{x:562.3,y:307.5},UG:{x:565.5,y:459.1},"UM-DQ":{x:25.8,y:464},"UM-FQ":{x:990,y:462.3},"UM-HQ":{x:989.5,y:460.7},"UM-JQ":{x:1009.4,y:415.6},"UM-MQ":{x:987.4,y:380.9},"UM-WQ":{x:942.6,y:408.1},US:{x:143.6,y:291},UY:{x:318.3,y:559},UZ:{x:656.1,y:335.4},VA:{x:509.8,y:333.9},VC:{x:303,y:426.3},VE:{x:288,y:444.9},VG:{x:293.9,y:410.2},VI:{x:293,y:411.8},VN:{x:771.8,y:417.4},VU:{x:947,y:511},WF:{x:988,y:501.7},WS:{x:1002.2,y:501.6},YE:{x:611.1,y:418.6},YT:{x:601.6,y:499},ZA:{x:551.1,y:569},ZM:{x:553,y:500},ZW:{x:556.6,y:517.1}},i={aliases:{usa:`US`,"u s a":`US`,"u s":`US`,"united states of america":`US`,uk:`GB`,"u k":`GB`,"great britain":`GB`,england:`GB`,britain:`GB`,uae:`AE`,drc:`CD`,"dr congo":`CD`,"democratic republic of the congo":`CD`,"republic of the congo":`CG`,congo:`CG`,"congo brazzaville":`CG`,"south korea":`KR`,"republic of korea":`KR`,korea:`KR`,"north korea":`KP`,czechia:`CZ`,"cote d ivoire":`CI`,"ivory coast":`CI`,russia:`RU`,"viet nam":`VN`,brunei:`BN`,laos:`LA`,"lao pdr":`LA`,micronesia:`FM`,"north macedonia":`MK`,macedonia:`MK`,"cabo verde":`CV`,"cape verde":`CV`,eswatini:`SZ`,swaziland:`SZ`,burma:`MM`,palestine:`PS`,"east timor":`TL`,vatican:`VA`,turkiye:`TR`,curacao:`CW`,aland:`AX`,bonaire:`BQ`,"caribbean netherlands":`BQ`,holland:`NL`,"the netherlands":`NL`,"sint maarten":`SX`,"st maarten":`SX`,"saint maarten":`SX`,"saint martin french":`MF`,"saint martin fr":`MF`,taiwan:`TW`,"hong kong":`HK`,macau:`MO`,macao:`MO`,iran:`IR`,syria:`SY`,tanzania:`TZ`,bolivia:`BO`,moldova:`MD`,"virgin islands":`VI`,"us virgin islands":`VI`,"british virgin islands":`VG`,reunion:`RE`,"south sudan":`SS`},disambiguated:{MF:[`Saint-Martin`,`Saint Martin (French part)`],SX:[`Sint Maarten`,`St Maarten`,`Saint Maarten`]}},a=i.aliases,o=i.disambiguated;function s(e){return e.trim().normalize(`NFD`).replace(/[\u0300-\u036f]/g,``).toLowerCase().replace(/[''`]/g,``).replace(/[.,()]/g,` `).replace(/[^a-z0-9\s-]/g,` `).replace(/\s+/g,` `).trim()}function c(e){let t=[];return e.querySelectorAll(`path[id][title]`).forEach(e=>{let n=e.getAttribute(`id`)?.trim().toUpperCase(),r=e.getAttribute(`title`)?.trim();n&&r&&t.push({code:n,name:r})}),t.sort((e,t)=>e.name.localeCompare(t.name))}function l(e){let t=c(e),n=new Map;for(let{code:e,name:r}of t){let t=s(r),i=n.get(t)??[];i.includes(e)||i.push(e),n.set(t,i)}let r=new Map;for(let[e,t]of Object.entries(a))r.set(s(e),t.toUpperCase());for(let[e,t]of Object.entries(o))for(let n of t)r.set(s(n),e.toUpperCase());for(let{code:e,name:i}of t){r.set(s(e),e);let t=s(i);(n.get(t)?.length??0)===1&&r.set(t,e)}return r}function u(e,t){let n=e.trim();return n?t.get(s(n))??null:null}var d=e=>/^#([0-9a-fA-F]{3}){1,2}$/.test(e),f=e=>e.toString(16).padStart(2,`0`),p=(e,t)=>{if(!d(e))return e;let n=e.replace(`#`,``),r=n.length===3?n.split(``).map(e=>e+e).join(``):n,i=parseInt(r,16),a=Math.min(255,Math.max(0,(i>>16&255)+t)),o=Math.min(255,Math.max(0,(i>>8&255)+t)),s=Math.min(255,Math.max(0,(i&255)+t));return`#${f(a)}${f(o)}${f(s)}`};function m(e,t){let n=t.x-e.x,r=t.y-e.y,i=Math.sqrt(n*n+r*r),a=(e.y+t.y)/2,o=Math.max(Math.min(i*.35,220),15),s=e.x+n*.25,c=a-o,l=e.x+n*.75,u=a-o;return`M ${e.x} ${e.y} C ${s},${c} ${l},${u} ${t.x} ${t.y}`}function h({backgroundColor:i,countryColor:a=`#093C5D`,svgUrl:o,className:s,showConnections:c=!0,connectionBase:d=`BD`,connectedCountries:f=[`US`,`IN`],onCountryHover:h,onCountryClick:g,onConnectionDotHover:_,onConnectionDotClick:v}){let[y,b]=(0,e.useState)(``),[x,S]=(0,e.useState)({name:``,x:0,y:0,visible:!1}),[C,w]=(0,e.useState)({name:``,x:0,y:0,visible:!1}),[T,E]=(0,e.useState)(1),[D,O]=(0,e.useState)({x:0,y:0}),[k,A]=(0,e.useState)(!1),j=(0,e.useRef)(null),M=(0,e.useRef)({isPanning:!1,startX:0,startY:0,originX:0,originY:0,moved:!1}),N=(0,e.useMemo)(()=>({hover:p(a,24),selected:p(a,-24),stroke:p(a,-36)}),[a]);(0,e.useEffect)(()=>{let e=!0;return(async()=>{try{let t;if(o){let e=await fetch(o);if(!e.ok)throw Error(`Failed to fetch SVG: ${e.status}`);t=await e.text()}else t=n;if(!e)return;let i=new DOMParser().parseFromString(t,`image/svg+xml`),a=i.querySelector(`svg`);if(!a){b(``);return}if(!a.getAttribute(`viewBox`)){let e=parseFloat(a.getAttribute(`width`)||``),t=parseFloat(a.getAttribute(`height`)||``);Number.isFinite(e)&&Number.isFinite(t)&&a.setAttribute(`viewBox`,`0 0 ${e} ${t}`)}if(a.removeAttribute(`width`),a.removeAttribute(`height`),a.setAttribute(`class`,`map-svg`),a.querySelectorAll(`path[title]`).forEach(e=>{let t=e.getAttribute(`title`)||``;t&&(e.classList.add(`country`),e.setAttribute(`data-name`,t))}),c){let e=l(a),t=u(d,e),n=t?r[t]:void 0;if(t&&n){let o=e=>{let t=i.createElementNS(`http://www.w3.org/2000/svg`,`path`);return t.setAttribute(`d`,e),t.setAttribute(`class`,`connection-line`),t.setAttribute(`fill`,`none`),t},s=e=>a.querySelector(`#${e}`)?.getAttribute(`title`)||e,c=(e,t,n,r,a)=>{let o=i.createElementNS(`http://www.w3.org/2000/svg`,`circle`);return o.setAttribute(`cx`,String(e)),o.setAttribute(`cy`,String(t)),o.setAttribute(`r`,`3`),o.setAttribute(`class`,n),o.setAttribute(`data-country-code`,r),o.setAttribute(`data-country-name`,a),o},l=new Set;for(let i of f){let d=u(i,e);if(!d||d===t)continue;let f=r[d];if(!f)continue;let p=m(f,n);if(a.appendChild(o(p)),!l.has(d)){let e=s(d);a.appendChild(c(f.x,f.y,`connection-dot connection-dot-start`,d,e)),l.add(d)}}if(!l.has(t)){let e=s(t);a.appendChild(c(n.x,n.y,`connection-dot connection-dot-end`,t,e)),l.add(t)}}}b(new XMLSerializer().serializeToString(a))}catch{e&&b(``)}})(),()=>{e=!1}},[o,c,d,f]);let P=e=>!e||!(e instanceof Element)?null:e.closest(`[data-name]`),F=e=>!e||!(e instanceof Element)?null:e.closest(`.connection-dot`),I=e=>{let t=j.current?.getBoundingClientRect();return t?{x:e.clientX-t.left,y:e.clientY-t.top}:{x:0,y:0}},L=()=>{let e=j.current;if(!e)return;let t=e.querySelector(`.country.is-selected`);t&&t.classList.remove(`is-selected`)},R=e=>{if(M.current.isPanning){let t=e.clientX-M.current.startX,n=e.clientY-M.current.startY;O({x:M.current.originX+t,y:M.current.originY+n}),Math.sqrt(t*t+n*n)>5&&(M.current.moved=!0),S(e=>({...e,visible:!1}));return}let t=F(e.target),n=t?.getAttribute(`data-country-code`),r=t?.getAttribute(`data-country-name`);if(n&&r){if(_){let{x:t,y:i}=I(e);_(n,r,t,i)}S(e=>({...e,visible:!1}));return}let i=P(e.target),a=i?.dataset.name;if(!a){S(e=>({...e,visible:!1}));return}let{x:o,y:s}=I(e);if(h){h(i.getAttribute(`id`)||``,a,o,s),S(e=>({...e,visible:!1}));return}S({name:a,x:o,y:s,visible:!0})},z=()=>{S(e=>({...e,visible:!1})),M.current.isPanning=!1,A(!1)},B=e=>{if(M.current.moved){M.current.moved=!1;return}let t=F(e.target),n=t?.getAttribute(`data-country-code`),r=t?.getAttribute(`data-country-name`);if(n&&r){if(v){let{x:t,y:i}=I(e);v(n,r,t,i)}return}let i=P(e.target),a=i?.dataset.name;if(!a){L(),w(e=>({...e,visible:!1}));return}let{x:o,y:s}=I(e);if(g){g(i.getAttribute(`id`)||``,a,o,s),w(e=>({...e,visible:!1}));return}w({name:a,x:o,y:s,visible:!0}),L(),i.classList.add(`is-selected`)},V=e=>{e.preventDefault();let t=e.deltaY>0?-1:1;E(e=>{let n=e+t*.1;return Math.min(3,Math.max(1,Number(n.toFixed(2))))})},H=e=>{if(e.button!==0)return;let t=F(e.target),n=P(e.target);if(t||n){M.current.isPanning=!1,M.current.moved=!1;return}e.currentTarget.setPointerCapture(e.pointerId),M.current.isPanning=!0,M.current.startX=e.clientX,M.current.startY=e.clientY,M.current.originX=D.x,M.current.originY=D.y,M.current.moved=!1,A(!0)},U=()=>{M.current.isPanning=!1,A(!1)},W={"--map-background":i||`transparent`,"--country-fill":a,"--country-hover":N.hover,"--country-selected":N.selected,"--country-stroke":N.stroke},G=[`map-container`,s].filter(Boolean).join(` `);return(0,t.jsxs)(`div`,{className:k?`${G} is-panning`.trim():G,style:W,ref:j,onPointerMove:R,onPointerLeave:z,onPointerDown:H,onPointerUp:U,onClick:B,onWheel:V,role:`img`,"aria-label":`World map with clickable countries`,children:[y?(0,t.jsx)(`div`,{className:`map-viewport`,style:{transform:`translate(${D.x}px, ${D.y}px) scale(${T})`},children:(0,t.jsx)(`div`,{className:`map-svg-wrap`,dangerouslySetInnerHTML:{__html:y}})}):(0,t.jsx)(`div`,{className:`map-loading`,children:`Loading map...`}),x.visible&&(0,t.jsx)(`div`,{className:`map-tooltip`,style:{left:x.x,top:x.y},role:`status`,children:x.name}),C.visible&&(0,t.jsx)(`div`,{className:`map-tooltip is-pinned`,style:{left:C.x,top:C.y},role:`status`,children:C.name})]})}exports.WorldMap=h,exports.default=h,exports.buildCountryLookup=l,exports.listMapCountries=c,exports.normalizeCountryName=s,exports.resolveCountryCode=u;
|
|
1038
|
+
`,r={AD:{x:479.3,y:331.5},AE:{x:626.4,y:392.9},AF:{x:664.9,y:361.8},AG:{x:301.5,y:413.8},AI:{x:297.9,y:411.2},AL:{x:531.5,y:336.6},AM:{x:601.2,y:340.6},AO:{x:525.1,y:494.6},AR:{x:296.3,y:586.5},AS:{x:1006.2,y:503.2},AT:{x:512.3,y:310.9},AU:{x:856.4,y:568.8},AW:{x:278.5,y:427.7},AX:{x:531.2,y:250.9},AZ:{x:608.4,y:340.3},BA:{x:524.5,y:326.1},BB:{x:307.8,y:425.8},BD:{x:728.4,y:394.8},BE:{x:487.4,y:299},BF:{x:470.5,y:428.5},BG:{x:546.4,y:330.7},BH:{x:616.7,y:387.7},BI:{x:558.8,y:472.4},BJ:{x:481.3,y:436.8},BL:{x:298.5,y:412.2},BN:{x:796.8,y:450.3},BO:{x:296.5,y:509.3},BM:{x:293.1,y:367.5},BQ:{x:290.6,y:421},BR:{x:322.2,y:505.6},BS:{x:262,y:394},BT:{x:728.6,y:383.1},BV:{x:484.5,y:644.8},BW:{x:544.1,y:527},BY:{x:553.3,y:284.1},BZ:{x:226.5,y:414.3},CA:{x:203.1,y:173.2},CC:{x:746.8,y:497.1},CD:{x:535.9,y:474.4},CF:{x:533.6,y:444.3},CG:{x:516.6,y:464.8},CH:{x:497.9,y:314.7},CI:{x:459.3,y:441.8},CK:{x:26.4,y:523.5},CL:{x:228.1,y:582.3},CM:{x:509.6,y:442.2},CN:{x:767.3,y:348.2},CO:{x:270.2,y:451.4},CR:{x:238.5,y:435.9},CU:{x:251.7,y:401.4},CV:{x:407.5,y:417.7},CW:{x:281.4,y:428.6},CX:{x:771.4,y:492.4},CY:{x:568.7,y:358.2},CZ:{x:518.3,y:302},DE:{x:504.2,y:295.3},DJ:{x:594.4,y:429.7},DK:{x:507.5,y:272.2},DM:{x:302.7,y:419.4},DO:{x:278,y:409.6},DZ:{x:479.5,y:380.2},EC:{x:240.7,y:467.9},EG:{x:561.3,y:384.9},EE:{x:545.1,y:259.8},EH:{x:438.7,y:393.1},ER:{x:586.5,y:420},ES:{x:455.5,y:354.7},ET:{x:588.5,y:437.2},FI:{x:548.1,y:218.7},FJ:{x:974.9,y:511.5},FK:{x:308,y:632.6},FM:{x:897.3,y:442.1},FO:{x:455.5,y:241.2},FR:{x:481.6,y:316.1},GA:{x:507.4,y:465.2},GB:{x:465.9,y:274.3},GE:{x:596.5,y:332.3},GD:{x:301.8,y:428.9},GF:{x:325.8,y:451.9},GG:{x:467.7,y:303.5},GH:{x:472,y:440.6},GI:{x:459.9,y:354.7},GL:{x:356.7,y:126.7},GM:{x:431.9,y:425.1},GN:{x:443,y:435},GO:{x:607.6,y:495.4},GP:{x:302.3,y:417.1},GQ:{x:502.6,y:456.3},GR:{x:542.1,y:346.6},GS:{x:384.7,y:654.1},GT:{x:221.7,y:418.3},GU:{x:881.3,y:425.1},GW:{x:432.3,y:429.8},GY:{x:309.5,y:449.3},HK:{x:795.1,y:398.9},HM:{x:681.3,y:638.5},HN:{x:232.8,y:421.3},HR:{x:521.1,y:323.9},HT:{x:269.8,y:408.7},HU:{x:529.6,y:313.2},ID:{x:806.3,y:470},IE:{x:451.9,y:285.6},IL:{x:573.3,y:370.3},IM:{x:462.1,y:281.9},IN:{x:707.1,y:400.5},IO:{x:678.2,y:483.4},IQ:{x:597.4,y:364.2},IR:{x:625.5,y:366.2},IS:{x:421.5,y:221.6},IT:{x:510.1,y:333.2},JE:{x:468.9,y:304.6},JM:{x:258,y:411.5},JO:{x:579.1,y:370.9},JP:{x:853.1,y:356.5},JU:{x:594.9,y:511.2},KE:{x:581.2,y:461.8},KG:{x:684.6,y:336.3},KH:{x:769.5,y:427.6},KI:{x:516.3,y:473.5},KM:{x:598,y:496.3},KN:{x:299,y:414.1},KP:{x:832.8,y:339.4},KR:{x:835.4,y:355.3},XK:{x:533.5,y:331.4},KW:{x:608.2,y:377.3},KY:{x:248.7,y:407.4},KZ:{x:662.8,y:307.5},LA:{x:766.4,y:411.1},LB:{x:575.5,y:362.4},LC:{x:303.8,y:423.8},LI:{x:501.7,y:313.2},LK:{x:701.6,y:440.9},LR:{x:448.4,y:444.9},LS:{x:554.1,y:549.5},LT:{x:541.8,y:277.4},LU:{x:492,y:302.1},LV:{x:544,y:268.8},LY:{x:523.3,y:386.1},MA:{x:454.9,y:369},MC:{x:495.7,y:326.8},MD:{x:554.5,y:314},MG:{x:606.4,y:516.8},ME:{x:529.3,y:330.8},MF:{x:297.9,y:411.6},MH:{x:950,y:439.2},MK:{x:535.9,y:335},ML:{x:463.6,y:412.7},MO:{x:793.5,y:399.3},MM:{x:746.2,y:407.6},MN:{x:766.3,y:313.4},MP:{x:883.2,y:416.3},MQ:{x:303.6,y:421.6},MR:{x:444.2,y:402.6},MS:{x:300.4,y:415.6},MT:{x:515.2,y:355.3},MU:{x:636.4,y:520.6},MV:{x:681,y:452.5},MW:{x:571.1,y:500.3},MX:{x:187.1,y:394.1},MY:{x:782.1,y:451.4},MZ:{x:574.6,y:516.5},NA:{x:526.8,y:529.1},NC:{x:935.3,y:522.5},NE:{x:497.5,y:412.7},NF:{x:946.2,y:547.7},NG:{x:499.2,y:437.4},NI:{x:235.2,y:426.7},NL:{x:489.7,y:291.4},NO:{x:525.1,y:219.1},NP:{x:710.9,y:380.3},NR:{x:943.4,y:464.4},NU:{x:1008.5,y:517.1},NZ:{x:965.7,y:600.7},OM:{x:631.8,y:401.3},PA:{x:250.1,y:439.4},PE:{x:264.4,y:489},PF:{x:71,y:505},PG:{x:891.4,y:481.1},PH:{x:816.7,y:426.1},PK:{x:669.4,y:373.1},PL:{x:528.5,y:292.2},PM:{x:317,y:314.2},PN:{x:114.8,y:533},PR:{x:287.9,y:411.2},PS:{x:572.8,y:369},PT:{x:422.3,y:349.7},PW:{x:847.9,y:447.9},PY:{x:310.9,y:530.3},QA:{x:618.5,y:389.8},RE:{x:630.8,y:523.2},RO:{x:545,y:317.9},RS:{x:533.6,y:325},RU:{x:769.4,y:187.8},RW:{x:558.7,y:468.3},SA:{x:601.5,y:392.4},SB:{x:927.6,y:488.8},SC:{x:630.6,y:476},SD:{x:559.7,y:419},SE:{x:524.4,y:234.6},SG:{x:766.3,y:459.1},SH:{x:446.7,y:496.6},SI:{x:516.8,y:317.4},SJ:{x:509.3,y:121.1},SK:{x:530.2,y:306.9},SL:{x:441.8,y:439.3},SM:{x:509.9,y:326.1},SN:{x:434.3,y:422},SO:{x:604.5,y:448.5},SR:{x:317.7,y:452},SS:{x:558.3,y:440.9},ST:{x:494.4,y:460.5},SV:{x:225.4,y:424.1},SX:{x:297.9,y:411.8},SY:{x:584.5,y:359.1},SZ:{x:563.2,y:539.7},TC:{x:272.9,y:400.5},TD:{x:527.4,y:418.8},TF:{x:646.4,y:616.3},TG:{x:477.3,y:438.8},TH:{x:759.8,y:425.9},TJ:{x:674.8,y:344.9},TK:{x:1003,y:488},TL:{x:827.6,y:487.6},TM:{x:642.1,y:344.3},TN:{x:501.6,y:362.4},TO:{x:995.1,y:519.9},TR:{x:573.8,y:344.4},TT:{x:303.1,y:432.9},TV:{x:973.8,y:483.4},TW:{x:812,y:395.1},TZ:{x:572.8,y:480.8},UA:{x:562.3,y:307.5},UG:{x:565.5,y:459.1},"UM-DQ":{x:25.8,y:464},"UM-FQ":{x:990,y:462.3},"UM-HQ":{x:989.5,y:460.7},"UM-JQ":{x:1009.4,y:415.6},"UM-MQ":{x:987.4,y:380.9},"UM-WQ":{x:942.6,y:408.1},US:{x:143.6,y:291},UY:{x:318.3,y:559},UZ:{x:656.1,y:335.4},VA:{x:509.8,y:333.9},VC:{x:303,y:426.3},VE:{x:288,y:444.9},VG:{x:293.9,y:410.2},VI:{x:293,y:411.8},VN:{x:771.8,y:417.4},VU:{x:947,y:511},WF:{x:988,y:501.7},WS:{x:1002.2,y:501.6},YE:{x:611.1,y:418.6},YT:{x:601.6,y:499},ZA:{x:551.1,y:569},ZM:{x:553,y:500},ZW:{x:556.6,y:517.1}},i={aliases:{usa:`US`,unitedstatesofamerica:`US`,uk:`GB`,greatbritain:`GB`,england:`GB`,britain:`GB`,uae:`AE`,drc:`CD`,drcongo:`CD`,democraticrepublicofthecongo:`CD`,republicofthecongo:`CG`,congo:`CG`,congobrazzaville:`CG`,southkorea:`KR`,republicofkorea:`KR`,korea:`KR`,northkorea:`KP`,czechia:`CZ`,cotedivoire:`CI`,ivorycoast:`CI`,russia:`RU`,vietnam:`VN`,brunei:`BN`,laos:`LA`,laopdr:`LA`,micronesia:`FM`,northmacedonia:`MK`,macedonia:`MK`,caboverde:`CV`,capeverde:`CV`,eswatini:`SZ`,swaziland:`SZ`,burma:`MM`,palestine:`PS`,easttimor:`TL`,vatican:`VA`,turkiye:`TR`,curacao:`CW`,aland:`AX`,bonaire:`BQ`,caribbeannetherlands:`BQ`,holland:`NL`,thenetherlands:`NL`,sintmaarten:`SX`,stmaarten:`SX`,saintmaarten:`SX`,saintmartinfrench:`MF`,saintmartinfr:`MF`,taiwan:`TW`,hongkong:`HK`,macau:`MO`,macao:`MO`,iran:`IR`,syria:`SY`,tanzania:`TZ`,bolivia:`BO`,moldova:`MD`,virginislands:`VI`,usvirginislands:`VI`,britishvirginislands:`VG`,reunion:`RE`,southsudan:`SS`},disambiguated:{MF:[`saintmartin`,`saintmartinfrenchpart`],SX:[`sintmaarten`,`stmaarten`,`saintmaarten`]}},a=i.aliases,o=i.disambiguated;function s(e){return e.normalize(`NFD`).replace(/[\u0300-\u036f]/g,``).toLowerCase().replace(/[^a-z0-9]/g,``)}function c(e){let t=[];return e.querySelectorAll(`path[id][title]`).forEach(e=>{let n=e.getAttribute(`id`)?.trim().toUpperCase(),r=e.getAttribute(`title`)?.trim();n&&r&&t.push({code:n,name:r})}),t.sort((e,t)=>e.name.localeCompare(t.name))}function l(e){let t=c(e),n=new Map;for(let{code:e,name:r}of t){let t=s(r),i=n.get(t)??[];i.includes(e)||i.push(e),n.set(t,i)}let r=new Map;for(let[e,t]of Object.entries(a))r.set(s(e),t.toUpperCase());for(let[e,t]of Object.entries(o))for(let n of t)r.set(s(n),e.toUpperCase());for(let{code:e,name:i}of t){r.set(s(e),e);let t=s(i);(n.get(t)?.length??0)===1&&r.set(t,e)}return r}function u(e,t){let n=e.trim();return n?t.get(s(n))??null:null}var d=e=>/^#([0-9a-fA-F]{3}){1,2}$/.test(e),f=e=>e.toString(16).padStart(2,`0`),p=(e,t)=>{if(!d(e))return e;let n=e.replace(`#`,``),r=n.length===3?n.split(``).map(e=>e+e).join(``):n,i=parseInt(r,16),a=Math.min(255,Math.max(0,(i>>16&255)+t)),o=Math.min(255,Math.max(0,(i>>8&255)+t)),s=Math.min(255,Math.max(0,(i&255)+t));return`#${f(a)}${f(o)}${f(s)}`};function m(e,t){let n=t.x-e.x,r=t.y-e.y,i=Math.sqrt(n*n+r*r),a=(e.y+t.y)/2,o=Math.max(Math.min(i*.35,220),15),s=e.x+n*.25,c=a-o,l=e.x+n*.75,u=a-o;return`M ${e.x} ${e.y} C ${s},${c} ${l},${u} ${t.x} ${t.y}`}function h({backgroundColor:i,countryColor:a=`#093C5D`,svgUrl:o,className:s,showConnections:c=!0,connectionBase:d=`BD`,connectedCountries:f=[`US`,`IN`],onCountryHover:h,onCountryClick:g,onConnectionDotHover:_,onConnectionDotClick:v}){let[y,b]=(0,e.useState)(``),[x,S]=(0,e.useState)({name:``,x:0,y:0,visible:!1}),[C,w]=(0,e.useState)({name:``,x:0,y:0,visible:!1}),[T,E]=(0,e.useState)(1),[D,O]=(0,e.useState)({x:0,y:0}),[k,A]=(0,e.useState)(!1),j=(0,e.useRef)(null),M=(0,e.useRef)({isPanning:!1,startX:0,startY:0,originX:0,originY:0,moved:!1}),N=(0,e.useMemo)(()=>({hover:p(a,24),selected:p(a,-24),stroke:p(a,-36)}),[a]);(0,e.useEffect)(()=>{let e=!0;return(async()=>{try{let t;if(o){let e=await fetch(o);if(!e.ok)throw Error(`Failed to fetch SVG: ${e.status}`);t=await e.text()}else t=n;if(!e)return;let i=new DOMParser().parseFromString(t,`image/svg+xml`),a=i.querySelector(`svg`);if(!a){b(``);return}if(!a.getAttribute(`viewBox`)){let e=parseFloat(a.getAttribute(`width`)||``),t=parseFloat(a.getAttribute(`height`)||``);Number.isFinite(e)&&Number.isFinite(t)&&a.setAttribute(`viewBox`,`0 0 ${e} ${t}`)}if(a.removeAttribute(`width`),a.removeAttribute(`height`),a.setAttribute(`class`,`map-svg`),a.querySelectorAll(`path[title]`).forEach(e=>{let t=e.getAttribute(`title`)||``;t&&(e.classList.add(`country`),e.setAttribute(`data-name`,t))}),c){let e=l(a),t=u(d,e),n=t?r[t]:void 0;if(t&&n){let o=e=>{let t=i.createElementNS(`http://www.w3.org/2000/svg`,`path`);return t.setAttribute(`d`,e),t.setAttribute(`class`,`connection-line`),t.setAttribute(`fill`,`none`),t},s=e=>a.querySelector(`#${e}`)?.getAttribute(`title`)||e,c=(e,t,n,r,a)=>{let o=i.createElementNS(`http://www.w3.org/2000/svg`,`circle`);return o.setAttribute(`cx`,String(e)),o.setAttribute(`cy`,String(t)),o.setAttribute(`r`,`3`),o.setAttribute(`class`,n),o.setAttribute(`data-country-code`,r),o.setAttribute(`data-country-name`,a),o},l=new Set;for(let i of f){let d=u(i,e);if(!d||d===t)continue;let f=r[d];if(!f)continue;let p=m(f,n);if(a.appendChild(o(p)),!l.has(d)){let e=s(d);a.appendChild(c(f.x,f.y,`connection-dot connection-dot-start`,d,e)),l.add(d)}}if(!l.has(t)){let e=s(t);a.appendChild(c(n.x,n.y,`connection-dot connection-dot-end`,t,e)),l.add(t)}}}b(new XMLSerializer().serializeToString(a))}catch{e&&b(``)}})(),()=>{e=!1}},[o,c,d,f]);let P=e=>!e||!(e instanceof Element)?null:e.closest(`[data-name]`),F=e=>!e||!(e instanceof Element)?null:e.closest(`.connection-dot`),I=e=>{let t=j.current?.getBoundingClientRect();return t?{x:e.clientX-t.left,y:e.clientY-t.top}:{x:0,y:0}},L=()=>{let e=j.current;if(!e)return;let t=e.querySelector(`.country.is-selected`);t&&t.classList.remove(`is-selected`)},R=e=>{if(M.current.isPanning){let t=e.clientX-M.current.startX,n=e.clientY-M.current.startY;O({x:M.current.originX+t,y:M.current.originY+n}),Math.sqrt(t*t+n*n)>5&&(M.current.moved=!0),S(e=>({...e,visible:!1}));return}let t=F(e.target),n=t?.getAttribute(`data-country-code`),r=t?.getAttribute(`data-country-name`);if(n&&r){if(_){let{x:t,y:i}=I(e);_(n,r,t,i)}S(e=>({...e,visible:!1}));return}let i=P(e.target),a=i?.dataset.name;if(!a){S(e=>({...e,visible:!1}));return}let{x:o,y:s}=I(e);if(h){h(i.getAttribute(`id`)||``,a,o,s),S(e=>({...e,visible:!1}));return}S({name:a,x:o,y:s,visible:!0})},z=()=>{S(e=>({...e,visible:!1})),M.current.isPanning=!1,A(!1)},B=e=>{if(M.current.moved){M.current.moved=!1;return}let t=F(e.target),n=t?.getAttribute(`data-country-code`),r=t?.getAttribute(`data-country-name`);if(n&&r){if(v){let{x:t,y:i}=I(e);v(n,r,t,i)}return}let i=P(e.target),a=i?.dataset.name;if(!a){L(),w(e=>({...e,visible:!1}));return}let{x:o,y:s}=I(e);if(g){g(i.getAttribute(`id`)||``,a,o,s),w(e=>({...e,visible:!1}));return}w({name:a,x:o,y:s,visible:!0}),L(),i.classList.add(`is-selected`)},V=e=>{e.preventDefault();let t=e.deltaY>0?-1:1;E(e=>{let n=e+t*.1;return Math.min(3,Math.max(1,Number(n.toFixed(2))))})},H=e=>{if(e.button!==0)return;let t=F(e.target),n=P(e.target);if(t||n){M.current.isPanning=!1,M.current.moved=!1;return}e.currentTarget.setPointerCapture(e.pointerId),M.current.isPanning=!0,M.current.startX=e.clientX,M.current.startY=e.clientY,M.current.originX=D.x,M.current.originY=D.y,M.current.moved=!1,A(!0)},U=()=>{M.current.isPanning=!1,A(!1)},W={"--map-background":i||`transparent`,"--country-fill":a,"--country-hover":N.hover,"--country-selected":N.selected,"--country-stroke":N.stroke},G=[`map-container`,s].filter(Boolean).join(` `);return(0,t.jsxs)(`div`,{className:k?`${G} is-panning`.trim():G,style:W,ref:j,onPointerMove:R,onPointerLeave:z,onPointerDown:H,onPointerUp:U,onClick:B,onWheel:V,role:`img`,"aria-label":`World map with clickable countries`,children:[y?(0,t.jsx)(`div`,{className:`map-viewport`,style:{transform:`translate(${D.x}px, ${D.y}px) scale(${T})`},children:(0,t.jsx)(`div`,{className:`map-svg-wrap`,dangerouslySetInnerHTML:{__html:y}})}):(0,t.jsx)(`div`,{className:`map-loading`,children:`Loading map...`}),x.visible&&(0,t.jsx)(`div`,{className:`map-tooltip`,style:{left:x.x,top:x.y},role:`status`,children:x.name}),C.visible&&(0,t.jsx)(`div`,{className:`map-tooltip is-pinned`,style:{left:C.x,top:C.y},role:`status`,children:C.name})]})}exports.WorldMap=h,exports.default=h,exports.buildCountryLookup=l,exports.listMapCountries=c,exports.normalizeCountryName=s,exports.resolveCountryCode=u;
|
package/dist/world-map-svg.es.js
CHANGED
|
@@ -1029,58 +1029,55 @@ var o = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!-- Crea
|
|
|
1029
1029
|
}, c = {
|
|
1030
1030
|
aliases: {
|
|
1031
1031
|
usa: "US",
|
|
1032
|
-
|
|
1033
|
-
"u s": "US",
|
|
1034
|
-
"united states of america": "US",
|
|
1032
|
+
unitedstatesofamerica: "US",
|
|
1035
1033
|
uk: "GB",
|
|
1036
|
-
|
|
1037
|
-
"great britain": "GB",
|
|
1034
|
+
greatbritain: "GB",
|
|
1038
1035
|
england: "GB",
|
|
1039
1036
|
britain: "GB",
|
|
1040
1037
|
uae: "AE",
|
|
1041
1038
|
drc: "CD",
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1039
|
+
drcongo: "CD",
|
|
1040
|
+
democraticrepublicofthecongo: "CD",
|
|
1041
|
+
republicofthecongo: "CG",
|
|
1045
1042
|
congo: "CG",
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1043
|
+
congobrazzaville: "CG",
|
|
1044
|
+
southkorea: "KR",
|
|
1045
|
+
republicofkorea: "KR",
|
|
1049
1046
|
korea: "KR",
|
|
1050
|
-
|
|
1047
|
+
northkorea: "KP",
|
|
1051
1048
|
czechia: "CZ",
|
|
1052
|
-
|
|
1053
|
-
|
|
1049
|
+
cotedivoire: "CI",
|
|
1050
|
+
ivorycoast: "CI",
|
|
1054
1051
|
russia: "RU",
|
|
1055
|
-
|
|
1052
|
+
vietnam: "VN",
|
|
1056
1053
|
brunei: "BN",
|
|
1057
1054
|
laos: "LA",
|
|
1058
|
-
|
|
1055
|
+
laopdr: "LA",
|
|
1059
1056
|
micronesia: "FM",
|
|
1060
|
-
|
|
1057
|
+
northmacedonia: "MK",
|
|
1061
1058
|
macedonia: "MK",
|
|
1062
|
-
|
|
1063
|
-
|
|
1059
|
+
caboverde: "CV",
|
|
1060
|
+
capeverde: "CV",
|
|
1064
1061
|
eswatini: "SZ",
|
|
1065
1062
|
swaziland: "SZ",
|
|
1066
1063
|
burma: "MM",
|
|
1067
1064
|
palestine: "PS",
|
|
1068
|
-
|
|
1065
|
+
easttimor: "TL",
|
|
1069
1066
|
vatican: "VA",
|
|
1070
1067
|
turkiye: "TR",
|
|
1071
1068
|
curacao: "CW",
|
|
1072
1069
|
aland: "AX",
|
|
1073
1070
|
bonaire: "BQ",
|
|
1074
|
-
|
|
1071
|
+
caribbeannetherlands: "BQ",
|
|
1075
1072
|
holland: "NL",
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1073
|
+
thenetherlands: "NL",
|
|
1074
|
+
sintmaarten: "SX",
|
|
1075
|
+
stmaarten: "SX",
|
|
1076
|
+
saintmaarten: "SX",
|
|
1077
|
+
saintmartinfrench: "MF",
|
|
1078
|
+
saintmartinfr: "MF",
|
|
1082
1079
|
taiwan: "TW",
|
|
1083
|
-
|
|
1080
|
+
hongkong: "HK",
|
|
1084
1081
|
macau: "MO",
|
|
1085
1082
|
macao: "MO",
|
|
1086
1083
|
iran: "IR",
|
|
@@ -1088,23 +1085,23 @@ var o = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!-- Crea
|
|
|
1088
1085
|
tanzania: "TZ",
|
|
1089
1086
|
bolivia: "BO",
|
|
1090
1087
|
moldova: "MD",
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1088
|
+
virginislands: "VI",
|
|
1089
|
+
usvirginislands: "VI",
|
|
1090
|
+
britishvirginislands: "VG",
|
|
1094
1091
|
reunion: "RE",
|
|
1095
|
-
|
|
1092
|
+
southsudan: "SS"
|
|
1096
1093
|
},
|
|
1097
1094
|
disambiguated: {
|
|
1098
|
-
MF: ["
|
|
1095
|
+
MF: ["saintmartin", "saintmartinfrenchpart"],
|
|
1099
1096
|
SX: [
|
|
1100
|
-
"
|
|
1101
|
-
"
|
|
1102
|
-
"
|
|
1097
|
+
"sintmaarten",
|
|
1098
|
+
"stmaarten",
|
|
1099
|
+
"saintmaarten"
|
|
1103
1100
|
]
|
|
1104
1101
|
}
|
|
1105
1102
|
}, l = c.aliases, u = c.disambiguated;
|
|
1106
1103
|
function d(e) {
|
|
1107
|
-
return e.
|
|
1104
|
+
return e.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1108
1105
|
}
|
|
1109
1106
|
function f(e) {
|
|
1110
1107
|
let t = [];
|