@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,318 @@
1
+ /**
2
+ * Utility exports for @buildcanada/charts
3
+ */
4
+
5
+ // Bounds utility
6
+ export {
7
+ type GridBounds,
8
+ type SplitBoundsPadding,
9
+ FontFamily,
10
+ Bounds,
11
+ } from "./Bounds.js"
12
+
13
+ // Browser utilities
14
+ export { isAndroid, isIOS } from "./BrowserUtils.js"
15
+
16
+ // Dayjs
17
+ import dayjs from "./dayjs.js"
18
+ export { dayjs }
19
+ export type {
20
+ Dayjs,
21
+ customParseFormatType,
22
+ isTodayType,
23
+ isYesterdayType,
24
+ relativeTimeType,
25
+ utcType,
26
+ } from "./dayjs.js"
27
+
28
+ // Format value
29
+ export { formatValue, checkIsVeryShortUnit } from "./formatValue.js"
30
+
31
+ // Fuzzy search
32
+ export { FuzzySearch, type FuzzySearchResult } from "./FuzzySearch.js"
33
+
34
+ // Grapher config utilities
35
+ export {
36
+ diffGrapherConfigs,
37
+ mergeGrapherConfigs,
38
+ } from "./grapherConfigUtils.js"
39
+
40
+ // Image utilities
41
+ export {
42
+ THUMBNAIL_WIDTH,
43
+ LARGE_THUMBNAIL_WIDTH,
44
+ LARGEST_IMAGE_WIDTH,
45
+ appendImageSizeSuffix,
46
+ getSizes,
47
+ generateSrcSet,
48
+ getFilenameWithoutExtension,
49
+ getFilenameAsPng,
50
+ getFilenameExtension,
51
+ getFilenameMIMEType,
52
+ type SourceProps,
53
+ generateSourceProps,
54
+ getFeaturedImageFilename,
55
+ } from "./image.js"
56
+
57
+ // isPresent utility
58
+ export { isPresent } from "./isPresent.js"
59
+
60
+ // Metadata helpers
61
+ export {
62
+ getOriginAttributionFragments,
63
+ getAttributionFragmentsFromVariable,
64
+ getETLPathComponents,
65
+ formatAuthors,
66
+ formatAuthorsForBibtex,
67
+ getLastUpdatedFromVariable,
68
+ getNextUpdateFromVariable,
69
+ getPhraseForProcessingLevel,
70
+ splitSourceTextIntoFragments,
71
+ prepareSourcesForDisplay,
72
+ formatSourceDate,
73
+ getDateRange,
74
+ getCitationLong,
75
+ getCitationShort,
76
+ getPhraseForArchivalDate,
77
+ } from "./metadataHelpers.js"
78
+
79
+ // OwidVariable display config
80
+ export { OwidVariableDisplayConfig } from "./OwidVariable.js"
81
+
82
+ // Persistable
83
+ export {
84
+ type Persistable,
85
+ objectWithPersistablesToObject,
86
+ updatePersistables,
87
+ deleteRuntimeAndUnchangedProps,
88
+ } from "./persistable/Persistable.js"
89
+
90
+ // PointVector
91
+ export { PointVector } from "./PointVector.js"
92
+
93
+ // PromiseCache
94
+ export { PromiseCache } from "./PromiseCache.js"
95
+
96
+ // PromiseSwitcher
97
+ export { PromiseSwitcher } from "./PromiseSwitcher.js"
98
+
99
+ // Regions
100
+ export {
101
+ RegionType,
102
+ regions,
103
+ type Region,
104
+ countries,
105
+ listedRegionsNames,
106
+ type Country,
107
+ type IncomeGroup,
108
+ type OwidIncomeGroupName,
109
+ checkIsOwidIncomeGroupName,
110
+ getCountryBySlug,
111
+ getCountryByName,
112
+ getRegionByNameOrVariantName,
113
+ isCountryName,
114
+ getContinents,
115
+ type Continent,
116
+ getAggregates,
117
+ type Aggregate,
118
+ type AggregateSource,
119
+ aggregateSources,
120
+ getOthers,
121
+ countriesByName,
122
+ incomeGroupsByName,
123
+ getRegionAlternativeNames,
124
+ mappableCountries,
125
+ checkIsCountry,
126
+ checkIsOwidContinent,
127
+ checkIsIncomeGroup,
128
+ getIncomeGroups,
129
+ getCountryNamesForRegion,
130
+ checkHasMembers,
131
+ getRegionByName,
132
+ getRegionBySlug,
133
+ getParentRegions,
134
+ getSiblingRegions,
135
+ articulateEntity,
136
+ } from "./regions.js"
137
+
138
+ // Serializers
139
+ export { serializeJSONForHTML, deserializeJSONFromHTML } from "./serializers.js"
140
+
141
+ // String utilities
142
+ export {
143
+ camelCaseProperties,
144
+ titleCase,
145
+ toAsciiQuotes,
146
+ removeDiacritics,
147
+ } from "./string.js"
148
+
149
+ // TimeBounds
150
+ export {
151
+ timeFromTimebounds,
152
+ minTimeBoundFromJSONOrNegativeInfinity,
153
+ maxTimeBoundFromJSONOrPositiveInfinity,
154
+ minTimeToJSON,
155
+ maxTimeToJSON,
156
+ timeBoundToTimeBoundString,
157
+ getTimeDomainFromQueryString,
158
+ } from "./TimeBounds.js"
159
+
160
+ // Tippy tooltip component
161
+ export { Tippy, TippyIfInteractive, LazyTippy } from "./Tippy.js"
162
+
163
+ // URL utilities
164
+ export {
165
+ strToQueryParams,
166
+ queryParamsToStr,
167
+ getWindowQueryStr,
168
+ setWindowQueryStr,
169
+ } from "./urls/UrlUtils.js"
170
+
171
+ export { Url, setWindowUrl, getWindowUrl } from "./urls/Url.js"
172
+
173
+ export { type UrlMigration, performUrlMigrations } from "./urls/UrlMigration.js"
174
+
175
+ // Main utility exports (from Util.ts)
176
+ export {
177
+ type NoUndefinedValues,
178
+ type AllKeysRequired,
179
+ type PartialBy,
180
+ type RequiredBy,
181
+ type PartialRecord,
182
+ createFormatter,
183
+ getRelativeMouse,
184
+ exposeInstanceOnWindow,
185
+ makeSafeForCSS,
186
+ makeIdForHumanConsumption,
187
+ formatDay,
188
+ formatYear,
189
+ numberMagnitude,
190
+ normaliseToSingleDigitNumber,
191
+ roundSigFig,
192
+ excludeNull,
193
+ excludeNullish,
194
+ excludeUndefined,
195
+ firstOfNonEmptyArray,
196
+ lastOfNonEmptyArray,
197
+ next,
198
+ previous,
199
+ domainExtent,
200
+ cagr,
201
+ makeAnnotationsSlug,
202
+ slugify,
203
+ slugifySameCase,
204
+ guid,
205
+ TESTING_ONLY_disable_guid,
206
+ pointsToPath,
207
+ sortedFindClosestIndex,
208
+ sortedFindClosest,
209
+ isMobile,
210
+ isTouchDevice,
211
+ type Json,
212
+ csvEscape,
213
+ trimObject,
214
+ fetchText,
215
+ fetchJson,
216
+ fetchWithTimeout,
217
+ getUserCountryInformation,
218
+ stripHTML,
219
+ getRandomNumberGenerator,
220
+ sampleFrom,
221
+ getIdealGridParams,
222
+ findClosestTimeIndex,
223
+ findClosestTime,
224
+ es6mapValues,
225
+ type DataValue,
226
+ valuesByEntityAtTimes,
227
+ dateDiffInDays,
228
+ diffDateISOStringInDays,
229
+ getYearFromISOStringAndDayOffset,
230
+ parseIntOrUndefined,
231
+ anyToString,
232
+ scrollIntoViewIfNeeded,
233
+ rollingMap,
234
+ keyMap,
235
+ intersectionOfSets,
236
+ differenceOfSets,
237
+ areSetsEqual,
238
+ isSubsetOf,
239
+ intersection,
240
+ sortByUndefinedLast,
241
+ mapNullToUndefined,
242
+ lowerCaseFirstLetterUnlessAbbreviation,
243
+ sortNumeric,
244
+ getClosestTimePairs,
245
+ omitUndefinedValues,
246
+ isInIFrame,
247
+ differenceObj,
248
+ findDOMParent,
249
+ wrapInDiv,
250
+ textAnchorFromAlign,
251
+ dyFromAlign,
252
+ stringifyUnknownError,
253
+ toRectangularMatrix,
254
+ checkIsStringIndexable,
255
+ checkIsTouchEvent,
256
+ triggerDownloadFromBlob,
257
+ triggerDownloadFromUrl,
258
+ removeAllWhitespace,
259
+ moveArrayItemToIndex,
260
+ getIndexableKeys,
261
+ retryPromise,
262
+ fetchWithRetry,
263
+ formatDate,
264
+ canWriteToClipboard,
265
+ isNegativeInfinity,
266
+ isPositiveInfinity,
267
+ imemo,
268
+ isArrayOfNumbers,
269
+ greatestCommonDivisor,
270
+ findGreatestCommonDivisorOfArray,
271
+ copyToClipboard,
272
+ cartesian,
273
+ removeTrailingParenthetical,
274
+ commafyNumber,
275
+ isFiniteWithGuard,
276
+ formatInlineList,
277
+ lazy,
278
+ getParentVariableIdFromChartConfig,
279
+ isArrayDifferentFromReference,
280
+ readFromAssetMap,
281
+ downloadImage,
282
+ getUserNavigatorLanguages,
283
+ getUserNavigatorLanguagesNonEnglish,
284
+ convertDaysSinceEpochToDate,
285
+ sleep,
286
+ lowercaseObjectKeys,
287
+ detailOnDemandRegex,
288
+ guidedChartRegex,
289
+ extractDetailsFromSyntax,
290
+ parseFloatOrUndefined,
291
+ bind,
292
+ merge,
293
+ calculateTrendDirection,
294
+ getDisplayUnit,
295
+ stripOuterParentheses,
296
+ dimensionsToViewId,
297
+ } from "./Util.js"
298
+
299
+ // Archival date utilities
300
+ export {
301
+ type ArchivalTimestamp,
302
+ type DateInput,
303
+ parseArchivalDate,
304
+ formatAsArchivalDate,
305
+ convertToArchivalDateStringIfNecessary,
306
+ getDateForArchival,
307
+ } from "./archival/archivalDate.js"
308
+
309
+ // Multi-dimensional data page config (stub)
310
+ export {
311
+ MultiDimDataPageConfig,
312
+ extractMultiDimChoicesFromSearchParams,
313
+ searchParamsToMultiDimView,
314
+ } from "./MultiDimDataPageConfig.js"
315
+
316
+ // Re-export all types from the types package for convenience
317
+ // This matches the pattern in @ourworldindata/utils
318
+ export * from "../types/index.js"
@@ -0,0 +1,5 @@
1
+ // https://github.com/robertmassaioli/ts-is-present
2
+ // A predicate for filtering an array of nulls and undefineds that returns the correct type
3
+
4
+ export const isPresent = <T>(t: T | undefined | null | void): t is T =>
5
+ t !== undefined && t !== null
@@ -0,0 +1,329 @@
1
+ // @ts-nocheck
2
+ import * as R from "remeda"
3
+ import {
4
+ OwidOrigin,
5
+ OwidVariableWithSource,
6
+ OwidProcessingLevel,
7
+ DisplaySource,
8
+ IndicatorTitleWithFragments,
9
+ OwidSource,
10
+ } from "../types/index.js"
11
+ import * as _ from "lodash-es"
12
+ import { excludeUndefined } from "./Util"
13
+ import dayjs from "./dayjs.js"
14
+ import { parseArchivalDate } from "./archival/archivalDate.js"
15
+
16
+ export function getOriginAttributionFragments(
17
+ origins: OwidOrigin[] | undefined
18
+ ): string[] {
19
+ return origins
20
+ ? origins.map((origin) => {
21
+ const yearPublished = origin.datePublished
22
+ ? dayjs(origin.datePublished, ["YYYY-MM-DD", "YYYY"]).year()
23
+ : undefined
24
+ const yearPublishedString = yearPublished
25
+ ? ` (${yearPublished})`
26
+ : ""
27
+ return (
28
+ origin.attribution ??
29
+ `${origin.producer}${yearPublishedString}`
30
+ )
31
+ })
32
+ : []
33
+ }
34
+
35
+ export const splitSourceTextIntoFragments = (
36
+ text: string | undefined
37
+ ): string[] => {
38
+ return text ? text.split(";").map((fragment) => fragment.trim()) : []
39
+ }
40
+
41
+ export function getAttributionFragmentsFromVariable(
42
+ variable: Pick<
43
+ OwidVariableWithSource,
44
+ "presentation" | "origins" | "source"
45
+ >
46
+ ): string[] {
47
+ if (
48
+ variable.presentation?.attribution &&
49
+ variable.presentation?.attribution !== ""
50
+ )
51
+ return [variable.presentation?.attribution]
52
+
53
+ const originAttributionFragments = getOriginAttributionFragments(
54
+ variable.origins
55
+ )
56
+ const name = variable.source?.name
57
+ return _.uniq(_.compact([name, ...originAttributionFragments]))
58
+ }
59
+
60
+ interface ETLPathComponents {
61
+ channel: string
62
+ producer: string
63
+ version: string
64
+ dataset: string
65
+ table: string
66
+ indicator: string
67
+ }
68
+
69
+ export const getETLPathComponents = (path: string): ETLPathComponents => {
70
+ const [channel, producer, version, dataset, table, indicator] =
71
+ path.split("/")
72
+ return { channel, producer, version, dataset, table, indicator }
73
+ }
74
+
75
+ export function formatAuthors(authors: string[]): string {
76
+ if (authors.length === 0) return ""
77
+ if (authors.length === 1) return authors[0]
78
+ if (authors.length === 2) return authors.join(" and ")
79
+ return authors.slice(0, -1).join(", ") + `, and ${R.last(authors)}`
80
+ }
81
+
82
+ export function formatAuthorsForBibtex(authors: string[]): string {
83
+ return authors.join(" and ")
84
+ }
85
+
86
+ const isDate = (date: string): boolean => {
87
+ const dateRegex = /^\d{4}-\d{2}-\d{2}$/
88
+ return !!date.match(dateRegex)
89
+ }
90
+
91
+ export const getLastUpdatedFromVariable = (
92
+ variable: Pick<OwidVariableWithSource, "catalogPath" | "origins">
93
+ ): string | undefined => {
94
+ // if possible, extract date from the catalog path
95
+ const version = getETLPathComponents(variable.catalogPath ?? "")?.version
96
+ if (version && isDate(version)) return version
97
+
98
+ const { origins = [] } = variable
99
+ const originDates = excludeUndefined(
100
+ origins.map((origin) => origin.dateAccessed)
101
+ )
102
+
103
+ if (originDates.length === 0) return undefined
104
+
105
+ // alternatively, pick the latest dateAccessed from the origins
106
+ const latestDate = new Date(
107
+ Math.max(...originDates.map((date) => new Date(date).getTime()))
108
+ )
109
+ return dayjs(latestDate).format("YYYY-MM-DD")
110
+ }
111
+
112
+ export const getNextUpdateFromVariable = (
113
+ variable: Pick<OwidVariableWithSource, "catalogPath" | "updatePeriodDays">
114
+ ): string | undefined => {
115
+ const lastUpdated = getLastUpdatedFromVariable(variable)
116
+ let nextUpdate = undefined
117
+ if (variable.updatePeriodDays) {
118
+ const date = dayjs(lastUpdated)
119
+ const nextUpdateDate = date.add(variable.updatePeriodDays, "day")
120
+ // If the next update date is in the past, we set it to the next month
121
+ if (nextUpdateDate.isBefore(dayjs()))
122
+ nextUpdate = dayjs().add(1, "month")
123
+ else nextUpdate = nextUpdateDate
124
+ }
125
+ return nextUpdate?.format("YYYY-MM-DD")
126
+ }
127
+
128
+ export const getPhraseForProcessingLevel = (
129
+ processingLevel: OwidProcessingLevel | undefined
130
+ ): string => {
131
+ switch (processingLevel) {
132
+ case "major":
133
+ return "with major processing"
134
+ case "minor":
135
+ return "with minor processing"
136
+ default:
137
+ return "processed"
138
+ }
139
+ }
140
+
141
+ const prepareOriginForDisplay = (origin: OwidOrigin): DisplaySource => {
142
+ let label = origin.producer ?? ""
143
+ if (origin.title && origin.title !== label) {
144
+ label += " – " + origin.title
145
+ }
146
+
147
+ return {
148
+ label,
149
+ description: origin.description,
150
+ retrievedOn: origin.dateAccessed,
151
+ retrievedFrom: origin.urlMain,
152
+ citation: origin.citationFull,
153
+ }
154
+ }
155
+
156
+ export const prepareSourcesForDisplay = (
157
+ variable: Pick<OwidVariableWithSource, "origins" | "source">
158
+ ): DisplaySource[] => {
159
+ const { origins, source } = variable
160
+
161
+ const sourcesForDisplay: DisplaySource[] = []
162
+
163
+ if (
164
+ source?.name &&
165
+ (source?.dataPublishedBy || source?.retrievedDate || source?.link)
166
+ ) {
167
+ sourcesForDisplay.push({
168
+ label: source?.name,
169
+ dataPublishedBy: source?.dataPublishedBy,
170
+ retrievedOn: source?.retrievedDate,
171
+ retrievedFrom: source?.link,
172
+ })
173
+ }
174
+
175
+ if (origins && origins.length > 0) {
176
+ sourcesForDisplay.push(
177
+ ...origins.map((origin) => prepareOriginForDisplay(origin))
178
+ )
179
+ }
180
+
181
+ return sourcesForDisplay
182
+ }
183
+
184
+ const getYearSuffixFromOrigin = (o: OwidOrigin): string => {
185
+ const year = o.dateAccessed
186
+ ? dayjs(o.dateAccessed, ["YYYY-MM-DD", "YYYY"]).year()
187
+ : o.datePublished
188
+ ? dayjs(o.datePublished, ["YYYY-MM-DD", "YYYY"]).year()
189
+ : undefined
190
+ if (year) return ` (${year})`
191
+ else return ""
192
+ }
193
+
194
+ export const getCitationShort = (
195
+ origins: OwidOrigin[],
196
+ attributions: string[],
197
+ owidProcessingLevel: OwidProcessingLevel | undefined
198
+ ): string => {
199
+ const producersWithYear = _.uniq(
200
+ origins.map((o) => `${o.producer}${getYearSuffixFromOrigin(o)}`)
201
+ )
202
+ const processingLevelPhrase =
203
+ getPhraseForProcessingLevel(owidProcessingLevel)
204
+
205
+ const attributionFragments = attributions ?? producersWithYear
206
+ const attributionPotentiallyShortened =
207
+ attributionFragments.length > 3
208
+ ? `${attributionFragments[0]} and other sources`
209
+ : attributionFragments.join("; ")
210
+
211
+ return `${attributionPotentiallyShortened} – ${processingLevelPhrase} by Our World in Data`
212
+ }
213
+
214
+ const getDateForCitation = (date: dayjs.Dayjs): string =>
215
+ date.format("MMMM D, YYYY")
216
+
217
+ export const getPhraseForArchivalDate = (
218
+ archivalDate: string | undefined
219
+ ): string | undefined => {
220
+ if (!archivalDate) return undefined
221
+
222
+ const parsedDate = parseArchivalDate(archivalDate)
223
+ const formatted = getDateForCitation(parsedDate)
224
+ return `(archived on ${formatted}).`
225
+ }
226
+
227
+ export const getCitationLong = (
228
+ indicatorTitle: IndicatorTitleWithFragments,
229
+ origins: OwidOrigin[],
230
+ source: OwidSource | undefined,
231
+ attributions: string[],
232
+ attributionShort: string | undefined,
233
+ titleVariant: string | undefined,
234
+ owidProcessingLevel: OwidProcessingLevel | undefined,
235
+ citationUrl: string | undefined,
236
+ archivalDate: string | undefined
237
+ ): string => {
238
+ const sourceShortName =
239
+ attributionShort && titleVariant
240
+ ? `${attributionShort} – ${titleVariant}`
241
+ : attributionShort || titleVariant
242
+ const producersWithYear = _.uniq(
243
+ origins.map((o) => `${o.producer}${getYearSuffixFromOrigin(o)}`)
244
+ )
245
+ const processingLevelPhrase =
246
+ getPhraseForProcessingLevel(owidProcessingLevel)
247
+
248
+ const attributionFragments = attributions ?? producersWithYear
249
+ const attributionUnshortened = attributionFragments.join("; ")
250
+ const citationLonger = `${attributionUnshortened} – ${processingLevelPhrase} by Our World in Data`
251
+ const titleWithOptionalFragments = excludeUndefined([
252
+ indicatorTitle.title,
253
+ sourceShortName,
254
+ ]).join(" – ")
255
+ const originsLong = _.uniq(
256
+ origins.map(
257
+ (o) =>
258
+ `${o.producer}, “${o.title ?? o.titleSnapshot}${
259
+ o.versionProducer ? " " + o.versionProducer : ""
260
+ }”`
261
+ )
262
+ ).join("; ")
263
+ const today = getDateForCitation(dayjs())
264
+ const archivalString = getPhraseForArchivalDate(archivalDate)
265
+ return excludeUndefined([
266
+ `${citationLonger}.`,
267
+ `“${titleWithOptionalFragments}” [dataset].`,
268
+ originsLong
269
+ ? `${originsLong} [original data].`
270
+ : source?.name
271
+ ? `${source?.name} [original data].`
272
+ : undefined,
273
+ citationUrl
274
+ ? `Retrieved ${today} from ${citationUrl}${archivalString ? ` ${archivalString}` : ""}`
275
+ : undefined,
276
+ ]).join(" ")
277
+ }
278
+
279
+ export const formatSourceDate = (
280
+ date: string | undefined,
281
+ format: string
282
+ ): string | null => {
283
+ const parsedDate = dayjs(date ?? "", ["YYYY-MM-DD", "DD/MM/YYYY"])
284
+ if (!parsedDate.isValid()) return date || null
285
+ return parsedDate.format(format)
286
+ }
287
+
288
+ export const getDateRange = (dateRange: string): string | null => {
289
+ // This regex matches:
290
+ // Beginning of string
291
+ // Ignore whitespace
292
+ // a named group called start that matches:
293
+ // hyphen aka minus
294
+ // 1 or more digits
295
+ // Ignore whitespace
296
+ // hyphen aka minus OR en dash
297
+ // Ignore whitespace
298
+ // a named group called end that matches:
299
+ // hyphen aka minus
300
+ // 1 or more digits
301
+ // Ignore whitespace
302
+ // End of string
303
+ const dateRangeRegex = /^\s*(?<start>(-)?\d+)\s*(-|–)\s*(?<end>(-)?\d+)\s*$/
304
+ const match = dateRange.match(dateRangeRegex)
305
+ if (match) {
306
+ const firstYearString = match.groups?.start
307
+ const lastYearString = match.groups?.end
308
+ if (!firstYearString || !lastYearString) return null
309
+
310
+ const firstYear = parseInt(firstYearString, 10)
311
+ const lastYear = parseInt(lastYearString, 10)
312
+ let formattedFirstYear
313
+
314
+ // if start year is before year 0, add BCE to the end
315
+ if (firstYear < 0) formattedFirstYear = `${Math.abs(firstYear)} BCE`
316
+ else formattedFirstYear = firstYear
317
+
318
+ // if end year is before year 0, add BCE to the end or, if start year is after year 0, add CE to the end
319
+ let formattedLastYear
320
+ if (lastYear < 0) formattedLastYear = `${Math.abs(lastYear)} BCE`
321
+ else if (firstYear < 0) formattedLastYear = `${lastYear} CE`
322
+ else formattedLastYear = lastYear
323
+
324
+ if (lastYear < 0 || firstYear < 0)
325
+ return `${formattedFirstYear} – ${formattedLastYear}`
326
+ else return `${formattedFirstYear}–${formattedLastYear}`
327
+ }
328
+ return null
329
+ }