@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,58 @@
|
|
|
1
|
+
import {
|
|
2
|
+
latestSchemaVersion,
|
|
3
|
+
outdatedSchemaVersions,
|
|
4
|
+
} from "../defaultGrapherConfig"
|
|
5
|
+
|
|
6
|
+
const allSchemaVersions = [...outdatedSchemaVersions, latestSchemaVersion]
|
|
7
|
+
|
|
8
|
+
type LatestSchemaVersion = typeof latestSchemaVersion
|
|
9
|
+
type OutdatedSchemaVersion = (typeof outdatedSchemaVersions)[number]
|
|
10
|
+
type SchemaVersion = OutdatedSchemaVersion | LatestSchemaVersion
|
|
11
|
+
|
|
12
|
+
type Schema =
|
|
13
|
+
`https://files.ourworldindata.org/schemas/grapher-schema.${SchemaVersion}.json`
|
|
14
|
+
|
|
15
|
+
// we can't type configs that don't adhere to the latest schema as we don't know what they look like
|
|
16
|
+
export type AnyConfig = Record<string, any>
|
|
17
|
+
export type AnyConfigWithValidSchema = AnyConfig & {
|
|
18
|
+
$schema: Schema
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const schemaVersionRegex =
|
|
22
|
+
/https:\/\/files\.ourworldindata\.org\/schemas\/grapher-schema\.(?<version>\d{3})\.json/m
|
|
23
|
+
|
|
24
|
+
const isValidSchemaVersion = (version: string): version is SchemaVersion =>
|
|
25
|
+
allSchemaVersions.includes(version as any)
|
|
26
|
+
|
|
27
|
+
export function getSchemaVersion(
|
|
28
|
+
config: AnyConfigWithValidSchema
|
|
29
|
+
): SchemaVersion
|
|
30
|
+
export function getSchemaVersion(config: AnyConfig): SchemaVersion | null
|
|
31
|
+
export function getSchemaVersion(
|
|
32
|
+
config: AnyConfig | AnyConfigWithValidSchema
|
|
33
|
+
): SchemaVersion | null {
|
|
34
|
+
const version = config.$schema?.match(schemaVersionRegex)?.groups?.version
|
|
35
|
+
if (!version || !isValidSchemaVersion(version)) return null
|
|
36
|
+
return version
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function createSchemaForVersion(version: SchemaVersion): Schema {
|
|
40
|
+
return `https://files.ourworldindata.org/schemas/grapher-schema.${version}.json`
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const isLatestVersion = (version: SchemaVersion) =>
|
|
44
|
+
version === latestSchemaVersion
|
|
45
|
+
|
|
46
|
+
export const isOutdatedVersion = (version: SchemaVersion) =>
|
|
47
|
+
outdatedSchemaVersions.includes(version as any)
|
|
48
|
+
|
|
49
|
+
export const hasValidSchema = (
|
|
50
|
+
config: AnyConfig
|
|
51
|
+
): config is AnyConfigWithValidSchema => getSchemaVersion(config) !== null
|
|
52
|
+
|
|
53
|
+
export const hasOutdatedSchema = (
|
|
54
|
+
config: AnyConfigWithValidSchema
|
|
55
|
+
): boolean => {
|
|
56
|
+
const version = getSchemaVersion(config)
|
|
57
|
+
return isOutdatedVersion(version)
|
|
58
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as _ from "lodash-es"
|
|
2
|
+
import { GrapherInterface } from "../../../types/index.js"
|
|
3
|
+
|
|
4
|
+
import { defaultGrapherConfig } from "../defaultGrapherConfig"
|
|
5
|
+
import {
|
|
6
|
+
getSchemaVersion,
|
|
7
|
+
hasValidSchema,
|
|
8
|
+
isLatestVersion,
|
|
9
|
+
hasOutdatedSchema,
|
|
10
|
+
type AnyConfig,
|
|
11
|
+
type AnyConfigWithValidSchema,
|
|
12
|
+
} from "./helpers"
|
|
13
|
+
import { runMigration } from "./migrations"
|
|
14
|
+
|
|
15
|
+
const recursivelyApplyMigrations = (
|
|
16
|
+
config: AnyConfigWithValidSchema
|
|
17
|
+
): AnyConfigWithValidSchema => {
|
|
18
|
+
const version = getSchemaVersion(config)
|
|
19
|
+
if (isLatestVersion(version)) return config
|
|
20
|
+
return recursivelyApplyMigrations(runMigration(config))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const migrate = (config: AnyConfigWithValidSchema): GrapherInterface =>
|
|
24
|
+
recursivelyApplyMigrations(config) as GrapherInterface
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Attempts to migrate a config to the latest schema version.
|
|
28
|
+
*
|
|
29
|
+
* An outdated config is migrated to the latest version by applying a series of
|
|
30
|
+
* predefined migrations. We rely on the schema version to determine if a config
|
|
31
|
+
* is outdated.
|
|
32
|
+
*
|
|
33
|
+
* Note that the given config is not actually validated against the schema!
|
|
34
|
+
*/
|
|
35
|
+
export const migrateGrapherConfigToLatestVersion = (
|
|
36
|
+
config: AnyConfig
|
|
37
|
+
): GrapherInterface => {
|
|
38
|
+
// the config adheres to the latest schema
|
|
39
|
+
if (config.$schema === defaultGrapherConfig.$schema) return config
|
|
40
|
+
|
|
41
|
+
// if the schema version is outdated, migrate it
|
|
42
|
+
if (hasValidSchema(config) && hasOutdatedSchema(config)) {
|
|
43
|
+
return migrate(_.cloneDeep(config))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// throw if the schema is missing
|
|
47
|
+
if (config.$schema === undefined) {
|
|
48
|
+
throw new Error("Schema missing")
|
|
49
|
+
} else {
|
|
50
|
+
/**
|
|
51
|
+
* If the schema version is not outdated and not the latest, we have most likely received a
|
|
52
|
+
* config from a future version of the codebase, that the client code is not yet aware of.
|
|
53
|
+
* That's not perfect, but in reality, most schema changes are benign changes,
|
|
54
|
+
* and rendering the config with the current code will result in a better user experience
|
|
55
|
+
* than just throwing an error and grapher not rendering at all without any explanation.
|
|
56
|
+
* - @marcelgerber, 2025-07-02
|
|
57
|
+
*/
|
|
58
|
+
const message = `Received grapher config with unsupported schema ${config.$schema}; this code expects schema ${defaultGrapherConfig.$schema}.`
|
|
59
|
+
console.warn(message)
|
|
60
|
+
return config
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const migrateGrapherConfigToLatestVersionAndFailOnError = (
|
|
65
|
+
config: AnyConfig
|
|
66
|
+
): GrapherInterface => {
|
|
67
|
+
const migrated = migrateGrapherConfigToLatestVersion(config)
|
|
68
|
+
|
|
69
|
+
if (migrated.$schema !== defaultGrapherConfig.$schema) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`Invalid schema version after schema migration: ${migrated.$schema}. Expected: ${defaultGrapherConfig.$schema}`
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
return migrated
|
|
75
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// Schema migrations
|
|
2
|
+
//
|
|
3
|
+
// Every breaking change to the schema should be accompanied by a migration.
|
|
4
|
+
//
|
|
5
|
+
// To add a migration, follow these steps:
|
|
6
|
+
// - Create a new function `migrateXXXToXXX` that migrates a config from one version to the next.
|
|
7
|
+
// Make sure to update the $schema field to the next version in your migration function,
|
|
8
|
+
// or else the recursively defined migrate function will not terminate!
|
|
9
|
+
// - Add a new case to the match statement in `runMigration` that calls the new migration function.
|
|
10
|
+
|
|
11
|
+
import { match } from "ts-pattern"
|
|
12
|
+
import {
|
|
13
|
+
type AnyConfigWithValidSchema,
|
|
14
|
+
createSchemaForVersion,
|
|
15
|
+
getSchemaVersion,
|
|
16
|
+
isLatestVersion,
|
|
17
|
+
} from "./helpers"
|
|
18
|
+
import { GRAPHER_CHART_TYPES } from "../../../types/index.js"
|
|
19
|
+
|
|
20
|
+
// see https://github.com/owid/owid-grapher/commit/26f2a0d1790c71bdda7e12f284ca552945d2f6ef
|
|
21
|
+
const migrateFrom001To002 = (
|
|
22
|
+
config: AnyConfigWithValidSchema
|
|
23
|
+
): AnyConfigWithValidSchema => {
|
|
24
|
+
delete config.selectedData
|
|
25
|
+
config.$schema = createSchemaForVersion("002")
|
|
26
|
+
return config
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// see https://github.com/owid/owid-grapher/commit/4525ad81fb7064709ffab83677a8b0354b324dfb
|
|
30
|
+
const migrateFrom002To003 = (
|
|
31
|
+
config: AnyConfigWithValidSchema
|
|
32
|
+
): AnyConfigWithValidSchema => {
|
|
33
|
+
if (config.hideTitleAnnotation) {
|
|
34
|
+
config.hideTitleAnnotations = {
|
|
35
|
+
entity: true,
|
|
36
|
+
time: true,
|
|
37
|
+
change: true,
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
delete config.hideTitleAnnotation
|
|
41
|
+
|
|
42
|
+
config.$schema = createSchemaForVersion("003")
|
|
43
|
+
return config
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// see https://github.com/owid/owid-grapher/commit/1776721253cf61d7f1e24ebadeaf7a7ca2f43ced
|
|
47
|
+
const migrateFrom003To004 = (
|
|
48
|
+
config: AnyConfigWithValidSchema
|
|
49
|
+
): AnyConfigWithValidSchema => {
|
|
50
|
+
delete config.data
|
|
51
|
+
config.$schema = createSchemaForVersion("004")
|
|
52
|
+
return config
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// see https://github.com/owid/owid-grapher/commit/1d67de3174764a413bc5055fbdf34efb2b49e079
|
|
56
|
+
const migrateFrom004To005 = (
|
|
57
|
+
config: AnyConfigWithValidSchema
|
|
58
|
+
): AnyConfigWithValidSchema => {
|
|
59
|
+
delete config.hideLinesOutsideTolerance
|
|
60
|
+
config.$schema = createSchemaForVersion("005")
|
|
61
|
+
return config
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const migrateFrom005To006 = (
|
|
65
|
+
config: AnyConfigWithValidSchema
|
|
66
|
+
): AnyConfigWithValidSchema => {
|
|
67
|
+
const { type = GRAPHER_CHART_TYPES.LineChart, hasChartTab = true } = config
|
|
68
|
+
|
|
69
|
+
// add types field
|
|
70
|
+
if (!hasChartTab) config.chartTypes = []
|
|
71
|
+
else if (type !== GRAPHER_CHART_TYPES.LineChart) config.chartTypes = [type]
|
|
72
|
+
|
|
73
|
+
// remove deprecated fields
|
|
74
|
+
delete config.type
|
|
75
|
+
delete config.hasChartTab
|
|
76
|
+
|
|
77
|
+
config.$schema = createSchemaForVersion("006")
|
|
78
|
+
return config
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const migrateFrom006To007 = (
|
|
82
|
+
config: AnyConfigWithValidSchema
|
|
83
|
+
): AnyConfigWithValidSchema => {
|
|
84
|
+
// rename map.projection to map.region
|
|
85
|
+
if (config.map?.projection) {
|
|
86
|
+
config.map.region = config.map.projection
|
|
87
|
+
delete config.map.projection
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
config.$schema = createSchemaForVersion("007")
|
|
91
|
+
return config
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export const migrateFrom007To008 = (
|
|
95
|
+
config: AnyConfigWithValidSchema
|
|
96
|
+
): AnyConfigWithValidSchema => {
|
|
97
|
+
// remove colorScale.customNumericMinValue, merge it into colorScale.customNumericValues
|
|
98
|
+
if (config.map?.colorScale?.customNumericValues) {
|
|
99
|
+
config.map.colorScale.customNumericValues = [
|
|
100
|
+
config.map.colorScale.customNumericMinValue ?? 0,
|
|
101
|
+
...config.map.colorScale.customNumericValues,
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
if (config.map?.colorScale?.customNumericMinValue !== undefined) {
|
|
105
|
+
delete config.map.colorScale.customNumericMinValue
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (config.colorScale?.customNumericValues) {
|
|
109
|
+
config.colorScale.customNumericValues = [
|
|
110
|
+
config.colorScale.customNumericMinValue ?? 0,
|
|
111
|
+
...config.colorScale.customNumericValues,
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
if (config.colorScale?.customNumericMinValue !== undefined) {
|
|
115
|
+
delete config.colorScale.customNumericMinValue
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
config.$schema = createSchemaForVersion("008")
|
|
119
|
+
return config
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export const migrateFrom008To009 = (config: AnyConfigWithValidSchema) => {
|
|
123
|
+
if ((config.map?.colorScale?.binningStrategy ?? "manual") !== "manual") {
|
|
124
|
+
config.map.colorScale.binningStrategy = "auto"
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (config.map?.colorScale?.binningStrategyBinCount !== undefined) {
|
|
128
|
+
delete config.map.colorScale.binningStrategyBinCount
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if ((config.colorScale?.binningStrategy ?? "manual") !== "manual") {
|
|
132
|
+
config.colorScale.binningStrategy = "auto"
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (config.colorScale?.binningStrategyBinCount !== undefined) {
|
|
136
|
+
delete config.colorScale.binningStrategyBinCount
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
config.$schema = createSchemaForVersion("009")
|
|
140
|
+
return config
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export const runMigration = (
|
|
144
|
+
config: AnyConfigWithValidSchema
|
|
145
|
+
): AnyConfigWithValidSchema => {
|
|
146
|
+
const version = getSchemaVersion(config)
|
|
147
|
+
if (isLatestVersion(version)) return config
|
|
148
|
+
return match(version)
|
|
149
|
+
.with("001", () => migrateFrom001To002(config))
|
|
150
|
+
.with("002", () => migrateFrom002To003(config))
|
|
151
|
+
.with("003", () => migrateFrom003To004(config))
|
|
152
|
+
.with("004", () => migrateFrom004To005(config))
|
|
153
|
+
.with("005", () => migrateFrom005To006(config))
|
|
154
|
+
.with("006", () => migrateFrom006To007(config))
|
|
155
|
+
.with("007", () => migrateFrom007To008(config))
|
|
156
|
+
.with("008", () => migrateFrom008To009(config))
|
|
157
|
+
.exhaustive()
|
|
158
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { computed, makeObservable } from "mobx"
|
|
2
|
+
import { SelectionArray } from "./SelectionArray"
|
|
3
|
+
import {
|
|
4
|
+
Aggregate,
|
|
5
|
+
checkHasMembers,
|
|
6
|
+
checkIsCountry,
|
|
7
|
+
Continent,
|
|
8
|
+
Country,
|
|
9
|
+
EntityName,
|
|
10
|
+
excludeUndefined,
|
|
11
|
+
getCountryNamesForRegion,
|
|
12
|
+
getRegionByName,
|
|
13
|
+
IncomeGroup,
|
|
14
|
+
Region,
|
|
15
|
+
} from "../../utils/index.js"
|
|
16
|
+
import * as R from "remeda"
|
|
17
|
+
|
|
18
|
+
export class MapSelectionArray extends SelectionArray {
|
|
19
|
+
constructor(selectedEntityNames: EntityName[] = []) {
|
|
20
|
+
super(selectedEntityNames)
|
|
21
|
+
|
|
22
|
+
makeObservable(this)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@computed private get selectedEntitiesWithRegionInfo(): Region[] {
|
|
26
|
+
return excludeUndefined(
|
|
27
|
+
this.selectedEntityNames.map((name) => getRegionByName(name))
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@computed get selectedCountries(): Country[] {
|
|
32
|
+
return this.selectedEntitiesWithRegionInfo.filter((region) =>
|
|
33
|
+
checkIsCountry(region)
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@computed get selectedCountryNames(): EntityName[] {
|
|
38
|
+
return this.selectedCountries.map((country) => country.name)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@computed get hasCountries(): boolean {
|
|
42
|
+
return this.selectedCountries.length > 0
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Subset of the selected countries that are part of the selected regions.
|
|
47
|
+
* Returns all selected countries if no region is selected.
|
|
48
|
+
*/
|
|
49
|
+
@computed get selectedCountryNamesInForeground(): EntityName[] {
|
|
50
|
+
if (!this.hasRegions) return this.selectedCountryNames
|
|
51
|
+
const memberCountries = this.countryNamesForSelectedRegionsSet
|
|
52
|
+
return this.selectedCountries
|
|
53
|
+
.filter((country) => memberCountries.has(country.name))
|
|
54
|
+
.map((country) => country.name)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Complement of `selectedCountryNamesInForeground`.
|
|
59
|
+
* Subset of the selected countries that are not part of any selected region.
|
|
60
|
+
* Returns an empty list if no region is selected.
|
|
61
|
+
*/
|
|
62
|
+
@computed get selectedCountryNamesInBackground(): EntityName[] {
|
|
63
|
+
return R.difference(
|
|
64
|
+
this.selectedCountryNames,
|
|
65
|
+
this.selectedCountryNamesInForeground
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* List of selected regions where a region is any geographic entity that
|
|
71
|
+
* is made up of a set of countries.
|
|
72
|
+
*/
|
|
73
|
+
@computed get selectedRegions(): (Continent | Aggregate | IncomeGroup)[] {
|
|
74
|
+
return this.selectedEntitiesWithRegionInfo.filter(
|
|
75
|
+
(region): region is Continent | Aggregate | IncomeGroup =>
|
|
76
|
+
checkHasMembers(region) && region.code !== "OWID_WRL"
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@computed get selectedRegionNames(): EntityName[] {
|
|
81
|
+
return this.selectedRegions.map((region) => region.name)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@computed get hasRegions(): boolean {
|
|
85
|
+
return this.selectedRegions.length > 0
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@computed get countryNamesForSelectedRegionsSet(): Set<EntityName> {
|
|
89
|
+
return new Set(
|
|
90
|
+
this.selectedRegions.flatMap((region) =>
|
|
91
|
+
getCountryNamesForRegion(region)
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@computed get countryNamesForSelectedRegions(): EntityName[] {
|
|
97
|
+
return Array.from(this.countryNamesForSelectedRegionsSet)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { EntityName } from "../../types/index.js"
|
|
2
|
+
import { action, computed, observable, makeObservable } from "mobx"
|
|
3
|
+
|
|
4
|
+
export class SelectionArray {
|
|
5
|
+
constructor(selectedEntityNames: EntityName[] = []) {
|
|
6
|
+
makeObservable(this, {
|
|
7
|
+
selectedEntityNames: observable,
|
|
8
|
+
})
|
|
9
|
+
this.selectedEntityNames = selectedEntityNames.slice()
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
selectedEntityNames: EntityName[]
|
|
13
|
+
|
|
14
|
+
@computed get hasSelection(): boolean {
|
|
15
|
+
return this.selectedEntityNames.length > 0
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@computed get numSelectedEntities(): number {
|
|
19
|
+
return this.selectedEntityNames.length
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@computed get selectedSet(): Set<EntityName> {
|
|
23
|
+
return new Set<EntityName>(this.selectedEntityNames)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Clears and sets selected entities
|
|
27
|
+
@action.bound setSelectedEntities(entityNames: EntityName[]): this {
|
|
28
|
+
this.clearSelection()
|
|
29
|
+
return this.addToSelection(entityNames)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@action.bound addToSelection(entityNames: EntityName[]): this {
|
|
33
|
+
this.selectedEntityNames = this.selectedEntityNames.concat(entityNames)
|
|
34
|
+
return this
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@action.bound clearSelection(): void {
|
|
38
|
+
this.selectedEntityNames = []
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@action.bound toggleSelection(entityName: EntityName): this {
|
|
42
|
+
return this.selectedSet.has(entityName)
|
|
43
|
+
? this.deselectEntity(entityName)
|
|
44
|
+
: this.selectEntity(entityName)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@action.bound selectEntity(entityName: EntityName): this {
|
|
48
|
+
if (!this.selectedSet.has(entityName))
|
|
49
|
+
return this.addToSelection([entityName])
|
|
50
|
+
return this
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@action.bound deselectEntity(entityName: EntityName): this {
|
|
54
|
+
this.selectedEntityNames = this.selectedEntityNames.filter(
|
|
55
|
+
(name) => name !== entityName
|
|
56
|
+
)
|
|
57
|
+
return this
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@action.bound selectEntities(entityNames: EntityName[]): this {
|
|
61
|
+
entityNames.forEach((entityName) => this.selectEntity(entityName))
|
|
62
|
+
return this
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@action.bound deselectEntities(entityNames: EntityName[]): this {
|
|
66
|
+
this.selectedEntityNames = this.selectedEntityNames.filter(
|
|
67
|
+
(name) => !entityNames.includes(name)
|
|
68
|
+
)
|
|
69
|
+
return this
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# SelectionArray
|
|
2
|
+
|
|
3
|
+
The browser already has a class named `Selection`, so for now we have `SelectionArray`.
|
|
4
|
+
|
|
5
|
+
This is a pretty simple class that maintains 2 arrays:
|
|
6
|
+
|
|
7
|
+
1. An array of strings which contains the names and or codes of selected entities
|
|
8
|
+
2. An array of Entities that can be selected
|
|
9
|
+
|
|
10
|
+
If something happens so the user has new choices, you can expand #2.
|
|
11
|
+
|
|
12
|
+
## Wish list
|
|
13
|
+
|
|
14
|
+
Except for Scatters, only selected entities will appear in charts. In Scatters "selected entities" really are "highlighted entities". It may be nice to separate those concepts.
|
|
15
|
+
|
|
16
|
+
SeriesSelection. It may be better to rename OwidTable to TimeSeriesTable, and remove the concept of `entityName` and replace with `seriesName`. Then we could have a nice simple concept "SeriesSelection". Similarly, we could ditch "EntityCode" and maybe have "SeriesNickname", which would be a shorter URL friendly way to specify seriesSelection. It would then be nice to rename the `country=` url param to something like `series=`
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Bounds } from "../../utils/index.js"
|
|
3
|
+
import { GRAPHER_SIDE_PANEL_CLASS } from "../core/GrapherConstants.js"
|
|
4
|
+
|
|
5
|
+
export const SidePanel = ({
|
|
6
|
+
bounds,
|
|
7
|
+
children,
|
|
8
|
+
}: {
|
|
9
|
+
bounds: Bounds
|
|
10
|
+
children: React.ReactNode
|
|
11
|
+
}) => {
|
|
12
|
+
return (
|
|
13
|
+
<div
|
|
14
|
+
className={GRAPHER_SIDE_PANEL_CLASS}
|
|
15
|
+
style={{
|
|
16
|
+
width: bounds.width,
|
|
17
|
+
height: bounds.height,
|
|
18
|
+
}}
|
|
19
|
+
>
|
|
20
|
+
{children}
|
|
21
|
+
</div>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
.drawer {
|
|
2
|
+
.drawer-contents {
|
|
3
|
+
position: absolute;
|
|
4
|
+
right: 0;
|
|
5
|
+
top: 0;
|
|
6
|
+
width: 300px;
|
|
7
|
+
height: 100%;
|
|
8
|
+
z-index: $zindex-controls-drawer;
|
|
9
|
+
background: white;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.drawer-backdrop {
|
|
13
|
+
position: absolute;
|
|
14
|
+
top: 0;
|
|
15
|
+
left: 0;
|
|
16
|
+
right: 0;
|
|
17
|
+
bottom: 0;
|
|
18
|
+
background: rgba(0, 0, 0, 0.1);
|
|
19
|
+
z-index: $zindex-controls-backdrop;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@keyframes drawer-backdrop-enter {
|
|
24
|
+
0% {
|
|
25
|
+
opacity: 0;
|
|
26
|
+
}
|
|
27
|
+
100% {
|
|
28
|
+
opacity: 1;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@keyframes drawer-backdrop-exit {
|
|
33
|
+
0% {
|
|
34
|
+
opacity: 1;
|
|
35
|
+
}
|
|
36
|
+
100% {
|
|
37
|
+
opacity: 0;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@keyframes drawer-contents-enter {
|
|
42
|
+
0% {
|
|
43
|
+
transform: translate(301px, 0);
|
|
44
|
+
}
|
|
45
|
+
100% {
|
|
46
|
+
transform: translate(0, 0);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@keyframes drawer-contents-exit {
|
|
51
|
+
0% {
|
|
52
|
+
transform: translate(0, 0);
|
|
53
|
+
}
|
|
54
|
+
100% {
|
|
55
|
+
transform: translate(301px, 0);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import cx from "classnames"
|
|
3
|
+
import { computed, action, observable, makeObservable } from "mobx"
|
|
4
|
+
import { observer } from "mobx-react"
|
|
5
|
+
import { isTargetOutsideElement } from "../chart/ChartUtils"
|
|
6
|
+
|
|
7
|
+
export const DrawerContext = React.createContext<{
|
|
8
|
+
toggleDrawerVisibility?: () => void
|
|
9
|
+
}>({})
|
|
10
|
+
|
|
11
|
+
interface SlideInDrawerProps {
|
|
12
|
+
active: boolean
|
|
13
|
+
toggle: () => void
|
|
14
|
+
children: React.ReactNode
|
|
15
|
+
grapherRef?: React.RefObject<HTMLDivElement | null>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@observer
|
|
19
|
+
export class SlideInDrawer extends React.Component<SlideInDrawerProps> {
|
|
20
|
+
visible: boolean = this.props.active // true while the drawer is active and during enter/exit transitions
|
|
21
|
+
drawerRef = React.createRef<HTMLDivElement>()
|
|
22
|
+
|
|
23
|
+
constructor(props: SlideInDrawerProps) {
|
|
24
|
+
super(props)
|
|
25
|
+
|
|
26
|
+
makeObservable(this, {
|
|
27
|
+
visible: observable.ref,
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
override componentDidMount(): void {
|
|
32
|
+
document.addEventListener("keydown", this.onDocumentKeyDown)
|
|
33
|
+
document.addEventListener("click", this.onDocumentClick, {
|
|
34
|
+
capture: true,
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
override componentWillUnmount(): void {
|
|
39
|
+
document.removeEventListener("keydown", this.onDocumentKeyDown)
|
|
40
|
+
document.removeEventListener("click", this.onDocumentClick, {
|
|
41
|
+
capture: true,
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
override componentDidUpdate(): void {
|
|
46
|
+
const grapherElement = this.props.grapherRef?.current
|
|
47
|
+
if (grapherElement) {
|
|
48
|
+
grapherElement.style.overflowX =
|
|
49
|
+
this.active || this.visible ? "clip" : "visible"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@action.bound onDocumentKeyDown(e: KeyboardEvent): void {
|
|
54
|
+
// dismiss menu on esc
|
|
55
|
+
if (this.active && e.key === "Escape") this.toggleVisibility()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@action.bound onDocumentClick(e: MouseEvent): void {
|
|
59
|
+
if (
|
|
60
|
+
this.active &&
|
|
61
|
+
this.drawerRef?.current &&
|
|
62
|
+
isTargetOutsideElement(e.target!, this.drawerRef.current)
|
|
63
|
+
)
|
|
64
|
+
this.toggleVisibility()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@action.bound toggleVisibility(e?: React.MouseEvent): void {
|
|
68
|
+
this.props.toggle()
|
|
69
|
+
if (this.active) this.visible = true
|
|
70
|
+
e?.stopPropagation()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@action.bound onAnimationEnd(): void {
|
|
74
|
+
if (!this.active) this.visible = false
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@computed private get active(): boolean {
|
|
78
|
+
return this.props.active
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private animationFor(selector: string): React.CSSProperties {
|
|
82
|
+
const phase = this.active ? "enter" : "exit"
|
|
83
|
+
return {
|
|
84
|
+
animationName: `${selector}-${phase}`,
|
|
85
|
+
animationDuration: "333ms",
|
|
86
|
+
animationFillMode: "forwards",
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
override render(): React.ReactElement | null {
|
|
91
|
+
const { visible, active } = this
|
|
92
|
+
|
|
93
|
+
if (active || visible) {
|
|
94
|
+
return (
|
|
95
|
+
<div
|
|
96
|
+
className={cx("drawer", { active: this.active })}
|
|
97
|
+
ref={this.drawerRef}
|
|
98
|
+
>
|
|
99
|
+
<div
|
|
100
|
+
className="drawer-backdrop"
|
|
101
|
+
onClick={this.toggleVisibility}
|
|
102
|
+
style={this.animationFor("drawer-backdrop")}
|
|
103
|
+
onAnimationEnd={this.onAnimationEnd} // triggers unmount
|
|
104
|
+
></div>
|
|
105
|
+
<div
|
|
106
|
+
className="drawer-contents"
|
|
107
|
+
style={{
|
|
108
|
+
...this.animationFor("drawer-contents"),
|
|
109
|
+
}}
|
|
110
|
+
>
|
|
111
|
+
<DrawerContext.Provider
|
|
112
|
+
value={{
|
|
113
|
+
toggleDrawerVisibility: this.toggleVisibility,
|
|
114
|
+
}}
|
|
115
|
+
>
|
|
116
|
+
{this.props.children}
|
|
117
|
+
</DrawerContext.Provider>
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return null
|
|
124
|
+
}
|
|
125
|
+
}
|