@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.
- package/LICENSE.md +8 -0
- package/README.md +113 -0
- package/package.json +137 -0
- package/src/components/BodyPortal/BodyPortal.tsx +40 -0
- package/src/components/Button/Button.scss +110 -0
- package/src/components/Button/Button.tsx +101 -0
- package/src/components/Checkbox.scss +93 -0
- package/src/components/Checkbox.tsx +47 -0
- package/src/components/ExpandableToggle/ExpandableToggle.scss +123 -0
- package/src/components/ExpandableToggle/ExpandableToggle.tsx +60 -0
- package/src/components/GrapherTabIcon.tsx +156 -0
- package/src/components/GrapherTrendArrow.scss +16 -0
- package/src/components/GrapherTrendArrow.tsx +30 -0
- package/src/components/Halo/Halo.tsx +44 -0
- package/src/components/LabeledSwitch/LabeledSwitch.scss +109 -0
- package/src/components/LabeledSwitch/LabeledSwitch.tsx +62 -0
- package/src/components/MarkdownTextWrap/MarkdownTextWrap.tsx +1173 -0
- package/src/components/OverlayHeader.scss +18 -0
- package/src/components/OverlayHeader.tsx +29 -0
- package/src/components/RadioButton.scss +69 -0
- package/src/components/RadioButton.tsx +42 -0
- package/src/components/SimpleMarkdownText.tsx +89 -0
- package/src/components/TextInput.scss +17 -0
- package/src/components/TextInput.tsx +19 -0
- package/src/components/TextWrap/TextWrap.tsx +361 -0
- package/src/components/TextWrap/TextWrapUtils.ts +32 -0
- package/src/components/closeButton/CloseButton.scss +40 -0
- package/src/components/closeButton/CloseButton.tsx +27 -0
- package/src/components/index.ts +70 -0
- package/src/components/loadingIndicator/LoadingIndicator.scss +40 -0
- package/src/components/loadingIndicator/LoadingIndicator.tsx +28 -0
- package/src/components/markdown/remarkPlainLinks.ts +36 -0
- package/src/components/reactUtil.ts +20 -0
- package/src/components/stubs/CodeSnippet.tsx +19 -0
- package/src/components/stubs/DataCitation.tsx +16 -0
- package/src/components/stubs/IndicatorKeyData.tsx +45 -0
- package/src/components/stubs/IndicatorProcessing.tsx +15 -0
- package/src/components/stubs/IndicatorSources.tsx +15 -0
- package/src/components/styles/colors.scss +113 -0
- package/src/components/styles/mixins.scss +630 -0
- package/src/components/styles/typography.scss +579 -0
- package/src/components/styles/util.scss +89 -0
- package/src/components/styles/variables.scss +208 -0
- package/src/config/ChartsConfig.ts +163 -0
- package/src/config/ChartsProvider.tsx +157 -0
- package/src/config/index.ts +20 -0
- package/src/core-table/CoreTable.ts +1355 -0
- package/src/core-table/CoreTableColumns.ts +973 -0
- package/src/core-table/CoreTableUtils.ts +793 -0
- package/src/core-table/ErrorValues.ts +73 -0
- package/src/core-table/OwidTable.ts +1175 -0
- package/src/core-table/OwidTableSynthesizers.ts +272 -0
- package/src/core-table/OwidTableUtil.ts +76 -0
- package/src/core-table/Transforms.ts +484 -0
- package/src/core-table/index.ts +82 -0
- package/src/explorer/ColumnGrammar.ts +217 -0
- package/src/explorer/Explorer.sample.ts +212 -0
- package/src/explorer/Explorer.scss +148 -0
- package/src/explorer/Explorer.tsx +1283 -0
- package/src/explorer/ExplorerConstants.ts +85 -0
- package/src/explorer/ExplorerControls.scss +156 -0
- package/src/explorer/ExplorerControls.tsx +210 -0
- package/src/explorer/ExplorerDecisionMatrix.ts +471 -0
- package/src/explorer/ExplorerGrammar.ts +161 -0
- package/src/explorer/ExplorerProgram.ts +568 -0
- package/src/explorer/ExplorerUtils.ts +59 -0
- package/src/explorer/GrapherGrammar.ts +387 -0
- package/src/explorer/gridLang/GrammarUtils.ts +121 -0
- package/src/explorer/gridLang/GridCell.ts +298 -0
- package/src/explorer/gridLang/GridLangConstants.ts +255 -0
- package/src/explorer/gridLang/GridProgram.ts +311 -0
- package/src/explorer/gridLang/readme.md +17 -0
- package/src/explorer/index.ts +69 -0
- package/src/explorer/readme.md +19 -0
- package/src/explorer/urlMigrations/CO2UrlMigration.ts +46 -0
- package/src/explorer/urlMigrations/CovidUrlMigration.ts +37 -0
- package/src/explorer/urlMigrations/EnergyUrlMigration.ts +41 -0
- package/src/explorer/urlMigrations/ExplorerPageUrlMigrationSpec.ts +12 -0
- package/src/explorer/urlMigrations/ExplorerUrlMigrationUtils.ts +45 -0
- package/src/explorer/urlMigrations/ExplorerUrlMigrations.ts +33 -0
- package/src/explorer/urlMigrations/LegacyCovidUrlMigration.ts +144 -0
- package/src/explorer/urlMigrations/readme.md +39 -0
- package/src/grapher/axis/Axis.ts +973 -0
- package/src/grapher/axis/AxisConfig.ts +179 -0
- package/src/grapher/axis/AxisViews.tsx +597 -0
- package/src/grapher/barCharts/DiscreteBarChart.tsx +728 -0
- package/src/grapher/barCharts/DiscreteBarChartConstants.ts +60 -0
- package/src/grapher/barCharts/DiscreteBarChartHelpers.ts +338 -0
- package/src/grapher/barCharts/DiscreteBarChartState.ts +354 -0
- package/src/grapher/barCharts/DiscreteBarChartThumbnail.tsx +34 -0
- package/src/grapher/captionedChart/CaptionedChart.scss +61 -0
- package/src/grapher/captionedChart/CaptionedChart.tsx +523 -0
- package/src/grapher/captionedChart/Logos.tsx +141 -0
- package/src/grapher/captionedChart/LogosSVG.tsx +16 -0
- package/src/grapher/captionedChart/StaticChartRasterizer.tsx +178 -0
- package/src/grapher/captionedChart/assets/buildcanada-logo-square.svg +15 -0
- package/src/grapher/captionedChart/assets/buildcanada-logo.svg +15 -0
- package/src/grapher/captionedChart/assets/canadaspends.svg +7 -0
- package/src/grapher/captionedChart/readme.md +14 -0
- package/src/grapher/chart/Chart.tsx +62 -0
- package/src/grapher/chart/ChartAreaContent.tsx +172 -0
- package/src/grapher/chart/ChartDimension.ts +121 -0
- package/src/grapher/chart/ChartInterface.ts +83 -0
- package/src/grapher/chart/ChartManager.ts +113 -0
- package/src/grapher/chart/ChartTabs.ts +178 -0
- package/src/grapher/chart/ChartTypeMap.tsx +158 -0
- package/src/grapher/chart/ChartTypeSwitcher.tsx +26 -0
- package/src/grapher/chart/ChartUtils.tsx +364 -0
- package/src/grapher/chart/DimensionSlot.ts +45 -0
- package/src/grapher/chart/StaticChartWrapper.tsx +94 -0
- package/src/grapher/chart/guidedChartUtils.ts +82 -0
- package/src/grapher/color/BinningStrategies.ts +484 -0
- package/src/grapher/color/BinningStrategyEqualSizeBins.ts +132 -0
- package/src/grapher/color/BinningStrategyLogarithmic.ts +121 -0
- package/src/grapher/color/CategoricalColorAssigner.ts +97 -0
- package/src/grapher/color/ColorBrewerSchemes.ts +80 -0
- package/src/grapher/color/ColorConstants.ts +20 -0
- package/src/grapher/color/ColorScale.ts +339 -0
- package/src/grapher/color/ColorScaleBin.ts +147 -0
- package/src/grapher/color/ColorScaleConfig.ts +204 -0
- package/src/grapher/color/ColorScheme.ts +137 -0
- package/src/grapher/color/ColorSchemes.ts +149 -0
- package/src/grapher/color/ColorUtils.ts +86 -0
- package/src/grapher/color/CustomSchemes.ts +1772 -0
- package/src/grapher/color/readme.md +84 -0
- package/src/grapher/comparisonLine/ComparisonLine.tsx +31 -0
- package/src/grapher/comparisonLine/ComparisonLineConstants.ts +11 -0
- package/src/grapher/comparisonLine/ComparisonLineGenerator.ts +60 -0
- package/src/grapher/comparisonLine/ComparisonLineHelpers.ts +10 -0
- package/src/grapher/comparisonLine/CustomComparisonLine.tsx +159 -0
- package/src/grapher/comparisonLine/VerticalComparisonLine.tsx +208 -0
- package/src/grapher/controls/ActionButtons.scss +97 -0
- package/src/grapher/controls/ActionButtons.tsx +453 -0
- package/src/grapher/controls/CommandPalette.scss +50 -0
- package/src/grapher/controls/CommandPalette.tsx +74 -0
- package/src/grapher/controls/ContentSwitchers.scss +93 -0
- package/src/grapher/controls/ContentSwitchers.tsx +238 -0
- package/src/grapher/controls/Controls.scss +158 -0
- package/src/grapher/controls/DataTableFilterDropdown.scss +7 -0
- package/src/grapher/controls/DataTableFilterDropdown.tsx +168 -0
- package/src/grapher/controls/DataTableSearchField.scss +3 -0
- package/src/grapher/controls/DataTableSearchField.tsx +76 -0
- package/src/grapher/controls/Dropdown.scss +252 -0
- package/src/grapher/controls/Dropdown.tsx +235 -0
- package/src/grapher/controls/EntitySelectionToggle.tsx +135 -0
- package/src/grapher/controls/MapRegionDropdown.scss +3 -0
- package/src/grapher/controls/MapRegionDropdown.tsx +104 -0
- package/src/grapher/controls/MapResetButton.tsx +115 -0
- package/src/grapher/controls/MapZoomDropdown.scss +9 -0
- package/src/grapher/controls/MapZoomDropdown.tsx +270 -0
- package/src/grapher/controls/MapZoomToSelectionButton.tsx +87 -0
- package/src/grapher/controls/SearchField.scss +78 -0
- package/src/grapher/controls/SearchField.tsx +63 -0
- package/src/grapher/controls/SettingsMenu.scss +191 -0
- package/src/grapher/controls/SettingsMenu.tsx +399 -0
- package/src/grapher/controls/ShareMenu.scss +58 -0
- package/src/grapher/controls/ShareMenu.tsx +304 -0
- package/src/grapher/controls/SortIcon.tsx +39 -0
- package/src/grapher/controls/VerticalScrollContainer.tsx +263 -0
- package/src/grapher/controls/controlsRow/ControlsRow.tsx +168 -0
- package/src/grapher/controls/dropdown-icons.scss +4 -0
- package/src/grapher/controls/entityPicker/EntityPicker.scss +255 -0
- package/src/grapher/controls/entityPicker/EntityPicker.tsx +816 -0
- package/src/grapher/controls/entityPicker/EntityPickerConstants.ts +23 -0
- package/src/grapher/controls/globalEntitySelector/GlobalEntitySelector.scss +129 -0
- package/src/grapher/controls/globalEntitySelector/GlobalEntitySelector.tsx +463 -0
- package/src/grapher/controls/globalEntitySelector/GlobalEntitySelectorConstants.ts +3 -0
- package/src/grapher/controls/globalEntitySelector/readme.md +17 -0
- package/src/grapher/controls/settings/AbsRelToggle.tsx +64 -0
- package/src/grapher/controls/settings/AxisScaleToggle.tsx +53 -0
- package/src/grapher/controls/settings/FacetStrategySelector.tsx +110 -0
- package/src/grapher/controls/settings/FacetYDomainToggle.tsx +51 -0
- package/src/grapher/controls/settings/NoDataAreaToggle.tsx +38 -0
- package/src/grapher/controls/settings/ZoomToggle.tsx +36 -0
- package/src/grapher/core/EntitiesByRegionType.ts +174 -0
- package/src/grapher/core/EntityCodes.ts +19 -0
- package/src/grapher/core/EntityUrlBuilder.ts +200 -0
- package/src/grapher/core/FetchingGrapher.tsx +156 -0
- package/src/grapher/core/Grapher.tsx +760 -0
- package/src/grapher/core/GrapherAnalytics.ts +229 -0
- package/src/grapher/core/GrapherConstants.ts +173 -0
- package/src/grapher/core/GrapherState.tsx +3659 -0
- package/src/grapher/core/GrapherUrl.ts +184 -0
- package/src/grapher/core/GrapherUrlMigrations.ts +29 -0
- package/src/grapher/core/GrapherUseHelpers.tsx +147 -0
- package/src/grapher/core/LegacyToOwidTable.ts +841 -0
- package/src/grapher/core/grapher.entry.ts +5 -0
- package/src/grapher/core/grapher.scss +257 -0
- package/src/grapher/core/loadGrapherTableHelpers.ts +116 -0
- package/src/grapher/core/loadVariable.ts +104 -0
- package/src/grapher/core/relatedQuestion.ts +12 -0
- package/src/grapher/core/typography.scss +206 -0
- package/src/grapher/dataTable/DataTable.sample.ts +206 -0
- package/src/grapher/dataTable/DataTable.scss +249 -0
- package/src/grapher/dataTable/DataTable.tsx +1332 -0
- package/src/grapher/dataTable/DataTableConstants.ts +186 -0
- package/src/grapher/entitySelector/EntitySelector.scss +255 -0
- package/src/grapher/entitySelector/EntitySelector.tsx +1838 -0
- package/src/grapher/facet/FacetChart.tsx +943 -0
- package/src/grapher/facet/FacetChartConstants.ts +24 -0
- package/src/grapher/facet/FacetChartUtils.ts +51 -0
- package/src/grapher/facet/FacetMap.tsx +604 -0
- package/src/grapher/facet/FacetMapConstants.ts +23 -0
- package/src/grapher/facet/readme.md +13 -0
- package/src/grapher/focus/FocusArray.ts +79 -0
- package/src/grapher/footer/Footer.scss +63 -0
- package/src/grapher/footer/Footer.tsx +809 -0
- package/src/grapher/footer/FooterManager.ts +44 -0
- package/src/grapher/fullScreen/FullScreen.scss +11 -0
- package/src/grapher/fullScreen/FullScreen.tsx +61 -0
- package/src/grapher/header/Header.scss +35 -0
- package/src/grapher/header/Header.tsx +372 -0
- package/src/grapher/header/HeaderManager.ts +28 -0
- package/src/grapher/index.ts +157 -0
- package/src/grapher/interaction/InteractionState.ts +60 -0
- package/src/grapher/legend/HorizontalColorLegends.tsx +923 -0
- package/src/grapher/legend/LegendInteractionState.ts +40 -0
- package/src/grapher/legend/VerticalColorLegend.tsx +295 -0
- package/src/grapher/lineCharts/LineChart.tsx +968 -0
- package/src/grapher/lineCharts/LineChartConstants.ts +89 -0
- package/src/grapher/lineCharts/LineChartHelpers.ts +184 -0
- package/src/grapher/lineCharts/LineChartState.ts +394 -0
- package/src/grapher/lineCharts/LineChartThumbnail.tsx +437 -0
- package/src/grapher/lineCharts/Lines.tsx +258 -0
- package/src/grapher/lineLegend/LineLegend.tsx +723 -0
- package/src/grapher/lineLegend/LineLegendConstants.ts +9 -0
- package/src/grapher/lineLegend/LineLegendFilterAlgorithms.ts +143 -0
- package/src/grapher/lineLegend/LineLegendHelpers.ts +253 -0
- package/src/grapher/lineLegend/LineLegendTypes.ts +32 -0
- package/src/grapher/mapCharts/CanadaTopology.ts +17922 -0
- package/src/grapher/mapCharts/ChoroplethGlobe.tsx +949 -0
- package/src/grapher/mapCharts/ChoroplethMap.tsx +662 -0
- package/src/grapher/mapCharts/GeoFeatures.ts +184 -0
- package/src/grapher/mapCharts/GlobeController.ts +496 -0
- package/src/grapher/mapCharts/MapAnnotationPlacements.json +1040 -0
- package/src/grapher/mapCharts/MapAnnotationPlacements.ts +31 -0
- package/src/grapher/mapCharts/MapAnnotations.ts +723 -0
- package/src/grapher/mapCharts/MapChart.sample.ts +59 -0
- package/src/grapher/mapCharts/MapChart.scss +5 -0
- package/src/grapher/mapCharts/MapChart.tsx +720 -0
- package/src/grapher/mapCharts/MapChartConstants.ts +260 -0
- package/src/grapher/mapCharts/MapChartState.ts +416 -0
- package/src/grapher/mapCharts/MapChartThumbnail.tsx +25 -0
- package/src/grapher/mapCharts/MapComponents.tsx +338 -0
- package/src/grapher/mapCharts/MapConfig.ts +156 -0
- package/src/grapher/mapCharts/MapHelpers.ts +181 -0
- package/src/grapher/mapCharts/MapProjections.ts +49 -0
- package/src/grapher/mapCharts/MapSparkline.tsx +257 -0
- package/src/grapher/mapCharts/MapTooltip.scss +49 -0
- package/src/grapher/mapCharts/MapTooltip.tsx +409 -0
- package/src/grapher/mapCharts/MapTopology.ts +1766 -0
- package/src/grapher/mapCharts/d3-bboxCollide.js +204 -0
- package/src/grapher/mapCharts/d3-geo-projection.ts +198 -0
- package/src/grapher/modal/DownloadIcons.tsx +39 -0
- package/src/grapher/modal/DownloadModal.scss +300 -0
- package/src/grapher/modal/DownloadModal.tsx +1226 -0
- package/src/grapher/modal/EmbedModal.scss +40 -0
- package/src/grapher/modal/EmbedModal.tsx +160 -0
- package/src/grapher/modal/EntitySelectorModal.tsx +59 -0
- package/src/grapher/modal/Modal.scss +31 -0
- package/src/grapher/modal/Modal.tsx +90 -0
- package/src/grapher/modal/ModalHeader.scss +12 -0
- package/src/grapher/modal/ModalHeader.tsx +16 -0
- package/src/grapher/modal/SourcesDescriptions.scss +87 -0
- package/src/grapher/modal/SourcesDescriptions.tsx +89 -0
- package/src/grapher/modal/SourcesKeyDataTable.scss +49 -0
- package/src/grapher/modal/SourcesKeyDataTable.tsx +87 -0
- package/src/grapher/modal/SourcesModal.scss +301 -0
- package/src/grapher/modal/SourcesModal.tsx +568 -0
- package/src/grapher/noDataModal/NoDataModal.tsx +125 -0
- package/src/grapher/scatterCharts/ConnectedScatterLegend.tsx +143 -0
- package/src/grapher/scatterCharts/MultiColorPolyline.tsx +129 -0
- package/src/grapher/scatterCharts/NoDataSection.scss +14 -0
- package/src/grapher/scatterCharts/NoDataSection.tsx +56 -0
- package/src/grapher/scatterCharts/ScatterPlotChart.tsx +792 -0
- package/src/grapher/scatterCharts/ScatterPlotChartConstants.ts +157 -0
- package/src/grapher/scatterCharts/ScatterPlotChartState.ts +678 -0
- package/src/grapher/scatterCharts/ScatterPlotChartThumbnail.tsx +155 -0
- package/src/grapher/scatterCharts/ScatterPlotTooltip.tsx +560 -0
- package/src/grapher/scatterCharts/ScatterPoints.tsx +153 -0
- package/src/grapher/scatterCharts/ScatterPointsWithLabels.tsx +708 -0
- package/src/grapher/scatterCharts/ScatterSizeLegend.tsx +327 -0
- package/src/grapher/scatterCharts/ScatterUtils.ts +265 -0
- package/src/grapher/scatterCharts/Triangle.tsx +41 -0
- package/src/grapher/schema/README.md +33 -0
- package/src/grapher/schema/defaultGrapherConfig.ts +100 -0
- package/src/grapher/schema/grapher-schema.009.yaml +781 -0
- package/src/grapher/schema/migrations/helpers.ts +58 -0
- package/src/grapher/schema/migrations/migrate.ts +75 -0
- package/src/grapher/schema/migrations/migrations.ts +158 -0
- package/src/grapher/selection/MapSelectionArray.ts +99 -0
- package/src/grapher/selection/SelectionArray.ts +71 -0
- package/src/grapher/selection/readme.md +16 -0
- package/src/grapher/sidePanel/SidePanel.scss +10 -0
- package/src/grapher/sidePanel/SidePanel.tsx +23 -0
- package/src/grapher/slideInDrawer/SlideInDrawer.scss +57 -0
- package/src/grapher/slideInDrawer/SlideInDrawer.tsx +125 -0
- package/src/grapher/slideshowController/SlideShowController.tsx +43 -0
- package/src/grapher/slideshowController/readme.md +7 -0
- package/src/grapher/slopeCharts/MarkX.tsx +45 -0
- package/src/grapher/slopeCharts/Slope.tsx +102 -0
- package/src/grapher/slopeCharts/SlopeChart.tsx +1152 -0
- package/src/grapher/slopeCharts/SlopeChartConstants.ts +33 -0
- package/src/grapher/slopeCharts/SlopeChartHelpers.ts +73 -0
- package/src/grapher/slopeCharts/SlopeChartState.ts +392 -0
- package/src/grapher/slopeCharts/SlopeChartThumbnail.tsx +368 -0
- package/src/grapher/stackedCharts/AbstractStackedChartState.ts +370 -0
- package/src/grapher/stackedCharts/MarimekkoBars.tsx +190 -0
- package/src/grapher/stackedCharts/MarimekkoBarsForOneEntity.tsx +168 -0
- package/src/grapher/stackedCharts/MarimekkoChart.tsx +1144 -0
- package/src/grapher/stackedCharts/MarimekkoChartConstants.ts +112 -0
- package/src/grapher/stackedCharts/MarimekkoChartHelpers.ts +21 -0
- package/src/grapher/stackedCharts/MarimekkoChartState.ts +465 -0
- package/src/grapher/stackedCharts/MarimekkoChartThumbnail.tsx +168 -0
- package/src/grapher/stackedCharts/MarimekkoInternalLabels.tsx +124 -0
- package/src/grapher/stackedCharts/StackedAreaChart.tsx +678 -0
- package/src/grapher/stackedCharts/StackedAreaChartState.ts +34 -0
- package/src/grapher/stackedCharts/StackedAreaChartThumbnail.tsx +215 -0
- package/src/grapher/stackedCharts/StackedAreas.tsx +223 -0
- package/src/grapher/stackedCharts/StackedBarChart.tsx +619 -0
- package/src/grapher/stackedCharts/StackedBarChartState.ts +80 -0
- package/src/grapher/stackedCharts/StackedBarChartThumbnail.tsx +220 -0
- package/src/grapher/stackedCharts/StackedBarSegment.tsx +87 -0
- package/src/grapher/stackedCharts/StackedBars.tsx +102 -0
- package/src/grapher/stackedCharts/StackedConstants.ts +109 -0
- package/src/grapher/stackedCharts/StackedDiscreteBarChart.tsx +270 -0
- package/src/grapher/stackedCharts/StackedDiscreteBarChartState.ts +296 -0
- package/src/grapher/stackedCharts/StackedDiscreteBarChartThumbnail.tsx +27 -0
- package/src/grapher/stackedCharts/StackedDiscreteBars.tsx +648 -0
- package/src/grapher/stackedCharts/StackedUtils.ts +142 -0
- package/src/grapher/tabs/Tabs.scss +169 -0
- package/src/grapher/tabs/Tabs.tsx +54 -0
- package/src/grapher/tabs/TabsWithDropdown.scss +62 -0
- package/src/grapher/tabs/TabsWithDropdown.tsx +114 -0
- package/src/grapher/testData/OwidTestData.sample.ts +273 -0
- package/src/grapher/testData/OwidTestData.ts +64 -0
- package/src/grapher/timeline/TimelineComponent.scss +139 -0
- package/src/grapher/timeline/TimelineComponent.tsx +658 -0
- package/src/grapher/timeline/TimelineController.ts +368 -0
- package/src/grapher/timeline/readme.md +7 -0
- package/src/grapher/tooltip/Tooltip.scss +510 -0
- package/src/grapher/tooltip/Tooltip.tsx +294 -0
- package/src/grapher/tooltip/TooltipContents.tsx +383 -0
- package/src/grapher/tooltip/TooltipProps.ts +123 -0
- package/src/grapher/tooltip/TooltipState.ts +81 -0
- package/src/grapher/verticalLabels/VerticalLabels.tsx +31 -0
- package/src/grapher/verticalLabels/VerticalLabelsState.ts +154 -0
- package/src/index.ts +226 -0
- package/src/styles/charts.scss +15 -0
- package/src/types/NominalType.ts +30 -0
- package/src/types/OwidOrigin.ts +18 -0
- package/src/types/OwidSource.ts +9 -0
- package/src/types/OwidVariable.ts +133 -0
- package/src/types/OwidVariableDisplayConfigInterface.ts +49 -0
- package/src/types/analyticsTypes.ts +54 -0
- package/src/types/dbTypes/Tags.ts +11 -0
- package/src/types/domainTypes/Archive.ts +139 -0
- package/src/types/domainTypes/Author.ts +28 -0
- package/src/types/domainTypes/ContentGraph.ts +76 -0
- package/src/types/domainTypes/CoreTableTypes.ts +305 -0
- package/src/types/domainTypes/DeployStatus.ts +23 -0
- package/src/types/domainTypes/Layout.ts +34 -0
- package/src/types/domainTypes/Posts.ts +34 -0
- package/src/types/domainTypes/Search.ts +299 -0
- package/src/types/domainTypes/Site.ts +8 -0
- package/src/types/domainTypes/StaticViz.ts +64 -0
- package/src/types/domainTypes/Toc.ts +11 -0
- package/src/types/domainTypes/Tombstone.ts +19 -0
- package/src/types/domainTypes/Various.ts +79 -0
- package/src/types/gdocTypes/Gdoc.ts +280 -0
- package/src/types/grapherTypes/BinningStrategyTypes.ts +46 -0
- package/src/types/grapherTypes/GrapherConstants.ts +53 -0
- package/src/types/grapherTypes/GrapherTypes.ts +743 -0
- package/src/types/index.ts +316 -0
- package/src/types/wordpressTypes/WordpressTypes.ts +9 -0
- package/src/utils/Bounds.ts +439 -0
- package/src/utils/BrowserUtils.ts +12 -0
- package/src/utils/FuzzySearch.ts +74 -0
- package/src/utils/MultiDimDataPageConfig.ts +31 -0
- package/src/utils/OwidVariable.ts +82 -0
- package/src/utils/PointVector.ts +97 -0
- package/src/utils/PromiseCache.ts +36 -0
- package/src/utils/PromiseSwitcher.ts +52 -0
- package/src/utils/TimeBounds.ts +130 -0
- package/src/utils/Tippy.tsx +57 -0
- package/src/utils/Util.ts +2369 -0
- package/src/utils/archival/archivalDate.ts +48 -0
- package/src/utils/dayjs.ts +32 -0
- package/src/utils/formatValue.ts +242 -0
- package/src/utils/grapherConfigUtils.ts +81 -0
- package/src/utils/image.ts +225 -0
- package/src/utils/index.ts +318 -0
- package/src/utils/isPresent.ts +5 -0
- package/src/utils/metadataHelpers.ts +329 -0
- package/src/utils/persistable/Persistable.ts +82 -0
- package/src/utils/persistable/readme.md +50 -0
- package/src/utils/regions.json +5635 -0
- package/src/utils/regions.ts +463 -0
- package/src/utils/serializers.ts +16 -0
- package/src/utils/string.ts +42 -0
- package/src/utils/urls/Url.ts +195 -0
- package/src/utils/urls/UrlMigration.ts +10 -0
- package/src/utils/urls/UrlUtils.ts +54 -0
- package/src/utils/urls/readme.md +90 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { ColorScaleBin } from "../color/ColorScaleBin"
|
|
2
|
+
import { Bounds, ColumnSlug } from "../../utils/index.js"
|
|
3
|
+
import {
|
|
4
|
+
MapRegionName,
|
|
5
|
+
SeriesName,
|
|
6
|
+
GlobeRegionName,
|
|
7
|
+
ProjectionColumnInfo,
|
|
8
|
+
type GrapherInteractionEvent,
|
|
9
|
+
Time,
|
|
10
|
+
} from "../../types/index.js"
|
|
11
|
+
import { ChartManager } from "../chart/ChartManager"
|
|
12
|
+
import { MapConfig } from "./MapConfig"
|
|
13
|
+
import { ChartSeries } from "../chart/ChartInterface"
|
|
14
|
+
import { GlobeController } from "./GlobeController"
|
|
15
|
+
import { MapSelectionArray } from "../selection/MapSelectionArray.js"
|
|
16
|
+
import { CoreColumn } from "../../core-table/index.js"
|
|
17
|
+
import * as R from "remeda"
|
|
18
|
+
import { InteractionState } from "../interaction/InteractionState"
|
|
19
|
+
|
|
20
|
+
export declare type SVGMouseEvent = React.MouseEvent<SVGElement>
|
|
21
|
+
|
|
22
|
+
export type GeoFeature = GeoJSON.Feature<GeoJSON.GeometryObject>
|
|
23
|
+
export type MapBracket = ColorScaleBin
|
|
24
|
+
|
|
25
|
+
export const MAP_HOVER_TARGET_RANGE = 20
|
|
26
|
+
|
|
27
|
+
export const DEFAULT_STROKE_COLOR = "#333"
|
|
28
|
+
export const HOVER_STROKE_COLOR = "#111"
|
|
29
|
+
|
|
30
|
+
export const DEFAULT_STROKE_WIDTH = 0.3
|
|
31
|
+
export const HOVER_STROKE_WIDTH = 1.5
|
|
32
|
+
export const SELECTED_STROKE_WIDTH = 1
|
|
33
|
+
export const PATTERN_STROKE_WIDTH = 0.7
|
|
34
|
+
|
|
35
|
+
export const BLUR_FILL_OPACITY = 0.2
|
|
36
|
+
export const BLUR_STROKE_OPACITY = 0.5
|
|
37
|
+
|
|
38
|
+
export const PROJECTED_DATA_LEGEND_COLOR = "#ffffff"
|
|
39
|
+
|
|
40
|
+
export const MAP_CHART_CLASSNAME = "MapChart"
|
|
41
|
+
export const CHOROPLETH_MAP_CLASSNAME = "ChoroplethMap"
|
|
42
|
+
export const GEO_FEATURES_CLASSNAME = "GeoFeatures"
|
|
43
|
+
|
|
44
|
+
export const DEFAULT_GLOBE_ZOOM = 1
|
|
45
|
+
export const GLOBE_MIN_ZOOM = 1
|
|
46
|
+
export const GLOBE_MAX_ZOOM = 5
|
|
47
|
+
export const GLOBE_COUNTRY_ZOOM = 2.5
|
|
48
|
+
|
|
49
|
+
export const GLOBE_LATITUDE_MIN = -65
|
|
50
|
+
export const GLOBE_LATITUDE_MAX = 65
|
|
51
|
+
|
|
52
|
+
export const DEFAULT_GLOBE_SIZE = 500 // defined by d3
|
|
53
|
+
export const DEFAULT_GLOBE_ROTATION: [number, number] = [-30, 20] // Atlantic ocean (i.e. Americas & Europe)
|
|
54
|
+
export const DEFAULT_GLOBE_ROTATIONS_FOR_TIME: Record<
|
|
55
|
+
"UTC_MORNING" | "UTC_MIDDAY" | "UTC_EVENING",
|
|
56
|
+
[number, number]
|
|
57
|
+
> = {
|
|
58
|
+
UTC_MORNING: [110, 15], // Asia & Oceania
|
|
59
|
+
UTC_MIDDAY: [20, 20], // Europe & Africa
|
|
60
|
+
UTC_EVENING: [-90, 15], // North & South America
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const ANNOTATION_COLOR_DARK = HOVER_STROKE_COLOR
|
|
64
|
+
export const ANNOTATION_COLOR_LIGHT = "#fff"
|
|
65
|
+
|
|
66
|
+
export const ANNOTATION_FONT_SIZE_INTERNAL_DEFAULT = 11
|
|
67
|
+
export const ANNOTATION_FONT_SIZE_INTERNAL_MIN = 7
|
|
68
|
+
export const ANNOTATION_FONT_SIZE_EXTERNAL_DEFAULT = 8
|
|
69
|
+
export const ANNOTATION_FONT_SIZE_EXTERNAL_MAX = 11
|
|
70
|
+
|
|
71
|
+
export const ANNOTATION_MARKER_LINE_LENGTH_DEFAULT = 6
|
|
72
|
+
export const ANNOTATION_MARKER_LINE_LENGTH_MAX = 10
|
|
73
|
+
|
|
74
|
+
export const MAP_REGION_LABELS: Record<MapRegionName, string> = {
|
|
75
|
+
World: "World",
|
|
76
|
+
Africa: "Africa",
|
|
77
|
+
NorthAmerica: "North America",
|
|
78
|
+
SouthAmerica: "South America",
|
|
79
|
+
Asia: "Asia",
|
|
80
|
+
Europe: "Europe",
|
|
81
|
+
Oceania: "Oceania",
|
|
82
|
+
Canada: "Canada",
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const MAP_REGION_NAMES = R.invert(MAP_REGION_LABELS)
|
|
86
|
+
|
|
87
|
+
export interface ChoroplethSeries extends ChartSeries {
|
|
88
|
+
value: number | string
|
|
89
|
+
time: number
|
|
90
|
+
isProjection?: boolean
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type ChoroplethSeriesByName = Map<SeriesName, ChoroplethSeries>
|
|
94
|
+
|
|
95
|
+
export interface ChoroplethMapManager {
|
|
96
|
+
choroplethData: ChoroplethSeriesByName
|
|
97
|
+
choroplethMapBounds: Bounds
|
|
98
|
+
mapConfig: MapConfig
|
|
99
|
+
mapColumn: CoreColumn
|
|
100
|
+
globeController?: GlobeController
|
|
101
|
+
selectionArray?: MapSelectionArray
|
|
102
|
+
fontSize?: number
|
|
103
|
+
getHoverState?: (featureId: string) => InteractionState
|
|
104
|
+
isSelected?: (featureId: string) => boolean
|
|
105
|
+
onMapMouseOver?: (d: GeoFeature) => void
|
|
106
|
+
onMapMouseLeave?: () => void
|
|
107
|
+
isMapSelectionEnabled?: boolean
|
|
108
|
+
isStatic?: boolean
|
|
109
|
+
binColors?: string[]
|
|
110
|
+
hasProjectedData?: boolean
|
|
111
|
+
mapViewport?: MapViewport
|
|
112
|
+
isFaceted?: boolean
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export enum RenderFeatureType {
|
|
116
|
+
Map = "map",
|
|
117
|
+
Globe = "globe",
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface RenderFeature {
|
|
121
|
+
type: RenderFeatureType
|
|
122
|
+
id: string
|
|
123
|
+
geo: GeoFeature
|
|
124
|
+
geoCentroid: [number, number] // unprojected
|
|
125
|
+
geoBounds: Bounds // unprojected
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface MapRenderFeature extends RenderFeature {
|
|
129
|
+
type: RenderFeatureType.Map
|
|
130
|
+
path: string
|
|
131
|
+
projBounds: Bounds
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface GlobeRenderFeature extends RenderFeature {
|
|
135
|
+
type: RenderFeatureType.Globe
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface MapChartManager extends ChartManager {
|
|
139
|
+
mapColumnSlug?: ColumnSlug
|
|
140
|
+
mapConfig?: MapConfig
|
|
141
|
+
targetTime?: Time
|
|
142
|
+
globeController?: GlobeController
|
|
143
|
+
isMapSelectionEnabled?: boolean
|
|
144
|
+
highlightedTimesInTooltip?: [Time, Time]
|
|
145
|
+
mapViewport?: MapViewport
|
|
146
|
+
isFaceted?: boolean
|
|
147
|
+
logGrapherInteractionEvent?: (
|
|
148
|
+
action: GrapherInteractionEvent,
|
|
149
|
+
target?: string
|
|
150
|
+
) => void
|
|
151
|
+
projectionColumnInfoBySlug?: Map<ColumnSlug, ProjectionColumnInfo>
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export interface GlobeViewport {
|
|
155
|
+
rotation: [number, number]
|
|
156
|
+
zoom: number
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export interface MapViewport {
|
|
160
|
+
x: number
|
|
161
|
+
y: number
|
|
162
|
+
width: number
|
|
163
|
+
height: number
|
|
164
|
+
ratio: number
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export const GLOBE_VIEWPORTS: Record<GlobeRegionName, GlobeViewport> = {
|
|
168
|
+
Europe: { rotation: [10, 55], zoom: 2.95 },
|
|
169
|
+
Africa: { rotation: [20, 0], zoom: 1.55 },
|
|
170
|
+
NorthAmerica: { rotation: [-94.5, 43], zoom: 1.5 },
|
|
171
|
+
SouthAmerica: { rotation: [-62, -22], zoom: 1.75 },
|
|
172
|
+
Asia: { rotation: [81, 26], zoom: 1.85 },
|
|
173
|
+
Oceania: { rotation: [152.65, -18.8], zoom: 2 },
|
|
174
|
+
Canada: { rotation: [-100, 60], zoom: 2.5 },
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Viewport for each region, defined by center and width+height in fractional coordinates */
|
|
178
|
+
export const MAP_VIEWPORTS: Record<MapRegionName, MapViewport> = {
|
|
179
|
+
World: { x: 0.565, y: 0.5, width: 1.01, height: 1.01, ratio: 2.29 },
|
|
180
|
+
Europe: { x: 0.53, y: 0.21, width: 0.2, height: 0.2, ratio: 1.77 },
|
|
181
|
+
Africa: { x: 0.48, y: 0.7, width: 0.21, height: 0.38, ratio: 1.07 },
|
|
182
|
+
NorthAmerica: { x: 0.46, y: 0.4, width: 0.19, height: 0.35, ratio: 1.12 },
|
|
183
|
+
SouthAmerica: { x: 0.52, y: 0.815, width: 0.1, height: 0.26, ratio: 0.62 },
|
|
184
|
+
Asia: { x: 0.74, y: 0.45, width: 0.36, height: 0.5, ratio: 1.65 },
|
|
185
|
+
Oceania: { x: 0.51, y: 0.75, width: 0.1, height: 0.2, ratio: 1.47 },
|
|
186
|
+
Canada: { x: 0.5, y: 0.5, width: 1, height: 1.05, ratio: 1.5 },
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Custom viewport for faceted world map, which zooms in a little bit to make best use of the available space
|
|
190
|
+
export const MAP_VIEWPORT_FACETED_WORLD: MapViewport = {
|
|
191
|
+
x: 0.545,
|
|
192
|
+
y: 0.5,
|
|
193
|
+
width: 0.91,
|
|
194
|
+
height: 1.01,
|
|
195
|
+
ratio: 2.29,
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export interface Circle {
|
|
199
|
+
cx: number // center x
|
|
200
|
+
cy: number // center y
|
|
201
|
+
r: number // radius
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export interface Ellipse {
|
|
205
|
+
cx: number // center x
|
|
206
|
+
cy: number // center y
|
|
207
|
+
rx: number // radius on the x-axis
|
|
208
|
+
ry: number // radius on the y-axis
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ellipse expressed in lon/lat
|
|
212
|
+
export interface EllipseCoords {
|
|
213
|
+
cx: number
|
|
214
|
+
cy: number
|
|
215
|
+
left: number // left x
|
|
216
|
+
top: number // top y
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
interface BaseAnnotation {
|
|
220
|
+
id: string
|
|
221
|
+
feature: RenderFeature
|
|
222
|
+
placedBounds: Bounds
|
|
223
|
+
text: string
|
|
224
|
+
fontSize: number
|
|
225
|
+
color: string
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export interface InternalAnnotation extends BaseAnnotation {
|
|
229
|
+
type: "internal"
|
|
230
|
+
ellipse: Ellipse
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export interface ExternalAnnotation extends BaseAnnotation {
|
|
234
|
+
type: "external"
|
|
235
|
+
direction: Direction
|
|
236
|
+
anchor: [number, number]
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export type Annotation = InternalAnnotation | ExternalAnnotation
|
|
240
|
+
|
|
241
|
+
export type Direction =
|
|
242
|
+
| "left"
|
|
243
|
+
| "right"
|
|
244
|
+
| "top"
|
|
245
|
+
| "bottom"
|
|
246
|
+
| "leftTop"
|
|
247
|
+
| "leftBottom"
|
|
248
|
+
| "rightTop"
|
|
249
|
+
| "rightBottom"
|
|
250
|
+
|
|
251
|
+
export type MapColumnInfo =
|
|
252
|
+
// the map column isn't a projection
|
|
253
|
+
| { type: "historical"; slug: ColumnSlug }
|
|
254
|
+
// the map column is a projection without an historical counterpart
|
|
255
|
+
| { type: "projected"; slug: ColumnSlug }
|
|
256
|
+
// the map column is a projection and has an historical counterpart
|
|
257
|
+
| ({
|
|
258
|
+
type: "historical+projected"
|
|
259
|
+
slug: ColumnSlug
|
|
260
|
+
} & ProjectionColumnInfo)
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
import * as R from "remeda"
|
|
2
|
+
import { computed, makeObservable } from "mobx"
|
|
3
|
+
import { ChartState } from "../chart/ChartInterface"
|
|
4
|
+
import {
|
|
5
|
+
ChoroplethSeries,
|
|
6
|
+
ChoroplethSeriesByName,
|
|
7
|
+
MAP_REGION_LABELS,
|
|
8
|
+
MapChartManager,
|
|
9
|
+
MapColumnInfo,
|
|
10
|
+
} from "./MapChartConstants"
|
|
11
|
+
import {
|
|
12
|
+
CoreColumn,
|
|
13
|
+
ErrorValueTypes,
|
|
14
|
+
OwidTable,
|
|
15
|
+
} from "../../core-table/index.js"
|
|
16
|
+
import { match, P } from "ts-pattern"
|
|
17
|
+
import {
|
|
18
|
+
ChartErrorInfo,
|
|
19
|
+
Color,
|
|
20
|
+
ColorSchemeName,
|
|
21
|
+
ColumnSlug,
|
|
22
|
+
EntityName,
|
|
23
|
+
MapRegionName,
|
|
24
|
+
PrimitiveType,
|
|
25
|
+
TickFormattingOptions,
|
|
26
|
+
Time,
|
|
27
|
+
} from "../../types/index.js"
|
|
28
|
+
import {
|
|
29
|
+
anyToString,
|
|
30
|
+
checkHasMembers,
|
|
31
|
+
isPresent,
|
|
32
|
+
mappableCountries,
|
|
33
|
+
regions,
|
|
34
|
+
} from "../../utils/index.js"
|
|
35
|
+
import { MapConfig } from "./MapConfig"
|
|
36
|
+
import { combineHistoricalAndProjectionColumns } from "../chart/ChartUtils"
|
|
37
|
+
import {
|
|
38
|
+
getCountriesByRegion,
|
|
39
|
+
isOnTheCanadaMap,
|
|
40
|
+
isOnTheMap,
|
|
41
|
+
} from "./MapHelpers"
|
|
42
|
+
import { MapSelectionArray } from "../selection/MapSelectionArray"
|
|
43
|
+
import { ColorScale, ColorScaleManager } from "../color/ColorScale"
|
|
44
|
+
import { ColorScaleConfig } from "../color/ColorScaleConfig"
|
|
45
|
+
|
|
46
|
+
export type MapFormatValueForTooltip = (
|
|
47
|
+
d: PrimitiveType,
|
|
48
|
+
options?: TickFormattingOptions
|
|
49
|
+
) => {
|
|
50
|
+
label: string
|
|
51
|
+
isCategorical: boolean
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export class MapChartState implements ChartState, ColorScaleManager {
|
|
55
|
+
manager: MapChartManager
|
|
56
|
+
|
|
57
|
+
colorScale: ColorScale
|
|
58
|
+
defaultBaseColorScheme = ColorSchemeName.BuGn
|
|
59
|
+
hasNoDataBin = true
|
|
60
|
+
|
|
61
|
+
constructor({ manager }: { manager: MapChartManager }) {
|
|
62
|
+
this.manager = manager
|
|
63
|
+
this.colorScale = new ColorScale(this)
|
|
64
|
+
makeObservable(this)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
transformTable(table: OwidTable): OwidTable {
|
|
68
|
+
// Drop non-mappable entities from the table
|
|
69
|
+
table = this.dropNonMapEntities(table)
|
|
70
|
+
|
|
71
|
+
return match(this.mapColumnInfo)
|
|
72
|
+
.with({ type: P.union("historical", "projected") }, (info) =>
|
|
73
|
+
this.transformTableForSingleMapColumn(table, info)
|
|
74
|
+
)
|
|
75
|
+
.with({ type: "historical+projected" }, (info) =>
|
|
76
|
+
this.transformTableForCombinedMapColumn(table, info)
|
|
77
|
+
)
|
|
78
|
+
.exhaustive()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private transformTableForSingleMapColumn(
|
|
82
|
+
table: OwidTable,
|
|
83
|
+
mapColumnInfo: Extract<
|
|
84
|
+
MapColumnInfo,
|
|
85
|
+
{ type: "historical" | "projected" }
|
|
86
|
+
>
|
|
87
|
+
): OwidTable {
|
|
88
|
+
return table
|
|
89
|
+
.dropRowsWithErrorValuesForColumn(mapColumnInfo.slug)
|
|
90
|
+
.interpolateColumnWithTolerance(mapColumnInfo.slug, {
|
|
91
|
+
toleranceOverride: this.mapConfig.timeTolerance,
|
|
92
|
+
toleranceStrategyOverride: this.mapConfig.toleranceStrategy,
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private transformTableForCombinedMapColumn(
|
|
97
|
+
table: OwidTable,
|
|
98
|
+
mapColumnInfo: Extract<MapColumnInfo, { type: "historical+projected" }>
|
|
99
|
+
): OwidTable {
|
|
100
|
+
const { historicalSlug, projectedSlug, combinedSlug } = mapColumnInfo
|
|
101
|
+
|
|
102
|
+
// Interpolate both columns separately
|
|
103
|
+
table = table
|
|
104
|
+
.interpolateColumnWithTolerance(projectedSlug, {
|
|
105
|
+
toleranceOverride: this.mapConfig.timeTolerance,
|
|
106
|
+
toleranceStrategyOverride: this.mapConfig.toleranceStrategy,
|
|
107
|
+
})
|
|
108
|
+
.interpolateColumnWithTolerance(historicalSlug, {
|
|
109
|
+
toleranceOverride: this.mapConfig.timeTolerance,
|
|
110
|
+
toleranceStrategyOverride: this.mapConfig.toleranceStrategy,
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
// Combine the projection column with its historical stem into one column
|
|
114
|
+
table = combineHistoricalAndProjectionColumns(table, mapColumnInfo, {
|
|
115
|
+
shouldAddIsProjectionColumn: true,
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
// Drop rows with error values for the combined column
|
|
119
|
+
table = table.dropRowsWithErrorValuesForColumn(combinedSlug)
|
|
120
|
+
|
|
121
|
+
return table
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
transformTableForSelection(table: OwidTable): OwidTable {
|
|
125
|
+
table = this.addMissingMapEntities(table)
|
|
126
|
+
table = this.dropNonMapEntitiesForSelection(table)
|
|
127
|
+
table = this.dropAntarctica(table)
|
|
128
|
+
return table
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private dropAntarctica(table: OwidTable): OwidTable {
|
|
132
|
+
// We prefer to not offer Antarctica in the entity selector on the map
|
|
133
|
+
// tab to avoid confusion since it's shown on the globe, but not on the map.
|
|
134
|
+
return table.filterByEntityNamesUsingIncludeExcludePattern({
|
|
135
|
+
excluded: ["Antarctica"],
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private dropNonMapEntities(table: OwidTable): OwidTable {
|
|
140
|
+
// For Canada region, filter by Canadian provinces/territories
|
|
141
|
+
if (this.mapConfig.region === MapRegionName.Canada) {
|
|
142
|
+
const entityNamesToSelect =
|
|
143
|
+
table.availableEntityNames.filter(isOnTheCanadaMap)
|
|
144
|
+
return table.filterByEntityNames(entityNamesToSelect)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// For world and other regions, filter by world map entities
|
|
148
|
+
const entityNamesToSelect =
|
|
149
|
+
table.availableEntityNames.filter(isOnTheMap)
|
|
150
|
+
return table.filterByEntityNames(entityNamesToSelect)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private dropNonMapEntitiesForSelection(table: OwidTable): OwidTable {
|
|
154
|
+
const { selectionArray, mapConfig } = this
|
|
155
|
+
|
|
156
|
+
const allMappableCountryNames = mappableCountries.map((c) => c.name)
|
|
157
|
+
const allRegionNames = regions
|
|
158
|
+
.filter((r) => checkHasMembers(r) && r.code !== "OWID_WRL")
|
|
159
|
+
.map((r) => r.name)
|
|
160
|
+
|
|
161
|
+
const mappableCountryNameSet = new Set(allMappableCountryNames)
|
|
162
|
+
|
|
163
|
+
// If in 2D mode and a continent is selected, then all countries
|
|
164
|
+
// outside of the selected continent are disabled on the map
|
|
165
|
+
// and thus also not selectable
|
|
166
|
+
if (this.mapConfig.is2dContinentActive()) {
|
|
167
|
+
const countriesInRegionSet = getCountriesByRegion(
|
|
168
|
+
MAP_REGION_LABELS[mapConfig.region]
|
|
169
|
+
)
|
|
170
|
+
if (!countriesInRegionSet) return table
|
|
171
|
+
|
|
172
|
+
const countriesInRegion = Array.from(countriesInRegionSet)
|
|
173
|
+
const mappableCountriesInRegion = countriesInRegion.filter(
|
|
174
|
+
(countryName) => mappableCountryNameSet.has(countryName)
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
return table.filterByEntityNames(
|
|
178
|
+
R.unique([
|
|
179
|
+
// only keep countries in the region
|
|
180
|
+
...mappableCountriesInRegion,
|
|
181
|
+
// keep the user's selection
|
|
182
|
+
...selectionArray.selectedEntityNames,
|
|
183
|
+
])
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// if no regions are currently selected, keep all mappable countries and regions
|
|
188
|
+
if (!selectionArray.hasRegions) {
|
|
189
|
+
return table.filterByEntityNames([
|
|
190
|
+
...allRegionNames,
|
|
191
|
+
...allMappableCountryNames,
|
|
192
|
+
])
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return table.filterByEntityNames(
|
|
196
|
+
R.unique([
|
|
197
|
+
// keep all regions
|
|
198
|
+
...allRegionNames,
|
|
199
|
+
// only keep those countries that are within the selected regions
|
|
200
|
+
...selectionArray.countryNamesForSelectedRegions,
|
|
201
|
+
// keep the user's selection
|
|
202
|
+
...selectionArray.selectedEntityNames,
|
|
203
|
+
])
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
private addMissingMapEntities(table: OwidTable): OwidTable {
|
|
208
|
+
// the given table might not have data for all mappable countries, but
|
|
209
|
+
// on the map tab, we do want every country to be selectable, even if
|
|
210
|
+
// it doesn't have data for any of the years. that's why we add a
|
|
211
|
+
// missing-data row for every mappable country that isn't in the table
|
|
212
|
+
|
|
213
|
+
const missingMappableCountries = mappableCountries.filter(
|
|
214
|
+
(country) => !table.availableEntityNameSet.has(country.name)
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
const rows = missingMappableCountries.map((country) => ({
|
|
218
|
+
entityName: country.name,
|
|
219
|
+
time: table.maxTime!, // arbitrary time
|
|
220
|
+
value: ErrorValueTypes.MissingValuePlaceholder,
|
|
221
|
+
}))
|
|
222
|
+
table = table.appendRows(
|
|
223
|
+
rows,
|
|
224
|
+
`Append rows for mappable countries without data: ${rows.map((row) => row.entityName).join(", ")}`
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
return table
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
@computed get inputTable(): OwidTable {
|
|
231
|
+
const { mapColumnInfo } = this
|
|
232
|
+
const { table } = this.manager
|
|
233
|
+
|
|
234
|
+
// For historical+projected data, we need to create the combined column
|
|
235
|
+
// on the input table. This ensures the color scale has access to the
|
|
236
|
+
// complete range of data across both columns
|
|
237
|
+
return mapColumnInfo.type === "historical+projected"
|
|
238
|
+
? combineHistoricalAndProjectionColumns(table, mapColumnInfo)
|
|
239
|
+
: table
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
@computed get transformedTableFromGrapher(): OwidTable {
|
|
243
|
+
return (
|
|
244
|
+
this.manager.transformedTable ??
|
|
245
|
+
this.transformTable(this.inputTable)
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
@computed get transformedTable(): OwidTable {
|
|
250
|
+
let table = this.transformedTableFromGrapher
|
|
251
|
+
|
|
252
|
+
// A target time is set for faceted maps
|
|
253
|
+
if (this.manager.targetTime !== undefined) {
|
|
254
|
+
table = table.filterByTargetTimes(
|
|
255
|
+
[this.manager.targetTime],
|
|
256
|
+
this.mapConfig.timeTolerance ??
|
|
257
|
+
table.get(this.mapColumnSlug).tolerance
|
|
258
|
+
)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return table
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
@computed get selectionArray(): MapSelectionArray {
|
|
265
|
+
return this.mapConfig.selection
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
@computed get mapColumn(): CoreColumn {
|
|
269
|
+
return this.transformedTable.get(this.mapColumnSlug)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
@computed get mapColumnInfo(): MapColumnInfo {
|
|
273
|
+
const mapColumnSlug = this.manager.mapColumnSlug!
|
|
274
|
+
|
|
275
|
+
// If projection info is available, then we can stitch together the
|
|
276
|
+
// historical and projected columns
|
|
277
|
+
const projectionInfo =
|
|
278
|
+
this.manager.projectionColumnInfoBySlug?.get(mapColumnSlug)
|
|
279
|
+
if (projectionInfo) {
|
|
280
|
+
return {
|
|
281
|
+
type: "historical+projected",
|
|
282
|
+
slug: projectionInfo.combinedSlug,
|
|
283
|
+
...projectionInfo,
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const type = this.manager.table.get(mapColumnSlug).isProjection
|
|
288
|
+
? "projected"
|
|
289
|
+
: "historical"
|
|
290
|
+
|
|
291
|
+
return { type, slug: mapColumnSlug }
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
@computed get mapConfig(): MapConfig {
|
|
295
|
+
return this.manager.mapConfig || new MapConfig()
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
@computed get mapColumnSlug(): ColumnSlug {
|
|
299
|
+
return this.mapColumnInfo.slug
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// The map column without tolerance and timeline filtering applied
|
|
303
|
+
@computed get mapColumnUntransformed(): CoreColumn {
|
|
304
|
+
return this.dropNonMapEntities(this.inputTable).get(this.mapColumnSlug)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
@computed get colorScaleConfig(): ColorScaleConfig {
|
|
308
|
+
return (
|
|
309
|
+
ColorScaleConfig.fromDSL(this.mapColumn.def) ??
|
|
310
|
+
this.mapConfig.colorScale
|
|
311
|
+
)
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
@computed get colorScaleColumn(): CoreColumn {
|
|
315
|
+
// Use the table before any transforms to collect all possible values over time.
|
|
316
|
+
// Otherwise the legend changes as you slide the timeline handle.
|
|
317
|
+
return this.mapColumnUntransformed
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
@computed get hasProjectedData(): boolean {
|
|
321
|
+
return this.mapColumnInfo.type !== "historical"
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
@computed get hasProjectedDataBin(): boolean {
|
|
325
|
+
return this.hasProjectedData
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
@computed get targetTime(): number | undefined {
|
|
329
|
+
return this.manager.targetTime ?? this.manager.endTime
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
@computed get columnIsProjection(): CoreColumn | undefined {
|
|
333
|
+
const slugForIsProjectionColumn =
|
|
334
|
+
this.mapColumnInfo?.type === "historical+projected"
|
|
335
|
+
? this.mapColumnInfo.slugForIsProjectionColumn
|
|
336
|
+
: undefined
|
|
337
|
+
|
|
338
|
+
return slugForIsProjectionColumn
|
|
339
|
+
? this.transformedTable.get(slugForIsProjectionColumn)
|
|
340
|
+
: undefined
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
private checkIsProjection(
|
|
344
|
+
entityName: EntityName,
|
|
345
|
+
originalTime: Time
|
|
346
|
+
): boolean {
|
|
347
|
+
return match(this.mapColumnInfo.type)
|
|
348
|
+
.with("historical", () => false)
|
|
349
|
+
.with("projected", () => true)
|
|
350
|
+
.with("historical+projected", () =>
|
|
351
|
+
this.columnIsProjection?.valueByEntityNameAndOriginalTime
|
|
352
|
+
.get(entityName)
|
|
353
|
+
?.get(originalTime)
|
|
354
|
+
)
|
|
355
|
+
.exhaustive()
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
@computed get noDataColor(): Color {
|
|
359
|
+
return this.colorScale.noDataColor
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
@computed get series(): ChoroplethSeries[] {
|
|
363
|
+
const { mapColumn, targetTime } = this
|
|
364
|
+
if (mapColumn.isMissing) return []
|
|
365
|
+
if (targetTime === undefined) return []
|
|
366
|
+
|
|
367
|
+
return mapColumn.owidRows
|
|
368
|
+
.map((row) => {
|
|
369
|
+
const { entityName, value, originalTime } = row
|
|
370
|
+
const color =
|
|
371
|
+
this.colorScale.getColor(value) || this.noDataColor
|
|
372
|
+
const isProjection = this.checkIsProjection(
|
|
373
|
+
entityName,
|
|
374
|
+
originalTime
|
|
375
|
+
)
|
|
376
|
+
return {
|
|
377
|
+
seriesName: entityName,
|
|
378
|
+
time: originalTime,
|
|
379
|
+
value,
|
|
380
|
+
color,
|
|
381
|
+
isProjection,
|
|
382
|
+
} satisfies ChoroplethSeries
|
|
383
|
+
})
|
|
384
|
+
.filter(isPresent)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
@computed get seriesMap(): ChoroplethSeriesByName {
|
|
388
|
+
return new Map(this.series.map((series) => [series.seriesName, series]))
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
@computed get formatValueForTooltip(): MapFormatValueForTooltip {
|
|
392
|
+
const { mapConfig, colorScale } = this
|
|
393
|
+
|
|
394
|
+
return (d: PrimitiveType, options?: TickFormattingOptions) => {
|
|
395
|
+
if (mapConfig.tooltipUseCustomLabels) {
|
|
396
|
+
// Find the bin (and its label) that this value belongs to
|
|
397
|
+
const bin = colorScale.getBinForValue(d)
|
|
398
|
+
const label = bin?.label
|
|
399
|
+
if (label !== undefined && label !== "")
|
|
400
|
+
return { label, isCategorical: true }
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (typeof d === "number") {
|
|
404
|
+
const label = this.mapColumn.formatValueShort(d, options)
|
|
405
|
+
return { label, isCategorical: false }
|
|
406
|
+
} else {
|
|
407
|
+
return { label: anyToString(d), isCategorical: true }
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
@computed get errorInfo(): ChartErrorInfo {
|
|
413
|
+
if (this.mapColumn.isMissing) return { reason: "Missing map column" }
|
|
414
|
+
return { reason: "" }
|
|
415
|
+
}
|
|
416
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { computed, makeObservable } from "mobx"
|
|
3
|
+
import { observer } from "mobx-react"
|
|
4
|
+
import { ChartInterface } from "../chart/ChartInterface"
|
|
5
|
+
import { MapChartState } from "./MapChartState"
|
|
6
|
+
import { MapChart, MapChartProps } from "./MapChart"
|
|
7
|
+
|
|
8
|
+
@observer
|
|
9
|
+
export class MapChartThumbnail
|
|
10
|
+
extends React.Component<MapChartProps>
|
|
11
|
+
implements ChartInterface
|
|
12
|
+
{
|
|
13
|
+
constructor(props: MapChartProps) {
|
|
14
|
+
super(props)
|
|
15
|
+
makeObservable(this)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@computed get chartState(): MapChartState {
|
|
19
|
+
return this.props.chartState
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
override render(): React.ReactElement {
|
|
23
|
+
return <MapChart {...this.props} />
|
|
24
|
+
}
|
|
25
|
+
}
|