@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,24 @@
1
+ import { ChartSeries } from "../chart/ChartInterface"
2
+ import { ChartManager } from "../chart/ChartManager"
3
+ import { GrapherChartType } from "../../types/index.js"
4
+ import { Bounds } from "../../utils/index.js"
5
+
6
+ export interface FacetChartManager extends ChartManager {
7
+ canSelectMultipleEntities?: boolean
8
+ }
9
+
10
+ export interface FacetChartProps {
11
+ bounds?: Bounds
12
+ chartTypeName?: GrapherChartType
13
+ manager: FacetChartManager
14
+ }
15
+
16
+ export interface FacetSeries extends ChartSeries {
17
+ manager: Partial<ChartManager>
18
+ }
19
+
20
+ export interface PlacedFacetSeries extends FacetSeries {
21
+ manager: ChartManager
22
+ bounds: Bounds
23
+ contentBounds: Bounds
24
+ }
@@ -0,0 +1,51 @@
1
+ import { BASE_FONT_SIZE, GRAPHER_FONT_SCALE_10 } from "../core/GrapherConstants"
2
+
3
+ // not sure if we want to do something more sophisticated
4
+ export const getFontSize = (
5
+ containerWidth: number,
6
+ count: number,
7
+ baseFontSize = BASE_FONT_SIZE,
8
+ minSize = 8
9
+ ): number => {
10
+ // Pick a fixed font size for very small charts
11
+ if (containerWidth < 300) return GRAPHER_FONT_SCALE_10 * baseFontSize
12
+
13
+ // Scale the font size based on the number of series otherwise
14
+ if (count <= 2) return Math.max(minSize, baseFontSize * (15 / 16))
15
+ if (count <= 4) return Math.max(minSize, baseFontSize * (14 / 16))
16
+ if (count <= 9) return Math.max(minSize, baseFontSize * (13 / 16))
17
+ if (count <= 16) return Math.max(minSize, baseFontSize * (12 / 16))
18
+ if (count <= 25) return Math.max(minSize, baseFontSize * (11 / 16))
19
+ return minSize
20
+ }
21
+
22
+ export const getLabelPadding = (baseFontSize: number): number =>
23
+ 0.5 * baseFontSize
24
+
25
+ export const getFacetGridPadding = ({
26
+ baseFontSize,
27
+ shouldAddRowPadding = true,
28
+ shouldAddColumnPadding = true,
29
+ }: {
30
+ baseFontSize: number
31
+ shouldAddRowPadding?: boolean
32
+ shouldAddColumnPadding?: boolean
33
+ }): { rowPadding: number; columnPadding: number; outerPadding: number } => {
34
+ const labelHeight = baseFontSize
35
+ const labelPadding = getLabelPadding(baseFontSize)
36
+
37
+ const rowPadding = shouldAddRowPadding ? baseFontSize : 0
38
+ const columnPadding = shouldAddColumnPadding ? baseFontSize : 0
39
+
40
+ return {
41
+ rowPadding: Math.round(labelHeight + labelPadding + rowPadding),
42
+ columnPadding: Math.round(columnPadding),
43
+ outerPadding: 0,
44
+ }
45
+ }
46
+
47
+ export const calculateAspectRatio = (width: number, height: number): number => {
48
+ const aspectRatio = width / height // can be NaN if height is 0, which can happen when the chart is temporarily hidden
49
+ if (isNaN(aspectRatio)) return 1
50
+ return aspectRatio
51
+ }
@@ -0,0 +1,604 @@
1
+ import React from "react"
2
+ import { observer } from "mobx-react"
3
+ import {
4
+ Bounds,
5
+ GridParameters,
6
+ HorizontalAlign,
7
+ Color,
8
+ makeIdForHumanConsumption,
9
+ exposeInstanceOnWindow,
10
+ SplitBoundsPadding,
11
+ } from "../../utils/index.js"
12
+ import { action, computed, makeObservable, observable } from "mobx"
13
+ import {
14
+ BASE_FONT_SIZE,
15
+ DEFAULT_GRAPHER_BOUNDS,
16
+ GRAPHER_FONT_SCALE_18,
17
+ } from "../core/GrapherConstants"
18
+ import {
19
+ ChartErrorInfo,
20
+ GRAPHER_MAP_TYPE,
21
+ GrapherInteractionEvent,
22
+ MapRegionName,
23
+ Time,
24
+ } from "../../types/index.js"
25
+ import {
26
+ calculateAspectRatio,
27
+ getFacetGridPadding,
28
+ getLabelPadding as getFacetLabelPadding,
29
+ } from "./FacetChartUtils"
30
+ import {
31
+ FacetMapManager,
32
+ MapFacetSeries,
33
+ FacetMapProps,
34
+ PlacedMapFacetSeries,
35
+ } from "./FacetMapConstants"
36
+ import { OwidTable } from "../../core-table/index.js"
37
+ import {
38
+ HorizontalCategoricalColorLegend,
39
+ HorizontalColorLegendManager,
40
+ HorizontalNumericColorLegend,
41
+ } from "../legend/HorizontalColorLegends"
42
+ import { CategoricalBin, ColorScaleBin } from "../color/ColorScaleBin"
43
+ import { GRAPHER_DARK_TEXT, GRAY_30 } from "../color/ColorConstants"
44
+ import {
45
+ LegendInteractionState,
46
+ LegendStyleConfig,
47
+ } from "../legend/LegendInteractionState"
48
+ import {
49
+ MAP_LEGEND_MAX_WIDTH_RATIO,
50
+ MapChart,
51
+ PADDING_BELOW_MAP_LEGEND,
52
+ PADDING_BETWEEN_MAP_AND_LEGEND,
53
+ PADDING_BETWEEN_MAP_LEGENDS,
54
+ } from "../mapCharts/MapChart"
55
+ import { ChartComponent, makeChartInstance } from "../chart/ChartTypeMap"
56
+ import {
57
+ MAP_VIEWPORT_FACETED_WORLD,
58
+ MAP_VIEWPORTS,
59
+ MapChartManager,
60
+ MapViewport,
61
+ } from "../mapCharts/MapChartConstants"
62
+ import { ChartState } from "../chart/ChartInterface.js"
63
+ import { MapConfig } from "../mapCharts/MapConfig"
64
+
65
+ @observer
66
+ export class FacetMap
67
+ extends React.Component<FacetMapProps>
68
+ implements ChartState, HorizontalColorLegendManager
69
+ {
70
+ private legendHoverBin: ColorScaleBin | undefined = undefined
71
+
72
+ constructor(props: FacetMapProps) {
73
+ super(props)
74
+ makeObservable<FacetMap, "legendHoverBin">(this, {
75
+ legendHoverBin: observable.ref,
76
+ })
77
+ }
78
+
79
+ transformTable(table: OwidTable): OwidTable {
80
+ return table
81
+ }
82
+
83
+ @computed get inputTable(): OwidTable {
84
+ return this.manager.table
85
+ }
86
+
87
+ @computed get transformedTable(): OwidTable {
88
+ return (
89
+ this.manager.transformedTable ??
90
+ this.transformTable(this.inputTable)
91
+ )
92
+ }
93
+
94
+ @computed private get manager(): FacetMapManager {
95
+ return this.props.manager
96
+ }
97
+
98
+ @computed private get table(): OwidTable {
99
+ return this.manager.table
100
+ }
101
+
102
+ @computed private get transformedTableFromGrapher(): OwidTable | undefined {
103
+ return this.manager.transformedTable
104
+ }
105
+
106
+ @computed get isStatic(): boolean {
107
+ return !!this.manager.isStatic
108
+ }
109
+
110
+ @computed get errorInfo(): ChartErrorInfo {
111
+ if (this.manager.startTime === undefined)
112
+ return { reason: "No start time selected" }
113
+
114
+ if (this.manager.endTime === undefined)
115
+ return { reason: "No end time selected" }
116
+
117
+ return { reason: "" }
118
+ }
119
+
120
+ @computed private get startTime(): Time {
121
+ return this.manager.startTime!
122
+ }
123
+
124
+ @computed private get endTime(): Time {
125
+ return this.manager.endTime!
126
+ }
127
+
128
+ @computed private get bounds(): Bounds {
129
+ const bounds = this.props.bounds ?? DEFAULT_GRAPHER_BOUNDS
130
+ return bounds.padTop(6)
131
+ }
132
+
133
+ @computed private get facetsContainerBounds(): Bounds {
134
+ return (
135
+ this.bounds
136
+ // Make space for facet labels
137
+ .padTop(this.labelHeight + this.labelPadding)
138
+ // Make space for the legend
139
+ .padBottom(
140
+ this.legendHeight +
141
+ PADDING_BETWEEN_MAP_AND_LEGEND +
142
+ PADDING_BELOW_MAP_LEGEND
143
+ )
144
+ )
145
+ }
146
+
147
+ @computed private get targetTimes(): [Time, Time] {
148
+ return [this.startTime, this.endTime]
149
+ }
150
+
151
+ @computed get fontSize(): number {
152
+ return this.manager.fontSize ?? BASE_FONT_SIZE
153
+ }
154
+
155
+ @computed private get facetFontSize(): number {
156
+ return Math.floor(this.fontSize * GRAPHER_FONT_SCALE_18)
157
+ }
158
+
159
+ @computed private get mapConfig(): MapConfig {
160
+ return this.manager.mapConfig ?? new MapConfig()
161
+ }
162
+
163
+ @computed private get mapViewport(): MapViewport {
164
+ const { region } = this.mapConfig
165
+
166
+ // Use a custom viewport for the World map that zooms in a little bit to make best use of the space
167
+ if (region === MapRegionName.World) return MAP_VIEWPORT_FACETED_WORLD
168
+
169
+ return MAP_VIEWPORTS[region]
170
+ }
171
+
172
+ private getGridParams(bounds: Bounds): GridParameters {
173
+ // We determine the preferred layout (horizontal vs vertical)
174
+ // by comparing which orientation produces an aspect ratio closest to
175
+ // the map's natural aspect ratio. The globe uses the horizontal layout.
176
+
177
+ const horizontalLayout = { rows: 1, columns: 2, count: 2 }
178
+ const verticalLayout = { rows: 2, columns: 1, count: 2 }
179
+
180
+ if (this.mapConfig.globe.isActive)
181
+ return bounds.width > bounds.height
182
+ ? horizontalLayout
183
+ : verticalLayout
184
+
185
+ const mapAspectRatio = this.mapViewport.ratio
186
+
187
+ // If the faceted maps are side-by-side
188
+ const horizontalLayoutAspectRatio = calculateAspectRatio(
189
+ bounds.width / 2,
190
+ bounds.height
191
+ )
192
+
193
+ // If the faceted maps are stacked vertically
194
+ const verticalLayoutAspectRatio = calculateAspectRatio(
195
+ bounds.width,
196
+ bounds.height / 2
197
+ )
198
+
199
+ const horizontalDiff = Math.abs(
200
+ Math.log2(mapAspectRatio / horizontalLayoutAspectRatio)
201
+ )
202
+ const verticalDiff = Math.abs(
203
+ Math.log2(mapAspectRatio / verticalLayoutAspectRatio)
204
+ )
205
+
206
+ // World maps tend to look better side-by-side, so we give the
207
+ // horizontal layout an advantage when the region is World
208
+ const bias = this.mapConfig.region === MapRegionName.World ? 0.5 : 0
209
+
210
+ return horizontalDiff - bias <= verticalDiff
211
+ ? horizontalLayout
212
+ : verticalLayout
213
+ }
214
+
215
+ @computed private get facetGridPadding(): SplitBoundsPadding {
216
+ return getFacetGridPadding({
217
+ baseFontSize: this.facetFontSize,
218
+ shouldAddRowPadding: false,
219
+ })
220
+ }
221
+
222
+ @computed private get labelHeight(): number {
223
+ return this.facetFontSize
224
+ }
225
+
226
+ @computed private get labelPadding(): number {
227
+ return getFacetLabelPadding(this.facetFontSize)
228
+ }
229
+
230
+ @computed get series(): MapFacetSeries[] {
231
+ return this.targetTimes.map((time) => ({
232
+ seriesName: this.table.timeColumn.formatTime(time),
233
+ // Required for a ChartSeries, but isn't meaningful for facets
234
+ color: "none",
235
+ // Only set overrides for this facet. Default properties are set elsewhere.
236
+ manager: { targetTime: time },
237
+ }))
238
+ }
239
+
240
+ @action.bound logGrapherInteractionEvent(
241
+ action: GrapherInteractionEvent,
242
+ target?: string
243
+ ): void {
244
+ this.manager.analytics?.logGrapherInteractionEvent(action, {
245
+ ...this.manager.analyticsContext,
246
+ target,
247
+ })
248
+ }
249
+
250
+ @computed private get intermediatePlacedSeries(): PlacedMapFacetSeries[] {
251
+ const {
252
+ manager,
253
+ series,
254
+ table,
255
+ transformedTableFromGrapher,
256
+ targetTimes,
257
+ mapViewport,
258
+ facetFontSize,
259
+ legendHoverBin,
260
+ logGrapherInteractionEvent,
261
+ } = this
262
+
263
+ // We are using `bounds` instead of `facetsContainerBounds` because the legend
264
+ // is not yet created, and it is derived from the intermediate chart series.
265
+ const bounds = this.bounds
266
+ const gridBoundsArr = bounds.grid(
267
+ this.getGridParams(bounds),
268
+ this.facetGridPadding
269
+ )
270
+
271
+ const {
272
+ backgroundColor,
273
+ isStatic,
274
+ mapColumnSlug = "",
275
+ mapConfig,
276
+ isMapSelectionEnabled,
277
+ colorScale,
278
+ globeController,
279
+ base,
280
+ tooltip,
281
+ shouldPinTooltipToBottom,
282
+ projectionColumnInfoBySlug,
283
+ isFaceted,
284
+ yColumnSlug,
285
+ } = manager
286
+
287
+ return series.map((series, index) => {
288
+ const { bounds } = gridBoundsArr[index]
289
+
290
+ const manager: MapChartManager = {
291
+ table,
292
+ transformedTable: transformedTableFromGrapher,
293
+ fontSize: facetFontSize,
294
+ showLegend: false,
295
+ backgroundColor,
296
+ isStatic,
297
+ mapColumnSlug,
298
+ mapConfig,
299
+ isMapSelectionEnabled,
300
+ colorScale,
301
+ globeController,
302
+ base,
303
+ tooltip,
304
+ shouldPinTooltipToBottom,
305
+ externalLegendHoverBin: legendHoverBin,
306
+ logGrapherInteractionEvent,
307
+ disableIntroAnimation: true,
308
+ projectionColumnInfoBySlug,
309
+ highlightedTimesInTooltip: targetTimes,
310
+ mapViewport,
311
+ isFaceted,
312
+ yColumnSlug,
313
+ ...series.manager,
314
+ }
315
+
316
+ return {
317
+ bounds,
318
+ manager,
319
+ seriesName: series.seriesName,
320
+ color: series.color,
321
+ }
322
+ })
323
+ }
324
+
325
+ @computed private get intermediateMapInstances(): MapChart[] {
326
+ return this.intermediatePlacedSeries.map(
327
+ ({ bounds, manager }) =>
328
+ makeChartInstance({
329
+ manager,
330
+ bounds,
331
+ chartType: GRAPHER_MAP_TYPE,
332
+ variant: this.manager.variant,
333
+ }) as MapChart
334
+ )
335
+ }
336
+
337
+ /**
338
+ * Used to construct the shared legend for all map facets.
339
+ *
340
+ * Unlike in FacetChart, we only need a single MapChart instance to construct
341
+ * the legend since all facets share the same legend.
342
+ */
343
+ @computed get intermediateMapInstance(): MapChart {
344
+ return this.intermediateMapInstances[0]
345
+ }
346
+
347
+ @computed private get gridParams(): GridParameters {
348
+ return this.getGridParams(this.facetsContainerBounds)
349
+ }
350
+
351
+ @computed private get facetArrangement(): "side-by-side" | "stacked" {
352
+ return this.gridParams.rows > this.gridParams.columns
353
+ ? "stacked"
354
+ : "side-by-side"
355
+ }
356
+
357
+ @computed get placedSeries(): PlacedMapFacetSeries[] {
358
+ const bounds = this.facetsContainerBounds
359
+ const gridBoundsArr = bounds.grid(
360
+ this.gridParams,
361
+ this.facetGridPadding
362
+ )
363
+ return this.intermediatePlacedSeries.map((series, i) => {
364
+ const { bounds } = gridBoundsArr[i]
365
+ return { ...series, bounds }
366
+ })
367
+ }
368
+
369
+ @computed private get externalLegend():
370
+ | HorizontalColorLegendManager
371
+ | undefined {
372
+ return this.intermediateMapInstance.externalLegend
373
+ }
374
+
375
+ @computed get legendX(): number {
376
+ return this.bounds.x
377
+ }
378
+
379
+ @computed get numericLegendY(): number {
380
+ if (!this.numericLegend) return 0
381
+ return (
382
+ this.bounds.bottom -
383
+ this.numericLegendHeight -
384
+ PADDING_BELOW_MAP_LEGEND -
385
+ // If present, the category legend is placed below the numeric legend
386
+ (this.categoryLegend
387
+ ? this.categoryLegendHeight + PADDING_BETWEEN_MAP_LEGENDS
388
+ : 0)
389
+ )
390
+ }
391
+
392
+ @computed get categoryLegendY(): number {
393
+ if (!this.categoryLegend) return 0
394
+ return (
395
+ this.bounds.bottom -
396
+ this.categoryLegend.height -
397
+ PADDING_BELOW_MAP_LEGEND
398
+ )
399
+ }
400
+
401
+ @computed get legendMaxWidth(): number {
402
+ return this.bounds.width * MAP_LEGEND_MAX_WIDTH_RATIO
403
+ }
404
+
405
+ @computed get legendAlign(): HorizontalAlign {
406
+ return HorizontalAlign.center
407
+ }
408
+
409
+ @computed get hoverColors(): Color[] | undefined {
410
+ if (!this.legendHoverBin) return undefined
411
+ return [this.legendHoverBin.color]
412
+ }
413
+
414
+ @computed get numericLegendData(): ColorScaleBin[] {
415
+ return this.externalLegend?.numericLegendData ?? []
416
+ }
417
+
418
+ @computed get categoricalLegendData(): CategoricalBin[] {
419
+ return this.externalLegend?.categoricalLegendData ?? []
420
+ }
421
+
422
+ @computed private get numericLegendHeight(): number {
423
+ return this.numericLegend ? this.numericLegend.height : 0
424
+ }
425
+
426
+ @computed private get categoryLegendHeight(): number {
427
+ return this.categoryLegend ? this.categoryLegend.height : 0
428
+ }
429
+
430
+ @computed get legendHeight(): number {
431
+ return this.categoryLegendHeight + this.numericLegendHeight
432
+ }
433
+
434
+ @action.bound onLegendMouseOver(bin: ColorScaleBin): void {
435
+ this.legendHoverBin = bin
436
+ }
437
+
438
+ @action.bound onLegendMouseLeave(): void {
439
+ this.legendHoverBin = undefined
440
+ }
441
+
442
+ @computed private get categoryLegend():
443
+ | HorizontalCategoricalColorLegend
444
+ | undefined {
445
+ return this.categoricalLegendData.length > 1
446
+ ? new HorizontalCategoricalColorLegend({ manager: this })
447
+ : undefined
448
+ }
449
+
450
+ @computed private get numericLegend():
451
+ | HorizontalNumericColorLegend
452
+ | undefined {
453
+ return this.numericLegendData.length > 1
454
+ ? new HorizontalNumericColorLegend({ manager: this })
455
+ : undefined
456
+ }
457
+
458
+ getLegendBinState(bin: ColorScaleBin): LegendInteractionState {
459
+ if (!this.legendHoverBin && !this.mapConfig.hoverCountry) {
460
+ return LegendInteractionState.Default
461
+ }
462
+
463
+ // Check if this bin is being hovered
464
+ if (this.legendHoverBin && bin.equals(this.legendHoverBin)) {
465
+ return LegendInteractionState.Focused
466
+ }
467
+
468
+ // Check if a country is being hovered and matches this bin
469
+ if (this.mapConfig.hoverCountry) {
470
+ const series = this.intermediateMapInstances.map((mapChart) =>
471
+ mapChart.chartState.series.find(
472
+ (s) => s.seriesName === this.mapConfig.hoverCountry
473
+ )
474
+ )
475
+ if (series.some((s) => s?.color === bin.color))
476
+ return LegendInteractionState.Focused
477
+ }
478
+
479
+ return LegendInteractionState.Muted
480
+ }
481
+
482
+ @computed get legendStyleConfig(): LegendStyleConfig | undefined {
483
+ return this.externalLegend?.legendStyleConfig
484
+ }
485
+
486
+ override componentDidMount(): void {
487
+ exposeInstanceOnWindow(this, "facetMap")
488
+ }
489
+
490
+ private getLabelPosition(facet: PlacedMapFacetSeries): {
491
+ x: number
492
+ y: number
493
+ } {
494
+ const { mapConfig, labelPadding } = this
495
+ const { bounds } = facet
496
+
497
+ const labelX = bounds.centerX
498
+ let labelY = bounds.top - labelPadding
499
+
500
+ // For the globe and 2D continent views, simply render the label at the top
501
+ if (
502
+ mapConfig.globe.isActive ||
503
+ mapConfig.region !== MapRegionName.World
504
+ )
505
+ return { x: labelX, y: labelY }
506
+
507
+ // There is often quite a bit of vertical padding around the 2D World map.
508
+ // It looks nicer to position the facet label closer to the actual map content
509
+ // rather than at the very top
510
+
511
+ const mapAspectRatio = MAP_VIEWPORT_FACETED_WORLD.ratio
512
+
513
+ // Find the map's width and height
514
+ let mapWidth = bounds.width
515
+ let mapHeight = mapWidth / mapAspectRatio
516
+ if (mapHeight > bounds.height) {
517
+ mapHeight = bounds.height
518
+ mapWidth = mapHeight * mapAspectRatio
519
+ }
520
+
521
+ // Move the label closer to the map if there is vertical padding
522
+ if (mapHeight < bounds.height) {
523
+ const shiftY = (bounds.height - mapHeight) / 2
524
+ labelY = Math.max(labelY, labelY + shiftY - 3 * labelPadding)
525
+ }
526
+
527
+ return { x: labelX, y: labelY }
528
+ }
529
+
530
+ private renderMapLegend(): React.ReactElement {
531
+ return (
532
+ <>
533
+ {this.numericLegend && (
534
+ <HorizontalNumericColorLegend manager={this} />
535
+ )}
536
+ {this.categoryLegend && (
537
+ <HorizontalCategoricalColorLegend manager={this} />
538
+ )}
539
+ </>
540
+ )
541
+ }
542
+
543
+ private renderSeparatorLine(): React.ReactElement | null {
544
+ const {
545
+ mapConfig,
546
+ facetArrangement,
547
+ facetsContainerBounds: bounds,
548
+ } = this
549
+
550
+ // It can be difficult to visually distinguish two continent maps
551
+ // when plotted side by side, so we draw a gray line between them
552
+ if (
553
+ mapConfig.region !== MapRegionName.World &&
554
+ facetArrangement === "side-by-side"
555
+ ) {
556
+ return (
557
+ <line
558
+ x1={bounds.centerX}
559
+ y1={bounds.top}
560
+ x2={bounds.centerX}
561
+ y2={bounds.bottom}
562
+ stroke={GRAY_30}
563
+ />
564
+ )
565
+ }
566
+
567
+ return null
568
+ }
569
+
570
+ override render(): React.ReactElement {
571
+ const { facetFontSize } = this
572
+ return (
573
+ <>
574
+ {this.renderMapLegend()}
575
+ {this.renderSeparatorLine()}
576
+ {this.placedSeries.map((series) => {
577
+ const { bounds, seriesName } = series
578
+
579
+ return (
580
+ <React.Fragment key={seriesName}>
581
+ <text
582
+ {...this.getLabelPosition(series)}
583
+ fill={GRAPHER_DARK_TEXT}
584
+ fontSize={facetFontSize}
585
+ textAnchor="middle"
586
+ style={{ fontWeight: 700 }}
587
+ >
588
+ {seriesName}
589
+ </text>
590
+ <g id={makeIdForHumanConsumption(seriesName)}>
591
+ <ChartComponent
592
+ manager={series.manager}
593
+ chartType={GRAPHER_MAP_TYPE}
594
+ variant={this.manager.variant}
595
+ bounds={bounds}
596
+ />
597
+ </g>
598
+ </React.Fragment>
599
+ )
600
+ })}
601
+ </>
602
+ )
603
+ }
604
+ }
@@ -0,0 +1,23 @@
1
+ import { ChartSeries } from "../chart/ChartInterface"
2
+ import { Bounds, GrapherAnalyticsContext } from "../../utils/index.js"
3
+ import { MapChartManager } from "../mapCharts/MapChartConstants"
4
+ import { GrapherAnalytics } from "../core/GrapherAnalytics"
5
+
6
+ export interface FacetMapManager extends MapChartManager {
7
+ analytics?: GrapherAnalytics
8
+ analyticsContext?: GrapherAnalyticsContext
9
+ }
10
+
11
+ export interface FacetMapProps {
12
+ bounds?: Bounds
13
+ manager: FacetMapManager
14
+ }
15
+
16
+ export interface MapFacetSeries extends ChartSeries {
17
+ manager: Partial<MapChartManager>
18
+ }
19
+
20
+ export interface PlacedMapFacetSeries extends MapFacetSeries {
21
+ manager: MapChartManager
22
+ bounds: Bounds
23
+ }