ethio-map-kit 0.1.1 → 0.1.2
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 +67 -337
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Ethio Map Kit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React components for building interactive Ethiopia map visualizations.
|
|
4
4
|
|
|
5
|
-
Ethio Map Kit
|
|
5
|
+
Ethio Map Kit includes a regional Ethiopia map, smooth region selection, light/dark themes, terrain and heat layers, marker support, service stats, and TypeScript types.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -10,13 +10,7 @@ Ethio Map Kit ships a polished Ethiopia map surface, region legend, selected-reg
|
|
|
10
10
|
npm install ethio-map-kit
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
npm install react react-dom
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Import the stylesheet once in your app:
|
|
13
|
+
Import the stylesheet once:
|
|
20
14
|
|
|
21
15
|
```tsx
|
|
22
16
|
import "ethio-map-kit/styles.css";
|
|
@@ -40,95 +34,68 @@ export function App() {
|
|
|
40
34
|
serviceStats={defaultRegionServiceStats}
|
|
41
35
|
locations={defaultLocations}
|
|
42
36
|
theme="light"
|
|
43
|
-
layer="
|
|
37
|
+
layer="regions"
|
|
44
38
|
showLabels
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
console.log(selection.regionId, selection.region);
|
|
39
|
+
onRegionSelect={({ regionId, region }) => {
|
|
40
|
+
console.log(regionId, region);
|
|
48
41
|
}}
|
|
49
42
|
/>
|
|
50
43
|
);
|
|
51
44
|
}
|
|
52
45
|
```
|
|
53
46
|
|
|
54
|
-
|
|
47
|
+
## Terrain Layer
|
|
55
48
|
|
|
56
49
|
```tsx
|
|
57
|
-
|
|
50
|
+
<EthiopiaMap
|
|
51
|
+
data={defaultRegionData}
|
|
52
|
+
layer="terrain"
|
|
53
|
+
theme="dark"
|
|
54
|
+
/>
|
|
58
55
|
```
|
|
59
56
|
|
|
60
|
-
|
|
57
|
+
The bundled terrain image is a transparent WebP, so it works in both light and dark mode.
|
|
61
58
|
|
|
62
|
-
|
|
59
|
+
## Custom Data
|
|
63
60
|
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
- `EthiopiaMapProvider`
|
|
67
|
-
- `EthiopiaMapRoot`
|
|
68
|
-
- `EthiopiaMapLegend`
|
|
69
|
-
- `EthiopiaSelectedRegionCard`
|
|
70
|
-
- `EthiopiaRegionServicesCard`
|
|
71
|
-
- `EthiopiaLocationsPanel`
|
|
72
|
-
|
|
73
|
-
Hooks:
|
|
74
|
-
|
|
75
|
-
- `useEthiopiaMap`
|
|
76
|
-
- `useSelectedRegionId`
|
|
77
|
-
|
|
78
|
-
Default data and map metadata:
|
|
79
|
-
|
|
80
|
-
- `defaultRegionData`
|
|
81
|
-
- `defaultRegionServiceStats`
|
|
82
|
-
- `defaultLocations`
|
|
83
|
-
- `regionPathMap`
|
|
84
|
-
- `ETHIOPIA_REGION_IDS`
|
|
85
|
-
- `ETHIOPIA_AUTO_TOUR_SEQUENCE`
|
|
86
|
-
|
|
87
|
-
## Main Component
|
|
61
|
+
```tsx
|
|
62
|
+
import type { RegionRecord, RegionDatum } from "ethio-map-kit";
|
|
88
63
|
|
|
89
|
-
|
|
64
|
+
const data: RegionRecord<RegionDatum> = {
|
|
65
|
+
...defaultRegionData,
|
|
66
|
+
amhara: {
|
|
67
|
+
name: "Amhara",
|
|
68
|
+
value: 78,
|
|
69
|
+
trend: "+12%",
|
|
70
|
+
copy: "High regional index with several sample cities.",
|
|
71
|
+
},
|
|
72
|
+
};
|
|
90
73
|
|
|
91
|
-
|
|
92
|
-
<EthiopiaMap
|
|
93
|
-
data={regionData}
|
|
94
|
-
serviceStats={serviceStats}
|
|
95
|
-
locations={locations}
|
|
96
|
-
theme="dark"
|
|
97
|
-
layer="heat"
|
|
98
|
-
selectedRegionId={selectedRegionId}
|
|
99
|
-
onRegionSelect={setSelection}
|
|
100
|
-
/>
|
|
74
|
+
<EthiopiaMap data={data} />;
|
|
101
75
|
```
|
|
102
76
|
|
|
103
|
-
|
|
77
|
+
## Common Props
|
|
104
78
|
|
|
105
|
-
| Prop | Type |
|
|
106
|
-
| --- | --- | --- |
|
|
107
|
-
| `data` | `RegionRecord<RegionDatum>` |
|
|
108
|
-
| `serviceStats` | `RegionServiceStats` |
|
|
109
|
-
| `locations` | `
|
|
110
|
-
| `theme` | `"light" \| "dark"` |
|
|
111
|
-
| `layer` | `"regions" \| "heat" \| "terrain"` |
|
|
112
|
-
| `viewMode` | `"map" \| "bars"` |
|
|
113
|
-
| `selectionAnimation` | `"pulse" \| "static" \| "none" \| "outline"` |
|
|
114
|
-
| `showLabels` | `boolean` |
|
|
115
|
-
| `showMarkers` | `boolean` |
|
|
116
|
-
| `
|
|
117
|
-
| `
|
|
118
|
-
| `
|
|
119
|
-
| `
|
|
120
|
-
| `
|
|
121
|
-
| `selectedRegionId` | `EthiopiaRegionId \| null` | Uncontrolled | Controlled selected region. |
|
|
122
|
-
| `defaultSelectedRegionId` | `EthiopiaRegionId \| null` | `null` | Initial selected region for uncontrolled usage. |
|
|
123
|
-
| `onRegionSelect` | `(selection: EthiopiaMapSelection) => void` | `undefined` | Called when the user selects or clears a region. |
|
|
124
|
-
| `className` | `string` | `undefined` | Extra class for the map surface. |
|
|
125
|
-
| `svgText` | `string` | Bundled SVG | Raw SVG text override. |
|
|
126
|
-
| `svgUrl` | `string` | `undefined` | Fetch an SVG from a URL instead of using the bundled SVG. |
|
|
127
|
-
| `terrainImageUrl` | `string` | Bundled WebP | Custom terrain image URL. |
|
|
79
|
+
| Prop | Type | Description |
|
|
80
|
+
| --- | --- | --- |
|
|
81
|
+
| `data` | `RegionRecord<RegionDatum>` | Region values and copy keyed by region ID. |
|
|
82
|
+
| `serviceStats` | `RegionServiceStats` | Optional service indicators for each region. |
|
|
83
|
+
| `locations` | `LatLngLocation[]` | Optional marker/location data. |
|
|
84
|
+
| `theme` | `"light" \| "dark"` | Map theme. |
|
|
85
|
+
| `layer` | `"regions" \| "heat" \| "terrain"` | Active visual layer. |
|
|
86
|
+
| `viewMode` | `"map" \| "bars"` | Map view or bar view. |
|
|
87
|
+
| `selectionAnimation` | `"pulse" \| "static" \| "none" \| "outline"` | Selected-region animation style. |
|
|
88
|
+
| `showLabels` | `boolean` | Show or hide region labels. |
|
|
89
|
+
| `showMarkers` | `boolean` | Show or hide location markers. |
|
|
90
|
+
| `regionColors` | `PartialRegionRecord<string>` | Override region colors. |
|
|
91
|
+
| `selectedRegionId` | `EthiopiaRegionId \| null` | Controlled selected region. |
|
|
92
|
+
| `defaultSelectedRegionId` | `EthiopiaRegionId \| null` | Initial selected region. |
|
|
93
|
+
| `onRegionSelect` | `(selection) => void` | Called when a region is selected or cleared. |
|
|
94
|
+
| `terrainImageUrl` | `string` | Custom terrain image URL. |
|
|
128
95
|
|
|
129
|
-
## Composable
|
|
96
|
+
## Composable Components
|
|
130
97
|
|
|
131
|
-
|
|
98
|
+
For custom layouts, wrap components with `EthiopiaMapProvider`.
|
|
132
99
|
|
|
133
100
|
```tsx
|
|
134
101
|
import {
|
|
@@ -143,112 +110,35 @@ import {
|
|
|
143
110
|
|
|
144
111
|
export function Dashboard() {
|
|
145
112
|
return (
|
|
146
|
-
<EthiopiaMapProvider data={defaultRegionData}
|
|
147
|
-
<
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
<EthiopiaRegionServicesCard />
|
|
153
|
-
<EthiopiaLocationsPanel />
|
|
154
|
-
</aside>
|
|
155
|
-
</div>
|
|
113
|
+
<EthiopiaMapProvider data={defaultRegionData}>
|
|
114
|
+
<EthiopiaMapSurface />
|
|
115
|
+
<EthiopiaMapLegend />
|
|
116
|
+
<EthiopiaSelectedRegionCard />
|
|
117
|
+
<EthiopiaRegionServicesCard />
|
|
118
|
+
<EthiopiaLocationsPanel />
|
|
156
119
|
</EthiopiaMapProvider>
|
|
157
120
|
);
|
|
158
121
|
}
|
|
159
122
|
```
|
|
160
123
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
`EthiopiaMapProvider` accepts the same data, selection, theme, layer, marker, label, service-stat, and auto-tour props as `EthiopiaMap`, except it requires `children` and does not accept `className`, `svgText`, `svgUrl`, or `terrainImageUrl`.
|
|
164
|
-
|
|
165
|
-
Use this when you want shared state across multiple package components.
|
|
166
|
-
|
|
167
|
-
### `EthiopiaMapSurface` Props
|
|
168
|
-
|
|
169
|
-
| Prop | Type | Default | Description |
|
|
170
|
-
| --- | --- | --- | --- |
|
|
171
|
-
| `className` | `string` | `undefined` | Extra class for the surface wrapper. |
|
|
172
|
-
| `svgText` | `string` | Bundled SVG | Raw SVG text override. |
|
|
173
|
-
| `svgUrl` | `string` | `undefined` | Runtime SVG URL override. |
|
|
174
|
-
| `terrainImageUrl` | `string` | Bundled WebP | Terrain raster URL override. |
|
|
175
|
-
|
|
176
|
-
`EthiopiaMapSurface` reads all map behavior from `EthiopiaMapProvider`.
|
|
177
|
-
|
|
178
|
-
## Panel Components
|
|
179
|
-
|
|
180
|
-
### `EthiopiaMapLegend`
|
|
181
|
-
|
|
182
|
-
Renders a sorted clickable legend using the current provider data.
|
|
183
|
-
|
|
184
|
-
| Prop | Type | Default | Description |
|
|
185
|
-
| --- | --- | --- | --- |
|
|
186
|
-
| `className` | `string` | `undefined` | Extra class for the legend panel. |
|
|
187
|
-
| `title` | `string` | `"Region index"` | Legend heading. |
|
|
188
|
-
| `kicker` | `string` | `"Legend"` | Small label above the heading. |
|
|
189
|
-
| `maxItems` | `number` | All regions | Limit visible legend rows. |
|
|
190
|
-
| `onRegionClick` | `(regionId: EthiopiaRegionId) => void` | `undefined` | Called when a non-active region is clicked. |
|
|
191
|
-
|
|
192
|
-
### `EthiopiaSelectedRegionCard`
|
|
193
|
-
|
|
194
|
-
Shows selected-region copy, preview SVG, and summary stats.
|
|
195
|
-
|
|
196
|
-
| Prop | Type | Default | Description |
|
|
197
|
-
| --- | --- | --- | --- |
|
|
198
|
-
| `className` | `string` | `undefined` | Extra class for the panel. |
|
|
199
|
-
| `emptyTitle` | `string` | `"Click a region"` | Title shown when nothing is selected. |
|
|
200
|
-
| `emptyCopy` | `string` | Built-in helper copy | Body text shown when nothing is selected. |
|
|
201
|
-
| `showStats` | `boolean` | `true` | Show or hide the three summary-stat boxes. |
|
|
202
|
-
| `previewSelectionAnimation` | `SelectionAnimationMode` | Provider value | Override preview animation mode. |
|
|
203
|
-
| `summaryStats` | `(selection) => readonly RegionSummaryStat[]` | Built-in stats | Custom stat rows for the card. |
|
|
204
|
-
| `renderPreview` | `(selection) => ReactNode` | Built-in SVG preview | Replace the selected-region preview area. |
|
|
205
|
-
|
|
206
|
-
### `EthiopiaRegionServicesCard`
|
|
207
|
-
|
|
208
|
-
Shows service indicators for the selected region.
|
|
209
|
-
|
|
210
|
-
| Prop | Type | Default | Description |
|
|
211
|
-
| --- | --- | --- | --- |
|
|
212
|
-
| `className` | `string` | `undefined` | Extra class for the service panel. |
|
|
213
|
-
| `emptyText` | `string` | `"Select a region to inspect service statistics."` | Empty state text. |
|
|
214
|
-
|
|
215
|
-
### `EthiopiaLocationsPanel`
|
|
216
|
-
|
|
217
|
-
Lists provided locations and their coordinates.
|
|
218
|
-
|
|
219
|
-
| Prop | Type | Default | Description |
|
|
220
|
-
| --- | --- | --- | --- |
|
|
221
|
-
| `className` | `string` | `undefined` | Extra class for the locations panel. |
|
|
222
|
-
| `title` | `string` | `"Locations"` | Panel heading. |
|
|
223
|
-
| `kicker` | `string` | `"Lat/lng overlay"` | Small label above the heading. |
|
|
224
|
-
| `showMarkerToggle` | `boolean` | `true` | Show current marker on/off state. |
|
|
225
|
-
|
|
226
|
-
## Data Types
|
|
227
|
-
|
|
228
|
-
### Region Data
|
|
229
|
-
|
|
230
|
-
Each region must be present in the `data` object.
|
|
231
|
-
|
|
232
|
-
```tsx
|
|
233
|
-
import type { RegionRecord, RegionDatum } from "ethio-map-kit";
|
|
124
|
+
## Exports
|
|
234
125
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
```
|
|
126
|
+
- `EthiopiaMap`
|
|
127
|
+
- `EthiopiaMapProvider`
|
|
128
|
+
- `EthiopiaMapSurface`
|
|
129
|
+
- `EthiopiaMapLegend`
|
|
130
|
+
- `EthiopiaSelectedRegionCard`
|
|
131
|
+
- `EthiopiaRegionServicesCard`
|
|
132
|
+
- `EthiopiaLocationsPanel`
|
|
133
|
+
- `useEthiopiaMap`
|
|
134
|
+
- `useSelectedRegionId`
|
|
135
|
+
- `defaultRegionData`
|
|
136
|
+
- `defaultRegionServiceStats`
|
|
137
|
+
- `defaultLocations`
|
|
138
|
+
- `ETHIOPIA_REGION_IDS`
|
|
139
|
+
- `ETHIOPIA_AUTO_TOUR_SEQUENCE`
|
|
250
140
|
|
|
251
|
-
|
|
141
|
+
## Region IDs
|
|
252
142
|
|
|
253
143
|
```text
|
|
254
144
|
tigray
|
|
@@ -266,163 +156,3 @@ somali
|
|
|
266
156
|
dire-dawa
|
|
267
157
|
harari
|
|
268
158
|
```
|
|
269
|
-
|
|
270
|
-
### Service Stats
|
|
271
|
-
|
|
272
|
-
```tsx
|
|
273
|
-
import type { RegionServiceStats } from "ethio-map-kit";
|
|
274
|
-
|
|
275
|
-
const serviceStats: RegionServiceStats = {
|
|
276
|
-
amhara: [
|
|
277
|
-
{
|
|
278
|
-
label: "Maternal death rate",
|
|
279
|
-
valueKind: "percent",
|
|
280
|
-
value: 67,
|
|
281
|
-
comparison: {
|
|
282
|
-
enabled: true,
|
|
283
|
-
percent: 12,
|
|
284
|
-
direction: "increase",
|
|
285
|
-
period: "last month",
|
|
286
|
-
outcome: "negative",
|
|
287
|
-
},
|
|
288
|
-
},
|
|
289
|
-
{
|
|
290
|
-
label: "Hospitals",
|
|
291
|
-
valueKind: "number",
|
|
292
|
-
value: 86,
|
|
293
|
-
comparison: {
|
|
294
|
-
enabled: true,
|
|
295
|
-
percent: 5,
|
|
296
|
-
direction: "increase",
|
|
297
|
-
period: "last year",
|
|
298
|
-
outcome: "positive",
|
|
299
|
-
},
|
|
300
|
-
},
|
|
301
|
-
],
|
|
302
|
-
};
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
### Locations
|
|
306
|
-
|
|
307
|
-
```tsx
|
|
308
|
-
import type { LatLngLocation } from "ethio-map-kit";
|
|
309
|
-
|
|
310
|
-
const locations: LatLngLocation[] = [
|
|
311
|
-
{
|
|
312
|
-
name: "Bahir Dar",
|
|
313
|
-
region: "amhara",
|
|
314
|
-
lat: 11.59,
|
|
315
|
-
lng: 37.39,
|
|
316
|
-
category: "hospital",
|
|
317
|
-
color: "#f7c948",
|
|
318
|
-
radius: 5,
|
|
319
|
-
intensity: 76,
|
|
320
|
-
},
|
|
321
|
-
];
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
## Customization Examples
|
|
325
|
-
|
|
326
|
-
### Controlled Selection
|
|
327
|
-
|
|
328
|
-
```tsx
|
|
329
|
-
const [selectedRegionId, setSelectedRegionId] =
|
|
330
|
-
useState<EthiopiaRegionId | null>(null);
|
|
331
|
-
|
|
332
|
-
<EthiopiaMap
|
|
333
|
-
data={defaultRegionData}
|
|
334
|
-
selectedRegionId={selectedRegionId}
|
|
335
|
-
onRegionSelect={({ regionId }) => setSelectedRegionId(regionId)}
|
|
336
|
-
/>;
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
### Custom Region Colors
|
|
340
|
-
|
|
341
|
-
```tsx
|
|
342
|
-
<EthiopiaMap
|
|
343
|
-
data={defaultRegionData}
|
|
344
|
-
regionColors={{
|
|
345
|
-
amhara: "#2563eb",
|
|
346
|
-
oromia: "#16a34a",
|
|
347
|
-
"addis-ababa": "#dc2626",
|
|
348
|
-
}}
|
|
349
|
-
/>
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
### Custom Terrain Asset
|
|
353
|
-
|
|
354
|
-
```tsx
|
|
355
|
-
<EthiopiaMap
|
|
356
|
-
data={defaultRegionData}
|
|
357
|
-
layer="terrain"
|
|
358
|
-
terrainImageUrl="/assets/ethiopia-terrain.webp"
|
|
359
|
-
/>
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
The bundled terrain asset is a transparent WebP so it works in both light and dark mode.
|
|
363
|
-
|
|
364
|
-
### Auto Tour
|
|
365
|
-
|
|
366
|
-
```tsx
|
|
367
|
-
<EthiopiaMap
|
|
368
|
-
data={defaultRegionData}
|
|
369
|
-
autoTour
|
|
370
|
-
autoTourIntervalMs={4500}
|
|
371
|
-
autoTourSequence={["amhara", "oromia", "addis-ababa", null]}
|
|
372
|
-
/>
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
The default route is:
|
|
376
|
-
|
|
377
|
-
```text
|
|
378
|
-
Afar -> Tigray -> Amhara -> Benishangul-Gumuz -> Gambela -> South West Ethiopia -> South Ethiopia -> Sidama -> Central Ethiopia -> Addis Ababa -> Dire Dawa -> Harari -> Somali -> Oromia -> reset
|
|
379
|
-
```
|
|
380
|
-
|
|
381
|
-
### Custom Selected-Region Preview
|
|
382
|
-
|
|
383
|
-
```tsx
|
|
384
|
-
<EthiopiaSelectedRegionCard
|
|
385
|
-
renderPreview={({ region }) =>
|
|
386
|
-
region ? <strong>{region.name}</strong> : <span>No region</span>
|
|
387
|
-
}
|
|
388
|
-
/>
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
## Package Boundary And Source Visibility
|
|
392
|
-
|
|
393
|
-
The published npm package contains compiled output from `dist` and this README. It does not publish the TypeScript source files or the original private repository structure.
|
|
394
|
-
|
|
395
|
-
This is the normal model for frontend npm packages: consumers receive JavaScript, CSS, type declarations, and assets needed to run the component. The code can still be inspected by determined users after installation, even when it is compiled or minified. Minification and narrow package exports are useful for distribution and casual obfuscation, but they are not a security boundary.
|
|
396
|
-
|
|
397
|
-
The same rule applies to browser deployments: any JavaScript, SVG, image, or CSS needed by a public client-side page can be downloaded by the browser. Keep sensitive business logic on a server if it must be private.
|
|
398
|
-
|
|
399
|
-
## Local Development
|
|
400
|
-
|
|
401
|
-
From the repository root:
|
|
402
|
-
|
|
403
|
-
```bash
|
|
404
|
-
npm install
|
|
405
|
-
npm run dev:react
|
|
406
|
-
npm run typecheck --workspace ethio-map-kit
|
|
407
|
-
npm run build --workspace ethio-map-kit
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
Open the local demo at:
|
|
411
|
-
|
|
412
|
-
```text
|
|
413
|
-
http://localhost:5174/
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
## Publishing
|
|
417
|
-
|
|
418
|
-
Before publishing a new package version:
|
|
419
|
-
|
|
420
|
-
```bash
|
|
421
|
-
npm run typecheck --workspace ethio-map-kit
|
|
422
|
-
npm run build --workspace ethio-map-kit
|
|
423
|
-
npm pack --workspace ethio-map-kit --dry-run
|
|
424
|
-
npm version patch --workspace ethio-map-kit
|
|
425
|
-
npm publish --workspace ethio-map-kit --access public
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
npm package versions are immutable. If `ethio-map-kit@0.1.0` has already been published, publish the next patch, minor, or major version instead of trying to overwrite it.
|