diff --git a/jsconfig.json b/jsconfig.json
index c7a0b10..4551534 100644
--- a/jsconfig.json
+++ b/jsconfig.json
@@ -23,7 +23,7 @@
* Typecheck JS in `.svelte` and `.js` files by default.
* Disable this if you'd like to use dynamic types.
*/
- "checkJs": true
+ "checkJs": false
},
/**
* Use global.d.ts instead of compilerOptions.types
diff --git a/src/App.svelte b/src/App.svelte
index c09a368..5287ced 100644
--- a/src/App.svelte
+++ b/src/App.svelte
@@ -1,6 +1,7 @@
-
-
-
-
diff --git a/src/lib/Footer.svelte b/src/lib/layout/Footer.svelte
similarity index 57%
rename from src/lib/Footer.svelte
rename to src/lib/layout/Footer.svelte
index dcbd363..bee400e 100644
--- a/src/lib/Footer.svelte
+++ b/src/lib/layout/Footer.svelte
@@ -9,8 +9,11 @@
align-items: center;
justify-content: flex-end;
padding-right: 24px;
- background: #dce8f0;
- font: 14px/1.5 sans-serif;
- color: #555;
+ background: #334155;
+ font: 15px/1.6 sans-serif;
+ color: #cbd5e1;
+ position: relative;
+ z-index: 10;
+ box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.1);
}
diff --git a/src/lib/Layout.svelte b/src/lib/layout/Layout.svelte
similarity index 100%
rename from src/lib/Layout.svelte
rename to src/lib/layout/Layout.svelte
diff --git a/src/lib/TopBar.svelte b/src/lib/layout/TopBar.svelte
similarity index 90%
rename from src/lib/TopBar.svelte
rename to src/lib/layout/TopBar.svelte
index 529a52e..f700cb7 100644
--- a/src/lib/TopBar.svelte
+++ b/src/lib/layout/TopBar.svelte
@@ -30,8 +30,11 @@
display: flex;
align-items: center;
padding: 0 24px;
- background: #dce8f0;
+ background: #1e2937;
gap: 16px;
+ position: relative;
+ z-index: 10;
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
}
.left {
@@ -50,7 +53,7 @@
.app-name {
font: 700 20px/1.2 sans-serif;
- color: #1f2937;
+ color: #f1f5f9;
white-space: nowrap;
}
@@ -63,7 +66,7 @@
.segmented {
position: relative;
display: flex;
- background: rgba(0, 0, 0, 0.08);
+ background: rgba(255, 255, 255, 0.1);
border-radius: 999px;
padding: 4px;
width: 300px;
@@ -90,7 +93,7 @@
background: none;
cursor: pointer;
font: 500 16px/1.4 sans-serif;
- color: #555;
+ color: #cbd5e1;
}
.right {
diff --git a/src/lib/layout/selection.svelte.js b/src/lib/layout/selection.svelte.js
new file mode 100644
index 0000000..c6a0d7f
--- /dev/null
+++ b/src/lib/layout/selection.svelte.js
@@ -0,0 +1,28 @@
+let selected = $state(new Set());
+let totalCountries = $state(0);
+
+export function toggle(id) {
+ const next = new Set(selected);
+ if (next.has(id)) {
+ next.delete(id);
+ } else {
+ next.add(id);
+ }
+ selected = next;
+}
+
+export function clearAll() {
+ selected = new Set();
+}
+
+export function getSelected() {
+ return selected;
+}
+
+export function setTotalCount(n) {
+ totalCountries = n;
+}
+
+export function getTotalCount() {
+ return totalCountries;
+}
diff --git a/src/lib/world-map/StatsPanel.svelte b/src/lib/world-map/StatsPanel.svelte
new file mode 100644
index 0000000..f96e17d
--- /dev/null
+++ b/src/lib/world-map/StatsPanel.svelte
@@ -0,0 +1,204 @@
+
+
+
+
your statistics
+
+
visited countries
+
+
+
{total} / {grandTotal}
+
+
+
+
+
by continent
+ {#each CONTINENTS as continent}
+ {@const contTotal = continentTotals[continent]}
+
+
+ {continent}
+ {counts[continent]}/{contTotal}
+
+ {/each}
+
+
+
+
+
+
Contains all UN countries, Kosovo, Hong Kong and Taiwan
+
+
+
diff --git a/src/lib/world-map/WorldMap.svelte b/src/lib/world-map/WorldMap.svelte
new file mode 100644
index 0000000..5cdfb52
--- /dev/null
+++ b/src/lib/world-map/WorldMap.svelte
@@ -0,0 +1,219 @@
+
+
+
+
+
diff --git a/src/lib/world-map/continents.js b/src/lib/world-map/continents.js
new file mode 100644
index 0000000..2eabc73
--- /dev/null
+++ b/src/lib/world-map/continents.js
@@ -0,0 +1,213 @@
+export const CONTINENTS = ['Europe', 'Asia', 'Africa', 'N. America', 'S. America', 'Oceania'];
+
+const map = {
+ '004': 'Asia', // Afghanistan
+ '008': 'Europe', // Albania
+ '012': 'Africa', // Algeria
+ '020': 'Europe', // Andorra
+ '024': 'Africa', // Angola
+ '028': 'N. America', // Antigua and Barb.
+ '031': 'Asia', // Azerbaijan
+ '032': 'S. America', // Argentina
+ '036': 'Oceania', // Australia
+ '040': 'Europe', // Austria
+ '044': 'N. America', // Bahamas
+ '048': 'Asia', // Bahrain
+ '050': 'Asia', // Bangladesh
+ '051': 'Asia', // Armenia
+ '052': 'N. America', // Barbados
+ '056': 'Europe', // Belgium
+ '064': 'Asia', // Bhutan
+ '068': 'S. America', // Bolivia
+ '070': 'Europe', // Bosnia and Herz.
+ '072': 'Africa', // Botswana
+ '076': 'S. America', // Brazil
+ '084': 'N. America', // Belize
+ '090': 'Oceania', // Solomon Is.
+ '096': 'Asia', // Brunei
+ '100': 'Europe', // Bulgaria
+ '104': 'Asia', // Myanmar
+ '108': 'Africa', // Burundi
+ '112': 'Europe', // Belarus
+ '116': 'Asia', // Cambodia
+ '120': 'Africa', // Cameroon
+ '124': 'N. America', // Canada
+ '132': 'Africa', // Cabo Verde
+ '140': 'Africa', // Central African Rep.
+ '144': 'Asia', // Sri Lanka
+ '148': 'Africa', // Chad
+ '152': 'S. America', // Chile
+ '156': 'Asia', // China
+ '158': 'Asia', // Taiwan
+ '170': 'S. America', // Colombia
+ '174': 'Africa', // Comoros
+ '178': 'Africa', // Congo
+ '180': 'Africa', // Dem. Rep. Congo
+ '188': 'N. America', // Costa Rica
+ '191': 'Europe', // Croatia
+ '192': 'N. America', // Cuba
+ '196': 'Asia', // Cyprus
+ '203': 'Europe', // Czechia
+ '204': 'Africa', // Benin
+ '208': 'Europe', // Denmark
+ '212': 'N. America', // Dominica
+ '214': 'N. America', // Dominican Rep.
+ '218': 'S. America', // Ecuador
+ '222': 'N. America', // El Salvador
+ '226': 'Africa', // Eq. Guinea
+ '231': 'Africa', // Ethiopia
+ '232': 'Africa', // Eritrea
+ '233': 'Europe', // Estonia
+ '242': 'Oceania', // Fiji
+ '246': 'Europe', // Finland
+ '250': 'Europe', // France
+ '262': 'Africa', // Djibouti
+ '266': 'Africa', // Gabon
+ '268': 'Asia', // Georgia
+ '270': 'Africa', // Gambia
+ '275': 'Asia', // Palestine
+ '276': 'Europe', // Germany
+ '288': 'Africa', // Ghana
+ '296': 'Oceania', // Kiribati
+ '300': 'Europe', // Greece
+ '308': 'N. America', // Grenada
+ '320': 'N. America', // Guatemala
+ '324': 'Africa', // Guinea
+ '328': 'S. America', // Guyana
+ '332': 'N. America', // Haiti
+ '336': 'Europe', // Vatican
+ '340': 'N. America', // Honduras
+ '344': 'Asia', // Hong Kong
+ '348': 'Europe', // Hungary
+ '352': 'Europe', // Iceland
+ '356': 'Asia', // India
+ '360': 'Asia', // Indonesia
+ '364': 'Asia', // Iran
+ '368': 'Asia', // Iraq
+ '372': 'Europe', // Ireland
+ '376': 'Asia', // Israel
+ '380': 'Europe', // Italy
+ '384': 'Africa', // Cote d'Ivoire
+ '388': 'N. America', // Jamaica
+ '392': 'Asia', // Japan
+ '398': 'Asia', // Kazakhstan
+ '400': 'Asia', // Jordan
+ '404': 'Africa', // Kenya
+ '408': 'Asia', // North Korea
+ '410': 'Asia', // South Korea
+ '414': 'Asia', // Kuwait
+ '417': 'Asia', // Kyrgyzstan
+ '418': 'Asia', // Laos
+ '422': 'Asia', // Lebanon
+ '426': 'Africa', // Lesotho
+ '428': 'Europe', // Latvia
+ '430': 'Africa', // Liberia
+ '434': 'Africa', // Libya
+ '438': 'Europe', // Liechtenstein
+ '440': 'Europe', // Lithuania
+ '442': 'Europe', // Luxembourg
+ '450': 'Africa', // Madagascar
+ '454': 'Africa', // Malawi
+ '458': 'Asia', // Malaysia
+ '462': 'Asia', // Maldives
+ '466': 'Africa', // Mali
+ '470': 'Europe', // Malta
+ '478': 'Africa', // Mauritania
+ '480': 'Africa', // Mauritius
+ '484': 'N. America', // Mexico
+ '492': 'Europe', // Monaco
+ '496': 'Asia', // Mongolia
+ '498': 'Europe', // Moldova
+ '499': 'Europe', // Montenegro
+ '504': 'Africa', // Morocco
+ '508': 'Africa', // Mozambique
+ '512': 'Asia', // Oman
+ '516': 'Africa', // Namibia
+ '520': 'Oceania', // Nauru
+ '524': 'Asia', // Nepal
+ '528': 'Europe', // Netherlands
+ '548': 'Oceania', // Vanuatu
+ '554': 'Oceania', // New Zealand
+ '558': 'N. America', // Nicaragua
+ '562': 'Africa', // Niger
+ '566': 'Africa', // Nigeria
+ '578': 'Europe', // Norway
+ '583': 'Oceania', // Micronesia
+ '584': 'Oceania', // Marshall Is.
+ '585': 'Oceania', // Palau
+ '586': 'Asia', // Pakistan
+ '591': 'N. America', // Panama
+ '598': 'Oceania', // Papua New Guinea
+ '600': 'S. America', // Paraguay
+ '604': 'S. America', // Peru
+ '608': 'Asia', // Philippines
+ '616': 'Europe', // Poland
+ '620': 'Europe', // Portugal
+ '624': 'Africa', // Guinea-Bissau
+ '626': 'Asia', // Timor-Leste
+ '634': 'Asia', // Qatar
+ '642': 'Europe', // Romania
+ '643': 'Europe', // Russia
+ '646': 'Africa', // Rwanda
+ '659': 'N. America', // St. Kitts and Nevis
+ '662': 'N. America', // Saint Lucia
+ '670': 'N. America', // St. Vin. and Gren.
+ '674': 'Europe', // San Marino
+ '678': 'Africa', // Sao Tome and Principe
+ '682': 'Asia', // Saudi Arabia
+ '686': 'Africa', // Senegal
+ '688': 'Europe', // Serbia
+ '690': 'Africa', // Seychelles
+ '694': 'Africa', // Sierra Leone
+ '702': 'Asia', // Singapore
+ '703': 'Europe', // Slovakia
+ '704': 'Asia', // Vietnam
+ '705': 'Europe', // Slovenia
+ '706': 'Africa', // Somalia
+ '710': 'Africa', // South Africa
+ '716': 'Africa', // Zimbabwe
+ '724': 'Europe', // Spain
+ '728': 'Africa', // S. Sudan
+ '729': 'Africa', // Sudan
+ '732': 'Africa', // W. Sahara
+ '740': 'S. America', // Suriname
+ '748': 'Africa', // eSwatini
+ '752': 'Europe', // Sweden
+ '756': 'Europe', // Switzerland
+ '760': 'Asia', // Syria
+ '762': 'Asia', // Tajikistan
+ '764': 'Asia', // Thailand
+ '768': 'Africa', // Togo
+ '776': 'Oceania', // Tonga
+ '780': 'N. America', // Trinidad and Tobago
+ '784': 'Asia', // United Arab Emirates
+ '788': 'Africa', // Tunisia
+ '792': 'Asia', // Turkey
+ '795': 'Asia', // Turkmenistan
+ '800': 'Africa', // Uganda
+ '804': 'Europe', // Ukraine
+ '807': 'Europe', // Macedonia
+ '818': 'Africa', // Egypt
+ '826': 'Europe', // United Kingdom
+ '834': 'Africa', // Tanzania
+ '840': 'N. America', // United States of America
+ '854': 'Africa', // Burkina Faso
+ '858': 'S. America', // Uruguay
+ '860': 'Asia', // Uzbekistan
+ '862': 'S. America', // Venezuela
+ '882': 'Oceania', // Samoa
+ '887': 'Asia', // Yemen
+ '894': 'Africa', // Zambia
+ 'XK': 'Europe', // Kosovo
+};
+
+export const continentTotals = CONTINENTS.reduce((acc, c) => (acc[c] = 0, acc), {});
+for (const id of Object.keys(map)) {
+ const cont = map[id];
+ if (cont) continentTotals[cont]++;
+}
+
+export function getContinent(id) {
+ return map[id] ?? null;
+}
+