@buildcanada/charts 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.
Files changed (404) hide show
  1. package/LICENSE.md +8 -0
  2. package/README.md +113 -0
  3. package/package.json +137 -0
  4. package/src/components/BodyPortal/BodyPortal.tsx +40 -0
  5. package/src/components/Button/Button.scss +110 -0
  6. package/src/components/Button/Button.tsx +101 -0
  7. package/src/components/Checkbox.scss +93 -0
  8. package/src/components/Checkbox.tsx +47 -0
  9. package/src/components/ExpandableToggle/ExpandableToggle.scss +123 -0
  10. package/src/components/ExpandableToggle/ExpandableToggle.tsx +60 -0
  11. package/src/components/GrapherTabIcon.tsx +156 -0
  12. package/src/components/GrapherTrendArrow.scss +16 -0
  13. package/src/components/GrapherTrendArrow.tsx +30 -0
  14. package/src/components/Halo/Halo.tsx +44 -0
  15. package/src/components/LabeledSwitch/LabeledSwitch.scss +109 -0
  16. package/src/components/LabeledSwitch/LabeledSwitch.tsx +62 -0
  17. package/src/components/MarkdownTextWrap/MarkdownTextWrap.tsx +1173 -0
  18. package/src/components/OverlayHeader.scss +18 -0
  19. package/src/components/OverlayHeader.tsx +29 -0
  20. package/src/components/RadioButton.scss +69 -0
  21. package/src/components/RadioButton.tsx +42 -0
  22. package/src/components/SimpleMarkdownText.tsx +89 -0
  23. package/src/components/TextInput.scss +17 -0
  24. package/src/components/TextInput.tsx +19 -0
  25. package/src/components/TextWrap/TextWrap.tsx +361 -0
  26. package/src/components/TextWrap/TextWrapUtils.ts +32 -0
  27. package/src/components/closeButton/CloseButton.scss +40 -0
  28. package/src/components/closeButton/CloseButton.tsx +27 -0
  29. package/src/components/index.ts +70 -0
  30. package/src/components/loadingIndicator/LoadingIndicator.scss +40 -0
  31. package/src/components/loadingIndicator/LoadingIndicator.tsx +28 -0
  32. package/src/components/markdown/remarkPlainLinks.ts +36 -0
  33. package/src/components/reactUtil.ts +20 -0
  34. package/src/components/stubs/CodeSnippet.tsx +19 -0
  35. package/src/components/stubs/DataCitation.tsx +16 -0
  36. package/src/components/stubs/IndicatorKeyData.tsx +45 -0
  37. package/src/components/stubs/IndicatorProcessing.tsx +15 -0
  38. package/src/components/stubs/IndicatorSources.tsx +15 -0
  39. package/src/components/styles/colors.scss +113 -0
  40. package/src/components/styles/mixins.scss +630 -0
  41. package/src/components/styles/typography.scss +579 -0
  42. package/src/components/styles/util.scss +89 -0
  43. package/src/components/styles/variables.scss +208 -0
  44. package/src/config/ChartsConfig.ts +163 -0
  45. package/src/config/ChartsProvider.tsx +157 -0
  46. package/src/config/index.ts +20 -0
  47. package/src/core-table/CoreTable.ts +1355 -0
  48. package/src/core-table/CoreTableColumns.ts +973 -0
  49. package/src/core-table/CoreTableUtils.ts +793 -0
  50. package/src/core-table/ErrorValues.ts +73 -0
  51. package/src/core-table/OwidTable.ts +1175 -0
  52. package/src/core-table/OwidTableSynthesizers.ts +272 -0
  53. package/src/core-table/OwidTableUtil.ts +76 -0
  54. package/src/core-table/Transforms.ts +484 -0
  55. package/src/core-table/index.ts +82 -0
  56. package/src/explorer/ColumnGrammar.ts +217 -0
  57. package/src/explorer/Explorer.sample.ts +212 -0
  58. package/src/explorer/Explorer.scss +148 -0
  59. package/src/explorer/Explorer.tsx +1283 -0
  60. package/src/explorer/ExplorerConstants.ts +85 -0
  61. package/src/explorer/ExplorerControls.scss +156 -0
  62. package/src/explorer/ExplorerControls.tsx +210 -0
  63. package/src/explorer/ExplorerDecisionMatrix.ts +471 -0
  64. package/src/explorer/ExplorerGrammar.ts +161 -0
  65. package/src/explorer/ExplorerProgram.ts +568 -0
  66. package/src/explorer/ExplorerUtils.ts +59 -0
  67. package/src/explorer/GrapherGrammar.ts +387 -0
  68. package/src/explorer/gridLang/GrammarUtils.ts +121 -0
  69. package/src/explorer/gridLang/GridCell.ts +298 -0
  70. package/src/explorer/gridLang/GridLangConstants.ts +255 -0
  71. package/src/explorer/gridLang/GridProgram.ts +311 -0
  72. package/src/explorer/gridLang/readme.md +17 -0
  73. package/src/explorer/index.ts +69 -0
  74. package/src/explorer/readme.md +19 -0
  75. package/src/explorer/urlMigrations/CO2UrlMigration.ts +46 -0
  76. package/src/explorer/urlMigrations/CovidUrlMigration.ts +37 -0
  77. package/src/explorer/urlMigrations/EnergyUrlMigration.ts +41 -0
  78. package/src/explorer/urlMigrations/ExplorerPageUrlMigrationSpec.ts +12 -0
  79. package/src/explorer/urlMigrations/ExplorerUrlMigrationUtils.ts +45 -0
  80. package/src/explorer/urlMigrations/ExplorerUrlMigrations.ts +33 -0
  81. package/src/explorer/urlMigrations/LegacyCovidUrlMigration.ts +144 -0
  82. package/src/explorer/urlMigrations/readme.md +39 -0
  83. package/src/grapher/axis/Axis.ts +973 -0
  84. package/src/grapher/axis/AxisConfig.ts +179 -0
  85. package/src/grapher/axis/AxisViews.tsx +597 -0
  86. package/src/grapher/barCharts/DiscreteBarChart.tsx +728 -0
  87. package/src/grapher/barCharts/DiscreteBarChartConstants.ts +60 -0
  88. package/src/grapher/barCharts/DiscreteBarChartHelpers.ts +338 -0
  89. package/src/grapher/barCharts/DiscreteBarChartState.ts +354 -0
  90. package/src/grapher/barCharts/DiscreteBarChartThumbnail.tsx +34 -0
  91. package/src/grapher/captionedChart/CaptionedChart.scss +61 -0
  92. package/src/grapher/captionedChart/CaptionedChart.tsx +523 -0
  93. package/src/grapher/captionedChart/Logos.tsx +141 -0
  94. package/src/grapher/captionedChart/LogosSVG.tsx +16 -0
  95. package/src/grapher/captionedChart/StaticChartRasterizer.tsx +178 -0
  96. package/src/grapher/captionedChart/assets/buildcanada-logo-square.svg +15 -0
  97. package/src/grapher/captionedChart/assets/buildcanada-logo.svg +15 -0
  98. package/src/grapher/captionedChart/assets/canadaspends.svg +7 -0
  99. package/src/grapher/captionedChart/readme.md +14 -0
  100. package/src/grapher/chart/Chart.tsx +62 -0
  101. package/src/grapher/chart/ChartAreaContent.tsx +172 -0
  102. package/src/grapher/chart/ChartDimension.ts +121 -0
  103. package/src/grapher/chart/ChartInterface.ts +83 -0
  104. package/src/grapher/chart/ChartManager.ts +113 -0
  105. package/src/grapher/chart/ChartTabs.ts +178 -0
  106. package/src/grapher/chart/ChartTypeMap.tsx +158 -0
  107. package/src/grapher/chart/ChartTypeSwitcher.tsx +26 -0
  108. package/src/grapher/chart/ChartUtils.tsx +364 -0
  109. package/src/grapher/chart/DimensionSlot.ts +45 -0
  110. package/src/grapher/chart/StaticChartWrapper.tsx +94 -0
  111. package/src/grapher/chart/guidedChartUtils.ts +82 -0
  112. package/src/grapher/color/BinningStrategies.ts +484 -0
  113. package/src/grapher/color/BinningStrategyEqualSizeBins.ts +132 -0
  114. package/src/grapher/color/BinningStrategyLogarithmic.ts +121 -0
  115. package/src/grapher/color/CategoricalColorAssigner.ts +97 -0
  116. package/src/grapher/color/ColorBrewerSchemes.ts +80 -0
  117. package/src/grapher/color/ColorConstants.ts +20 -0
  118. package/src/grapher/color/ColorScale.ts +339 -0
  119. package/src/grapher/color/ColorScaleBin.ts +147 -0
  120. package/src/grapher/color/ColorScaleConfig.ts +204 -0
  121. package/src/grapher/color/ColorScheme.ts +137 -0
  122. package/src/grapher/color/ColorSchemes.ts +149 -0
  123. package/src/grapher/color/ColorUtils.ts +86 -0
  124. package/src/grapher/color/CustomSchemes.ts +1772 -0
  125. package/src/grapher/color/readme.md +84 -0
  126. package/src/grapher/comparisonLine/ComparisonLine.tsx +31 -0
  127. package/src/grapher/comparisonLine/ComparisonLineConstants.ts +11 -0
  128. package/src/grapher/comparisonLine/ComparisonLineGenerator.ts +60 -0
  129. package/src/grapher/comparisonLine/ComparisonLineHelpers.ts +10 -0
  130. package/src/grapher/comparisonLine/CustomComparisonLine.tsx +159 -0
  131. package/src/grapher/comparisonLine/VerticalComparisonLine.tsx +208 -0
  132. package/src/grapher/controls/ActionButtons.scss +97 -0
  133. package/src/grapher/controls/ActionButtons.tsx +453 -0
  134. package/src/grapher/controls/CommandPalette.scss +50 -0
  135. package/src/grapher/controls/CommandPalette.tsx +74 -0
  136. package/src/grapher/controls/ContentSwitchers.scss +93 -0
  137. package/src/grapher/controls/ContentSwitchers.tsx +238 -0
  138. package/src/grapher/controls/Controls.scss +158 -0
  139. package/src/grapher/controls/DataTableFilterDropdown.scss +7 -0
  140. package/src/grapher/controls/DataTableFilterDropdown.tsx +168 -0
  141. package/src/grapher/controls/DataTableSearchField.scss +3 -0
  142. package/src/grapher/controls/DataTableSearchField.tsx +76 -0
  143. package/src/grapher/controls/Dropdown.scss +252 -0
  144. package/src/grapher/controls/Dropdown.tsx +235 -0
  145. package/src/grapher/controls/EntitySelectionToggle.tsx +135 -0
  146. package/src/grapher/controls/MapRegionDropdown.scss +3 -0
  147. package/src/grapher/controls/MapRegionDropdown.tsx +104 -0
  148. package/src/grapher/controls/MapResetButton.tsx +115 -0
  149. package/src/grapher/controls/MapZoomDropdown.scss +9 -0
  150. package/src/grapher/controls/MapZoomDropdown.tsx +270 -0
  151. package/src/grapher/controls/MapZoomToSelectionButton.tsx +87 -0
  152. package/src/grapher/controls/SearchField.scss +78 -0
  153. package/src/grapher/controls/SearchField.tsx +63 -0
  154. package/src/grapher/controls/SettingsMenu.scss +191 -0
  155. package/src/grapher/controls/SettingsMenu.tsx +399 -0
  156. package/src/grapher/controls/ShareMenu.scss +58 -0
  157. package/src/grapher/controls/ShareMenu.tsx +304 -0
  158. package/src/grapher/controls/SortIcon.tsx +39 -0
  159. package/src/grapher/controls/VerticalScrollContainer.tsx +263 -0
  160. package/src/grapher/controls/controlsRow/ControlsRow.tsx +168 -0
  161. package/src/grapher/controls/dropdown-icons.scss +4 -0
  162. package/src/grapher/controls/entityPicker/EntityPicker.scss +255 -0
  163. package/src/grapher/controls/entityPicker/EntityPicker.tsx +816 -0
  164. package/src/grapher/controls/entityPicker/EntityPickerConstants.ts +23 -0
  165. package/src/grapher/controls/globalEntitySelector/GlobalEntitySelector.scss +129 -0
  166. package/src/grapher/controls/globalEntitySelector/GlobalEntitySelector.tsx +463 -0
  167. package/src/grapher/controls/globalEntitySelector/GlobalEntitySelectorConstants.ts +3 -0
  168. package/src/grapher/controls/globalEntitySelector/readme.md +17 -0
  169. package/src/grapher/controls/settings/AbsRelToggle.tsx +64 -0
  170. package/src/grapher/controls/settings/AxisScaleToggle.tsx +53 -0
  171. package/src/grapher/controls/settings/FacetStrategySelector.tsx +110 -0
  172. package/src/grapher/controls/settings/FacetYDomainToggle.tsx +51 -0
  173. package/src/grapher/controls/settings/NoDataAreaToggle.tsx +38 -0
  174. package/src/grapher/controls/settings/ZoomToggle.tsx +36 -0
  175. package/src/grapher/core/EntitiesByRegionType.ts +174 -0
  176. package/src/grapher/core/EntityCodes.ts +19 -0
  177. package/src/grapher/core/EntityUrlBuilder.ts +200 -0
  178. package/src/grapher/core/FetchingGrapher.tsx +156 -0
  179. package/src/grapher/core/Grapher.tsx +760 -0
  180. package/src/grapher/core/GrapherAnalytics.ts +229 -0
  181. package/src/grapher/core/GrapherConstants.ts +173 -0
  182. package/src/grapher/core/GrapherState.tsx +3659 -0
  183. package/src/grapher/core/GrapherUrl.ts +184 -0
  184. package/src/grapher/core/GrapherUrlMigrations.ts +29 -0
  185. package/src/grapher/core/GrapherUseHelpers.tsx +147 -0
  186. package/src/grapher/core/LegacyToOwidTable.ts +841 -0
  187. package/src/grapher/core/grapher.entry.ts +5 -0
  188. package/src/grapher/core/grapher.scss +257 -0
  189. package/src/grapher/core/loadGrapherTableHelpers.ts +116 -0
  190. package/src/grapher/core/loadVariable.ts +104 -0
  191. package/src/grapher/core/relatedQuestion.ts +12 -0
  192. package/src/grapher/core/typography.scss +206 -0
  193. package/src/grapher/dataTable/DataTable.sample.ts +206 -0
  194. package/src/grapher/dataTable/DataTable.scss +249 -0
  195. package/src/grapher/dataTable/DataTable.tsx +1332 -0
  196. package/src/grapher/dataTable/DataTableConstants.ts +186 -0
  197. package/src/grapher/entitySelector/EntitySelector.scss +255 -0
  198. package/src/grapher/entitySelector/EntitySelector.tsx +1838 -0
  199. package/src/grapher/facet/FacetChart.tsx +943 -0
  200. package/src/grapher/facet/FacetChartConstants.ts +24 -0
  201. package/src/grapher/facet/FacetChartUtils.ts +51 -0
  202. package/src/grapher/facet/FacetMap.tsx +604 -0
  203. package/src/grapher/facet/FacetMapConstants.ts +23 -0
  204. package/src/grapher/facet/readme.md +13 -0
  205. package/src/grapher/focus/FocusArray.ts +79 -0
  206. package/src/grapher/footer/Footer.scss +63 -0
  207. package/src/grapher/footer/Footer.tsx +809 -0
  208. package/src/grapher/footer/FooterManager.ts +44 -0
  209. package/src/grapher/fullScreen/FullScreen.scss +11 -0
  210. package/src/grapher/fullScreen/FullScreen.tsx +61 -0
  211. package/src/grapher/header/Header.scss +35 -0
  212. package/src/grapher/header/Header.tsx +372 -0
  213. package/src/grapher/header/HeaderManager.ts +28 -0
  214. package/src/grapher/index.ts +157 -0
  215. package/src/grapher/interaction/InteractionState.ts +60 -0
  216. package/src/grapher/legend/HorizontalColorLegends.tsx +923 -0
  217. package/src/grapher/legend/LegendInteractionState.ts +40 -0
  218. package/src/grapher/legend/VerticalColorLegend.tsx +295 -0
  219. package/src/grapher/lineCharts/LineChart.tsx +968 -0
  220. package/src/grapher/lineCharts/LineChartConstants.ts +89 -0
  221. package/src/grapher/lineCharts/LineChartHelpers.ts +184 -0
  222. package/src/grapher/lineCharts/LineChartState.ts +394 -0
  223. package/src/grapher/lineCharts/LineChartThumbnail.tsx +437 -0
  224. package/src/grapher/lineCharts/Lines.tsx +258 -0
  225. package/src/grapher/lineLegend/LineLegend.tsx +723 -0
  226. package/src/grapher/lineLegend/LineLegendConstants.ts +9 -0
  227. package/src/grapher/lineLegend/LineLegendFilterAlgorithms.ts +143 -0
  228. package/src/grapher/lineLegend/LineLegendHelpers.ts +253 -0
  229. package/src/grapher/lineLegend/LineLegendTypes.ts +32 -0
  230. package/src/grapher/mapCharts/CanadaTopology.ts +17922 -0
  231. package/src/grapher/mapCharts/ChoroplethGlobe.tsx +949 -0
  232. package/src/grapher/mapCharts/ChoroplethMap.tsx +662 -0
  233. package/src/grapher/mapCharts/GeoFeatures.ts +184 -0
  234. package/src/grapher/mapCharts/GlobeController.ts +496 -0
  235. package/src/grapher/mapCharts/MapAnnotationPlacements.json +1040 -0
  236. package/src/grapher/mapCharts/MapAnnotationPlacements.ts +31 -0
  237. package/src/grapher/mapCharts/MapAnnotations.ts +723 -0
  238. package/src/grapher/mapCharts/MapChart.sample.ts +59 -0
  239. package/src/grapher/mapCharts/MapChart.scss +5 -0
  240. package/src/grapher/mapCharts/MapChart.tsx +720 -0
  241. package/src/grapher/mapCharts/MapChartConstants.ts +260 -0
  242. package/src/grapher/mapCharts/MapChartState.ts +416 -0
  243. package/src/grapher/mapCharts/MapChartThumbnail.tsx +25 -0
  244. package/src/grapher/mapCharts/MapComponents.tsx +338 -0
  245. package/src/grapher/mapCharts/MapConfig.ts +156 -0
  246. package/src/grapher/mapCharts/MapHelpers.ts +181 -0
  247. package/src/grapher/mapCharts/MapProjections.ts +49 -0
  248. package/src/grapher/mapCharts/MapSparkline.tsx +257 -0
  249. package/src/grapher/mapCharts/MapTooltip.scss +49 -0
  250. package/src/grapher/mapCharts/MapTooltip.tsx +409 -0
  251. package/src/grapher/mapCharts/MapTopology.ts +1766 -0
  252. package/src/grapher/mapCharts/d3-bboxCollide.js +204 -0
  253. package/src/grapher/mapCharts/d3-geo-projection.ts +198 -0
  254. package/src/grapher/modal/DownloadIcons.tsx +39 -0
  255. package/src/grapher/modal/DownloadModal.scss +300 -0
  256. package/src/grapher/modal/DownloadModal.tsx +1226 -0
  257. package/src/grapher/modal/EmbedModal.scss +40 -0
  258. package/src/grapher/modal/EmbedModal.tsx +160 -0
  259. package/src/grapher/modal/EntitySelectorModal.tsx +59 -0
  260. package/src/grapher/modal/Modal.scss +31 -0
  261. package/src/grapher/modal/Modal.tsx +90 -0
  262. package/src/grapher/modal/ModalHeader.scss +12 -0
  263. package/src/grapher/modal/ModalHeader.tsx +16 -0
  264. package/src/grapher/modal/SourcesDescriptions.scss +87 -0
  265. package/src/grapher/modal/SourcesDescriptions.tsx +89 -0
  266. package/src/grapher/modal/SourcesKeyDataTable.scss +49 -0
  267. package/src/grapher/modal/SourcesKeyDataTable.tsx +87 -0
  268. package/src/grapher/modal/SourcesModal.scss +301 -0
  269. package/src/grapher/modal/SourcesModal.tsx +568 -0
  270. package/src/grapher/noDataModal/NoDataModal.tsx +125 -0
  271. package/src/grapher/scatterCharts/ConnectedScatterLegend.tsx +143 -0
  272. package/src/grapher/scatterCharts/MultiColorPolyline.tsx +129 -0
  273. package/src/grapher/scatterCharts/NoDataSection.scss +14 -0
  274. package/src/grapher/scatterCharts/NoDataSection.tsx +56 -0
  275. package/src/grapher/scatterCharts/ScatterPlotChart.tsx +792 -0
  276. package/src/grapher/scatterCharts/ScatterPlotChartConstants.ts +157 -0
  277. package/src/grapher/scatterCharts/ScatterPlotChartState.ts +678 -0
  278. package/src/grapher/scatterCharts/ScatterPlotChartThumbnail.tsx +155 -0
  279. package/src/grapher/scatterCharts/ScatterPlotTooltip.tsx +560 -0
  280. package/src/grapher/scatterCharts/ScatterPoints.tsx +153 -0
  281. package/src/grapher/scatterCharts/ScatterPointsWithLabels.tsx +708 -0
  282. package/src/grapher/scatterCharts/ScatterSizeLegend.tsx +327 -0
  283. package/src/grapher/scatterCharts/ScatterUtils.ts +265 -0
  284. package/src/grapher/scatterCharts/Triangle.tsx +41 -0
  285. package/src/grapher/schema/README.md +33 -0
  286. package/src/grapher/schema/defaultGrapherConfig.ts +100 -0
  287. package/src/grapher/schema/grapher-schema.009.yaml +781 -0
  288. package/src/grapher/schema/migrations/helpers.ts +58 -0
  289. package/src/grapher/schema/migrations/migrate.ts +75 -0
  290. package/src/grapher/schema/migrations/migrations.ts +158 -0
  291. package/src/grapher/selection/MapSelectionArray.ts +99 -0
  292. package/src/grapher/selection/SelectionArray.ts +71 -0
  293. package/src/grapher/selection/readme.md +16 -0
  294. package/src/grapher/sidePanel/SidePanel.scss +10 -0
  295. package/src/grapher/sidePanel/SidePanel.tsx +23 -0
  296. package/src/grapher/slideInDrawer/SlideInDrawer.scss +57 -0
  297. package/src/grapher/slideInDrawer/SlideInDrawer.tsx +125 -0
  298. package/src/grapher/slideshowController/SlideShowController.tsx +43 -0
  299. package/src/grapher/slideshowController/readme.md +7 -0
  300. package/src/grapher/slopeCharts/MarkX.tsx +45 -0
  301. package/src/grapher/slopeCharts/Slope.tsx +102 -0
  302. package/src/grapher/slopeCharts/SlopeChart.tsx +1152 -0
  303. package/src/grapher/slopeCharts/SlopeChartConstants.ts +33 -0
  304. package/src/grapher/slopeCharts/SlopeChartHelpers.ts +73 -0
  305. package/src/grapher/slopeCharts/SlopeChartState.ts +392 -0
  306. package/src/grapher/slopeCharts/SlopeChartThumbnail.tsx +368 -0
  307. package/src/grapher/stackedCharts/AbstractStackedChartState.ts +370 -0
  308. package/src/grapher/stackedCharts/MarimekkoBars.tsx +190 -0
  309. package/src/grapher/stackedCharts/MarimekkoBarsForOneEntity.tsx +168 -0
  310. package/src/grapher/stackedCharts/MarimekkoChart.tsx +1144 -0
  311. package/src/grapher/stackedCharts/MarimekkoChartConstants.ts +112 -0
  312. package/src/grapher/stackedCharts/MarimekkoChartHelpers.ts +21 -0
  313. package/src/grapher/stackedCharts/MarimekkoChartState.ts +465 -0
  314. package/src/grapher/stackedCharts/MarimekkoChartThumbnail.tsx +168 -0
  315. package/src/grapher/stackedCharts/MarimekkoInternalLabels.tsx +124 -0
  316. package/src/grapher/stackedCharts/StackedAreaChart.tsx +678 -0
  317. package/src/grapher/stackedCharts/StackedAreaChartState.ts +34 -0
  318. package/src/grapher/stackedCharts/StackedAreaChartThumbnail.tsx +215 -0
  319. package/src/grapher/stackedCharts/StackedAreas.tsx +223 -0
  320. package/src/grapher/stackedCharts/StackedBarChart.tsx +619 -0
  321. package/src/grapher/stackedCharts/StackedBarChartState.ts +80 -0
  322. package/src/grapher/stackedCharts/StackedBarChartThumbnail.tsx +220 -0
  323. package/src/grapher/stackedCharts/StackedBarSegment.tsx +87 -0
  324. package/src/grapher/stackedCharts/StackedBars.tsx +102 -0
  325. package/src/grapher/stackedCharts/StackedConstants.ts +109 -0
  326. package/src/grapher/stackedCharts/StackedDiscreteBarChart.tsx +270 -0
  327. package/src/grapher/stackedCharts/StackedDiscreteBarChartState.ts +296 -0
  328. package/src/grapher/stackedCharts/StackedDiscreteBarChartThumbnail.tsx +27 -0
  329. package/src/grapher/stackedCharts/StackedDiscreteBars.tsx +648 -0
  330. package/src/grapher/stackedCharts/StackedUtils.ts +142 -0
  331. package/src/grapher/tabs/Tabs.scss +169 -0
  332. package/src/grapher/tabs/Tabs.tsx +54 -0
  333. package/src/grapher/tabs/TabsWithDropdown.scss +62 -0
  334. package/src/grapher/tabs/TabsWithDropdown.tsx +114 -0
  335. package/src/grapher/testData/OwidTestData.sample.ts +273 -0
  336. package/src/grapher/testData/OwidTestData.ts +64 -0
  337. package/src/grapher/timeline/TimelineComponent.scss +139 -0
  338. package/src/grapher/timeline/TimelineComponent.tsx +658 -0
  339. package/src/grapher/timeline/TimelineController.ts +368 -0
  340. package/src/grapher/timeline/readme.md +7 -0
  341. package/src/grapher/tooltip/Tooltip.scss +510 -0
  342. package/src/grapher/tooltip/Tooltip.tsx +294 -0
  343. package/src/grapher/tooltip/TooltipContents.tsx +383 -0
  344. package/src/grapher/tooltip/TooltipProps.ts +123 -0
  345. package/src/grapher/tooltip/TooltipState.ts +81 -0
  346. package/src/grapher/verticalLabels/VerticalLabels.tsx +31 -0
  347. package/src/grapher/verticalLabels/VerticalLabelsState.ts +154 -0
  348. package/src/index.ts +226 -0
  349. package/src/styles/charts.scss +15 -0
  350. package/src/types/NominalType.ts +30 -0
  351. package/src/types/OwidOrigin.ts +18 -0
  352. package/src/types/OwidSource.ts +9 -0
  353. package/src/types/OwidVariable.ts +133 -0
  354. package/src/types/OwidVariableDisplayConfigInterface.ts +49 -0
  355. package/src/types/analyticsTypes.ts +54 -0
  356. package/src/types/dbTypes/Tags.ts +11 -0
  357. package/src/types/domainTypes/Archive.ts +139 -0
  358. package/src/types/domainTypes/Author.ts +28 -0
  359. package/src/types/domainTypes/ContentGraph.ts +76 -0
  360. package/src/types/domainTypes/CoreTableTypes.ts +305 -0
  361. package/src/types/domainTypes/DeployStatus.ts +23 -0
  362. package/src/types/domainTypes/Layout.ts +34 -0
  363. package/src/types/domainTypes/Posts.ts +34 -0
  364. package/src/types/domainTypes/Search.ts +299 -0
  365. package/src/types/domainTypes/Site.ts +8 -0
  366. package/src/types/domainTypes/StaticViz.ts +64 -0
  367. package/src/types/domainTypes/Toc.ts +11 -0
  368. package/src/types/domainTypes/Tombstone.ts +19 -0
  369. package/src/types/domainTypes/Various.ts +79 -0
  370. package/src/types/gdocTypes/Gdoc.ts +280 -0
  371. package/src/types/grapherTypes/BinningStrategyTypes.ts +46 -0
  372. package/src/types/grapherTypes/GrapherConstants.ts +53 -0
  373. package/src/types/grapherTypes/GrapherTypes.ts +743 -0
  374. package/src/types/index.ts +316 -0
  375. package/src/types/wordpressTypes/WordpressTypes.ts +9 -0
  376. package/src/utils/Bounds.ts +439 -0
  377. package/src/utils/BrowserUtils.ts +12 -0
  378. package/src/utils/FuzzySearch.ts +74 -0
  379. package/src/utils/MultiDimDataPageConfig.ts +31 -0
  380. package/src/utils/OwidVariable.ts +82 -0
  381. package/src/utils/PointVector.ts +97 -0
  382. package/src/utils/PromiseCache.ts +36 -0
  383. package/src/utils/PromiseSwitcher.ts +52 -0
  384. package/src/utils/TimeBounds.ts +130 -0
  385. package/src/utils/Tippy.tsx +57 -0
  386. package/src/utils/Util.ts +2369 -0
  387. package/src/utils/archival/archivalDate.ts +48 -0
  388. package/src/utils/dayjs.ts +32 -0
  389. package/src/utils/formatValue.ts +242 -0
  390. package/src/utils/grapherConfigUtils.ts +81 -0
  391. package/src/utils/image.ts +225 -0
  392. package/src/utils/index.ts +318 -0
  393. package/src/utils/isPresent.ts +5 -0
  394. package/src/utils/metadataHelpers.ts +329 -0
  395. package/src/utils/persistable/Persistable.ts +82 -0
  396. package/src/utils/persistable/readme.md +50 -0
  397. package/src/utils/regions.json +5635 -0
  398. package/src/utils/regions.ts +463 -0
  399. package/src/utils/serializers.ts +16 -0
  400. package/src/utils/string.ts +42 -0
  401. package/src/utils/urls/Url.ts +195 -0
  402. package/src/utils/urls/UrlMigration.ts +10 -0
  403. package/src/utils/urls/UrlUtils.ts +54 -0
  404. package/src/utils/urls/readme.md +90 -0
@@ -0,0 +1,260 @@
1
+ import { ColorScaleBin } from "../color/ColorScaleBin"
2
+ import { Bounds, ColumnSlug } from "../../utils/index.js"
3
+ import {
4
+ MapRegionName,
5
+ SeriesName,
6
+ GlobeRegionName,
7
+ ProjectionColumnInfo,
8
+ type GrapherInteractionEvent,
9
+ Time,
10
+ } from "../../types/index.js"
11
+ import { ChartManager } from "../chart/ChartManager"
12
+ import { MapConfig } from "./MapConfig"
13
+ import { ChartSeries } from "../chart/ChartInterface"
14
+ import { GlobeController } from "./GlobeController"
15
+ import { MapSelectionArray } from "../selection/MapSelectionArray.js"
16
+ import { CoreColumn } from "../../core-table/index.js"
17
+ import * as R from "remeda"
18
+ import { InteractionState } from "../interaction/InteractionState"
19
+
20
+ export declare type SVGMouseEvent = React.MouseEvent<SVGElement>
21
+
22
+ export type GeoFeature = GeoJSON.Feature<GeoJSON.GeometryObject>
23
+ export type MapBracket = ColorScaleBin
24
+
25
+ export const MAP_HOVER_TARGET_RANGE = 20
26
+
27
+ export const DEFAULT_STROKE_COLOR = "#333"
28
+ export const HOVER_STROKE_COLOR = "#111"
29
+
30
+ export const DEFAULT_STROKE_WIDTH = 0.3
31
+ export const HOVER_STROKE_WIDTH = 1.5
32
+ export const SELECTED_STROKE_WIDTH = 1
33
+ export const PATTERN_STROKE_WIDTH = 0.7
34
+
35
+ export const BLUR_FILL_OPACITY = 0.2
36
+ export const BLUR_STROKE_OPACITY = 0.5
37
+
38
+ export const PROJECTED_DATA_LEGEND_COLOR = "#ffffff"
39
+
40
+ export const MAP_CHART_CLASSNAME = "MapChart"
41
+ export const CHOROPLETH_MAP_CLASSNAME = "ChoroplethMap"
42
+ export const GEO_FEATURES_CLASSNAME = "GeoFeatures"
43
+
44
+ export const DEFAULT_GLOBE_ZOOM = 1
45
+ export const GLOBE_MIN_ZOOM = 1
46
+ export const GLOBE_MAX_ZOOM = 5
47
+ export const GLOBE_COUNTRY_ZOOM = 2.5
48
+
49
+ export const GLOBE_LATITUDE_MIN = -65
50
+ export const GLOBE_LATITUDE_MAX = 65
51
+
52
+ export const DEFAULT_GLOBE_SIZE = 500 // defined by d3
53
+ export const DEFAULT_GLOBE_ROTATION: [number, number] = [-30, 20] // Atlantic ocean (i.e. Americas & Europe)
54
+ export const DEFAULT_GLOBE_ROTATIONS_FOR_TIME: Record<
55
+ "UTC_MORNING" | "UTC_MIDDAY" | "UTC_EVENING",
56
+ [number, number]
57
+ > = {
58
+ UTC_MORNING: [110, 15], // Asia & Oceania
59
+ UTC_MIDDAY: [20, 20], // Europe & Africa
60
+ UTC_EVENING: [-90, 15], // North & South America
61
+ }
62
+
63
+ export const ANNOTATION_COLOR_DARK = HOVER_STROKE_COLOR
64
+ export const ANNOTATION_COLOR_LIGHT = "#fff"
65
+
66
+ export const ANNOTATION_FONT_SIZE_INTERNAL_DEFAULT = 11
67
+ export const ANNOTATION_FONT_SIZE_INTERNAL_MIN = 7
68
+ export const ANNOTATION_FONT_SIZE_EXTERNAL_DEFAULT = 8
69
+ export const ANNOTATION_FONT_SIZE_EXTERNAL_MAX = 11
70
+
71
+ export const ANNOTATION_MARKER_LINE_LENGTH_DEFAULT = 6
72
+ export const ANNOTATION_MARKER_LINE_LENGTH_MAX = 10
73
+
74
+ export const MAP_REGION_LABELS: Record<MapRegionName, string> = {
75
+ World: "World",
76
+ Africa: "Africa",
77
+ NorthAmerica: "North America",
78
+ SouthAmerica: "South America",
79
+ Asia: "Asia",
80
+ Europe: "Europe",
81
+ Oceania: "Oceania",
82
+ Canada: "Canada",
83
+ }
84
+
85
+ export const MAP_REGION_NAMES = R.invert(MAP_REGION_LABELS)
86
+
87
+ export interface ChoroplethSeries extends ChartSeries {
88
+ value: number | string
89
+ time: number
90
+ isProjection?: boolean
91
+ }
92
+
93
+ export type ChoroplethSeriesByName = Map<SeriesName, ChoroplethSeries>
94
+
95
+ export interface ChoroplethMapManager {
96
+ choroplethData: ChoroplethSeriesByName
97
+ choroplethMapBounds: Bounds
98
+ mapConfig: MapConfig
99
+ mapColumn: CoreColumn
100
+ globeController?: GlobeController
101
+ selectionArray?: MapSelectionArray
102
+ fontSize?: number
103
+ getHoverState?: (featureId: string) => InteractionState
104
+ isSelected?: (featureId: string) => boolean
105
+ onMapMouseOver?: (d: GeoFeature) => void
106
+ onMapMouseLeave?: () => void
107
+ isMapSelectionEnabled?: boolean
108
+ isStatic?: boolean
109
+ binColors?: string[]
110
+ hasProjectedData?: boolean
111
+ mapViewport?: MapViewport
112
+ isFaceted?: boolean
113
+ }
114
+
115
+ export enum RenderFeatureType {
116
+ Map = "map",
117
+ Globe = "globe",
118
+ }
119
+
120
+ export interface RenderFeature {
121
+ type: RenderFeatureType
122
+ id: string
123
+ geo: GeoFeature
124
+ geoCentroid: [number, number] // unprojected
125
+ geoBounds: Bounds // unprojected
126
+ }
127
+
128
+ export interface MapRenderFeature extends RenderFeature {
129
+ type: RenderFeatureType.Map
130
+ path: string
131
+ projBounds: Bounds
132
+ }
133
+
134
+ export interface GlobeRenderFeature extends RenderFeature {
135
+ type: RenderFeatureType.Globe
136
+ }
137
+
138
+ export interface MapChartManager extends ChartManager {
139
+ mapColumnSlug?: ColumnSlug
140
+ mapConfig?: MapConfig
141
+ targetTime?: Time
142
+ globeController?: GlobeController
143
+ isMapSelectionEnabled?: boolean
144
+ highlightedTimesInTooltip?: [Time, Time]
145
+ mapViewport?: MapViewport
146
+ isFaceted?: boolean
147
+ logGrapherInteractionEvent?: (
148
+ action: GrapherInteractionEvent,
149
+ target?: string
150
+ ) => void
151
+ projectionColumnInfoBySlug?: Map<ColumnSlug, ProjectionColumnInfo>
152
+ }
153
+
154
+ export interface GlobeViewport {
155
+ rotation: [number, number]
156
+ zoom: number
157
+ }
158
+
159
+ export interface MapViewport {
160
+ x: number
161
+ y: number
162
+ width: number
163
+ height: number
164
+ ratio: number
165
+ }
166
+
167
+ export const GLOBE_VIEWPORTS: Record<GlobeRegionName, GlobeViewport> = {
168
+ Europe: { rotation: [10, 55], zoom: 2.95 },
169
+ Africa: { rotation: [20, 0], zoom: 1.55 },
170
+ NorthAmerica: { rotation: [-94.5, 43], zoom: 1.5 },
171
+ SouthAmerica: { rotation: [-62, -22], zoom: 1.75 },
172
+ Asia: { rotation: [81, 26], zoom: 1.85 },
173
+ Oceania: { rotation: [152.65, -18.8], zoom: 2 },
174
+ Canada: { rotation: [-100, 60], zoom: 2.5 },
175
+ }
176
+
177
+ /** Viewport for each region, defined by center and width+height in fractional coordinates */
178
+ export const MAP_VIEWPORTS: Record<MapRegionName, MapViewport> = {
179
+ World: { x: 0.565, y: 0.5, width: 1.01, height: 1.01, ratio: 2.29 },
180
+ Europe: { x: 0.53, y: 0.21, width: 0.2, height: 0.2, ratio: 1.77 },
181
+ Africa: { x: 0.48, y: 0.7, width: 0.21, height: 0.38, ratio: 1.07 },
182
+ NorthAmerica: { x: 0.46, y: 0.4, width: 0.19, height: 0.35, ratio: 1.12 },
183
+ SouthAmerica: { x: 0.52, y: 0.815, width: 0.1, height: 0.26, ratio: 0.62 },
184
+ Asia: { x: 0.74, y: 0.45, width: 0.36, height: 0.5, ratio: 1.65 },
185
+ Oceania: { x: 0.51, y: 0.75, width: 0.1, height: 0.2, ratio: 1.47 },
186
+ Canada: { x: 0.5, y: 0.5, width: 1, height: 1.05, ratio: 1.5 },
187
+ }
188
+
189
+ // Custom viewport for faceted world map, which zooms in a little bit to make best use of the available space
190
+ export const MAP_VIEWPORT_FACETED_WORLD: MapViewport = {
191
+ x: 0.545,
192
+ y: 0.5,
193
+ width: 0.91,
194
+ height: 1.01,
195
+ ratio: 2.29,
196
+ }
197
+
198
+ export interface Circle {
199
+ cx: number // center x
200
+ cy: number // center y
201
+ r: number // radius
202
+ }
203
+
204
+ export interface Ellipse {
205
+ cx: number // center x
206
+ cy: number // center y
207
+ rx: number // radius on the x-axis
208
+ ry: number // radius on the y-axis
209
+ }
210
+
211
+ // ellipse expressed in lon/lat
212
+ export interface EllipseCoords {
213
+ cx: number
214
+ cy: number
215
+ left: number // left x
216
+ top: number // top y
217
+ }
218
+
219
+ interface BaseAnnotation {
220
+ id: string
221
+ feature: RenderFeature
222
+ placedBounds: Bounds
223
+ text: string
224
+ fontSize: number
225
+ color: string
226
+ }
227
+
228
+ export interface InternalAnnotation extends BaseAnnotation {
229
+ type: "internal"
230
+ ellipse: Ellipse
231
+ }
232
+
233
+ export interface ExternalAnnotation extends BaseAnnotation {
234
+ type: "external"
235
+ direction: Direction
236
+ anchor: [number, number]
237
+ }
238
+
239
+ export type Annotation = InternalAnnotation | ExternalAnnotation
240
+
241
+ export type Direction =
242
+ | "left"
243
+ | "right"
244
+ | "top"
245
+ | "bottom"
246
+ | "leftTop"
247
+ | "leftBottom"
248
+ | "rightTop"
249
+ | "rightBottom"
250
+
251
+ export type MapColumnInfo =
252
+ // the map column isn't a projection
253
+ | { type: "historical"; slug: ColumnSlug }
254
+ // the map column is a projection without an historical counterpart
255
+ | { type: "projected"; slug: ColumnSlug }
256
+ // the map column is a projection and has an historical counterpart
257
+ | ({
258
+ type: "historical+projected"
259
+ slug: ColumnSlug
260
+ } & ProjectionColumnInfo)
@@ -0,0 +1,416 @@
1
+ import * as R from "remeda"
2
+ import { computed, makeObservable } from "mobx"
3
+ import { ChartState } from "../chart/ChartInterface"
4
+ import {
5
+ ChoroplethSeries,
6
+ ChoroplethSeriesByName,
7
+ MAP_REGION_LABELS,
8
+ MapChartManager,
9
+ MapColumnInfo,
10
+ } from "./MapChartConstants"
11
+ import {
12
+ CoreColumn,
13
+ ErrorValueTypes,
14
+ OwidTable,
15
+ } from "../../core-table/index.js"
16
+ import { match, P } from "ts-pattern"
17
+ import {
18
+ ChartErrorInfo,
19
+ Color,
20
+ ColorSchemeName,
21
+ ColumnSlug,
22
+ EntityName,
23
+ MapRegionName,
24
+ PrimitiveType,
25
+ TickFormattingOptions,
26
+ Time,
27
+ } from "../../types/index.js"
28
+ import {
29
+ anyToString,
30
+ checkHasMembers,
31
+ isPresent,
32
+ mappableCountries,
33
+ regions,
34
+ } from "../../utils/index.js"
35
+ import { MapConfig } from "./MapConfig"
36
+ import { combineHistoricalAndProjectionColumns } from "../chart/ChartUtils"
37
+ import {
38
+ getCountriesByRegion,
39
+ isOnTheCanadaMap,
40
+ isOnTheMap,
41
+ } from "./MapHelpers"
42
+ import { MapSelectionArray } from "../selection/MapSelectionArray"
43
+ import { ColorScale, ColorScaleManager } from "../color/ColorScale"
44
+ import { ColorScaleConfig } from "../color/ColorScaleConfig"
45
+
46
+ export type MapFormatValueForTooltip = (
47
+ d: PrimitiveType,
48
+ options?: TickFormattingOptions
49
+ ) => {
50
+ label: string
51
+ isCategorical: boolean
52
+ }
53
+
54
+ export class MapChartState implements ChartState, ColorScaleManager {
55
+ manager: MapChartManager
56
+
57
+ colorScale: ColorScale
58
+ defaultBaseColorScheme = ColorSchemeName.BuGn
59
+ hasNoDataBin = true
60
+
61
+ constructor({ manager }: { manager: MapChartManager }) {
62
+ this.manager = manager
63
+ this.colorScale = new ColorScale(this)
64
+ makeObservable(this)
65
+ }
66
+
67
+ transformTable(table: OwidTable): OwidTable {
68
+ // Drop non-mappable entities from the table
69
+ table = this.dropNonMapEntities(table)
70
+
71
+ return match(this.mapColumnInfo)
72
+ .with({ type: P.union("historical", "projected") }, (info) =>
73
+ this.transformTableForSingleMapColumn(table, info)
74
+ )
75
+ .with({ type: "historical+projected" }, (info) =>
76
+ this.transformTableForCombinedMapColumn(table, info)
77
+ )
78
+ .exhaustive()
79
+ }
80
+
81
+ private transformTableForSingleMapColumn(
82
+ table: OwidTable,
83
+ mapColumnInfo: Extract<
84
+ MapColumnInfo,
85
+ { type: "historical" | "projected" }
86
+ >
87
+ ): OwidTable {
88
+ return table
89
+ .dropRowsWithErrorValuesForColumn(mapColumnInfo.slug)
90
+ .interpolateColumnWithTolerance(mapColumnInfo.slug, {
91
+ toleranceOverride: this.mapConfig.timeTolerance,
92
+ toleranceStrategyOverride: this.mapConfig.toleranceStrategy,
93
+ })
94
+ }
95
+
96
+ private transformTableForCombinedMapColumn(
97
+ table: OwidTable,
98
+ mapColumnInfo: Extract<MapColumnInfo, { type: "historical+projected" }>
99
+ ): OwidTable {
100
+ const { historicalSlug, projectedSlug, combinedSlug } = mapColumnInfo
101
+
102
+ // Interpolate both columns separately
103
+ table = table
104
+ .interpolateColumnWithTolerance(projectedSlug, {
105
+ toleranceOverride: this.mapConfig.timeTolerance,
106
+ toleranceStrategyOverride: this.mapConfig.toleranceStrategy,
107
+ })
108
+ .interpolateColumnWithTolerance(historicalSlug, {
109
+ toleranceOverride: this.mapConfig.timeTolerance,
110
+ toleranceStrategyOverride: this.mapConfig.toleranceStrategy,
111
+ })
112
+
113
+ // Combine the projection column with its historical stem into one column
114
+ table = combineHistoricalAndProjectionColumns(table, mapColumnInfo, {
115
+ shouldAddIsProjectionColumn: true,
116
+ })
117
+
118
+ // Drop rows with error values for the combined column
119
+ table = table.dropRowsWithErrorValuesForColumn(combinedSlug)
120
+
121
+ return table
122
+ }
123
+
124
+ transformTableForSelection(table: OwidTable): OwidTable {
125
+ table = this.addMissingMapEntities(table)
126
+ table = this.dropNonMapEntitiesForSelection(table)
127
+ table = this.dropAntarctica(table)
128
+ return table
129
+ }
130
+
131
+ private dropAntarctica(table: OwidTable): OwidTable {
132
+ // We prefer to not offer Antarctica in the entity selector on the map
133
+ // tab to avoid confusion since it's shown on the globe, but not on the map.
134
+ return table.filterByEntityNamesUsingIncludeExcludePattern({
135
+ excluded: ["Antarctica"],
136
+ })
137
+ }
138
+
139
+ private dropNonMapEntities(table: OwidTable): OwidTable {
140
+ // For Canada region, filter by Canadian provinces/territories
141
+ if (this.mapConfig.region === MapRegionName.Canada) {
142
+ const entityNamesToSelect =
143
+ table.availableEntityNames.filter(isOnTheCanadaMap)
144
+ return table.filterByEntityNames(entityNamesToSelect)
145
+ }
146
+
147
+ // For world and other regions, filter by world map entities
148
+ const entityNamesToSelect =
149
+ table.availableEntityNames.filter(isOnTheMap)
150
+ return table.filterByEntityNames(entityNamesToSelect)
151
+ }
152
+
153
+ private dropNonMapEntitiesForSelection(table: OwidTable): OwidTable {
154
+ const { selectionArray, mapConfig } = this
155
+
156
+ const allMappableCountryNames = mappableCountries.map((c) => c.name)
157
+ const allRegionNames = regions
158
+ .filter((r) => checkHasMembers(r) && r.code !== "OWID_WRL")
159
+ .map((r) => r.name)
160
+
161
+ const mappableCountryNameSet = new Set(allMappableCountryNames)
162
+
163
+ // If in 2D mode and a continent is selected, then all countries
164
+ // outside of the selected continent are disabled on the map
165
+ // and thus also not selectable
166
+ if (this.mapConfig.is2dContinentActive()) {
167
+ const countriesInRegionSet = getCountriesByRegion(
168
+ MAP_REGION_LABELS[mapConfig.region]
169
+ )
170
+ if (!countriesInRegionSet) return table
171
+
172
+ const countriesInRegion = Array.from(countriesInRegionSet)
173
+ const mappableCountriesInRegion = countriesInRegion.filter(
174
+ (countryName) => mappableCountryNameSet.has(countryName)
175
+ )
176
+
177
+ return table.filterByEntityNames(
178
+ R.unique([
179
+ // only keep countries in the region
180
+ ...mappableCountriesInRegion,
181
+ // keep the user's selection
182
+ ...selectionArray.selectedEntityNames,
183
+ ])
184
+ )
185
+ }
186
+
187
+ // if no regions are currently selected, keep all mappable countries and regions
188
+ if (!selectionArray.hasRegions) {
189
+ return table.filterByEntityNames([
190
+ ...allRegionNames,
191
+ ...allMappableCountryNames,
192
+ ])
193
+ }
194
+
195
+ return table.filterByEntityNames(
196
+ R.unique([
197
+ // keep all regions
198
+ ...allRegionNames,
199
+ // only keep those countries that are within the selected regions
200
+ ...selectionArray.countryNamesForSelectedRegions,
201
+ // keep the user's selection
202
+ ...selectionArray.selectedEntityNames,
203
+ ])
204
+ )
205
+ }
206
+
207
+ private addMissingMapEntities(table: OwidTable): OwidTable {
208
+ // the given table might not have data for all mappable countries, but
209
+ // on the map tab, we do want every country to be selectable, even if
210
+ // it doesn't have data for any of the years. that's why we add a
211
+ // missing-data row for every mappable country that isn't in the table
212
+
213
+ const missingMappableCountries = mappableCountries.filter(
214
+ (country) => !table.availableEntityNameSet.has(country.name)
215
+ )
216
+
217
+ const rows = missingMappableCountries.map((country) => ({
218
+ entityName: country.name,
219
+ time: table.maxTime!, // arbitrary time
220
+ value: ErrorValueTypes.MissingValuePlaceholder,
221
+ }))
222
+ table = table.appendRows(
223
+ rows,
224
+ `Append rows for mappable countries without data: ${rows.map((row) => row.entityName).join(", ")}`
225
+ )
226
+
227
+ return table
228
+ }
229
+
230
+ @computed get inputTable(): OwidTable {
231
+ const { mapColumnInfo } = this
232
+ const { table } = this.manager
233
+
234
+ // For historical+projected data, we need to create the combined column
235
+ // on the input table. This ensures the color scale has access to the
236
+ // complete range of data across both columns
237
+ return mapColumnInfo.type === "historical+projected"
238
+ ? combineHistoricalAndProjectionColumns(table, mapColumnInfo)
239
+ : table
240
+ }
241
+
242
+ @computed get transformedTableFromGrapher(): OwidTable {
243
+ return (
244
+ this.manager.transformedTable ??
245
+ this.transformTable(this.inputTable)
246
+ )
247
+ }
248
+
249
+ @computed get transformedTable(): OwidTable {
250
+ let table = this.transformedTableFromGrapher
251
+
252
+ // A target time is set for faceted maps
253
+ if (this.manager.targetTime !== undefined) {
254
+ table = table.filterByTargetTimes(
255
+ [this.manager.targetTime],
256
+ this.mapConfig.timeTolerance ??
257
+ table.get(this.mapColumnSlug).tolerance
258
+ )
259
+ }
260
+
261
+ return table
262
+ }
263
+
264
+ @computed get selectionArray(): MapSelectionArray {
265
+ return this.mapConfig.selection
266
+ }
267
+
268
+ @computed get mapColumn(): CoreColumn {
269
+ return this.transformedTable.get(this.mapColumnSlug)
270
+ }
271
+
272
+ @computed get mapColumnInfo(): MapColumnInfo {
273
+ const mapColumnSlug = this.manager.mapColumnSlug!
274
+
275
+ // If projection info is available, then we can stitch together the
276
+ // historical and projected columns
277
+ const projectionInfo =
278
+ this.manager.projectionColumnInfoBySlug?.get(mapColumnSlug)
279
+ if (projectionInfo) {
280
+ return {
281
+ type: "historical+projected",
282
+ slug: projectionInfo.combinedSlug,
283
+ ...projectionInfo,
284
+ }
285
+ }
286
+
287
+ const type = this.manager.table.get(mapColumnSlug).isProjection
288
+ ? "projected"
289
+ : "historical"
290
+
291
+ return { type, slug: mapColumnSlug }
292
+ }
293
+
294
+ @computed get mapConfig(): MapConfig {
295
+ return this.manager.mapConfig || new MapConfig()
296
+ }
297
+
298
+ @computed get mapColumnSlug(): ColumnSlug {
299
+ return this.mapColumnInfo.slug
300
+ }
301
+
302
+ // The map column without tolerance and timeline filtering applied
303
+ @computed get mapColumnUntransformed(): CoreColumn {
304
+ return this.dropNonMapEntities(this.inputTable).get(this.mapColumnSlug)
305
+ }
306
+
307
+ @computed get colorScaleConfig(): ColorScaleConfig {
308
+ return (
309
+ ColorScaleConfig.fromDSL(this.mapColumn.def) ??
310
+ this.mapConfig.colorScale
311
+ )
312
+ }
313
+
314
+ @computed get colorScaleColumn(): CoreColumn {
315
+ // Use the table before any transforms to collect all possible values over time.
316
+ // Otherwise the legend changes as you slide the timeline handle.
317
+ return this.mapColumnUntransformed
318
+ }
319
+
320
+ @computed get hasProjectedData(): boolean {
321
+ return this.mapColumnInfo.type !== "historical"
322
+ }
323
+
324
+ @computed get hasProjectedDataBin(): boolean {
325
+ return this.hasProjectedData
326
+ }
327
+
328
+ @computed get targetTime(): number | undefined {
329
+ return this.manager.targetTime ?? this.manager.endTime
330
+ }
331
+
332
+ @computed get columnIsProjection(): CoreColumn | undefined {
333
+ const slugForIsProjectionColumn =
334
+ this.mapColumnInfo?.type === "historical+projected"
335
+ ? this.mapColumnInfo.slugForIsProjectionColumn
336
+ : undefined
337
+
338
+ return slugForIsProjectionColumn
339
+ ? this.transformedTable.get(slugForIsProjectionColumn)
340
+ : undefined
341
+ }
342
+
343
+ private checkIsProjection(
344
+ entityName: EntityName,
345
+ originalTime: Time
346
+ ): boolean {
347
+ return match(this.mapColumnInfo.type)
348
+ .with("historical", () => false)
349
+ .with("projected", () => true)
350
+ .with("historical+projected", () =>
351
+ this.columnIsProjection?.valueByEntityNameAndOriginalTime
352
+ .get(entityName)
353
+ ?.get(originalTime)
354
+ )
355
+ .exhaustive()
356
+ }
357
+
358
+ @computed get noDataColor(): Color {
359
+ return this.colorScale.noDataColor
360
+ }
361
+
362
+ @computed get series(): ChoroplethSeries[] {
363
+ const { mapColumn, targetTime } = this
364
+ if (mapColumn.isMissing) return []
365
+ if (targetTime === undefined) return []
366
+
367
+ return mapColumn.owidRows
368
+ .map((row) => {
369
+ const { entityName, value, originalTime } = row
370
+ const color =
371
+ this.colorScale.getColor(value) || this.noDataColor
372
+ const isProjection = this.checkIsProjection(
373
+ entityName,
374
+ originalTime
375
+ )
376
+ return {
377
+ seriesName: entityName,
378
+ time: originalTime,
379
+ value,
380
+ color,
381
+ isProjection,
382
+ } satisfies ChoroplethSeries
383
+ })
384
+ .filter(isPresent)
385
+ }
386
+
387
+ @computed get seriesMap(): ChoroplethSeriesByName {
388
+ return new Map(this.series.map((series) => [series.seriesName, series]))
389
+ }
390
+
391
+ @computed get formatValueForTooltip(): MapFormatValueForTooltip {
392
+ const { mapConfig, colorScale } = this
393
+
394
+ return (d: PrimitiveType, options?: TickFormattingOptions) => {
395
+ if (mapConfig.tooltipUseCustomLabels) {
396
+ // Find the bin (and its label) that this value belongs to
397
+ const bin = colorScale.getBinForValue(d)
398
+ const label = bin?.label
399
+ if (label !== undefined && label !== "")
400
+ return { label, isCategorical: true }
401
+ }
402
+
403
+ if (typeof d === "number") {
404
+ const label = this.mapColumn.formatValueShort(d, options)
405
+ return { label, isCategorical: false }
406
+ } else {
407
+ return { label: anyToString(d), isCategorical: true }
408
+ }
409
+ }
410
+ }
411
+
412
+ @computed get errorInfo(): ChartErrorInfo {
413
+ if (this.mapColumn.isMissing) return { reason: "Missing map column" }
414
+ return { reason: "" }
415
+ }
416
+ }
@@ -0,0 +1,25 @@
1
+ import React from "react"
2
+ import { computed, makeObservable } from "mobx"
3
+ import { observer } from "mobx-react"
4
+ import { ChartInterface } from "../chart/ChartInterface"
5
+ import { MapChartState } from "./MapChartState"
6
+ import { MapChart, MapChartProps } from "./MapChart"
7
+
8
+ @observer
9
+ export class MapChartThumbnail
10
+ extends React.Component<MapChartProps>
11
+ implements ChartInterface
12
+ {
13
+ constructor(props: MapChartProps) {
14
+ super(props)
15
+ makeObservable(this)
16
+ }
17
+
18
+ @computed get chartState(): MapChartState {
19
+ return this.props.chartState
20
+ }
21
+
22
+ override render(): React.ReactElement {
23
+ return <MapChart {...this.props} />
24
+ }
25
+ }