@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,311 @@
1
+ import { trimMatrix } from "../../core-table/index.js"
2
+ import {
3
+ isPresent,
4
+ GitCommit,
5
+ SerializedGridProgram,
6
+ } from "../../utils/index.js"
7
+
8
+ import { GridCell } from "./GridCell.js"
9
+ import {
10
+ CellDef,
11
+ CellPosition,
12
+ GRID_CELL_DELIMITER,
13
+ GRID_EDGE_DELIMITER,
14
+ GRID_NODE_DELIMITER,
15
+ Origin,
16
+ ParsedCell,
17
+ } from "./GridLangConstants.js"
18
+ import { tsvToMatrix } from "./GrammarUtils.js"
19
+
20
+ /**
21
+ * Block location for the below would be like (numRows = 2)
22
+ * table |
23
+ * slug name | startRow = 1
24
+ * pop Population | endRow = 2
25
+ */
26
+ interface BlockLocation {
27
+ startRow: number
28
+ endRow: number
29
+ numRows: number
30
+ }
31
+
32
+ export class GridProgram {
33
+ constructor(
34
+ slug: string,
35
+ tsv: string,
36
+ lastCommit?: GitCommit,
37
+ grammar?: CellDef
38
+ ) {
39
+ this.lines = tsvToMatrix(tsv.replace(/\r/g, ""))
40
+ this.slug = slug
41
+ this.lastCommit = lastCommit
42
+ this.grammar = grammar
43
+ }
44
+
45
+ private grammar?
46
+
47
+ private static guids = 0
48
+ guid = ++GridProgram.guids
49
+
50
+ lastCommit?: GitCommit
51
+ slug: string
52
+
53
+ private nodeDelimiter = GRID_NODE_DELIMITER
54
+ cellDelimiter = GRID_CELL_DELIMITER
55
+ private edgeDelimiter = GRID_EDGE_DELIMITER
56
+ lines: string[][]
57
+
58
+ toJson(): SerializedGridProgram {
59
+ return {
60
+ program: this.toString(),
61
+ slug: this.slug,
62
+ lastCommit: this.lastCommit,
63
+ }
64
+ }
65
+
66
+ findNext(position: CellPosition) {
67
+ const cell = this.getCell(position)
68
+ const { contents } = cell
69
+ return this.grepFirst(contents, {
70
+ ...position,
71
+ column: position.column + 1,
72
+ })
73
+ }
74
+
75
+ findAll(position: CellPosition) {
76
+ const cell = this.getCell(position)
77
+ const { contents } = cell
78
+ return this.grep(contents, {
79
+ ...position,
80
+ column: position.column + 1,
81
+ })
82
+ }
83
+
84
+ private ring(position: CellPosition) {
85
+ const lines = this.lines
86
+ const numRows = lines.length
87
+ if (!numRows)
88
+ return (function* generator() {
89
+ // no rows to iterate over
90
+ })()
91
+ const pointer = {
92
+ ...position,
93
+ started: false,
94
+ endRow: position.row,
95
+ endCol: position.column,
96
+ }
97
+ if (pointer.row >= numRows) pointer.endRow = numRows - 1
98
+
99
+ const lastLine = lines[pointer.endRow]
100
+ pointer.endCol =
101
+ lastLine[pointer.endCol] === undefined
102
+ ? lastLine.length
103
+ : pointer.endCol
104
+ function* generator() {
105
+ while (true) {
106
+ if (
107
+ pointer.started &&
108
+ pointer.row === pointer.endRow &&
109
+ pointer.column === pointer.endCol
110
+ )
111
+ return
112
+ pointer.started = true
113
+
114
+ if (
115
+ lines[pointer.row] === undefined ||
116
+ lines[pointer.row][pointer.column] === undefined
117
+ ) {
118
+ pointer.row++
119
+ pointer.column = 0
120
+ if (pointer.row >= numRows) pointer.row = 0
121
+ continue
122
+ }
123
+
124
+ yield {
125
+ row: pointer.row,
126
+ column: pointer.column,
127
+ } as CellPosition
128
+ pointer.column++
129
+ }
130
+ }
131
+
132
+ return generator()
133
+ }
134
+
135
+ valuesFrom(position = Origin) {
136
+ return Array.from(this.ring(position)).map((next) =>
137
+ this.getCellContents(next)
138
+ )
139
+ }
140
+
141
+ get numRows() {
142
+ return this.lines.length
143
+ }
144
+
145
+ patch(obj: any) {
146
+ Object.keys(obj).forEach((key) => this.setLineValue(key, obj[key]))
147
+ return this
148
+ }
149
+
150
+ grepFirst(key: string, position = Origin) {
151
+ for (const next of this.ring(position)) {
152
+ if (this.getCellContents(next) === key) return next
153
+ }
154
+ return undefined
155
+ }
156
+
157
+ grep(key: string, position = Origin) {
158
+ const hits: CellPosition[] = []
159
+ for (const next of this.ring(position)) {
160
+ if (this.getCellContents(next) === key) hits.push(next)
161
+ }
162
+ return hits
163
+ }
164
+
165
+ /**
166
+ * Returns all non-blocks as an object literal
167
+ */
168
+ get tuplesObject() {
169
+ const obj: { [key: string]: any } = {}
170
+ this.lines
171
+ .filter((line) => line[0] !== "")
172
+ .forEach((line) => {
173
+ const [key, ...rest] = line
174
+ if (key) obj[key.trim()] = rest.join(this.cellDelimiter).trim()
175
+ })
176
+ return obj
177
+ }
178
+
179
+ getLine(keyword: string) {
180
+ return this.lines.find((line) => line[0] === keyword)
181
+ }
182
+
183
+ getLineValue(keyword: string) {
184
+ const line = this.getLine(keyword)
185
+ return line?.[1]
186
+ }
187
+
188
+ protected getBlockLocation(
189
+ blockRowNumber: number
190
+ ): BlockLocation | undefined {
191
+ const startRow = blockRowNumber + 1
192
+ let numRows = this.lines
193
+ .slice(startRow)
194
+ .findIndex((line) => line.length && line[0] !== "")
195
+ if (numRows === 0) return undefined
196
+ if (numRows === -1) numRows = this.lines.slice(startRow).length
197
+ return { startRow, endRow: startRow + numRows, numRows }
198
+ }
199
+
200
+ protected getKeywordIndex(key: string) {
201
+ return this.lines.findIndex((line) => line[0] === key)
202
+ }
203
+
204
+ getCell(position: CellPosition): ParsedCell {
205
+ return new GridCell(this.lines, position, this.grammar!)
206
+ }
207
+
208
+ getCellContents(position: CellPosition) {
209
+ const line = this.lines[position.row]
210
+ return line ? line[position.column] : undefined
211
+ }
212
+
213
+ deleteBlock(row?: number) {
214
+ if (row === undefined) return this
215
+ const location = this.getBlockLocation(row)
216
+ if (!location) return this
217
+
218
+ this.lines.splice(location.startRow, location.numRows)
219
+ return this
220
+ }
221
+
222
+ deleteLine(row?: number) {
223
+ if (row === undefined) return this
224
+ this.lines.splice(row, 1)
225
+ return this
226
+ }
227
+
228
+ appendLine(line: string) {
229
+ this.lines.push(line.split(this.cellDelimiter))
230
+ return this
231
+ }
232
+
233
+ // todo: make immutable and return a new copy
234
+ setCell(row: number, col: number, value: string) {
235
+ this.lines[row][col] = value
236
+ return this
237
+ }
238
+
239
+ setLineValue(key: string, value: string | undefined) {
240
+ const index = this.getKeywordIndex(key)
241
+ if (index === -1 && value !== undefined) this.lines.push([key, value])
242
+ else if (value === undefined) this.deleteLine(index)
243
+ else this.lines[index] = [key, value]
244
+ return this
245
+ }
246
+
247
+ getBlock(keywordIndex: number) {
248
+ const location = this.getBlockLocation(keywordIndex)
249
+ if (!location) return undefined
250
+ return this.lines
251
+ .slice(location.startRow, location.endRow)
252
+ .map((line) => line.slice(1))
253
+ }
254
+
255
+ updateBlock(rowNumber: number, value: string[][]) {
256
+ const location = this.getBlockLocation(rowNumber)
257
+ if (!location) throw new Error("Block not found")
258
+ this.lines.splice(
259
+ location.startRow,
260
+ location.numRows,
261
+ ...value.map((line) => ["", ...line])
262
+ )
263
+ return this
264
+ }
265
+
266
+ protected appendBlock(key: string, value: string[][]) {
267
+ this.lines.push([key])
268
+ value.forEach((line) => this.lines.push(["", ...line]))
269
+ }
270
+
271
+ getRowNumbersStartingWith(startsWith: string) {
272
+ return this.lines
273
+ .map((line, index) => (line[0] === startsWith ? index : null))
274
+ .filter(isPresent)
275
+ }
276
+
277
+ private static lineMatchesWords = (
278
+ line: string[],
279
+ words: (string | undefined)[]
280
+ ): boolean =>
281
+ words.every((word, index) => word === undefined || line[index] === word)
282
+
283
+ getRowMatchingWords(...words: (string | undefined)[]): number {
284
+ return this.lines.findIndex((line) =>
285
+ GridProgram.lineMatchesWords(line, words)
286
+ )
287
+ }
288
+
289
+ getAllRowsMatchingWords(...words: (string | undefined)[]): number[] {
290
+ const rows: number[] = []
291
+ this.lines.forEach((line: string[], rowIndex: number) => {
292
+ if (GridProgram.lineMatchesWords(line, words)) rows.push(rowIndex)
293
+ })
294
+ return rows
295
+ }
296
+
297
+ // The max number of columns in any row when you view a program as a spreadsheet
298
+ get width() {
299
+ return Math.max(...this.lines.map((arr) => arr.length))
300
+ }
301
+
302
+ toString() {
303
+ return this.prettify()
304
+ }
305
+
306
+ protected prettify() {
307
+ return trimMatrix(this.lines)
308
+ .map((line) => line.join(this.cellDelimiter))
309
+ .join(this.nodeDelimiter)
310
+ }
311
+ }
@@ -0,0 +1,17 @@
1
+ # GridLang
2
+
3
+ (Note: GridLang name is a placeholder and this readme is a stub)
4
+
5
+ GridLang is a library for building 2-dimensional domain specific languages designed to be edited in a Spreadsheet UI.
6
+
7
+ Unlike traditional computer languages that parse tokens in-order, tokens in GridLanguages are parsed in a lazy, non-linear manner, based upon there position in a 2-d matrix.
8
+
9
+ Our "Explorer"—a DSL for building OWID explorers and Graphers—is a GridLang.
10
+
11
+ GridLangs are also intrinsically "patchable"—a great way for perserving user state.
12
+
13
+ ## How it works
14
+
15
+ 1. Extend the base GridProgram class with a class for your new DSL.
16
+ 2. Create a grammar for your DSL.
17
+ 3. Load in some "programs" from TSVs.
@@ -0,0 +1,69 @@
1
+ export { Explorer, type ExplorerProps } from "./Explorer.js"
2
+
3
+ export { buildExplorerProps } from "./ExplorerUtils.js"
4
+
5
+ export {
6
+ DefaultNewExplorerSlug,
7
+ EMBEDDED_EXPLORER_DELIMITER,
8
+ EMBEDDED_EXPLORER_GRAPHER_CONFIGS,
9
+ EMBEDDED_EXPLORER_PARTIAL_GRAPHER_CONFIGS,
10
+ EXPLORER_CONSTANTS_DELIMITER,
11
+ EXPLORER_EMBEDDED_FIGURE_SELECTOR,
12
+ ExplorerChartCreationMode,
13
+ ExplorerContainerId,
14
+ ExplorerControlType,
15
+ ExplorerControlTypeRegex,
16
+ EXPLORERS_GIT_CMS_FOLDER,
17
+ EXPLORERS_PREVIEW_ROUTE,
18
+ EXPLORERS_ROUTE_FOLDER,
19
+ GetAllExplorersRoute,
20
+ GetAllExplorersTagsRoute,
21
+ type ChoiceMap,
22
+ type ChoiceName,
23
+ type ChoiceValue,
24
+ type ExplorerChoice,
25
+ type ExplorerChoiceOption,
26
+ type ExplorerChoiceParams,
27
+ type ExplorerFullQueryParams,
28
+ type ExplorersRouteResponse,
29
+ type ExplorerStandardQueryParams,
30
+ UNSAVED_EXPLORER_DRAFT,
31
+ UNSAVED_EXPLORER_PREVIEW_QUERYPARAMS,
32
+ } from "./ExplorerConstants.js"
33
+
34
+ export {
35
+ type TableDef,
36
+ ExplorerProgram,
37
+ EXPLORER_FILE_SUFFIX,
38
+ makeFullPath,
39
+ type ExplorerGrapherInterface,
40
+ } from "./ExplorerProgram.js"
41
+
42
+ export { type ExplorerPageUrlMigrationSpec } from "./urlMigrations/ExplorerPageUrlMigrationSpec.js"
43
+
44
+ export {
45
+ explorerUrlMigrationsById,
46
+ migrateExplorerUrl,
47
+ } from "./urlMigrations/ExplorerUrlMigrations.js"
48
+
49
+ export { isEmpty } from "./gridLang/GrammarUtils.js"
50
+
51
+ export { ColumnGrammar } from "./ColumnGrammar.js"
52
+
53
+ export { GridCell } from "./gridLang/GridCell.js"
54
+
55
+ export { GridProgram } from "./gridLang/GridProgram.js"
56
+
57
+ export { ExplorerGrammar } from "./ExplorerGrammar.js"
58
+
59
+ export { ExplorerUrlMigrationId } from "./urlMigrations/ExplorerUrlMigrations.js"
60
+
61
+ export { DecisionMatrix } from "./ExplorerDecisionMatrix.js"
62
+
63
+ export {
64
+ GridBoolean,
65
+ type CellPosition,
66
+ type ParsedCell,
67
+ } from "./gridLang/GridLangConstants.js"
68
+
69
+ export { GrapherGrammar } from "./GrapherGrammar.js"
@@ -0,0 +1,19 @@
1
+ # Explorers
2
+
3
+ The Explorer is our component that allows easy navigating through a set of authored charts or charts generated on the fly. With the Explorer a reader can quickly navigate across dozens or hundreds of different chart views without leaving the page.
4
+
5
+ The Explorer component adds a control bar above the chart with controls including radios, dropdowns and checkboxes that the reader can use to change the chart on the page. The Explorer also adds a standalone entity selection tool on the left.
6
+
7
+ The Explorer works best on desktop but is also designed to work decently on mobile devices.
8
+
9
+ ## Implementation Notes
10
+
11
+ The Explorer depends on our Chart library, but the Chart library does not have a dependency on the Explorer. You should be able to delete the `explorer` folder, remove a few links, and the rest of Grapher should still work fine.
12
+
13
+ ### Explorer DSL
14
+
15
+ Explorers are created in a DSL that authors can edit in a spreadsheet which is parsed to create an instance of the ExplorerProgram class.
16
+
17
+ # Explorer Grammars
18
+
19
+ This folder also contains the declarative grammars that defines all the keywords and values authors can have in their Explorer programs.
@@ -0,0 +1,46 @@
1
+ import { legacyToCurrentGrapherUrl } from "../../grapher/index.js"
2
+ import { Url, UrlMigration } from "../../utils/index.js"
3
+ import {
4
+ decodeURIComponentOrUndefined,
5
+ getExplorerSlugFromUrl,
6
+ QueryParamTransformMap,
7
+ transformQueryParams,
8
+ } from "./ExplorerUrlMigrationUtils.js"
9
+
10
+ const EXPLORER_SLUG = "co2"
11
+
12
+ const co2QueryParamTransformMap: QueryParamTransformMap = {
13
+ "Gas ": {
14
+ newName: "Gas",
15
+ transformValue: decodeURIComponentOrUndefined,
16
+ },
17
+ "Accounting ": {
18
+ newName: "Accounting",
19
+ transformValue: decodeURIComponentOrUndefined,
20
+ },
21
+ "Fuel ": {
22
+ newName: "Fuel",
23
+ transformValue: decodeURIComponentOrUndefined,
24
+ },
25
+ "Count ": {
26
+ newName: "Count",
27
+ transformValue: decodeURIComponentOrUndefined,
28
+ },
29
+ "Relative to world total ": {
30
+ newName: "Relative to world total",
31
+ transformValue: (value) => (value ? "true" : "false"),
32
+ },
33
+ }
34
+
35
+ export const co2UrlMigration: UrlMigration = (url: Url) => {
36
+ // if it's not the /explorer/co2 path, skip it
37
+ const explorerSlug = getExplorerSlugFromUrl(url)
38
+ if (explorerSlug !== EXPLORER_SLUG) return url
39
+
40
+ url = legacyToCurrentGrapherUrl(url)
41
+ const queryParams = transformQueryParams(
42
+ url.queryParams,
43
+ co2QueryParamTransformMap
44
+ )
45
+ return url.setQueryParams(queryParams)
46
+ }
@@ -0,0 +1,37 @@
1
+ import { Url, UrlMigration } from "../../utils/index.js"
2
+ import {
3
+ getExplorerSlugFromUrl,
4
+ QueryParamTransformMap,
5
+ transformQueryParams,
6
+ } from "./ExplorerUrlMigrationUtils.js"
7
+
8
+ const EXPLORER_SLUG = "coronavirus-data-explorer"
9
+
10
+ const transformMap: QueryParamTransformMap = {
11
+ Metric: {
12
+ transformValue: (value) => {
13
+ // Since we introduced multiple vaccinations metrics, we want to
14
+ // differentiate between them.
15
+ // And while we're there, reduce the length of "Tests per confirmed
16
+ // case", because it wraps to 2 lines.
17
+ //
18
+ // -@danielgavrilov, 2021-03-30
19
+ //
20
+ if (value === "Vaccinations") return "Vaccine doses"
21
+ if (value === "Tests per confirmed case") return "Tests per case"
22
+ return value
23
+ },
24
+ },
25
+ "Align outbreaks": {
26
+ newName: "Color by test positivity",
27
+ },
28
+ }
29
+
30
+ export const covidUrlMigration: UrlMigration = (url: Url) => {
31
+ // if it's not the /explorer/energy path, skip it
32
+ const explorerSlug = getExplorerSlugFromUrl(url)
33
+ if (explorerSlug !== EXPLORER_SLUG) return url
34
+ return url.setQueryParams(
35
+ transformQueryParams(url.queryParams, transformMap)
36
+ )
37
+ }
@@ -0,0 +1,41 @@
1
+ import { legacyToCurrentGrapherUrl } from "../../grapher/index.js"
2
+ import { Url, UrlMigration } from "../../utils/index.js"
3
+ import {
4
+ decodeURIComponentOrUndefined,
5
+ getExplorerSlugFromUrl,
6
+ QueryParamTransformMap,
7
+ transformQueryParams,
8
+ } from "./ExplorerUrlMigrationUtils.js"
9
+
10
+ const EXPLORER_SLUG = "energy"
11
+
12
+ const energyQueryParamTransformMap: QueryParamTransformMap = {
13
+ "Total or Breakdown ": {
14
+ newName: "Total or Breakdown",
15
+ transformValue: decodeURIComponentOrUndefined,
16
+ },
17
+ "Select a source ": {
18
+ newName: "Select a source",
19
+ transformValue: decodeURIComponentOrUndefined,
20
+ },
21
+ "Energy or Electricity ": {
22
+ newName: "Energy or Electricity",
23
+ transformValue: decodeURIComponentOrUndefined,
24
+ },
25
+ "Metric ": {
26
+ newName: "Metric",
27
+ transformValue: decodeURIComponentOrUndefined,
28
+ },
29
+ }
30
+
31
+ export const energyUrlMigration: UrlMigration = (url: Url) => {
32
+ // if it's not the /explorer/energy path, skip it
33
+ const explorerSlug = getExplorerSlugFromUrl(url)
34
+ if (explorerSlug !== EXPLORER_SLUG) return url
35
+ url = legacyToCurrentGrapherUrl(url)
36
+ const queryParams = transformQueryParams(
37
+ url.queryParams,
38
+ energyQueryParamTransformMap
39
+ )
40
+ return url.setQueryParams(queryParams)
41
+ }
@@ -0,0 +1,12 @@
1
+ import { ExplorerUrlMigrationId } from "./ExplorerUrlMigrations.js"
2
+
3
+ /**
4
+ * An object spec that gets encoded into pages that redirect to an explorer.
5
+ *
6
+ * It's encoded as a JSON object on the page in order to avoid storing all redirects
7
+ * in the client-side bundle.
8
+ */
9
+ export interface ExplorerPageUrlMigrationSpec {
10
+ explorerUrlMigrationId: ExplorerUrlMigrationId
11
+ baseQueryStr: string
12
+ }
@@ -0,0 +1,45 @@
1
+ import * as _ from "lodash-es"
2
+ import { Url, QueryParams } from "../../utils/index.js"
3
+
4
+ import { EXPLORERS_ROUTE_FOLDER } from "../ExplorerConstants.js"
5
+
6
+ export const decodeURIComponentOrUndefined = (value: string | undefined) =>
7
+ value !== undefined
8
+ ? decodeURIComponent(value.replace(/\+/g, "%20"))
9
+ : undefined
10
+
11
+ export type QueryParamTransformMap = Record<
12
+ string,
13
+ {
14
+ newName?: string
15
+ transformValue?: (value: string | undefined) => string | undefined
16
+ }
17
+ >
18
+
19
+ export const transformQueryParams = (
20
+ oldQueryParams: Readonly<QueryParams>,
21
+ transformMap: QueryParamTransformMap
22
+ ) => {
23
+ const newQueryParams = _.omit(
24
+ oldQueryParams,
25
+ ...Object.keys(transformMap)
26
+ ) as QueryParams
27
+ for (const oldParamName in transformMap) {
28
+ if (!(oldParamName in oldQueryParams)) continue
29
+ const { newName, transformValue } = transformMap[oldParamName]
30
+ const name = newName ?? oldParamName
31
+ const transform = transformValue ?? _.identity
32
+ newQueryParams[name] = transform(oldQueryParams[oldParamName])
33
+ }
34
+ return newQueryParams
35
+ }
36
+
37
+ // todo(refactor): merge with Url's get explorerSlug()
38
+ export const getExplorerSlugFromUrl = (url: Url): string | undefined => {
39
+ if (!url.pathname) return undefined
40
+ const match = url.pathname.match(
41
+ new RegExp(`^/+${EXPLORERS_ROUTE_FOLDER}/+([^/]+)`)
42
+ )
43
+ if (match && match[1]) return match[1]
44
+ return undefined
45
+ }
@@ -0,0 +1,33 @@
1
+ import { Url, UrlMigration, performUrlMigrations } from "../../utils/index.js"
2
+
3
+ import { legacyCovidMigrationSpec } from "./LegacyCovidUrlMigration.js"
4
+ import { co2UrlMigration } from "./CO2UrlMigration.js"
5
+ import { energyUrlMigration } from "./EnergyUrlMigration.js"
6
+ import { covidUrlMigration } from "./CovidUrlMigration.js"
7
+
8
+ export enum ExplorerUrlMigrationId {
9
+ legacyToGridCovidExplorer = "legacyToGridCovidExplorer",
10
+ }
11
+
12
+ export interface ExplorerUrlMigrationSpec {
13
+ explorerSlug: string
14
+ migrateUrl: (url: Url, baseQueryStr: string) => Url
15
+ }
16
+
17
+ export const explorerUrlMigrationsById: Record<
18
+ ExplorerUrlMigrationId,
19
+ ExplorerUrlMigrationSpec
20
+ > = {
21
+ legacyToGridCovidExplorer: legacyCovidMigrationSpec,
22
+ }
23
+
24
+ const explorerUrlMigrations: UrlMigration[] = [
25
+ // NOTE: The order of migrations matters!
26
+ co2UrlMigration,
27
+ energyUrlMigration,
28
+ covidUrlMigration,
29
+ ]
30
+
31
+ export const migrateExplorerUrl: UrlMigration = (url: Url): Url => {
32
+ return performUrlMigrations(explorerUrlMigrations, url)
33
+ }