bharat-choropleth-js 0.1.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/LICENSE +21 -0
- package/README.md +185 -0
- package/dist/bharat-choropleth.min.js +126 -0
- package/dist/bharat-choropleth.min.js.map +1 -0
- package/dist/index.d.ts +458 -0
- package/dist/index.js +1587 -0
- package/dist/index.js.map +1 -0
- package/dist/style.css +124 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bharat Choropleth contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# `bharat-choropleth-js`
|
|
2
|
+
|
|
3
|
+
An accessible SVG India state-to-district choropleth with no framework dependency. Drop one `<script>` tag into any HTML page, or import it as an ES module from a bundler. Same behavior, CSS classes, and stylesheet as the React [`bharat-choropleth`](https://www.npmjs.com/package/bharat-choropleth) package.
|
|
4
|
+
|
|
5
|
+
## One script tag
|
|
6
|
+
|
|
7
|
+
```html
|
|
8
|
+
<div id="map"></div>
|
|
9
|
+
|
|
10
|
+
<script src="https://cdn.jsdelivr.net/npm/bharat-choropleth-js"></script>
|
|
11
|
+
<script>
|
|
12
|
+
var map = new BharatChoropleth("#map");
|
|
13
|
+
|
|
14
|
+
map.fontColor = "maroon";
|
|
15
|
+
map.colorScale = ["#ffffff", "#800000"];
|
|
16
|
+
|
|
17
|
+
map.goa = 6;
|
|
18
|
+
map.gujarat = 7;
|
|
19
|
+
map.tamil_nadu = 18;
|
|
20
|
+
map.states["Jammu & Kashmir"] = 2;
|
|
21
|
+
</script>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
That's the whole setup. No stylesheet link, no build step, no `await`, no boundary files to find:
|
|
25
|
+
|
|
26
|
+
- **The script tag injects its own CSS.** (Bundler users import `bharat-choropleth-js/style.css` instead, so their pipeline can extract and hash it — see [From a bundler](#from-a-bundler).)
|
|
27
|
+
- **Boundary data is fetched, not bundled.** The package ships no geometry; the prepared current-vintage state bundle is downloaded from `dataBaseUrl` on construction. Set `dataBaseUrl` to self-host — see [Boundary data](#boundary-data).
|
|
28
|
+
- **Values set before the data arrives are applied when it arrives.** Every line above runs while the download is still in flight; nothing is dropped and nothing needs awaiting. `map.ready` is a promise if you want one.
|
|
29
|
+
- **Clicking a state drills into its districts**, fetched from the same base URL. Pass `districts: false` to turn that off.
|
|
30
|
+
|
|
31
|
+
See the [complete example](https://github.com/shashankbudem/bharat-choropleth/tree/main/packages/js/example) in the repository. To run it locally, serve the **repo root** over HTTP (`npx serve`), then open `/packages/js/example/bharat-choropleth.html`.
|
|
32
|
+
|
|
33
|
+
## Setting values
|
|
34
|
+
|
|
35
|
+
Every one of these reaches the same state, so you can use whichever your data already has:
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
map.goa = 6; // dot-notation slug
|
|
39
|
+
map.tamil_nadu = 18; // underscores
|
|
40
|
+
map.states["Tamil Nadu"] = 18; // display name
|
|
41
|
+
map.states["tamilnadu"] = 18; // no separators
|
|
42
|
+
map.states["in-cs-33-tamil-nadu"] // LGD id
|
|
43
|
+
map.orissa = 8; // former name → Odisha
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Names are matched case-insensitively, with `&` treated as `and`. `Orissa`, `Pondicherry`, `Uttaranchal`, `NCT of Delhi`, `J&K` and similar former or colloquial names resolve to their current state. A name that matches nothing logs a console warning naming the property you typed — it never throws, and never silently does nothing. (The warning waits until the boundary data has loaded, since that is the first moment an unknown name can be told apart from one that just hasn't been matched yet.)
|
|
47
|
+
|
|
48
|
+
Other value APIs:
|
|
49
|
+
|
|
50
|
+
- `map.setValues({ Goa: 6, Gujarat: 7 })` — many values, one re-render.
|
|
51
|
+
- `map.getValues()` — everything currently set, keyed by display name.
|
|
52
|
+
- `values: { Goa: 6 }` as a constructor option — same thing, before first paint.
|
|
53
|
+
- District values work through the same accessor once you drill in: `map.states["North Goa"] = 3`.
|
|
54
|
+
|
|
55
|
+
## Options
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
var map = new BharatChoropleth("#map", { showRegionValues: true, districts: false });
|
|
59
|
+
// or, equivalently:
|
|
60
|
+
var map = new BharatChoropleth({ container: "#map", showRegionValues: true });
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
| Option | Default | Purpose |
|
|
64
|
+
| --- | --- | --- |
|
|
65
|
+
| `container` | `#bharat-choropleth`, then `#map` | Element or CSS selector. Also the first constructor argument. |
|
|
66
|
+
| `geometry` | fetched from `dataBaseUrl` | Inline GeoJSON/TopoJSON, a URL string, or a promise of either. |
|
|
67
|
+
| `dataBaseUrl` | jsDelivr copy of `data/generated` | Base URL for the prepared bundles. Point at your own copy to self-host. |
|
|
68
|
+
| `districts` | `true` with default data, else `false` | Click-to-drill-down into districts. |
|
|
69
|
+
| `fontColor` / `borderColor` | — | Sets the `--india-map-text` / `--india-map-stroke` CSS variables. |
|
|
70
|
+
| `borderWidth` | `2.5` | Region border thickness in px. Sets `--india-map-border-width`. |
|
|
71
|
+
| `selectionWidth` | `3` | Selection ring thickness in px; its halo is drawn at twice this. Sets `--india-map-selection-width`. |
|
|
72
|
+
| `colorScale` | built-in teal ramp | Ordered low-to-high colors, or a `(value, context) => color` function. |
|
|
73
|
+
| `values` | `{}` | Initial values, keyed by any accepted spelling. |
|
|
74
|
+
| `onReady` / `onError` | — | Called after the data renders, or if it fails to load. |
|
|
75
|
+
| `getId` / `getLabel` | `properties.id` / `properties.name` | Only needed for custom `geometry` with different property keys. |
|
|
76
|
+
|
|
77
|
+
Options can also be set as properties after construction, in either case style — `map.fontColor = "maroon"` and `map.font_color = "maroon"` are the same assignment, and neither is mistaken for a state name.
|
|
78
|
+
|
|
79
|
+
Every thickness is a CSS variable, so you can theme without touching the renderer. Strokes are `non-scaling`, meaning these are true on-screen pixels no matter how far the map is scaled down:
|
|
80
|
+
|
|
81
|
+
```css
|
|
82
|
+
.india-choropleth {
|
|
83
|
+
--india-map-border-width: 2.5; /* region borders */
|
|
84
|
+
--india-map-border-width-active: 2; /* hovered/focused region */
|
|
85
|
+
--india-map-selection-width: 3; /* selection ring; halo is 2x this */
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Every other [`IndiaChoroplethOptions`](https://github.com/shashankbudem/bharat-choropleth/blob/main/packages/js/src/types.ts) field (`referenceOverlay`, `loadDistricts`, `onRegionClick`, `formatValue`, `renderTooltip`, `showLegend`, ...) is accepted and forwarded.
|
|
90
|
+
|
|
91
|
+
Methods: `setValues`, `getValues`, `select(id)`, `drillDown(name | null)`, `getSelected()`, `getInspected()`, `destroy()`. The full engine is at `map.engine` (`null` until the data loads — `await map.ready` first).
|
|
92
|
+
|
|
93
|
+
## Hover and focus detail
|
|
94
|
+
|
|
95
|
+
Pointing at (or tabbing to) a region shows a tooltip with the region name, its formatted value, a share bar, and `26.3% of total · 1st of 36`. Regions with no value say `No data` and show neither share nor rank — the same wording the region's `aria-label` uses.
|
|
96
|
+
|
|
97
|
+
- **Rank** counts only regions that have a value, highest first, and ties share the better rank (`1st` twice, then `3rd`).
|
|
98
|
+
- **Placement** is anchored to the region's centroid, not the cursor, because hover and keyboard focus run through the same path and a focused region has no cursor to follow. The box shifts horizontally and flips below the centroid as needed so it never leaves the map.
|
|
99
|
+
- **Announcement** happens on focus, via `aria-describedby`. The tooltip is not an `aria-live` region; it would otherwise re-read itself on every hover, and the region's `aria-label` already carries name and value.
|
|
100
|
+
|
|
101
|
+
Replace the whole thing with `renderTooltip`, which receives `{ label, value, total, share, rank, rankedCount, level, feature, id, meta }` and returns a string or a DOM node:
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
var map = new BharatChoropleth("#map", {
|
|
105
|
+
renderTooltip: function (c) {
|
|
106
|
+
return c.value === null ? c.label + ": no data" : c.label + ": " + c.value + " (" + c.rank + " of " + c.rankedCount + ")";
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Boundary data
|
|
112
|
+
|
|
113
|
+
The package deliberately bundles no geographic boundaries; it downloads them. By default that means the prepared bundles in this repo's `data/generated`, served over jsDelivr, which must be attributed as:
|
|
114
|
+
|
|
115
|
+
> State/UT and district boundaries derived from datta07/INDIAN-SHAPEFILES (MIT).
|
|
116
|
+
|
|
117
|
+
For production, offline or air-gapped use, copy `data/generated/current-2019-states/` and `data/generated/current-2019-districts/` next to your app and point at them — no third-party CDN request at runtime:
|
|
118
|
+
|
|
119
|
+
```js
|
|
120
|
+
var map = new BharatChoropleth("#map", { dataBaseUrl: "/maps" });
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Or supply geometry directly and skip the fetch entirely, in which case the map renders synchronously:
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
var map = new BharatChoropleth("#map", { geometry: myTopoJson }); // or a URL string
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
See the repository's [data attribution](https://github.com/shashankbudem/bharat-choropleth/blob/main/data/ATTRIBUTION.md) for the licence and attribution of every bundle. Each asset keeps its own source's terms — don't blend the notices.
|
|
130
|
+
|
|
131
|
+
## From a bundler
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
npm add bharat-choropleth-js
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { BharatChoropleth } from "bharat-choropleth-js";
|
|
139
|
+
import "bharat-choropleth-js/style.css"; // the ESM build does not inject CSS
|
|
140
|
+
|
|
141
|
+
const map = new BharatChoropleth("#map");
|
|
142
|
+
map.states["Goa"] = 6;
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The ESM entry also exports the full `IndiaChoropleth` engine, the `STATES` registry, `resolveState`, `ATTRIBUTION` and `DEFAULT_DATA_BASE_URL`, plus every type.
|
|
146
|
+
|
|
147
|
+
## `IndiaChoropleth` (full-featured engine)
|
|
148
|
+
|
|
149
|
+
`BharatChoropleth` is a facade for the common case. `IndiaChoropleth` is the engine underneath, for controlled selection, custom tooltips, reference overlays and data that isn't one-number-per-state:
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
const map = new IndiaChoropleth(container, options);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
- `container`: an `HTMLElement`, or a CSS selector string resolved via `document.querySelector`.
|
|
156
|
+
- `options`: the same shape as the React `IndiaChoroplethProps` — see [`src/types.ts`](https://github.com/shashankbudem/bharat-choropleth/blob/main/packages/js/src/types.ts). Two slots differ because there's no JSX:
|
|
157
|
+
- `renderTooltip?: (context) => string | Node` — return a string (set as `textContent`) or a DOM node to mount directly. Omit for the built-in tooltip.
|
|
158
|
+
- `renderInsights?: (context, container: HTMLElement) => void` — imperatively populate the given container; called on every hover/selection change. Omit to skip the insights panel entirely.
|
|
159
|
+
|
|
160
|
+
It requires an explicit `states` layer with `getId`/`getLabel`/`getValue` accessors, and never fetches anything on your behalf. Under a script tag it is available as `window.IndiaChoropleth`; see the [full-engine example](https://github.com/shashankbudem/bharat-choropleth/blob/main/packages/js/example/index.html).
|
|
161
|
+
|
|
162
|
+
### Instance methods
|
|
163
|
+
|
|
164
|
+
- `update(partialOptions)` — merge new options (new data, controlled `selectedId`/`drillDownId`, swapped callbacks) and re-render.
|
|
165
|
+
- `select(id | null)` — select a region at the current level without changing drill-down.
|
|
166
|
+
- `drillDown(id | null)` — drill into a state, or pass `null` to return to the state view.
|
|
167
|
+
- `getSelected()` / `getInspected()` — read the current `MapRegion | null`.
|
|
168
|
+
- `destroy()` — remove all DOM content and cancel any in-flight loads. Call this before discarding the instance.
|
|
169
|
+
|
|
170
|
+
Controlled vs. uncontrolled state works the same way as the React version: pass `selectedId`/`drillDownId` (and keep passing them via `update()`) for controlled usage, or `defaultSelectedId`/`defaultDrillDownId` to let the instance manage its own.
|
|
171
|
+
|
|
172
|
+
## Design notes
|
|
173
|
+
|
|
174
|
+
- Hover/focus updates never rebuild the DOM — only class names, ARIA attributes, and the tooltip/insights content change. A full rebuild only happens when the underlying region set changes (drill-down navigation, new district data arriving, or an `update()` with new data). This matters in practice: rebuilding on every hover would drop keyboard focus mid-interaction.
|
|
175
|
+
- Load-attempt tracking is keyed by drill-down id, not by "do we have data yet" — a failed `loadDistricts` call intentionally does not retry on every re-render (see the comment on `attemptedDistrictLoadForId` in `src/IndiaChoropleth.ts`).
|
|
176
|
+
- `src/states.ts` carries state *identities* (id, name, slug) but no coordinates. It's what lets `map.goa = 6` be recognized and validated before any boundary file has downloaded — the geometry itself still never ships in the package.
|
|
177
|
+
- The script-tag build has its own entry (`src/iife.ts`) because it does two things the ESM build must not: inject the stylesheet, and assign the constructors to `window` by hand. Bundlers' `globalName` would have exposed the module *namespace*, making the call `new BharatChoropleth.BharatChoropleth(...)`.
|
|
178
|
+
|
|
179
|
+
## Build
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
pnpm build # ESM (dist/index.js) + script-tag IIFE (dist/bharat-choropleth.min.js) + style.css
|
|
183
|
+
pnpm test
|
|
184
|
+
pnpm typecheck
|
|
185
|
+
```
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";(()=>{var Ut=`.india-choropleth {
|
|
2
|
+
--india-map-stroke: #fff;
|
|
3
|
+
--india-map-stroke-active: #0f1b38;
|
|
4
|
+
/* Border widths, in screen pixels (the strokes are non-scaling). Override any
|
|
5
|
+
of these to retheme without touching the renderer. */
|
|
6
|
+
--india-map-border-width: 2.5;
|
|
7
|
+
--india-map-border-width-active: 2;
|
|
8
|
+
--india-map-selection-width: 3;
|
|
9
|
+
--india-map-small-marker-stroke: #53617b;
|
|
10
|
+
--india-map-focus: #0f766e;
|
|
11
|
+
--india-map-active: #ff725f;
|
|
12
|
+
--india-map-empty: #e7edf0;
|
|
13
|
+
--india-map-tooltip-bg: #fff;
|
|
14
|
+
--india-map-tooltip-border: #b8c2ce;
|
|
15
|
+
--india-map-text: #081435;
|
|
16
|
+
--india-map-muted: #53617b;
|
|
17
|
+
--india-map-line: #dce3e7;
|
|
18
|
+
--india-map-reference-bg: #eef1f3;
|
|
19
|
+
--india-map-reference-hatch: #9ba8af;
|
|
20
|
+
--india-map-reference-stroke: #6f7d85;
|
|
21
|
+
position: relative;
|
|
22
|
+
color: var(--india-map-text);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.india-choropleth__toolbar { min-height: 40px; display: flex; align-items: center; justify-content: flex-end; }
|
|
26
|
+
.india-choropleth__breadcrumb { display: flex; align-items: center; gap: .5rem; font: 500 .875rem/1.3 system-ui, sans-serif; }
|
|
27
|
+
.india-choropleth__back { border: 0; padding: .375rem; background: transparent; color: var(--india-map-focus); font: inherit; cursor: pointer; }
|
|
28
|
+
.india-choropleth__back:hover { text-decoration: underline; }
|
|
29
|
+
.india-choropleth__back:focus-visible { outline: 3px solid color-mix(in srgb, var(--india-map-focus) 35%, transparent); outline-offset: 2px; }
|
|
30
|
+
.india-choropleth__canvas { position: relative; width: 100%; }
|
|
31
|
+
.india-choropleth__status { min-height: 16rem; padding: 2rem; border: 1px dashed var(--india-map-line); display: grid; place-items: center; color: var(--india-map-muted); font: 500 .9375rem/1.5 system-ui, sans-serif; text-align: center; }
|
|
32
|
+
.india-choropleth__svg { display: block; width: 100%; height: auto; overflow: visible; }
|
|
33
|
+
.india-choropleth__region { stroke: var(--india-map-stroke); stroke-width: var(--india-map-border-width); stroke-linejoin: round; vector-effect: non-scaling-stroke; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: filter 160ms ease, opacity 160ms ease, stroke 160ms ease, stroke-width 160ms ease, transform 160ms ease; transform-box: fill-box; transform-origin: center; }
|
|
34
|
+
/* An SVG outline draws a rectangle around the path's bounding box, not its actual
|
|
35
|
+
shape. Suppress it here (both our own prior rule and the browser default) and
|
|
36
|
+
rely on the shape-following stroke/shadow/lift below as the focus indicator.
|
|
37
|
+
\`:focus\` and \`:focus-visible\` are separate rules (not a comma list) so a browser
|
|
38
|
+
that doesn't parse \`:focus-visible\` still applies the plain \`:focus\` one instead
|
|
39
|
+
of silently dropping the whole rule and falling back to its own default ring. */
|
|
40
|
+
.india-choropleth__region:focus { outline: none; }
|
|
41
|
+
.india-choropleth__region:focus-visible { outline: none; }
|
|
42
|
+
.india-choropleth__region--reference-merged { stroke: transparent; }
|
|
43
|
+
.india-choropleth--static .india-choropleth__region { cursor: default; }
|
|
44
|
+
.india-choropleth__region:is(:hover, :focus-visible), .india-choropleth__region--inspected { stroke: var(--india-map-stroke-active); stroke-width: var(--india-map-border-width-active); filter: drop-shadow(0 5px 4px rgb(8 20 53 / .14)); transform: translateY(-2px); }
|
|
45
|
+
/* Selection is a ring, never a fill: on a choropleth the fill carries the value,
|
|
46
|
+
so recoloring the picked region made its color stop meaning anything. The halo
|
|
47
|
+
sits under the ring so the accent stays legible on pale and saturated fills alike. */
|
|
48
|
+
.india-choropleth__selection { pointer-events: none; transition: transform 160ms ease; }
|
|
49
|
+
.india-choropleth__selection--lifted { transform: translateY(-2px); }
|
|
50
|
+
.india-choropleth__selection-halo { stroke: var(--india-map-stroke); stroke-width: calc(var(--india-map-selection-width) * 2); stroke-linejoin: round; vector-effect: non-scaling-stroke; }
|
|
51
|
+
.india-choropleth__selection-ring { stroke: var(--india-map-active); stroke-width: var(--india-map-selection-width); stroke-linejoin: round; vector-effect: non-scaling-stroke; }
|
|
52
|
+
.india-choropleth__reference-fill path { pointer-events: none; stroke: var(--india-map-reference-stroke); stroke-width: 1; vector-effect: non-scaling-stroke; }
|
|
53
|
+
.india-choropleth__reference-outline path { pointer-events: none; stroke: var(--india-map-reference-stroke); stroke-width: 1.6; stroke-dasharray: 4 3; vector-effect: non-scaling-stroke; }
|
|
54
|
+
/* Dulled by a legend filter \u2014 the regions outside the picked band, plus their
|
|
55
|
+
markers, values and leader lines. Dulled rather than hidden, so the map keeps
|
|
56
|
+
its shape and a dimmed region can still be hovered for its number. The
|
|
57
|
+
reference overlay is left alone: it is non-statistical context, in no band.
|
|
58
|
+
|
|
59
|
+
Greyed as well as faded, because fading alone does not separate the pale end
|
|
60
|
+
of a ramp: a dark fill at low opacity lands on roughly the same light grey as
|
|
61
|
+
a pale fill at full opacity, so picking the lightest band left the map reading
|
|
62
|
+
as though nothing had been picked. Draining the colour instead makes "in the
|
|
63
|
+
band" mean "still coloured", whichever band it is. */
|
|
64
|
+
.india-choropleth__dimmed { opacity: .25; filter: grayscale(1); }
|
|
65
|
+
/* The region's own hover rule outranks this one on \`filter\`, so pointing at a
|
|
66
|
+
dulled region brings its colour back along with the usual lift. */
|
|
67
|
+
.india-choropleth__region.india-choropleth__dimmed:is(:hover, :focus-visible) { opacity: .6; }
|
|
68
|
+
/* And the survivors are lifted off the page, so the picked band reads as a group
|
|
69
|
+
even where its own colour is nearly white. A shadow rather than a heavier
|
|
70
|
+
outline: strokes here are non-scaling, so a 2px dark edge around one of
|
|
71
|
+
Lakshadweep's one-unit islands swallows the island whole. */
|
|
72
|
+
.india-choropleth__svg--filtered .india-choropleth__region:not(.india-choropleth__dimmed) { filter: drop-shadow(0 2px 3px rgb(8 20 53 / .28)); }
|
|
73
|
+
/* The water an island group encloses, hoverable as part of the group. Invisible
|
|
74
|
+
by design and painted under every region, so it only ever picks up a pointer
|
|
75
|
+
that would otherwise have hit nothing. */
|
|
76
|
+
.india-choropleth__hit-areas path { cursor: pointer; }
|
|
77
|
+
/* A dot standing in for a region too small to see at this scale (Puducherry's
|
|
78
|
+
enclaves). Filled with the region's own ramp colour by the renderer, so it
|
|
79
|
+
still reads as data rather than decoration \u2014 and hoverable, because the dot
|
|
80
|
+
is what the reader can see and aim at. */
|
|
81
|
+
.india-choropleth__small-markers circle { cursor: pointer; stroke: var(--india-map-small-marker-stroke); stroke-width: var(--india-map-border-width); vector-effect: non-scaling-stroke; }
|
|
82
|
+
.india-choropleth--static .india-choropleth__small-markers circle { pointer-events: none; cursor: default; }
|
|
83
|
+
/* Leader from a small region to its value label, which sits outside the shape. */
|
|
84
|
+
.india-choropleth__value-leaders line { pointer-events: none; stroke: var(--india-map-small-marker-stroke); stroke-width: 1; vector-effect: non-scaling-stroke; }
|
|
85
|
+
.india-choropleth__region-values { pointer-events: none; fill: var(--india-map-text); font: 700 11px/1 system-ui, sans-serif; paint-order: stroke; stroke: rgb(255 255 255 / .82); stroke-width: 3px; stroke-linejoin: round; }
|
|
86
|
+
.india-choropleth__region-values--district { font-size: 9px; }
|
|
87
|
+
/* --india-map-tooltip-dx/dy are set by the renderer to keep the box inside the map:
|
|
88
|
+
dx nudges it away from a left/right edge, dy flips it below a region near the top. */
|
|
89
|
+
.india-choropleth__tooltip-anchor { position: absolute; z-index: 1; pointer-events: none; transform: translate(calc(-50% + var(--india-map-tooltip-dx, 0px)), var(--india-map-tooltip-dy, calc(-100% - .75rem))); }
|
|
90
|
+
.india-choropleth__tooltip { min-width: 8rem; padding: .75rem .875rem; border: 1px solid var(--india-map-tooltip-border); border-radius: .625rem; display: grid; gap: .18rem; background: var(--india-map-tooltip-bg); box-shadow: 0 .5rem 1.25rem rgb(8 20 53 / .11); font: 500 .875rem/1.3 system-ui, sans-serif; }
|
|
91
|
+
.india-choropleth__tooltip strong { font-size: .875rem; }
|
|
92
|
+
.india-choropleth__tooltip b { font-size: 1.2rem; }
|
|
93
|
+
.india-choropleth__tooltip small { color: var(--india-map-muted); font-size: .75rem; }
|
|
94
|
+
.india-choropleth__tooltip-bar { display: block; height: .3rem; margin: .1rem 0 .15rem; border-radius: .3rem; background: var(--india-map-empty); overflow: hidden; }
|
|
95
|
+
.india-choropleth__tooltip-bar > span { display: block; height: 100%; border-radius: inherit; background: var(--india-map-active); }
|
|
96
|
+
.india-choropleth__legend { margin-top: .75rem; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: .75rem; color: var(--india-map-muted); font: .8125rem/1.3 system-ui, sans-serif; }
|
|
97
|
+
.india-choropleth__swatches { display: flex; gap: .25rem; }
|
|
98
|
+
.india-choropleth__swatch { width: clamp(1.75rem, 7vw, 4.25rem); height: .75rem; border-radius: .1rem; }
|
|
99
|
+
/* On an interactive map each swatch filters to its own band. The bar stays the
|
|
100
|
+
same 12px it has always been; a transparent border above and below it lifts
|
|
101
|
+
the pointer and touch target to 24px, and the negative margin gives that
|
|
102
|
+
height back so the legend row is unchanged. Deliberately top and bottom only:
|
|
103
|
+
widening sideways too would push the row out and leave neighbouring targets
|
|
104
|
+
overlapping in the 4px gap between them, where a click is then decided by
|
|
105
|
+
paint order rather than by which swatch you aimed at. */
|
|
106
|
+
button.india-choropleth__swatch { box-sizing: content-box; margin: -.375rem 0; padding: 0; border: 0 solid transparent; border-top-width: .375rem; border-bottom-width: .375rem; background-clip: padding-box; cursor: pointer; appearance: none; transition: opacity 160ms ease, box-shadow 160ms ease; }
|
|
107
|
+
button.india-choropleth__swatch:focus-visible { outline: 3px solid color-mix(in srgb, var(--india-map-focus) 35%, transparent); outline-offset: 1px; }
|
|
108
|
+
/* A band no region falls in stays at full strength: the ramp is continuous, and
|
|
109
|
+
fading one stop out of the middle of it reads as a broken legend rather than
|
|
110
|
+
as an empty band. It is inert instead \u2014 default cursor, and a title saying so
|
|
111
|
+
\u2014 because filtering to nothing would just dim the whole map. */
|
|
112
|
+
button.india-choropleth__swatch[aria-disabled="true"] { cursor: default; }
|
|
113
|
+
/* The picked band, and the bands it is picked over. */
|
|
114
|
+
.india-choropleth__swatch--active { box-shadow: 0 0 0 2px var(--india-map-stroke), 0 0 0 4px var(--india-map-active); }
|
|
115
|
+
.india-choropleth__swatch--muted { opacity: .3; }
|
|
116
|
+
.india-choropleth__reference-key { width: 1rem; height: .75rem; border: 1px solid var(--india-map-reference-stroke); background: repeating-linear-gradient(45deg, var(--india-map-reference-bg) 0 3px, var(--india-map-reference-hatch) 3px 4px); }
|
|
117
|
+
.india-choropleth__reference-key--solid { background: var(--india-map-reference-bg); }
|
|
118
|
+
.india-choropleth__insights { margin-top: 1rem; }
|
|
119
|
+
@media (prefers-reduced-motion: reduce) { .india-choropleth__region, button.india-choropleth__swatch { transition: none; } }
|
|
120
|
+
|
|
121
|
+
/* Placeholder shown by the \`BharatChoropleth\` facade while boundary data is
|
|
122
|
+
being fetched, and for the message if that fetch fails. */
|
|
123
|
+
.bharat-choropleth__status { padding: 1.25rem; border-radius: .625rem; background: var(--india-map-empty, #eef1f7); color: var(--india-map-muted, #53617b); font: 500 .875rem/1.45 system-ui, sans-serif; text-align: center; }
|
|
124
|
+
.bharat-choropleth__status--error { background: #fdeceb; color: #8a1c14; }
|
|
125
|
+
`;var K=class{constructor(){this._partials=new Float64Array(32),this._n=0}add(e){let n=this._partials,r=0;for(let i=0;i<this._n&&i<32;i++){let o=n[i],a=e+o,l=Math.abs(e)<Math.abs(o)?e-(a-o):o-(a-e);l&&(n[r++]=l),e=a}return n[r]=e,this._n=r+1,this}valueOf(){let e=this._partials,n=this._n,r,i,o,a=0;if(n>0){for(a=e[--n];n>0&&(r=a,i=e[--n],a=r+i,o=i-(a-r),!o););n>0&&(o<0&&e[n-1]<0||o>0&&e[n-1]>0)&&(i=o*2,r=a+i,i==r-a&&(a=r))}return a}};function*hr(t){for(let e of t)yield*e}function pe(t){return Array.from(hr(t))}var P=1e-6,Vt=1e-12,I=Math.PI,$=I/2,dt=I/4,q=I*2,U=180/I,B=I/180,M=Math.abs,je=Math.atan,re=Math.atan2,D=Math.cos;var Wt=Math.exp;var Kt=Math.log;var T=Math.sin,Yt=Math.sign||function(t){return t>0?1:t<0?-1:0},Y=Math.sqrt,Xt=Math.tan;function Jt(t){return t>1?0:t<-1?I:Math.acos(t)}function ie(t){return t>1?$:t<-1?-$:Math.asin(t)}function z(){}function $e(t,e){t&&Qt.hasOwnProperty(t.type)&&Qt[t.type](t,e)}var Zt={Feature:function(t,e){$e(t.geometry,e)},FeatureCollection:function(t,e){for(var n=t.features,r=-1,i=n.length;++r<i;)$e(n[r].geometry,e)}},Qt={Sphere:function(t,e){e.sphere()},Point:function(t,e){t=t.coordinates,e.point(t[0],t[1],t[2])},MultiPoint:function(t,e){for(var n=t.coordinates,r=-1,i=n.length;++r<i;)t=n[r],e.point(t[0],t[1],t[2])},LineString:function(t,e){ut(t.coordinates,e,0)},MultiLineString:function(t,e){for(var n=t.coordinates,r=-1,i=n.length;++r<i;)ut(n[r],e,0)},Polygon:function(t,e){en(t.coordinates,e)},MultiPolygon:function(t,e){for(var n=t.coordinates,r=-1,i=n.length;++r<i;)en(n[r],e)},GeometryCollection:function(t,e){for(var n=t.geometries,r=-1,i=n.length;++r<i;)$e(n[r],e)}};function ut(t,e,n){var r=-1,i=t.length-n,o;for(e.lineStart();++r<i;)o=t[r],e.point(o[0],o[1],o[2]);e.lineEnd()}function en(t,e){var n=-1,r=t.length;for(e.polygonStart();++n<r;)ut(t[n],e,1);e.polygonEnd()}function ae(t,e){t&&Zt.hasOwnProperty(t.type)?Zt[t.type](t,e):$e(t,e)}function we(t){return[re(t[1],t[0]),ie(t[2])]}function Z(t){var e=t[0],n=t[1],r=D(n);return[r*D(e),r*T(e),T(n)]}function Se(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function fe(t,e){return[t[1]*e[2]-t[2]*e[1],t[2]*e[0]-t[0]*e[2],t[0]*e[1]-t[1]*e[0]]}function qe(t,e){t[0]+=e[0],t[1]+=e[1],t[2]+=e[2]}function _e(t,e){return[t[0]*e,t[1]*e,t[2]*e]}function ke(t){var e=Y(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=e,t[1]/=e,t[2]/=e}function Ie(t,e){function n(r,i){return r=t(r,i),e(r[0],r[1])}return t.invert&&e.invert&&(n.invert=function(r,i){return r=e.invert(r,i),r&&t.invert(r[0],r[1])}),n}function ht(t,e){return M(t)>I&&(t-=Math.round(t/q)*q),[t,e]}ht.invert=ht;function pt(t,e,n){return(t%=q)?e||n?Ie(nn(t),rn(e,n)):nn(t):e||n?rn(e,n):ht}function tn(t){return function(e,n){return e+=t,M(e)>I&&(e-=Math.round(e/q)*q),[e,n]}}function nn(t){var e=tn(t);return e.invert=tn(-t),e}function rn(t,e){var n=D(t),r=T(t),i=D(e),o=T(e);function a(l,h){var d=D(h),s=D(l)*d,c=T(l)*d,u=T(h),p=u*n+s*r;return[re(c*i-p*o,s*n-u*r),ie(p*i+c*o)]}return a.invert=function(l,h){var d=D(h),s=D(l)*d,c=T(l)*d,u=T(h),p=u*i-c*o;return[re(c*i+u*o,s*n+p*r),ie(p*n-s*r)]},a}function on(t){t=pt(t[0]*B,t[1]*B,t.length>2?t[2]*B:0);function e(n){return n=t(n[0]*B,n[1]*B),n[0]*=U,n[1]*=U,n}return e.invert=function(n){return n=t.invert(n[0]*B,n[1]*B),n[0]*=U,n[1]*=U,n},e}function sn(t,e,n,r,i,o){if(n){var a=D(e),l=T(e),h=r*n;i==null?(i=e+r*q,o=e-h/2):(i=an(a,i),o=an(a,o),(r>0?i<o:i>o)&&(i+=r*q));for(var d,s=i;r>0?s>o:s<o;s-=h)d=we([a,-l*D(s),-l*T(s)]),t.point(d[0],d[1])}}function an(t,e){e=Z(e),e[0]-=t,ke(e);var n=Jt(-e[1]);return((-e[2]<0?-n:n)+q-P)%q}function ze(){var t=[],e;return{point:function(n,r,i){e.push([n,r,i])},lineStart:function(){t.push(e=[])},lineEnd:z,rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))},result:function(){var n=t;return t=[],e=null,n}}}function me(t,e){return M(t[0]-e[0])<P&&M(t[1]-e[1])<P}function He(t,e,n,r){this.x=t,this.z=e,this.o=n,this.e=r,this.v=!1,this.n=this.p=null}function Ue(t,e,n,r,i){var o=[],a=[],l,h;if(t.forEach(function(f){if(!((m=f.length-1)<=0)){var m,v=f[0],b=f[m],y;if(me(v,b)){if(!v[2]&&!b[2]){for(i.lineStart(),l=0;l<m;++l)i.point((v=f[l])[0],v[1]);i.lineEnd();return}b[0]+=2*P}o.push(y=new He(v,f,null,!0)),a.push(y.o=new He(v,null,y,!1)),o.push(y=new He(b,f,null,!1)),a.push(y.o=new He(b,null,y,!0))}}),!!o.length){for(a.sort(e),ln(o),ln(a),l=0,h=a.length;l<h;++l)a[l].e=n=!n;for(var d=o[0],s,c;;){for(var u=d,p=!0;u.v;)if((u=u.n)===d)return;s=u.z,i.lineStart();do{if(u.v=u.o.v=!0,u.e){if(p)for(l=0,h=s.length;l<h;++l)i.point((c=s[l])[0],c[1]);else r(u.x,u.n.x,1,i);u=u.n}else{if(p)for(s=u.p.z,l=s.length-1;l>=0;--l)i.point((c=s[l])[0],c[1]);else r(u.x,u.p.x,-1,i);u=u.p}u=u.o,s=u.z,p=!p}while(!u.v);i.lineEnd()}}}function ln(t){if(e=t.length){for(var e,n=0,r=t[0],i;++n<e;)r.n=i=t[n],i.p=r,r=i;r.n=i=t[0],i.p=r}}function ft(t){return M(t[0])<=I?t[0]:Yt(t[0])*((M(t[0])+I)%q-I)}function cn(t,e){var n=ft(e),r=e[1],i=T(r),o=[T(n),-D(n),0],a=0,l=0,h=new K;i===1?r=$+P:i===-1&&(r=-$-P);for(var d=0,s=t.length;d<s;++d)if(u=(c=t[d]).length)for(var c,u,p=c[u-1],f=ft(p),m=p[1]/2+dt,v=T(m),b=D(m),y=0;y<u;++y,f=E,v=k,b=L,p=x){var x=c[y],E=ft(x),w=x[1]/2+dt,k=T(w),L=D(w),S=E-f,C=S>=0?1:-1,O=C*S,_=O>I,V=v*k;if(h.add(re(V*C*T(O),b*L+V*D(O))),a+=_?S+C*q:S,_^f>=n^E>=n){var F=fe(Z(p),Z(x));ke(F);var A=fe(o,F);ke(A);var g=(_^S>=0?-1:1)*ie(A[2]);(r>g||r===g&&(F[0]||F[1]))&&(l+=_^S>=0?1:-1)}}return(a<-P||a<P&&h<-Vt)^l&1}function Ve(t,e,n,r){return function(i){var o=e(i),a=ze(),l=e(a),h=!1,d,s,c,u={point:p,lineStart:m,lineEnd:v,polygonStart:function(){u.point=b,u.lineStart=y,u.lineEnd=x,s=[],d=[]},polygonEnd:function(){u.point=p,u.lineStart=m,u.lineEnd=v,s=pe(s);var E=cn(d,r);s.length?(h||(i.polygonStart(),h=!0),Ue(s,fr,E,n,i)):E&&(h||(i.polygonStart(),h=!0),i.lineStart(),n(null,null,1,i),i.lineEnd()),h&&(i.polygonEnd(),h=!1),s=d=null},sphere:function(){i.polygonStart(),i.lineStart(),n(null,null,1,i),i.lineEnd(),i.polygonEnd()}};function p(E,w){t(E,w)&&i.point(E,w)}function f(E,w){o.point(E,w)}function m(){u.point=f,o.lineStart()}function v(){u.point=p,o.lineEnd()}function b(E,w){c.push([E,w]),l.point(E,w)}function y(){l.lineStart(),c=[]}function x(){b(c[0][0],c[0][1]),l.lineEnd();var E=l.clean(),w=a.result(),k,L=w.length,S,C,O;if(c.pop(),d.push(c),c=null,!!L){if(E&1){if(C=w[0],(S=C.length-1)>0){for(h||(i.polygonStart(),h=!0),i.lineStart(),k=0;k<S;++k)i.point((O=C[k])[0],O[1]);i.lineEnd()}return}L>1&&E&2&&w.push(w.pop().concat(w.shift())),s.push(w.filter(pr))}}return u}}function pr(t){return t.length>1}function fr(t,e){return((t=t.x)[0]<0?t[1]-$-P:$-t[1])-((e=e.x)[0]<0?e[1]-$-P:$-e[1])}var mt=Ve(function(){return!0},mr,vr,[-I,-$]);function mr(t){var e=NaN,n=NaN,r=NaN,i;return{lineStart:function(){t.lineStart(),i=1},point:function(o,a){var l=o>0?I:-I,h=M(o-e);M(h-I)<P?(t.point(e,n=(n+a)/2>0?$:-$),t.point(r,n),t.lineEnd(),t.lineStart(),t.point(l,n),t.point(o,n),i=0):r!==l&&h>=I&&(M(e-r)<P&&(e-=r*P),M(o-l)<P&&(o-=l*P),n=gr(e,n,o,a),t.point(r,n),t.lineEnd(),t.lineStart(),t.point(l,n),i=0),t.point(e=o,n=a),r=l},lineEnd:function(){t.lineEnd(),e=n=NaN},clean:function(){return 2-i}}}function gr(t,e,n,r){var i,o,a=T(t-n);return M(a)>P?je((T(e)*(o=D(r))*T(n)-T(r)*(i=D(e))*T(t))/(i*o*a)):(e+r)/2}function vr(t,e,n,r){var i;if(t==null)i=n*$,r.point(-I,i),r.point(0,i),r.point(I,i),r.point(I,0),r.point(I,-i),r.point(0,-i),r.point(-I,-i),r.point(-I,0),r.point(-I,i);else if(M(t[0]-e[0])>P){var o=t[0]<e[0]?I:-I;i=n*o/2,r.point(-o,i),r.point(0,i),r.point(o,i)}else r.point(e[0],e[1])}function dn(t){var e=D(t),n=2*B,r=e>0,i=M(e)>P;function o(s,c,u,p){sn(p,t,n,u,s,c)}function a(s,c){return D(s)*D(c)>e}function l(s){var c,u,p,f,m;return{lineStart:function(){f=p=!1,m=1},point:function(v,b){var y=[v,b],x,E=a(v,b),w=r?E?0:d(v,b):E?d(v+(v<0?I:-I),b):0;if(!c&&(f=p=E)&&s.lineStart(),E!==p&&(x=h(c,y),(!x||me(c,x)||me(y,x))&&(y[2]=1)),E!==p)m=0,E?(s.lineStart(),x=h(y,c),s.point(x[0],x[1])):(x=h(c,y),s.point(x[0],x[1],2),s.lineEnd()),c=x;else if(i&&c&&r^E){var k;!(w&u)&&(k=h(y,c,!0))&&(m=0,r?(s.lineStart(),s.point(k[0][0],k[0][1]),s.point(k[1][0],k[1][1]),s.lineEnd()):(s.point(k[1][0],k[1][1]),s.lineEnd(),s.lineStart(),s.point(k[0][0],k[0][1],3)))}E&&(!c||!me(c,y))&&s.point(y[0],y[1]),c=y,p=E,u=w},lineEnd:function(){p&&s.lineEnd(),c=null},clean:function(){return m|(f&&p)<<1}}}function h(s,c,u){var p=Z(s),f=Z(c),m=[1,0,0],v=fe(p,f),b=Se(v,v),y=v[0],x=b-y*y;if(!x)return!u&&s;var E=e*b/x,w=-e*y/x,k=fe(m,v),L=_e(m,E),S=_e(v,w);qe(L,S);var C=k,O=Se(L,C),_=Se(C,C),V=O*O-_*(Se(L,L)-1);if(!(V<0)){var F=Y(V),A=_e(C,(-O-F)/_);if(qe(A,L),A=we(A),!u)return A;var g=s[0],R=c[0],j=s[1],W=c[1],X;R<g&&(X=g,g=R,R=X);var Ee=R-g,te=M(Ee-I)<P,le=te||Ee<P;if(!te&&W<j&&(X=j,j=W,W=X),le?te?j+W>0^A[1]<(M(A[0]-g)<P?j:W):j<=A[1]&&A[1]<=W:Ee>I^(g<=A[0]&&A[0]<=R)){var ne=_e(C,(-O+F)/_);return qe(ne,L),[A,we(ne)]}}}function d(s,c){var u=r?t:I-t,p=0;return s<-u?p|=1:s>u&&(p|=2),c<-u?p|=4:c>u&&(p|=8),p}return Ve(a,l,o,r?[0,-t]:[-I,t-I])}function un(t,e,n,r,i,o){var a=t[0],l=t[1],h=e[0],d=e[1],s=0,c=1,u=h-a,p=d-l,f;if(f=n-a,!(!u&&f>0)){if(f/=u,u<0){if(f<s)return;f<c&&(c=f)}else if(u>0){if(f>c)return;f>s&&(s=f)}if(f=i-a,!(!u&&f<0)){if(f/=u,u<0){if(f>c)return;f>s&&(s=f)}else if(u>0){if(f<s)return;f<c&&(c=f)}if(f=r-l,!(!p&&f>0)){if(f/=p,p<0){if(f<s)return;f<c&&(c=f)}else if(p>0){if(f>c)return;f>s&&(s=f)}if(f=o-l,!(!p&&f<0)){if(f/=p,p<0){if(f>c)return;f>s&&(s=f)}else if(p>0){if(f<s)return;f<c&&(c=f)}return s>0&&(t[0]=a+s*u,t[1]=l+s*p),c<1&&(e[0]=a+c*u,e[1]=l+c*p),!0}}}}}var Re=1e9,We=-Re;function gt(t,e,n,r){function i(d,s){return t<=d&&d<=n&&e<=s&&s<=r}function o(d,s,c,u){var p=0,f=0;if(d==null||(p=a(d,c))!==(f=a(s,c))||h(d,s)<0^c>0)do u.point(p===0||p===3?t:n,p>1?r:e);while((p=(p+c+4)%4)!==f);else u.point(s[0],s[1])}function a(d,s){return M(d[0]-t)<P?s>0?0:3:M(d[0]-n)<P?s>0?2:1:M(d[1]-e)<P?s>0?1:0:s>0?3:2}function l(d,s){return h(d.x,s.x)}function h(d,s){var c=a(d,1),u=a(s,1);return c!==u?c-u:c===0?s[1]-d[1]:c===1?d[0]-s[0]:c===2?d[1]-s[1]:s[0]-d[0]}return function(d){var s=d,c=ze(),u,p,f,m,v,b,y,x,E,w,k,L={point:S,lineStart:V,lineEnd:F,polygonStart:O,polygonEnd:_};function S(g,R){i(g,R)&&s.point(g,R)}function C(){for(var g=0,R=0,j=p.length;R<j;++R)for(var W=p[R],X=1,Ee=W.length,te=W[0],le,ne,Ne=te[0],he=te[1];X<Ee;++X)le=Ne,ne=he,te=W[X],Ne=te[0],he=te[1],ne<=r?he>r&&(Ne-le)*(r-ne)>(he-ne)*(t-le)&&++g:he<=r&&(Ne-le)*(r-ne)<(he-ne)*(t-le)&&--g;return g}function O(){s=c,u=[],p=[],k=!0}function _(){var g=C(),R=k&&g,j=(u=pe(u)).length;(R||j)&&(d.polygonStart(),R&&(d.lineStart(),o(null,null,1,d),d.lineEnd()),j&&Ue(u,l,g,o,d),d.polygonEnd()),s=d,u=p=f=null}function V(){L.point=A,p&&p.push(f=[]),w=!0,E=!1,y=x=NaN}function F(){u&&(A(m,v),b&&E&&c.rejoin(),u.push(c.result())),L.point=S,E&&s.lineEnd()}function A(g,R){var j=i(g,R);if(p&&f.push([g,R]),w)m=g,v=R,b=j,w=!1,j&&(s.lineStart(),s.point(g,R));else if(j&&E)s.point(g,R);else{var W=[y=Math.max(We,Math.min(Re,y)),x=Math.max(We,Math.min(Re,x))],X=[g=Math.max(We,Math.min(Re,g)),R=Math.max(We,Math.min(Re,R))];un(W,X,t,e,n,r)?(E||(s.lineStart(),s.point(W[0],W[1])),s.point(X[0],X[1]),j||s.lineEnd(),k=!1):j&&(s.lineStart(),s.point(g,R),k=!1)}y=g,x=R,E=j}return L}}var Pe=t=>t;var vt=new K,yt=new K,hn,pn,bt,xt,se={point:z,lineStart:z,lineEnd:z,polygonStart:function(){se.lineStart=yr,se.lineEnd=xr},polygonEnd:function(){se.lineStart=se.lineEnd=se.point=z,vt.add(M(yt)),yt=new K},result:function(){var t=vt/2;return vt=new K,t}};function yr(){se.point=br}function br(t,e){se.point=fn,hn=bt=t,pn=xt=e}function fn(t,e){yt.add(xt*t-bt*e),bt=t,xt=e}function xr(){fn(hn,pn)}var Et=se;var ge=1/0,Ke=ge,Ce=-ge,Ye=Ce,Er={point:wr,lineStart:z,lineEnd:z,polygonStart:z,polygonEnd:z,result:function(){var t=[[ge,Ke],[Ce,Ye]];return Ce=Ye=-(Ke=ge=1/0),t}};function wr(t,e){t<ge&&(ge=t),t>Ce&&(Ce=t),e<Ke&&(Ke=e),e>Ye&&(Ye=e)}var ve=Er;var wt=0,St=0,Me=0,Xe=0,Je=0,ye=0,_t=0,kt=0,Le=0,vn,yn,Q,ee,J={point:ce,lineStart:mn,lineEnd:gn,polygonStart:function(){J.lineStart=kr,J.lineEnd=Ir},polygonEnd:function(){J.point=ce,J.lineStart=mn,J.lineEnd=gn},result:function(){var t=Le?[_t/Le,kt/Le]:ye?[Xe/ye,Je/ye]:Me?[wt/Me,St/Me]:[NaN,NaN];return wt=St=Me=Xe=Je=ye=_t=kt=Le=0,t}};function ce(t,e){wt+=t,St+=e,++Me}function mn(){J.point=Sr}function Sr(t,e){J.point=_r,ce(Q=t,ee=e)}function _r(t,e){var n=t-Q,r=e-ee,i=Y(n*n+r*r);Xe+=i*(Q+t)/2,Je+=i*(ee+e)/2,ye+=i,ce(Q=t,ee=e)}function gn(){J.point=ce}function kr(){J.point=Rr}function Ir(){bn(vn,yn)}function Rr(t,e){J.point=bn,ce(vn=Q=t,yn=ee=e)}function bn(t,e){var n=t-Q,r=e-ee,i=Y(n*n+r*r);Xe+=i*(Q+t)/2,Je+=i*(ee+e)/2,ye+=i,i=ee*t-Q*e,_t+=i*(Q+t),kt+=i*(ee+e),Le+=i*3,ce(Q=t,ee=e)}var It=J;function Ze(t){this._context=t}Ze.prototype={_radius:4.5,pointRadius:function(t){return this._radius=t,this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){this._line===0&&this._context.closePath(),this._point=NaN},point:function(t,e){switch(this._point){case 0:{this._context.moveTo(t,e),this._point=1;break}case 1:{this._context.lineTo(t,e);break}default:{this._context.moveTo(t+this._radius,e),this._context.arc(t,e,this._radius,0,q);break}}},result:z};var Pt=new K,Rt,xn,En,De,Ae,Qe={point:z,lineStart:function(){Qe.point=Pr},lineEnd:function(){Rt&&wn(xn,En),Qe.point=z},polygonStart:function(){Rt=!0},polygonEnd:function(){Rt=null},result:function(){var t=+Pt;return Pt=new K,t}};function Pr(t,e){Qe.point=wn,xn=De=t,En=Ae=e}function wn(t,e){De-=t,Ae-=e,Pt.add(Y(De*De+Ae*Ae)),De=t,Ae=e}var Ct=Qe;var Sn,et,_n,kn,be=class{constructor(e){this._append=e==null?In:Cr(e),this._radius=4.5,this._=""}pointRadius(e){return this._radius=+e,this}polygonStart(){this._line=0}polygonEnd(){this._line=NaN}lineStart(){this._point=0}lineEnd(){this._line===0&&(this._+="Z"),this._point=NaN}point(e,n){switch(this._point){case 0:{this._append`M${e},${n}`,this._point=1;break}case 1:{this._append`L${e},${n}`;break}default:{if(this._append`M${e},${n}`,this._radius!==_n||this._append!==et){let r=this._radius,i=this._;this._="",this._append`m0,${r}a${r},${r} 0 1,1 0,${-2*r}a${r},${r} 0 1,1 0,${2*r}z`,_n=r,et=this._append,kn=this._,this._=i}this._+=kn;break}}}result(){let e=this._;return this._="",e.length?e:null}};function In(t){let e=1;this._+=t[0];for(let n=t.length;e<n;++e)this._+=arguments[e]+t[e]}function Cr(t){let e=Math.floor(t);if(!(e>=0))throw new RangeError(`invalid digits: ${t}`);if(e>15)return In;if(e!==Sn){let n=10**e;Sn=e,et=function(i){let o=1;this._+=i[0];for(let a=i.length;o<a;++o)this._+=Math.round(arguments[o]*n)/n+i[o]}}return et}function tt(t,e){let n=3,r=4.5,i,o;function a(l){return l&&(typeof r=="function"&&o.pointRadius(+r.apply(this,arguments)),ae(l,i(o))),o.result()}return a.area=function(l){return ae(l,i(Et)),Et.result()},a.measure=function(l){return ae(l,i(Ct)),Ct.result()},a.bounds=function(l){return ae(l,i(ve)),ve.result()},a.centroid=function(l){return ae(l,i(It)),It.result()},a.projection=function(l){return arguments.length?(i=l==null?(t=null,Pe):(t=l).stream,a):t},a.context=function(l){return arguments.length?(o=l==null?(e=null,new be(n)):new Ze(e=l),typeof r!="function"&&o.pointRadius(r),a):e},a.pointRadius=function(l){return arguments.length?(r=typeof l=="function"?l:(o.pointRadius(+l),+l),a):r},a.digits=function(l){if(!arguments.length)return n;if(l==null)n=null;else{let h=Math.floor(l);if(!(h>=0))throw new RangeError(`invalid digits: ${l}`);n=h}return e===null&&(o=new be(n)),a},a.projection(t).digits(n).context(e)}function Te(t){return function(e){var n=new Mt;for(var r in t)n[r]=t[r];return n.stream=e,n}}function Mt(){}Mt.prototype={constructor:Mt,point:function(t,e){this.stream.point(t,e)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};function Lt(t,e,n){var r=t.clipExtent&&t.clipExtent();return t.scale(150).translate([0,0]),r!=null&&t.clipExtent(null),ae(n,t.stream(ve)),e(ve.result()),r!=null&&t.clipExtent(r),t}function Dt(t,e,n){return Lt(t,function(r){var i=e[1][0]-e[0][0],o=e[1][1]-e[0][1],a=Math.min(i/(r[1][0]-r[0][0]),o/(r[1][1]-r[0][1])),l=+e[0][0]+(i-a*(r[1][0]+r[0][0]))/2,h=+e[0][1]+(o-a*(r[1][1]+r[0][1]))/2;t.scale(150*a).translate([l,h])},n)}function Rn(t,e,n){return Dt(t,[[0,0],e],n)}function Pn(t,e,n){return Lt(t,function(r){var i=+e,o=i/(r[1][0]-r[0][0]),a=(i-o*(r[1][0]+r[0][0]))/2,l=-o*r[0][1];t.scale(150*o).translate([a,l])},n)}function Cn(t,e,n){return Lt(t,function(r){var i=+e,o=i/(r[1][1]-r[0][1]),a=-o*r[0][0],l=(i-o*(r[1][1]+r[0][1]))/2;t.scale(150*o).translate([a,l])},n)}var Mn=16,Mr=D(30*B);function At(t,e){return+e?Dr(t,e):Lr(t)}function Lr(t){return Te({point:function(e,n){e=t(e,n),this.stream.point(e[0],e[1])}})}function Dr(t,e){function n(r,i,o,a,l,h,d,s,c,u,p,f,m,v){var b=d-r,y=s-i,x=b*b+y*y;if(x>4*e&&m--){var E=a+u,w=l+p,k=h+f,L=Y(E*E+w*w+k*k),S=ie(k/=L),C=M(M(k)-1)<P||M(o-c)<P?(o+c)/2:re(w,E),O=t(C,S),_=O[0],V=O[1],F=_-r,A=V-i,g=y*F-b*A;(g*g/x>e||M((b*F+y*A)/x-.5)>.3||a*u+l*p+h*f<Mr)&&(n(r,i,o,a,l,h,_,V,C,E/=L,w/=L,k,m,v),v.point(_,V),n(_,V,C,E,w,k,d,s,c,u,p,f,m,v))}}return function(r){var i,o,a,l,h,d,s,c,u,p,f,m,v={point:b,lineStart:y,lineEnd:E,polygonStart:function(){r.polygonStart(),v.lineStart=w},polygonEnd:function(){r.polygonEnd(),v.lineStart=y}};function b(S,C){S=t(S,C),r.point(S[0],S[1])}function y(){c=NaN,v.point=x,r.lineStart()}function x(S,C){var O=Z([S,C]),_=t(S,C);n(c,u,s,p,f,m,c=_[0],u=_[1],s=S,p=O[0],f=O[1],m=O[2],Mn,r),r.point(c,u)}function E(){v.point=b,r.lineEnd()}function w(){y(),v.point=k,v.lineEnd=L}function k(S,C){x(i=S,C),o=c,a=u,l=p,h=f,d=m,v.point=x}function L(){n(c,u,s,p,f,m,o,a,i,l,h,d,Mn,r),v.lineEnd=E,E()}return v}}var Ar=Te({point:function(t,e){this.stream.point(t*B,e*B)}});function Tr(t){return Te({point:function(e,n){var r=t(e,n);return this.stream.point(r[0],r[1])}})}function Br(t,e,n,r,i){function o(a,l){return a*=r,l*=i,[e+t*a,n-t*l]}return o.invert=function(a,l){return[(a-e)/t*r,(n-l)/t*i]},o}function Ln(t,e,n,r,i,o){if(!o)return Br(t,e,n,r,i);var a=D(o),l=T(o),h=a*t,d=l*t,s=a/t,c=l/t,u=(l*n-a*e)/t,p=(l*e+a*n)/t;function f(m,v){return m*=r,v*=i,[h*m-d*v+e,n-d*m-h*v]}return f.invert=function(m,v){return[r*(s*m-c*v+u),i*(p-c*m-s*v)]},f}function Tt(t){return Or(function(){return t})()}function Or(t){var e,n=150,r=480,i=250,o=0,a=0,l=0,h=0,d=0,s,c=0,u=1,p=1,f=null,m=mt,v=null,b,y,x,E=Pe,w=.5,k,L,S,C,O;function _(g){return S(g[0]*B,g[1]*B)}function V(g){return g=S.invert(g[0],g[1]),g&&[g[0]*U,g[1]*U]}_.stream=function(g){return C&&O===g?C:C=Ar(Tr(s)(m(k(E(O=g)))))},_.preclip=function(g){return arguments.length?(m=g,f=void 0,A()):m},_.postclip=function(g){return arguments.length?(E=g,v=b=y=x=null,A()):E},_.clipAngle=function(g){return arguments.length?(m=+g?dn(f=g*B):(f=null,mt),A()):f*U},_.clipExtent=function(g){return arguments.length?(E=g==null?(v=b=y=x=null,Pe):gt(v=+g[0][0],b=+g[0][1],y=+g[1][0],x=+g[1][1]),A()):v==null?null:[[v,b],[y,x]]},_.scale=function(g){return arguments.length?(n=+g,F()):n},_.translate=function(g){return arguments.length?(r=+g[0],i=+g[1],F()):[r,i]},_.center=function(g){return arguments.length?(o=g[0]%360*B,a=g[1]%360*B,F()):[o*U,a*U]},_.rotate=function(g){return arguments.length?(l=g[0]%360*B,h=g[1]%360*B,d=g.length>2?g[2]%360*B:0,F()):[l*U,h*U,d*U]},_.angle=function(g){return arguments.length?(c=g%360*B,F()):c*U},_.reflectX=function(g){return arguments.length?(u=g?-1:1,F()):u<0},_.reflectY=function(g){return arguments.length?(p=g?-1:1,F()):p<0},_.precision=function(g){return arguments.length?(k=At(L,w=g*g),A()):Y(w)},_.fitExtent=function(g,R){return Dt(_,g,R)},_.fitSize=function(g,R){return Rn(_,g,R)},_.fitWidth=function(g,R){return Pn(_,g,R)},_.fitHeight=function(g,R){return Cn(_,g,R)};function F(){var g=Ln(n,0,0,u,p,c).apply(null,e(o,a)),R=Ln(n,r-g[0],i-g[1],u,p,c);return s=pt(l,h,d),L=Ie(e,R),S=Ie(s,L),k=At(L,w),A()}function A(){return C=O=null,_}return function(){return e=t.apply(this,arguments),_.invert=e.invert&&V,F()}}function nt(t,e){return[t,Kt(Xt(($+e)/2))]}nt.invert=function(t,e){return[t,2*je(Wt(e))-$]};function Bt(){return Fr(nt).scale(961/q)}function Fr(t){var e=Tt(t),n=e.center,r=e.scale,i=e.translate,o=e.clipExtent,a=null,l,h,d;e.scale=function(c){return arguments.length?(r(c),s()):r()},e.translate=function(c){return arguments.length?(i(c),s()):i()},e.center=function(c){return arguments.length?(n(c),s()):n()},e.clipExtent=function(c){return arguments.length?(c==null?a=l=h=d=null:(a=+c[0][0],l=+c[0][1],h=+c[1][0],d=+c[1][1]),s()):a==null?null:[[a,l],[h,d]]};function s(){var c=I*r(),u=e(on(e.rotate()).invert([0,0]));return o(a==null?[[u[0]-c,u[1]-c],[u[0]+c,u[1]+c]]:t===nt?[[Math.max(u[0]-c,a),l],[Math.min(u[0]+c,h),d]]:[[a,Math.max(u[1]-c,l)],[h,Math.min(u[1]+c,d)]])}return s()}function Ot(t){return t}function rt(t){if(t==null)return Ot;var e,n,r=t.scale[0],i=t.scale[1],o=t.translate[0],a=t.translate[1];return function(l,h){h||(e=n=0);var d=2,s=l.length,c=new Array(s);for(c[0]=(e+=l[0])*r+o,c[1]=(n+=l[1])*i+a;d<s;)c[d]=l[d],++d;return c}}function Dn(t,e){for(var n,r=t.length,i=r-e;i<--r;)n=t[i],t[i++]=t[r],t[r]=n}function Ft(t,e){return typeof e=="string"&&(e=t.objects[e]),e.type==="GeometryCollection"?{type:"FeatureCollection",features:e.geometries.map(function(n){return An(t,n)})}:An(t,e)}function An(t,e){var n=e.id,r=e.bbox,i=e.properties==null?{}:e.properties,o=Gt(t,e);return n==null&&r==null?{type:"Feature",properties:i,geometry:o}:r==null?{type:"Feature",id:n,properties:i,geometry:o}:{type:"Feature",id:n,bbox:r,properties:i,geometry:o}}function Gt(t,e){var n=rt(t.transform),r=t.arcs;function i(s,c){c.length&&c.pop();for(var u=r[s<0?~s:s],p=0,f=u.length;p<f;++p)c.push(n(u[p],p));s<0&&Dn(c,f)}function o(s){return n(s)}function a(s){for(var c=[],u=0,p=s.length;u<p;++u)i(s[u],c);return c.length<2&&c.push(c[0]),c}function l(s){for(var c=a(s);c.length<4;)c.push(c[0]);return c}function h(s){return s.map(l)}function d(s){var c=s.type,u;switch(c){case"GeometryCollection":return{type:c,geometries:s.geometries.map(d)};case"Point":u=o(s.coordinates);break;case"MultiPoint":u=s.coordinates.map(o);break;case"LineString":u=a(s.arcs);break;case"MultiLineString":u=s.arcs.map(a);break;case"Polygon":u=h(s.arcs);break;case"MultiPolygon":u=s.arcs.map(h);break;default:return null}return{type:c,coordinates:u}}return d(e)}function oe(t){if("type"in t&&t.type==="FeatureCollection")return t;let e=t,n=typeof e.object=="string"?e.topology.objects[e.object]:e.object;if(!n)throw new Error("The named TopoJSON object does not exist in this topology.");let r=Ft(e.topology,n);return r.type==="FeatureCollection"?r:{type:"FeatureCollection",features:[r]}}function Tn(t){return t.reduce((e,n)=>e+(n??0),0)}function it(t,e,n,r){if(t===null||r<=0)return null;if(r===1||n===e)return r-1;let i=Math.round((t-e)/(n-e)*(r-1));return Math.min(Math.max(i,0),r-1)}function Bn(t,e,n,r){let i=t.length;return t.map((o,a)=>{let l=e.filter(h=>it(h,n,r,i)===a);return{index:a,color:o,from:l.length?Math.min(...l):null,to:l.length?Math.max(...l):null,matches:l.length}})}function On(t,e){if(t.matches===0||t.from===null||t.to===null)return"No regions in this band";let n=t.from===t.to?e(t.from):`${e(t.from)} to ${e(t.to)}`;return`Highlight ${t.matches} ${t.matches===1?"region":"regions"}, ${n}`}function Fn(t,e,n,r=4){let i=0;t.right>e.right-r&&(i=e.right-r-t.right),t.left+i<e.left+r&&(i=e.left+r-t.left);let o=t.top<e.top+r?"below":"above";return{dx:i,side:o}}var $r=["puducherry"];function jn(t){let e=t.toLowerCase();return $r.some(n=>e.includes(n))}function ot(t){let e=1/0,n=1/0,r=-1/0,i=-1/0;for(let[o,a]of t)o<e&&(e=o),o>r&&(r=o),a<n&&(n=a),a>i&&(i=a);return[e,n,r,i]}function at(t){let e=0;for(let n of t){if(n.length===0)continue;let[r,i,o,a]=ot(n),l=Math.max(o-r,a-i);l>e&&(e=l)}return e}function Gn(t){let e=0;for(let n=0;n<t.length;n++){let[r,i]=t[n],[o,a]=t[(n+1)%t.length];e+=r*a-o*i}return e/2}function $n(t,e){let n=null,r=0;for(let h of t){if(h.length<3)continue;let d=Math.abs(Gn(h));d>r&&(r=d,n=h)}if(!n||r===0)return e;let i=Gn(n),o=0,a=0;for(let h=0;h<n.length;h++){let[d,s]=n[h],[c,u]=n[(h+1)%n.length],p=d*u-c*s;o+=(d+c)*p,a+=(s+u)*p}let l=[o/(6*i),a/(6*i)];return Number.isFinite(l[0])&&Number.isFinite(l[1])?l:e}function qr(t,e){let[n,r]=t,[i,o,a,l]=e,h=Math.max(i-n,0)+Math.max(n-a,0),d=Math.max(o-r,0)+Math.max(r-l,0);return Math.hypot(h,d)}function qn(t,e){let n=1/0;for(let r of e){let i=qr(t,r);i<n&&(n=i)}return n}var zr=[0,Math.PI/6,-Math.PI/6,Math.PI/3,-Math.PI/3,Math.PI/2,-Math.PI/2,2*Math.PI/3,-(2*Math.PI)/3,5*Math.PI/6,-(5*Math.PI)/6,Math.PI];function zn(t){let{anchor:e,clearance:n,halfSize:r,viewBox:i,centre:o,isBlocked:a}=t,l=e[0]-o[0],h=e[1]-o[1],d=l===0&&h===0?0:Math.atan2(h,l);for(let s of zr){let c=d+s,u=[Nn(e[0]+Math.cos(c)*n,r[0],i[0]-r[0]),Nn(e[1]+Math.sin(c)*n,r[1],i[1]-r[1])];if(!a(u))return u}return null}function Nn(t,e,n){return Math.min(Math.max(t,e),n)}function Hn(t,e,n=8){let r=()=>t.map(o=>[...o]);if(e<=0)return r();let i=at(t);return i<=0||i>=e?r():t.map(o=>{let[a,l,h,d]=ot(o),s=Math.max(h-a,d-l),c=s<=0?1:Math.min(e/s,n),u=(a+h)/2,p=(l+d)/2;return o.map(([f,m])=>[u+(f-u)*c,p+(m-p)*c])})}function Hr(t){let e=[...t].sort((h,d)=>h[0]-d[0]||h[1]-d[1]),n=[];for(let h of e){let d=n.at(-1);(!d||d[0]!==h[0]||d[1]!==h[1])&&n.push(h)}if(n.length<3)return n.map(h=>[...h]);let r=(h,d,s)=>(d[0]-h[0])*(s[1]-h[1])-(d[1]-h[1])*(s[0]-h[0]),i=h=>{let d=[];for(let s of h){for(;d.length>=2&&r(d[d.length-2],d[d.length-1],s)<=0;)d.pop();d.push(s)}return d},o=i(n),a=i([...n].reverse()),l=[...o.slice(0,-1),...a.slice(0,-1)];return l.length>=3?l:n.map(h=>[...h])}function Un(t,e){if(t.length<2||e<=0)return null;let n=at(t);if(n<=0||n>=e)return null;let r=Hr(t.flat());return r.length>=3?r:null}function Nt(t){let e="";for(let n of t)if(n.length!==0){e+=`M${n[0][0]},${n[0][1]}`;for(let r=1;r<n.length;r++)e+=`L${n[r][0]},${n[r][1]}`;e+="Z"}return e}var Ur="http://www.w3.org/2000/svg",H={width:960,height:640,padding:28},Be=["#d9f1ed","#b9e3dd","#8fd1c8","#5bb9ae","#2f9c90","#147b71","#075b55"],st=new Intl.NumberFormat("en-IN").format,Vn=12,jt=22,Vr=14,lt=7;function Wn(t,e){let n=t.geometry;if(!n)return[];let r=n.type==="Polygon"?[n.coordinates]:n.type==="MultiPolygon"?n.coordinates:[],i=[];for(let o of r)for(let a of o){let l=[];for(let h of a){let d=e(h);d&&Number.isFinite(d[0])&&Number.isFinite(d[1])&&l.push([d[0],d[1]])}l.length>0&&i.push(l)}return i}var Wr=0;function Kn(t,e,n,r,i){if(typeof i=="function"){let a={min:n,max:r,feature:e.feature,id:e.id};return i(t,a)}let o=it(t,n,r,i.length);return o===null?"var(--india-map-empty)":i[o]??"var(--india-map-empty)"}function Yn(t){return typeof t.colorScale=="function"?Be:t.colorScale??Be}function Xn(t){return Bt().fitExtent([[H.padding,H.padding],[H.width-H.padding,H.height-H.padding]],t)}function Jn(t,e,n=0){let r=oe(t.geometry),i=tt(e);return r.features.map(o=>{let a=i.centroid(o),l=i.bounds(o),h=[(l[0][0]+l[1][0])/2,(l[0][1]+l[1][1])/2],d={id:t.getId(o),label:t.getLabel(o),value:t.getValue(o),meta:t.getMeta?.(o),feature:o},s=n>0&&!jn(d.id),c=s?Hn(Wn(o,e),n):Wn(o,e),u=Un(c,jt);return{...d,path:s?Nt(c):i(o)??"",hitPath:u?Nt([u]):null,centroid:c.length>0?$n(c,a.every(Number.isFinite)?a:h):a.every(Number.isFinite)?a:h,partBounds:c.map(ot),extent:at(c)}})}function Zn(t,e){let n=tt(e);return oe(t.geometry).features.map(r=>({id:t.getId(r),label:t.getLabel(r),description:t.getDescription(r),path:n(r)??""}))}function Kr(t){let e=t%100;return e>=11&&e<=13?`${t}th`:`${t}${["th","st","nd","rd"][t%10]??"th"}`}function Yr(t,e){let n=document.createDocumentFragment(),r=document.createElement("strong");r.textContent=t.label;let i=document.createElement("b");if(i.textContent=t.value===null?"No data":e(t.value),n.append(r,i),t.share!==null){let o=document.createElement("span");o.className="india-choropleth__tooltip-bar",o.setAttribute("aria-hidden","true");let a=document.createElement("span");a.style.width=`${Math.max(t.share,1.5)}%`,o.append(a);let l=document.createElement("small"),h=[`${t.share.toFixed(1)}% of total`];t.rank!==null&&h.push(`${Kr(t.rank)} of ${t.rankedCount}`),l.textContent=h.join(" \xB7 "),n.append(o,l)}return n}function N(t,e){let n=document.createElement(t);for(let[r,i]of Object.entries(e??{}))n.setAttribute(r,i);return n}function G(t,e){let n=document.createElementNS(Ur,t);for(let[r,i]of Object.entries(e??{}))n.setAttribute(r,i);return n}function Xr(t,e){typeof e=="string"?t.textContent=e:t.appendChild(e)}var de=class{containerEl;options;instanceId=`india-choropleth-${++Wr}`;tooltipId=`${this.instanceId}-tooltip`;hatchId=`${this.instanceId}-hatch`;activeDrillDownId;activeSelectedId;inspectedId=null;loadedDistricts=null;loadedDistrictReferenceOverlay=null;loadingState=null;loadError=null;districtGeneration=0;overlayGeneration=0;restoreFocusId=null;destroyed=!1;attemptedDistrictLoadForId=null;attemptedOverlayLoadForId=null;pathRefs=new Map;derived;rootEl;toolbarEl;canvasEl;legendEl=null;swatchEls=[];bucketEls=[];activeBucket=null;bandsKey=null;insightsEl=null;tooltipAnchorEl=null;tooltipContentEl=null;svgRootEl=null;selectionGroupEl=null;selectionPathEls=[];constructor(e,n){let r=typeof e=="string"?document.querySelector(e):e;if(!r)throw new Error(`IndiaChoropleth: container ${typeof e=="string"?`"${e}"`:""} was not found.`);this.containerEl=r,this.options=n,this.activeDrillDownId=n.drillDownId!==void 0?n.drillDownId:n.defaultDrillDownId??null,this.activeSelectedId=n.selectedId!==void 0?n.selectedId:n.defaultSelectedId??null,this.buildShell(),this.renderStructure()}update(e){"loadDistricts"in e&&e.loadDistricts!==this.options.loadDistricts&&(this.attemptedDistrictLoadForId=null),"loadDistrictReferenceOverlay"in e&&e.loadDistrictReferenceOverlay!==this.options.loadDistrictReferenceOverlay&&(this.attemptedOverlayLoadForId=null),this.options={...this.options,...e},"drillDownId"in e&&e.drillDownId!==void 0&&(this.activeDrillDownId=e.drillDownId),"selectedId"in e&&e.selectedId!==void 0&&(this.activeSelectedId=e.selectedId),this.renderStructure()}select(e){let n=this.derived.regions.find(r=>r.id===e)??null;this.setActiveSelectedId(n?.id??null),n&&this.options.onSelectedChange?.(n,this.derived.level),this.applyInteractionState()}drillDown(e){if(e===null){this.goBack();return}let n=this.derived.stateRegions.find(r=>r.id===e);n&&(this.setActiveDrillDownId(e),this.options.onDrillDownChange?.(e,n),this.renderStructure())}getSelected(){return this.derived.selected}getInspected(){return this.derived.inspected}destroy(){this.destroyed=!0,this.districtGeneration+=1,this.overlayGeneration+=1,this.pathRefs.clear(),this.containerEl.textContent=""}setActiveDrillDownId(e){this.options.drillDownId===void 0&&(this.activeDrillDownId=e)}setActiveSelectedId(e){this.options.selectedId===void 0&&(this.activeSelectedId=e)}buildShell(){this.rootEl=N("section"),this.toolbarEl=N("div",{class:"india-choropleth__toolbar"}),this.canvasEl=N("div",{class:"india-choropleth__canvas"}),this.canvasEl.addEventListener("mouseleave",()=>{this.options.interactive!==!1&&this.inspect(null)}),this.rootEl.append(this.toolbarEl,this.canvasEl),this.containerEl.textContent="",this.containerEl.appendChild(this.rootEl)}recompute(){let e=this.options,n=oe(e.states.geometry),r=e.referenceOverlay?oe(e.referenceOverlay.geometry):null,i=Xn({type:"FeatureCollection",features:[...n.features,...r?.features??[]]}),o=Jn(e.states,i,e.minPartExtent??0),a=e.referenceOverlay?Zn(e.referenceOverlay,i):[],l=o.find(S=>S.id===this.activeDrillDownId)??null,d=!!(l&&this.activeDrillDownId)?"district":"state",s=this.loadedDistricts?.stateId===this.activeDrillDownId?this.loadedDistricts.layer:null,c=this.loadedDistrictReferenceOverlay?.stateId===this.activeDrillDownId?this.loadedDistrictReferenceOverlay.overlay:null,u=s?oe(s.geometry):null,p=c?oe(c.geometry):null,f=u?Xn({type:"FeatureCollection",features:[...u.features,...p?.features??[]]}):null,m=d==="district"&&s&&f?Jn(s,f,e.minDistrictPartExtent??e.minPartExtent??0):d==="state"?o:[],v=d==="district"&&c&&f?Zn(c,f):[],b=m.find(S=>S.id===this.activeSelectedId)??null,y=m.find(S=>S.id===this.inspectedId)??null;this.inspectedId&&!y&&(this.inspectedId=null);let x=m.map(S=>S.value).filter(S=>S!==null),E=Tn(x),w=x.length?Math.min(...x):0,k=x.length?Math.max(...x):0;this.derived={stateRegions:o,referenceRegions:a,drilledState:l,level:d,regions:m,visibleReferenceRegions:d==="state"?a:v,selected:b,inspected:y,total:E,min:w,max:k,canDrill:!!(e.loadDistricts&&d==="state"),mergedReferenceIds:new Set(e.referenceOverlayMergeIds??[]),buckets:Bn(Yn(e),m.map(S=>S.value),w,k)};let L=[d,this.activeDrillDownId??"",typeof e.colorScale=="function"?"function":(e.colorScale??Be).join(",")].join("|");L!==this.bandsKey&&(this.bandsKey=L,this.activeBucket=null),this.activeBucket!==null&&this.activeBucket>=this.derived.buckets.length&&(this.activeBucket=null)}loadDistrictsFor(e){let n=this.options;if(!n.loadDistricts){this.loadedDistricts=null,this.loadingState=null,this.loadError=null;return}let r=this.derived.stateRegions.find(o=>o.id===e);if(!r)return;let i=++this.districtGeneration;this.loadingState=e,this.loadError=null,this.loadedDistricts=null,n.loadDistricts(e,r).then(o=>{this.destroyed||i!==this.districtGeneration||(this.loadedDistricts={stateId:e,layer:o},this.loadingState=null,this.renderStructure())}).catch(o=>{this.destroyed||i!==this.districtGeneration||(this.loadError=o instanceof Error?o:new Error("Unable to load districts."),this.loadingState=null,this.renderStructure())})}loadDistrictReferenceOverlayFor(e){let n=this.options;if(!n.loadDistrictReferenceOverlay){this.loadedDistrictReferenceOverlay=null;return}let r=this.derived.stateRegions.find(o=>o.id===e);if(!r)return;let i=++this.overlayGeneration;this.loadedDistrictReferenceOverlay=null,n.loadDistrictReferenceOverlay(e,r).then(o=>{this.destroyed||i!==this.overlayGeneration||(this.loadedDistrictReferenceOverlay={stateId:e,overlay:o},this.renderStructure())}).catch(()=>{this.destroyed||i!==this.overlayGeneration||(this.loadedDistrictReferenceOverlay={stateId:e,overlay:null},this.renderStructure())})}inspect(e){let n=e?.id??null;n===null&&this.inspectedId===null||(this.inspectedId=n,this.derived.inspected=e,this.options.onInspect?.(e??null,this.derived.level),this.applyInteractionState())}toViewBox(e){let n=this.canvasEl.querySelector("svg");if(!n)return null;let r=n.getBoundingClientRect();if(r.width===0||r.height===0)return null;let i=Math.min(r.width/H.width,r.height/H.height),o=(r.width-H.width*i)/2,a=(r.height-H.height*i)/2;return[(e.clientX-r.left-o)/i,(e.clientY-r.top-a)/i]}smallRegionNear(e){let n=null,r=1/0;for(let i of this.derived.regions){if(i.extent<=0||i.extent>=jt)continue;let o=qn(e,i.partBounds);o<=Vr&&o<r&&(r=o,n=i)}return n}activate(e){let n=this.options;n.onRegionClick?.(e,this.derived.level),this.setActiveSelectedId(e.id),n.onSelectedChange?.(e,this.derived.level),this.derived.level==="state"&&n.loadDistricts?(this.setActiveSelectedId(null),this.setActiveDrillDownId(e.id),n.onDrillDownChange?.(e.id,e),this.renderStructure()):this.applyInteractionState()}goBack(){let e=this.derived.drilledState??void 0;this.setActiveDrillDownId(null),this.setActiveSelectedId(e?.id??null),this.inspectedId=e?.id??null,this.restoreFocusId=e?.id??null,this.options.onDrillDownChange?.(null,e),this.renderStructure()}renderStructure(){if(this.destroyed)return;this.recompute();let e=this.options;this.activeDrillDownId&&e.loadDistricts&&this.attemptedDistrictLoadForId!==this.activeDrillDownId&&(this.attemptedDistrictLoadForId=this.activeDrillDownId,this.loadDistrictsFor(this.activeDrillDownId)),this.activeDrillDownId||(this.loadedDistricts=null,this.loadingState=null,this.loadError=null,this.attemptedDistrictLoadForId=null),this.activeDrillDownId&&e.loadDistrictReferenceOverlay&&this.attemptedOverlayLoadForId!==this.activeDrillDownId&&(this.attemptedOverlayLoadForId=this.activeDrillDownId,this.loadDistrictReferenceOverlayFor(this.activeDrillDownId)),(!this.activeDrillDownId||!e.loadDistrictReferenceOverlay)&&(this.loadedDistrictReferenceOverlay=null,this.attemptedOverlayLoadForId=null);let n=e.interactive!==!1;if(this.rootEl.className=["india-choropleth",!n&&"india-choropleth--static",e.className].filter(Boolean).join(" "),this.loadingState?this.rootEl.setAttribute("aria-busy","true"):this.rootEl.removeAttribute("aria-busy"),this.renderToolbar(),this.renderCanvas(),this.renderLegend(),this.restoreFocusId&&this.derived.level==="state"){let r=this.restoreFocusId;this.restoreFocusId=null,this.pathRefs.get(r)?.focus()}}renderToolbar(){let e=this.options;if(this.toolbarEl.textContent="",e.showBreadcrumb===!1)return;let n=N("nav",{class:"india-choropleth__breadcrumb","aria-label":"Map hierarchy"});if(this.derived.drilledState){let r=N("button",{class:"india-choropleth__back",type:"button"});r.textContent="All states",r.addEventListener("click",()=>this.goBack());let i=N("span",{"aria-hidden":"true"});i.textContent="/";let o=N("span",{"aria-current":"page"});o.textContent=this.derived.drilledState.label,n.append(r,i,o)}else{let r=N("span");r.textContent="All states",n.append(r)}this.toolbarEl.append(n)}renderCanvas(){let e=this.options,n=e.interactive!==!1;this.canvasEl.textContent="",this.pathRefs.clear(),this.bucketEls=[],this.svgRootEl=null,this.tooltipAnchorEl=null,this.tooltipContentEl=null,this.selectionGroupEl=null,this.selectionPathEls=[];let i=!!(this.derived.drilledState&&this.activeDrillDownId)&&(!this.loadedDistricts||this.loadedDistricts.stateId!==this.activeDrillDownId||this.loadError),o=!i&&this.derived.regions.length===0;if(i||o){let m=N("div",{class:"india-choropleth__status",role:i&&this.loadError?"alert":"status"});m.textContent=o?"No district data is available for this state.":this.loadError?this.loadError.message:this.loadingState?"Loading districts\u2026":"District data is unavailable for this state.",this.canvasEl.append(m),this.applyInteractionState();return}let a=G("svg",{class:"india-choropleth__svg",viewBox:`0 0 ${H.width} ${H.height}`,role:"group","aria-label":e.ariaLabel??"Interactive choropleth map"});if(this.svgRootEl=a,n&&(a.addEventListener("keydown",m=>{m.key==="Escape"&&(m.preventDefault(),this.inspect(null))}),a.addEventListener("click",m=>{if(m.target!==a)return;let v=this.toViewBox(m),b=v?this.smallRegionNear(v):null;if(b){this.activate(b);return}this.options.onBackgroundClick?.(),this.activeSelectedId!==null&&(this.setActiveSelectedId(null),this.options.onSelectedChange?.(null,this.derived.level),this.applyInteractionState())})),this.derived.visibleReferenceRegions.length>0){let m=G("defs"),v=G("pattern",{id:this.hatchId,width:"8",height:"8",patternUnits:"userSpaceOnUse",patternTransform:"rotate(45)"});v.append(G("rect",{width:"8",height:"8",fill:"var(--india-map-reference-bg)"}),G("line",{x1:"0",y1:"0",x2:"0",y2:"8",stroke:"var(--india-map-reference-hatch)","stroke-width":"2"})),m.append(v),a.append(m);let b=G("g",{class:"india-choropleth__reference-fill",role:"group","aria-label":"Non-statistical reference context."});for(let y of this.derived.visibleReferenceRegions)b.append(G("path",{d:y.path,fill:e.referenceOverlayFill==="solid"?"var(--india-map-reference-bg)":`url(#${this.hatchId})`,"aria-label":`${y.label}.${y.description?` ${y.description}`:""}`,role:"img"}));a.append(b)}let l=n?this.derived.regions.filter(m=>m.hitPath):[];if(l.length>0){let m=G("g",{class:"india-choropleth__hit-areas","aria-hidden":"true"});for(let v of l){let b=G("path",{d:v.hitPath,fill:"none","pointer-events":"all",tabindex:"-1"});b.addEventListener("mouseenter",()=>this.inspect(v)),b.addEventListener("mouseleave",()=>this.inspect(null)),b.addEventListener("click",()=>this.activate(v)),m.append(b)}a.append(m)}let h=m=>it(m.value,this.derived.min,this.derived.max,Yn(e).length);for(let m of this.derived.regions){let v=this.derived.canDrill?"Activate to view districts.":"Activate to select.",b=m.value===null?"No data":(e.formatValue??st)(m.value),y=G("path",{class:"india-choropleth__region",d:m.path,fill:Kn(m.value,m,this.derived.min,this.derived.max,e.colorScale??Be),tabindex:n?"0":"-1","aria-label":`${m.label}, ${b}. ${v}`});n&&y.setAttribute("role","button"),this.derived.mergedReferenceIds.has(m.id)&&y.classList.add("india-choropleth__region--reference-merged"),n&&(y.setAttribute("aria-pressed",m.id===this.derived.selected?.id?"true":"false"),y.addEventListener("mouseenter",()=>this.inspect(m)),y.addEventListener("mouseleave",()=>this.inspect(null)),y.addEventListener("focus",()=>this.inspect(m)),y.addEventListener("blur",()=>this.inspect(null)),y.addEventListener("click",()=>this.activate(m)),y.addEventListener("keydown",x=>{(x.key==="Enter"||x.key===" ")&&(x.preventDefault(),this.activate(m))})),a.append(y),this.pathRefs.set(m.id,y),this.bucketEls.push({el:y,bucket:h(m)})}let d=this.derived.regions.filter(m=>m.extent>0&&m.extent<lt);if(d.length>0){let m=G("g",{class:"india-choropleth__small-markers","aria-hidden":"true"});for(let v of d){let b=G("circle",{cx:String(v.centroid[0]),cy:String(v.centroid[1]),r:String(lt/2),fill:Kn(v.value,v,this.derived.min,this.derived.max,e.colorScale??Be)});n&&(b.addEventListener("mouseenter",()=>this.inspect(v)),b.addEventListener("mouseleave",()=>this.inspect(null)),b.addEventListener("click",()=>this.activate(v))),this.bucketEls.push({el:b,bucket:h(v)}),m.append(b)}a.append(m)}if(e.showRegionValues){let m=G("g",{class:`india-choropleth__region-values${this.derived.level==="district"?" india-choropleth__region-values--district":""}`,"aria-hidden":"true"}),v=G("g",{class:"india-choropleth__value-leaders","aria-hidden":"true"});for(let b of this.derived.regions){if(!b.centroid.every(Number.isFinite))continue;let y=b.value===null?"\u2014":(e.formatValue??st)(b.value),x=this.placeRegionValue(b,y);if(!x)continue;let E=G("text",{x:String(x.at[0]),y:String(x.at[1]),"text-anchor":"middle","dominant-baseline":"central"});if(E.textContent=y,m.append(E),this.bucketEls.push({el:E,bucket:h(b)}),x.leader){let w=G("line",{x1:String(x.leader[0][0]),y1:String(x.leader[0][1]),x2:String(x.leader[1][0]),y2:String(x.leader[1][1])});this.bucketEls.push({el:w,bucket:h(b)}),v.append(w)}}a.append(v,m)}if(this.derived.visibleReferenceRegions.length>0){let m=G("g",{class:"india-choropleth__reference-outline","aria-hidden":"true"});for(let v of this.derived.visibleReferenceRegions)m.append(G("path",{d:v.path,fill:"none"}));a.append(m)}let s=G("g",{class:"india-choropleth__selection","aria-hidden":"true"}),c=G("path",{class:"india-choropleth__selection-halo",fill:"none"}),u=G("path",{class:"india-choropleth__selection-ring",fill:"none"});s.append(c,u),a.append(s),this.selectionGroupEl=s,this.selectionPathEls=[c,u],this.canvasEl.append(a);let p=N("div",{class:"india-choropleth__tooltip-anchor"});p.style.display="none";let f=N("div",{id:this.tooltipId,class:"india-choropleth__tooltip"});p.append(f),this.canvasEl.append(p),this.tooltipAnchorEl=p,this.tooltipContentEl=f,this.applyInteractionState()}placeRegionValue(e,n){let r=e.extent>0&&e.extent<jt,i=Math.max(n.length*3.1,3),o=5.5,a=e.partBounds.some(([f,m,v,b])=>v-f>=i*2&&b-m>=o*2);if(!r&&a)return{at:e.centroid};let l=r?zn({anchor:e.centroid,clearance:Math.max(e.extent,lt)/2+4+i,halfSize:[i,o],viewBox:[H.width,H.height],centre:[H.width/2,H.height/2],isBlocked:f=>this.coversAnotherRegion(e,f,i,o)}):null;if(!l)return a?{at:e.centroid}:null;let h=Math.max(e.extent,lt)/2+1,d=l[0]-e.centroid[0],s=l[1]-e.centroid[1],c=Math.hypot(d,s);if(c<=h+i)return{at:l};let u=[e.centroid[0]+d/c*h,e.centroid[1]+s/c*h],p=[l[0]-d/c*(i+1.5),l[1]-s/c*(i+1.5)];return{at:l,leader:[u,p]}}coversAnotherRegion(e,n,r,i){let o=[n,[n[0]-r,n[1]-i],[n[0]+r,n[1]+i],[n[0]+r,n[1]-i],[n[0]-r,n[1]+i]];for(let a of this.derived.regions)if(a.id!==e.id){for(let l of o)if(a.partBounds.some(([h,d,s,c])=>l[0]>=h&&l[0]<=s&&l[1]>=d&&l[1]<=c))return!0}return!1}renderLegend(){let e=this.options;if(this.legendEl&&(this.legendEl.remove(),this.legendEl=null),e.showLegend===!1)return;let[n,r]=e.legendLabels??["Lower","Higher"],i=N("div",{class:"india-choropleth__legend",role:"group","aria-label":`Color scale: ${n} to ${r} values`}),o=N("span");o.textContent=n;let a=e.interactive!==!1,l=N("div",{class:"india-choropleth__swatches"});a||l.setAttribute("aria-hidden","true"),this.swatchEls=[];for(let d of this.derived.buckets){let s=N(a?"button":"i",{class:"india-choropleth__swatch"});if(s.style.backgroundColor=d.color,a){s.setAttribute("type","button");let c=On(d,e.formatValue??st);s.setAttribute("aria-label",c),s.setAttribute("title",c),d.matches===0&&s.setAttribute("aria-disabled","true"),s.addEventListener("click",()=>{d.matches!==0&&(this.activeBucket=this.activeBucket===d.index?null:d.index,this.applyInteractionState())}),this.swatchEls.push(s)}l.append(s)}let h=N("span");if(h.textContent=r,i.append(o,l,h),this.derived.visibleReferenceRegions.length>0){let d=N("i",{class:`india-choropleth__reference-key${e.referenceOverlayFill==="solid"?" india-choropleth__reference-key--solid":""}`,"aria-hidden":"true"}),s=N("span");s.textContent=e.referenceOverlayLegendLabel??"Reference context \xB7 data unavailable",i.append(d,s)}this.insightsEl?this.rootEl.insertBefore(i,this.insightsEl):this.rootEl.append(i),this.legendEl=i,a&&i.addEventListener("keydown",d=>{d.key==="Escape"&&(d.preventDefault(),this.activeBucket=null,this.applyInteractionState())}),this.applyLegendState()}renderInsights(){let e=this.options;if(this.insightsEl&&(this.insightsEl.remove(),this.insightsEl=null),!e.renderInsights)return;let n=N("aside",{class:"india-choropleth__insights","aria-live":"polite"});e.renderInsights(this.computeInsightContext(),n),this.rootEl.append(n),this.insightsEl=n}applyInteractionState(){if(this.destroyed)return;this.derived.selected=this.derived.regions.find(n=>n.id===this.activeSelectedId)??null,this.derived.inspected=this.derived.regions.find(n=>n.id===this.inspectedId)??null;let e=this.options.interactive!==!1;for(let[n,r]of this.pathRefs){let i=n===this.derived.inspected?.id,o=n===this.derived.selected?.id;r.classList.toggle("india-choropleth__region--inspected",i),r.classList.toggle("india-choropleth__region--selected",o),e&&(r.setAttribute("aria-pressed",o?"true":"false"),i?r.setAttribute("aria-describedby",this.tooltipId):r.removeAttribute("aria-describedby"))}for(let{el:n,bucket:r}of this.bucketEls)n.classList.toggle("india-choropleth__dimmed",this.activeBucket!==null&&r!==this.activeBucket);this.svgRootEl?.classList.toggle("india-choropleth__svg--filtered",this.activeBucket!==null),this.applyLegendState(),this.renderSelectionRing(),this.renderTooltip(),this.renderInsights(),this.options.onInsight?.(this.computeInsightContext())}applyLegendState(){if(this.legendEl)for(let[e,n]of this.swatchEls.entries()){let r=this.activeBucket===e;n.classList.toggle("india-choropleth__swatch--active",r),n.classList.toggle("india-choropleth__swatch--muted",this.activeBucket!==null&&!r),n.setAttribute("aria-pressed",r?"true":"false")}}renderTooltip(){if(!this.tooltipAnchorEl||!this.tooltipContentEl)return;let e=this.derived.inspected;if(!e){this.tooltipAnchorEl.style.display="none";return}let n=this.toTooltipContext(e);this.tooltipAnchorEl.style.display="",this.tooltipAnchorEl.style.left=`${e.centroid[0]/H.width*100}%`,this.tooltipAnchorEl.style.top=`${e.centroid[1]/H.height*100}%`,this.tooltipContentEl.textContent="";let r=this.options.renderTooltip?this.options.renderTooltip(n):Yr(n,this.options.formatValue??st);Xr(this.tooltipContentEl,r),this.positionTooltip()}renderSelectionRing(){let e=this.selectionGroupEl;if(!e)return;let n=this.derived.selected;if(!n){e.style.display="none";return}e.style.display="";for(let r of this.selectionPathEls)r.setAttribute("d",n.path);e.classList.toggle("india-choropleth__selection--lifted",n.id===this.derived.inspected?.id)}positionTooltip(){let e=this.tooltipAnchorEl;if(!e)return;e.style.removeProperty("--india-map-tooltip-dx"),e.style.removeProperty("--india-map-tooltip-dy");let n=e.getBoundingClientRect(),r=this.canvasEl.getBoundingClientRect();if(n.width===0||r.width===0)return;let{dx:i,side:o}=Fn(n,r,Vn);i!==0&&e.style.setProperty("--india-map-tooltip-dx",`${Math.round(i)}px`),o==="below"&&e.style.setProperty("--india-map-tooltip-dy",`${Vn}px`)}toTooltipContext(e){let n=this.derived.regions.filter(i=>i.value!==null),r=e.value===null?null:n.filter(i=>(i.value??0)>(e.value??0)).length+1;return{...e,level:this.derived.level,total:this.derived.total,share:e.value===null||this.derived.total===0?null:e.value/this.derived.total*100,rank:r,rankedCount:n.length}}computeInsightContext(){let e=this.derived.inspected??this.derived.selected;return e?{...this.toTooltipContext(e),selected:e.id===this.derived.selected?.id}:null}};var ct="https://cdn.jsdelivr.net/gh/shashankbudem/bharat-choropleth@v0.1.0/data/generated",Qn="State/UT and district boundaries derived from datta07/INDIAN-SHAPEFILES (MIT).";function er(t){return t.replace(/\/+$/,"")}function tr(t){return`${er(t)}/current-2019-states/states.topo.json`}function Jr(t,e){return`${er(t)}/current-2019-districts/districts/${e}.topo.json`}async function nr(t,e){if(typeof fetch!="function")throw new Error("BharatChoropleth: no global fetch is available, so boundary data cannot be downloaded. Pass `geometry` with data you loaded yourself.");let n=await fetch(t,{signal:e});if(!n.ok)throw new Error(`BharatChoropleth: failed to load boundary data from ${t} (HTTP ${n.status}). Set \`dataBaseUrl\` to your own copy of data/generated, or pass \`geometry\` directly.`);return n.json()}function $t(t,e){if(!t||typeof t!="object")throw new Error("BharatChoropleth: boundary data must be TopoJSON or a GeoJSON FeatureCollection.");let n=t;if(n.type==="FeatureCollection"||"topology"in n&&"object"in n)return t;if(n.type==="Topology"&&n.objects&&typeof n.objects=="object"){let r=n.objects,i=e in r?e:Object.keys(r)[0];if(!i)throw new Error("BharatChoropleth: the TopoJSON topology contains no objects.");return{topology:t,object:i}}throw new Error("BharatChoropleth: boundary data must be TopoJSON or a GeoJSON FeatureCollection.")}async function rr(t,e,n){return typeof t=="string"?$t(await nr(t,n),e):t instanceof Promise?$t(await t,e):t}function ir(t){return typeof t=="object"&&t!==null&&!(t instanceof Promise)}async function or(t,e,n){return $t(await nr(Jr(t,e),n),"districts")}var qt=[{id:"in-cs-01-jammu-and-kashmir",name:"Jammu & Kashmir",slug:"jammu-and-kashmir"},{id:"in-cs-02-himachal-pradesh",name:"Himachal Pradesh",slug:"himachal-pradesh"},{id:"in-cs-03-punjab",name:"Punjab",slug:"punjab"},{id:"in-cs-04-chandigarh",name:"Chandigarh",slug:"chandigarh"},{id:"in-cs-05-uttarakhand",name:"Uttarakhand",slug:"uttarakhand"},{id:"in-cs-06-haryana",name:"Haryana",slug:"haryana"},{id:"in-cs-07-delhi",name:"Delhi",slug:"delhi"},{id:"in-cs-08-rajasthan",name:"Rajasthan",slug:"rajasthan"},{id:"in-cs-09-uttar-pradesh",name:"Uttar Pradesh",slug:"uttar-pradesh"},{id:"in-cs-10-bihar",name:"Bihar",slug:"bihar"},{id:"in-cs-11-sikkim",name:"Sikkim",slug:"sikkim"},{id:"in-cs-12-arunachal-pradesh",name:"Arunachal Pradesh",slug:"arunachal-pradesh"},{id:"in-cs-13-nagaland",name:"Nagaland",slug:"nagaland"},{id:"in-cs-14-manipur",name:"Manipur",slug:"manipur"},{id:"in-cs-15-mizoram",name:"Mizoram",slug:"mizoram"},{id:"in-cs-16-tripura",name:"Tripura",slug:"tripura"},{id:"in-cs-17-meghalaya",name:"Meghalaya",slug:"meghalaya"},{id:"in-cs-18-assam",name:"Assam",slug:"assam"},{id:"in-cs-19-west-bengal",name:"West Bengal",slug:"west-bengal"},{id:"in-cs-20-jharkhand",name:"Jharkhand",slug:"jharkhand"},{id:"in-cs-21-odisha",name:"Odisha",slug:"odisha"},{id:"in-cs-22-chhattisgarh",name:"Chhattisgarh",slug:"chhattisgarh"},{id:"in-cs-23-madhya-pradesh",name:"Madhya Pradesh",slug:"madhya-pradesh"},{id:"in-cs-24-gujarat",name:"Gujarat",slug:"gujarat"},{id:"in-cs-26-dadra-and-nagar-haveli-and-daman-and-diu",name:"Dadra and Nagar Haveli and Daman and Diu",slug:"dadra-and-nagar-haveli-and-daman-and-diu"},{id:"in-cs-27-maharashtra",name:"Maharashtra",slug:"maharashtra"},{id:"in-cs-28-andhra-pradesh",name:"Andhra Pradesh",slug:"andhra-pradesh"},{id:"in-cs-29-karnataka",name:"Karnataka",slug:"karnataka"},{id:"in-cs-30-goa",name:"Goa",slug:"goa"},{id:"in-cs-31-lakshadweep",name:"Lakshadweep",slug:"lakshadweep"},{id:"in-cs-32-kerala",name:"Kerala",slug:"kerala"},{id:"in-cs-33-tamil-nadu",name:"Tamil Nadu",slug:"tamil-nadu"},{id:"in-cs-34-puducherry",name:"Puducherry",slug:"puducherry"},{id:"in-cs-35-andaman-and-nicobar",name:"Andaman & Nicobar",slug:"andaman-and-nicobar"},{id:"in-cs-36-telangana",name:"Telangana",slug:"telangana"},{id:"in-cs-37-ladakh",name:"Ladakh",slug:"ladakh"}],Zr={orissa:"odisha",pondicherry:"puducherry",uttaranchal:"uttarakhand","nct-of-delhi":"delhi","new-delhi":"delhi","delhi-nct":"delhi","jammu-kashmir":"jammu-and-kashmir","j-and-k":"jammu-and-kashmir",jk:"jammu-and-kashmir","andaman-nicobar":"andaman-and-nicobar","andaman-and-nicobar-islands":"andaman-and-nicobar","dadra-and-nagar-haveli":"dadra-and-nagar-haveli-and-daman-and-diu","daman-and-diu":"dadra-and-nagar-haveli-and-daman-and-diu",dnhdd:"dadra-and-nagar-haveli-and-daman-and-diu","nagar-haveli":"dadra-and-nagar-haveli-and-daman-and-diu"};function Fe(t){return t.toLowerCase().replace(/&/g," and ").replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function zt(t){return t.replace(/-/g,"")}var xe=new Map,Oe=new Map;for(let t of qt)for(let e of[t.slug,Fe(t.name),t.id]){xe.has(e)||xe.set(e,t);let n=zt(e);Oe.has(n)||Oe.set(n,t)}for(let[t,e]of Object.entries(Zr)){let n=xe.get(e);if(!n)continue;xe.has(t)||xe.set(t,n);let r=zt(t);Oe.has(r)||Oe.set(r,n)}function ue(t){let e=Fe(t);return xe.get(e)??Oe.get(zt(e))}function ar(t,e){if(!t.includes("_"))return;let n=t.replace(/_([a-z])/g,(r,i)=>i.toUpperCase());return n!==t&&n in e?n:void 0}function lr(t){return typeof t=="object"&&t!==null&&t.nodeType===1}var sr=["#bharat-choropleth","#map"];function Qr(t){if(lr(t))return t;if(typeof t=="string"){let e=document.querySelector(t);if(e)return e;throw new Error(`BharatChoropleth: container "${t}" was not found.`)}for(let e of sr){let n=document.querySelector(e);if(n)return n}throw new Error(`BharatChoropleth: no container given and none of ${sr.join(", ")} exist. Pass an element or selector: new BharatChoropleth("#map").`)}var Ge=class{ready;engineInstance=null;containerEl;options;dataBaseUrl;usingDefaultData;values=new Map;labelByKey=new Map;writtenAs=new Map;statesAccessor;abortController;getId;getLabel;loadingEl=null;destroyed=!1;_fontColor;_borderColor;_borderWidth;_selectionWidth;_colorScale;constructor(e,n={}){let i=typeof e=="object"&&e!==null&&!lr(e)?{...e}:{...n,container:e??n.container};this.options=i,this.containerEl=Qr(i.container),this.dataBaseUrl=i.dataBaseUrl??ct,this.usingDefaultData=i.geometry===void 0,this.getId=i.getId??(o=>String(o.properties?.id??o.properties?.name)),this.getLabel=i.getLabel??(o=>String(o.properties?.name??o.properties?.id));for(let[o,a]of Object.entries(i.values??{})){let l=this.keyFor(o);this.values.set(l,a),this.writtenAs.set(l,o)}return this._colorScale=i.colorScale,this._fontColor=i.fontColor,this._borderColor=i.borderColor,this._borderWidth=i.borderWidth,this._selectionWidth=i.selectionWidth,this.statesAccessor=new Proxy({},{get:(o,a)=>typeof a=="string"?this.getValue(a):void 0,has:(o,a)=>typeof a=="string"&&this.values.has(this.keyFor(a)),ownKeys:()=>[...this.labelByKey.values()],getOwnPropertyDescriptor:(o,a)=>typeof a=="string"&&this.values.has(this.keyFor(a))?{enumerable:!0,configurable:!0,value:this.getValue(a)}:void 0,set:(o,a,l)=>typeof a!="string"?!1:(this.setValue(a,l),!0)}),ir(i.geometry)?(this.abortController=null,this.ready=Promise.resolve(this),this.mount(i.geometry)):(this.abortController=typeof AbortController=="function"?new AbortController:null,this.showLoading(),this.ready=rr(i.geometry??tr(this.dataBaseUrl),"states",this.abortController?.signal).then(o=>this.destroyed?this.proxied??this:(this.mount(o),this.proxied??this)).catch(o=>{if(this.destroyed||o.name==="AbortError")return this.proxied??this;throw this.showError(o),o}),this.ready.catch(()=>{})),this.proxied=new Proxy(this,{get:(o,a,l)=>{if(typeof a=="string"&&!(a in o)){let h=ar(a,o);return h?Reflect.get(o,h,l):this.getValue(a)}return Reflect.get(o,a,l)},set:(o,a,l,h)=>{if(typeof a=="string"&&!(a in o)){let d=ar(a,o);return d?Reflect.set(o,d,l,h):(this.setValue(a,l),!0)}return Reflect.set(o,a,l,h)}}),this.proxied}proxied;keyFor(e){return ue(e)?.id??Fe(e)}keyForFeature(e){let n=this.getId(e);return ue(n)?.id??ue(this.getLabel(e))?.id??Fe(this.getLabel(e))}getValue(e){return this.values.get(this.keyFor(e))??null}setValue(e,n){let r=this.keyFor(e);this.values.set(r,n),this.writtenAs.has(r)||this.writtenAs.set(r,e),this.engineInstance&&(this.labelByKey.has(r)?this.engineInstance.update({}):this.warnUnknown(e))}warnUnknown(e){console.warn(`BharatChoropleth: "${e}" is not a recognized state/UT \u2014 its value is ignored.`)}mount(e){this.clearPlaceholder();for(let y of oe(e).features){let x=this.keyForFeature(y);this.labelByKey.set(x,this.getLabel(y)),this.values.has(x)||this.values.set(x,null)}for(let[y,x]of this.values)!this.labelByKey.has(y)&&x!==null&&this.warnUnknown(this.writtenAs.get(y)??y);let{container:n,geometry:r,dataBaseUrl:i,districts:o,getId:a,getLabel:l,values:h,fontColor:d,borderColor:s,borderWidth:c,selectionWidth:u,colorScale:p,onReady:f,onError:m,...v}=this.options,b=o??this.usingDefaultData;this.engineInstance=new de(this.containerEl,{...v,colorScale:p,loadDistricts:v.loadDistricts??(b?this.defaultDistrictLoader:void 0),states:{geometry:e,getId:this.getId,getLabel:this.getLabel,getValue:y=>this.values.get(this.keyForFeature(y))??null}}),this._fontColor&&this.mapRootEl.style.setProperty("--india-map-text",this._fontColor),this._borderColor&&this.mapRootEl.style.setProperty("--india-map-stroke",this._borderColor),this._borderWidth!==void 0&&this.mapRootEl.style.setProperty("--india-map-border-width",String(this._borderWidth)),this._selectionWidth!==void 0&&this.mapRootEl.style.setProperty("--india-map-selection-width",String(this._selectionWidth)),f?.(this.proxied??this)}defaultDistrictLoader=async e=>({geometry:await or(this.dataBaseUrl,e,this.abortController?.signal),getId:r=>String(r.properties?.id??r.properties?.name),getLabel:r=>String(r.properties?.name??r.properties?.id),getValue:r=>this.values.get(this.keyFor(this.getLabel(r)))??null});showLoading(){this.loadingEl=document.createElement("div"),this.loadingEl.className="bharat-choropleth__status",this.loadingEl.setAttribute("role","status"),this.loadingEl.textContent="Loading map\u2026",this.containerEl.appendChild(this.loadingEl)}showError(e){this.clearPlaceholder();let n=document.createElement("div");n.className="bharat-choropleth__status bharat-choropleth__status--error",n.setAttribute("role","alert"),n.textContent=e.message,this.containerEl.appendChild(n),this.loadingEl=n,this.options.onError?this.options.onError(e):console.error(e)}clearPlaceholder(){this.loadingEl?.remove(),this.loadingEl=null}get engine(){return this.engineInstance}get states(){return this.statesAccessor}setValues(e){for(let[n,r]of Object.entries(e)){let i=this.keyFor(n);this.values.set(i,r),this.writtenAs.has(i)||this.writtenAs.set(i,n),this.engineInstance&&!this.labelByKey.has(i)&&this.warnUnknown(n)}this.engineInstance?.update({})}getValues(){let e={};for(let[n,r]of this.labelByKey)e[r]=this.values.get(n)??null;return e}get mapRootEl(){return this.containerEl.querySelector(".india-choropleth")??this.containerEl}get fontColor(){return this._fontColor}set fontColor(e){this._fontColor=e,this.engineInstance&&(e?this.mapRootEl.style.setProperty("--india-map-text",e):this.mapRootEl.style.removeProperty("--india-map-text"))}get borderColor(){return this._borderColor}set borderColor(e){this._borderColor=e,this.engineInstance&&(e?this.mapRootEl.style.setProperty("--india-map-stroke",e):this.mapRootEl.style.removeProperty("--india-map-stroke"))}get borderWidth(){return this._borderWidth}set borderWidth(e){this._borderWidth=e,this.setWidthVar("--india-map-border-width",e)}get selectionWidth(){return this._selectionWidth}set selectionWidth(e){this._selectionWidth=e,this.setWidthVar("--india-map-selection-width",e)}setWidthVar(e,n){this.engineInstance&&(n===void 0?this.mapRootEl.style.removeProperty(e):this.mapRootEl.style.setProperty(e,String(n)))}get colorScale(){return this._colorScale}set colorScale(e){this._colorScale=e,this.options.colorScale=e,this.engineInstance?.update({colorScale:e})}select(e){this.engineInstance?.select(e)}drillDown(e){let n=e===null?null:ue(e)?.id??e;this.engineInstance?.drillDown(n)}getSelected(){return this.engineInstance?.getSelected()??null}getInspected(){return this.engineInstance?.getInspected()??null}destroy(){this.destroyed=!0,this.abortController?.abort(),this.clearPlaceholder(),this.engineInstance?.destroy(),this.engineInstance=null}};var cr="bharat-choropleth-styles";function dr(){if(typeof document>"u"||document.getElementById(cr))return;let t=document.createElement("style");t.id=cr,t.textContent=Ut,document.head.appendChild(t)}dr();var Ht=globalThis;Ht.BharatChoropleth=Ge;Ht.IndiaChoropleth=de;Ht.BharatChoroplethLib={BharatChoropleth:Ge,IndiaChoropleth:de,STATES:qt,resolveState:ue,ATTRIBUTION:Qn,DEFAULT_DATA_BASE_URL:ct,injectStyles:dr};})();
|
|
126
|
+
//# sourceMappingURL=bharat-choropleth.min.js.map
|