@neo4j-ndl/react-charts 1.3.18 → 1.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/lib/cjs/charts/ChartTooltip.js +6 -2
- package/lib/cjs/charts/ChartTooltip.js.map +1 -1
- package/lib/cjs/charts/hooks/use-chart-option.js +6 -0
- package/lib/cjs/charts/hooks/use-chart-option.js.map +1 -1
- package/lib/cjs/charts/hooks/use-legend-series.js +7 -1
- package/lib/cjs/charts/hooks/use-legend-series.js.map +1 -1
- package/lib/cjs/charts/index.js.map +1 -1
- package/lib/cjs/charts/tests/chart-test-utils.js +121 -1
- package/lib/cjs/charts/tests/chart-test-utils.js.map +1 -1
- package/lib/cjs/charts/utils/build-chart-option.js +39 -4
- package/lib/cjs/charts/utils/build-chart-option.js.map +1 -1
- package/lib/cjs/charts/utils/chart-tooltip-formatter.js +93 -0
- package/lib/cjs/charts/utils/chart-tooltip-formatter.js.map +1 -1
- package/lib/cjs/charts/utils/defaults.js +18 -1
- package/lib/cjs/charts/utils/defaults.js.map +1 -1
- package/lib/cjs/charts/utils/legend-utils.js +7 -2
- package/lib/cjs/charts/utils/legend-utils.js.map +1 -1
- package/lib/cjs/charts/utils/scatter-tooltip-points.js +301 -0
- package/lib/cjs/charts/utils/scatter-tooltip-points.js.map +1 -0
- package/lib/cjs/charts/utils/user-option-utils.js +16 -6
- package/lib/cjs/charts/utils/user-option-utils.js.map +1 -1
- package/lib/esm/charts/ChartTooltip.js +6 -2
- package/lib/esm/charts/ChartTooltip.js.map +1 -1
- package/lib/esm/charts/hooks/use-chart-option.js +6 -0
- package/lib/esm/charts/hooks/use-chart-option.js.map +1 -1
- package/lib/esm/charts/hooks/use-legend-series.js +7 -1
- package/lib/esm/charts/hooks/use-legend-series.js.map +1 -1
- package/lib/esm/charts/index.js.map +1 -1
- package/lib/esm/charts/tests/chart-test-utils.js +115 -0
- package/lib/esm/charts/tests/chart-test-utils.js.map +1 -1
- package/lib/esm/charts/utils/build-chart-option.js +40 -5
- package/lib/esm/charts/utils/build-chart-option.js.map +1 -1
- package/lib/esm/charts/utils/chart-tooltip-formatter.js +92 -0
- package/lib/esm/charts/utils/chart-tooltip-formatter.js.map +1 -1
- package/lib/esm/charts/utils/defaults.js +16 -1
- package/lib/esm/charts/utils/defaults.js.map +1 -1
- package/lib/esm/charts/utils/legend-utils.js +7 -2
- package/lib/esm/charts/utils/legend-utils.js.map +1 -1
- package/lib/esm/charts/utils/scatter-tooltip-points.js +291 -0
- package/lib/esm/charts/utils/scatter-tooltip-points.js.map +1 -0
- package/lib/esm/charts/utils/user-option-utils.js +17 -7
- package/lib/esm/charts/utils/user-option-utils.js.map +1 -1
- package/lib/types/charts/ChartTooltip.d.ts +6 -1
- package/lib/types/charts/ChartTooltip.d.ts.map +1 -1
- package/lib/types/charts/hooks/use-chart-option.d.ts.map +1 -1
- package/lib/types/charts/hooks/use-legend-series.d.ts.map +1 -1
- package/lib/types/charts/index.d.ts +1 -0
- package/lib/types/charts/index.d.ts.map +1 -1
- package/lib/types/charts/tests/chart-test-utils.d.ts +78 -0
- package/lib/types/charts/tests/chart-test-utils.d.ts.map +1 -1
- package/lib/types/charts/utils/build-chart-option.d.ts +4 -1
- package/lib/types/charts/utils/build-chart-option.d.ts.map +1 -1
- package/lib/types/charts/utils/chart-tooltip-formatter.d.ts +45 -2
- package/lib/types/charts/utils/chart-tooltip-formatter.d.ts.map +1 -1
- package/lib/types/charts/utils/defaults.d.ts +10 -1
- package/lib/types/charts/utils/defaults.d.ts.map +1 -1
- package/lib/types/charts/utils/legend-utils.d.ts.map +1 -1
- package/lib/types/charts/utils/scatter-tooltip-points.d.ts +84 -0
- package/lib/types/charts/utils/scatter-tooltip-points.d.ts.map +1 -0
- package/lib/types/charts/utils/user-option-utils.d.ts.map +1 -1
- package/package.json +3 -3
- package/skills/ndl-react-charts/SKILL.md +3 -3
- package/skills/ndl-react-charts/components/charts.md +279 -0
|
@@ -1853,6 +1853,285 @@ const Component = () => {
|
|
|
1853
1853
|
export default Component;
|
|
1854
1854
|
```
|
|
1855
1855
|
|
|
1856
|
+
### Scatter
|
|
1857
|
+
|
|
1858
|
+
```tsx
|
|
1859
|
+
import { Chart, type TooltipValueContext } from '@neo4j-ndl/react-charts';
|
|
1860
|
+
|
|
1861
|
+
const Component = () => {
|
|
1862
|
+
return (
|
|
1863
|
+
// The Chart component requires its parent to have an explicit height.
|
|
1864
|
+
// Without one the chart canvas collapses to 0px and nothing renders.
|
|
1865
|
+
// You can also check the components documentation by hovering over it.
|
|
1866
|
+
<div
|
|
1867
|
+
style={{
|
|
1868
|
+
border: '1px solid silver',
|
|
1869
|
+
borderRadius: '10px',
|
|
1870
|
+
height: '350px',
|
|
1871
|
+
padding: '20px',
|
|
1872
|
+
width: '100%',
|
|
1873
|
+
}}
|
|
1874
|
+
>
|
|
1875
|
+
<Chart
|
|
1876
|
+
legend={{
|
|
1877
|
+
show: true,
|
|
1878
|
+
}}
|
|
1879
|
+
dataset={[
|
|
1880
|
+
{
|
|
1881
|
+
source: [
|
|
1882
|
+
['x', 'y', 'label', 'id'],
|
|
1883
|
+
[10, 8.04, 'Checkout', 'A-1'],
|
|
1884
|
+
[8, 6.95, 'Search', 'A-2'],
|
|
1885
|
+
[13, 7.58, 'Catalog', 'A-3'],
|
|
1886
|
+
[9, 8.81, 'Cart', 'A-4'],
|
|
1887
|
+
[11, 8.33, 'Profile', 'A-5'],
|
|
1888
|
+
[14, 9.96, 'Recommendations', 'A-6'],
|
|
1889
|
+
[6, 7.24, 'Login', 'A-7'],
|
|
1890
|
+
[4, 4.26, 'Signup', 'A-8'],
|
|
1891
|
+
[12, 10.84, 'Billing', 'A-9'],
|
|
1892
|
+
[7, 4.82, 'Settings', 'A-10'],
|
|
1893
|
+
[5, 5.68, 'Support', 'A-11'],
|
|
1894
|
+
// Sits on top of A-9, so hovering there lists both points.
|
|
1895
|
+
[12.05, 10.8, 'Invoices', 'A-12'],
|
|
1896
|
+
// Shares A-2's coordinates exactly, which the tooltip lists as
|
|
1897
|
+
// two separate points.
|
|
1898
|
+
[8, 6.95, 'Search retry', 'A-13'],
|
|
1899
|
+
],
|
|
1900
|
+
},
|
|
1901
|
+
{
|
|
1902
|
+
source: [
|
|
1903
|
+
['x', 'y', 'label', 'id'],
|
|
1904
|
+
[12, 3.1, 'Cache miss', 'B-1'],
|
|
1905
|
+
[5, 9.13, 'Index scan', 'B-2'],
|
|
1906
|
+
[7, 7.26, 'Planner', 'B-3'],
|
|
1907
|
+
[11, 4.74, 'Page fault', 'B-4'],
|
|
1908
|
+
[3, 7.46, 'Lock wait', 'B-5'],
|
|
1909
|
+
[8, 6.77, 'Commit', 'B-6'],
|
|
1910
|
+
[14, 5.13, 'Replication', 'B-7'],
|
|
1911
|
+
[9, 8.14, 'Compaction', 'B-8'],
|
|
1912
|
+
[6, 6.08, 'Flush', 'B-9'],
|
|
1913
|
+
[10, 5.39, 'Checkpoint', 'B-10'],
|
|
1914
|
+
[4, 8.1, 'Recovery', 'B-11'],
|
|
1915
|
+
],
|
|
1916
|
+
},
|
|
1917
|
+
]}
|
|
1918
|
+
series={[
|
|
1919
|
+
{
|
|
1920
|
+
datasetIndex: 0,
|
|
1921
|
+
// encode.tooltip picks the column that titles the tooltip. `id`
|
|
1922
|
+
// comes after `label` here, so the title only shows the id when
|
|
1923
|
+
// encode.tooltip is honored.
|
|
1924
|
+
// https://echarts.apache.org/en/option.html#series-scatter.encode
|
|
1925
|
+
encode: {
|
|
1926
|
+
tooltip: 'id',
|
|
1927
|
+
// oxlint-disable-next-line id-length
|
|
1928
|
+
x: 'x',
|
|
1929
|
+
// oxlint-disable-next-line id-length
|
|
1930
|
+
y: 'y',
|
|
1931
|
+
},
|
|
1932
|
+
name: 'Group A',
|
|
1933
|
+
type: 'scatter',
|
|
1934
|
+
},
|
|
1935
|
+
{
|
|
1936
|
+
datasetIndex: 1,
|
|
1937
|
+
encode: {
|
|
1938
|
+
tooltip: 'id',
|
|
1939
|
+
// oxlint-disable-next-line id-length
|
|
1940
|
+
x: 'x',
|
|
1941
|
+
// oxlint-disable-next-line id-length
|
|
1942
|
+
y: 'y',
|
|
1943
|
+
},
|
|
1944
|
+
name: 'Group B',
|
|
1945
|
+
type: 'scatter',
|
|
1946
|
+
},
|
|
1947
|
+
{
|
|
1948
|
+
data: [
|
|
1949
|
+
[1, 10],
|
|
1950
|
+
[2, 20],
|
|
1951
|
+
[3, 30],
|
|
1952
|
+
[4, 40],
|
|
1953
|
+
[5, 50],
|
|
1954
|
+
[6, 60],
|
|
1955
|
+
],
|
|
1956
|
+
// No point identifier, so the tooltip is titled with the series name.
|
|
1957
|
+
name: 'Group C',
|
|
1958
|
+
type: 'scatter',
|
|
1959
|
+
},
|
|
1960
|
+
]}
|
|
1961
|
+
xAxis={{
|
|
1962
|
+
// The axis name labels the matching row in the scatter tooltip.
|
|
1963
|
+
name: 'Concurrent queries',
|
|
1964
|
+
type: 'value',
|
|
1965
|
+
}}
|
|
1966
|
+
yAxis={{
|
|
1967
|
+
name: 'Latency',
|
|
1968
|
+
type: 'value',
|
|
1969
|
+
}}
|
|
1970
|
+
option={{
|
|
1971
|
+
tooltip: {
|
|
1972
|
+
// `valueFormatter` formats the x and y values only. The third
|
|
1973
|
+
// argument is the axis, so this one adds the unit to latency. The
|
|
1974
|
+
// point id in the title is shown unchanged.
|
|
1975
|
+
valueFormatter: (
|
|
1976
|
+
value: number,
|
|
1977
|
+
_dataIndex?: number,
|
|
1978
|
+
context?: TooltipValueContext,
|
|
1979
|
+
) => (context?.axis === 'y' ? `${value} ms` : `${value}`),
|
|
1980
|
+
},
|
|
1981
|
+
}}
|
|
1982
|
+
/>
|
|
1983
|
+
</div>
|
|
1984
|
+
);
|
|
1985
|
+
};
|
|
1986
|
+
|
|
1987
|
+
export default Component;
|
|
1988
|
+
```
|
|
1989
|
+
|
|
1990
|
+
### Scatter Large
|
|
1991
|
+
|
|
1992
|
+
```tsx
|
|
1993
|
+
import { Chart, type TooltipValueContext } from '@neo4j-ndl/react-charts';
|
|
1994
|
+
|
|
1995
|
+
const POINT_COUNT = 20_000;
|
|
1996
|
+
const SERIES_COUNT = 2;
|
|
1997
|
+
const POINTS_PER_SERIES = POINT_COUNT / SERIES_COUNT;
|
|
1998
|
+
|
|
1999
|
+
/**
|
|
2000
|
+
* Deterministic 0–1 values so the chart looks the same on every Storybook
|
|
2001
|
+
* load, without shipping twenty thousand hardcoded rows.
|
|
2002
|
+
*/
|
|
2003
|
+
const createSeededRandom = (seed: number) => {
|
|
2004
|
+
let next = seed;
|
|
2005
|
+
|
|
2006
|
+
return () => {
|
|
2007
|
+
next = (Math.imul(next, 1664525) + 1013904223) >>> 0;
|
|
2008
|
+
|
|
2009
|
+
return next / 4_294_967_296;
|
|
2010
|
+
};
|
|
2011
|
+
};
|
|
2012
|
+
|
|
2013
|
+
const roundToTwo = (value: number) => Math.round(value * 100) / 100;
|
|
2014
|
+
|
|
2015
|
+
/**
|
|
2016
|
+
* Standard normal sample from a uniform generator (Box–Muller), so y can sit
|
|
2017
|
+
* on a bell instead of filling the plot evenly.
|
|
2018
|
+
*/
|
|
2019
|
+
const nextStandardNormal = (random: () => number) => {
|
|
2020
|
+
const uniform = Math.max(random(), Number.EPSILON);
|
|
2021
|
+
const angle = random();
|
|
2022
|
+
|
|
2023
|
+
return Math.sqrt(-2 * Math.log(uniform)) * Math.cos(2 * Math.PI * angle);
|
|
2024
|
+
};
|
|
2025
|
+
|
|
2026
|
+
const scatterEncode = {
|
|
2027
|
+
tooltip: 'id',
|
|
2028
|
+
// oxlint-disable-next-line id-length
|
|
2029
|
+
x: 'x',
|
|
2030
|
+
// oxlint-disable-next-line id-length
|
|
2031
|
+
y: 'y',
|
|
2032
|
+
};
|
|
2033
|
+
|
|
2034
|
+
const BELL_BASELINE = 8;
|
|
2035
|
+
const BELL_HEIGHT = 72;
|
|
2036
|
+
const BELL_WIDTH = 16;
|
|
2037
|
+
|
|
2038
|
+
const datasets = [
|
|
2039
|
+
{ center: 42, group: 'A' },
|
|
2040
|
+
{ center: 58, group: 'B' },
|
|
2041
|
+
].map(({ center, group }, seriesIndex) => {
|
|
2042
|
+
const random = createSeededRandom(seriesIndex + 1);
|
|
2043
|
+
const source: Array<[string, number, number] | ['id', 'x', 'y']> = [
|
|
2044
|
+
['id', 'x', 'y'],
|
|
2045
|
+
];
|
|
2046
|
+
|
|
2047
|
+
for (let index = 0; index < POINTS_PER_SERIES - 3; index += 1) {
|
|
2048
|
+
const xValue = random() * 100;
|
|
2049
|
+
const bell =
|
|
2050
|
+
BELL_BASELINE +
|
|
2051
|
+
BELL_HEIGHT * Math.exp(-((xValue - center) ** 2) / (2 * BELL_WIDTH ** 2));
|
|
2052
|
+
const yValue = Math.max(0, bell + nextStandardNormal(random) * 4);
|
|
2053
|
+
|
|
2054
|
+
source.push([
|
|
2055
|
+
`${group}-${index + 1}`,
|
|
2056
|
+
roundToTwo(xValue),
|
|
2057
|
+
roundToTwo(yValue),
|
|
2058
|
+
]);
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
const peak = roundToTwo(BELL_BASELINE + BELL_HEIGHT);
|
|
2062
|
+
|
|
2063
|
+
// A known cluster on the crest so hovering there lists several points,
|
|
2064
|
+
// including an exact duplicate.
|
|
2065
|
+
source.push(
|
|
2066
|
+
[`${group}-overlap-1`, center, peak],
|
|
2067
|
+
[`${group}-overlap-2`, roundToTwo(center + 0.08), roundToTwo(peak - 0.05)],
|
|
2068
|
+
[`${group}-overlap-3`, center, peak],
|
|
2069
|
+
);
|
|
2070
|
+
|
|
2071
|
+
return { source };
|
|
2072
|
+
});
|
|
2073
|
+
|
|
2074
|
+
const Component = () => {
|
|
2075
|
+
return (
|
|
2076
|
+
// The Chart component requires its parent to have an explicit height.
|
|
2077
|
+
// Without one the chart canvas collapses to 0px and nothing renders.
|
|
2078
|
+
// You can also check the components documentation by hovering over it.
|
|
2079
|
+
<div
|
|
2080
|
+
style={{
|
|
2081
|
+
border: '1px solid silver',
|
|
2082
|
+
borderRadius: '10px',
|
|
2083
|
+
height: '350px',
|
|
2084
|
+
padding: '20px',
|
|
2085
|
+
width: '100%',
|
|
2086
|
+
}}
|
|
2087
|
+
>
|
|
2088
|
+
<Chart
|
|
2089
|
+
legend={{
|
|
2090
|
+
show: true,
|
|
2091
|
+
}}
|
|
2092
|
+
dataset={datasets}
|
|
2093
|
+
series={[
|
|
2094
|
+
{
|
|
2095
|
+
datasetIndex: 0,
|
|
2096
|
+
encode: scatterEncode,
|
|
2097
|
+
name: 'Group A',
|
|
2098
|
+
type: 'scatter',
|
|
2099
|
+
},
|
|
2100
|
+
{
|
|
2101
|
+
datasetIndex: 1,
|
|
2102
|
+
encode: scatterEncode,
|
|
2103
|
+
name: 'Group B',
|
|
2104
|
+
type: 'scatter',
|
|
2105
|
+
},
|
|
2106
|
+
]}
|
|
2107
|
+
xAxis={{
|
|
2108
|
+
name: 'Concurrent queries',
|
|
2109
|
+
type: 'value',
|
|
2110
|
+
}}
|
|
2111
|
+
yAxis={{
|
|
2112
|
+
name: 'Latency',
|
|
2113
|
+
type: 'value',
|
|
2114
|
+
}}
|
|
2115
|
+
option={{
|
|
2116
|
+
tooltip: {
|
|
2117
|
+
// `valueFormatter` formats the x and y values only. The third
|
|
2118
|
+
// argument is the axis, so this one adds the unit to latency. The
|
|
2119
|
+
// point id in the title is shown unchanged.
|
|
2120
|
+
valueFormatter: (
|
|
2121
|
+
value: number,
|
|
2122
|
+
_dataIndex?: number,
|
|
2123
|
+
context?: TooltipValueContext,
|
|
2124
|
+
) => (context?.axis === 'y' ? `${value} ms` : `${value}`),
|
|
2125
|
+
},
|
|
2126
|
+
}}
|
|
2127
|
+
/>
|
|
2128
|
+
</div>
|
|
2129
|
+
);
|
|
2130
|
+
};
|
|
2131
|
+
|
|
2132
|
+
export default Component;
|
|
2133
|
+
```
|
|
2134
|
+
|
|
1856
2135
|
### Slider
|
|
1857
2136
|
|
|
1858
2137
|
```tsx
|