@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,523 @@
1
+ import * as _ from "lodash-es"
2
+ import * as React from "react"
3
+ import { computed, makeObservable } from "mobx"
4
+ import { observer } from "mobx-react"
5
+ import {
6
+ Bounds,
7
+ exposeInstanceOnWindow,
8
+ makeIdForHumanConsumption,
9
+ } from "../../utils/index.js"
10
+ import { MarkdownTextWrap, LoadingIndicator } from "../../components/index.js"
11
+ import { Header, StaticHeader } from "../header/Header"
12
+ import { Footer, StaticFooter } from "../footer/Footer"
13
+ import {
14
+ STATIC_EXPORT_DETAIL_SPACING,
15
+ GRAPHER_FRAME_PADDING_VERTICAL,
16
+ GRAPHER_FRAME_PADDING_HORIZONTAL,
17
+ DEFAULT_GRAPHER_BOUNDS,
18
+ } from "../core/GrapherConstants"
19
+ import { MapChartManager } from "../mapCharts/MapChartConstants"
20
+ import { ChartManager } from "../chart/ChartManager"
21
+ import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons"
22
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
23
+ import { FooterManager } from "../footer/FooterManager"
24
+ import { HeaderManager } from "../header/HeaderManager"
25
+ import { SelectionArray } from "../selection/SelectionArray"
26
+ import {
27
+ EntityName,
28
+ RelatedQuestionsConfig,
29
+ Color,
30
+ GrapherTabName,
31
+ GrapherChartType,
32
+ } from "../../types/index.js"
33
+ import { DataTableManager } from "../dataTable/DataTableConstants"
34
+ import {
35
+ TimelineComponent,
36
+ TIMELINE_HEIGHT,
37
+ } from "../timeline/TimelineComponent"
38
+ import { TimelineController } from "../timeline/TimelineController"
39
+ import {
40
+ ControlsRow,
41
+ ControlsRowManager,
42
+ } from "../controls/controlsRow/ControlsRow"
43
+ import { GRAPHER_BACKGROUND_DEFAULT } from "../color/ColorConstants.js"
44
+ import { ChartAreaContent } from "../chart/ChartAreaContent"
45
+ import { getChartSvgProps } from "../chart/ChartUtils"
46
+ import { StaticChartWrapper } from "../chart/StaticChartWrapper"
47
+
48
+ export interface CaptionedChartManager
49
+ extends ChartManager,
50
+ MapChartManager,
51
+ FooterManager,
52
+ HeaderManager,
53
+ DataTableManager,
54
+ ControlsRowManager {
55
+ bakedGrapherURL?: string
56
+ isReady?: boolean
57
+ whatAreWeWaitingFor?: string
58
+
59
+ // bounds
60
+ captionedChartBounds?: Bounds
61
+ sidePanelBounds?: Bounds
62
+ staticBounds?: Bounds
63
+ staticBoundsWithDetails?: Bounds
64
+
65
+ // layout & style
66
+ isSmall?: boolean
67
+ isMedium?: boolean
68
+ fontSize?: number
69
+ backgroundColor?: string
70
+
71
+ // state
72
+ activeTab?: GrapherTabName
73
+ isOnMapTab?: boolean
74
+ isOnTableTab?: boolean
75
+ activeChartType?: GrapherChartType
76
+ isFaceted?: boolean
77
+ isExportingForSocialMedia?: boolean
78
+ isExportingForWikimedia?: boolean
79
+
80
+ // timeline
81
+ hasTimeline?: boolean
82
+ timelineController?: TimelineController
83
+
84
+ // details on demand
85
+ shouldIncludeDetailsInStaticExport?: boolean
86
+ detailRenderers: MarkdownTextWrap[]
87
+
88
+ // related question
89
+ relatedQuestions?: RelatedQuestionsConfig[]
90
+ showRelatedQuestion?: boolean
91
+ }
92
+
93
+ interface CaptionedChartProps {
94
+ manager: CaptionedChartManager
95
+ bounds?: Bounds
96
+ maxWidth?: number
97
+ }
98
+
99
+ // keep in sync with sass variables in CaptionedChart.scss
100
+ export const CONTROLS_ROW_HEIGHT = 32
101
+
102
+ abstract class AbstractCaptionedChart extends React.Component<CaptionedChartProps> {
103
+ protected framePaddingHorizontal = GRAPHER_FRAME_PADDING_HORIZONTAL
104
+ protected framePaddingVertical = GRAPHER_FRAME_PADDING_VERTICAL
105
+
106
+ constructor(props: CaptionedChartProps) {
107
+ super(props)
108
+ makeObservable(this)
109
+ }
110
+
111
+ @computed protected get manager(): CaptionedChartManager {
112
+ return this.props.manager
113
+ }
114
+
115
+ @computed protected get maxWidth(): number {
116
+ return (
117
+ this.props.maxWidth ??
118
+ this.bounds.width - 2 * this.framePaddingHorizontal
119
+ )
120
+ }
121
+
122
+ @computed protected get verticalPadding(): number {
123
+ return this.manager.isSmall ? 8 : this.manager.isMedium ? 12 : 16
124
+ }
125
+
126
+ @computed protected get verticalPaddingSmall(): number {
127
+ if (this.manager.isOnMapTab) return 4
128
+ return this.manager.isMedium ? 8 : 16
129
+ }
130
+
131
+ @computed protected get header(): Header {
132
+ return new Header({
133
+ manager: this.manager,
134
+ maxWidth: this.maxWidth,
135
+ })
136
+ }
137
+
138
+ @computed protected get footer(): Footer {
139
+ return new Footer({
140
+ manager: this.manager,
141
+ maxWidth: this.maxWidth,
142
+ })
143
+ }
144
+
145
+ @computed protected get bounds(): Bounds {
146
+ const bounds =
147
+ this.props.bounds ??
148
+ this.manager.captionedChartBounds ??
149
+ DEFAULT_GRAPHER_BOUNDS
150
+ // the padding ensures grapher's frame is not cut off
151
+ return bounds.padRight(2).padBottom(2)
152
+ }
153
+
154
+ @computed protected get boundsForChartArea(): Bounds {
155
+ const { bounds, chartHeight } = this
156
+ return new Bounds(0, 0, bounds.width, chartHeight)
157
+ }
158
+
159
+ override componentDidMount(): void {
160
+ exposeInstanceOnWindow(this, "captionedChart")
161
+ }
162
+
163
+ @computed get selectionArray(): SelectionArray | EntityName[] | undefined {
164
+ return this.manager.selection
165
+ }
166
+
167
+ @computed private get showRelatedQuestion(): boolean {
168
+ return !!this.manager.showRelatedQuestion
169
+ }
170
+
171
+ @computed get relatedQuestionHeight(): number {
172
+ if (!this.showRelatedQuestion) return 0
173
+ return this.manager.isMedium ? 24 : 28
174
+ }
175
+
176
+ @computed private get showControlsRow(): boolean {
177
+ return ControlsRow.shouldShow(this.manager)
178
+ }
179
+
180
+ @computed private get settingsPopoverMaxWidth(): number {
181
+ const availableWidth =
182
+ this.bounds.width - 2 * this.framePaddingHorizontal
183
+
184
+ // Ensure the popover is at most 300px wide
185
+ return Math.min(300, Math.floor(availableWidth))
186
+ }
187
+
188
+ @computed private get settingsPopoverMaxHeight(): number {
189
+ const availableHeight =
190
+ this.bounds.height -
191
+ 2 * this.framePaddingVertical -
192
+ this.headerHeightWithPadding -
193
+ this.controlsRowHeightWithPadding
194
+
195
+ return Math.floor(availableHeight)
196
+ }
197
+
198
+ private renderControlsRow(): React.ReactElement {
199
+ return (
200
+ <ControlsRow
201
+ manager={this.manager}
202
+ maxWidth={this.maxWidth}
203
+ popoverMaxWidth={this.settingsPopoverMaxWidth}
204
+ popoverMaxHeight={this.settingsPopoverMaxHeight}
205
+ />
206
+ )
207
+ }
208
+
209
+ private renderRelatedQuestion(): React.ReactElement {
210
+ const { relatedQuestions } = this.manager
211
+ return (
212
+ <div
213
+ className="relatedQuestion"
214
+ style={{
215
+ width: this.bounds.width,
216
+ height: this.relatedQuestionHeight,
217
+ padding: `0 ${this.framePaddingHorizontal}px`,
218
+ }}
219
+ >
220
+ Related:&nbsp;
221
+ <a
222
+ href={relatedQuestions![0].url}
223
+ target="_blank"
224
+ rel="noopener"
225
+ data-track-note="chart_click_related"
226
+ >
227
+ {relatedQuestions![0].text}
228
+ </a>
229
+ <FontAwesomeIcon icon={faExternalLinkAlt} />
230
+ </div>
231
+ )
232
+ }
233
+
234
+ private renderLoadingIndicator(): React.ReactElement {
235
+ return (
236
+ <LoadingIndicator
237
+ title={this.manager.whatAreWeWaitingFor}
238
+ bounds={this.bounds}
239
+ />
240
+ )
241
+ }
242
+
243
+ private renderTimeline(): React.ReactElement {
244
+ return (
245
+ <TimelineComponent
246
+ timelineController={this.manager.timelineController!}
247
+ maxWidth={this.maxWidth}
248
+ />
249
+ )
250
+ }
251
+
252
+ @computed private get headerHeightWithPadding(): number {
253
+ return this.header.height + this.verticalPadding
254
+ }
255
+
256
+ @computed private get footerHeightWithPadding(): number {
257
+ return this.footer.height + this.verticalPadding
258
+ }
259
+
260
+ @computed private get controlsRowHeightWithPadding(): number {
261
+ return this.showControlsRow
262
+ ? CONTROLS_ROW_HEIGHT + this.verticalPaddingSmall
263
+ : 0
264
+ }
265
+
266
+ @computed private get timelineHeightWithPadding(): number {
267
+ return this.manager.hasTimeline
268
+ ? TIMELINE_HEIGHT + this.verticalPaddingSmall
269
+ : 0
270
+ }
271
+
272
+ @computed private get relatedQuestionHeightWithPadding(): number {
273
+ return this.showRelatedQuestion
274
+ ? this.relatedQuestionHeight - this.framePaddingVertical * 0.25
275
+ : 0
276
+ }
277
+
278
+ /**
279
+ * The height of the chart area is the total height of the frame minus
280
+ * the height of the header, footer, controls, etc.
281
+ */
282
+ @computed protected get chartHeight(): number {
283
+ return Math.floor(
284
+ this.bounds.height -
285
+ 2 * this.framePaddingVertical -
286
+ this.headerHeightWithPadding -
287
+ this.controlsRowHeightWithPadding -
288
+ this.timelineHeightWithPadding -
289
+ this.footerHeightWithPadding -
290
+ this.relatedQuestionHeightWithPadding
291
+ )
292
+ }
293
+
294
+ // make sure to keep this.chartHeight in sync if you edit the render function
295
+ override render(): React.ReactElement {
296
+ // CaptionedChart renders at the very least a header, a chart, and a footer.
297
+ // Interactive charts also have controls above the chart area and a timeline below it.
298
+ // Some charts have a related question below the footer.
299
+ // A CaptionedChart looks like this (components in [brackets] are optional):
300
+ // #1 Header
301
+ // ---- vertical space
302
+ // #2 [Controls]
303
+ // ---- vertical space (small)
304
+ // #3 Chart/Map/Table
305
+ // ---- vertical space (small)
306
+ // #4 [Timeline]
307
+ // ---- vertical space
308
+ // #5 Footer
309
+ // #6 [Related question]
310
+ return (
311
+ <div
312
+ className="CaptionedChart"
313
+ style={{
314
+ backgroundColor: this.backgroundColor,
315
+ }}
316
+ >
317
+ {/* #1 Header */}
318
+ <Header manager={this.manager} maxWidth={this.maxWidth} />
319
+ <VerticalSpace height={this.verticalPadding} />
320
+
321
+ {this.manager.isReady ? (
322
+ <>
323
+ {/* #2 [Controls] */}
324
+ {this.showControlsRow && this.renderControlsRow()}
325
+ {this.showControlsRow && (
326
+ <VerticalSpace height={this.verticalPaddingSmall} />
327
+ )}
328
+
329
+ {/* #3 Chart/Map/Table */}
330
+ <ChartAreaContent
331
+ manager={this.manager}
332
+ bounds={this.boundsForChartArea}
333
+ padWidth={GRAPHER_FRAME_PADDING_HORIZONTAL}
334
+ />
335
+
336
+ {/* #4 [Timeline] */}
337
+ {this.manager.hasTimeline && (
338
+ <VerticalSpace height={this.verticalPaddingSmall} />
339
+ )}
340
+ {this.manager.hasTimeline && this.renderTimeline()}
341
+
342
+ {/* #5 Footer */}
343
+ <VerticalSpace height={this.verticalPadding} />
344
+ <Footer
345
+ manager={this.manager}
346
+ maxWidth={this.maxWidth}
347
+ />
348
+
349
+ {/* #6 [Related question] */}
350
+ {this.showRelatedQuestion &&
351
+ this.renderRelatedQuestion()}
352
+ </>
353
+ ) : (
354
+ this.renderLoadingIndicator()
355
+ )}
356
+ </div>
357
+ )
358
+ }
359
+
360
+ @computed protected get backgroundColor(): Color {
361
+ return this.manager.backgroundColor ?? GRAPHER_BACKGROUND_DEFAULT
362
+ }
363
+
364
+ @computed protected get svgProps(): React.SVGProps<SVGSVGElement> {
365
+ return getChartSvgProps(this.manager)
366
+ }
367
+ }
368
+
369
+ @observer
370
+ export class CaptionedChart extends AbstractCaptionedChart {}
371
+
372
+ @observer
373
+ export class StaticCaptionedChart extends AbstractCaptionedChart {
374
+ constructor(props: CaptionedChartProps) {
375
+ super(props)
376
+ makeObservable(this)
377
+ }
378
+
379
+ // Bounds diagram
380
+ //
381
+ // +---------------------------+ | |
382
+ // | Padding | | |
383
+ // | +--------------------+ | | | |
384
+ // | | Header | | | | |
385
+ // | | | | | | |
386
+ // | | Chart area | | | | |
387
+ // | | | | | | |
388
+ // | | Footer | | | | | innerBounds
389
+ // | +--------------------+ | | |
390
+ // | Padding | | |
391
+ // +---------------------------+ | | bounds
392
+ // | Details | |
393
+ // +---------------------------+ | svgBounds
394
+
395
+ /** Bounds of the SVG element including details */
396
+ @computed private get svgBounds(): Bounds {
397
+ return this.manager.staticBoundsWithDetails ?? this.bounds
398
+ }
399
+
400
+ /** Bounds without details */
401
+ protected override get bounds(): Bounds {
402
+ return (
403
+ this.props.bounds ??
404
+ this.manager.staticBounds ??
405
+ DEFAULT_GRAPHER_BOUNDS
406
+ )
407
+ }
408
+
409
+ /** Padded bounds of the actual chart area (without whitespace around it) */
410
+ @computed private get innerBounds(): Bounds {
411
+ return this.bounds
412
+ .padWidth(this.framePaddingHorizontal)
413
+ .padHeight(this.framePaddingVertical)
414
+ }
415
+
416
+ /** Bounds of the chart area (without header and footer) */
417
+ protected override get boundsForChartArea(): Bounds {
418
+ return this.innerBounds
419
+ .padTop(this.staticHeader.height)
420
+ .padBottom(this.staticFooter.height + this.verticalPadding)
421
+ .padTop(this.manager.isOnMapTab ? 0 : this.verticalPadding)
422
+ }
423
+
424
+ @computed protected get staticFooter(): Footer {
425
+ return new StaticFooter({
426
+ manager: this.manager,
427
+ maxWidth: this.maxWidth,
428
+ targetX: this.innerBounds.x,
429
+ targetY: this.innerBounds.bottom - this.footer.height,
430
+ })
431
+ }
432
+
433
+ @computed protected get staticHeader(): Header {
434
+ return new StaticHeader({
435
+ manager: this.manager,
436
+ maxWidth: this.maxWidth,
437
+ targetX: this.innerBounds.x,
438
+ targetY: this.innerBounds.y,
439
+ })
440
+ }
441
+
442
+ renderSVGDetails(): React.ReactElement {
443
+ let yOffset = 0
444
+ let previousOffset = 0
445
+ return (
446
+ <>
447
+ <line
448
+ id={makeIdForHumanConsumption("separator-line")}
449
+ x1={this.framePaddingHorizontal}
450
+ y1={this.bounds.height}
451
+ x2={
452
+ this.boundsForChartArea.width +
453
+ this.framePaddingHorizontal
454
+ }
455
+ y2={this.bounds.height}
456
+ stroke="#e7e7e7"
457
+ ></line>
458
+ <g
459
+ id={makeIdForHumanConsumption("details")}
460
+ transform={`translate(15, ${
461
+ // + padding below the grey line
462
+ this.bounds.height + this.framePaddingVertical
463
+ })`}
464
+ >
465
+ {this.manager.detailRenderers.map((detail, i) => {
466
+ previousOffset = yOffset
467
+ yOffset += detail.height + STATIC_EXPORT_DETAIL_SPACING
468
+ return (
469
+ <React.Fragment key={i}>
470
+ {detail.renderSVG(0, previousOffset)}
471
+ </React.Fragment>
472
+ )
473
+ })}
474
+ </g>
475
+ </>
476
+ )
477
+ }
478
+
479
+ override render(): React.ReactElement {
480
+ const { innerBounds, manager, maxWidth } = this
481
+
482
+ const includeDetailsInStaticExport =
483
+ manager.shouldIncludeDetailsInStaticExport &&
484
+ !_.isEmpty(this.manager.detailRenderers)
485
+
486
+ return (
487
+ <StaticChartWrapper manager={this.manager} bounds={this.svgBounds}>
488
+ <StaticHeader
489
+ manager={manager}
490
+ maxWidth={maxWidth}
491
+ targetX={innerBounds.x}
492
+ targetY={innerBounds.y}
493
+ />
494
+ <ChartAreaContent
495
+ manager={this.manager}
496
+ bounds={this.boundsForChartArea}
497
+ />
498
+ <StaticFooter
499
+ manager={manager}
500
+ maxWidth={maxWidth}
501
+ targetX={innerBounds.x}
502
+ targetY={innerBounds.bottom - this.staticFooter.height}
503
+ />
504
+ {includeDetailsInStaticExport && this.renderSVGDetails()}
505
+ </StaticChartWrapper>
506
+ )
507
+ }
508
+ }
509
+
510
+ // Although a bit unconventional, adding vertical space as a <div />
511
+ // makes margin collapsing impossible and makes it easier to track the
512
+ // space available for the chart area (see the CaptionedChart's `chartHeight` method)
513
+ function VerticalSpace({ height }: { height: number }): React.ReactElement {
514
+ return (
515
+ <div
516
+ className="VerticalSpace"
517
+ style={{
518
+ height,
519
+ width: "100%",
520
+ }}
521
+ />
522
+ )
523
+ }
@@ -0,0 +1,141 @@
1
+ import * as React from "react"
2
+ import {
3
+ BUILDCANADA_LOGO_SVG,
4
+ BUILDCANADA_WIDE_LOGO_SVG,
5
+ CANADASPENDS_LOGO_SVG,
6
+ CORE_LOGO_SVG,
7
+ GV_LOGO_SVG,
8
+ OWID_LOGO_SVG,
9
+ SMALL_OWID_LOGO_SVG,
10
+ } from "./LogosSVG"
11
+ import { LogoOption } from "../../types/index.js"
12
+ import { makeIdForHumanConsumption } from "../../utils/index.js"
13
+
14
+ interface LogoAttributes {
15
+ svg: string
16
+ width: number
17
+ height: number
18
+ targetHeight: number
19
+ url?: string
20
+ }
21
+
22
+ const logos: Record<LogoOption, LogoAttributes> = {
23
+ owid: {
24
+ svg: OWID_LOGO_SVG,
25
+ width: 65,
26
+ height: 36,
27
+ targetHeight: 36,
28
+ url: "https://ourworldindata.org",
29
+ },
30
+ "core+owid": {
31
+ svg: CORE_LOGO_SVG,
32
+ width: 102,
33
+ height: 37,
34
+ targetHeight: 36,
35
+ },
36
+ "gv+owid": {
37
+ svg: GV_LOGO_SVG,
38
+ width: 420,
39
+ height: 350,
40
+ targetHeight: 52,
41
+ },
42
+ buildcanada: {
43
+ svg: BUILDCANADA_LOGO_SVG,
44
+ width: 65,
45
+ height: 65,
46
+ targetHeight: 36,
47
+ url: "https://buildcanada.ca",
48
+ },
49
+ "buildcanada-wide": {
50
+ svg: BUILDCANADA_WIDE_LOGO_SVG,
51
+ width: 107,
52
+ height: 65,
53
+ targetHeight: 36,
54
+ url: "https://buildcanada.ca",
55
+ },
56
+ canadaspends: {
57
+ svg: CANADASPENDS_LOGO_SVG,
58
+ width: 117,
59
+ height: 36,
60
+ targetHeight: 36,
61
+ url: "https://canadaspends.ca",
62
+ },
63
+ }
64
+
65
+ // owid logo optimized for small sizes
66
+ const smallOwidLogo = {
67
+ svg: SMALL_OWID_LOGO_SVG,
68
+ width: 51,
69
+ height: 28,
70
+ targetHeight: 28,
71
+ url: "https://ourworldindata.org",
72
+ }
73
+
74
+ interface LogoProps {
75
+ logo?: LogoOption
76
+ isLink: boolean
77
+ heightScale?: number
78
+ useSmallVersion?: boolean
79
+ }
80
+
81
+ export class Logo {
82
+ props: LogoProps
83
+ constructor(props: LogoProps) {
84
+ this.props = props
85
+ }
86
+
87
+ private get logo(): LogoOption {
88
+ return this.props.logo ?? LogoOption["buildcanada-wide"]
89
+ }
90
+
91
+ private get spec(): LogoAttributes {
92
+ if (this.props.useSmallVersion && this.logo === LogoOption.owid) {
93
+ return smallOwidLogo
94
+ }
95
+ return logos[this.logo]
96
+ }
97
+
98
+ private get targetHeight(): number {
99
+ return (this.props.heightScale ?? 1) * this.spec.targetHeight
100
+ }
101
+
102
+ private get scale(): number {
103
+ return this.targetHeight / this.spec.height
104
+ }
105
+
106
+ get width(): number {
107
+ return this.spec.width * this.scale
108
+ }
109
+ get height(): number {
110
+ return this.spec.height * this.scale
111
+ }
112
+
113
+ renderSVG(targetX: number, targetY: number): React.ReactElement {
114
+ const { scale } = this
115
+ const svg =
116
+ (this.spec.svg.match(/<svg>(.*)<\/svg>/) || "")[1] || this.spec.svg
117
+ return (
118
+ <g
119
+ id={makeIdForHumanConsumption("logo")}
120
+ transform={`translate(${Math.round(
121
+ targetX
122
+ )}, ${targetY}) scale(${parseFloat(scale.toFixed(2))})`}
123
+ dangerouslySetInnerHTML={{ __html: svg }}
124
+ />
125
+ )
126
+ }
127
+
128
+ renderHTML(): React.ReactElement {
129
+ const { spec } = this
130
+ const props: React.HTMLAttributes<HTMLElement> = {
131
+ className: "logo",
132
+ dangerouslySetInnerHTML: { __html: spec.svg },
133
+ style: { height: `${this.targetHeight}px` },
134
+ }
135
+ if (this.props.isLink && spec.url)
136
+ return (
137
+ <a {...props} href={spec.url} target="_blank" rel="noopener" />
138
+ )
139
+ else return <div {...props} />
140
+ }
141
+ }