@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,437 @@
1
+ import React from "react"
2
+ import { computed, makeObservable } from "mobx"
3
+ import { observer } from "mobx-react"
4
+ import * as _ from "lodash-es"
5
+ import { Bounds, SeriesName } from "../../utils/index.js"
6
+ import { ChartInterface } from "../chart/ChartInterface"
7
+ import { LineChartState } from "./LineChartState"
8
+ import { LineChartProps } from "./LineChart.js"
9
+ import { DualAxis, HorizontalAxis, VerticalAxis } from "../axis/Axis"
10
+ import {
11
+ LineChartManager,
12
+ PlacedLineChartSeries,
13
+ PlacedPoint,
14
+ RenderLineChartSeries,
15
+ } from "./LineChartConstants"
16
+ import {
17
+ BASE_FONT_SIZE,
18
+ DEFAULT_GRAPHER_BOUNDS,
19
+ GRAPHER_FONT_SCALE_12,
20
+ } from "../core/GrapherConstants"
21
+ import { AxisConfig, AxisManager } from "../axis/AxisConfig"
22
+ import { Lines } from "./Lines"
23
+ import {
24
+ getYAxisConfigDefaults,
25
+ toPlacedLineChartSeries,
26
+ toRenderLineChartSeries,
27
+ } from "./LineChartHelpers"
28
+ import {
29
+ HorizontalAxisComponent,
30
+ VerticalAxisZeroLine,
31
+ } from "../axis/AxisViews"
32
+ import {
33
+ InitialVerticalLabelsSeries,
34
+ VerticalLabelsState,
35
+ } from "../verticalLabels/VerticalLabelsState"
36
+ import { VerticalLabels } from "../verticalLabels/VerticalLabels"
37
+ import { darkenColorForLine } from "../color/ColorUtils.js"
38
+ import { NoDataModal } from "../noDataModal/NoDataModal"
39
+
40
+ const DOT_RADIUS = 4
41
+ const SPACE_BETWEEN_DOT_AND_LABEL = 4
42
+
43
+ const LABEL_PADDING = DOT_RADIUS + SPACE_BETWEEN_DOT_AND_LABEL
44
+
45
+ @observer
46
+ export class LineChartThumbnail
47
+ extends React.Component<LineChartProps>
48
+ implements ChartInterface, AxisManager
49
+ {
50
+ constructor(props: LineChartProps) {
51
+ super(props)
52
+ makeObservable(this)
53
+ }
54
+
55
+ @computed get chartState(): LineChartState {
56
+ return this.props.chartState
57
+ }
58
+
59
+ @computed private get manager(): LineChartManager {
60
+ return this.chartState.manager
61
+ }
62
+
63
+ @computed private get bounds(): Bounds {
64
+ return this.props.bounds ?? DEFAULT_GRAPHER_BOUNDS
65
+ }
66
+
67
+ @computed private get innerBounds(): Bounds {
68
+ return this.bounds
69
+ .padRight(this.paddedEndLabelsWidth)
70
+ .padLeft(this.paddedStartLabelsWidth)
71
+ }
72
+
73
+ @computed get fontSize(): number {
74
+ return this.manager.fontSize ?? BASE_FONT_SIZE
75
+ }
76
+
77
+ @computed get yAxisConfig(): AxisConfig {
78
+ const { yAxisConfig } = this.manager
79
+ const defaults = getYAxisConfigDefaults(yAxisConfig)
80
+ const custom = { hideAxis: true }
81
+ return new AxisConfig({ ...defaults, ...custom, ...yAxisConfig }, this)
82
+ }
83
+
84
+ @computed private get xAxisConfig(): AxisConfig {
85
+ const { xAxisConfig } = this.manager
86
+ const custom = { labelPadding: 0 }
87
+ return new AxisConfig({ ...custom, ...xAxisConfig }, this)
88
+ }
89
+
90
+ @computed private get horizontalAxisPart(): HorizontalAxis {
91
+ return this.chartState.toHorizontalAxis(this.xAxisConfig)
92
+ }
93
+
94
+ @computed private get verticalAxisPart(): VerticalAxis {
95
+ return this.chartState.toVerticalAxis(this.yAxisConfig)
96
+ }
97
+
98
+ @computed get dualAxis(): DualAxis {
99
+ return new DualAxis({
100
+ bounds: this.innerBounds,
101
+ verticalAxis: this.verticalAxisPart,
102
+ horizontalAxis: this.horizontalAxisPart,
103
+ })
104
+ }
105
+
106
+ @computed get xAxis(): HorizontalAxis {
107
+ return this.dualAxis.horizontalAxis
108
+ }
109
+
110
+ @computed get yAxis(): VerticalAxis {
111
+ return this.dualAxis.verticalAxis
112
+ }
113
+
114
+ @computed get placedSeries(): PlacedLineChartSeries[] {
115
+ return toPlacedLineChartSeries(this.chartState.series, {
116
+ chartState: this.chartState,
117
+ dualAxis: this.dualAxis,
118
+ })
119
+ }
120
+
121
+ @computed private get renderSeries(): RenderLineChartSeries[] {
122
+ return toRenderLineChartSeries(this.placedSeries, {
123
+ isFocusModeActive: this.chartState.isFocusModeActive,
124
+ })
125
+ }
126
+
127
+ /** Start points displayed as dots */
128
+ @computed private get visibleStartPoints(): PlacedPoint[] {
129
+ return this.renderSeries
130
+ .filter(
131
+ (series) =>
132
+ this.visibleStartLabels.has(series.seriesName) &&
133
+ // Only show start points for historical series, not projected ones
134
+ !series.isProjection
135
+ )
136
+ .map((series) => _.minBy(series.placedPoints, (point) => point.x))
137
+ .filter((point) => point !== undefined)
138
+ }
139
+
140
+ /** End points displayed as dots */
141
+ @computed private get visibleEndPoints(): PlacedPoint[] {
142
+ return this.renderSeries
143
+ .filter(
144
+ (series) =>
145
+ this.visibleEndLabels.has(series.seriesName) &&
146
+ // When projected series exist in the chart, only show end dots
147
+ // for the projected series. Otherwise, show end dots for all series
148
+ (!this.hasProjectedSeries || series.isProjection)
149
+ )
150
+ .map((series) => _.maxBy(series.placedPoints, (point) => point.x))
151
+ .filter((point) => point !== undefined)
152
+ }
153
+
154
+ // Same as dualAxis.verticalAxis, but doesn't depend on innerBounds
155
+ @computed get outerBoundsVerticalAxis(): VerticalAxis {
156
+ const yAxis = this.verticalAxisPart.clone()
157
+ yAxis.range = this.bounds.yRange()
158
+ return yAxis
159
+ }
160
+
161
+ @computed private get labelFontSize(): number {
162
+ return Math.floor(GRAPHER_FONT_SCALE_12 * this.fontSize)
163
+ }
164
+
165
+ private formatLabel(value: number): string {
166
+ return this.chartState.formatColumn.formatValueShortWithAbbreviations(
167
+ value
168
+ )
169
+ }
170
+
171
+ @computed private get hasProjectedSeries(): boolean {
172
+ return this.chartState.series.some((series) => !!series.isProjection)
173
+ }
174
+
175
+ @computed private get labelsRange(): [number, number] {
176
+ const {
177
+ horizontalAxisPart,
178
+ manager: { chartAreaPadding = 0 },
179
+ } = this
180
+
181
+ return this.bounds
182
+ .expand({
183
+ top: chartAreaPadding,
184
+ bottom: chartAreaPadding + horizontalAxisPart.height,
185
+ })
186
+ .yRange()
187
+ }
188
+
189
+ @computed private get endLabelsState(): VerticalLabelsState | undefined {
190
+ if (!this.manager.showLegend) return undefined
191
+
192
+ let labelCandidateSeries = this.chartState.series
193
+
194
+ // If there is a projected series, only show the labels for the projected ones
195
+ if (this.hasProjectedSeries)
196
+ labelCandidateSeries = labelCandidateSeries.filter(
197
+ (series) => series.isProjection
198
+ )
199
+
200
+ // If any series is focused, only show the labels for the focused ones
201
+ if (this.chartState.isFocusModeActive)
202
+ labelCandidateSeries = labelCandidateSeries.filter(
203
+ (series) => series.focus.active
204
+ )
205
+
206
+ const endPointBySeriesName = new Map(
207
+ labelCandidateSeries.map((series) => [
208
+ series.seriesName,
209
+ _.maxBy(series.points, (point) => point.x),
210
+ ])
211
+ )
212
+
213
+ const series = labelCandidateSeries.map((series) => {
214
+ const { seriesName } = series
215
+
216
+ const endPoint = endPointBySeriesName.get(series.seriesName)
217
+ const value = endPoint?.y ?? 0
218
+
219
+ const yPosition = this.outerBoundsVerticalAxis.place(value)
220
+ const label = this.formatLabel(value)
221
+
222
+ const color = this.chartState.hasColorScale
223
+ ? darkenColorForLine(
224
+ this.chartState.getColorScaleColor(endPoint?.colorValue)
225
+ )
226
+ : series.color
227
+
228
+ const labelSeries = { seriesName, value, label, yPosition, color }
229
+
230
+ return { ...labelSeries, point: endPoint }
231
+ })
232
+
233
+ return new VerticalLabelsState(series, {
234
+ fontSize: this.labelFontSize,
235
+ fontWeight: 500,
236
+ yRange: this.labelsRange,
237
+ minSpacing: 2,
238
+ resolveCollision: (
239
+ s1: InitialVerticalLabelsSeries,
240
+ s2: InitialVerticalLabelsSeries
241
+ ): InitialVerticalLabelsSeries => {
242
+ const endPoint1 = endPointBySeriesName.get(s1.seriesName)
243
+ const endPoint2 = endPointBySeriesName.get(s2.seriesName)
244
+
245
+ const x1 = endPoint1?.x ?? 0
246
+ const x2 = endPoint2?.x ?? 0
247
+
248
+ // Prefer the series with the larger x value
249
+ if (x1 > x2) return s1
250
+ if (x2 > x1) return s2
251
+
252
+ return s1 // no preference
253
+ },
254
+ })
255
+ }
256
+
257
+ @computed private get startLabelsState(): VerticalLabelsState | undefined {
258
+ if (!this.manager.showLegend) return undefined
259
+
260
+ const showEntityNames =
261
+ !this.manager.isDisplayedAlongsideComplementaryTable
262
+
263
+ let labelCandidateSeries = this.chartState.series
264
+
265
+ // If there is a projected series, only show the labels for the historical ones
266
+ if (this.hasProjectedSeries)
267
+ labelCandidateSeries = labelCandidateSeries.filter(
268
+ (series) => !series.isProjection
269
+ )
270
+
271
+ // If any series is focused, only show the labels for the focused ones
272
+ if (this.chartState.isFocusModeActive)
273
+ labelCandidateSeries = labelCandidateSeries.filter(
274
+ (series) => series.focus.active
275
+ )
276
+
277
+ const startPointBySeriesName = new Map(
278
+ labelCandidateSeries.map((series) => [
279
+ series.seriesName,
280
+ _.minBy(series.points, (point) => point.x),
281
+ ])
282
+ )
283
+
284
+ const series = labelCandidateSeries
285
+ .map((series) => {
286
+ const { seriesName } = series
287
+
288
+ // Don't show start label if there is only a single point
289
+ if (series.points.length < 2) return undefined
290
+
291
+ const startPoint = startPointBySeriesName.get(series.seriesName)
292
+ const value = startPoint?.y ?? 0
293
+
294
+ const yPosition = this.outerBoundsVerticalAxis.place(value)
295
+ const label = showEntityNames
296
+ ? seriesName
297
+ : this.formatLabel(value)
298
+
299
+ const color = this.chartState.hasColorScale
300
+ ? darkenColorForLine(
301
+ this.chartState.getColorScaleColor(
302
+ startPoint?.colorValue
303
+ )
304
+ )
305
+ : series.color
306
+
307
+ const labelSeries = {
308
+ seriesName,
309
+ value,
310
+ label,
311
+ yPosition,
312
+ color,
313
+ }
314
+ return { ...labelSeries, point: startPoint }
315
+ })
316
+ .filter((series) => series !== undefined)
317
+
318
+ return new VerticalLabelsState(series, {
319
+ fontSize: this.labelFontSize,
320
+ fontWeight: 500,
321
+ maxWidth: showEntityNames ? 0.25 * this.bounds.width : undefined,
322
+ minSpacing: showEntityNames ? 5 : 2,
323
+ yRange: this.labelsRange,
324
+ resolveCollision: (
325
+ s1: InitialVerticalLabelsSeries,
326
+ s2: InitialVerticalLabelsSeries
327
+ ): InitialVerticalLabelsSeries => {
328
+ // Prefer to label series that have an end label
329
+ if (this.visibleEndLabels.has(s1.seriesName)) return s1
330
+ if (this.visibleEndLabels.has(s2.seriesName)) return s2
331
+
332
+ const startPoint1 = startPointBySeriesName.get(s1.seriesName)
333
+ const startPoint2 = startPointBySeriesName.get(s2.seriesName)
334
+
335
+ const x1 = startPoint1?.x ?? 0
336
+ const x2 = startPoint2?.x ?? 0
337
+
338
+ // Prefer the series with the larger x value
339
+ if (x1 > x2) return s1
340
+ if (x2 > x1) return s2
341
+
342
+ return s1 // no preference
343
+ },
344
+ })
345
+ }
346
+
347
+ @computed private get endLabelsWidth(): number {
348
+ return this.endLabelsState?.width ?? 0
349
+ }
350
+
351
+ @computed private get startLabelsWidth(): number {
352
+ return this.startLabelsState?.width ?? 0
353
+ }
354
+
355
+ @computed private get paddedEndLabelsWidth(): number {
356
+ return this.endLabelsWidth > 0 ? this.endLabelsWidth + LABEL_PADDING : 0
357
+ }
358
+
359
+ @computed private get paddedStartLabelsWidth(): number {
360
+ return this.startLabelsWidth > 0
361
+ ? this.startLabelsWidth + LABEL_PADDING
362
+ : 0
363
+ }
364
+
365
+ @computed private get visibleStartLabels(): Set<SeriesName> {
366
+ return new Set(
367
+ this.startLabelsState?.series.map((series) => series.seriesName)
368
+ )
369
+ }
370
+
371
+ @computed private get visibleEndLabels(): Set<SeriesName> {
372
+ return new Set(
373
+ this.endLabelsState?.series.map((series) => series.seriesName)
374
+ )
375
+ }
376
+
377
+ override render(): React.ReactElement {
378
+ if (this.chartState.errorInfo.reason)
379
+ return (
380
+ <NoDataModal
381
+ manager={this.manager}
382
+ bounds={this.props.bounds}
383
+ message={this.chartState.errorInfo.reason}
384
+ />
385
+ )
386
+
387
+ return (
388
+ <>
389
+ <VerticalAxisZeroLine
390
+ verticalAxis={this.dualAxis.verticalAxis}
391
+ bounds={this.dualAxis.innerBounds}
392
+ />
393
+ <HorizontalAxisComponent
394
+ axis={this.dualAxis.horizontalAxis}
395
+ bounds={this.dualAxis.bounds}
396
+ showEndpointsOnly
397
+ />
398
+ <Lines
399
+ series={this.renderSeries}
400
+ dualAxis={this.dualAxis}
401
+ multiColor={this.chartState.hasColorScale}
402
+ hidePoints
403
+ lineStrokeWidth={1.5}
404
+ lineOutlineWidth={0}
405
+ isStatic={this.manager.isStatic}
406
+ />
407
+ {this.visibleStartPoints.map((point, index) => (
408
+ <Dot key={index} point={point} />
409
+ ))}
410
+ {this.visibleEndPoints.map((point, index) => (
411
+ <Dot key={index} point={point} />
412
+ ))}
413
+ {this.startLabelsState && (
414
+ <VerticalLabels
415
+ state={this.startLabelsState}
416
+ yAxis={this.dualAxis.verticalAxis}
417
+ x={this.innerBounds.left - LABEL_PADDING}
418
+ xAnchor="end"
419
+ />
420
+ )}
421
+ {this.endLabelsState && (
422
+ <VerticalLabels
423
+ state={this.endLabelsState}
424
+ yAxis={this.dualAxis.verticalAxis}
425
+ x={this.innerBounds.right + LABEL_PADDING}
426
+ />
427
+ )}
428
+ </>
429
+ )
430
+ }
431
+ }
432
+
433
+ function Dot({ point }: { point: PlacedPoint }): React.ReactElement | null {
434
+ return (
435
+ <circle cx={point.x} cy={point.y} r={DOT_RADIUS} fill={point.color} />
436
+ )
437
+ }
@@ -0,0 +1,258 @@
1
+ import * as _ from "lodash-es"
2
+ import React from "react"
3
+ import {
4
+ Bounds,
5
+ PointVector,
6
+ makeIdForHumanConsumption,
7
+ pointsToPath,
8
+ } from "../../utils/index.js"
9
+ import { computed, makeObservable } from "mobx"
10
+ import { observer } from "mobx-react"
11
+ import { GRAPHER_OPACITY_MUTE } from "../core/GrapherConstants"
12
+ import {
13
+ DEFAULT_LINE_COLOR,
14
+ DEFAULT_LINE_OUTLINE_WIDTH,
15
+ DEFAULT_MARKER_RADIUS,
16
+ DEFAULT_STROKE_WIDTH,
17
+ LinesProps,
18
+ PlacedLineChartSeries,
19
+ RenderLineChartSeries,
20
+ } from "./LineChartConstants"
21
+ import { getSeriesKey } from "../chart/ChartUtils"
22
+ import { GRAPHER_BACKGROUND_DEFAULT } from "../color/ColorConstants"
23
+ import { MultiColorPolyline } from "../scatterCharts/MultiColorPolyline"
24
+
25
+ @observer
26
+ export class Lines extends React.Component<LinesProps> {
27
+ constructor(props: LinesProps) {
28
+ super(props)
29
+ makeObservable(this)
30
+ }
31
+
32
+ @computed get bounds(): Bounds {
33
+ const { horizontalAxis, verticalAxis } = this.props.dualAxis
34
+ return Bounds.fromCorners(
35
+ new PointVector(horizontalAxis.range[0], verticalAxis.range[0]),
36
+ new PointVector(horizontalAxis.range[1], verticalAxis.range[1])
37
+ )
38
+ }
39
+
40
+ @computed private get markerRadius(): number {
41
+ return this.props.markerRadius ?? DEFAULT_MARKER_RADIUS
42
+ }
43
+
44
+ @computed private get strokeWidth(): number {
45
+ return this.props.lineStrokeWidth ?? DEFAULT_STROKE_WIDTH
46
+ }
47
+
48
+ @computed private get outlineWidth(): number {
49
+ return this.props.lineOutlineWidth ?? DEFAULT_LINE_OUTLINE_WIDTH
50
+ }
51
+
52
+ @computed private get outlineColor(): string {
53
+ return this.props.backgroundColor ?? GRAPHER_BACKGROUND_DEFAULT
54
+ }
55
+
56
+ // Don't display point markers if there are very many of them for performance reasons
57
+ // Note that we're using circle elements instead of marker-mid because marker performance in Safari 10 is very poor for some reason
58
+ @computed private get hasMarkers(): boolean {
59
+ if (this.props.hidePoints) return false
60
+ const totalPoints = _.sum(
61
+ this.props.series
62
+ .filter((series) => this.seriesHasMarkers(series))
63
+ .map((series) => series.placedPoints.length)
64
+ )
65
+ return totalPoints < 500
66
+ }
67
+
68
+ @computed private get hasMarkersOnlySeries(): boolean {
69
+ return this.props.series.some((series) => series.plotMarkersOnly)
70
+ }
71
+
72
+ private seriesHasMarkers(series: RenderLineChartSeries): boolean {
73
+ if (
74
+ series.hover.background ||
75
+ series.isProjection ||
76
+ // if the series has a line, but there is another one that hasn't, then
77
+ // don't show markers since the plotted line is likely a smoothed version
78
+ (this.hasMarkersOnlySeries && !series.plotMarkersOnly)
79
+ )
80
+ return false
81
+ return !series.focus.background || series.hover.active
82
+ }
83
+
84
+ private seriesIsInForeground(series: RenderLineChartSeries): boolean {
85
+ return (
86
+ series.hover.active ||
87
+ series.focus.active ||
88
+ (series.focus.idle && series.hover.idle)
89
+ )
90
+ }
91
+
92
+ private renderLine(
93
+ series: RenderLineChartSeries
94
+ ): React.ReactElement | undefined {
95
+ if (series.plotMarkersOnly) return
96
+ const { isProjection } = series
97
+
98
+ const isInForeground = this.seriesIsInForeground(series)
99
+
100
+ const color = series.placedPoints[0]?.color ?? DEFAULT_LINE_COLOR
101
+
102
+ const strokeDasharray = isProjection ? "2,3" : undefined
103
+ const strokeWidth = isInForeground
104
+ ? this.strokeWidth
105
+ : 0.66 * this.strokeWidth
106
+ const strokeOpacity = isInForeground ? 1 : GRAPHER_OPACITY_MUTE
107
+
108
+ const showOutline = isInForeground
109
+ const outlineColor = this.outlineColor
110
+ const outlineWidth = strokeWidth + this.outlineWidth * 2
111
+
112
+ const outline = (
113
+ <LinePath
114
+ id={makeIdForHumanConsumption("outline", series.displayName)}
115
+ placedPoints={series.placedPoints}
116
+ stroke={outlineColor}
117
+ strokeWidth={outlineWidth.toFixed(1)}
118
+ />
119
+ )
120
+
121
+ const line = this.props.multiColor ? (
122
+ <MultiColorPolyline
123
+ id={makeIdForHumanConsumption("line", series.seriesName)}
124
+ points={series.placedPoints}
125
+ strokeLinejoin="round"
126
+ strokeWidth={strokeWidth.toFixed(1)}
127
+ strokeDasharray={strokeDasharray}
128
+ strokeOpacity={strokeOpacity}
129
+ />
130
+ ) : (
131
+ <LinePath
132
+ id={makeIdForHumanConsumption("line", series.seriesName)}
133
+ placedPoints={series.placedPoints}
134
+ stroke={color}
135
+ strokeWidth={strokeWidth.toFixed(1)}
136
+ strokeOpacity={strokeOpacity}
137
+ strokeDasharray={strokeDasharray}
138
+ />
139
+ )
140
+
141
+ return (
142
+ <>
143
+ {showOutline && outline}
144
+ {line}
145
+ </>
146
+ )
147
+ }
148
+
149
+ private renderLineMarkers(
150
+ series: RenderLineChartSeries
151
+ ): React.ReactElement | undefined {
152
+ const { horizontalAxis } = this.props.dualAxis
153
+
154
+ const forceMarkers =
155
+ // If the series only contains one point, then we will always want to
156
+ // show a marker/circle because we can't draw a line.
157
+ series.placedPoints.length === 1 ||
158
+ // If no line is plotted, we'll always want to show markers
159
+ series.plotMarkersOnly
160
+
161
+ // check if we should hide markers on the chart and series level
162
+ const hideMarkers = !this.hasMarkers || !this.seriesHasMarkers(series)
163
+
164
+ if (hideMarkers && !forceMarkers) return
165
+
166
+ const opacity = this.seriesIsInForeground(series)
167
+ ? 1
168
+ : GRAPHER_OPACITY_MUTE
169
+
170
+ const outlineColor = series.plotMarkersOnly
171
+ ? this.outlineColor
172
+ : undefined
173
+ const outlineWidth = series.plotMarkersOnly
174
+ ? this.outlineWidth
175
+ : undefined
176
+
177
+ return (
178
+ <g id={makeIdForHumanConsumption("datapoints", series.displayName)}>
179
+ {series.placedPoints.map((value, index) => (
180
+ <circle
181
+ id={makeIdForHumanConsumption(
182
+ horizontalAxis.formatTick(value.time)
183
+ )}
184
+ key={index}
185
+ cx={value.x}
186
+ cy={value.y}
187
+ r={this.markerRadius}
188
+ fill={value.color}
189
+ stroke={outlineColor}
190
+ strokeWidth={outlineWidth}
191
+ opacity={opacity}
192
+ />
193
+ ))}
194
+ </g>
195
+ )
196
+ }
197
+
198
+ private renderLines(): React.ReactElement {
199
+ return (
200
+ <>
201
+ {this.props.series.map((series, index) => (
202
+ <React.Fragment key={getSeriesKey(series, index)}>
203
+ {this.renderLine(series)}
204
+ {this.renderLineMarkers(series)}
205
+ </React.Fragment>
206
+ ))}
207
+ </>
208
+ )
209
+ }
210
+
211
+ private renderStatic(): React.ReactElement {
212
+ return (
213
+ <g id={makeIdForHumanConsumption("lines")}>{this.renderLines()}</g>
214
+ )
215
+ }
216
+
217
+ private renderInteractive(): React.ReactElement {
218
+ const { bounds } = this
219
+ return (
220
+ <g className="Lines">
221
+ <rect
222
+ x={Math.round(bounds.x)}
223
+ y={Math.round(bounds.y)}
224
+ width={Math.round(bounds.width)}
225
+ height={Math.round(bounds.height)}
226
+ fill="rgba(255,255,255,0)"
227
+ opacity={0}
228
+ />
229
+ {this.renderLines()}
230
+ </g>
231
+ )
232
+ }
233
+
234
+ override render(): React.ReactElement {
235
+ return this.props.isStatic
236
+ ? this.renderStatic()
237
+ : this.renderInteractive()
238
+ }
239
+ }
240
+
241
+ interface LinePathProps extends React.SVGProps<SVGPathElement> {
242
+ placedPoints: PlacedLineChartSeries["placedPoints"]
243
+ }
244
+
245
+ function LinePath(props: LinePathProps): React.ReactElement {
246
+ const { placedPoints, ...pathProps } = props
247
+ const coords = placedPoints.map(({ x, y }) => [x, y] as [number, number])
248
+ return (
249
+ <path
250
+ fill="none"
251
+ strokeLinecap="butt"
252
+ strokeLinejoin="round"
253
+ stroke={DEFAULT_LINE_COLOR}
254
+ {...pathProps}
255
+ d={pointsToPath(coords)}
256
+ />
257
+ )
258
+ }