choropleth-kit 0.0.0-stage → 0.2.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.
Files changed (489) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +305 -2
  3. package/dist/admin1/ad.d.ts +4 -0
  4. package/dist/admin1/ad.js +2 -0
  5. package/dist/admin1/ae.d.ts +4 -0
  6. package/dist/admin1/ae.js +2 -0
  7. package/dist/admin1/af.d.ts +4 -0
  8. package/dist/admin1/af.js +2 -0
  9. package/dist/admin1/ag.d.ts +4 -0
  10. package/dist/admin1/ag.js +2 -0
  11. package/dist/admin1/ai.d.ts +4 -0
  12. package/dist/admin1/ai.js +2 -0
  13. package/dist/admin1/al.d.ts +4 -0
  14. package/dist/admin1/al.js +2 -0
  15. package/dist/admin1/am.d.ts +4 -0
  16. package/dist/admin1/am.js +2 -0
  17. package/dist/admin1/ao.d.ts +4 -0
  18. package/dist/admin1/ao.js +2 -0
  19. package/dist/admin1/aq.d.ts +4 -0
  20. package/dist/admin1/aq.js +2 -0
  21. package/dist/admin1/ar.d.ts +4 -0
  22. package/dist/admin1/ar.js +2 -0
  23. package/dist/admin1/as.d.ts +4 -0
  24. package/dist/admin1/as.js +2 -0
  25. package/dist/admin1/at.d.ts +4 -0
  26. package/dist/admin1/at.js +2 -0
  27. package/dist/admin1/au.d.ts +4 -0
  28. package/dist/admin1/au.js +2 -0
  29. package/dist/admin1/aw.d.ts +4 -0
  30. package/dist/admin1/aw.js +2 -0
  31. package/dist/admin1/ax.d.ts +4 -0
  32. package/dist/admin1/ax.js +2 -0
  33. package/dist/admin1/az.d.ts +4 -0
  34. package/dist/admin1/az.js +2 -0
  35. package/dist/admin1/ba.d.ts +4 -0
  36. package/dist/admin1/ba.js +2 -0
  37. package/dist/admin1/bb.d.ts +4 -0
  38. package/dist/admin1/bb.js +2 -0
  39. package/dist/admin1/bd.d.ts +4 -0
  40. package/dist/admin1/bd.js +2 -0
  41. package/dist/admin1/be.d.ts +4 -0
  42. package/dist/admin1/be.js +2 -0
  43. package/dist/admin1/bf.d.ts +4 -0
  44. package/dist/admin1/bf.js +2 -0
  45. package/dist/admin1/bg.d.ts +4 -0
  46. package/dist/admin1/bg.js +2 -0
  47. package/dist/admin1/bh.d.ts +4 -0
  48. package/dist/admin1/bh.js +2 -0
  49. package/dist/admin1/bi.d.ts +4 -0
  50. package/dist/admin1/bi.js +2 -0
  51. package/dist/admin1/bj.d.ts +4 -0
  52. package/dist/admin1/bj.js +2 -0
  53. package/dist/admin1/bl.d.ts +4 -0
  54. package/dist/admin1/bl.js +2 -0
  55. package/dist/admin1/bm.d.ts +4 -0
  56. package/dist/admin1/bm.js +2 -0
  57. package/dist/admin1/bn.d.ts +4 -0
  58. package/dist/admin1/bn.js +2 -0
  59. package/dist/admin1/bo.d.ts +4 -0
  60. package/dist/admin1/bo.js +2 -0
  61. package/dist/admin1/br.d.ts +4 -0
  62. package/dist/admin1/br.js +2 -0
  63. package/dist/admin1/bs.d.ts +4 -0
  64. package/dist/admin1/bs.js +2 -0
  65. package/dist/admin1/bt.d.ts +4 -0
  66. package/dist/admin1/bt.js +2 -0
  67. package/dist/admin1/bw.d.ts +4 -0
  68. package/dist/admin1/bw.js +2 -0
  69. package/dist/admin1/by.d.ts +4 -0
  70. package/dist/admin1/by.js +2 -0
  71. package/dist/admin1/bz.d.ts +4 -0
  72. package/dist/admin1/bz.js +2 -0
  73. package/dist/admin1/ca.d.ts +4 -0
  74. package/dist/admin1/ca.js +2 -0
  75. package/dist/admin1/cd.d.ts +4 -0
  76. package/dist/admin1/cd.js +2 -0
  77. package/dist/admin1/cf.d.ts +4 -0
  78. package/dist/admin1/cf.js +2 -0
  79. package/dist/admin1/cg.d.ts +4 -0
  80. package/dist/admin1/cg.js +2 -0
  81. package/dist/admin1/ch.d.ts +4 -0
  82. package/dist/admin1/ch.js +2 -0
  83. package/dist/admin1/ci.d.ts +4 -0
  84. package/dist/admin1/ci.js +2 -0
  85. package/dist/admin1/ck.d.ts +4 -0
  86. package/dist/admin1/ck.js +2 -0
  87. package/dist/admin1/cl.d.ts +4 -0
  88. package/dist/admin1/cl.js +2 -0
  89. package/dist/admin1/cm.d.ts +4 -0
  90. package/dist/admin1/cm.js +2 -0
  91. package/dist/admin1/cn.d.ts +4 -0
  92. package/dist/admin1/cn.js +2 -0
  93. package/dist/admin1/co.d.ts +4 -0
  94. package/dist/admin1/co.js +2 -0
  95. package/dist/admin1/cr.d.ts +4 -0
  96. package/dist/admin1/cr.js +2 -0
  97. package/dist/admin1/cu.d.ts +4 -0
  98. package/dist/admin1/cu.js +2 -0
  99. package/dist/admin1/cv.d.ts +4 -0
  100. package/dist/admin1/cv.js +2 -0
  101. package/dist/admin1/cw.d.ts +4 -0
  102. package/dist/admin1/cw.js +2 -0
  103. package/dist/admin1/cy.d.ts +4 -0
  104. package/dist/admin1/cy.js +2 -0
  105. package/dist/admin1/cz.d.ts +4 -0
  106. package/dist/admin1/cz.js +2 -0
  107. package/dist/admin1/de.d.ts +4 -0
  108. package/dist/admin1/de.js +2 -0
  109. package/dist/admin1/dj.d.ts +4 -0
  110. package/dist/admin1/dj.js +2 -0
  111. package/dist/admin1/dk.d.ts +4 -0
  112. package/dist/admin1/dk.js +2 -0
  113. package/dist/admin1/dm.d.ts +4 -0
  114. package/dist/admin1/dm.js +2 -0
  115. package/dist/admin1/do.d.ts +4 -0
  116. package/dist/admin1/do.js +2 -0
  117. package/dist/admin1/dz.d.ts +4 -0
  118. package/dist/admin1/dz.js +2 -0
  119. package/dist/admin1/ec.d.ts +4 -0
  120. package/dist/admin1/ec.js +2 -0
  121. package/dist/admin1/ee.d.ts +4 -0
  122. package/dist/admin1/ee.js +2 -0
  123. package/dist/admin1/eg.d.ts +4 -0
  124. package/dist/admin1/eg.js +2 -0
  125. package/dist/admin1/eh.d.ts +4 -0
  126. package/dist/admin1/eh.js +2 -0
  127. package/dist/admin1/er.d.ts +4 -0
  128. package/dist/admin1/er.js +2 -0
  129. package/dist/admin1/es.d.ts +4 -0
  130. package/dist/admin1/es.js +2 -0
  131. package/dist/admin1/et.d.ts +4 -0
  132. package/dist/admin1/et.js +2 -0
  133. package/dist/admin1/fi.d.ts +4 -0
  134. package/dist/admin1/fi.js +2 -0
  135. package/dist/admin1/fj.d.ts +4 -0
  136. package/dist/admin1/fj.js +2 -0
  137. package/dist/admin1/fk.d.ts +4 -0
  138. package/dist/admin1/fk.js +2 -0
  139. package/dist/admin1/fm.d.ts +4 -0
  140. package/dist/admin1/fm.js +2 -0
  141. package/dist/admin1/fo.d.ts +4 -0
  142. package/dist/admin1/fo.js +2 -0
  143. package/dist/admin1/fr.d.ts +4 -0
  144. package/dist/admin1/fr.js +2 -0
  145. package/dist/admin1/ga.d.ts +4 -0
  146. package/dist/admin1/ga.js +2 -0
  147. package/dist/admin1/gb.d.ts +4 -0
  148. package/dist/admin1/gb.js +2 -0
  149. package/dist/admin1/gd.d.ts +4 -0
  150. package/dist/admin1/gd.js +2 -0
  151. package/dist/admin1/ge.d.ts +4 -0
  152. package/dist/admin1/ge.js +2 -0
  153. package/dist/admin1/gg.d.ts +4 -0
  154. package/dist/admin1/gg.js +2 -0
  155. package/dist/admin1/gh.d.ts +4 -0
  156. package/dist/admin1/gh.js +2 -0
  157. package/dist/admin1/gi.d.ts +4 -0
  158. package/dist/admin1/gi.js +2 -0
  159. package/dist/admin1/gl.d.ts +4 -0
  160. package/dist/admin1/gl.js +2 -0
  161. package/dist/admin1/gm.d.ts +4 -0
  162. package/dist/admin1/gm.js +2 -0
  163. package/dist/admin1/gn.d.ts +4 -0
  164. package/dist/admin1/gn.js +2 -0
  165. package/dist/admin1/gq.d.ts +4 -0
  166. package/dist/admin1/gq.js +2 -0
  167. package/dist/admin1/gr.d.ts +4 -0
  168. package/dist/admin1/gr.js +2 -0
  169. package/dist/admin1/gs.d.ts +4 -0
  170. package/dist/admin1/gs.js +2 -0
  171. package/dist/admin1/gt.d.ts +4 -0
  172. package/dist/admin1/gt.js +2 -0
  173. package/dist/admin1/gu.d.ts +4 -0
  174. package/dist/admin1/gu.js +2 -0
  175. package/dist/admin1/gw.d.ts +4 -0
  176. package/dist/admin1/gw.js +2 -0
  177. package/dist/admin1/gy.d.ts +4 -0
  178. package/dist/admin1/gy.js +2 -0
  179. package/dist/admin1/hk.d.ts +4 -0
  180. package/dist/admin1/hk.js +2 -0
  181. package/dist/admin1/hm.d.ts +4 -0
  182. package/dist/admin1/hm.js +2 -0
  183. package/dist/admin1/hn.d.ts +4 -0
  184. package/dist/admin1/hn.js +2 -0
  185. package/dist/admin1/hr.d.ts +4 -0
  186. package/dist/admin1/hr.js +2 -0
  187. package/dist/admin1/ht.d.ts +4 -0
  188. package/dist/admin1/ht.js +2 -0
  189. package/dist/admin1/hu.d.ts +4 -0
  190. package/dist/admin1/hu.js +2 -0
  191. package/dist/admin1/id.d.ts +4 -0
  192. package/dist/admin1/id.js +2 -0
  193. package/dist/admin1/ie.d.ts +4 -0
  194. package/dist/admin1/ie.js +2 -0
  195. package/dist/admin1/il.d.ts +4 -0
  196. package/dist/admin1/il.js +2 -0
  197. package/dist/admin1/im.d.ts +4 -0
  198. package/dist/admin1/im.js +2 -0
  199. package/dist/admin1/in.d.ts +4 -0
  200. package/dist/admin1/in.js +2 -0
  201. package/dist/admin1/io.d.ts +4 -0
  202. package/dist/admin1/io.js +2 -0
  203. package/dist/admin1/iq.d.ts +4 -0
  204. package/dist/admin1/iq.js +2 -0
  205. package/dist/admin1/ir.d.ts +4 -0
  206. package/dist/admin1/ir.js +2 -0
  207. package/dist/admin1/is.d.ts +4 -0
  208. package/dist/admin1/is.js +2 -0
  209. package/dist/admin1/it.d.ts +4 -0
  210. package/dist/admin1/it.js +2 -0
  211. package/dist/admin1/je.d.ts +4 -0
  212. package/dist/admin1/je.js +2 -0
  213. package/dist/admin1/jm.d.ts +4 -0
  214. package/dist/admin1/jm.js +2 -0
  215. package/dist/admin1/jo.d.ts +4 -0
  216. package/dist/admin1/jo.js +2 -0
  217. package/dist/admin1/jp.d.ts +4 -0
  218. package/dist/admin1/jp.js +2 -0
  219. package/dist/admin1/ke.d.ts +4 -0
  220. package/dist/admin1/ke.js +2 -0
  221. package/dist/admin1/kg.d.ts +4 -0
  222. package/dist/admin1/kg.js +2 -0
  223. package/dist/admin1/kh.d.ts +4 -0
  224. package/dist/admin1/kh.js +2 -0
  225. package/dist/admin1/ki.d.ts +4 -0
  226. package/dist/admin1/ki.js +2 -0
  227. package/dist/admin1/km.d.ts +4 -0
  228. package/dist/admin1/km.js +2 -0
  229. package/dist/admin1/kn.d.ts +4 -0
  230. package/dist/admin1/kn.js +2 -0
  231. package/dist/admin1/kp.d.ts +4 -0
  232. package/dist/admin1/kp.js +2 -0
  233. package/dist/admin1/kr.d.ts +4 -0
  234. package/dist/admin1/kr.js +2 -0
  235. package/dist/admin1/kw.d.ts +4 -0
  236. package/dist/admin1/kw.js +2 -0
  237. package/dist/admin1/ky.d.ts +4 -0
  238. package/dist/admin1/ky.js +2 -0
  239. package/dist/admin1/kz.d.ts +4 -0
  240. package/dist/admin1/kz.js +2 -0
  241. package/dist/admin1/la.d.ts +4 -0
  242. package/dist/admin1/la.js +2 -0
  243. package/dist/admin1/lb.d.ts +4 -0
  244. package/dist/admin1/lb.js +2 -0
  245. package/dist/admin1/lc.d.ts +4 -0
  246. package/dist/admin1/lc.js +2 -0
  247. package/dist/admin1/li.d.ts +4 -0
  248. package/dist/admin1/li.js +2 -0
  249. package/dist/admin1/lk.d.ts +4 -0
  250. package/dist/admin1/lk.js +2 -0
  251. package/dist/admin1/lr.d.ts +4 -0
  252. package/dist/admin1/lr.js +2 -0
  253. package/dist/admin1/ls.d.ts +4 -0
  254. package/dist/admin1/ls.js +2 -0
  255. package/dist/admin1/lt.d.ts +4 -0
  256. package/dist/admin1/lt.js +2 -0
  257. package/dist/admin1/lu.d.ts +4 -0
  258. package/dist/admin1/lu.js +2 -0
  259. package/dist/admin1/lv.d.ts +4 -0
  260. package/dist/admin1/lv.js +2 -0
  261. package/dist/admin1/ly.d.ts +4 -0
  262. package/dist/admin1/ly.js +2 -0
  263. package/dist/admin1/ma.d.ts +4 -0
  264. package/dist/admin1/ma.js +2 -0
  265. package/dist/admin1/mc.d.ts +4 -0
  266. package/dist/admin1/mc.js +2 -0
  267. package/dist/admin1/md.d.ts +4 -0
  268. package/dist/admin1/md.js +2 -0
  269. package/dist/admin1/me.d.ts +4 -0
  270. package/dist/admin1/me.js +2 -0
  271. package/dist/admin1/mf.d.ts +4 -0
  272. package/dist/admin1/mf.js +2 -0
  273. package/dist/admin1/mg.d.ts +4 -0
  274. package/dist/admin1/mg.js +2 -0
  275. package/dist/admin1/mh.d.ts +4 -0
  276. package/dist/admin1/mh.js +2 -0
  277. package/dist/admin1/mk.d.ts +4 -0
  278. package/dist/admin1/mk.js +2 -0
  279. package/dist/admin1/ml.d.ts +4 -0
  280. package/dist/admin1/ml.js +2 -0
  281. package/dist/admin1/mm.d.ts +4 -0
  282. package/dist/admin1/mm.js +2 -0
  283. package/dist/admin1/mn.d.ts +4 -0
  284. package/dist/admin1/mn.js +2 -0
  285. package/dist/admin1/mo.d.ts +4 -0
  286. package/dist/admin1/mo.js +2 -0
  287. package/dist/admin1/mp.d.ts +4 -0
  288. package/dist/admin1/mp.js +2 -0
  289. package/dist/admin1/mr.d.ts +4 -0
  290. package/dist/admin1/mr.js +2 -0
  291. package/dist/admin1/ms.d.ts +4 -0
  292. package/dist/admin1/ms.js +2 -0
  293. package/dist/admin1/mt.d.ts +4 -0
  294. package/dist/admin1/mt.js +2 -0
  295. package/dist/admin1/mu.d.ts +4 -0
  296. package/dist/admin1/mu.js +2 -0
  297. package/dist/admin1/mv.d.ts +4 -0
  298. package/dist/admin1/mv.js +2 -0
  299. package/dist/admin1/mw.d.ts +4 -0
  300. package/dist/admin1/mw.js +2 -0
  301. package/dist/admin1/mx.d.ts +4 -0
  302. package/dist/admin1/mx.js +2 -0
  303. package/dist/admin1/my.d.ts +4 -0
  304. package/dist/admin1/my.js +2 -0
  305. package/dist/admin1/mz.d.ts +4 -0
  306. package/dist/admin1/mz.js +2 -0
  307. package/dist/admin1/na.d.ts +4 -0
  308. package/dist/admin1/na.js +2 -0
  309. package/dist/admin1/nc.d.ts +4 -0
  310. package/dist/admin1/nc.js +2 -0
  311. package/dist/admin1/ne.d.ts +4 -0
  312. package/dist/admin1/ne.js +2 -0
  313. package/dist/admin1/nf.d.ts +4 -0
  314. package/dist/admin1/nf.js +2 -0
  315. package/dist/admin1/ng.d.ts +4 -0
  316. package/dist/admin1/ng.js +2 -0
  317. package/dist/admin1/ni.d.ts +4 -0
  318. package/dist/admin1/ni.js +2 -0
  319. package/dist/admin1/nl.d.ts +4 -0
  320. package/dist/admin1/nl.js +2 -0
  321. package/dist/admin1/no.d.ts +4 -0
  322. package/dist/admin1/no.js +2 -0
  323. package/dist/admin1/np.d.ts +4 -0
  324. package/dist/admin1/np.js +2 -0
  325. package/dist/admin1/nr.d.ts +4 -0
  326. package/dist/admin1/nr.js +2 -0
  327. package/dist/admin1/nu.d.ts +4 -0
  328. package/dist/admin1/nu.js +2 -0
  329. package/dist/admin1/nz.d.ts +4 -0
  330. package/dist/admin1/nz.js +2 -0
  331. package/dist/admin1/om.d.ts +4 -0
  332. package/dist/admin1/om.js +2 -0
  333. package/dist/admin1/pa.d.ts +4 -0
  334. package/dist/admin1/pa.js +2 -0
  335. package/dist/admin1/pe.d.ts +4 -0
  336. package/dist/admin1/pe.js +2 -0
  337. package/dist/admin1/pf.d.ts +4 -0
  338. package/dist/admin1/pf.js +2 -0
  339. package/dist/admin1/pg.d.ts +4 -0
  340. package/dist/admin1/pg.js +2 -0
  341. package/dist/admin1/ph.d.ts +4 -0
  342. package/dist/admin1/ph.js +2 -0
  343. package/dist/admin1/pk.d.ts +4 -0
  344. package/dist/admin1/pk.js +2 -0
  345. package/dist/admin1/pl.d.ts +4 -0
  346. package/dist/admin1/pl.js +2 -0
  347. package/dist/admin1/pm.d.ts +4 -0
  348. package/dist/admin1/pm.js +2 -0
  349. package/dist/admin1/pn.d.ts +4 -0
  350. package/dist/admin1/pn.js +2 -0
  351. package/dist/admin1/ps.d.ts +4 -0
  352. package/dist/admin1/ps.js +2 -0
  353. package/dist/admin1/pt.d.ts +4 -0
  354. package/dist/admin1/pt.js +2 -0
  355. package/dist/admin1/pw.d.ts +4 -0
  356. package/dist/admin1/pw.js +2 -0
  357. package/dist/admin1/py.d.ts +4 -0
  358. package/dist/admin1/py.js +2 -0
  359. package/dist/admin1/qa.d.ts +4 -0
  360. package/dist/admin1/qa.js +2 -0
  361. package/dist/admin1/ro.d.ts +4 -0
  362. package/dist/admin1/ro.js +2 -0
  363. package/dist/admin1/rs.d.ts +4 -0
  364. package/dist/admin1/rs.js +2 -0
  365. package/dist/admin1/ru.d.ts +4 -0
  366. package/dist/admin1/ru.js +2 -0
  367. package/dist/admin1/rw.d.ts +4 -0
  368. package/dist/admin1/rw.js +2 -0
  369. package/dist/admin1/sa.d.ts +4 -0
  370. package/dist/admin1/sa.js +2 -0
  371. package/dist/admin1/sb.d.ts +4 -0
  372. package/dist/admin1/sb.js +2 -0
  373. package/dist/admin1/sc.d.ts +4 -0
  374. package/dist/admin1/sc.js +2 -0
  375. package/dist/admin1/sd.d.ts +4 -0
  376. package/dist/admin1/sd.js +2 -0
  377. package/dist/admin1/se.d.ts +4 -0
  378. package/dist/admin1/se.js +2 -0
  379. package/dist/admin1/sg.d.ts +4 -0
  380. package/dist/admin1/sg.js +2 -0
  381. package/dist/admin1/sh.d.ts +4 -0
  382. package/dist/admin1/sh.js +2 -0
  383. package/dist/admin1/si.d.ts +4 -0
  384. package/dist/admin1/si.js +2 -0
  385. package/dist/admin1/sk.d.ts +4 -0
  386. package/dist/admin1/sk.js +2 -0
  387. package/dist/admin1/sl.d.ts +4 -0
  388. package/dist/admin1/sl.js +2 -0
  389. package/dist/admin1/sm.d.ts +4 -0
  390. package/dist/admin1/sm.js +2 -0
  391. package/dist/admin1/sn.d.ts +4 -0
  392. package/dist/admin1/sn.js +2 -0
  393. package/dist/admin1/so.d.ts +4 -0
  394. package/dist/admin1/so.js +2 -0
  395. package/dist/admin1/sr.d.ts +4 -0
  396. package/dist/admin1/sr.js +2 -0
  397. package/dist/admin1/ss.d.ts +4 -0
  398. package/dist/admin1/ss.js +2 -0
  399. package/dist/admin1/st.d.ts +4 -0
  400. package/dist/admin1/st.js +2 -0
  401. package/dist/admin1/sv.d.ts +4 -0
  402. package/dist/admin1/sv.js +2 -0
  403. package/dist/admin1/sy.d.ts +4 -0
  404. package/dist/admin1/sy.js +2 -0
  405. package/dist/admin1/sz.d.ts +4 -0
  406. package/dist/admin1/sz.js +2 -0
  407. package/dist/admin1/tc.d.ts +4 -0
  408. package/dist/admin1/tc.js +2 -0
  409. package/dist/admin1/td.d.ts +4 -0
  410. package/dist/admin1/td.js +2 -0
  411. package/dist/admin1/tf.d.ts +4 -0
  412. package/dist/admin1/tf.js +2 -0
  413. package/dist/admin1/tg.d.ts +4 -0
  414. package/dist/admin1/tg.js +2 -0
  415. package/dist/admin1/th.d.ts +4 -0
  416. package/dist/admin1/th.js +2 -0
  417. package/dist/admin1/tj.d.ts +4 -0
  418. package/dist/admin1/tj.js +2 -0
  419. package/dist/admin1/tk.d.ts +4 -0
  420. package/dist/admin1/tk.js +2 -0
  421. package/dist/admin1/tl.d.ts +4 -0
  422. package/dist/admin1/tl.js +2 -0
  423. package/dist/admin1/tm.d.ts +4 -0
  424. package/dist/admin1/tm.js +2 -0
  425. package/dist/admin1/tn.d.ts +4 -0
  426. package/dist/admin1/tn.js +2 -0
  427. package/dist/admin1/to.d.ts +4 -0
  428. package/dist/admin1/to.js +2 -0
  429. package/dist/admin1/tr.d.ts +4 -0
  430. package/dist/admin1/tr.js +2 -0
  431. package/dist/admin1/tt.d.ts +4 -0
  432. package/dist/admin1/tt.js +2 -0
  433. package/dist/admin1/tv.d.ts +4 -0
  434. package/dist/admin1/tv.js +2 -0
  435. package/dist/admin1/tw.d.ts +4 -0
  436. package/dist/admin1/tw.js +2 -0
  437. package/dist/admin1/tz.d.ts +4 -0
  438. package/dist/admin1/tz.js +2 -0
  439. package/dist/admin1/ua.d.ts +4 -0
  440. package/dist/admin1/ua.js +2 -0
  441. package/dist/admin1/ug.d.ts +4 -0
  442. package/dist/admin1/ug.js +2 -0
  443. package/dist/admin1/um.d.ts +4 -0
  444. package/dist/admin1/um.js +2 -0
  445. package/dist/admin1/us.d.ts +4 -0
  446. package/dist/admin1/us.js +2 -0
  447. package/dist/admin1/uy.d.ts +4 -0
  448. package/dist/admin1/uy.js +2 -0
  449. package/dist/admin1/uz.d.ts +4 -0
  450. package/dist/admin1/uz.js +2 -0
  451. package/dist/admin1/va.d.ts +4 -0
  452. package/dist/admin1/va.js +2 -0
  453. package/dist/admin1/vc.d.ts +4 -0
  454. package/dist/admin1/vc.js +2 -0
  455. package/dist/admin1/ve.d.ts +4 -0
  456. package/dist/admin1/ve.js +2 -0
  457. package/dist/admin1/vg.d.ts +4 -0
  458. package/dist/admin1/vg.js +2 -0
  459. package/dist/admin1/vi.d.ts +4 -0
  460. package/dist/admin1/vi.js +2 -0
  461. package/dist/admin1/vn.d.ts +4 -0
  462. package/dist/admin1/vn.js +2 -0
  463. package/dist/admin1/vu.d.ts +4 -0
  464. package/dist/admin1/vu.js +2 -0
  465. package/dist/admin1/wf.d.ts +4 -0
  466. package/dist/admin1/wf.js +2 -0
  467. package/dist/admin1/ws.d.ts +4 -0
  468. package/dist/admin1/ws.js +2 -0
  469. package/dist/admin1/xk.d.ts +4 -0
  470. package/dist/admin1/xk.js +2 -0
  471. package/dist/admin1/ye.d.ts +4 -0
  472. package/dist/admin1/ye.js +2 -0
  473. package/dist/admin1/za.d.ts +4 -0
  474. package/dist/admin1/za.js +2 -0
  475. package/dist/admin1/zm.d.ts +4 -0
  476. package/dist/admin1/zm.js +2 -0
  477. package/dist/admin1/zw.d.ts +4 -0
  478. package/dist/admin1/zw.js +2 -0
  479. package/dist/chunk-ZN6SLXL3.js +1932 -0
  480. package/dist/core.d.ts +173 -0
  481. package/dist/core.js +203 -0
  482. package/dist/drill-chain-C8hhHBnd.d.ts +1256 -0
  483. package/dist/geo.d.ts +89 -0
  484. package/dist/geo.js +457 -0
  485. package/dist/index.d.ts +1256 -0
  486. package/dist/index.js +3110 -0
  487. package/dist/styles.css +417 -0
  488. package/dist/styles.d.ts +2 -0
  489. package/package.json +147 -3
@@ -0,0 +1,1932 @@
1
+ // src/core/geography.ts
2
+ import { feature } from "topojson-client";
3
+ var unwrapGeography = (value) => "default" in value ? value.default : value;
4
+ var toFeatureCollection = ({
5
+ geography,
6
+ objectName
7
+ }) => {
8
+ const kind = geography?.type;
9
+ if (kind === "FeatureCollection") {
10
+ return geography;
11
+ }
12
+ if (kind !== "Topology") {
13
+ throw new Error(
14
+ `[choropleth] toFeatureCollection: unrecognized format (type = ${JSON.stringify(kind)}). Expected a "Topology" (TopoJSON) or a "FeatureCollection" (GeoJSON).`
15
+ );
16
+ }
17
+ const topology = geography;
18
+ const availableNames = Object.keys(topology.objects);
19
+ const name = objectName ?? availableNames[0];
20
+ const object = name === void 0 ? void 0 : topology.objects[name];
21
+ if (name === void 0 || object === void 0) {
22
+ throw new Error(
23
+ `[choropleth] toFeatureCollection: object "${objectName ?? "(none)"}" does not exist in the topology. Available objects: ${availableNames.length > 0 ? availableNames.join(", ") : "(none)"}.`
24
+ );
25
+ }
26
+ const converted = feature(topology, object);
27
+ if (converted.type === "FeatureCollection") {
28
+ return converted;
29
+ }
30
+ return { type: "FeatureCollection", features: [converted] };
31
+ };
32
+
33
+ // src/core/bounds.ts
34
+ import { geoBounds } from "d3-geo";
35
+ import polylabel from "polylabel";
36
+ var polygonsOf = (geometry) => {
37
+ if (geometry.type === "Polygon") return [geometry];
38
+ if (geometry.type === "MultiPolygon") {
39
+ return geometry.coordinates.map((coordinates) => ({ type: "Polygon", coordinates }));
40
+ }
41
+ return null;
42
+ };
43
+ var getFocusGeometry = ({
44
+ feature: feature2,
45
+ path,
46
+ near = 0.5
47
+ }) => {
48
+ const { geometry } = feature2;
49
+ if (geometry === null) return null;
50
+ const polygons = polygonsOf(geometry);
51
+ if (polygons === null || polygons.length <= 1) return geometry;
52
+ const measured = polygons.map((polygon) => {
53
+ const [[x0, y0], [x1, y1]] = path.bounds(polygon);
54
+ return {
55
+ polygon,
56
+ area: path.area(polygon),
57
+ cx: (x0 + x1) / 2,
58
+ cy: (y0 + y1) / 2,
59
+ diagonal: Math.hypot(x1 - x0, y1 - y0)
60
+ };
61
+ });
62
+ const usable = measured.filter((m) => Number.isFinite(m.area) && Number.isFinite(m.cx));
63
+ const main = usable.reduce(
64
+ (best, m) => best === void 0 || m.area > best.area ? m : best,
65
+ void 0
66
+ );
67
+ if (main === void 0) return geometry;
68
+ const kept = usable.filter(
69
+ (m) => m === main || Math.hypot(m.cx - main.cx, m.cy - main.cy) <= near * main.diagonal
70
+ );
71
+ const [only] = kept;
72
+ return kept.length === 1 && only !== void 0 ? only.polygon : { type: "MultiPolygon", coordinates: kept.map((m) => m.polygon.coordinates) };
73
+ };
74
+ var ringArea = (ring) => {
75
+ let sum = 0;
76
+ ring.forEach(([x, y], i) => {
77
+ const [nx, ny] = ring[(i + 1) % ring.length] ?? [x, y];
78
+ sum += x * ny - nx * y;
79
+ });
80
+ return Math.abs(sum / 2);
81
+ };
82
+ var getAnchorPoint = ({
83
+ geometry,
84
+ project,
85
+ precision = 1
86
+ }) => {
87
+ if (geometry === null) return null;
88
+ const polygons = polygonsOf(geometry)?.map((p) => p.coordinates);
89
+ if (polygons === void 0) return null;
90
+ const projected = polygons.map(
91
+ (rings) => rings.map(
92
+ (ring) => ring.flatMap(([lon, lat]) => {
93
+ const at = lon === void 0 || lat === void 0 ? null : project([lon, lat]);
94
+ return at === null ? [] : [at];
95
+ })
96
+ )
97
+ ).filter(([outer]) => outer !== void 0 && outer.length >= 3);
98
+ const biggest = projected.reduce((best, rings) => {
99
+ const outer = rings[0] ?? [];
100
+ return best === void 0 || ringArea(outer) > ringArea(best[0] ?? []) ? rings : best;
101
+ }, void 0);
102
+ if (biggest === void 0) return null;
103
+ const [x, y] = polylabel(
104
+ biggest.map((ring) => ring.map(([px2, py]) => [px2, py])),
105
+ precision
106
+ );
107
+ return Number.isFinite(x) && Number.isFinite(y) ? [x, y] : null;
108
+ };
109
+ var DEFAULT_PADDING = 24;
110
+ var normalizePadding = (padding = DEFAULT_PADDING) => typeof padding === "number" ? { top: padding, right: padding, bottom: padding, left: padding } : padding;
111
+ var boundsToTransform = ({
112
+ bounds,
113
+ size,
114
+ padding = DEFAULT_PADDING,
115
+ scaleExtent = [0, Infinity]
116
+ }) => {
117
+ const [[x0, y0], [x1, y1]] = bounds;
118
+ const { top, right, bottom, left } = normalizePadding(padding);
119
+ const innerW = size.width - left - right;
120
+ const innerH = size.height - top - bottom;
121
+ const raw = Math.min(innerW / (x1 - x0), innerH / (y1 - y0));
122
+ const k = Math.min(scaleExtent[1], Math.max(scaleExtent[0], Number.isNaN(raw) ? 1 : raw));
123
+ return {
124
+ k,
125
+ x: left + innerW / 2 - k * ((x0 + x1) / 2),
126
+ y: top + innerH / 2 - k * ((y0 + y1) / 2)
127
+ };
128
+ };
129
+ var EDGE_SAMPLES = 9;
130
+ var projectBounds = (bounds, project) => {
131
+ const [[west, south], [east, north]] = bounds;
132
+ if (east < west) {
133
+ const eastHalf = [
134
+ [west, south],
135
+ [180, north]
136
+ ];
137
+ const westHalf = [
138
+ [-180, south],
139
+ [east, north]
140
+ ];
141
+ return projectBounds(180 - west >= east + 180 ? eastHalf : westHalf, project);
142
+ }
143
+ const samples = [];
144
+ for (let i = 0; i < EDGE_SAMPLES; i += 1) {
145
+ const t = i / (EDGE_SAMPLES - 1);
146
+ const lon = west + (east - west) * t;
147
+ const lat = south + (north - south) * t;
148
+ samples.push([lon, south], [lon, north], [west, lat], [east, lat]);
149
+ }
150
+ const projected = samples.flatMap((at) => {
151
+ const p = project(at);
152
+ return p === null ? [] : [p];
153
+ });
154
+ if (projected.length === 0) return null;
155
+ const xs = projected.map(([x]) => x);
156
+ const ys = projected.map(([, y]) => y);
157
+ return [
158
+ [Math.min(...xs), Math.min(...ys)],
159
+ [Math.max(...xs), Math.max(...ys)]
160
+ ];
161
+ };
162
+ var getFocusExtent = ({
163
+ feature: feature2,
164
+ path,
165
+ project,
166
+ near
167
+ }) => {
168
+ const geometry = getFocusGeometry({ feature: feature2, path, near });
169
+ if (geometry === null) return null;
170
+ const [[west, south], [east, north]] = geoBounds(geometry);
171
+ if (west > east)
172
+ return projectBounds(
173
+ [
174
+ [west, south],
175
+ [east, north]
176
+ ],
177
+ project
178
+ );
179
+ const [[x0, y0], [x1, y1]] = path.bounds(geometry);
180
+ return [x0, y0, x1, y1].every(Number.isFinite) ? [
181
+ [x0, y0],
182
+ [x1, y1]
183
+ ] : null;
184
+ };
185
+
186
+ // src/core/camera.ts
187
+ import { interpolateZoom } from "d3-interpolate";
188
+ var FIT_TRANSFORM = { k: 1, x: 0, y: 0 };
189
+ var isFitTransform = (t, epsilon = 1e-3) => Math.abs(t.k - 1) < epsilon && Math.abs(t.x) < epsilon && Math.abs(t.y) < epsilon;
190
+ var applyTransform = ({ k, x, y }, [px2, py]) => [
191
+ px2 * k + x,
192
+ py * k + y
193
+ ];
194
+ var invertTransform = ({ k, x, y }, [sx, sy]) => [
195
+ (sx - x) / k,
196
+ (sy - y) / k
197
+ ];
198
+ var constrainAxis = ({
199
+ t,
200
+ k,
201
+ c0,
202
+ c1,
203
+ v0,
204
+ v1,
205
+ overscroll = 0
206
+ }) => {
207
+ const size = (c1 - c0) * k;
208
+ const view = v1 - v0;
209
+ if (size <= view) return v0 + (view - size) / 2 - c0 * k;
210
+ const slack = view * overscroll;
211
+ const min = v1 - c1 * k - slack;
212
+ const max = v0 - c0 * k + slack;
213
+ return Math.min(max, Math.max(min, t));
214
+ };
215
+ var constrainTransform = ({
216
+ transform,
217
+ content,
218
+ view,
219
+ overscroll
220
+ }) => ({
221
+ k: transform.k,
222
+ x: constrainAxis({
223
+ t: transform.x,
224
+ k: transform.k,
225
+ c0: content[0][0],
226
+ c1: content[1][0],
227
+ v0: view[0][0],
228
+ v1: view[1][0],
229
+ overscroll
230
+ }),
231
+ y: constrainAxis({
232
+ t: transform.y,
233
+ k: transform.k,
234
+ c0: content[0][1],
235
+ c1: content[1][1],
236
+ v0: view[0][1],
237
+ v1: view[1][1],
238
+ overscroll
239
+ })
240
+ });
241
+ var preserveView = ({
242
+ transform,
243
+ oldSize,
244
+ newSize,
245
+ invertOld,
246
+ projectNew
247
+ }) => {
248
+ const center = invertOld(invertTransform(transform, [oldSize.width / 2, oldSize.height / 2]));
249
+ const projected = center === null ? null : projectNew(center);
250
+ if (projected === null) return FIT_TRANSFORM;
251
+ return {
252
+ k: transform.k,
253
+ x: newSize.width / 2 - transform.k * projected[0],
254
+ y: newSize.height / 2 - transform.k * projected[1]
255
+ };
256
+ };
257
+ var MIN_FLIGHT_MS = 350;
258
+ var MAX_FLIGHT_MS = 1200;
259
+ var DEFAULT_FLIGHT_CURVATURE = 1.25;
260
+ var transformToZoomView = ({ k, x, y }, { width, height }) => [(width / 2 - x) / k, (height / 2 - y) / k, width / k];
261
+ var createZoomInterpolator = (rho) => interpolateZoom.rho(rho);
262
+ var flightDuration = ({
263
+ from,
264
+ to,
265
+ size,
266
+ speed = 1,
267
+ curvature = DEFAULT_FLIGHT_CURVATURE
268
+ }) => {
269
+ const natural = createZoomInterpolator(curvature)(
270
+ transformToZoomView(from, size),
271
+ transformToZoomView(to, size)
272
+ ).duration;
273
+ const scaled = natural * speed;
274
+ if (!Number.isFinite(scaled)) return MIN_FLIGHT_MS;
275
+ return Math.min(MAX_FLIGHT_MS, Math.max(MIN_FLIGHT_MS, scaled));
276
+ };
277
+ var INERTIA_TAU_MS = 325;
278
+ var inertiaOffset = ({
279
+ velocity,
280
+ elapsed,
281
+ tau = INERTIA_TAU_MS
282
+ }) => {
283
+ if (!(elapsed > 0) || !Number.isFinite(velocity)) return 0;
284
+ return velocity * tau * (1 - Math.exp(-elapsed / tau));
285
+ };
286
+ var INERTIA_MIN_VELOCITY = 0.3;
287
+ var INERTIA_WINDOW_MS = 100;
288
+ var releaseVelocity = ({
289
+ samples,
290
+ now,
291
+ windowMs = INERTIA_WINDOW_MS,
292
+ minVelocity = INERTIA_MIN_VELOCITY
293
+ }) => {
294
+ const recent = samples.filter((s) => now - s.time <= windowMs);
295
+ if (recent.length < 2) return null;
296
+ const first = recent[0];
297
+ const last = recent[recent.length - 1];
298
+ if (first === void 0 || last === void 0) return null;
299
+ if (recent.some((s) => s.k !== last.k)) return null;
300
+ const dt = last.time - first.time;
301
+ if (!(dt > 0)) return null;
302
+ const vx = (last.x - first.x) / dt;
303
+ const vy = (last.y - first.y) / dt;
304
+ return Math.hypot(vx, vy) >= minVelocity ? [vx, vy] : null;
305
+ };
306
+ var bubbleScale = (k, scaling) => {
307
+ if (!(k > 0) || !Number.isFinite(k)) return 1;
308
+ switch (scaling) {
309
+ case "screen":
310
+ return 1 / k;
311
+ case "geo":
312
+ return 1;
313
+ case "sqrt":
314
+ return 1 / Math.sqrt(k);
315
+ }
316
+ };
317
+ var WORLD_BOUNDS = [
318
+ [-180, -90],
319
+ [180, 90]
320
+ ];
321
+ var BOUNDS_SAMPLES = 5;
322
+ var toViewState = ({
323
+ transform,
324
+ size,
325
+ invert,
326
+ level = { id: "root", depth: 0 }
327
+ }) => {
328
+ const toCoordinates = (screen) => {
329
+ const at = invert(invertTransform(transform, screen));
330
+ return at !== null && Number.isFinite(at[0]) && Number.isFinite(at[1]) ? at : null;
331
+ };
332
+ const samples = [];
333
+ for (let i = 0; i < BOUNDS_SAMPLES; i += 1) {
334
+ for (let j = 0; j < BOUNDS_SAMPLES; j += 1) {
335
+ const at = toCoordinates([
336
+ size.width * i / (BOUNDS_SAMPLES - 1),
337
+ size.height * j / (BOUNDS_SAMPLES - 1)
338
+ ]);
339
+ if (at !== null) samples.push(at);
340
+ }
341
+ }
342
+ const lons = samples.map(([lon]) => lon);
343
+ const lats = samples.map(([, lat]) => lat);
344
+ const bounds = samples.length === 0 ? WORLD_BOUNDS : [
345
+ [Math.min(...lons), Math.min(...lats)],
346
+ [Math.max(...lons), Math.max(...lats)]
347
+ ];
348
+ const center = toCoordinates([size.width / 2, size.height / 2]) ?? [
349
+ (bounds[0][0] + bounds[1][0]) / 2,
350
+ (bounds[0][1] + bounds[1][1]) / 2
351
+ ];
352
+ return {
353
+ k: transform.k,
354
+ x: transform.x,
355
+ y: transform.y,
356
+ zoom: transform.k,
357
+ center,
358
+ bounds,
359
+ level
360
+ };
361
+ };
362
+
363
+ // src/core/theme.ts
364
+ var defineTheme = (theme) => theme;
365
+ var light = {
366
+ background: "transparent",
367
+ empty: { fill: "#d4d4d4" },
368
+ context: { fill: "#e5e5e5", border: "#ffffff" },
369
+ border: { color: "#ffffff", width: 0.5 },
370
+ hover: { stroke: "#000000", width: 1.5 },
371
+ selected: { stroke: "#0b5fff", width: 2 },
372
+ focus: { ring: "#0b5fff", width: 2 },
373
+ dim: { opacity: 0.45 },
374
+ bubble: { fill: "#2563eb", stroke: "#ffffff", opacity: 0.75 },
375
+ font: { color: "#111111" },
376
+ tooltip: {
377
+ background: "#ffffff",
378
+ color: "#111111",
379
+ border: "#cccccc",
380
+ radius: 4,
381
+ shadow: "none"
382
+ },
383
+ controls: { background: "#ffffff", color: "#111111", border: "#cccccc", radius: 6 }
384
+ };
385
+ var dark = {
386
+ background: "#0f172a",
387
+ empty: { fill: "#475569" },
388
+ context: { fill: "#1e293b", border: "#0f172a" },
389
+ border: { color: "#0f172a", width: 0.5 },
390
+ hover: { stroke: "#f8fafc", width: 1.5 },
391
+ selected: { stroke: "#60a5fa", width: 2 },
392
+ focus: { ring: "#93c5fd", width: 2 },
393
+ dim: { opacity: 0.4 },
394
+ bubble: { fill: "#60a5fa", stroke: "#0f172a", opacity: 0.8 },
395
+ font: { color: "#e2e8f0" },
396
+ tooltip: {
397
+ background: "#f8fafc",
398
+ color: "#0f172a",
399
+ border: "#cbd5e1",
400
+ radius: 4,
401
+ shadow: "0 4px 12px rgb(0 0 0 / 0.4)"
402
+ },
403
+ controls: { background: "#1e293b", color: "#e2e8f0", border: "#334155", radius: 6 }
404
+ };
405
+ var minimal = {
406
+ background: "transparent",
407
+ empty: { fill: "#eeeeee" },
408
+ context: { fill: "#f3f3f3", border: "#ffffff" },
409
+ border: { color: "#ffffff", width: 0.25 },
410
+ hover: { stroke: "#444444", width: 1 },
411
+ selected: { stroke: "#111111", width: 1.5 },
412
+ focus: { ring: "#111111", width: 2 },
413
+ dim: { opacity: 0.5 },
414
+ bubble: { fill: "#111111", stroke: "#ffffff", opacity: 0.6 },
415
+ font: { color: "#333333" },
416
+ tooltip: {
417
+ background: "#ffffff",
418
+ color: "#222222",
419
+ border: "transparent",
420
+ radius: 2,
421
+ shadow: "0 1px 4px rgb(0 0 0 / 0.18)"
422
+ },
423
+ controls: { background: "#ffffff", color: "#333333", border: "transparent", radius: 2 }
424
+ };
425
+ var contrast = {
426
+ background: "#ffffff",
427
+ empty: { fill: "#bdbdbd", pattern: "hatch" },
428
+ context: { fill: "#e0e0e0", border: "#000000" },
429
+ border: { color: "#000000", width: 1 },
430
+ hover: { stroke: "#000000", width: 3 },
431
+ selected: { stroke: "#0033cc", width: 4 },
432
+ focus: { ring: "#000000", width: 4 },
433
+ dim: { opacity: 0.35 },
434
+ bubble: { fill: "#003399", stroke: "#000000", opacity: 0.85 },
435
+ font: { color: "#000000", size: 14 },
436
+ tooltip: {
437
+ background: "#000000",
438
+ color: "#ffffff",
439
+ border: "#ffffff",
440
+ radius: 0,
441
+ shadow: "none"
442
+ },
443
+ controls: { background: "#ffffff", color: "#000000", border: "#000000", radius: 0 }
444
+ };
445
+ var THEMES = {
446
+ light,
447
+ dark,
448
+ minimal,
449
+ contrast
450
+ };
451
+ var isThemeName = (value) => typeof value === "string" && Object.hasOwn(THEMES, value);
452
+ var resolveTheme = (theme) => isThemeName(theme) ? THEMES[theme] : theme;
453
+ var extendTheme = (base, overrides) => {
454
+ const from = resolveTheme(base) ?? {};
455
+ const merged = { ...from };
456
+ for (const [key, value] of Object.entries(overrides)) {
457
+ if (value === void 0) continue;
458
+ const previous = merged[key];
459
+ merged[key] = typeof value === "object" && value !== null && typeof previous === "object" ? { ...previous, ...value } : value;
460
+ }
461
+ return merged;
462
+ };
463
+ var px = (value) => `${value}px`;
464
+ var themeToCssVars = (theme) => {
465
+ const vars = {};
466
+ if (theme === void 0) return vars;
467
+ const set = (name, value, unit) => {
468
+ if (value === void 0) return;
469
+ vars[`--cm-${name}`] = typeof value === "number" && unit !== void 0 ? unit(value) : `${value}`;
470
+ };
471
+ set("background", theme.background);
472
+ set("empty-fill", theme.empty?.fill);
473
+ set("context-fill", theme.context?.fill);
474
+ set("context-border-color", theme.context?.border);
475
+ set("border-color", theme.border?.color);
476
+ set("border-width", theme.border?.width, px);
477
+ set("hover-stroke", theme.hover?.stroke);
478
+ set("hover-stroke-width", theme.hover?.width, px);
479
+ set("selected-stroke", theme.selected?.stroke);
480
+ set("selected-stroke-width", theme.selected?.width, px);
481
+ set("focus-ring", theme.focus?.ring);
482
+ set("focus-ring-width", theme.focus?.width, px);
483
+ set("dim-opacity", theme.dim?.opacity);
484
+ set("bubble-fill", theme.bubble?.fill);
485
+ set("bubble-stroke", theme.bubble?.stroke);
486
+ set("bubble-opacity", theme.bubble?.opacity);
487
+ set("font-family", theme.font?.family);
488
+ set("font-size", theme.font?.size, px);
489
+ set("label-color", theme.font?.color);
490
+ set("tooltip-bg", theme.tooltip?.background);
491
+ set("tooltip-color", theme.tooltip?.color);
492
+ set("tooltip-border", theme.tooltip?.border);
493
+ set("tooltip-radius", theme.tooltip?.radius, px);
494
+ set("tooltip-shadow", theme.tooltip?.shadow);
495
+ set("control-bg", theme.controls?.background);
496
+ set("control-color", theme.controls?.color);
497
+ set("control-border", theme.controls?.border);
498
+ set("control-radius", theme.controls?.radius, px);
499
+ return vars;
500
+ };
501
+
502
+ // src/core/labels.ts
503
+ var en = {
504
+ noData: "No data",
505
+ geographyError: "The map could not be loaded.",
506
+ zoomIn: "Zoom in",
507
+ zoomOut: "Zoom out",
508
+ resetView: "Reset view",
509
+ gestureHintWheel: "Use Ctrl + scroll to zoom",
510
+ gestureHintWheelMac: "Use \u2318 + scroll to zoom",
511
+ gestureHintTouch: "Use two fingers to move the map",
512
+ breadcrumb: "Breadcrumb",
513
+ breadcrumbRoot: "All",
514
+ drillUp: "Up one level",
515
+ drillHint: "Click to see regions",
516
+ tapAgainHint: "Tap again to enter"
517
+ };
518
+ var es = {
519
+ noData: "Sin dato",
520
+ geographyError: "No se pudo cargar el mapa.",
521
+ zoomIn: "Acercar",
522
+ zoomOut: "Alejar",
523
+ resetView: "Restablecer vista",
524
+ gestureHintWheel: "Usa Ctrl + rueda para hacer zoom",
525
+ gestureHintWheelMac: "Usa \u2318 + rueda para hacer zoom",
526
+ gestureHintTouch: "Usa dos dedos para mover el mapa",
527
+ breadcrumb: "Ruta de navegaci\xF3n",
528
+ breadcrumbRoot: "Todo",
529
+ drillUp: "Subir un nivel",
530
+ drillHint: "Clic para ver regiones",
531
+ tapAgainHint: "Toca de nuevo para entrar"
532
+ };
533
+ var resolveLabels = (labels) => ({
534
+ ...en,
535
+ ...labels
536
+ });
537
+
538
+ // src/core/join.ts
539
+ var defaultGetFeatureId = (feature2) => feature2.id === void 0 ? void 0 : String(feature2.id);
540
+ var joinData = ({
541
+ features,
542
+ data,
543
+ getId,
544
+ getFeatureId = defaultGetFeatureId
545
+ }) => {
546
+ const featureIds = /* @__PURE__ */ new Set();
547
+ for (const feature2 of features) {
548
+ const id = getFeatureId(feature2);
549
+ if (id !== void 0) featureIds.add(id);
550
+ }
551
+ const dataById = /* @__PURE__ */ new Map();
552
+ const duplicates = /* @__PURE__ */ new Set();
553
+ for (const datum of data) {
554
+ const id = getId(datum);
555
+ if (dataById.has(id)) duplicates.add(id);
556
+ else dataById.set(id, datum);
557
+ }
558
+ const joined = /* @__PURE__ */ new Map();
559
+ const unmatchedData = [];
560
+ for (const [id, datum] of dataById) {
561
+ if (featureIds.has(id)) joined.set(id, datum);
562
+ else unmatchedData.push(id);
563
+ }
564
+ const featuresWithoutData = [...featureIds].filter((id) => !dataById.has(id));
565
+ return { joined, unmatchedData, featuresWithoutData, duplicateDataIds: [...duplicates] };
566
+ };
567
+
568
+ // src/core/classify.ts
569
+ import { scaleQuantile, scaleQuantize } from "d3-scale";
570
+ var DEFAULT_CLASSES = 5;
571
+ var finiteValues = (values) => values.filter((v) => typeof v === "number" && Number.isFinite(v));
572
+ var assertValidClasses = (classes) => {
573
+ if (!Number.isInteger(classes) || classes < 1) {
574
+ throw new Error(
575
+ `[choropleth] classify: "classes" must be an integer \u2265 1 (received: ${classes}).`
576
+ );
577
+ }
578
+ };
579
+ var computeThresholds = ({
580
+ values,
581
+ classification,
582
+ domain
583
+ }) => {
584
+ switch (classification.method) {
585
+ case "linear":
586
+ return [];
587
+ case "threshold": {
588
+ const { thresholds } = classification;
589
+ const ascending = thresholds.every(
590
+ (t, i) => Number.isFinite(t) && (i === 0 || t > (thresholds[i - 1] ?? t))
591
+ );
592
+ if (!ascending) {
593
+ throw new Error(
594
+ `[choropleth] classify: "thresholds" must be a list of finite numbers in strictly ascending order (received: [${thresholds.join(", ")}]).`
595
+ );
596
+ }
597
+ return [...thresholds];
598
+ }
599
+ case "quantize": {
600
+ const classes = classification.classes ?? DEFAULT_CLASSES;
601
+ assertValidClasses(classes);
602
+ return scaleQuantize().domain([...domain]).range(Array.from({ length: classes }, (_, i) => i)).thresholds();
603
+ }
604
+ case "quantile": {
605
+ const classes = classification.classes ?? DEFAULT_CLASSES;
606
+ assertValidClasses(classes);
607
+ if (values.length === 0) return [];
608
+ return scaleQuantile().domain([...values]).range(Array.from({ length: classes }, (_, i) => i)).quantiles();
609
+ }
610
+ }
611
+ };
612
+
613
+ // src/core/scales.ts
614
+ import { scaleDiverging, scaleSequential, scaleThreshold } from "d3-scale";
615
+
616
+ // src/core/palettes.ts
617
+ import {
618
+ interpolateBlues,
619
+ interpolateBrBG,
620
+ interpolateGreens,
621
+ interpolateGreys,
622
+ interpolateOranges,
623
+ interpolatePiYG,
624
+ interpolatePRGn,
625
+ interpolatePuOr,
626
+ interpolatePurples,
627
+ interpolateRdBu,
628
+ interpolateRdYlBu,
629
+ interpolateRdYlGn,
630
+ interpolateReds,
631
+ interpolateSpectral,
632
+ interpolateViridis,
633
+ schemeAccent,
634
+ schemeDark2,
635
+ schemePaired,
636
+ schemePastel1,
637
+ schemeSet2,
638
+ schemeSet3,
639
+ schemeTableau10
640
+ } from "d3-scale-chromatic";
641
+ var SEQUENTIAL_PALETTES = {
642
+ blues: interpolateBlues,
643
+ greens: interpolateGreens,
644
+ greys: interpolateGreys,
645
+ oranges: interpolateOranges,
646
+ purples: interpolatePurples,
647
+ reds: interpolateReds,
648
+ viridis: interpolateViridis
649
+ };
650
+ var DIVERGING_PALETTES = {
651
+ rdbu: interpolateRdBu,
652
+ brbg: interpolateBrBG,
653
+ piyg: interpolatePiYG,
654
+ prgn: interpolatePRGn,
655
+ puor: interpolatePuOr,
656
+ rdylbu: interpolateRdYlBu,
657
+ rdylgn: interpolateRdYlGn,
658
+ spectral: interpolateSpectral
659
+ };
660
+ var DEFAULT_SEQUENTIAL_PALETTE = "blues";
661
+ var DEFAULT_DIVERGING_PALETTE = "rdbu";
662
+ var SEQUENTIAL_START = 0.15;
663
+ var sampleSequentialColors = ({
664
+ interpolate,
665
+ classes
666
+ }) => Array.from(
667
+ { length: classes },
668
+ (_, i) => (
669
+ // With a single class there is no "from less to more": a mid tone is used, not the light extreme.
670
+ interpolate(
671
+ classes === 1 ? 0.6 : SEQUENTIAL_START + (1 - SEQUENTIAL_START) * i / (classes - 1)
672
+ )
673
+ )
674
+ );
675
+ var sampleDivergingColors = ({
676
+ interpolate,
677
+ classes
678
+ }) => (
679
+ // Center of each band: with 5 classes t = 0.1, 0.3, 0.5, 0.7, 0.9. With an odd number the middle
680
+ // class falls exactly at t = 0.5, the palette's neutral color, which is the one that must
681
+ // represent the midpoint. That is why the diverging one does not use SEQUENTIAL_START: its light
682
+ // end is in the center, and that is intentional.
683
+ Array.from({ length: classes }, (_, i) => interpolate((i + 0.5) / classes))
684
+ );
685
+ var CATEGORICAL_PALETTES = {
686
+ tableau10: schemeTableau10,
687
+ set2: schemeSet2,
688
+ set3: schemeSet3,
689
+ accent: schemeAccent,
690
+ dark2: schemeDark2,
691
+ paired: schemePaired,
692
+ pastel1: schemePastel1
693
+ };
694
+ var DEFAULT_CATEGORICAL_PALETTE = "tableau10";
695
+
696
+ // src/core/scales.ts
697
+ var DEFAULT_EMPTY_FILL = "#d4d4d4";
698
+ var extent = (values) => {
699
+ let min = Infinity;
700
+ let max = -Infinity;
701
+ for (const v of values) {
702
+ if (v < min) min = v;
703
+ if (v > max) max = v;
704
+ }
705
+ return values.length === 0 ? [0, 1] : [min, max];
706
+ };
707
+ var createColorScale = (options) => {
708
+ const emptyFill = options.emptyFill ?? DEFAULT_EMPTY_FILL;
709
+ const values = finiteValues(options.values);
710
+ const midpoint = options.variant === "diverging" ? options.midpoint ?? 0 : 0;
711
+ const [min, max] = extent(values);
712
+ let domain = [min, max];
713
+ if (options.variant === "diverging") {
714
+ const spread = Math.max(Math.abs(min - midpoint), Math.abs(max - midpoint)) || 1;
715
+ domain = [midpoint - spread, midpoint + spread];
716
+ }
717
+ const classification = options.classification ?? (options.variant === "diverging" ? { method: "quantize", classes: DEFAULT_CLASSES } : { method: "quantile", classes: DEFAULT_CLASSES });
718
+ const thresholds = computeThresholds({ values, classification, domain });
719
+ const interpolate = options.variant === "diverging" ? DIVERGING_PALETTES[options.palette ?? DEFAULT_DIVERGING_PALETTE] : SEQUENTIAL_PALETTES[options.palette ?? DEFAULT_SEQUENTIAL_PALETTE];
720
+ const isUsable2 = (v) => typeof v === "number" && Number.isFinite(v);
721
+ if (classification.method === "linear") {
722
+ const continuous = options.variant === "diverging" ? scaleDiverging(interpolate).domain([domain[0], midpoint, domain[1]]).clamp(true) : scaleSequential(interpolate).domain(domain).clamp(true);
723
+ return {
724
+ getColor: (value) => isUsable2(value) ? continuous(value) : emptyFill,
725
+ kind: "continuous",
726
+ domain,
727
+ thresholds: [],
728
+ colors: [],
729
+ emptyFill
730
+ };
731
+ }
732
+ const classes = thresholds.length + 1;
733
+ const colors = options.variant === "diverging" ? sampleDivergingColors({ interpolate, classes }) : sampleSequentialColors({ interpolate, classes });
734
+ const classed = scaleThreshold().domain(thresholds).range(colors);
735
+ return {
736
+ getColor: (value) => isUsable2(value) ? classed(value) : emptyFill,
737
+ kind: "classed",
738
+ domain,
739
+ thresholds,
740
+ colors,
741
+ emptyFill
742
+ };
743
+ };
744
+
745
+ // src/core/projection.ts
746
+ import {
747
+ geoAlbers,
748
+ geoPath,
749
+ geoEqualEarth,
750
+ geoMercator,
751
+ geoNaturalEarth1,
752
+ geoOrthographic
753
+ } from "d3-geo";
754
+ var PROJECTIONS = {
755
+ // Equal areas: each country takes up the area that belongs to it. Recommended for the world.
756
+ equalEarth: geoEqualEarth,
757
+ // Compromise projection, pleasant to the eye; distorts areas somewhat.
758
+ naturalEarth: geoNaturalEarth1,
759
+ // Inflates polar areas (Greenland ≈ Africa). Useful for street maps, not for world choropleths:
760
+ // the eye associates more painted area with more importance.
761
+ mercator: geoMercator,
762
+ // Conic for the US (with Alaska and Hawaii repositioned). Looks bad over the whole world.
763
+ albers: geoAlbers,
764
+ // Globe view: only one hemisphere is visible.
765
+ orthographic: geoOrthographic
766
+ };
767
+ var projectionFactory = (name = DEFAULT_PROJECTION) => PROJECTIONS[name];
768
+ var DEFAULT_PROJECTION = "equalEarth";
769
+ var createProjection = ({
770
+ name = DEFAULT_PROJECTION,
771
+ width,
772
+ height,
773
+ featureCollection,
774
+ rotate
775
+ }) => {
776
+ if (!(Number.isFinite(width) && width > 0 && Number.isFinite(height) && height > 0)) {
777
+ throw new Error(
778
+ `[choropleth] createProjection: width and height must be finite numbers > 0 (received: ${width} \xD7 ${height}).`
779
+ );
780
+ }
781
+ const projection = PROJECTIONS[name]();
782
+ if (rotate !== void 0) projection.rotate([rotate[0], rotate[1]]);
783
+ if (featureCollection.features.length === 0) return projection;
784
+ return projection.fitSize([width, height], featureCollection);
785
+ };
786
+ var DEFAULT_ASPECT_RATIO = 960 / 500;
787
+ var MIN_ASPECT_RATIO = 0.2;
788
+ var MAX_ASPECT_RATIO = 5;
789
+ var computeAspectRatio = ({
790
+ name = DEFAULT_PROJECTION,
791
+ featureCollection,
792
+ rotate
793
+ }) => {
794
+ if (featureCollection.features.length === 0) return DEFAULT_ASPECT_RATIO;
795
+ const base = PROJECTIONS[name]();
796
+ if (rotate !== void 0) base.rotate([rotate[0], rotate[1]]);
797
+ const projection = base.fitWidth(1e3, featureCollection);
798
+ const [[x0, y0], [x1, y1]] = geoPath(projection).bounds(featureCollection);
799
+ const ratio = (x1 - x0) / (y1 - y0);
800
+ if (!Number.isFinite(ratio) || ratio <= 0) return DEFAULT_ASPECT_RATIO;
801
+ return Math.min(MAX_ASPECT_RATIO, Math.max(MIN_ASPECT_RATIO, ratio));
802
+ };
803
+ var relativeTransform = (from, to) => {
804
+ const k = to.scale() / from.scale();
805
+ const [fx, fy] = from.translate();
806
+ const [tx, ty] = to.translate();
807
+ return { k, x: tx - k * fx, y: ty - k * fy };
808
+ };
809
+ var rebaseProjection = ({
810
+ parent,
811
+ factory,
812
+ focus,
813
+ width,
814
+ height,
815
+ padding
816
+ }) => {
817
+ if (!(Number.isFinite(width) && width > 0 && Number.isFinite(height) && height > 0)) {
818
+ throw new Error(
819
+ `[choropleth] rebaseProjection: width and height must be finite numbers > 0 (received: ${width} \xD7 ${height}).`
820
+ );
821
+ }
822
+ const child = copyShape(factory(), parent);
823
+ child.fitExtent(
824
+ [
825
+ [padding.left, padding.top],
826
+ [width - padding.right, height - padding.bottom]
827
+ ],
828
+ focus
829
+ );
830
+ if (!(child.scale() > 0) || !Number.isFinite(child.scale())) {
831
+ throw new Error(
832
+ "[choropleth] rebaseProjection: the focus geometry has no extent (empty or a single point), so it cannot be fitted."
833
+ );
834
+ }
835
+ return { projection: child, relative: relativeTransform(parent, child) };
836
+ };
837
+ var copyShape = (child, parent) => {
838
+ child.rotate(parent.rotate()).center(parent.center());
839
+ child.angle(parent.angle()).reflectX(parent.reflectX()).reflectY(parent.reflectY());
840
+ child.precision(parent.precision());
841
+ const clipAngle = parent.clipAngle();
842
+ if (clipAngle !== null) child.clipAngle(clipAngle);
843
+ const conic = parent;
844
+ const target = child;
845
+ if (conic.parallels !== void 0 && target.parallels !== void 0) {
846
+ target.parallels(conic.parallels());
847
+ }
848
+ return child;
849
+ };
850
+
851
+ // src/core/legend.ts
852
+ var defaultFormatValue = (value) => Number.isInteger(value) ? String(value) : String(Number(value.toFixed(2)));
853
+ var classIndex = (thresholds, value) => {
854
+ let lo = 0;
855
+ let hi = thresholds.length;
856
+ while (lo < hi) {
857
+ const mid = lo + hi >> 1;
858
+ if (thresholds[mid] <= value) lo = mid + 1;
859
+ else hi = mid;
860
+ }
861
+ return lo;
862
+ };
863
+ var buildLegend = (options) => {
864
+ const { scale, values, emptyLabel } = options;
865
+ const format = options.formatValue ?? defaultFormatValue;
866
+ if (scale.kind === "continuous") return [];
867
+ const counts = Array.from({ length: scale.colors.length }, () => 0);
868
+ let empty = 0;
869
+ for (const v of values) {
870
+ if (typeof v !== "number" || !Number.isFinite(v)) empty += 1;
871
+ else
872
+ counts[classIndex(scale.thresholds, v)] = (counts[classIndex(scale.thresholds, v)] ?? 0) + 1;
873
+ }
874
+ const items = scale.colors.map((color, i) => {
875
+ const from = i === 0 ? scale.domain[0] : scale.thresholds[i - 1];
876
+ const to = i === scale.colors.length - 1 ? scale.domain[1] : scale.thresholds[i];
877
+ return { color, from, to, label: `${format(from)} \u2013 ${format(to)}`, count: counts[i] ?? 0 };
878
+ });
879
+ if (emptyLabel !== void 0) {
880
+ items.push({ color: scale.emptyFill, label: emptyLabel, count: empty, empty: true });
881
+ }
882
+ return items;
883
+ };
884
+
885
+ // src/core/borders.ts
886
+ import { feature as toFeature, mesh } from "topojson-client";
887
+ var createBorders = ({
888
+ geography,
889
+ objectName,
890
+ filterFeatures
891
+ }) => {
892
+ if (geography.type !== "Topology") return null;
893
+ const topology = geography;
894
+ const name = objectName ?? Object.keys(topology.objects)[0];
895
+ const object = name === void 0 ? void 0 : topology.objects[name];
896
+ if (object === void 0) return null;
897
+ if (filterFeatures === void 0) {
898
+ return mesh(topology, object, (a, b) => a !== b);
899
+ }
900
+ const kept = /* @__PURE__ */ new Map();
901
+ const keep = (geometry) => {
902
+ let result = kept.get(geometry);
903
+ if (result === void 0) {
904
+ result = filterFeatures(toFeature(topology, geometry));
905
+ kept.set(geometry, result);
906
+ }
907
+ return result;
908
+ };
909
+ return mesh(
910
+ topology,
911
+ object,
912
+ (a, b) => a !== b && keep(a) && keep(b)
913
+ );
914
+ };
915
+
916
+ // src/core/diagnostics.ts
917
+ var MAX_LISTED = 8;
918
+ var list = (ids) => {
919
+ const shown = ids.slice(0, MAX_LISTED).map((id) => JSON.stringify(id));
920
+ const rest = ids.length - shown.length;
921
+ return rest > 0 ? `${shown.join(", ")} and ${rest} more` : shown.join(", ");
922
+ };
923
+ var styleOf = (id) => {
924
+ if (/^\d+$/.test(id)) return "numeric";
925
+ if (/^[A-Za-z]{2}$/.test(id)) return "alpha-2";
926
+ if (/^[A-Za-z]{3}$/.test(id)) return "alpha-3";
927
+ return "other";
928
+ };
929
+ var commonStyle = (ids) => {
930
+ const first = ids[0];
931
+ if (first === void 0) return null;
932
+ const style = styleOf(first);
933
+ return style !== "other" && ids.every((id) => styleOf(id) === style) ? style : null;
934
+ };
935
+ var STYLE_NAMES = {
936
+ numeric: 'ISO 3166-1 numeric (e.g. "724")',
937
+ "alpha-2": 'ISO 3166-1 alpha-2 (e.g. "ES")',
938
+ "alpha-3": 'ISO 3166-1 alpha-3 (e.g. "ESP")',
939
+ other: "something else"
940
+ };
941
+ var hintFor = (unmatched, featuresWithoutData) => {
942
+ const features = new Set(featuresWithoutData);
943
+ const padded = unmatched.find((id) => /^\d{1,2}$/.test(id) && features.has(id.padStart(3, "0")));
944
+ if (padded !== void 0) {
945
+ return `Hint: ${JSON.stringify(padded)} does not match ${JSON.stringify(padded.padStart(3, "0"))}. Leading zeros matter (a spreadsheet may have dropped them).`;
946
+ }
947
+ const upper = new Set(featuresWithoutData.map((id) => id.toUpperCase()));
948
+ const lowered = unmatched.find((id) => id !== id.toUpperCase() && upper.has(id.toUpperCase()));
949
+ if (lowered !== void 0) {
950
+ return `Hint: ids are case-sensitive; ${JSON.stringify(lowered)} would match ${JSON.stringify(lowered.toUpperCase())}.`;
951
+ }
952
+ const dataStyle = commonStyle(unmatched);
953
+ const geometryStyle = commonStyle(featuresWithoutData);
954
+ if (dataStyle !== null && geometryStyle !== null && dataStyle !== geometryStyle) {
955
+ return `Hint: your data ids look like ${STYLE_NAMES[dataStyle]} but the geometry ids look like ${STYLE_NAMES[geometryStyle]}. Convert one of them, or use \`getFeatureId\` to read another property of the geometry.`;
956
+ }
957
+ return null;
958
+ };
959
+ var formatJoinDiagnostics = ({
960
+ unmatchedData,
961
+ featuresWithoutData,
962
+ duplicateDataIds,
963
+ dataCount
964
+ }) => {
965
+ if (dataCount === 0) return null;
966
+ const lines = [];
967
+ if (unmatchedData.length > 0) {
968
+ lines.push(
969
+ `${unmatchedData.length} datum(s) have no matching geometry: ${list(unmatchedData)}.`
970
+ );
971
+ const hint = hintFor(unmatchedData, featuresWithoutData);
972
+ if (hint !== null) lines.push(hint);
973
+ }
974
+ if (duplicateDataIds.length > 0) {
975
+ lines.push(
976
+ `${duplicateDataIds.length} id(s) appear more than once in \`data\` (only the first row of each is used): ${list(duplicateDataIds)}.`
977
+ );
978
+ }
979
+ if (featuresWithoutData.length > 0) {
980
+ lines.push(`${featuresWithoutData.length} region(s) have no data and will use \`emptyFill\`.`);
981
+ }
982
+ return lines.length === 0 ? null : `[choropleth] ${lines.join("\n ")}`;
983
+ };
984
+
985
+ // src/core/categories.ts
986
+ var createCategoricalScale = ({
987
+ values,
988
+ categories,
989
+ palette = DEFAULT_CATEGORICAL_PALETTE,
990
+ emptyFill
991
+ }) => {
992
+ const colors = CATEGORICAL_PALETTES[palette];
993
+ const specs = categories ?? [...new Set(values.filter((v) => typeof v === "string"))].sort((a, b) => a.localeCompare(b)).map((id) => ({ id }));
994
+ const resolved = specs.map((spec, index) => ({
995
+ id: spec.id,
996
+ label: spec.label ?? spec.id,
997
+ // `as string`: the modulo never gives undefined because `colors` has length ≥ 1.
998
+ color: spec.color ?? colors[index % colors.length]
999
+ }));
1000
+ const byId = new Map(resolved.map((c) => [c.id, c]));
1001
+ return {
1002
+ getColor: (category) => category == null ? emptyFill : byId.get(category)?.color ?? emptyFill,
1003
+ getLabel: (category) => category == null ? "" : byId.get(category)?.label ?? category,
1004
+ categories: resolved,
1005
+ emptyFill
1006
+ };
1007
+ };
1008
+ var buildCategoricalLegend = ({
1009
+ scale,
1010
+ values,
1011
+ emptyLabel
1012
+ }) => {
1013
+ const counts = /* @__PURE__ */ new Map();
1014
+ let empty = 0;
1015
+ for (const v of values) {
1016
+ if (v == null || !scale.categories.some((c) => c.id === v)) empty += 1;
1017
+ else counts.set(v, (counts.get(v) ?? 0) + 1);
1018
+ }
1019
+ const items = scale.categories.map((c) => ({
1020
+ color: c.color,
1021
+ label: c.label,
1022
+ count: counts.get(c.id) ?? 0
1023
+ }));
1024
+ if (emptyLabel !== void 0)
1025
+ items.push({ color: scale.emptyFill, label: emptyLabel, count: empty, empty: true });
1026
+ return items;
1027
+ };
1028
+
1029
+ // src/core/bubbles.ts
1030
+ import { scaleSqrt } from "d3-scale";
1031
+ var DEFAULT_MAX_RADIUS = 24;
1032
+ var isPositive = (v) => typeof v === "number" && Number.isFinite(v) && v > 0;
1033
+ var createRadiusScale = ({
1034
+ values,
1035
+ maxRadius = DEFAULT_MAX_RADIUS
1036
+ }) => {
1037
+ let max = 0;
1038
+ for (const v of values) if (isPositive(v) && v > max) max = v;
1039
+ const scale = scaleSqrt().domain([0, max || 1]).range([0, maxRadius]).clamp(true);
1040
+ return { getRadius: (value) => max === 0 ? 0 : scale(value), max, maxRadius };
1041
+ };
1042
+ var buildSizeLegend = ({
1043
+ scale,
1044
+ formatValue = defaultFormatValue
1045
+ }) => {
1046
+ if (scale.max === 0) return [];
1047
+ return [0.25, 0.5, 1].map((fraction) => {
1048
+ const value = scale.max * fraction;
1049
+ return { value, radius: scale.getRadius(value), label: formatValue(value) };
1050
+ });
1051
+ };
1052
+
1053
+ // src/core/variants.ts
1054
+ var DEFAULT_BUBBLE_FILL = "#2563eb";
1055
+ var isUsable = (v) => typeof v === "number" && Number.isFinite(v);
1056
+ var resolveVariant = (options) => {
1057
+ const { config, entries, emptyFill, formatValue, emptyLabel } = options;
1058
+ const numeric = (get) => entries.map((e) => e.datum === void 0 ? null : get(e.datum));
1059
+ const formatted = (values2) => values2.map((v) => isUsable(v) ? formatValue(v) : "");
1060
+ if (config.variant === "categorical") {
1061
+ const values2 = entries.map((e) => e.datum === void 0 ? null : config.getCategory(e.datum));
1062
+ const scale2 = createCategoricalScale({
1063
+ values: values2,
1064
+ categories: config.categories,
1065
+ palette: config.palette,
1066
+ emptyFill
1067
+ });
1068
+ return {
1069
+ fills: values2.map((v) => scale2.getColor(v)),
1070
+ values: values2,
1071
+ labels: values2.map((v) => scale2.getLabel(v)),
1072
+ scale: null,
1073
+ legend: buildCategoricalLegend({ scale: scale2, values: values2, emptyLabel }),
1074
+ classes: values2.map((v) => {
1075
+ const index = v == null ? -1 : scale2.categories.findIndex((c) => c.id === v);
1076
+ return index < 0 ? null : index;
1077
+ }),
1078
+ bubbles: [],
1079
+ sizeLegend: []
1080
+ };
1081
+ }
1082
+ if (config.variant === "bubble") return resolveBubbles(options, config);
1083
+ const values = numeric(config.getValue);
1084
+ const scale = createColorScale({
1085
+ values,
1086
+ classification: config.classification,
1087
+ emptyFill,
1088
+ ...config.variant === "diverging" ? { variant: "diverging", palette: config.palette, midpoint: config.midpoint } : { variant: "sequential", palette: config.palette }
1089
+ });
1090
+ return {
1091
+ fills: values.map((v) => scale.getColor(v)),
1092
+ values,
1093
+ labels: formatted(values),
1094
+ scale,
1095
+ legend: buildLegend({ scale, values, formatValue, emptyLabel }),
1096
+ classes: values.map(
1097
+ (v) => isUsable(v) && scale.kind !== "continuous" ? classIndex(scale.thresholds, v) : null
1098
+ ),
1099
+ bubbles: [],
1100
+ sizeLegend: []
1101
+ };
1102
+ };
1103
+ var resolveBubbles = (options, config) => {
1104
+ const { entries, data, getId, centroids, project, emptyFill, formatValue, emptyLabel } = options;
1105
+ const values = entries.map((e) => e.datum === void 0 ? null : config.getValue(e.datum));
1106
+ const sources = [];
1107
+ if (config.getCoordinates !== void 0) {
1108
+ for (const datum of data) {
1109
+ const coordinates = config.getCoordinates(datum);
1110
+ const at = coordinates === null ? null : project(coordinates);
1111
+ if (coordinates !== null && at !== null) {
1112
+ sources.push({ id: getId(datum), datum, at, coordinates });
1113
+ }
1114
+ }
1115
+ } else {
1116
+ entries.forEach((entry, index) => {
1117
+ const at = centroids[index];
1118
+ if (entry.id !== void 0 && entry.datum !== void 0 && at != null) {
1119
+ sources.push({ id: entry.id, datum: entry.datum, at, coordinates: null });
1120
+ }
1121
+ });
1122
+ }
1123
+ const sized = sources.map((source) => ({ ...source, value: config.getValue(source.datum) })).filter((s) => isUsable(s.value) && s.value > 0);
1124
+ const radius = createRadiusScale({
1125
+ values: sized.map((s) => s.value),
1126
+ maxRadius: config.maxRadius ?? DEFAULT_MAX_RADIUS
1127
+ });
1128
+ const colorValues = sized.map(
1129
+ (s) => config.getColorValue ? config.getColorValue(s.datum) : null
1130
+ );
1131
+ const colorScale = config.getColorValue === void 0 ? null : createColorScale({
1132
+ variant: "diverging",
1133
+ values: colorValues,
1134
+ classification: config.classification,
1135
+ palette: config.palette,
1136
+ midpoint: config.midpoint,
1137
+ emptyFill
1138
+ });
1139
+ const bubbles = sized.map((s, i) => ({
1140
+ id: s.id,
1141
+ x: s.at[0],
1142
+ y: s.at[1],
1143
+ r: radius.getRadius(s.value),
1144
+ fill: colorScale === null ? config.color ?? DEFAULT_BUBBLE_FILL : colorScale.getColor(colorValues[i]),
1145
+ value: s.value,
1146
+ colorValue: colorValues[i] ?? null,
1147
+ datum: s.datum,
1148
+ coordinates: s.coordinates
1149
+ })).sort((a, b) => b.r - a.r);
1150
+ return {
1151
+ fills: entries.map(() => emptyFill),
1152
+ values,
1153
+ labels: values.map((v) => isUsable(v) ? formatValue(v) : ""),
1154
+ scale: colorScale,
1155
+ legend: colorScale === null ? [] : buildLegend({ scale: colorScale, values: colorValues, formatValue, emptyLabel }),
1156
+ // The bubbles carry the color, not the regions: there is no per-region class here.
1157
+ classes: entries.map(() => null),
1158
+ bubbles,
1159
+ sizeLegend: buildSizeLegend({ scale: radius, formatValue })
1160
+ };
1161
+ };
1162
+
1163
+ // src/core/zoom.ts
1164
+ var DEFAULT_FOCUS_BOUNDS = {
1165
+ ES: [
1166
+ [-18.5, 27.5],
1167
+ [4.5, 44]
1168
+ ]
1169
+ };
1170
+ var DEFAULT_ZOOM_MIN = 1;
1171
+ var DEFAULT_ZOOM_MAX = 12;
1172
+ var resolveZoomOptions = (zoom, { clickIsBusy }) => {
1173
+ if (zoom === false) return null;
1174
+ const options = zoom === true || zoom === void 0 ? {} : zoom;
1175
+ const { min = DEFAULT_ZOOM_MIN, max = DEFAULT_ZOOM_MAX } = options;
1176
+ if (!(min > 0) || !Number.isFinite(max) || max < min) {
1177
+ throw new Error(
1178
+ `[choropleth] zoom: "min" must be > 0 and "max" must be finite and \u2265 "min" (received: min = ${min}, max = ${max}).`
1179
+ );
1180
+ }
1181
+ const { doubleClick = "auto" } = options;
1182
+ return {
1183
+ min,
1184
+ max,
1185
+ wheel: options.wheel ?? "always",
1186
+ pinch: options.pinch ?? true,
1187
+ pan: options.pan ?? true,
1188
+ doubleClick: doubleClick === "auto" ? !clickIsBusy : doubleClick,
1189
+ constrain: options.constrain ?? "contain",
1190
+ bubbleScaling: options.bubbleScaling ?? "sqrt",
1191
+ inertia: options.inertia ?? true,
1192
+ keyboard: options.keyboard ?? true,
1193
+ padding: options.padding ?? 24,
1194
+ initialView: options.initialView
1195
+ };
1196
+ };
1197
+ var resolveControls = (zoom) => {
1198
+ if (typeof zoom !== "object" || zoom.controls === void 0 || zoom.controls === false) {
1199
+ return null;
1200
+ }
1201
+ const options = zoom.controls === true ? {} : zoom.controls;
1202
+ return { position: options.position ?? "bottom-right", reset: options.reset ?? true };
1203
+ };
1204
+ var zoomKeyAction = (event) => {
1205
+ if (event.ctrlKey === true || event.metaKey === true || event.altKey === true) return null;
1206
+ switch (event.key) {
1207
+ case "+":
1208
+ case "=":
1209
+ return "in";
1210
+ case "-":
1211
+ case "_":
1212
+ return "out";
1213
+ case "0":
1214
+ return "reset";
1215
+ default:
1216
+ return null;
1217
+ }
1218
+ };
1219
+ var createZoomFilter = ({ wheel, pinch, pan, doubleClick, onGestureHint }) => (event) => {
1220
+ switch (event.type) {
1221
+ case "wheel": {
1222
+ if (wheel === "never") return false;
1223
+ if (wheel === "always" || event.ctrlKey === true || event.metaKey === true) return true;
1224
+ onGestureHint?.("wheel");
1225
+ return false;
1226
+ }
1227
+ case "touchstart": {
1228
+ const multi = (event.touches?.length ?? 0) >= 2;
1229
+ if (multi) return pinch || pan;
1230
+ if (wheel === "cooperative") {
1231
+ onGestureHint?.("touch");
1232
+ return false;
1233
+ }
1234
+ return pan;
1235
+ }
1236
+ case "dblclick":
1237
+ return doubleClick;
1238
+ case "mousedown":
1239
+ return pan && !event.button;
1240
+ // primary button only
1241
+ default:
1242
+ return !event.button;
1243
+ }
1244
+ };
1245
+ var clamp = (value, [min, max]) => Math.min(max, Math.max(min, value));
1246
+ var resolveZoomTarget = ({
1247
+ target,
1248
+ size,
1249
+ padding,
1250
+ scaleExtent,
1251
+ project,
1252
+ getRegionExtent,
1253
+ focusBounds
1254
+ }) => {
1255
+ if (typeof target === "string") {
1256
+ const override = focusBounds?.[target];
1257
+ const extent2 = override ? projectBounds(override, project) : getRegionExtent(target);
1258
+ return extent2 === null ? null : boundsToTransform({ bounds: extent2, size, padding, scaleExtent });
1259
+ }
1260
+ if ("bounds" in target) {
1261
+ const extent2 = projectBounds(target.bounds, project);
1262
+ return extent2 === null ? null : boundsToTransform({ bounds: extent2, size, padding, scaleExtent });
1263
+ }
1264
+ const at = project([target.center[0], target.center[1]]);
1265
+ if (at === null || !Number.isFinite(target.zoom)) return null;
1266
+ const k = clamp(target.zoom, scaleExtent);
1267
+ return { k, x: size.width / 2 - k * at[0], y: size.height / 2 - k * at[1] };
1268
+ };
1269
+
1270
+ // src/core/drill.ts
1271
+ var layerKey = (path, depth = path.length) => JSON.stringify(path.slice(0, depth));
1272
+ var samePath = (a, b) => a.length === b.length && a.every((id, i) => id === b[i]);
1273
+ var startsWith = (path, prefix) => prefix.length <= path.length && prefix.every((id, i) => id === path[i]);
1274
+ var classifyDrill = (from, to) => {
1275
+ if (samePath(from, to)) return "equal";
1276
+ if (startsWith(from, to)) return "up";
1277
+ if (to.length === from.length + 1 && startsWith(to, from)) return "down";
1278
+ if (to.length === from.length && startsWith(to.slice(0, -1), from.slice(0, -1))) return "lateral";
1279
+ return "jump";
1280
+ };
1281
+ var settledLayers = (path) => Array.from({ length: path.length + 1 }, (_, depth) => ({
1282
+ key: layerKey(path, depth),
1283
+ depth,
1284
+ role: depth === path.length ? "active" : "context"
1285
+ }));
1286
+ var createDrillState = (path = []) => ({
1287
+ phase: "idle",
1288
+ path,
1289
+ settledPath: path,
1290
+ direction: null,
1291
+ layers: settledLayers(path),
1292
+ flight: "done",
1293
+ flightId: 0,
1294
+ geometry: null,
1295
+ geometryKey: null,
1296
+ savedCameras: {},
1297
+ returnCamera: null,
1298
+ error: null
1299
+ });
1300
+ var savedCameraFor = (state, path) => state.savedCameras[layerKey(path)] ?? null;
1301
+ var layersFor = (current, to, newRole) => {
1302
+ const existing = new Set(current.map((layer) => layer.key));
1303
+ const wanted = settledLayers(to).map(
1304
+ (layer) => !existing.has(layer.key) && layer.role === "active" ? { ...layer, role: newRole } : layer
1305
+ );
1306
+ const wantedKeys = new Set(wanted.map((layer) => layer.key));
1307
+ const leaving = current.filter((layer) => !wantedKeys.has(layer.key)).map((layer) => ({ ...layer, role: "exiting" }));
1308
+ return [...wanted, ...leaving].sort((a, b) => a.depth - b.depth);
1309
+ };
1310
+ var settleLayers = (layers) => layers.filter((layer) => layer.role !== "exiting").map((layer) => layer.role === "entering" ? { ...layer, role: "active" } : layer);
1311
+ var settle = (state) => state.phase === "revealing" || state.direction === "up" ? {
1312
+ ...state,
1313
+ phase: "idle",
1314
+ direction: null,
1315
+ settledPath: state.path,
1316
+ layers: settleLayers(state.layers),
1317
+ flight: "done",
1318
+ geometry: null,
1319
+ geometryKey: null,
1320
+ returnCamera: null
1321
+ } : state;
1322
+ var cancelled = (state) => ({
1323
+ ...state,
1324
+ phase: "idle",
1325
+ path: state.settledPath,
1326
+ direction: null,
1327
+ layers: settleLayers(state.layers),
1328
+ flight: "done",
1329
+ geometry: null,
1330
+ geometryKey: null,
1331
+ returnCamera: null
1332
+ });
1333
+ var flyBack = (state) => ({
1334
+ ...cancelled(state),
1335
+ phase: "flying",
1336
+ direction: "up",
1337
+ flight: "pending",
1338
+ flightId: state.flightId + 1,
1339
+ returnCamera: state.returnCamera
1340
+ });
1341
+ var pruneCameras = (cameras, path) => {
1342
+ const keep = new Set(Array.from({ length: path.length + 1 }, (_, d) => layerKey(path, d)));
1343
+ return Object.fromEntries(Object.entries(cameras).filter(([key]) => keep.has(key)));
1344
+ };
1345
+ var onDrill = (state, event) => {
1346
+ const start = settle(state);
1347
+ const { to } = event;
1348
+ const from = start.settledPath;
1349
+ const direction = event.direction === "jump" ? "jump" : classifyDrill(from, to);
1350
+ const base = { ...start, error: null };
1351
+ if (start.direction !== null && start.direction !== "up" && samePath(to, start.path))
1352
+ return state;
1353
+ const busy = start.direction !== null;
1354
+ if (direction === "equal") {
1355
+ return busy ? flyBack({ ...base, returnCamera: start.returnCamera }) : base;
1356
+ }
1357
+ if (direction === "up") {
1358
+ return {
1359
+ ...base,
1360
+ phase: "flying",
1361
+ path: to,
1362
+ settledPath: to,
1363
+ direction: "up",
1364
+ layers: layersFor(start.layers, to, "active"),
1365
+ flight: "pending",
1366
+ flightId: start.flightId + 1,
1367
+ geometry: null,
1368
+ geometryKey: null,
1369
+ savedCameras: pruneCameras(start.savedCameras, to),
1370
+ returnCamera: null
1371
+ };
1372
+ }
1373
+ const key = layerKey(to);
1374
+ const cached = event.cached === true;
1375
+ const geometry = cached ? "ready" : "pending";
1376
+ if (direction === "jump") {
1377
+ if (cached) {
1378
+ return {
1379
+ ...base,
1380
+ phase: "idle",
1381
+ path: to,
1382
+ settledPath: to,
1383
+ direction: null,
1384
+ layers: settledLayers(to),
1385
+ flight: "done",
1386
+ flightId: start.flightId + 1,
1387
+ geometry: null,
1388
+ geometryKey: null,
1389
+ savedCameras: pruneCameras(start.savedCameras, to),
1390
+ returnCamera: null
1391
+ };
1392
+ }
1393
+ return {
1394
+ ...base,
1395
+ phase: "loading",
1396
+ path: to,
1397
+ direction: "jump",
1398
+ flight: "done",
1399
+ flightId: start.flightId + 1,
1400
+ geometry: "pending",
1401
+ geometryKey: key,
1402
+ returnCamera: null
1403
+ };
1404
+ }
1405
+ const fresh = !busy;
1406
+ return {
1407
+ ...base,
1408
+ phase: "flying",
1409
+ path: to,
1410
+ direction,
1411
+ flight: "pending",
1412
+ flightId: start.flightId + 1,
1413
+ geometry,
1414
+ geometryKey: key,
1415
+ savedCameras: direction === "down" && fresh && event.camera !== void 0 ? { ...start.savedCameras, [layerKey(from)]: event.camera } : start.savedCameras,
1416
+ returnCamera: fresh ? event.camera ?? null : start.returnCamera
1417
+ };
1418
+ };
1419
+ var startReveal = (state) => ({
1420
+ ...state,
1421
+ phase: "revealing",
1422
+ layers: layersFor(state.layers, state.path, "entering"),
1423
+ flight: "done"
1424
+ });
1425
+ var finishJump = (state) => ({
1426
+ ...state,
1427
+ phase: "idle",
1428
+ settledPath: state.path,
1429
+ direction: null,
1430
+ layers: settledLayers(state.path),
1431
+ geometry: null,
1432
+ geometryKey: null,
1433
+ savedCameras: pruneCameras(state.savedCameras, state.path),
1434
+ returnCamera: null
1435
+ });
1436
+ var drillReducer = (state, event) => {
1437
+ switch (event.type) {
1438
+ case "DRILL":
1439
+ return onDrill(state, event);
1440
+ case "FLIGHT_END": {
1441
+ if (state.phase !== "flying" || event.id !== state.flightId) return state;
1442
+ if (state.direction === "up") return settle(state);
1443
+ if (!event.completed) return cancelled(state);
1444
+ if (state.geometry === "error") return flyBack(state);
1445
+ return state.geometry === "ready" ? startReveal(state) : { ...state, phase: "loading", flight: "done" };
1446
+ }
1447
+ case "GEOMETRY_READY": {
1448
+ if (event.key !== state.geometryKey || state.geometry !== "pending") return state;
1449
+ const ready = { ...state, geometry: "ready" };
1450
+ if (state.phase !== "loading") return ready;
1451
+ return state.direction === "jump" ? finishJump(ready) : startReveal(ready);
1452
+ }
1453
+ case "GEOMETRY_ERROR": {
1454
+ if (event.key !== state.geometryKey || state.geometry !== "pending") return state;
1455
+ const failed = { ...state, geometry: "error", error: event.key };
1456
+ if (state.phase === "flying") return failed;
1457
+ if (state.phase !== "loading") return state;
1458
+ return state.direction === "jump" ? cancelled(failed) : flyBack(failed);
1459
+ }
1460
+ case "REVEAL_END":
1461
+ return state.phase === "revealing" ? settle(state) : state;
1462
+ }
1463
+ };
1464
+
1465
+ // src/core/drill-levels.ts
1466
+ var contextOf = (path) => ({
1467
+ path,
1468
+ parentId: path.at(-1) ?? null,
1469
+ depth: path.length
1470
+ });
1471
+ var validateLevels = (levels) => {
1472
+ if (levels.length === 0) {
1473
+ throw new Error(
1474
+ "[choropleth] drill: at least one level is required (received an empty array)."
1475
+ );
1476
+ }
1477
+ const seen = /* @__PURE__ */ new Set();
1478
+ for (const level of levels) {
1479
+ if (seen.has(level.id)) {
1480
+ throw new Error(
1481
+ `[choropleth] drill: duplicate level id "${level.id}". Each level needs a unique id.`
1482
+ );
1483
+ }
1484
+ seen.add(level.id);
1485
+ }
1486
+ if (levels[0]?.geography === "inherit") {
1487
+ throw new Error(
1488
+ `[choropleth] drill: the first level ("${levels[0].id}") cannot use geography: "inherit" because it has no parent. Pass its geometry.`
1489
+ );
1490
+ }
1491
+ };
1492
+ var clampPath = (path, levelCount) => {
1493
+ const max = Math.max(0, levelCount - 1);
1494
+ return path.length <= max ? { path, clamped: false } : { path: path.slice(0, max), clamped: true };
1495
+ };
1496
+ var buildBreadcrumbs = ({
1497
+ path,
1498
+ rootLabel,
1499
+ getLabel
1500
+ }) => [
1501
+ { depth: 0, id: null, label: rootLabel },
1502
+ ...path.map((id, index) => ({
1503
+ depth: index + 1,
1504
+ id,
1505
+ label: getLabel?.({ id, depth: index + 1 }) ?? id
1506
+ }))
1507
+ ];
1508
+ var geographyKeyFor = (levels, path) => {
1509
+ for (let depth = Math.min(path.length, levels.length - 1); depth >= 0; depth--) {
1510
+ const level = levels[depth];
1511
+ if (level === void 0) continue;
1512
+ const ctx = contextOf(path.slice(0, depth));
1513
+ if (level.geographyKey !== void 0) return level.geographyKey(ctx);
1514
+ if (level.geography === "inherit" && depth > 0) continue;
1515
+ return typeof level.geography === "function" ? `${level.id}:${ctx.parentId}` : level.id;
1516
+ }
1517
+ return "";
1518
+ };
1519
+ var resolveDrillData = (data, ctx) => typeof data === "function" ? data(ctx) : data;
1520
+ var drillDirectionBetween = (from, to) => {
1521
+ const direction = classifyDrill(from, to);
1522
+ return direction === "equal" ? null : direction;
1523
+ };
1524
+ var DEFAULT_LEVEL_CACHE_SIZE = 8;
1525
+ var createLruCache = (capacity = DEFAULT_LEVEL_CACHE_SIZE) => {
1526
+ if (!(Number.isInteger(capacity) && capacity >= 1)) {
1527
+ throw new Error(
1528
+ `[choropleth] createLruCache: capacity must be an integer \u2265 1 (received: ${capacity}).`
1529
+ );
1530
+ }
1531
+ const entries = /* @__PURE__ */ new Map();
1532
+ return {
1533
+ get: (key) => {
1534
+ if (!entries.has(key)) return void 0;
1535
+ const value = entries.get(key);
1536
+ entries.delete(key);
1537
+ entries.set(key, value);
1538
+ return value;
1539
+ },
1540
+ has: (key) => entries.has(key),
1541
+ set: (key, value) => {
1542
+ entries.delete(key);
1543
+ entries.set(key, value);
1544
+ if (entries.size > capacity) {
1545
+ const oldest = entries.keys().next().value;
1546
+ if (oldest !== void 0) entries.delete(oldest);
1547
+ }
1548
+ },
1549
+ delete: (key) => void entries.delete(key),
1550
+ clear: () => entries.clear(),
1551
+ get size() {
1552
+ return entries.size;
1553
+ }
1554
+ };
1555
+ };
1556
+
1557
+ // src/core/drill-intent.ts
1558
+ var DRILL_INTENT_MS = 150;
1559
+ var createIntentTimer = ({
1560
+ onIntent,
1561
+ delay = DRILL_INTENT_MS,
1562
+ setTimer = (callback, ms) => setTimeout(callback, ms),
1563
+ clearTimer = (handle) => clearTimeout(handle)
1564
+ }) => {
1565
+ let current = null;
1566
+ let handle;
1567
+ let armed = false;
1568
+ const cancel = () => {
1569
+ if (armed) clearTimer(handle);
1570
+ armed = false;
1571
+ };
1572
+ return {
1573
+ hover: (key) => {
1574
+ if (key === current) return;
1575
+ cancel();
1576
+ current = key;
1577
+ if (key === null) return;
1578
+ armed = true;
1579
+ handle = setTimer(() => {
1580
+ armed = false;
1581
+ onIntent(key);
1582
+ }, delay);
1583
+ },
1584
+ dispose: () => {
1585
+ cancel();
1586
+ current = null;
1587
+ }
1588
+ };
1589
+ };
1590
+ var checkDrillStep = ({
1591
+ id,
1592
+ depth,
1593
+ levelId,
1594
+ knownIds,
1595
+ drillable
1596
+ }) => {
1597
+ if (knownIds !== void 0 && !knownIds.has(id)) {
1598
+ return { kind: "unknown-id", id, depth, levelId };
1599
+ }
1600
+ if (drillable === false) return { kind: "cannot-drill", id, depth, levelId };
1601
+ return null;
1602
+ };
1603
+ var formatDrillRequestProblem = (problem, source) => {
1604
+ const where = `level "${problem.levelId}" (depth ${problem.depth})`;
1605
+ return problem.kind === "unknown-id" ? `[choropleth] ${source}: region ${JSON.stringify(problem.id)} does not exist in ${where}. Hint: ids come from \`getFeatureId\` / \`feature.id\`; navigation was ignored.` : `[choropleth] ${source}: region ${JSON.stringify(problem.id)} cannot be drilled into: \`canDrill\` is false for it in ${where}; navigation was ignored.`;
1606
+ };
1607
+ var formatTooDeepRequest = (path, levelCount, source) => `[choropleth] ${source}: cannot go to ${JSON.stringify(path)}: only ${levelCount} level(s) are defined (max depth ${Math.max(0, levelCount - 1)}); navigation was ignored.`;
1608
+ var formatNoIdsDiagnostic = ({
1609
+ featureCount,
1610
+ idCount,
1611
+ levelId,
1612
+ customGetFeatureId
1613
+ }) => {
1614
+ if (featureCount === 0 || idCount > 0) return null;
1615
+ const level = levelId === null ? "" : ` in level "${levelId}"`;
1616
+ const hint = customGetFeatureId ? "`getFeatureId` returned `undefined` for every one; check the property it reads." : "none has a `feature.id`; pass `getFeatureId` to read another property.";
1617
+ return `[choropleth] none of the ${featureCount} region(s)${level} has an id, so no data can match: ${hint}`;
1618
+ };
1619
+ var formatWrongLevelDataHint = ({
1620
+ drillActive,
1621
+ dataIsSelector,
1622
+ dataCount,
1623
+ unmatchedCount,
1624
+ levelId
1625
+ }) => {
1626
+ if (!drillActive || dataIsSelector || dataCount === 0 || unmatchedCount < dataCount) return null;
1627
+ const level = levelId === null ? "this level" : `level "${levelId}"`;
1628
+ return `Hint: with \`drill\`, a fixed \`data\` array is used for every level and none of its rows match ${level}. Pass \`data\` as a selector to give each level its own rows: \`data={(ctx) => rowsFor(ctx)}\`.`;
1629
+ };
1630
+
1631
+ // src/core/drill-chain.ts
1632
+ import { geoBounds as geoBounds2, geoPath as geoPath2 } from "d3-geo";
1633
+ var boundsToObject = ([[west, south], [east, north]]) => ({
1634
+ type: "MultiPoint",
1635
+ coordinates: [
1636
+ [west, south],
1637
+ [(west + east) / 2, south],
1638
+ [east, south],
1639
+ [east, (south + north) / 2],
1640
+ [east, north],
1641
+ [(west + east) / 2, north],
1642
+ [west, north],
1643
+ [west, (south + north) / 2]
1644
+ ]
1645
+ });
1646
+ var widerHalf = ([[west, south], [east, north]]) => {
1647
+ if (west <= east)
1648
+ return [
1649
+ [west, south],
1650
+ [east, north]
1651
+ ];
1652
+ return 180 - west >= east + 180 ? [
1653
+ [west, south],
1654
+ [180, north]
1655
+ ] : [
1656
+ [-180, south],
1657
+ [east, north]
1658
+ ];
1659
+ };
1660
+ var mainBody = (geometry) => {
1661
+ if (geometry === null) return null;
1662
+ const [[west, south], [east, north]] = geoBounds2(geometry);
1663
+ return west > east ? boundsToObject(
1664
+ widerHalf([
1665
+ [west, south],
1666
+ [east, north]
1667
+ ])
1668
+ ) : geometry;
1669
+ };
1670
+ var buildProjectionChain = ({
1671
+ levels,
1672
+ path,
1673
+ name,
1674
+ width,
1675
+ height,
1676
+ padding,
1677
+ focusBounds,
1678
+ rotate
1679
+ }) => {
1680
+ const root = levels[0];
1681
+ const collection = (features) => ({
1682
+ type: "FeatureCollection",
1683
+ features: [...features]
1684
+ });
1685
+ const projections = [
1686
+ createProjection({
1687
+ name,
1688
+ width,
1689
+ height,
1690
+ featureCollection: collection(root?.features ?? []),
1691
+ rotate
1692
+ })
1693
+ ];
1694
+ const factory = projectionFactory(name);
1695
+ const pad = normalizePadding(padding);
1696
+ let missing = null;
1697
+ for (let depth = 1; depth <= path.length; depth++) {
1698
+ const parent = projections[depth - 1];
1699
+ const id = path[depth - 1];
1700
+ if (missing !== null) {
1701
+ projections.push(parent);
1702
+ continue;
1703
+ }
1704
+ const level = levels[depth - 1];
1705
+ const feature2 = level?.features.find((f) => level.idOf(f) === id);
1706
+ const bounds = focusBounds?.[id];
1707
+ const focus = bounds != null ? boundsToObject(widerHalf(bounds)) : feature2 === void 0 ? null : mainBody(getFocusGeometry({ feature: feature2, path: geoPath2(parent) }));
1708
+ if (focus === null) {
1709
+ missing = id;
1710
+ projections.push(parent);
1711
+ continue;
1712
+ }
1713
+ try {
1714
+ projections.push(
1715
+ rebaseProjection({ parent, factory, focus, width, height, padding: pad }).projection
1716
+ );
1717
+ } catch {
1718
+ missing = id;
1719
+ projections.push(parent);
1720
+ }
1721
+ }
1722
+ return { projections, missing };
1723
+ };
1724
+
1725
+ // src/core/region.ts
1726
+ var ALPHA2 = /^[A-Za-z]{2}$/;
1727
+ var resolveRegion = (region, presets) => {
1728
+ const entries = typeof region === "string" ? [region] : region;
1729
+ if (entries.length === 0) {
1730
+ throw new Error(
1731
+ `[choropleth] region: the list is empty. Pass a preset (${presetNames(presets)}) or alpha-2 codes.`
1732
+ );
1733
+ }
1734
+ const ids = /* @__PURE__ */ new Set();
1735
+ for (const entry of entries) {
1736
+ const preset = Object.hasOwn(presets, entry) ? presets[entry] : void 0;
1737
+ if (preset !== void 0) {
1738
+ for (const id of preset) ids.add(id);
1739
+ } else if (ALPHA2.test(entry)) {
1740
+ ids.add(entry.toUpperCase());
1741
+ } else {
1742
+ throw new Error(
1743
+ `[choropleth] region: unknown "${entry}". Use an alpha-2 code ("ES") or one of the presets: ${presetNames(presets)}.`
1744
+ );
1745
+ }
1746
+ }
1747
+ return ids;
1748
+ };
1749
+ var presetNames = (presets) => Object.keys(presets).join(", ");
1750
+ var centerInBox = ([ring], [[west, south], [east, north]]) => {
1751
+ if (ring === void 0 || ring.length === 0) return false;
1752
+ let minLon = Infinity;
1753
+ let maxLon = -Infinity;
1754
+ let minLat = Infinity;
1755
+ let maxLat = -Infinity;
1756
+ for (const [lon2 = NaN, lat2 = NaN] of ring) {
1757
+ minLon = Math.min(minLon, lon2);
1758
+ maxLon = Math.max(maxLon, lon2);
1759
+ minLat = Math.min(minLat, lat2);
1760
+ maxLat = Math.max(maxLat, lat2);
1761
+ }
1762
+ const lon = (minLon + maxLon) / 2;
1763
+ const lat = (minLat + maxLat) / 2;
1764
+ return lon >= west && lon <= east && lat >= south && lat <= north;
1765
+ };
1766
+ var dropOverseas = (features, territories) => features.map((feature2) => {
1767
+ const boxes = feature2.id === void 0 ? void 0 : territories[String(feature2.id)];
1768
+ const { geometry } = feature2;
1769
+ if (boxes === void 0 || boxes.length === 0 || geometry.type !== "MultiPolygon")
1770
+ return feature2;
1771
+ const kept = geometry.coordinates.filter(
1772
+ (coordinates) => !boxes.some((box) => centerInBox(coordinates, box))
1773
+ );
1774
+ if (kept.length === geometry.coordinates.length || kept.length === 0) return feature2;
1775
+ const trimmed = { type: "MultiPolygon", coordinates: kept };
1776
+ return { ...feature2, geometry: trimmed };
1777
+ });
1778
+ var BINS = 360;
1779
+ var binOf = (lon) => Math.floor(((lon + 180) % 360 + 360) % 360);
1780
+ var markRing = (ring, occupied) => {
1781
+ let previous;
1782
+ for (const [lon] of ring) {
1783
+ if (lon === void 0 || !Number.isFinite(lon)) continue;
1784
+ const at = ((lon + 180) % 360 + 360) % 360;
1785
+ if (previous !== void 0) {
1786
+ const delta = (at - previous + 540) % 360 - 180;
1787
+ const steps = Math.max(1, Math.ceil(Math.abs(delta)));
1788
+ for (let i = 0; i <= steps; i++) {
1789
+ occupied[binOf(previous + delta * i / steps - 180)] = 1;
1790
+ }
1791
+ }
1792
+ occupied[binOf(lon)] = 1;
1793
+ previous = at;
1794
+ }
1795
+ };
1796
+ var markGeometry = (geometry, occupied) => {
1797
+ if (geometry === null) return;
1798
+ if (geometry.type === "Polygon") {
1799
+ for (const ring of geometry.coordinates) markRing(ring, occupied);
1800
+ } else if (geometry.type === "MultiPolygon") {
1801
+ for (const polygon of geometry.coordinates) {
1802
+ for (const ring of polygon) markRing(ring, occupied);
1803
+ }
1804
+ }
1805
+ };
1806
+ var regionRotation = (features, points = []) => {
1807
+ const occupied = new Uint8Array(BINS);
1808
+ for (const feature2 of features) markGeometry(feature2.geometry, occupied);
1809
+ for (const [lon] of points) if (Number.isFinite(lon)) occupied[binOf(lon)] = 1;
1810
+ let start = -1;
1811
+ let length = 0;
1812
+ let runStart = -1;
1813
+ for (let i = 0; i < BINS * 2; i++) {
1814
+ if (occupied[i % BINS] === 1) {
1815
+ runStart = -1;
1816
+ continue;
1817
+ }
1818
+ if (runStart === -1) runStart = i;
1819
+ const runLength = Math.min(i - runStart + 1, BINS);
1820
+ if (runLength > length) {
1821
+ length = runLength;
1822
+ start = runStart;
1823
+ }
1824
+ }
1825
+ if (length === 0) return void 0;
1826
+ if (start + length > BINS || start === 0) return void 0;
1827
+ const lambda = -(start + length / 2);
1828
+ return [((lambda + 180) % 360 + 360) % 360 - 180, 0];
1829
+ };
1830
+
1831
+ export {
1832
+ unwrapGeography,
1833
+ toFeatureCollection,
1834
+ getFocusGeometry,
1835
+ getAnchorPoint,
1836
+ DEFAULT_PADDING,
1837
+ normalizePadding,
1838
+ boundsToTransform,
1839
+ projectBounds,
1840
+ getFocusExtent,
1841
+ FIT_TRANSFORM,
1842
+ isFitTransform,
1843
+ applyTransform,
1844
+ invertTransform,
1845
+ constrainAxis,
1846
+ constrainTransform,
1847
+ preserveView,
1848
+ MIN_FLIGHT_MS,
1849
+ MAX_FLIGHT_MS,
1850
+ DEFAULT_FLIGHT_CURVATURE,
1851
+ transformToZoomView,
1852
+ createZoomInterpolator,
1853
+ flightDuration,
1854
+ INERTIA_TAU_MS,
1855
+ inertiaOffset,
1856
+ INERTIA_MIN_VELOCITY,
1857
+ INERTIA_WINDOW_MS,
1858
+ releaseVelocity,
1859
+ bubbleScale,
1860
+ toViewState,
1861
+ defineTheme,
1862
+ THEMES,
1863
+ isThemeName,
1864
+ resolveTheme,
1865
+ extendTheme,
1866
+ themeToCssVars,
1867
+ en,
1868
+ es,
1869
+ resolveLabels,
1870
+ joinData,
1871
+ DEFAULT_CLASSES,
1872
+ finiteValues,
1873
+ computeThresholds,
1874
+ SEQUENTIAL_PALETTES,
1875
+ DIVERGING_PALETTES,
1876
+ CATEGORICAL_PALETTES,
1877
+ DEFAULT_EMPTY_FILL,
1878
+ createColorScale,
1879
+ projectionFactory,
1880
+ DEFAULT_PROJECTION,
1881
+ createProjection,
1882
+ DEFAULT_ASPECT_RATIO,
1883
+ computeAspectRatio,
1884
+ relativeTransform,
1885
+ rebaseProjection,
1886
+ defaultFormatValue,
1887
+ classIndex,
1888
+ buildLegend,
1889
+ createBorders,
1890
+ formatJoinDiagnostics,
1891
+ createCategoricalScale,
1892
+ buildCategoricalLegend,
1893
+ DEFAULT_MAX_RADIUS,
1894
+ createRadiusScale,
1895
+ buildSizeLegend,
1896
+ DEFAULT_BUBBLE_FILL,
1897
+ resolveVariant,
1898
+ DEFAULT_FOCUS_BOUNDS,
1899
+ DEFAULT_ZOOM_MIN,
1900
+ DEFAULT_ZOOM_MAX,
1901
+ resolveZoomOptions,
1902
+ resolveControls,
1903
+ zoomKeyAction,
1904
+ createZoomFilter,
1905
+ resolveZoomTarget,
1906
+ layerKey,
1907
+ classifyDrill,
1908
+ createDrillState,
1909
+ savedCameraFor,
1910
+ drillReducer,
1911
+ contextOf,
1912
+ validateLevels,
1913
+ clampPath,
1914
+ buildBreadcrumbs,
1915
+ geographyKeyFor,
1916
+ resolveDrillData,
1917
+ drillDirectionBetween,
1918
+ DEFAULT_LEVEL_CACHE_SIZE,
1919
+ createLruCache,
1920
+ DRILL_INTENT_MS,
1921
+ createIntentTimer,
1922
+ checkDrillStep,
1923
+ formatDrillRequestProblem,
1924
+ formatTooDeepRequest,
1925
+ formatNoIdsDiagnostic,
1926
+ formatWrongLevelDataHint,
1927
+ buildProjectionChain,
1928
+ resolveRegion,
1929
+ dropOverseas,
1930
+ regionRotation
1931
+ };
1932
+ //# sourceMappingURL=chunk-ZN6SLXL3.js.map