@automattic/charts 4.2.0 → 4.4.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/CHANGELOG.md +28 -0
- package/dist/index.cjs +533 -127
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -2
- package/dist/index.d.ts +27 -2
- package/dist/index.js +535 -129
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/charts/area-chart/area-chart.tsx +42 -10
- package/src/charts/area-chart/private/validate-data.ts +2 -3
- package/src/charts/area-chart/test/area-chart.test.tsx +72 -1
- package/src/charts/bar-chart/bar-chart.tsx +135 -96
- package/src/charts/bar-chart/index.ts +1 -1
- package/src/charts/bar-chart/private/band-highlight.tsx +3 -1
- package/src/charts/bar-chart/private/band-tooltip.tsx +1 -1
- package/src/charts/bar-chart/private/classified-bar-series.tsx +85 -0
- package/src/charts/bar-chart/private/comparison-bars-geometry.ts +3 -6
- package/src/charts/bar-chart/private/index.ts +2 -0
- package/src/charts/bar-chart/private/test/band-highlight.test.tsx +28 -2
- package/src/charts/bar-chart/private/test/comparison-bars-geometry.test.ts +2 -3
- package/src/charts/bar-chart/private/test/value-domain.test.ts +100 -0
- package/src/charts/bar-chart/private/use-bar-chart-options.ts +12 -39
- package/src/charts/bar-chart/private/value-domain.ts +90 -0
- package/src/charts/bar-chart/test/bar-chart.test.tsx +614 -10
- package/src/charts/bar-chart/types.ts +43 -0
- package/src/charts/line-chart/line-chart.tsx +148 -35
- package/src/charts/line-chart/private/index.ts +1 -0
- package/src/charts/line-chart/private/line-chart-glyph.tsx +17 -3
- package/src/charts/line-chart/private/nearest-pointer-events.tsx +155 -0
- package/src/charts/line-chart/test/line-chart.test.tsx +604 -9
- package/src/charts/line-chart/types.ts +2 -1
- package/src/charts/private/readings.ts +34 -0
- package/src/charts/private/test/readings.test.ts +29 -0
- package/src/charts/private/test/whole-number-ticks.test.tsx +57 -0
- package/src/charts/private/whole-number-ticks.tsx +79 -0
- package/src/components/legend/hooks/test/use-chart-legend-items.test.tsx +124 -0
- package/src/components/legend/hooks/use-chart-legend-items.ts +60 -2
- package/src/components/legend/private/base-legend.tsx +36 -21
- package/src/components/legend/test/legend.test.tsx +84 -0
- package/src/components/legend/types.ts +2 -0
- package/src/components/legend/utils/index.ts +0 -1
- package/src/components/tooltip/accessible-tooltip.tsx +1 -1
- package/src/hooks/test/use-chart-margin.test.tsx +35 -0
- package/src/hooks/use-chart-margin.tsx +7 -2
- package/src/providers/chart-context/global-charts-provider.tsx +1 -1
- package/src/providers/chart-context/test/chart-context.test.tsx +4 -4
- package/src/types.ts +8 -0
- package/src/components/legend/utils/label-transform-factory.ts +0 -24
|
@@ -353,6 +353,41 @@ describe( 'useChartMargin', () => {
|
|
|
353
353
|
|
|
354
354
|
expect( result.current.left ).toBe( 20 );
|
|
355
355
|
} );
|
|
356
|
+
|
|
357
|
+
it( 'measures ticks from readings that exist', () => {
|
|
358
|
+
const partialData = [
|
|
359
|
+
{
|
|
360
|
+
label: 'Series 1',
|
|
361
|
+
data: [
|
|
362
|
+
{ date: new Date( '2024-01-01' ), value: null },
|
|
363
|
+
{ date: new Date( '2024-01-02' ), value: 100 },
|
|
364
|
+
{ date: new Date( '2024-01-03' ), value: 200 },
|
|
365
|
+
],
|
|
366
|
+
},
|
|
367
|
+
];
|
|
368
|
+
|
|
369
|
+
renderHook( () => useChartMargin( 300, optionsBase, partialData, baseTheme ) );
|
|
370
|
+
|
|
371
|
+
const ticks = mockGetLongestTickWidth.mock.calls[ 0 ][ 0 ] as number[];
|
|
372
|
+
expect( Math.min( ...ticks ) ).toBe( 100 );
|
|
373
|
+
} );
|
|
374
|
+
|
|
375
|
+
it( 'measures a unit range when no bucket has a reading', () => {
|
|
376
|
+
const allNullData = [
|
|
377
|
+
{
|
|
378
|
+
label: 'Series 1',
|
|
379
|
+
data: [
|
|
380
|
+
{ date: new Date( '2024-01-01' ), value: null },
|
|
381
|
+
{ date: new Date( '2024-01-02' ), value: null },
|
|
382
|
+
],
|
|
383
|
+
},
|
|
384
|
+
];
|
|
385
|
+
|
|
386
|
+
renderHook( () => useChartMargin( 300, optionsBase, allNullData, baseTheme ) );
|
|
387
|
+
|
|
388
|
+
const ticks = mockGetLongestTickWidth.mock.calls[ 0 ][ 0 ] as number[];
|
|
389
|
+
expect( Math.max( ...ticks ) ).toBe( 1 );
|
|
390
|
+
} );
|
|
356
391
|
} );
|
|
357
392
|
|
|
358
393
|
describe( 'horizontal y ticks', () => {
|
|
@@ -111,8 +111,13 @@ export const useChartMargin = (
|
|
|
111
111
|
return options.axis.y.tickValues;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
const
|
|
115
|
-
|
|
114
|
+
const values = allDataPoints
|
|
115
|
+
.map( d => d.value )
|
|
116
|
+
.filter(
|
|
117
|
+
( value ): value is number => typeof value === 'number' && Number.isFinite( value )
|
|
118
|
+
);
|
|
119
|
+
const minY = values.length ? Math.min( ...values ) : 0;
|
|
120
|
+
const maxY = values.length ? Math.max( ...values ) : 1;
|
|
116
121
|
const yScale = createScale( {
|
|
117
122
|
...options.yScale,
|
|
118
123
|
// A pinned domain is what the axis actually renders, so measure those
|
|
@@ -219,7 +219,7 @@ export const GlobalChartsProvider: FC< GlobalChartsProviderProps > = ( {
|
|
|
219
219
|
|
|
220
220
|
const getElementStyles = useCallback< GlobalChartsContextValue[ 'getElementStyles' ] >(
|
|
221
221
|
( { data, index, overrideColor, legendShape } ) => {
|
|
222
|
-
const isSeriesData = data && typeof data === 'object' && 'data' in data
|
|
222
|
+
const isSeriesData = data && typeof data === 'object' && 'data' in data;
|
|
223
223
|
// DataPointPercentage has a numeric 'value' directly, unlike SeriesData which has 'data' array
|
|
224
224
|
const isPointPercentageData =
|
|
225
225
|
data &&
|
|
@@ -1318,11 +1318,11 @@ describe( 'ChartContext', () => {
|
|
|
1318
1318
|
expect( styles ).toHaveProperty( 'glyph' );
|
|
1319
1319
|
expect( styles ).toHaveProperty( 'shapeStyles' );
|
|
1320
1320
|
|
|
1321
|
-
//
|
|
1321
|
+
// A series without an `options` key is still a series, so theme styles apply.
|
|
1322
1322
|
expect( typeof styles.color ).toBe( 'string' );
|
|
1323
|
-
expect(
|
|
1324
|
-
expect(
|
|
1325
|
-
expect(
|
|
1323
|
+
expect( styles.lineStyles ).toEqual( { strokeWidth: 2 } );
|
|
1324
|
+
expect( styles.glyph ).toBe( mockGlyph );
|
|
1325
|
+
expect( styles.shapeStyles ).toEqual( { fill: '#SHAPE1' } );
|
|
1326
1326
|
} );
|
|
1327
1327
|
|
|
1328
1328
|
it( 'returns complete ElementStyles object for DataPointPercentage', () => {
|
package/src/types.ts
CHANGED
|
@@ -134,6 +134,7 @@ export type ThemeAnnotationStyles = {
|
|
|
134
134
|
export type DataPoint = {
|
|
135
135
|
label: string;
|
|
136
136
|
value: number;
|
|
137
|
+
/** Per-point fill override for BarChart; other built-in charts ignore it. */
|
|
137
138
|
color?: string;
|
|
138
139
|
};
|
|
139
140
|
|
|
@@ -186,6 +187,7 @@ export type DataPointDate = {
|
|
|
186
187
|
dateString?: string;
|
|
187
188
|
value: number | null;
|
|
188
189
|
label?: string;
|
|
190
|
+
/** Per-point fill override for BarChart; other built-in charts ignore it. */
|
|
189
191
|
color?: string;
|
|
190
192
|
};
|
|
191
193
|
|
|
@@ -650,6 +652,12 @@ export type SeriesChartLegendConfig = ChartLegendConfig< SeriesData[] > & {
|
|
|
650
652
|
* uncollapsed one toggles only its own.
|
|
651
653
|
*/
|
|
652
654
|
collapseGroups?: boolean;
|
|
655
|
+
/**
|
|
656
|
+
* Append a static, non-interactive item explaining the comparison overlay whenever a series
|
|
657
|
+
* has `options.type === 'comparison'`. Skipped when that series already has its own item.
|
|
658
|
+
* Pass a string to replace the default label.
|
|
659
|
+
*/
|
|
660
|
+
comparisonItem?: boolean | string;
|
|
653
661
|
};
|
|
654
662
|
|
|
655
663
|
/**
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { ItemTransformer, LabelFormatter } from '@visx/legend';
|
|
2
|
-
import type { AnyD3Scale, ScaleInput } from '@visx/scale';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Returns a function which takes a Datum and index as input, and returns a formatted label object.
|
|
6
|
-
* @param {object} root0 - The object to return the value of.
|
|
7
|
-
* @param {AnyD3Scale} root0.scale - The scale to use.
|
|
8
|
-
* @param {LabelFormatter<ScaleInput<Scale>>} root0.labelFormat - The label format to use.
|
|
9
|
-
* @return {ItemTransformer<ScaleInput<Scale>, ReturnType<Scale>>} The label transform factory.
|
|
10
|
-
*/
|
|
11
|
-
export function labelTransformFactory< Scale extends AnyD3Scale >( {
|
|
12
|
-
scale,
|
|
13
|
-
labelFormat,
|
|
14
|
-
}: {
|
|
15
|
-
scale: Scale;
|
|
16
|
-
labelFormat: LabelFormatter< ScaleInput< Scale > >;
|
|
17
|
-
} ): ItemTransformer< ScaleInput< Scale >, ReturnType< Scale > > {
|
|
18
|
-
return ( d, i ) => ( {
|
|
19
|
-
datum: d,
|
|
20
|
-
index: i,
|
|
21
|
-
text: `${ labelFormat( d, i ) }`,
|
|
22
|
-
value: scale( d ),
|
|
23
|
-
} );
|
|
24
|
-
}
|