@pharos-ds/charts 0.0.0-stage → 1.0.10-canary.2189f39
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 +73 -0
- package/LICENSE +24 -0
- package/README.md +117 -2
- package/dist/Chart.d.ts +62 -0
- package/dist/Chart.d.ts.map +1 -0
- package/dist/Chart.js +401 -0
- package/dist/ChartAxis.d.ts +37 -0
- package/dist/ChartAxis.d.ts.map +1 -0
- package/dist/ChartAxis.js +233 -0
- package/dist/ChartContext.d.ts +4 -0
- package/dist/ChartContext.d.ts.map +1 -0
- package/dist/ChartContext.js +15 -0
- package/dist/ChartGrid.d.ts +26 -0
- package/dist/ChartGrid.d.ts.map +1 -0
- package/dist/ChartGrid.js +118 -0
- package/dist/ChartLegend.d.ts +14 -0
- package/dist/ChartLegend.d.ts.map +1 -0
- package/dist/ChartLegend.js +62 -0
- package/dist/ChartSwatch.d.ts +36 -0
- package/dist/ChartSwatch.d.ts.map +1 -0
- package/dist/ChartSwatch.js +85 -0
- package/dist/ChartTooltip.d.ts +46 -0
- package/dist/ChartTooltip.d.ts.map +1 -0
- package/dist/ChartTooltip.js +330 -0
- package/dist/charts.css +33 -0
- package/dist/dataTable.d.ts +56 -0
- package/dist/dataTable.d.ts.map +1 -0
- package/dist/dataTable.js +88 -0
- package/dist/formatters.d.ts +37 -0
- package/dist/formatters.d.ts.map +1 -0
- package/dist/formatters.js +156 -0
- package/dist/getChartColors.d.ts +67 -0
- package/dist/getChartColors.d.ts.map +1 -0
- package/dist/getChartColors.js +191 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/layout.d.ts +40 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +322 -0
- package/dist/legend.d.ts +17 -0
- package/dist/legend.d.ts.map +1 -0
- package/dist/legend.js +40 -0
- package/dist/markColor.d.ts +20 -0
- package/dist/markColor.d.ts.map +1 -0
- package/dist/markColor.js +56 -0
- package/dist/marks/area.d.ts +19 -0
- package/dist/marks/area.d.ts.map +1 -0
- package/dist/marks/area.js +121 -0
- package/dist/marks/band.d.ts +9 -0
- package/dist/marks/band.d.ts.map +1 -0
- package/dist/marks/band.js +64 -0
- package/dist/marks/bar.d.ts +21 -0
- package/dist/marks/bar.d.ts.map +1 -0
- package/dist/marks/bar.js +161 -0
- package/dist/marks/candlestick.d.ts +16 -0
- package/dist/marks/candlestick.d.ts.map +1 -0
- package/dist/marks/candlestick.js +110 -0
- package/dist/marks/dot.d.ts +19 -0
- package/dist/marks/dot.d.ts.map +1 -0
- package/dist/marks/dot.js +98 -0
- package/dist/marks/dotGL.d.ts +16 -0
- package/dist/marks/dotGL.d.ts.map +1 -0
- package/dist/marks/dotGL.js +231 -0
- package/dist/marks/dotGLInteractive.d.ts +35 -0
- package/dist/marks/dotGLInteractive.d.ts.map +1 -0
- package/dist/marks/dotGLInteractive.js +584 -0
- package/dist/marks/errorBar.d.ts +29 -0
- package/dist/marks/errorBar.d.ts.map +1 -0
- package/dist/marks/errorBar.js +95 -0
- package/dist/marks/heatmapGL.d.ts +27 -0
- package/dist/marks/heatmapGL.d.ts.map +1 -0
- package/dist/marks/heatmapGL.js +335 -0
- package/dist/marks/index.d.ts +13 -0
- package/dist/marks/index.d.ts.map +1 -0
- package/dist/marks/index.js +14 -0
- package/dist/marks/line.d.ts +18 -0
- package/dist/marks/line.d.ts.map +1 -0
- package/dist/marks/line.js +83 -0
- package/dist/marks/referenceLine.d.ts +37 -0
- package/dist/marks/referenceLine.d.ts.map +1 -0
- package/dist/marks/referenceLine.js +204 -0
- package/dist/marks/streamGL.d.ts +41 -0
- package/dist/marks/streamGL.d.ts.map +1 -0
- package/dist/marks/streamGL.js +317 -0
- package/dist/tooltip.d.ts +38 -0
- package/dist/tooltip.d.ts.map +1 -0
- package/dist/tooltip.js +57 -0
- package/dist/types.d.ts +193 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +70 -0
- package/dist/useChartColors.d.ts +16 -0
- package/dist/useChartColors.d.ts.map +1 -0
- package/dist/useChartColors.js +37 -0
- package/dist/utils.d.ts +15 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +31 -0
- package/dist/webgl.d.ts +77 -0
- package/dist/webgl.d.ts.map +1 -0
- package/dist/webgl.js +235 -0
- package/package.json +71 -3
- package/src/Chart.doc.mjs +174 -0
- package/src/Chart.test.tsx +273 -0
- package/src/Chart.tsx +535 -0
- package/src/ChartAxis.tsx +289 -0
- package/src/ChartContext.ts +18 -0
- package/src/ChartGrid.tsx +136 -0
- package/src/ChartLegend.tsx +77 -0
- package/src/ChartSwatch.doc.mjs +17 -0
- package/src/ChartSwatch.tsx +89 -0
- package/src/ChartTooltip.tsx +452 -0
- package/src/charts.css.d.ts +3 -0
- package/src/dataTable.test.ts +86 -0
- package/src/dataTable.ts +124 -0
- package/src/formatters.ts +167 -0
- package/src/getChartColors.test.ts +114 -0
- package/src/getChartColors.ts +282 -0
- package/src/index.ts +88 -0
- package/src/layout.ts +372 -0
- package/src/legend.ts +44 -0
- package/src/markColor.ts +70 -0
- package/src/marks/area.tsx +142 -0
- package/src/marks/band.tsx +86 -0
- package/src/marks/bar.tsx +210 -0
- package/src/marks/candlestick.tsx +128 -0
- package/src/marks/dot.tsx +119 -0
- package/src/marks/dotGL.tsx +274 -0
- package/src/marks/dotGLInteractive.tsx +660 -0
- package/src/marks/errorBar.tsx +119 -0
- package/src/marks/heatmapGL.tsx +392 -0
- package/src/marks/index.ts +17 -0
- package/src/marks/line.tsx +118 -0
- package/src/marks/referenceLine.tsx +252 -0
- package/src/marks/streamGL.tsx +381 -0
- package/src/tooltip.ts +73 -0
- package/src/types.ts +212 -0
- package/src/useChartColors.ts +41 -0
- package/src/utils.ts +38 -0
- package/src/webgl.ts +262 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# @pharos-ds/charts
|
|
2
|
+
|
|
3
|
+
# 1.0.10
|
|
4
|
+
|
|
5
|
+
#### New Features
|
|
6
|
+
|
|
7
|
+
- `@pharos-ds/charts` passa a ser publicado no npm junto com o core (mesma versão, peer exato `@pharos-ds/core`, CSS pronto em `@pharos-ds/charts/charts.css`). O `Chart` fica acessível por padrão: SVG com `role="img"` e nome (`aria-label` → `title` → séries), `description` no `aria-describedby` e tabela de dados escondida visualmente (`dataTable`, desligável). Novo `orientation="horizontal"` para barras horizontais, com eixos e grade acompanhando.
|
|
8
|
+
|
|
9
|
+
#### Contributors
|
|
10
|
+
|
|
11
|
+
Thanks to everyone who contributed to this release:
|
|
12
|
+
|
|
13
|
+
- @Caio-Silvestre
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# 1.0.8
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# 1.0.7
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# 1.0.6
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
# 1.0.5
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
# 1.0.4
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
# 1.0.3
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
# 1.0.2
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
# 1.0.1
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
# 1.0.0
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
# 0.1.9
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
# 0.1.8
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
# 0.1.7
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
# 0.1.6
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
# 0.1.5
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
# 0.1.4
|
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Caio Silvestre
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2026 Meta Platforms, Inc.
|
|
6
|
+
(portions derived from Astryx — https://github.com/facebook/astryx)
|
|
7
|
+
|
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
10
|
+
in the Software without restriction, including without limitation the rights
|
|
11
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
13
|
+
furnished to do so, subject to the following conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be included in all
|
|
16
|
+
copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,118 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @pharos-ds/charts
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Pharos charts — a config-model data visualization library built on d3, themed by
|
|
4
|
+
Pharos tokens and accessible by default.
|
|
5
|
+
|
|
6
|
+
```tsx
|
|
7
|
+
import {Chart, ChartAxis, ChartGrid, bar, line} from '@pharos-ds/charts';
|
|
8
|
+
|
|
9
|
+
<Chart
|
|
10
|
+
title="Leads por mês"
|
|
11
|
+
description="Março teve o maior volume do trimestre."
|
|
12
|
+
data={data}
|
|
13
|
+
xKey="mes"
|
|
14
|
+
series={[bar('leads', {label: 'Leads'}), line('meta', {label: 'Meta'})]}
|
|
15
|
+
grid={<ChartGrid />}
|
|
16
|
+
axes={
|
|
17
|
+
<>
|
|
18
|
+
<ChartAxis position="bottom" />
|
|
19
|
+
<ChartAxis position="left" />
|
|
20
|
+
</>
|
|
21
|
+
}
|
|
22
|
+
legend
|
|
23
|
+
tooltip
|
|
24
|
+
/>;
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Marks are factory functions (`bar`, `line`, `area`, `dot`, `band`, `candlestick`,
|
|
28
|
+
`errorBar`, `referenceLine`, and WebGL variants) that return config objects passed
|
|
29
|
+
via the `series` prop. The chart root owns **one** x/y scale that every mark, axis,
|
|
30
|
+
and grid line reads, so they can never disagree.
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
`@pharos-ds/charts` is versioned together with `@pharos-ds/core` (same version
|
|
35
|
+
number, exact peer). Install matching versions:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install @pharos-ds/charts@1.0.x @pharos-ds/core@1.0.x @stylexjs/stylex
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Peers: `@pharos-ds/core` (exact version), `@stylexjs/stylex` (runtime only — no
|
|
42
|
+
compiler needed), `react` and `react-dom` ≥ 19.
|
|
43
|
+
|
|
44
|
+
## Styles
|
|
45
|
+
|
|
46
|
+
The package ships prebuilt CSS, the same way core does. Import it once, after
|
|
47
|
+
core's stylesheet — no StyleX compiler is needed in your app:
|
|
48
|
+
|
|
49
|
+
```css
|
|
50
|
+
@import '@pharos-ds/core/pharos.css';
|
|
51
|
+
@import '@pharos-ds/theme-pharos/theme.css';
|
|
52
|
+
@import '@pharos-ds/charts/charts.css';
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Render charts inside core's `<Theme>` (e.g. with `pharosTheme`). Series without
|
|
56
|
+
an explicit `color` take the theme's categorical palette in order — for Pharos:
|
|
57
|
+
azul, roxo, laranja, amarelo, chumbo — resolved for the active light/dark mode.
|
|
58
|
+
|
|
59
|
+
`Chart` is a client component (`'use client'`): it measures its container, so the
|
|
60
|
+
plot draws after hydration. The hidden data table is part of the server HTML.
|
|
61
|
+
|
|
62
|
+
## Horizontal bars
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
<Chart
|
|
66
|
+
title="Leads por canal"
|
|
67
|
+
orientation="horizontal"
|
|
68
|
+
data={porCanal}
|
|
69
|
+
xKey="canal"
|
|
70
|
+
series={[bar('leads', {label: 'Leads'})]}
|
|
71
|
+
margin={{left: 96}}
|
|
72
|
+
grid={<ChartGrid />}
|
|
73
|
+
axes={
|
|
74
|
+
<>
|
|
75
|
+
<ChartAxis position="left" />
|
|
76
|
+
<ChartAxis position="bottom" />
|
|
77
|
+
</>
|
|
78
|
+
}
|
|
79
|
+
tooltip
|
|
80
|
+
/>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Categories go on the y-axis and values grow to the right. The grid follows the
|
|
84
|
+
value axis by default. Use the `tooltip` prop (not a `ChartTooltip` child) in
|
|
85
|
+
horizontal charts.
|
|
86
|
+
|
|
87
|
+
## Accessibility
|
|
88
|
+
|
|
89
|
+
Every chart is exposed as one image with a text alternative (WCAG 1.1.1):
|
|
90
|
+
|
|
91
|
+
- The SVG has `role="img"` and an accessible name: `aria-label` → `title` → the
|
|
92
|
+
data series labels.
|
|
93
|
+
- `subtitle` and `description` become the image description (`aria-describedby`).
|
|
94
|
+
Use `description` for the takeaway.
|
|
95
|
+
- A visually hidden `<table>` is generated from `data`: caption = accessible name,
|
|
96
|
+
header row = x label + series labels, one row per x value. Utility marks
|
|
97
|
+
(`band`, `errorBar`, `referenceLine`) get no column. Customize with
|
|
98
|
+
`dataTable={{xLabel, formatX, formatValue, maxRows}}`, or opt out with
|
|
99
|
+
`dataTable={false}` when the same data is already on the page as a table. Charts
|
|
100
|
+
with more than `maxRows` rows (default 1000) skip the table.
|
|
101
|
+
- Grid, marks and axes are `aria-hidden`.
|
|
102
|
+
- The tooltip is pointer-only: it is never focusable and never traps focus.
|
|
103
|
+
There is no keyboard tooltip; keyboard and screen-reader users get the values
|
|
104
|
+
from the data table.
|
|
105
|
+
|
|
106
|
+
## Development
|
|
107
|
+
|
|
108
|
+
Inside the monorepo (storybook/sandbox), imports resolve via pnpm workspaces.
|
|
109
|
+
Stories live in `apps/storybook/stories/charts/`. Run the tests with:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
corepack pnpm exec vitest run packages/charts
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
> Note: this package is the successor to the experimental `Chart` (formerly
|
|
116
|
+
> `ChartV2`) that used to live in `@pharos-ds/lab`; that code has moved here and
|
|
117
|
+
> d3 is a direct dependency. See the repo-root `docs/CHARTV2_*` docs for the
|
|
118
|
+
> original plan and verification checklist.
|
package/dist/Chart.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { SeriesDef, YBaseline, ChartOrientation } from './types';
|
|
3
|
+
import type { ChartMargin } from './types';
|
|
4
|
+
import { type ChartDataTableOptions } from './dataTable';
|
|
5
|
+
import { type ChartLegendProps } from './ChartLegend';
|
|
6
|
+
import { type ChartTooltipProps } from './ChartTooltip';
|
|
7
|
+
export interface ChartProps {
|
|
8
|
+
data: Record<string, unknown>[];
|
|
9
|
+
xKey: string;
|
|
10
|
+
series: SeriesDef[];
|
|
11
|
+
height?: number;
|
|
12
|
+
margin?: Partial<ChartMargin>;
|
|
13
|
+
/** How the y-domain is derived when `yDomain` is not set. Default `'auto'`. */
|
|
14
|
+
yBaseline?: YBaseline;
|
|
15
|
+
/** Explicit y-domain [min, max]. Authoritative — disables baseline/headroom. */
|
|
16
|
+
yDomain?: [number, number];
|
|
17
|
+
/**
|
|
18
|
+
* Explicit x-domain [min, max] for numeric/linear x. Honored even when `data`
|
|
19
|
+
* is empty (stable streaming window). Ignored for categorical (band) scales.
|
|
20
|
+
*/
|
|
21
|
+
xDomain?: [number, number];
|
|
22
|
+
grid?: ReactNode;
|
|
23
|
+
axes?: ReactNode;
|
|
24
|
+
legend?: boolean | ChartLegendProps;
|
|
25
|
+
tooltip?: boolean | Omit<ChartTooltipProps, 'series'>;
|
|
26
|
+
interactions?: ReactNode;
|
|
27
|
+
children?: ReactNode;
|
|
28
|
+
/**
|
|
29
|
+
* Visible heading above the chart. Also the chart's accessible name and the
|
|
30
|
+
* hidden data table's caption, unless `aria-label` is given.
|
|
31
|
+
*/
|
|
32
|
+
title?: string;
|
|
33
|
+
/** Visible supporting line under the title; exposed as the SVG description. */
|
|
34
|
+
subtitle?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Accessible name for the chart (`role="img"`). Defaults to `title`, then to
|
|
37
|
+
* the data series labels. Use it when the visible title lives outside the
|
|
38
|
+
* chart (e.g. a Card header).
|
|
39
|
+
*/
|
|
40
|
+
'aria-label'?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Text alternative summarizing what the chart shows (trend, highlights). Not
|
|
43
|
+
* rendered visibly; exposed via `aria-describedby` alongside `subtitle`.
|
|
44
|
+
*/
|
|
45
|
+
description?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Visually hidden `<table>` with the chart's data, for screen readers
|
|
48
|
+
* (caption = accessible name, header row = x label + series labels, one row
|
|
49
|
+
* per x value). Default `true`. Pass `false` to opt out (e.g. when the same
|
|
50
|
+
* data is already on the page as a table) or an object to customize labels
|
|
51
|
+
* and formatting.
|
|
52
|
+
*/
|
|
53
|
+
dataTable?: boolean | ChartDataTableOptions;
|
|
54
|
+
/**
|
|
55
|
+
* `'vertical'` (default) or `'horizontal'` — categories on the y-axis and
|
|
56
|
+
* values growing right (horizontal bars). Axes and grid follow automatically;
|
|
57
|
+
* for the tooltip use the `tooltip` prop (not a `ChartTooltip` child).
|
|
58
|
+
*/
|
|
59
|
+
orientation?: ChartOrientation;
|
|
60
|
+
}
|
|
61
|
+
export declare function Chart({ data, xKey, series, height, margin: marginOverride, yBaseline, yDomain, xDomain, grid, axes, legend, tooltip, interactions, children, title, subtitle, 'aria-label': ariaLabel, description, dataTable, orientation, }: ChartProps): import("react").JSX.Element;
|
|
62
|
+
//# sourceMappingURL=Chart.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Chart.d.ts","sourceRoot":"","sources":["../src/Chart.tsx"],"names":[],"mappings":"AA0BA,OAAO,EACL,KAAK,SAAS,EAOf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAC,SAAS,EAAE,SAAS,EAAE,gBAAgB,EAAC,MAAM,SAAS,CAAC;AACpE,OAAO,KAAK,EAAe,WAAW,EAAoB,MAAM,SAAS,CAAC;AAQ1E,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,aAAa,CAAC;AAErB,OAAO,EAAc,KAAK,gBAAgB,EAAC,MAAM,eAAe,CAAC;AAEjE,OAAO,EAAe,KAAK,iBAAiB,EAAC,MAAM,gBAAgB,CAAC;AAIpE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9B,+EAA+E;IAC/E,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,gFAAgF;IAChF,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;IACpC,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;IACtD,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,qBAAqB,CAAC;IAC5C;;;;OAIG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAC;CAChC;AAkBD,wBAAgB,KAAK,CAAC,EACpB,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,MAAY,EACZ,MAAM,EAAE,cAAc,EACtB,SAAS,EACT,OAAO,EACP,OAAO,EACP,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,OAAO,EACP,YAAY,EACZ,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,YAAY,EAAE,SAAS,EACvB,WAAW,EACX,SAAgB,EAChB,WAAwB,GACzB,EAAE,UAAU,+BAkYZ"}
|
package/dist/Chart.js
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Chart.tsx (v2)
|
|
5
|
+
* @output Root chart — coordinates layout, rendering, and events
|
|
6
|
+
* @position Top-level; delegates everything to series configs and interaction slots
|
|
7
|
+
*
|
|
8
|
+
* The chart root has ZERO knowledge of mark types. It:
|
|
9
|
+
* 1. Runs the layout engine (scales + stacking + grouping)
|
|
10
|
+
* 2. Calls each series' resolve() and render() methods
|
|
11
|
+
* 3. Provides a single event layer for interaction children
|
|
12
|
+
* 4. Exposes the text alternative (WCAG 1.1.1): the SVG is `role="img"` with
|
|
13
|
+
* an accessible name (`aria-label` → `title` → series labels), optional
|
|
14
|
+
* `<desc>` from `subtitle`/`description`, and a visually hidden data table
|
|
15
|
+
* built from `data` (opt out with `dataTable={false}`). Plot internals are
|
|
16
|
+
* `aria-hidden`.
|
|
17
|
+
* 5. Transposes the plot for `orientation="horizontal"`: marks resolve in the
|
|
18
|
+
* vertical plot space and are drawn through a 90° transform, while axes
|
|
19
|
+
* and grid read display-space scales from context.
|
|
20
|
+
*
|
|
21
|
+
* SYNC: When modified, update /packages/charts/src/Chart.doc.mjs and
|
|
22
|
+
* /packages/charts/README.md
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
'use client';
|
|
26
|
+
|
|
27
|
+
import { useId, useMemo, useRef, useState, useCallback, useLayoutEffect } from 'react';
|
|
28
|
+
import { computeLayout } from "./layout.js";
|
|
29
|
+
import { ChartProvider } from "./ChartContext.js";
|
|
30
|
+
import { Text } from '@pharos-ds/core';
|
|
31
|
+
import { VStack, HStack } from '@pharos-ds/core';
|
|
32
|
+
import { VisuallyHidden } from '@pharos-ds/core';
|
|
33
|
+
import * as stylex from '@stylexjs/stylex';
|
|
34
|
+
import { scaleLinear } from 'd3-scale';
|
|
35
|
+
import { buildDataTable, fallbackChartLabel } from "./dataTable.js";
|
|
36
|
+
import { isBandScale } from "./utils.js";
|
|
37
|
+
import { ChartLegend } from "./ChartLegend.js";
|
|
38
|
+
import { deriveLegendItems } from "./legend.js";
|
|
39
|
+
import { ChartTooltip } from "./ChartTooltip.js";
|
|
40
|
+
import { useChartColors } from "./useChartColors.js";
|
|
41
|
+
import { isUtilityMarkType } from "./types.js";
|
|
42
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
43
|
+
const DEFAULT_MARGIN = {
|
|
44
|
+
top: 24,
|
|
45
|
+
right: 24,
|
|
46
|
+
bottom: 32,
|
|
47
|
+
left: 48
|
|
48
|
+
};
|
|
49
|
+
export function Chart({
|
|
50
|
+
data,
|
|
51
|
+
xKey,
|
|
52
|
+
series,
|
|
53
|
+
height = 300,
|
|
54
|
+
margin: marginOverride,
|
|
55
|
+
yBaseline,
|
|
56
|
+
yDomain,
|
|
57
|
+
xDomain,
|
|
58
|
+
grid,
|
|
59
|
+
axes,
|
|
60
|
+
legend,
|
|
61
|
+
tooltip,
|
|
62
|
+
interactions,
|
|
63
|
+
children,
|
|
64
|
+
title,
|
|
65
|
+
subtitle,
|
|
66
|
+
'aria-label': ariaLabel,
|
|
67
|
+
description,
|
|
68
|
+
dataTable = true,
|
|
69
|
+
orientation = 'vertical'
|
|
70
|
+
}) {
|
|
71
|
+
const chartId = useId();
|
|
72
|
+
const descId = `${chartId}-desc`;
|
|
73
|
+
const isHorizontal = orientation === 'horizontal';
|
|
74
|
+
// useId() can contain ':' which is invalid in an SVG url(#id) reference.
|
|
75
|
+
const clipId = `plot-${chartId.replace(/:/g, '')}`;
|
|
76
|
+
const containerRef = useRef(null);
|
|
77
|
+
const svgRef = useRef(null);
|
|
78
|
+
const [containerWidth, setContainerWidth] = useState(0);
|
|
79
|
+
const pointerHandlers = useRef(new Set());
|
|
80
|
+
useLayoutEffect(() => {
|
|
81
|
+
if (!containerRef.current) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const observer = new ResizeObserver(entries => {
|
|
85
|
+
const entry = entries[0];
|
|
86
|
+
if (entry) {
|
|
87
|
+
setContainerWidth(entry.contentRect.width);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
observer.observe(containerRef.current);
|
|
91
|
+
return () => observer.disconnect();
|
|
92
|
+
}, []);
|
|
93
|
+
const margin = useMemo(() => ({
|
|
94
|
+
...DEFAULT_MARGIN,
|
|
95
|
+
...marginOverride
|
|
96
|
+
}), [marginOverride]);
|
|
97
|
+
// Clamp plot dimensions to finite, non-negative values. layout.ts hardens
|
|
98
|
+
// against NaN in the *data*, but a non-finite `height` prop or margin override
|
|
99
|
+
// would still collapse every scale range — and the clipPath/event-rect
|
|
100
|
+
// geometry — into NaN. `containerWidth` is always finite (from ResizeObserver).
|
|
101
|
+
const safeHeight = Number.isFinite(height) ? Math.max(0, height) : 0;
|
|
102
|
+
const rawInnerWidth = containerWidth - margin.left - margin.right;
|
|
103
|
+
const rawInnerHeight = safeHeight - margin.top - margin.bottom;
|
|
104
|
+
const innerWidth = Number.isFinite(rawInnerWidth) ? Math.max(0, rawInnerWidth) : 0;
|
|
105
|
+
const innerHeight = Number.isFinite(rawInnerHeight) ? Math.max(0, rawInnerHeight) : 0;
|
|
106
|
+
// Plot space: marks always resolve as if the chart were vertical. For a
|
|
107
|
+
// horizontal chart the category axis runs along the display height and the
|
|
108
|
+
// value axis along the display width, so the plot box is transposed.
|
|
109
|
+
const plotWidth = isHorizontal ? innerHeight : innerWidth;
|
|
110
|
+
const plotHeight = isHorizontal ? innerWidth : innerHeight;
|
|
111
|
+
|
|
112
|
+
// ─── Color assignment ─────────────────────────────────────────────────
|
|
113
|
+
// Give every primary series that doesn't supply a static color (auto-colored
|
|
114
|
+
// or accessor-colored) a distinct color from the theme's categorical palette.
|
|
115
|
+
// Utility marks (band/errorBar/referenceLine) don't consume palette slots.
|
|
116
|
+
// Assigned during render (like the layout pass annotates `_uid`) so the first
|
|
117
|
+
// paint is already colored; intentionally not a `useMemo` — it mutates the
|
|
118
|
+
// caller's series defs, and useMemo is allowed to drop its cached result.
|
|
119
|
+
const chartColors = useChartColors();
|
|
120
|
+
const needsColor = series.filter(s => !isUtilityMarkType(s.type) && s.color == null);
|
|
121
|
+
const palette = chartColors.categorical(Math.max(needsColor.length, 1));
|
|
122
|
+
for (let i = 0; i < needsColor.length; i++) {
|
|
123
|
+
needsColor[i]._resolvedColor = palette[i % palette.length];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ─── Layout pass ──────────────────────────────────────────────────────
|
|
127
|
+
const layout = useMemo(() => computeLayout({
|
|
128
|
+
data,
|
|
129
|
+
xKey,
|
|
130
|
+
series,
|
|
131
|
+
width: plotWidth,
|
|
132
|
+
height: plotHeight,
|
|
133
|
+
yBaseline,
|
|
134
|
+
yDomain,
|
|
135
|
+
xDomain
|
|
136
|
+
}), [data, xKey, series, plotWidth, plotHeight, yBaseline, yDomain, xDomain]);
|
|
137
|
+
const seriesCtx = useMemo(() => ({
|
|
138
|
+
data,
|
|
139
|
+
xKey,
|
|
140
|
+
xScale: layout.xScale,
|
|
141
|
+
yScale: layout.yScale,
|
|
142
|
+
yBandScale: layout.yBandScale,
|
|
143
|
+
width: plotWidth,
|
|
144
|
+
height: plotHeight
|
|
145
|
+
}), [data, xKey, layout, plotWidth, plotHeight]);
|
|
146
|
+
|
|
147
|
+
// ─── Event dispatch ───────────────────────────────────────────────────
|
|
148
|
+
const onPointer = useCallback(handler => {
|
|
149
|
+
pointerHandlers.current.add(handler);
|
|
150
|
+
return () => {
|
|
151
|
+
pointerHandlers.current.delete(handler);
|
|
152
|
+
};
|
|
153
|
+
}, []);
|
|
154
|
+
const dispatch = useCallback(e => {
|
|
155
|
+
for (const handler of pointerHandlers.current) {
|
|
156
|
+
handler(e);
|
|
157
|
+
}
|
|
158
|
+
}, []);
|
|
159
|
+
const handlePointerMove = useCallback(e => {
|
|
160
|
+
const svg = svgRef.current;
|
|
161
|
+
if (!svg) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const point = svg.createSVGPoint();
|
|
165
|
+
point.x = e.clientX;
|
|
166
|
+
point.y = e.clientY;
|
|
167
|
+
const ctm = e.currentTarget.getScreenCTM()?.inverse();
|
|
168
|
+
if (!ctm) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const cursor = point.matrixTransform(ctm);
|
|
172
|
+
|
|
173
|
+
// Find nearest point by category distance only (the full column — or
|
|
174
|
+
// row, when horizontal — is the hover zone). Resolved points live in
|
|
175
|
+
// plot space, where the category position is always `px`.
|
|
176
|
+
const cursorCategory = isHorizontal ? cursor.y : cursor.x;
|
|
177
|
+
let nearest = null;
|
|
178
|
+
let bestXDist = Infinity;
|
|
179
|
+
for (const [seriesKey, points] of layout.resolved) {
|
|
180
|
+
for (const p of points) {
|
|
181
|
+
const xDist = Math.abs(p.px - cursorCategory);
|
|
182
|
+
if (xDist < bestXDist) {
|
|
183
|
+
bestXDist = xDist;
|
|
184
|
+
nearest = {
|
|
185
|
+
...p,
|
|
186
|
+
seriesKey
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
dispatch({
|
|
192
|
+
x: cursor.x,
|
|
193
|
+
y: cursor.y,
|
|
194
|
+
nearest,
|
|
195
|
+
active: e.buttons > 0
|
|
196
|
+
});
|
|
197
|
+
}, [layout.resolved, dispatch, isHorizontal]);
|
|
198
|
+
const handlePointerLeave = useCallback(() => {
|
|
199
|
+
dispatch({
|
|
200
|
+
x: -1,
|
|
201
|
+
y: -1,
|
|
202
|
+
nearest: null,
|
|
203
|
+
active: false
|
|
204
|
+
});
|
|
205
|
+
}, [dispatch]);
|
|
206
|
+
|
|
207
|
+
// ─── Context for interactions + v1 chrome ─────────────────────────────
|
|
208
|
+
// `plotCtx` is the vertical plot space marks resolve in (it is also the
|
|
209
|
+
// display space for vertical charts). For horizontal charts, chrome gets a
|
|
210
|
+
// display-space view: the value scale runs along x (left → right) and the
|
|
211
|
+
// category scale along y (top → bottom).
|
|
212
|
+
const plotCtx = useMemo(() => ({
|
|
213
|
+
orientation,
|
|
214
|
+
width: plotWidth,
|
|
215
|
+
height: plotHeight,
|
|
216
|
+
margin,
|
|
217
|
+
data,
|
|
218
|
+
xKey,
|
|
219
|
+
xScale: layout.xScale,
|
|
220
|
+
yScale: layout.yScale,
|
|
221
|
+
yBandScale: layout.yBandScale,
|
|
222
|
+
resolved: layout.resolved,
|
|
223
|
+
onPointer,
|
|
224
|
+
svgRef
|
|
225
|
+
}), [orientation, plotWidth, plotHeight, margin, data, xKey, layout, onPointer]);
|
|
226
|
+
const ctx = useMemo(() => {
|
|
227
|
+
if (!isHorizontal) {
|
|
228
|
+
return plotCtx;
|
|
229
|
+
}
|
|
230
|
+
const valueScale = layout.yScale.copy().range([0, innerWidth]);
|
|
231
|
+
const plotX = layout.xScale;
|
|
232
|
+
return {
|
|
233
|
+
...plotCtx,
|
|
234
|
+
width: innerWidth,
|
|
235
|
+
height: innerHeight,
|
|
236
|
+
xScale: valueScale,
|
|
237
|
+
...(isBandScale(plotX) ? {
|
|
238
|
+
yBandScale: plotX.copy().range([0, innerHeight]),
|
|
239
|
+
// Unused for a categorical y; kept so `yScale` stays a valid scale.
|
|
240
|
+
yScale: scaleLinear().range([innerHeight, 0])
|
|
241
|
+
} : {
|
|
242
|
+
yBandScale: undefined,
|
|
243
|
+
yScale: plotX.copy().range([0, innerHeight])
|
|
244
|
+
})
|
|
245
|
+
};
|
|
246
|
+
}, [plotCtx, isHorizontal, layout, innerWidth, innerHeight]);
|
|
247
|
+
|
|
248
|
+
// ─── Accessibility ────────────────────────────────────────────────────
|
|
249
|
+
const accessibleName = ariaLabel || title || fallbackChartLabel(series) || undefined;
|
|
250
|
+
const descriptionText = [subtitle, description].filter(Boolean).join('. ');
|
|
251
|
+
const tableModel = useMemo(() => dataTable === false ? null : buildDataTable(data, xKey, series, dataTable === true ? {} : dataTable), [data, xKey, series, dataTable]);
|
|
252
|
+
const tableElement = tableModel ? /*#__PURE__*/_jsx(VisuallyHidden, {
|
|
253
|
+
as: "div",
|
|
254
|
+
children: /*#__PURE__*/_jsxs("table", {
|
|
255
|
+
children: [accessibleName && /*#__PURE__*/_jsx("caption", {
|
|
256
|
+
children: accessibleName
|
|
257
|
+
}), /*#__PURE__*/_jsx("thead", {
|
|
258
|
+
children: /*#__PURE__*/_jsx("tr", {
|
|
259
|
+
children: tableModel.headers.map((h, i) => /*#__PURE__*/_jsx("th", {
|
|
260
|
+
scope: "col",
|
|
261
|
+
children: h
|
|
262
|
+
}, i))
|
|
263
|
+
})
|
|
264
|
+
}), /*#__PURE__*/_jsx("tbody", {
|
|
265
|
+
children: tableModel.rows.map(row => /*#__PURE__*/_jsxs("tr", {
|
|
266
|
+
children: [/*#__PURE__*/_jsx("th", {
|
|
267
|
+
scope: "row",
|
|
268
|
+
children: row.header
|
|
269
|
+
}), row.cells.map((cell, i) => /*#__PURE__*/_jsx("td", {
|
|
270
|
+
children: cell
|
|
271
|
+
}, i))]
|
|
272
|
+
}, row.key))
|
|
273
|
+
})]
|
|
274
|
+
})
|
|
275
|
+
}) : null;
|
|
276
|
+
|
|
277
|
+
// ─── Legend ────────────────────────────────────────────────────────────
|
|
278
|
+
const legendConfig = legend === true ? {} : legend || null;
|
|
279
|
+
const legendElement = legendConfig ? /*#__PURE__*/_jsx(ChartLegend, {
|
|
280
|
+
items: legendConfig.items ?? deriveLegendItems(series),
|
|
281
|
+
position: legendConfig.position,
|
|
282
|
+
alignment: legendConfig.alignment
|
|
283
|
+
}) : null;
|
|
284
|
+
const legendPosition = legendConfig?.position ?? 'bottom';
|
|
285
|
+
const isLegendHorizontal = legendPosition === 'start' || legendPosition === 'end';
|
|
286
|
+
|
|
287
|
+
// ─── Render ───────────────────────────────────────────────────────────
|
|
288
|
+
// Before the first measurement (and during SSR) only the sized placeholder
|
|
289
|
+
// renders — plus the hidden data table, which doesn't depend on width, so
|
|
290
|
+
// the text alternative is in the server HTML too.
|
|
291
|
+
if (containerWidth === 0) {
|
|
292
|
+
return /*#__PURE__*/_jsx("div", {
|
|
293
|
+
ref: containerRef,
|
|
294
|
+
...{
|
|
295
|
+
className: "xh8yej3"
|
|
296
|
+
},
|
|
297
|
+
style: {
|
|
298
|
+
height: safeHeight
|
|
299
|
+
},
|
|
300
|
+
children: tableElement
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
304
|
+
ref: containerRef,
|
|
305
|
+
...{
|
|
306
|
+
className: "xh8yej3"
|
|
307
|
+
},
|
|
308
|
+
children: [(title || subtitle) && /*#__PURE__*/_jsxs("div", {
|
|
309
|
+
...{
|
|
310
|
+
className: "x1yztbdb"
|
|
311
|
+
},
|
|
312
|
+
children: [title && /*#__PURE__*/_jsx(Text, {
|
|
313
|
+
type: "body",
|
|
314
|
+
weight: "semibold",
|
|
315
|
+
display: "block",
|
|
316
|
+
children: title
|
|
317
|
+
}), subtitle && /*#__PURE__*/_jsx(Text, {
|
|
318
|
+
type: "supporting",
|
|
319
|
+
display: "block",
|
|
320
|
+
children: subtitle
|
|
321
|
+
})]
|
|
322
|
+
}), /*#__PURE__*/_jsx(ChartProvider, {
|
|
323
|
+
value: ctx,
|
|
324
|
+
children: legendConfig == null ? renderSvg() : isLegendHorizontal ? /*#__PURE__*/_jsxs(HStack, {
|
|
325
|
+
gap: 4,
|
|
326
|
+
children: [legendPosition === 'start' && legendElement, /*#__PURE__*/_jsx("div", {
|
|
327
|
+
...{
|
|
328
|
+
className: "x98rzlu xeuugli xb3r6kr"
|
|
329
|
+
},
|
|
330
|
+
children: renderSvg()
|
|
331
|
+
}), legendPosition === 'end' && legendElement]
|
|
332
|
+
}) : /*#__PURE__*/_jsxs(VStack, {
|
|
333
|
+
gap: 4,
|
|
334
|
+
children: [legendPosition === 'top' && legendElement, renderSvg(), legendPosition === 'bottom' && legendElement]
|
|
335
|
+
})
|
|
336
|
+
}), tableElement]
|
|
337
|
+
});
|
|
338
|
+
function renderSvg() {
|
|
339
|
+
const plotTransform = isHorizontal ? `matrix(0,1,-1,0,${innerWidth},0)` : undefined;
|
|
340
|
+
return /*#__PURE__*/_jsxs("svg", {
|
|
341
|
+
ref: svgRef,
|
|
342
|
+
width: "100%",
|
|
343
|
+
height: safeHeight,
|
|
344
|
+
role: "img",
|
|
345
|
+
"aria-label": accessibleName,
|
|
346
|
+
"aria-describedby": descriptionText ? descId : undefined,
|
|
347
|
+
children: [descriptionText && /*#__PURE__*/_jsx("desc", {
|
|
348
|
+
id: descId,
|
|
349
|
+
children: descriptionText
|
|
350
|
+
}), /*#__PURE__*/_jsx("defs", {
|
|
351
|
+
children: /*#__PURE__*/_jsx("clipPath", {
|
|
352
|
+
id: clipId,
|
|
353
|
+
children: /*#__PURE__*/_jsx("rect", {
|
|
354
|
+
x: 0,
|
|
355
|
+
y: 0,
|
|
356
|
+
width: innerWidth,
|
|
357
|
+
height: innerHeight
|
|
358
|
+
})
|
|
359
|
+
})
|
|
360
|
+
}), /*#__PURE__*/_jsxs("g", {
|
|
361
|
+
transform: `translate(${margin.left},${margin.top})`,
|
|
362
|
+
children: [/*#__PURE__*/_jsxs("g", {
|
|
363
|
+
"aria-hidden": "true",
|
|
364
|
+
children: [grid, /*#__PURE__*/_jsx("g", {
|
|
365
|
+
clipPath: `url(#${clipId})`,
|
|
366
|
+
children: /*#__PURE__*/_jsx("g", {
|
|
367
|
+
transform: plotTransform,
|
|
368
|
+
children: series.map(s => {
|
|
369
|
+
const resolved = s._uid ? layout.resolved.get(s._uid) : undefined;
|
|
370
|
+
if (!resolved) {
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
return /*#__PURE__*/_jsx("g", {
|
|
374
|
+
children: s.render(resolved, seriesCtx)
|
|
375
|
+
}, s._uid);
|
|
376
|
+
})
|
|
377
|
+
})
|
|
378
|
+
}), axes]
|
|
379
|
+
}), /*#__PURE__*/_jsx("rect", {
|
|
380
|
+
x: 0,
|
|
381
|
+
y: 0,
|
|
382
|
+
width: innerWidth,
|
|
383
|
+
height: innerHeight,
|
|
384
|
+
fill: "transparent",
|
|
385
|
+
onPointerMove: handlePointerMove,
|
|
386
|
+
onPointerLeave: handlePointerLeave
|
|
387
|
+
}), interactions, tooltip && /*#__PURE__*/_jsx("g", {
|
|
388
|
+
"aria-hidden": "true",
|
|
389
|
+
transform: plotTransform,
|
|
390
|
+
children: /*#__PURE__*/_jsx(ChartProvider, {
|
|
391
|
+
value: plotCtx,
|
|
392
|
+
children: /*#__PURE__*/_jsx(ChartTooltip, {
|
|
393
|
+
series: series,
|
|
394
|
+
...(tooltip === true ? {} : tooltip)
|
|
395
|
+
})
|
|
396
|
+
})
|
|
397
|
+
}), children]
|
|
398
|
+
})]
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
}
|