@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,58 @@
1
+ import {
2
+ latestSchemaVersion,
3
+ outdatedSchemaVersions,
4
+ } from "../defaultGrapherConfig"
5
+
6
+ const allSchemaVersions = [...outdatedSchemaVersions, latestSchemaVersion]
7
+
8
+ type LatestSchemaVersion = typeof latestSchemaVersion
9
+ type OutdatedSchemaVersion = (typeof outdatedSchemaVersions)[number]
10
+ type SchemaVersion = OutdatedSchemaVersion | LatestSchemaVersion
11
+
12
+ type Schema =
13
+ `https://files.ourworldindata.org/schemas/grapher-schema.${SchemaVersion}.json`
14
+
15
+ // we can't type configs that don't adhere to the latest schema as we don't know what they look like
16
+ export type AnyConfig = Record<string, any>
17
+ export type AnyConfigWithValidSchema = AnyConfig & {
18
+ $schema: Schema
19
+ }
20
+
21
+ const schemaVersionRegex =
22
+ /https:\/\/files\.ourworldindata\.org\/schemas\/grapher-schema\.(?<version>\d{3})\.json/m
23
+
24
+ const isValidSchemaVersion = (version: string): version is SchemaVersion =>
25
+ allSchemaVersions.includes(version as any)
26
+
27
+ export function getSchemaVersion(
28
+ config: AnyConfigWithValidSchema
29
+ ): SchemaVersion
30
+ export function getSchemaVersion(config: AnyConfig): SchemaVersion | null
31
+ export function getSchemaVersion(
32
+ config: AnyConfig | AnyConfigWithValidSchema
33
+ ): SchemaVersion | null {
34
+ const version = config.$schema?.match(schemaVersionRegex)?.groups?.version
35
+ if (!version || !isValidSchemaVersion(version)) return null
36
+ return version
37
+ }
38
+
39
+ export function createSchemaForVersion(version: SchemaVersion): Schema {
40
+ return `https://files.ourworldindata.org/schemas/grapher-schema.${version}.json`
41
+ }
42
+
43
+ export const isLatestVersion = (version: SchemaVersion) =>
44
+ version === latestSchemaVersion
45
+
46
+ export const isOutdatedVersion = (version: SchemaVersion) =>
47
+ outdatedSchemaVersions.includes(version as any)
48
+
49
+ export const hasValidSchema = (
50
+ config: AnyConfig
51
+ ): config is AnyConfigWithValidSchema => getSchemaVersion(config) !== null
52
+
53
+ export const hasOutdatedSchema = (
54
+ config: AnyConfigWithValidSchema
55
+ ): boolean => {
56
+ const version = getSchemaVersion(config)
57
+ return isOutdatedVersion(version)
58
+ }
@@ -0,0 +1,75 @@
1
+ import * as _ from "lodash-es"
2
+ import { GrapherInterface } from "../../../types/index.js"
3
+
4
+ import { defaultGrapherConfig } from "../defaultGrapherConfig"
5
+ import {
6
+ getSchemaVersion,
7
+ hasValidSchema,
8
+ isLatestVersion,
9
+ hasOutdatedSchema,
10
+ type AnyConfig,
11
+ type AnyConfigWithValidSchema,
12
+ } from "./helpers"
13
+ import { runMigration } from "./migrations"
14
+
15
+ const recursivelyApplyMigrations = (
16
+ config: AnyConfigWithValidSchema
17
+ ): AnyConfigWithValidSchema => {
18
+ const version = getSchemaVersion(config)
19
+ if (isLatestVersion(version)) return config
20
+ return recursivelyApplyMigrations(runMigration(config))
21
+ }
22
+
23
+ const migrate = (config: AnyConfigWithValidSchema): GrapherInterface =>
24
+ recursivelyApplyMigrations(config) as GrapherInterface
25
+
26
+ /**
27
+ * Attempts to migrate a config to the latest schema version.
28
+ *
29
+ * An outdated config is migrated to the latest version by applying a series of
30
+ * predefined migrations. We rely on the schema version to determine if a config
31
+ * is outdated.
32
+ *
33
+ * Note that the given config is not actually validated against the schema!
34
+ */
35
+ export const migrateGrapherConfigToLatestVersion = (
36
+ config: AnyConfig
37
+ ): GrapherInterface => {
38
+ // the config adheres to the latest schema
39
+ if (config.$schema === defaultGrapherConfig.$schema) return config
40
+
41
+ // if the schema version is outdated, migrate it
42
+ if (hasValidSchema(config) && hasOutdatedSchema(config)) {
43
+ return migrate(_.cloneDeep(config))
44
+ }
45
+
46
+ // throw if the schema is missing
47
+ if (config.$schema === undefined) {
48
+ throw new Error("Schema missing")
49
+ } else {
50
+ /**
51
+ * If the schema version is not outdated and not the latest, we have most likely received a
52
+ * config from a future version of the codebase, that the client code is not yet aware of.
53
+ * That's not perfect, but in reality, most schema changes are benign changes,
54
+ * and rendering the config with the current code will result in a better user experience
55
+ * than just throwing an error and grapher not rendering at all without any explanation.
56
+ * - @marcelgerber, 2025-07-02
57
+ */
58
+ const message = `Received grapher config with unsupported schema ${config.$schema}; this code expects schema ${defaultGrapherConfig.$schema}.`
59
+ console.warn(message)
60
+ return config
61
+ }
62
+ }
63
+
64
+ export const migrateGrapherConfigToLatestVersionAndFailOnError = (
65
+ config: AnyConfig
66
+ ): GrapherInterface => {
67
+ const migrated = migrateGrapherConfigToLatestVersion(config)
68
+
69
+ if (migrated.$schema !== defaultGrapherConfig.$schema) {
70
+ throw new Error(
71
+ `Invalid schema version after schema migration: ${migrated.$schema}. Expected: ${defaultGrapherConfig.$schema}`
72
+ )
73
+ }
74
+ return migrated
75
+ }
@@ -0,0 +1,158 @@
1
+ // Schema migrations
2
+ //
3
+ // Every breaking change to the schema should be accompanied by a migration.
4
+ //
5
+ // To add a migration, follow these steps:
6
+ // - Create a new function `migrateXXXToXXX` that migrates a config from one version to the next.
7
+ // Make sure to update the $schema field to the next version in your migration function,
8
+ // or else the recursively defined migrate function will not terminate!
9
+ // - Add a new case to the match statement in `runMigration` that calls the new migration function.
10
+
11
+ import { match } from "ts-pattern"
12
+ import {
13
+ type AnyConfigWithValidSchema,
14
+ createSchemaForVersion,
15
+ getSchemaVersion,
16
+ isLatestVersion,
17
+ } from "./helpers"
18
+ import { GRAPHER_CHART_TYPES } from "../../../types/index.js"
19
+
20
+ // see https://github.com/owid/owid-grapher/commit/26f2a0d1790c71bdda7e12f284ca552945d2f6ef
21
+ const migrateFrom001To002 = (
22
+ config: AnyConfigWithValidSchema
23
+ ): AnyConfigWithValidSchema => {
24
+ delete config.selectedData
25
+ config.$schema = createSchemaForVersion("002")
26
+ return config
27
+ }
28
+
29
+ // see https://github.com/owid/owid-grapher/commit/4525ad81fb7064709ffab83677a8b0354b324dfb
30
+ const migrateFrom002To003 = (
31
+ config: AnyConfigWithValidSchema
32
+ ): AnyConfigWithValidSchema => {
33
+ if (config.hideTitleAnnotation) {
34
+ config.hideTitleAnnotations = {
35
+ entity: true,
36
+ time: true,
37
+ change: true,
38
+ }
39
+ }
40
+ delete config.hideTitleAnnotation
41
+
42
+ config.$schema = createSchemaForVersion("003")
43
+ return config
44
+ }
45
+
46
+ // see https://github.com/owid/owid-grapher/commit/1776721253cf61d7f1e24ebadeaf7a7ca2f43ced
47
+ const migrateFrom003To004 = (
48
+ config: AnyConfigWithValidSchema
49
+ ): AnyConfigWithValidSchema => {
50
+ delete config.data
51
+ config.$schema = createSchemaForVersion("004")
52
+ return config
53
+ }
54
+
55
+ // see https://github.com/owid/owid-grapher/commit/1d67de3174764a413bc5055fbdf34efb2b49e079
56
+ const migrateFrom004To005 = (
57
+ config: AnyConfigWithValidSchema
58
+ ): AnyConfigWithValidSchema => {
59
+ delete config.hideLinesOutsideTolerance
60
+ config.$schema = createSchemaForVersion("005")
61
+ return config
62
+ }
63
+
64
+ const migrateFrom005To006 = (
65
+ config: AnyConfigWithValidSchema
66
+ ): AnyConfigWithValidSchema => {
67
+ const { type = GRAPHER_CHART_TYPES.LineChart, hasChartTab = true } = config
68
+
69
+ // add types field
70
+ if (!hasChartTab) config.chartTypes = []
71
+ else if (type !== GRAPHER_CHART_TYPES.LineChart) config.chartTypes = [type]
72
+
73
+ // remove deprecated fields
74
+ delete config.type
75
+ delete config.hasChartTab
76
+
77
+ config.$schema = createSchemaForVersion("006")
78
+ return config
79
+ }
80
+
81
+ export const migrateFrom006To007 = (
82
+ config: AnyConfigWithValidSchema
83
+ ): AnyConfigWithValidSchema => {
84
+ // rename map.projection to map.region
85
+ if (config.map?.projection) {
86
+ config.map.region = config.map.projection
87
+ delete config.map.projection
88
+ }
89
+
90
+ config.$schema = createSchemaForVersion("007")
91
+ return config
92
+ }
93
+
94
+ export const migrateFrom007To008 = (
95
+ config: AnyConfigWithValidSchema
96
+ ): AnyConfigWithValidSchema => {
97
+ // remove colorScale.customNumericMinValue, merge it into colorScale.customNumericValues
98
+ if (config.map?.colorScale?.customNumericValues) {
99
+ config.map.colorScale.customNumericValues = [
100
+ config.map.colorScale.customNumericMinValue ?? 0,
101
+ ...config.map.colorScale.customNumericValues,
102
+ ]
103
+ }
104
+ if (config.map?.colorScale?.customNumericMinValue !== undefined) {
105
+ delete config.map.colorScale.customNumericMinValue
106
+ }
107
+
108
+ if (config.colorScale?.customNumericValues) {
109
+ config.colorScale.customNumericValues = [
110
+ config.colorScale.customNumericMinValue ?? 0,
111
+ ...config.colorScale.customNumericValues,
112
+ ]
113
+ }
114
+ if (config.colorScale?.customNumericMinValue !== undefined) {
115
+ delete config.colorScale.customNumericMinValue
116
+ }
117
+
118
+ config.$schema = createSchemaForVersion("008")
119
+ return config
120
+ }
121
+
122
+ export const migrateFrom008To009 = (config: AnyConfigWithValidSchema) => {
123
+ if ((config.map?.colorScale?.binningStrategy ?? "manual") !== "manual") {
124
+ config.map.colorScale.binningStrategy = "auto"
125
+ }
126
+
127
+ if (config.map?.colorScale?.binningStrategyBinCount !== undefined) {
128
+ delete config.map.colorScale.binningStrategyBinCount
129
+ }
130
+
131
+ if ((config.colorScale?.binningStrategy ?? "manual") !== "manual") {
132
+ config.colorScale.binningStrategy = "auto"
133
+ }
134
+
135
+ if (config.colorScale?.binningStrategyBinCount !== undefined) {
136
+ delete config.colorScale.binningStrategyBinCount
137
+ }
138
+
139
+ config.$schema = createSchemaForVersion("009")
140
+ return config
141
+ }
142
+
143
+ export const runMigration = (
144
+ config: AnyConfigWithValidSchema
145
+ ): AnyConfigWithValidSchema => {
146
+ const version = getSchemaVersion(config)
147
+ if (isLatestVersion(version)) return config
148
+ return match(version)
149
+ .with("001", () => migrateFrom001To002(config))
150
+ .with("002", () => migrateFrom002To003(config))
151
+ .with("003", () => migrateFrom003To004(config))
152
+ .with("004", () => migrateFrom004To005(config))
153
+ .with("005", () => migrateFrom005To006(config))
154
+ .with("006", () => migrateFrom006To007(config))
155
+ .with("007", () => migrateFrom007To008(config))
156
+ .with("008", () => migrateFrom008To009(config))
157
+ .exhaustive()
158
+ }
@@ -0,0 +1,99 @@
1
+ import { computed, makeObservable } from "mobx"
2
+ import { SelectionArray } from "./SelectionArray"
3
+ import {
4
+ Aggregate,
5
+ checkHasMembers,
6
+ checkIsCountry,
7
+ Continent,
8
+ Country,
9
+ EntityName,
10
+ excludeUndefined,
11
+ getCountryNamesForRegion,
12
+ getRegionByName,
13
+ IncomeGroup,
14
+ Region,
15
+ } from "../../utils/index.js"
16
+ import * as R from "remeda"
17
+
18
+ export class MapSelectionArray extends SelectionArray {
19
+ constructor(selectedEntityNames: EntityName[] = []) {
20
+ super(selectedEntityNames)
21
+
22
+ makeObservable(this)
23
+ }
24
+
25
+ @computed private get selectedEntitiesWithRegionInfo(): Region[] {
26
+ return excludeUndefined(
27
+ this.selectedEntityNames.map((name) => getRegionByName(name))
28
+ )
29
+ }
30
+
31
+ @computed get selectedCountries(): Country[] {
32
+ return this.selectedEntitiesWithRegionInfo.filter((region) =>
33
+ checkIsCountry(region)
34
+ )
35
+ }
36
+
37
+ @computed get selectedCountryNames(): EntityName[] {
38
+ return this.selectedCountries.map((country) => country.name)
39
+ }
40
+
41
+ @computed get hasCountries(): boolean {
42
+ return this.selectedCountries.length > 0
43
+ }
44
+
45
+ /**
46
+ * Subset of the selected countries that are part of the selected regions.
47
+ * Returns all selected countries if no region is selected.
48
+ */
49
+ @computed get selectedCountryNamesInForeground(): EntityName[] {
50
+ if (!this.hasRegions) return this.selectedCountryNames
51
+ const memberCountries = this.countryNamesForSelectedRegionsSet
52
+ return this.selectedCountries
53
+ .filter((country) => memberCountries.has(country.name))
54
+ .map((country) => country.name)
55
+ }
56
+
57
+ /**
58
+ * Complement of `selectedCountryNamesInForeground`.
59
+ * Subset of the selected countries that are not part of any selected region.
60
+ * Returns an empty list if no region is selected.
61
+ */
62
+ @computed get selectedCountryNamesInBackground(): EntityName[] {
63
+ return R.difference(
64
+ this.selectedCountryNames,
65
+ this.selectedCountryNamesInForeground
66
+ )
67
+ }
68
+
69
+ /**
70
+ * List of selected regions where a region is any geographic entity that
71
+ * is made up of a set of countries.
72
+ */
73
+ @computed get selectedRegions(): (Continent | Aggregate | IncomeGroup)[] {
74
+ return this.selectedEntitiesWithRegionInfo.filter(
75
+ (region): region is Continent | Aggregate | IncomeGroup =>
76
+ checkHasMembers(region) && region.code !== "OWID_WRL"
77
+ )
78
+ }
79
+
80
+ @computed get selectedRegionNames(): EntityName[] {
81
+ return this.selectedRegions.map((region) => region.name)
82
+ }
83
+
84
+ @computed get hasRegions(): boolean {
85
+ return this.selectedRegions.length > 0
86
+ }
87
+
88
+ @computed get countryNamesForSelectedRegionsSet(): Set<EntityName> {
89
+ return new Set(
90
+ this.selectedRegions.flatMap((region) =>
91
+ getCountryNamesForRegion(region)
92
+ )
93
+ )
94
+ }
95
+
96
+ @computed get countryNamesForSelectedRegions(): EntityName[] {
97
+ return Array.from(this.countryNamesForSelectedRegionsSet)
98
+ }
99
+ }
@@ -0,0 +1,71 @@
1
+ import { EntityName } from "../../types/index.js"
2
+ import { action, computed, observable, makeObservable } from "mobx"
3
+
4
+ export class SelectionArray {
5
+ constructor(selectedEntityNames: EntityName[] = []) {
6
+ makeObservable(this, {
7
+ selectedEntityNames: observable,
8
+ })
9
+ this.selectedEntityNames = selectedEntityNames.slice()
10
+ }
11
+
12
+ selectedEntityNames: EntityName[]
13
+
14
+ @computed get hasSelection(): boolean {
15
+ return this.selectedEntityNames.length > 0
16
+ }
17
+
18
+ @computed get numSelectedEntities(): number {
19
+ return this.selectedEntityNames.length
20
+ }
21
+
22
+ @computed get selectedSet(): Set<EntityName> {
23
+ return new Set<EntityName>(this.selectedEntityNames)
24
+ }
25
+
26
+ // Clears and sets selected entities
27
+ @action.bound setSelectedEntities(entityNames: EntityName[]): this {
28
+ this.clearSelection()
29
+ return this.addToSelection(entityNames)
30
+ }
31
+
32
+ @action.bound addToSelection(entityNames: EntityName[]): this {
33
+ this.selectedEntityNames = this.selectedEntityNames.concat(entityNames)
34
+ return this
35
+ }
36
+
37
+ @action.bound clearSelection(): void {
38
+ this.selectedEntityNames = []
39
+ }
40
+
41
+ @action.bound toggleSelection(entityName: EntityName): this {
42
+ return this.selectedSet.has(entityName)
43
+ ? this.deselectEntity(entityName)
44
+ : this.selectEntity(entityName)
45
+ }
46
+
47
+ @action.bound selectEntity(entityName: EntityName): this {
48
+ if (!this.selectedSet.has(entityName))
49
+ return this.addToSelection([entityName])
50
+ return this
51
+ }
52
+
53
+ @action.bound deselectEntity(entityName: EntityName): this {
54
+ this.selectedEntityNames = this.selectedEntityNames.filter(
55
+ (name) => name !== entityName
56
+ )
57
+ return this
58
+ }
59
+
60
+ @action.bound selectEntities(entityNames: EntityName[]): this {
61
+ entityNames.forEach((entityName) => this.selectEntity(entityName))
62
+ return this
63
+ }
64
+
65
+ @action.bound deselectEntities(entityNames: EntityName[]): this {
66
+ this.selectedEntityNames = this.selectedEntityNames.filter(
67
+ (name) => !entityNames.includes(name)
68
+ )
69
+ return this
70
+ }
71
+ }
@@ -0,0 +1,16 @@
1
+ # SelectionArray
2
+
3
+ The browser already has a class named `Selection`, so for now we have `SelectionArray`.
4
+
5
+ This is a pretty simple class that maintains 2 arrays:
6
+
7
+ 1. An array of strings which contains the names and or codes of selected entities
8
+ 2. An array of Entities that can be selected
9
+
10
+ If something happens so the user has new choices, you can expand #2.
11
+
12
+ ## Wish list
13
+
14
+ Except for Scatters, only selected entities will appear in charts. In Scatters "selected entities" really are "highlighted entities". It may be nice to separate those concepts.
15
+
16
+ SeriesSelection. It may be better to rename OwidTable to TimeSeriesTable, and remove the concept of `entityName` and replace with `seriesName`. Then we could have a nice simple concept "SeriesSelection". Similarly, we could ditch "EntityCode" and maybe have "SeriesNickname", which would be a shorter URL friendly way to specify seriesSelection. It would then be nice to rename the `country=` url param to something like `series=`
@@ -0,0 +1,10 @@
1
+ .side-panel {
2
+ flex-grow: 0;
3
+ flex-shrink: 0;
4
+ border-left: 1px solid $frame-color;
5
+
6
+ // don't show close button in the side panel header
7
+ .overlay-header .close-button {
8
+ display: none;
9
+ }
10
+ }
@@ -0,0 +1,23 @@
1
+ import * as React from "react"
2
+ import { Bounds } from "../../utils/index.js"
3
+ import { GRAPHER_SIDE_PANEL_CLASS } from "../core/GrapherConstants.js"
4
+
5
+ export const SidePanel = ({
6
+ bounds,
7
+ children,
8
+ }: {
9
+ bounds: Bounds
10
+ children: React.ReactNode
11
+ }) => {
12
+ return (
13
+ <div
14
+ className={GRAPHER_SIDE_PANEL_CLASS}
15
+ style={{
16
+ width: bounds.width,
17
+ height: bounds.height,
18
+ }}
19
+ >
20
+ {children}
21
+ </div>
22
+ )
23
+ }
@@ -0,0 +1,57 @@
1
+ .drawer {
2
+ .drawer-contents {
3
+ position: absolute;
4
+ right: 0;
5
+ top: 0;
6
+ width: 300px;
7
+ height: 100%;
8
+ z-index: $zindex-controls-drawer;
9
+ background: white;
10
+ }
11
+
12
+ .drawer-backdrop {
13
+ position: absolute;
14
+ top: 0;
15
+ left: 0;
16
+ right: 0;
17
+ bottom: 0;
18
+ background: rgba(0, 0, 0, 0.1);
19
+ z-index: $zindex-controls-backdrop;
20
+ }
21
+ }
22
+
23
+ @keyframes drawer-backdrop-enter {
24
+ 0% {
25
+ opacity: 0;
26
+ }
27
+ 100% {
28
+ opacity: 1;
29
+ }
30
+ }
31
+
32
+ @keyframes drawer-backdrop-exit {
33
+ 0% {
34
+ opacity: 1;
35
+ }
36
+ 100% {
37
+ opacity: 0;
38
+ }
39
+ }
40
+
41
+ @keyframes drawer-contents-enter {
42
+ 0% {
43
+ transform: translate(301px, 0);
44
+ }
45
+ 100% {
46
+ transform: translate(0, 0);
47
+ }
48
+ }
49
+
50
+ @keyframes drawer-contents-exit {
51
+ 0% {
52
+ transform: translate(0, 0);
53
+ }
54
+ 100% {
55
+ transform: translate(301px, 0);
56
+ }
57
+ }
@@ -0,0 +1,125 @@
1
+ import * as React from "react"
2
+ import cx from "classnames"
3
+ import { computed, action, observable, makeObservable } from "mobx"
4
+ import { observer } from "mobx-react"
5
+ import { isTargetOutsideElement } from "../chart/ChartUtils"
6
+
7
+ export const DrawerContext = React.createContext<{
8
+ toggleDrawerVisibility?: () => void
9
+ }>({})
10
+
11
+ interface SlideInDrawerProps {
12
+ active: boolean
13
+ toggle: () => void
14
+ children: React.ReactNode
15
+ grapherRef?: React.RefObject<HTMLDivElement | null>
16
+ }
17
+
18
+ @observer
19
+ export class SlideInDrawer extends React.Component<SlideInDrawerProps> {
20
+ visible: boolean = this.props.active // true while the drawer is active and during enter/exit transitions
21
+ drawerRef = React.createRef<HTMLDivElement>()
22
+
23
+ constructor(props: SlideInDrawerProps) {
24
+ super(props)
25
+
26
+ makeObservable(this, {
27
+ visible: observable.ref,
28
+ })
29
+ }
30
+
31
+ override componentDidMount(): void {
32
+ document.addEventListener("keydown", this.onDocumentKeyDown)
33
+ document.addEventListener("click", this.onDocumentClick, {
34
+ capture: true,
35
+ })
36
+ }
37
+
38
+ override componentWillUnmount(): void {
39
+ document.removeEventListener("keydown", this.onDocumentKeyDown)
40
+ document.removeEventListener("click", this.onDocumentClick, {
41
+ capture: true,
42
+ })
43
+ }
44
+
45
+ override componentDidUpdate(): void {
46
+ const grapherElement = this.props.grapherRef?.current
47
+ if (grapherElement) {
48
+ grapherElement.style.overflowX =
49
+ this.active || this.visible ? "clip" : "visible"
50
+ }
51
+ }
52
+
53
+ @action.bound onDocumentKeyDown(e: KeyboardEvent): void {
54
+ // dismiss menu on esc
55
+ if (this.active && e.key === "Escape") this.toggleVisibility()
56
+ }
57
+
58
+ @action.bound onDocumentClick(e: MouseEvent): void {
59
+ if (
60
+ this.active &&
61
+ this.drawerRef?.current &&
62
+ isTargetOutsideElement(e.target!, this.drawerRef.current)
63
+ )
64
+ this.toggleVisibility()
65
+ }
66
+
67
+ @action.bound toggleVisibility(e?: React.MouseEvent): void {
68
+ this.props.toggle()
69
+ if (this.active) this.visible = true
70
+ e?.stopPropagation()
71
+ }
72
+
73
+ @action.bound onAnimationEnd(): void {
74
+ if (!this.active) this.visible = false
75
+ }
76
+
77
+ @computed private get active(): boolean {
78
+ return this.props.active
79
+ }
80
+
81
+ private animationFor(selector: string): React.CSSProperties {
82
+ const phase = this.active ? "enter" : "exit"
83
+ return {
84
+ animationName: `${selector}-${phase}`,
85
+ animationDuration: "333ms",
86
+ animationFillMode: "forwards",
87
+ }
88
+ }
89
+
90
+ override render(): React.ReactElement | null {
91
+ const { visible, active } = this
92
+
93
+ if (active || visible) {
94
+ return (
95
+ <div
96
+ className={cx("drawer", { active: this.active })}
97
+ ref={this.drawerRef}
98
+ >
99
+ <div
100
+ className="drawer-backdrop"
101
+ onClick={this.toggleVisibility}
102
+ style={this.animationFor("drawer-backdrop")}
103
+ onAnimationEnd={this.onAnimationEnd} // triggers unmount
104
+ ></div>
105
+ <div
106
+ className="drawer-contents"
107
+ style={{
108
+ ...this.animationFor("drawer-contents"),
109
+ }}
110
+ >
111
+ <DrawerContext.Provider
112
+ value={{
113
+ toggleDrawerVisibility: this.toggleVisibility,
114
+ }}
115
+ >
116
+ {this.props.children}
117
+ </DrawerContext.Provider>
118
+ </div>
119
+ </div>
120
+ )
121
+ }
122
+
123
+ return null
124
+ }
125
+ }