@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,294 @@
1
+ import * as React from "react"
2
+ import { computed, action, makeObservable } from "mobx"
3
+ import { observer } from "mobx-react"
4
+ import { faInfoCircle } from "@fortawesome/free-solid-svg-icons"
5
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
6
+ import classnames from "classnames"
7
+ import { match } from "ts-pattern"
8
+ import {
9
+ Bounds,
10
+ GrapherTooltipAnchor,
11
+ stripOuterParentheses,
12
+ } from "../../utils/index.js"
13
+ import {
14
+ TooltipProps,
15
+ TooltipManager,
16
+ TooltipContainerProps,
17
+ TooltipContext,
18
+ TooltipFooterIcon,
19
+ } from "./TooltipProps"
20
+ import { SignificanceIcon } from "./TooltipContents.js"
21
+
22
+ export * from "./TooltipContents.js"
23
+ export { TooltipState } from "./TooltipState.js"
24
+
25
+ export class TooltipCard extends React.Component<
26
+ TooltipProps & TooltipContainerProps
27
+ > {
28
+ private base = React.createRef<HTMLDivElement>()
29
+ private bounds: Bounds | undefined = undefined
30
+
31
+ private updateBounds(): void {
32
+ if (this.base.current) {
33
+ this.bounds = Bounds.fromElement(this.base.current)
34
+ }
35
+ }
36
+
37
+ private get tooltipStyle(): React.CSSProperties {
38
+ const { bounds } = this
39
+ const {
40
+ containerBounds,
41
+ anchor,
42
+ x = 0,
43
+ y = 0,
44
+ offsetX = 0,
45
+ offsetY = 0,
46
+ } = this.props
47
+ const isPinnedToBottom = anchor === GrapherTooltipAnchor.bottom
48
+
49
+ const style = { ...this.props.style }
50
+
51
+ // if container dimensions are given, we make sure the tooltip
52
+ // is positioned within the container bounds
53
+ if (
54
+ containerBounds?.width &&
55
+ containerBounds.height &&
56
+ !isPinnedToBottom
57
+ ) {
58
+ let adjustedOffsetY = offsetY
59
+ let adjustedOffsetX = offsetX
60
+
61
+ if (this.props.offsetYDirection === "upward") {
62
+ adjustedOffsetY = -offsetY - (bounds?.height ?? 0)
63
+ }
64
+
65
+ if (
66
+ this.props.offsetXDirection === "left" &&
67
+ x > (bounds?.width ?? 0)
68
+ ) {
69
+ adjustedOffsetX = -offsetX - (bounds?.width ?? 0)
70
+ }
71
+
72
+ // Ensure tooltip remains inside chart
73
+ let left = x + adjustedOffsetX
74
+ let top = y + adjustedOffsetY
75
+ if (bounds) {
76
+ if (left + bounds.width > containerBounds?.width)
77
+ left -= bounds.width + 2 * adjustedOffsetX // flip left
78
+ if (top + bounds.height * 0.75 > containerBounds.height)
79
+ top -= bounds.height + 2 * adjustedOffsetY // flip upwards eventually...
80
+ if (top + bounds.height > containerBounds.height)
81
+ top = containerBounds.height - bounds.height // ...but first pin at bottom
82
+
83
+ if (left < 0) left = 0 // pin on left
84
+ if (top < 0) top = 0 // pin at top
85
+ }
86
+
87
+ style.position = "absolute"
88
+ style.left = left
89
+ style.top = top
90
+ }
91
+
92
+ // ignore the given width and max-width if the tooltip position is fixed
93
+ // since we want to use the full width of the screen in that case
94
+ if (isPinnedToBottom && (style.width || style.maxWidth)) {
95
+ style.width = style.maxWidth = undefined
96
+ }
97
+
98
+ return style
99
+ }
100
+
101
+ override componentDidMount(): void {
102
+ this.updateBounds()
103
+ }
104
+
105
+ override componentDidUpdate(): void {
106
+ this.updateBounds()
107
+ }
108
+
109
+ override render(): React.ReactElement {
110
+ let {
111
+ id,
112
+ title,
113
+ titleAnnotation,
114
+ subtitle,
115
+ subtitleFormat,
116
+ footer,
117
+ dissolve,
118
+ children,
119
+ anchor,
120
+ } = this.props
121
+ const isPinnedToBottom = anchor === GrapherTooltipAnchor.bottom
122
+
123
+ // add a preposition to unit-based subtitles
124
+ const hasHeader = title !== undefined || subtitle !== undefined
125
+ if (!!subtitle && subtitleFormat === "unit") {
126
+ const unit = subtitle.toString()
127
+ const preposition = !unit.match(/^(per|in|\() /i) ? "in " : ""
128
+ subtitle = preposition + stripOuterParentheses(unit)
129
+ }
130
+
131
+ // flag the year in the header and add note in footer (if necessary)
132
+ const timeNotice = !!subtitle && subtitleFormat === "notice"
133
+
134
+ // style the box differently if just displaying title/subtitle
135
+ const plain = hasHeader && !children
136
+
137
+ // skip transition delay if requested
138
+ const immediate = dissolve === "immediate"
139
+
140
+ return (
141
+ <TooltipContext.Provider value={{ anchor }}>
142
+ <div
143
+ className={classnames("tooltip-container", {
144
+ "fixed-bottom": isPinnedToBottom,
145
+ })}
146
+ >
147
+ <div
148
+ ref={this.base}
149
+ id={id?.toString()}
150
+ role="tooltip"
151
+ className={classnames("Tooltip", {
152
+ plain,
153
+ dissolve,
154
+ immediate,
155
+ })}
156
+ style={this.tooltipStyle}
157
+ >
158
+ {hasHeader && (
159
+ <div className="frontmatter">
160
+ {title && (
161
+ <div className="title">
162
+ {title}{" "}
163
+ <span className="annotation">
164
+ {titleAnnotation}
165
+ </span>
166
+ </div>
167
+ )}
168
+ {subtitle && (
169
+ <div className="subtitle">
170
+ {timeNotice && (
171
+ <TooltipIcon
172
+ icon={TooltipFooterIcon.Notice}
173
+ />
174
+ )}
175
+ <span>{subtitle}</span>
176
+ </div>
177
+ )}
178
+ </div>
179
+ )}
180
+ <div className="content-and-endmatter">
181
+ {children && (
182
+ <div className="content">{children}</div>
183
+ )}
184
+ {footer && footer.length > 0 && (
185
+ <div
186
+ className={classnames("endmatter", {
187
+ "multiple-lines": footer.length > 1,
188
+ })}
189
+ >
190
+ {footer?.map(({ icon, text }) => (
191
+ <div
192
+ key={text}
193
+ className={classnames("line", {
194
+ "icon-sig":
195
+ icon ===
196
+ TooltipFooterIcon.Significance,
197
+ "no-icon":
198
+ icon ===
199
+ TooltipFooterIcon.None,
200
+ })}
201
+ >
202
+ <TooltipIcon icon={icon} />
203
+ <p>{text}</p>
204
+ </div>
205
+ ))}
206
+ </div>
207
+ )}
208
+ </div>
209
+ </div>
210
+ </div>
211
+ </TooltipContext.Provider>
212
+ )
213
+ }
214
+ }
215
+
216
+ interface ManagedTooltipContainerProps extends TooltipContainerProps {
217
+ tooltipManager: TooltipManager
218
+ }
219
+
220
+ @observer
221
+ export class TooltipContainer extends React.Component<ManagedTooltipContainerProps> {
222
+ constructor(props: ManagedTooltipContainerProps) {
223
+ super(props)
224
+ makeObservable(this)
225
+ }
226
+
227
+ @computed private get tooltip(): TooltipProps | undefined {
228
+ const { tooltip } = this.props.tooltipManager
229
+ return tooltip?.get()
230
+ }
231
+
232
+ override render(): React.ReactElement | null {
233
+ const { props, tooltip } = this
234
+ if (!tooltip) return null
235
+ return <TooltipCard {...props} {...tooltip} />
236
+ }
237
+ }
238
+
239
+ interface ManagedTooltipProps extends TooltipProps {
240
+ tooltipManager: TooltipManager
241
+ }
242
+
243
+ @observer
244
+ export class Tooltip extends React.Component<ManagedTooltipProps> {
245
+ constructor(props: ManagedTooltipProps) {
246
+ super(props)
247
+ makeObservable(this)
248
+ }
249
+
250
+ override componentDidMount(): void {
251
+ this.connectTooltipToContainer()
252
+ }
253
+
254
+ @action.bound private connectTooltipToContainer(): void {
255
+ this.props.tooltipManager.tooltip?.set(this.props)
256
+ }
257
+
258
+ @action.bound private removeToolTipFromContainer(): void {
259
+ this.props.tooltipManager.tooltip?.set(undefined)
260
+ }
261
+
262
+ override componentDidUpdate(): void {
263
+ this.connectTooltipToContainer()
264
+ }
265
+
266
+ override componentWillUnmount(): void {
267
+ this.removeToolTipFromContainer()
268
+ }
269
+
270
+ override render(): null {
271
+ return null
272
+ }
273
+ }
274
+
275
+ function TooltipIcon({
276
+ icon,
277
+ }: {
278
+ icon: TooltipFooterIcon
279
+ }): React.ReactElement | null {
280
+ return match(icon)
281
+ .with(TooltipFooterIcon.Notice, () => (
282
+ <FontAwesomeIcon className="icon" icon={faInfoCircle} />
283
+ ))
284
+ .with(TooltipFooterIcon.Stripes, () => (
285
+ <div className="stripes icon"></div>
286
+ ))
287
+ .with(TooltipFooterIcon.Significance, () => (
288
+ <div className="icon">
289
+ <SignificanceIcon />
290
+ </div>
291
+ ))
292
+ .with(TooltipFooterIcon.None, () => null)
293
+ .exhaustive()
294
+ }
@@ -0,0 +1,383 @@
1
+ import * as _ from "lodash-es"
2
+ import * as React from "react"
3
+ import classnames from "classnames"
4
+ import { NO_DATA_LABEL } from "../color/ColorScale.js"
5
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
6
+ import { faInfoCircle, faS } from "@fortawesome/free-solid-svg-icons"
7
+ import { formatInlineList, GrapherTooltipAnchor } from "../../utils/index.js"
8
+ import { GrapherTrendArrow } from "../../components/index.js"
9
+ import {
10
+ TooltipValueProps,
11
+ TooltipValueRangeProps,
12
+ TooltipContext,
13
+ TooltipTableProps,
14
+ TooltipVariableProps,
15
+ } from "./TooltipProps"
16
+ import { makeAxisLabel } from "../chart/ChartUtils.js"
17
+ import * as R from "remeda"
18
+ import { CoreColumn } from "../../core-table/index.js"
19
+
20
+ type TooltipValue = number | string | undefined
21
+
22
+ export const NO_DATA_COLOR = "#999"
23
+
24
+ export function TooltipValue({
25
+ label,
26
+ unit,
27
+ value,
28
+ color,
29
+ originalTime,
30
+ isProjection,
31
+ labelVariant = "label+unit",
32
+ isRoundedToSignificantFigures,
33
+ showSignificanceSuperscript,
34
+ }: TooltipValueProps): React.ReactElement {
35
+ const displayValue = value || NO_DATA_LABEL
36
+ const displayColor = displayValue === NO_DATA_LABEL ? NO_DATA_COLOR : color
37
+
38
+ const showSuperscript =
39
+ showSignificanceSuperscript && isRoundedToSignificantFigures
40
+ const superscript = showSuperscript ? (
41
+ <SignificanceIcon asSuperscript={true} />
42
+ ) : null
43
+
44
+ return (
45
+ <Variable
46
+ label={label}
47
+ unit={unit}
48
+ color={displayColor}
49
+ isProjection={isProjection}
50
+ originalTimes={originalTime ? [originalTime] : undefined}
51
+ labelVariant={labelVariant}
52
+ >
53
+ <span>
54
+ {displayValue}
55
+ {superscript}
56
+ </span>
57
+ </Variable>
58
+ )
59
+ }
60
+
61
+ export function TooltipValueRange({
62
+ label,
63
+ unit,
64
+ values,
65
+ colors,
66
+ originalTimes,
67
+ trend,
68
+ labelVariant = "label+unit",
69
+ isRoundedToSignificantFigures,
70
+ showSignificanceSuperscript,
71
+ }: TooltipValueRangeProps): React.ReactElement | null {
72
+ const [firstTerm, lastTerm] = values
73
+
74
+ if (firstTerm === undefined && lastTerm === undefined) return null
75
+
76
+ const showSuperscript =
77
+ showSignificanceSuperscript && isRoundedToSignificantFigures
78
+ const superscript = showSuperscript ? (
79
+ <SignificanceIcon asSuperscript={true} />
80
+ ) : null
81
+
82
+ return (
83
+ <Variable
84
+ label={label}
85
+ unit={unit}
86
+ originalTimes={originalTimes}
87
+ labelVariant={labelVariant}
88
+ >
89
+ <span className="range">
90
+ <span className="term">
91
+ <span style={{ color: colors?.[0] }}>{firstTerm}</span>
92
+ {!lastTerm && superscript}
93
+ </span>
94
+ {trend && (
95
+ <GrapherTrendArrow direction={trend} isColored={!colors} />
96
+ )}
97
+ {lastTerm && (
98
+ <span className="term">
99
+ <span style={{ color: colors?.[1] }}>{lastTerm}</span>
100
+ {superscript}
101
+ </span>
102
+ )}
103
+ </span>
104
+ </Variable>
105
+ )
106
+ }
107
+
108
+ function Variable({
109
+ label,
110
+ unit,
111
+ children,
112
+ color,
113
+ originalTimes,
114
+ isProjection,
115
+ labelVariant = "label+unit",
116
+ }: TooltipVariableProps): React.ReactElement {
117
+ const { mainLabel: columnName, unit: formattedUnit } = makeAxisLabel({
118
+ label: label || "",
119
+ displayUnit: unit,
120
+ })
121
+
122
+ const displayOriginalTimes =
123
+ _.uniq((originalTimes ?? []).filter((t) => t !== undefined)).join(
124
+ "\u2013"
125
+ ) || null
126
+
127
+ return (
128
+ <div
129
+ className={classnames("variable", {
130
+ "variable--no-name": labelVariant === "unit-only",
131
+ })}
132
+ >
133
+ <div className="definition">
134
+ {columnName && <span className="name">{columnName}</span>}
135
+ {formattedUnit && formattedUnit.length > 1 && (
136
+ <span className="unit">{formattedUnit}</span>
137
+ )}
138
+ {isProjection && (
139
+ <span className="projection">projected data</span>
140
+ )}
141
+ </div>
142
+ <div className="values" style={{ color }}>
143
+ {children}
144
+ {displayOriginalTimes && (
145
+ <span className="time-notice">
146
+ <FontAwesomeIcon icon={faInfoCircle} />
147
+ {displayOriginalTimes}
148
+ </span>
149
+ )}
150
+ </div>
151
+ </div>
152
+ )
153
+ }
154
+
155
+ export function TooltipTable({
156
+ columns,
157
+ rows,
158
+ totals = [],
159
+ }: TooltipTableProps): React.ReactElement | null {
160
+ const context = React.useContext(TooltipContext)
161
+ const focal = rows.some((row) => row.focused)
162
+ const swatched = rows.some((row) => row.swatch)
163
+
164
+ const tooEmpty =
165
+ rows.length < 2 ||
166
+ totals.every((value) => value === undefined) ||
167
+ rows.some(({ values }) => values.every((value) => value === undefined))
168
+ const tooTrivial = R.zip(columns, totals).every(
169
+ ([column, total]) => !!column?.formatValue(total).match(/^100(\.0+)?%/)
170
+ )
171
+ const showTotals = totals && !(tooEmpty || tooTrivial)
172
+
173
+ // if the tooltip is pinned to the bottom, show the total at the top,
174
+ // so that it's always visible even if the tooltip is scrollable
175
+ const showTotalsAtTop = context?.anchor === GrapherTooltipAnchor.bottom
176
+
177
+ const totalsCells = R.zip(columns, totals).map(([column, total]) => (
178
+ <td key={column?.label} className="series-value">
179
+ {column && total !== undefined ? column.formatValue(total) : null}
180
+ </td>
181
+ ))
182
+
183
+ return (
184
+ <table className={classnames("series-list", { focal, swatched })}>
185
+ {columns.length > 1 && (
186
+ <thead>
187
+ <tr>
188
+ <td className="series-color"></td>
189
+ <td className="series-name"></td>
190
+ {columns.map((column) => (
191
+ <td className="series-value" key={column.label}>
192
+ {column.label}
193
+ </td>
194
+ ))}
195
+ </tr>
196
+ </thead>
197
+ )}
198
+ <tbody>
199
+ {showTotals && showTotalsAtTop && (
200
+ <>
201
+ <tr className="total--top">
202
+ <td className="series-color"></td>
203
+ <td className="series-name">Total</td>
204
+ {totalsCells}
205
+ </tr>
206
+ <tr className="spacer"></tr>
207
+ </>
208
+ )}
209
+ {rows.map((row) => {
210
+ const {
211
+ name,
212
+ focused,
213
+ blurred,
214
+ striped,
215
+ annotation,
216
+ values,
217
+ originalTime,
218
+ swatch = {},
219
+ } = row
220
+ const {
221
+ color: swatchColor = "transparent",
222
+ opacity: swatchOpacity = 1,
223
+ } = swatch
224
+
225
+ const [_m, seriesName, seriesParenthetical] =
226
+ name.trim().match(/^(.*?)(\([^()]*\))?$/) ?? []
227
+
228
+ return (
229
+ <tr
230
+ key={name}
231
+ className={classnames({
232
+ focused,
233
+ blurred,
234
+ striped,
235
+ })}
236
+ >
237
+ <td className="series-color">
238
+ <div
239
+ className="swatch"
240
+ style={{
241
+ backgroundColor: swatchColor,
242
+ opacity: swatchOpacity,
243
+ }}
244
+ />
245
+ </td>
246
+ <td className="series-name">
247
+ {seriesName}
248
+ {seriesParenthetical && (
249
+ <span className="parenthetical">
250
+ {seriesParenthetical}
251
+ </span>
252
+ )}
253
+ {annotation && (
254
+ <span className="annotation">
255
+ {annotation}
256
+ </span>
257
+ )}
258
+ </td>
259
+ {R.zip(columns, values).map(([column, value]) => {
260
+ const missing = value === undefined
261
+ return column ? (
262
+ <td
263
+ key={column.label}
264
+ className={classnames("series-value", {
265
+ missing,
266
+ })}
267
+ >
268
+ {!missing && column.formatValue(value)}
269
+ </td>
270
+ ) : null
271
+ })}
272
+ {originalTime && (
273
+ <td className="time-notice">
274
+ <FontAwesomeIcon icon={faInfoCircle} />{" "}
275
+ {originalTime}
276
+ </td>
277
+ )}
278
+ </tr>
279
+ )
280
+ })}
281
+ {showTotals && !showTotalsAtTop && (
282
+ <>
283
+ <tr className="spacer"></tr>
284
+ <tr className="total">
285
+ <td className="series-color"></td>
286
+ <td className="series-name">Total</td>
287
+ {totalsCells}
288
+ </tr>
289
+ </>
290
+ )}
291
+ </tbody>
292
+ </table>
293
+ )
294
+ }
295
+
296
+ export function SignificanceIcon({
297
+ asSuperscript = false,
298
+ }: {
299
+ asSuperscript?: boolean
300
+ }): React.ReactElement {
301
+ return (
302
+ <div
303
+ className={classnames("icon-circled-s", {
304
+ "as-superscript": asSuperscript,
305
+ })}
306
+ >
307
+ <div className="circle" />
308
+ <FontAwesomeIcon icon={faS} />
309
+ </div>
310
+ )
311
+ }
312
+
313
+ export function makeTooltipToleranceNotice(
314
+ targetYear: string,
315
+ { plural }: { plural: boolean } = { plural: false }
316
+ ): string {
317
+ const dataPoint = plural ? "data points" : "data point"
318
+ return `Data not available for ${targetYear}. Showing closest available ${dataPoint} instead`
319
+ }
320
+
321
+ export function makeTooltipRoundingNotice(
322
+ numSignificantFigures: number[],
323
+ { plural }: { plural: boolean } = { plural: true }
324
+ ): string {
325
+ const uniqueNumSigFigs = _.uniq(numSignificantFigures)
326
+ const formattedNumSigFigs = formatInlineList(
327
+ _.sortBy(uniqueNumSigFigs),
328
+ "or"
329
+ )
330
+
331
+ const values = plural ? "Values" : "Value"
332
+ const are = plural ? "are" : "is"
333
+ const figures = formattedNumSigFigs === "1" ? "figure" : "figures"
334
+ return `${values} ${are} rounded to ${formattedNumSigFigs} significant ${figures}`
335
+ }
336
+
337
+ export function toTooltipTableColumns(
338
+ columns: CoreColumn | CoreColumn[]
339
+ ): TooltipTableProps["columns"] {
340
+ const columnsArray = Array.isArray(columns) ? columns : [columns]
341
+
342
+ return columnsArray.map((column) => ({
343
+ label: column.displayName,
344
+ formatValue: (value) =>
345
+ column.formatValueShort(value, { trailingZeroes: true }),
346
+ }))
347
+ }
348
+
349
+ export function formatTooltipRangeValues(
350
+ values: TooltipValue[],
351
+ column: CoreColumn
352
+ ): [string, string] {
353
+ const formatTooltipValueShort = (value: TooltipValue): string =>
354
+ formatTooltipValue(value, (value) => column.formatValueShort(value))
355
+ const formatTooltipValueShortWithAbbreviations = (
356
+ value: TooltipValue
357
+ ): string =>
358
+ formatTooltipValue(value, (value) =>
359
+ column.formatValueShortWithAbbreviations(value)
360
+ )
361
+
362
+ const [firstValue, lastValue] = values.map((v) =>
363
+ formatTooltipValueShort(v)
364
+ )
365
+
366
+ const [firstTerm, lastTerm] =
367
+ // TODO: would be nicer to actually measure the typeset text but we would need to
368
+ // add Lato's metrics to the `string-pixel-width` module to use Bounds.forText
369
+ _.sum([firstValue?.length, lastValue?.length]) > 20
370
+ ? values.map((v) => formatTooltipValueShortWithAbbreviations(v))
371
+ : [firstValue, lastValue]
372
+
373
+ return [firstTerm, lastTerm]
374
+ }
375
+
376
+ function formatTooltipValue(
377
+ value: TooltipValue,
378
+ formatValue: (value: number) => string
379
+ ): string {
380
+ if (value === undefined) return NO_DATA_LABEL
381
+ if (typeof value === "string") return value
382
+ return formatValue(value)
383
+ }