-
Notifications
You must be signed in to change notification settings - Fork 843
Charts: Update GeoChart to support Google Charts native data format with custom tooltips #46330
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
717c791
4066ba5
46875ed
c975f51
2b18d51
3d78026
e98ebd9
282ab62
a0b62d6
101e4a6
9332e0d
e665340
7898111
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| Significance: minor | ||
| Type: changed | ||
|
|
||
| Change Geo Chart data format to handle all Google Charts data | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,7 +3,7 @@ | |
| */ | ||
| import { __ } from '@wordpress/i18n'; | ||
| import clsx from 'clsx'; | ||
| import { FC, useContext } from 'react'; | ||
| import { FC, useContext, useMemo } from 'react'; | ||
| import { Chart, type GoogleChartOptions } from 'react-google-charts'; | ||
| /** | ||
| * Internal dependencies | ||
|
|
@@ -21,8 +21,14 @@ const DEFAULT_BACKGROUND_COLOR = '#ffffff'; | |
| /** | ||
| * Renders a geographical chart using Google Charts GeoChart to visualize data by country. | ||
| * | ||
| * Supports the full Google Charts data format including custom tooltips, formatted values, | ||
| * and multiple data columns for maximum flexibility. | ||
| * | ||
| * Countries can be identified by full name (e.g., 'United States') or ISO 3166-1 alpha-2 | ||
| * codes (e.g., 'US'). Full names are recommended for better readability in tooltips. | ||
| * | ||
| * @param props - The props for the GeoChart component | ||
| * @param props.data - Record mapping country IDs to numeric values | ||
| * @param props.data - Data in Google Charts format (array of arrays with headers) | ||
| * @param props.width - Width of the chart in pixels | ||
| * @param props.height - Height of the chart in pixels | ||
| * @param props.className - Additional CSS class name for the chart container | ||
|
|
@@ -64,20 +70,37 @@ const GeoChartInternal: FC< GeoChartProps > = ( { | |
| const defaultFillColorHex = | ||
| normalizeColorToHex( featureFillColor, null, resolveCssVariable ) || DEFAULT_FEATURE_FILL_COLOR; | ||
|
|
||
| // Transform data from Record<string, number> to Google Charts format | ||
| // Google Charts expects [['Country', 'Value'], ['US', 100], ['CA', 50], ...] | ||
| // Country codes must be ISO 3166-1 alpha-2 format (2-letter codes) | ||
| const chartData = [ [ 'Country', 'Value' ], ...Object.entries( data ) ]; | ||
| // Check if data has HTML tooltips (column with role: 'tooltip' and p.html: true) | ||
| const hasHtmlTooltips = useMemo( | ||
| () => | ||
| data.length > 0 && | ||
| data[ 0 ].some( | ||
| col => | ||
| typeof col === 'object' && | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible to use optional chaining to simply the conditions here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No unfortunately, due to TS. Claude's explanation: The verbose version is required because The issue: The data format allows columns to be defined as either: Why optional chaining alone doesn't work: When TypeScript sees a union type (string | object), it can't safely assume properties exist even with ?. because strings don't have those properties at all. We need the typeof check and in operator to properly narrow the type. This is the correct TypeScript pattern for type-safe property access on union types. |
||
| col !== null && | ||
| 'role' in col && | ||
| col.role === 'tooltip' && | ||
| 'p' in col && | ||
| typeof col.p === 'object' && | ||
| col.p !== null && | ||
| 'html' in col.p && | ||
| col.p.html === true | ||
| ), | ||
| [ data ] | ||
| ); | ||
|
|
||
| const options: GoogleChartOptions = { | ||
| colorAxis: { colors: [ lightColorHex, fullColorHex ] }, | ||
| backgroundColor: backgroundColorHex, | ||
| datalessRegionColor: defaultFillColorHex, | ||
| defaultColor: defaultFillColorHex, | ||
| tooltip: { trigger: 'focus' }, | ||
| legend: 'none', | ||
| keepAspectRatio: true, | ||
| }; | ||
| const options: GoogleChartOptions = useMemo( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
| () => ( { | ||
| colorAxis: { colors: [ lightColorHex, fullColorHex ] }, | ||
| backgroundColor: backgroundColorHex, | ||
| datalessRegionColor: defaultFillColorHex, | ||
| defaultColor: defaultFillColorHex, | ||
| tooltip: { trigger: 'focus', isHtml: hasHtmlTooltips }, | ||
| legend: 'none', | ||
| keepAspectRatio: true, | ||
| } ), | ||
| [ lightColorHex, fullColorHex, backgroundColorHex, defaultFillColorHex, hasHtmlTooltips ] | ||
| ); | ||
|
|
||
| return ( | ||
| <div | ||
|
|
@@ -89,7 +112,7 @@ const GeoChartInternal: FC< GeoChartProps > = ( { | |
| chartType="GeoChart" | ||
| width={ width } | ||
| height={ height } | ||
| data={ chartData } | ||
| data={ data } | ||
| options={ options } | ||
| loader={ loadingPlaceholder } | ||
| /> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| import { | ||
| chartDecorator, | ||
| sharedChartArgTypes, | ||
| ChartStoryArgs, | ||
| viewsByCountry, | ||
| themeArgTypes, | ||
| } from '../../../stories'; | ||
| import GeoChart from '../geo-chart'; | ||
| import type { Meta } from '@storybook/react'; | ||
|
|
||
| type StoryArgs = ChartStoryArgs< React.ComponentProps< typeof GeoChart > >; | ||
|
|
||
| export const geoChartMetaArgs: Meta< StoryArgs > = { | ||
| title: 'JS Packages/Charts Library/Charts/Geo Chart', | ||
| component: GeoChart, | ||
| parameters: { | ||
| layout: 'centered', | ||
| }, | ||
| decorators: [ chartDecorator ], | ||
| argTypes: { | ||
| ...sharedChartArgTypes, | ||
| ...themeArgTypes, | ||
| }, | ||
| }; | ||
|
|
||
| export const geoChartStoryArgs = { | ||
| data: viewsByCountry, | ||
| withPadding: false, | ||
| height: 500, | ||
| }; |
Uh oh!
There was an error while loading. Please reload this page.