@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,327 @@
1
+ import * as React from "react"
2
+ import * as R from "remeda"
3
+ import { computed, makeObservable } from "mobx"
4
+ import { scaleLinear, ScaleLinear } from "d3-scale"
5
+ import { TextWrap, Halo } from "../../components/index.js"
6
+ import {
7
+ Color,
8
+ makeIdForHumanConsumption,
9
+ OwidVariableRoundingMode,
10
+ } from "../../utils/index.js"
11
+ import {
12
+ BASE_FONT_SIZE,
13
+ GRAPHER_FONT_SCALE_10,
14
+ GRAPHER_FONT_SCALE_11,
15
+ GRAPHER_TEXT_OUTLINE_FACTOR,
16
+ } from "../core/GrapherConstants"
17
+ import { CoreColumn } from "../../core-table/index.js"
18
+ import {
19
+ ScatterSeries,
20
+ SCATTER_POINT_MAX_RADIUS,
21
+ SCATTER_POINT_OPACITY,
22
+ SCATTER_POINT_STROKE_WIDTH,
23
+ SCATTER_POINT_DEFAULT_RADIUS,
24
+ } from "./ScatterPlotChartConstants"
25
+ import { darkenColorForText } from "../color/ColorUtils"
26
+ import {
27
+ GRAPHER_BACKGROUND_DEFAULT,
28
+ GRAPHER_DARK_TEXT,
29
+ GRAPHER_LIGHT_TEXT,
30
+ } from "../color/ColorConstants"
31
+
32
+ export interface ScatterSizeLegendManager {
33
+ sidebarWidth: number
34
+ sizeColumn: CoreColumn
35
+ sizeScale: ScaleLinear<number, number>
36
+ fontSize?: number
37
+ tooltipSeries?: ScatterSeries
38
+ backgroundColor?: Color
39
+ }
40
+
41
+ const LEGEND_PADDING = 3
42
+ const LEGEND_CIRCLE_COLOR = "#bbb"
43
+ const LEGEND_VALUE_COLOR = "#444"
44
+ const LABEL_PADDING = 2
45
+ const LABEL_COLOR = GRAPHER_LIGHT_TEXT
46
+ const TITLE_COLOR = GRAPHER_DARK_TEXT
47
+
48
+ const MIN_FONT_SIZE = 9
49
+
50
+ export class ScatterSizeLegend {
51
+ manager: ScatterSizeLegendManager
52
+ constructor(manager: ScatterSizeLegendManager) {
53
+ makeObservable(this)
54
+ this.manager = manager
55
+ }
56
+
57
+ @computed private get baseFontSize(): number {
58
+ return this.manager.fontSize ?? BASE_FONT_SIZE
59
+ }
60
+
61
+ @computed private get maxWidth(): number {
62
+ return this.manager.sidebarWidth
63
+ }
64
+
65
+ @computed private get ticks(): number[] {
66
+ const { sizeScale } = this.manager
67
+ const [domainStart, domainEnd] = sizeScale.domain()
68
+ if (domainStart === domainEnd) return [domainStart]
69
+ const [largestTick, ...restTicks] = sizeScale.ticks(6).toReversed()
70
+ if (largestTick === undefined) return []
71
+ const ticks = [largestTick]
72
+ restTicks.forEach((value) => {
73
+ if (
74
+ // make sure there is enough distance to prevent overlap with previous tick
75
+ sizeScale(value) <= sizeScale(R.last(ticks)!) - 6 &&
76
+ // don't go below the minimum tick radius
77
+ sizeScale(value) >= 6
78
+ ) {
79
+ ticks.push(value)
80
+ }
81
+ })
82
+ return ticks
83
+ }
84
+
85
+ private getPointRadius(value: number | undefined): number {
86
+ if (value === undefined) return SCATTER_POINT_DEFAULT_RADIUS
87
+ return this.manager.sizeScale(value)
88
+ }
89
+
90
+ // input radius, output font size
91
+ @computed private get fontSizeFromRadius(): ScaleLinear<number, number> {
92
+ return (
93
+ scaleLinear()
94
+ // choosing the domain & range somewhat arbitrarily here,
95
+ // by experimenting visually with font sizes
96
+ .domain([6, SCATTER_POINT_MAX_RADIUS])
97
+ .range([8, 11])
98
+ .clamp(true)
99
+ )
100
+ }
101
+
102
+ // Since it's circular, this is both the width and the height of the legend.
103
+ @computed private get legendSize(): number {
104
+ if (this.ticks.length === 0) return 0
105
+ const maxRadius = R.last(this.manager.sizeScale.range()) ?? 0
106
+ // adding some padding to account for label sticking out at the top
107
+ return 2 * maxRadius + 2
108
+ }
109
+
110
+ @computed private get label(): TextWrap {
111
+ const fontSize = Math.max(
112
+ MIN_FONT_SIZE,
113
+ GRAPHER_FONT_SCALE_10 * this.baseFontSize
114
+ )
115
+ return new TextWrap({
116
+ text: "Circles sized by",
117
+ // Allow text to _slightly_ go outside boundaries.
118
+ // Since we have padding left and right, this doesn't
119
+ // actually visibly overflow.
120
+ maxWidth: this.maxWidth + 12,
121
+ fontSize,
122
+ lineHeight: 1,
123
+ })
124
+ }
125
+
126
+ @computed private get title(): TextWrap {
127
+ const fontSize = Math.max(
128
+ MIN_FONT_SIZE,
129
+ GRAPHER_FONT_SCALE_11 * this.baseFontSize
130
+ )
131
+ return new TextWrap({
132
+ text: this.manager.sizeColumn.displayName,
133
+ // Allow text to _slightly_ go outside boundaries.
134
+ // Since we have padding left and right, this doesn't
135
+ // actually visibly overflow.
136
+ maxWidth: this.maxWidth + 10,
137
+ fontSize,
138
+ fontWeight: 700,
139
+ lineHeight: 1,
140
+ })
141
+ }
142
+
143
+ @computed get width(): number {
144
+ return this.manager.sidebarWidth
145
+ }
146
+
147
+ @computed get height(): number {
148
+ return (
149
+ this.legendSize +
150
+ LEGEND_PADDING +
151
+ this.label.height +
152
+ LABEL_PADDING +
153
+ this.title.height
154
+ )
155
+ }
156
+
157
+ @computed private get highlight():
158
+ | { value: number | undefined; color: string }
159
+ | undefined {
160
+ const { tooltipSeries } = this.manager
161
+ if (
162
+ tooltipSeries?.points.length === 1 &&
163
+ R.first(tooltipSeries.points)?.size !== undefined
164
+ ) {
165
+ return {
166
+ value: R.first(tooltipSeries.points)!.size,
167
+ color: tooltipSeries.color,
168
+ }
169
+ }
170
+ return undefined
171
+ }
172
+
173
+ private renderLegend(targetX: number, targetY: number): React.ReactElement {
174
+ const { highlight } = this
175
+ const cx = targetX + this.maxWidth / 2
176
+ return (
177
+ <React.Fragment>
178
+ {this.ticks.map((value) => {
179
+ const radius = this.getPointRadius(value)
180
+ return (
181
+ <LegendItem
182
+ key={value}
183
+ label={this.manager.sizeColumn.formatValueShortWithAbbreviations(
184
+ value,
185
+ {
186
+ roundingMode:
187
+ OwidVariableRoundingMode.decimalPlaces,
188
+ }
189
+ )}
190
+ cx={cx}
191
+ cy={targetY + this.legendSize - radius}
192
+ circleRadius={radius}
193
+ circleStroke={
194
+ highlight ? "#ddd" : LEGEND_CIRCLE_COLOR
195
+ }
196
+ labelFontSize={this.fontSizeFromRadius(radius)}
197
+ labelFill={highlight ? "#bbb" : LEGEND_VALUE_COLOR}
198
+ backgroundColor={this.manager.backgroundColor}
199
+ />
200
+ )
201
+ })}
202
+ {highlight && (
203
+ <LegendItem
204
+ key={highlight.value}
205
+ label={this.manager.sizeColumn.formatValueShort(
206
+ highlight.value
207
+ )}
208
+ cx={cx}
209
+ cy={
210
+ targetY +
211
+ this.legendSize -
212
+ this.getPointRadius(highlight.value)
213
+ }
214
+ circleFill={highlight.color}
215
+ circleStroke={"#333"}
216
+ circleStrokeWidth={SCATTER_POINT_STROKE_WIDTH}
217
+ circleRadius={this.getPointRadius(highlight.value)}
218
+ circleOpacity={SCATTER_POINT_OPACITY}
219
+ labelFontSize={12}
220
+ labelFill={darkenColorForText(highlight.color)}
221
+ labelFontWeight={700}
222
+ outsideLabel={true}
223
+ backgroundColor={this.manager.backgroundColor}
224
+ />
225
+ )}
226
+ </React.Fragment>
227
+ )
228
+ }
229
+
230
+ render(
231
+ targetX: number,
232
+ targetY: number,
233
+ renderOptions: React.SVGAttributes<SVGGElement> = {}
234
+ ): React.ReactElement {
235
+ const centerX = targetX + this.maxWidth / 2
236
+ return (
237
+ <g id={makeIdForHumanConsumption("size-legend")} {...renderOptions}>
238
+ {this.renderLegend(targetX, targetY)}
239
+ {this.label.renderSVG(
240
+ centerX,
241
+ targetY + this.legendSize + LEGEND_PADDING,
242
+ {
243
+ textProps: {
244
+ fill: LABEL_COLOR,
245
+ textAnchor: "middle",
246
+ },
247
+ }
248
+ )}
249
+ {this.title.renderSVG(
250
+ centerX,
251
+ targetY +
252
+ this.legendSize +
253
+ LEGEND_PADDING +
254
+ this.label.height +
255
+ LABEL_PADDING,
256
+ {
257
+ textProps: {
258
+ fill: TITLE_COLOR,
259
+ textAnchor: "middle",
260
+ },
261
+ }
262
+ )}
263
+ </g>
264
+ )
265
+ }
266
+ }
267
+
268
+ const LegendItem = ({
269
+ label,
270
+ cx,
271
+ cy,
272
+ circleRadius,
273
+ circleFill = "none",
274
+ circleStroke = LEGEND_CIRCLE_COLOR,
275
+ circleStrokeWidth = 1.25,
276
+ circleOpacity = 1,
277
+ labelFill = LEGEND_VALUE_COLOR,
278
+ labelFontSize,
279
+ labelFontWeight = 400,
280
+ outsideLabel = false,
281
+ backgroundColor = GRAPHER_BACKGROUND_DEFAULT,
282
+ }: {
283
+ label: string
284
+ cx: number
285
+ cy: number
286
+ circleRadius: number
287
+ circleFill?: string
288
+ circleStroke?: string
289
+ circleStrokeWidth?: number
290
+ circleOpacity?: number
291
+ labelFill?: string
292
+ labelFontSize: number
293
+ labelFontWeight?: number
294
+ outsideLabel?: boolean
295
+ backgroundColor?: Color
296
+ }): React.ReactElement => {
297
+ return (
298
+ <g>
299
+ <circle
300
+ cx={cx}
301
+ cy={cy}
302
+ r={circleRadius}
303
+ fill={circleFill}
304
+ stroke={circleStroke}
305
+ strokeWidth={circleStrokeWidth}
306
+ opacity={circleOpacity}
307
+ />
308
+ <Halo
309
+ id={label}
310
+ outlineWidth={GRAPHER_TEXT_OUTLINE_FACTOR * labelFontSize}
311
+ outlineColor={backgroundColor}
312
+ >
313
+ <text
314
+ x={cx}
315
+ y={cy - circleRadius}
316
+ dy={outsideLabel ? "-.32em" : ".47em"}
317
+ fill={labelFill}
318
+ fontSize={labelFontSize}
319
+ fontWeight={labelFontWeight}
320
+ textAnchor="middle"
321
+ >
322
+ {label}
323
+ </text>
324
+ </Halo>
325
+ </g>
326
+ )
327
+ }
@@ -0,0 +1,265 @@
1
+ import * as _ from "lodash-es"
2
+ import * as R from "remeda"
3
+ import {
4
+ Bounds,
5
+ ColumnSlug,
6
+ PointVector,
7
+ ValueRange,
8
+ } from "../../utils/index.js"
9
+ import {
10
+ SCATTER_LABEL_FONT_SIZE_FACTOR_WHEN_HIDDEN_LINES,
11
+ SCATTER_LINE_DEFAULT_WIDTH,
12
+ SCATTER_LINE_MAX_WIDTH,
13
+ SCATTER_POINT_DEFAULT_RADIUS,
14
+ SCATTER_POINT_MAX_RADIUS,
15
+ ScatterLabel,
16
+ ScatterRenderPoint,
17
+ ScatterRenderSeries,
18
+ } from "./ScatterPlotChartConstants"
19
+ import { BASE_FONT_SIZE } from "../core/GrapherConstants.js"
20
+ import { ScatterPlotChartState } from "./ScatterPlotChartState"
21
+ import { OwidTable } from "../../core-table/index.js"
22
+
23
+ export const labelPriority = (label: ScatterLabel): number => {
24
+ let priority = label.fontSize
25
+
26
+ if (label.series.isHover) priority += 10000
27
+ if (label.series.isFocus) priority += 1000
28
+ if (label.isEnd) priority += 100
29
+
30
+ return priority
31
+ }
32
+
33
+ // Create the start year label for a series
34
+ export const makeStartLabel = (
35
+ series: ScatterRenderSeries,
36
+ isSubtleForeground: boolean,
37
+ hideConnectedScatterLines: boolean,
38
+ baseFontSize: number
39
+ ): ScatterLabel | undefined => {
40
+ // No room to label the year if it's a single point
41
+ if (!series.isForeground || series.points.length <= 1) return undefined
42
+
43
+ const fontSize = hideConnectedScatterLines
44
+ ? SCATTER_LABEL_FONT_SIZE_FACTOR_WHEN_HIDDEN_LINES * baseFontSize
45
+ : series.isForeground
46
+ ? isSubtleForeground
47
+ ? (8 / BASE_FONT_SIZE) * baseFontSize
48
+ : (9 / BASE_FONT_SIZE) * baseFontSize
49
+ : (7 / BASE_FONT_SIZE) * baseFontSize
50
+ const firstValue = series.points[0]
51
+ const nextValue = series.points[1]
52
+ const nextSegment = nextValue.position.subtract(firstValue.position)
53
+
54
+ const pos = firstValue.position.subtract(nextSegment.normalize().times(5))
55
+ let bounds = Bounds.forText(firstValue.label, {
56
+ x: pos.x,
57
+ y: pos.y,
58
+ fontSize: fontSize,
59
+ })
60
+ if (pos.x < firstValue.position.x)
61
+ bounds = new Bounds(
62
+ bounds.x - bounds.width + 2,
63
+ bounds.y,
64
+ bounds.width,
65
+ bounds.height
66
+ )
67
+ if (pos.y > firstValue.position.y)
68
+ bounds = new Bounds(
69
+ bounds.x,
70
+ bounds.y + bounds.height / 2,
71
+ bounds.width,
72
+ bounds.height
73
+ )
74
+
75
+ return {
76
+ text: firstValue.label,
77
+ fontSize,
78
+ fontWeight: 400,
79
+ color: firstValue.color,
80
+ bounds,
81
+ series,
82
+ isStart: true,
83
+ }
84
+ }
85
+
86
+ // Make labels for the points between start and end on a series
87
+ // Positioned using normals of the line segments
88
+ export const makeMidLabels = (
89
+ series: ScatterRenderSeries,
90
+ isSubtleForeground: boolean,
91
+ hideConnectedScatterLines: boolean,
92
+ baseFontSize: number
93
+ ): ScatterLabel[] => {
94
+ if (
95
+ !series.isForeground ||
96
+ series.points.length <= 1 ||
97
+ (!series.isHover && isSubtleForeground)
98
+ )
99
+ return []
100
+
101
+ const fontSize = hideConnectedScatterLines
102
+ ? SCATTER_LABEL_FONT_SIZE_FACTOR_WHEN_HIDDEN_LINES * baseFontSize
103
+ : series.isForeground
104
+ ? isSubtleForeground
105
+ ? (8 / BASE_FONT_SIZE) * baseFontSize
106
+ : (9 / BASE_FONT_SIZE) * baseFontSize
107
+ : (7 / BASE_FONT_SIZE) * baseFontSize
108
+ const fontWeight = 400
109
+
110
+ // label all the way to the end for the tooltip series, otherwise to n-1
111
+ const lastIndex = series.isTooltip && !series.isFocus ? Infinity : -1
112
+
113
+ return series.points.slice(1, lastIndex).map((v, i) => {
114
+ const prevPos = i > 0 && series.points[i - 1].position
115
+ const prevSegment = prevPos && v.position.subtract(prevPos)
116
+ const nextPos = series.points[i + 1].position
117
+ const nextSegment = nextPos.subtract(v.position)
118
+
119
+ let pos = v.position
120
+ if (prevPos && prevSegment) {
121
+ const normals = prevSegment
122
+ .add(nextSegment)
123
+ .normalize()
124
+ .normals()
125
+ .map((x) => x.times(5))
126
+ const potentialSpots = normals.map((n) => v.position.add(n))
127
+ pos = _.maxBy(potentialSpots, (p) => {
128
+ return (
129
+ PointVector.distance(p, prevPos) +
130
+ PointVector.distance(p, nextPos)
131
+ )
132
+ }) as PointVector
133
+ } else {
134
+ pos = v.position.subtract(nextSegment.normalize().times(5))
135
+ }
136
+
137
+ let bounds = Bounds.forText(v.label, {
138
+ x: pos.x,
139
+ y: pos.y,
140
+ fontSize: fontSize,
141
+ fontWeight: fontWeight,
142
+ })
143
+ if (pos.x < v.position.x)
144
+ bounds = new Bounds(
145
+ bounds.x - bounds.width + 2,
146
+ bounds.y,
147
+ bounds.width,
148
+ bounds.height
149
+ )
150
+ if (pos.y > v.position.y)
151
+ bounds = new Bounds(
152
+ bounds.x,
153
+ bounds.y + bounds.height / 2,
154
+ bounds.width,
155
+ bounds.height
156
+ )
157
+
158
+ return {
159
+ text: v.label,
160
+ fontSize,
161
+ fontWeight,
162
+ color: v.color,
163
+ bounds,
164
+ series,
165
+ isMid: true,
166
+ }
167
+ })
168
+ }
169
+
170
+ // Make the end label (entity label) for a series. Will be pushed
171
+ // slightly out based on the direction of the series if multiple values
172
+ // are present
173
+ // This is also the one label in the case of a single point
174
+ export const makeEndLabel = (
175
+ series: ScatterRenderSeries,
176
+ isSubtleForeground: boolean,
177
+ hideConnectedScatterLines: boolean,
178
+ baseFontSize: number
179
+ ): ScatterLabel => {
180
+ const lastValue = R.last(series.points) as ScatterRenderPoint
181
+ const lastPos = lastValue.position
182
+ const fontSize = hideConnectedScatterLines
183
+ ? SCATTER_LABEL_FONT_SIZE_FACTOR_WHEN_HIDDEN_LINES * baseFontSize
184
+ : series.fontSize *
185
+ (series.isForeground ? (isSubtleForeground ? 1.2 : 1.3) : 1.1)
186
+ const fontWeight =
187
+ series.isForeground && !hideConnectedScatterLines ? 700 : 400
188
+
189
+ let offsetVector = PointVector.up
190
+ if (series.points.length > 1) {
191
+ const prevValue = series.points[series.points.length - 2]
192
+ const prevPos = prevValue.position
193
+ offsetVector = lastPos.subtract(prevPos)
194
+ }
195
+ series.offsetVector = offsetVector
196
+
197
+ const labelPos = lastPos.add(
198
+ offsetVector
199
+ .normalize()
200
+ .times(series.points.length === 1 ? lastValue.size + 1 : 5)
201
+ )
202
+
203
+ let labelBounds = Bounds.forText(series.text, {
204
+ x: labelPos.x,
205
+ y: labelPos.y,
206
+ fontSize: fontSize,
207
+ })
208
+
209
+ if (labelPos.x < lastPos.x)
210
+ labelBounds = labelBounds.set({
211
+ x: labelBounds.x - labelBounds.width,
212
+ })
213
+ if (labelPos.y > lastPos.y)
214
+ labelBounds = labelBounds.set({
215
+ y: labelBounds.y + labelBounds.height / 2,
216
+ })
217
+
218
+ return {
219
+ text:
220
+ hideConnectedScatterLines && series.isForeground
221
+ ? lastValue.label
222
+ : series.isTooltip && !series.isFocus
223
+ ? "" // don't doubly label the series name when the tooltip is visible
224
+ : series.text,
225
+ fontSize,
226
+ fontWeight,
227
+ color: lastValue.color,
228
+ bounds: labelBounds,
229
+ series,
230
+ isEnd: true,
231
+ }
232
+ }
233
+
234
+ export function toSizeRange(
235
+ chartState: ScatterPlotChartState,
236
+ bounds: Bounds
237
+ ): [number, number] {
238
+ if (chartState.sizeColumn.isMissing) {
239
+ // if the size column is missing, we want all points/lines to have the same width
240
+ return chartState.isConnected
241
+ ? [SCATTER_LINE_DEFAULT_WIDTH, SCATTER_LINE_DEFAULT_WIDTH]
242
+ : [SCATTER_POINT_DEFAULT_RADIUS, SCATTER_POINT_DEFAULT_RADIUS]
243
+ }
244
+
245
+ const maxLineWidth = SCATTER_LINE_MAX_WIDTH
246
+ const maxPointRadius = Math.min(
247
+ SCATTER_POINT_MAX_RADIUS,
248
+ _.round(Math.min(bounds.width, bounds.height) * 0.06, 1)
249
+ )
250
+
251
+ return chartState.isConnected
252
+ ? // Note that the scale starts at 0.
253
+ // When using the scale to plot marks, we need to make sure the minimums
254
+ // (e.g. `SCATTER_POINT_MIN_RADIUS`) are respected.
255
+ [0, maxLineWidth]
256
+ : [0, maxPointRadius]
257
+ }
258
+
259
+ export function computeSizeDomain(
260
+ table: OwidTable,
261
+ slug: ColumnSlug
262
+ ): ValueRange {
263
+ const sizeValues = table.get(slug).values.filter(_.isNumber)
264
+ return [0, _.max(sizeValues) ?? 1]
265
+ }
@@ -0,0 +1,41 @@
1
+ import * as React from "react"
2
+ import * as _ from "lodash-es"
3
+
4
+ type TriangleProps = Readonly<{
5
+ cx: number
6
+ cy: number
7
+ r: number
8
+ fill?: string
9
+ stroke?: string
10
+ strokeWidth?: number
11
+ rotation?: number
12
+ }> &
13
+ React.SVGProps<SVGPolygonElement>
14
+
15
+ export const Triangle = (props: TriangleProps): React.ReactElement => {
16
+ const { cx, cy, r, rotation } = props
17
+ const x = cx - r,
18
+ y = cy - r
19
+ const points = [
20
+ [x, y + r * 2],
21
+ [x + (r * 2) / 2, y],
22
+ [x + r * 2, y + r * 2],
23
+ ]
24
+ const rotationRounded = rotation
25
+ ? [rotation, cx, cy].map((v) => _.round(v, 2))
26
+ : undefined
27
+
28
+ return (
29
+ <polygon
30
+ points={points
31
+ .map((p) => `${p[0].toFixed(2)},${p[1].toFixed(2)}`)
32
+ .join(" ")}
33
+ transform={
34
+ rotationRounded
35
+ ? `rotate(${rotationRounded.join(", ")})`
36
+ : undefined
37
+ }
38
+ {..._.omit(props, "rotation")}
39
+ />
40
+ )
41
+ }
@@ -0,0 +1,33 @@
1
+ This folder contains the JSON schema for the configuration of Grapher.
2
+
3
+ ## How to evolve the schema
4
+
5
+ The schema is versioned. There is one yaml file with a version number. For nonbreaking changes (e.g. additions of optional fields) you can just
6
+ edit the yaml file as is. A github action will then generate a .latest.yaml and two json files (one .latest.json and one with the version number.json)
7
+ and upload them to S3 so they can be accessed publicly.
8
+
9
+ If you update the default value of an existing property or you add a new property with a default value, make sure to regenerate the default object from the schema and save it to `defaultGrapherConfig.ts` (see below).
10
+
11
+ Breaking changes should be done by renaming the schema file to an increased version number. Make sure to also rename the authorative url
12
+ inside the schema file (the "$id" field at the top level) to point to the new version number json. Then write the migrations from the last to
13
+ the current version of the schema, including the migration of pointing to the URL of the new schema version.s
14
+
15
+ Checklist for breaking changes:
16
+
17
+ - Rename the schema file to an increased version number
18
+ - Rename the authorative url inside the schema file to point to the new version number json
19
+ - Write the migrations from the last to the current version of the schema, including the migration of pointing to the URL of the new schema version
20
+ - Regenerate the default object from the schema and save it to `defaultGrapherConfig.ts` (see below)
21
+ - Write a migration to update the `chart_configs.full` column in the database for all stand-alone charts
22
+ - Write a migration to update configs in code (see `migrations/migrations.ts`)
23
+ - Update the hardcoded default schema version in ETL
24
+
25
+ To regenerate `defaultGrapherConfig.ts` from the schema, replace `XXX` with the current schema version number and run:
26
+
27
+ ```bash
28
+ # generate json from the yaml schema
29
+ nu -c 'open packages/@ourworldindata/grapher/src/schema/grapher-schema.XXX.yaml | to json' > packages/@ourworldindata/grapher/src/schema/grapher-schema.XXX.json
30
+
31
+ # generate the default object from the schema
32
+ yarn tsx --tsconfig tsconfig.tsx.json devTools/schema/generate-default-object-from-schema.ts packages/@ourworldindata/grapher/src/schema/grapher-schema.XXX.json --save-ts packages/@ourworldindata/grapher/src/schema/defaultGrapherConfig.ts
33
+ ```