@advui/charts 0.5.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.
Files changed (88) hide show
  1. package/LICENSE +49 -0
  2. package/README.md +41 -0
  3. package/dist/charts/ChartFrame.d.ts +75 -0
  4. package/dist/charts/ChartFrame.d.ts.map +1 -0
  5. package/dist/charts/ChartFrame.js +100 -0
  6. package/dist/charts/ChartFrame.js.map +1 -0
  7. package/dist/charts/LinePlot.d.ts +32 -0
  8. package/dist/charts/LinePlot.d.ts.map +1 -0
  9. package/dist/charts/LinePlot.js +93 -0
  10. package/dist/charts/LinePlot.js.map +1 -0
  11. package/dist/charts/cartesian.d.ts +35 -0
  12. package/dist/charts/cartesian.d.ts.map +1 -0
  13. package/dist/charts/cartesian.js +23 -0
  14. package/dist/charts/cartesian.js.map +1 -0
  15. package/dist/charts/format.d.ts +7 -0
  16. package/dist/charts/format.d.ts.map +1 -0
  17. package/dist/charts/format.js +12 -0
  18. package/dist/charts/format.js.map +1 -0
  19. package/dist/charts/index.d.ts +7 -0
  20. package/dist/charts/index.d.ts.map +1 -0
  21. package/dist/charts/index.js +7 -0
  22. package/dist/charts/index.js.map +1 -0
  23. package/dist/charts/scale.d.ts +20 -0
  24. package/dist/charts/scale.d.ts.map +1 -0
  25. package/dist/charts/scale.js +75 -0
  26. package/dist/charts/scale.js.map +1 -0
  27. package/dist/charts/svg.d.ts +51 -0
  28. package/dist/charts/svg.d.ts.map +1 -0
  29. package/dist/charts/svg.js +13 -0
  30. package/dist/charts/svg.js.map +1 -0
  31. package/dist/charts/svg.native.d.ts +50 -0
  32. package/dist/charts/svg.native.d.ts.map +1 -0
  33. package/dist/charts/svg.native.js +14 -0
  34. package/dist/charts/svg.native.js.map +1 -0
  35. package/dist/components/area-chart/AreaChart.d.ts +11 -0
  36. package/dist/components/area-chart/AreaChart.d.ts.map +1 -0
  37. package/dist/components/area-chart/AreaChart.js +10 -0
  38. package/dist/components/area-chart/AreaChart.js.map +1 -0
  39. package/dist/components/area-chart/index.d.ts +2 -0
  40. package/dist/components/area-chart/index.d.ts.map +1 -0
  41. package/dist/components/area-chart/index.js +2 -0
  42. package/dist/components/area-chart/index.js.map +1 -0
  43. package/dist/components/bar-chart/BarChart.d.ts +31 -0
  44. package/dist/components/bar-chart/BarChart.d.ts.map +1 -0
  45. package/dist/components/bar-chart/BarChart.js +114 -0
  46. package/dist/components/bar-chart/BarChart.js.map +1 -0
  47. package/dist/components/bar-chart/index.d.ts +2 -0
  48. package/dist/components/bar-chart/index.d.ts.map +1 -0
  49. package/dist/components/bar-chart/index.js +2 -0
  50. package/dist/components/bar-chart/index.js.map +1 -0
  51. package/dist/components/line-chart/LineChart.d.ts +8 -0
  52. package/dist/components/line-chart/LineChart.d.ts.map +1 -0
  53. package/dist/components/line-chart/LineChart.js +10 -0
  54. package/dist/components/line-chart/LineChart.js.map +1 -0
  55. package/dist/components/line-chart/index.d.ts +2 -0
  56. package/dist/components/line-chart/index.d.ts.map +1 -0
  57. package/dist/components/line-chart/index.js +2 -0
  58. package/dist/components/line-chart/index.js.map +1 -0
  59. package/dist/components/pie-chart/PieChart.d.ts +37 -0
  60. package/dist/components/pie-chart/PieChart.d.ts.map +1 -0
  61. package/dist/components/pie-chart/PieChart.js +89 -0
  62. package/dist/components/pie-chart/PieChart.js.map +1 -0
  63. package/dist/components/pie-chart/index.d.ts +2 -0
  64. package/dist/components/pie-chart/index.d.ts.map +1 -0
  65. package/dist/components/pie-chart/index.js +2 -0
  66. package/dist/components/pie-chart/index.js.map +1 -0
  67. package/dist/index.d.ts +5 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +7 -0
  70. package/dist/index.js.map +1 -0
  71. package/package.json +93 -0
  72. package/src/charts/ChartFrame.tsx +303 -0
  73. package/src/charts/LinePlot.tsx +216 -0
  74. package/src/charts/cartesian.tsx +99 -0
  75. package/src/charts/format.ts +14 -0
  76. package/src/charts/index.ts +16 -0
  77. package/src/charts/scale.ts +91 -0
  78. package/src/charts/svg.native.tsx +62 -0
  79. package/src/charts/svg.tsx +57 -0
  80. package/src/components/area-chart/AreaChart.tsx +14 -0
  81. package/src/components/area-chart/index.ts +1 -0
  82. package/src/components/bar-chart/BarChart.tsx +300 -0
  83. package/src/components/bar-chart/index.ts +1 -0
  84. package/src/components/line-chart/LineChart.tsx +11 -0
  85. package/src/components/line-chart/index.ts +1 -0
  86. package/src/components/pie-chart/PieChart.tsx +192 -0
  87. package/src/components/pie-chart/index.ts +1 -0
  88. package/src/index.ts +6 -0
@@ -0,0 +1,300 @@
1
+ import {
2
+ CategoryLabels,
3
+ ChartFrame,
4
+ type ChartLabels,
5
+ type ChartSeries,
6
+ G,
7
+ Line,
8
+ Path,
9
+ Svg,
10
+ SvgText,
11
+ ValueGrid,
12
+ bandScale,
13
+ barPath,
14
+ cartesianPadding,
15
+ formatCompact,
16
+ formatFull,
17
+ linearScale,
18
+ niceTicks,
19
+ numberAt,
20
+ useChartColors,
21
+ useChartInk,
22
+ } from '../../charts'
23
+
24
+ const MAX_BAR = 24
25
+ const GAP = 2
26
+ const RADIUS = 4
27
+
28
+ export interface BarChartProps {
29
+ /** Names the chart: its heading and accessible name. */
30
+ title: string
31
+ description?: string
32
+ /** One object per category, e.g. `{ month: 'Jan', health: 120, wash: 80 }`. */
33
+ data: Record<string, unknown>[]
34
+ /** The field holding each row's category name. */
35
+ index: string
36
+ /** Heading of the category column in the table view. Default: `index`. */
37
+ indexLabel?: string
38
+ /** The numeric fields to plot, in color order. */
39
+ series: ChartSeries[]
40
+ /** `vertical` draws columns; `horizontal` bars suit long category names. */
41
+ layout?: 'vertical' | 'horizontal'
42
+ /** Stacks the series in one bar per category (part-to-whole). */
43
+ stacked?: boolean
44
+ /** Height in pixels. Default: 240, or 36 per category for horizontal bars. */
45
+ height?: number
46
+ /** Fixed width; by default the chart fills its container. */
47
+ width?: number
48
+ /** Formats values in the tooltip and table. Axis ticks are always compact (1.2K). */
49
+ valueFormatter?: (value: number) => string
50
+ labels?: Partial<ChartLabels>
51
+ }
52
+
53
+ /**
54
+ * Compares values across categories as columns or bars, grouped or stacked.
55
+ * Includes a legend, a tooltip (hover, tap or arrow keys) and a table view.
56
+ */
57
+ export function BarChart({
58
+ title,
59
+ description,
60
+ data,
61
+ index,
62
+ indexLabel = index,
63
+ series,
64
+ layout = 'vertical',
65
+ stacked = false,
66
+ height: heightProp,
67
+ width,
68
+ valueFormatter = formatFull,
69
+ labels,
70
+ }: BarChartProps) {
71
+ const colors = useChartColors()
72
+ const ink = useChartInk('$background')
73
+ const horizontal = layout === 'horizontal'
74
+ const height = heightProp ?? (horizontal ? Math.max(120, data.length * 36 + 32) : 240)
75
+ const categories = data.map((row) => String(row[index] ?? ''))
76
+ const values = data.map((row) => series.map((s) => numberAt(row, s.key)))
77
+
78
+ // Stacks sum positives up and negatives down; groups need each value.
79
+ const extents = values.flatMap((row) =>
80
+ stacked
81
+ ? [
82
+ row.reduce<number>((sum, v) => sum + Math.max(0, v ?? 0), 0),
83
+ row.reduce<number>((sum, v) => sum + Math.min(0, v ?? 0), 0),
84
+ ]
85
+ : row.map((v) => v ?? 0),
86
+ )
87
+ const ticks = niceTicks(Math.min(0, ...extents), Math.max(0, ...extents))
88
+ const domain: [number, number] = [ticks[0]!, ticks.at(-1)!]
89
+
90
+ const categoryWidth = horizontal
91
+ ? Math.min(160, Math.max(...categories.map((c) => c.length), 1) * 7 + 12)
92
+ : 0
93
+ const pad = horizontal
94
+ ? { top: 8, right: 16, bottom: 24, left: categoryWidth }
95
+ : cartesianPadding(ticks)
96
+
97
+ const layoutAt = (w: number) => {
98
+ const valueScale = horizontal
99
+ ? linearScale(domain, [pad.left, w - pad.right])
100
+ : linearScale(domain, [height - pad.bottom, pad.top])
101
+ const band = horizontal
102
+ ? bandScale(data.length, [pad.top, height - pad.bottom])
103
+ : bandScale(data.length, [pad.left, w - pad.right])
104
+ const k = stacked ? 1 : series.length
105
+ // Bars never fill their slot: at most 24px, and the rest of the band is air.
106
+ const thickness = Math.max(2, Math.min(MAX_BAR, (band.bandwidth * 0.7 - GAP * (k - 1)) / k))
107
+ const group = k * thickness + (k - 1) * GAP
108
+ return { valueScale, band, thickness, group }
109
+ }
110
+
111
+ const hitTest = (x: number, y: number, w: number) => {
112
+ const { band } = layoutAt(w)
113
+ const position = horizontal ? y : x
114
+ const i = Math.floor((position - (horizontal ? pad.top : pad.left)) / band.bandwidth)
115
+ return i >= 0 && i < data.length ? i : null
116
+ }
117
+
118
+ const format = (value: number | null) => (value == null ? '–' : valueFormatter(value))
119
+ const legend =
120
+ series.length > 1
121
+ ? series.map((s, i) => ({ label: s.label, color: colors[i % 8]!, shape: 'square' as const }))
122
+ : []
123
+
124
+ return (
125
+ <ChartFrame
126
+ title={title}
127
+ description={description}
128
+ legend={legend}
129
+ height={height}
130
+ width={width}
131
+ count={data.length}
132
+ hitTest={hitTest}
133
+ anchor={(i, w) => {
134
+ const { band } = layoutAt(w)
135
+ const center = band.band(i) + band.bandwidth / 2
136
+ return horizontal ? { x: w - pad.right, y: center } : { x: center, y: pad.top }
137
+ }}
138
+ tooltip={(i) => ({
139
+ title: categories[i]!,
140
+ rows: series.map((s, j) => ({
141
+ label: s.label,
142
+ value: format(values[i]![j]!),
143
+ color: colors[j % 8]!,
144
+ shape: 'square',
145
+ })),
146
+ })}
147
+ table={{
148
+ columns: [indexLabel, ...series.map((s) => s.label)],
149
+ rows: data.map((_, i) => [categories[i]!, ...values[i]!.map(format)]),
150
+ numeric: [false, ...series.map(() => true)],
151
+ }}
152
+ labels={labels}
153
+ >
154
+ {(w, active) => {
155
+ const { valueScale, band, thickness, group } = layoutAt(w)
156
+ const zero = valueScale(0)
157
+ return (
158
+ <Svg width={w} height={height}>
159
+ {horizontal ? (
160
+ <>
161
+ {ticks.map((tick) => (
162
+ <Line
163
+ key={`grid-${tick}`}
164
+ x1={valueScale(tick)}
165
+ x2={valueScale(tick)}
166
+ y1={pad.top}
167
+ y2={height - pad.bottom}
168
+ stroke={tick === 0 ? ink.axis : ink.grid}
169
+ strokeWidth={1}
170
+ />
171
+ ))}
172
+ {ticks.map((tick) => (
173
+ <SvgText
174
+ key={`tick-${tick}`}
175
+ x={valueScale(tick)}
176
+ y={height - pad.bottom + 4}
177
+ dy="0.9em"
178
+ fill={ink.text}
179
+ fontSize={12}
180
+ textAnchor="middle"
181
+ >
182
+ {formatCompact(tick)}
183
+ </SvgText>
184
+ ))}
185
+ {categories.map((category, i) => (
186
+ <SvgText
187
+ key={`cat-${i}`}
188
+ x={pad.left - 8}
189
+ y={band.band(i) + band.bandwidth / 2}
190
+ dy="0.35em"
191
+ fill={ink.text}
192
+ fontSize={12}
193
+ textAnchor="end"
194
+ >
195
+ {truncate(category, Math.floor((pad.left - 12) / 7))}
196
+ </SvgText>
197
+ ))}
198
+ </>
199
+ ) : (
200
+ <>
201
+ <ValueGrid
202
+ ticks={ticks}
203
+ y={valueScale}
204
+ left={pad.left}
205
+ right={w - pad.right}
206
+ ink={ink}
207
+ />
208
+ <CategoryLabels
209
+ labels={categories}
210
+ x={(i) => band.band(i) + band.bandwidth / 2}
211
+ y={height - pad.bottom + 4}
212
+ available={band.bandwidth}
213
+ ink={ink}
214
+ />
215
+ </>
216
+ )}
217
+ {values.map((row, i) => {
218
+ const start = band.band(i) + (band.bandwidth - group) / 2
219
+ let positive = 0
220
+ let negative = 0
221
+ // In a stack, only the outermost segment on each side gets the rounded end.
222
+ const lastPositive = row.reduce<number>((last, v, j) => ((v ?? 0) > 0 ? j : last), -1)
223
+ const lastNegative = row.reduce<number>((last, v, j) => ((v ?? 0) < 0 ? j : last), -1)
224
+ return (
225
+ <G key={i} opacity={active == null || active === i ? 1 : 0.55}>
226
+ {row.map((value, j) => {
227
+ if (value == null || value === 0) return null
228
+ const offset = stacked ? start : start + j * (thickness + GAP)
229
+ const from = stacked ? (value > 0 ? positive : negative) : 0
230
+ const to = from + value
231
+ if (stacked) {
232
+ if (value > 0) positive = to
233
+ else negative = to
234
+ }
235
+ const a = valueScale(from)
236
+ const b = valueScale(to)
237
+ // A 2px gap separates a stacked segment from the one on its baseline side.
238
+ const inset = stacked && from !== 0 ? GAP : 0
239
+ const rounded = !stacked || j === (value > 0 ? lastPositive : lastNegative)
240
+ const radius = rounded ? RADIUS : 0
241
+ const d = horizontal
242
+ ? value > 0
243
+ ? barPath(
244
+ Math.min(a, b) + inset,
245
+ offset,
246
+ Math.abs(b - a) - inset,
247
+ thickness,
248
+ radius,
249
+ 'right',
250
+ )
251
+ : barPath(
252
+ Math.min(a, b),
253
+ offset,
254
+ Math.abs(b - a) - inset,
255
+ thickness,
256
+ radius,
257
+ 'left',
258
+ )
259
+ : value > 0
260
+ ? barPath(
261
+ offset,
262
+ Math.min(a, b),
263
+ thickness,
264
+ Math.abs(b - a) - inset,
265
+ radius,
266
+ 'up',
267
+ )
268
+ : barPath(
269
+ offset,
270
+ Math.min(a, b) + inset,
271
+ thickness,
272
+ Math.abs(b - a) - inset,
273
+ radius,
274
+ 'down',
275
+ )
276
+ return <Path key={j} d={d} fill={colors[j % 8]} />
277
+ })}
278
+ </G>
279
+ )
280
+ })}
281
+ {horizontal ? null : (
282
+ <Line
283
+ x1={pad.left}
284
+ x2={w - pad.right}
285
+ y1={zero}
286
+ y2={zero}
287
+ stroke={ink.axis}
288
+ strokeWidth={1}
289
+ />
290
+ )}
291
+ </Svg>
292
+ )
293
+ }}
294
+ </ChartFrame>
295
+ )
296
+ }
297
+
298
+ function truncate(text: string, max: number) {
299
+ return text.length > max ? `${text.slice(0, Math.max(1, max - 1))}…` : text
300
+ }
@@ -0,0 +1 @@
1
+ export { BarChart, type BarChartProps } from './BarChart'
@@ -0,0 +1,11 @@
1
+ import { LinePlot, type LinePlotProps } from '../../charts'
2
+
3
+ export type LineChartProps = LinePlotProps
4
+
5
+ /**
6
+ * Shows change over an ordered axis (months, years) as 2px lines, with a
7
+ * crosshair tooltip (hover, tap or arrow keys), a legend and a table view.
8
+ */
9
+ export function LineChart(props: LineChartProps) {
10
+ return <LinePlot {...props} />
11
+ }
@@ -0,0 +1 @@
1
+ export { LineChart, type LineChartProps } from './LineChart'
@@ -0,0 +1,192 @@
1
+ import { useIconColor } from '@advui/icons'
2
+ import {
3
+ ChartFrame,
4
+ type ChartLabels,
5
+ G,
6
+ Path,
7
+ Svg,
8
+ SvgText,
9
+ arcPath,
10
+ formatFull,
11
+ useChartColors,
12
+ useChartInk,
13
+ } from '../../charts'
14
+
15
+ export interface PieSlice {
16
+ label: string
17
+ value: number
18
+ }
19
+
20
+ export interface PieChartProps {
21
+ /** Names the chart: its heading and accessible name. */
22
+ title: string
23
+ description?: string
24
+ /** The parts of the whole. Negative and zero values are left out. */
25
+ data: PieSlice[]
26
+ /** `donut` leaves room for the total in the middle. */
27
+ variant?: 'donut' | 'pie'
28
+ /** More slices than this fold the smallest into "Other". Default: 6. */
29
+ maxSlices?: number
30
+ /** Height in pixels. Default: 240. */
31
+ height?: number
32
+ width?: number
33
+ /** Formats values in the legend, tooltip and table. */
34
+ valueFormatter?: (value: number) => string
35
+ /** Headings for the table and the folded slice, for translation. */
36
+ text?: { label?: string; value?: string; share?: string; other?: string; total?: string }
37
+ labels?: Partial<ChartLabels>
38
+ }
39
+
40
+ const percent = (part: number, total: number) =>
41
+ total > 0 ? `${Math.round((part / total) * 1000) / 10}%` : '0%'
42
+
43
+ /**
44
+ * Part-to-whole at a glance, for up to six parts. Each slice is named in the
45
+ * legend with its share; the tooltip (hover, tap or arrow keys) and the
46
+ * table view give the exact values. For close values, a bar chart reads better.
47
+ */
48
+ export function PieChart({
49
+ title,
50
+ description,
51
+ data,
52
+ variant = 'donut',
53
+ maxSlices = 6,
54
+ height = 240,
55
+ width,
56
+ valueFormatter = formatFull,
57
+ text: textProp,
58
+ labels,
59
+ }: PieChartProps) {
60
+ const text = {
61
+ label: 'Label',
62
+ value: 'Value',
63
+ share: 'Share',
64
+ other: 'Other',
65
+ total: 'Total',
66
+ ...textProp,
67
+ }
68
+ const colors = useChartColors()
69
+ const ink = useChartInk('$background')
70
+ const foreground = useIconColor('$foreground') ?? 'currentColor'
71
+
72
+ // Largest first; past the limit, the tail folds into one "Other" slice.
73
+ const positive = data.filter((d) => d.value > 0).sort((a, b) => b.value - a.value)
74
+ const slices =
75
+ positive.length > maxSlices
76
+ ? [
77
+ ...positive.slice(0, maxSlices - 1),
78
+ {
79
+ label: text.other,
80
+ value: positive.slice(maxSlices - 1).reduce((sum, d) => sum + d.value, 0),
81
+ },
82
+ ]
83
+ : positive
84
+ const folded = positive.length > maxSlices
85
+ const total = slices.reduce((sum, d) => sum + d.value, 0)
86
+ const colorOf = (i: number) => (folded && i === slices.length - 1 ? ink.axis : colors[i % 8]!)
87
+
88
+ let angle = 0
89
+ const arcs = slices.map((slice, i) => {
90
+ const start = angle
91
+ angle += total > 0 ? (slice.value / total) * Math.PI * 2 : 0
92
+ return { ...slice, start, end: angle, color: colorOf(i) }
93
+ })
94
+
95
+ const geometry = (w: number) => {
96
+ const outer = Math.min(w, height) / 2 - 8
97
+ return { cx: w / 2, cy: height / 2, outer, inner: variant === 'donut' ? outer * 0.62 : 0 }
98
+ }
99
+
100
+ return (
101
+ <ChartFrame
102
+ title={title}
103
+ description={description}
104
+ legend={arcs.map((arc) => ({
105
+ label: arc.label,
106
+ color: arc.color,
107
+ shape: 'square',
108
+ detail: percent(arc.value, total),
109
+ }))}
110
+ height={height}
111
+ width={width}
112
+ count={arcs.length}
113
+ hitTest={(x, y, w) => {
114
+ const { cx, cy, outer, inner } = geometry(w)
115
+ const dx = x - cx
116
+ const dy = y - cy
117
+ const r = Math.hypot(dx, dy)
118
+ if (r > outer + 8 || r < inner) return null
119
+ const a = (Math.atan2(dx, -dy) + Math.PI * 2) % (Math.PI * 2)
120
+ const found = arcs.findIndex((arc) => a >= arc.start && a < arc.end)
121
+ return found >= 0 ? found : null
122
+ }}
123
+ anchor={(i, w) => {
124
+ const { cx, outer } = geometry(w)
125
+ const mid = (arcs[i]!.start + arcs[i]!.end) / 2
126
+ return { x: cx + outer * Math.sin(mid), y: 0 }
127
+ }}
128
+ tooltip={(i) => ({
129
+ title: arcs[i]!.label,
130
+ rows: [
131
+ {
132
+ label: percent(arcs[i]!.value, total),
133
+ value: valueFormatter(arcs[i]!.value),
134
+ color: arcs[i]!.color,
135
+ shape: 'square',
136
+ },
137
+ ],
138
+ })}
139
+ table={{
140
+ columns: [text.label, text.value, text.share],
141
+ rows: [
142
+ ...arcs.map((arc) => [arc.label, valueFormatter(arc.value), percent(arc.value, total)]),
143
+ [text.total, valueFormatter(total), '100%'],
144
+ ],
145
+ numeric: [false, true, true],
146
+ }}
147
+ labels={labels}
148
+ >
149
+ {(w, active) => {
150
+ const { cx, cy, outer, inner } = geometry(w)
151
+ // A 2px gap between slices, as angle at the outer edge.
152
+ const gap = arcs.length > 1 ? 2 / outer : 0
153
+ return (
154
+ <Svg width={w} height={height}>
155
+ {arcs.map((arc, i) => (
156
+ <G key={arc.label} opacity={active == null || active === i ? 1 : 0.55}>
157
+ <Path
158
+ d={arcPath(
159
+ cx,
160
+ cy,
161
+ active === i ? outer + 4 : outer,
162
+ inner,
163
+ arc.start + gap / 2,
164
+ Math.max(arc.start + gap / 2, arc.end - gap / 2),
165
+ )}
166
+ fill={arc.color}
167
+ />
168
+ </G>
169
+ ))}
170
+ {variant === 'donut' ? (
171
+ <>
172
+ <SvgText
173
+ x={cx}
174
+ y={cy - 6}
175
+ fill={foreground}
176
+ fontSize={20}
177
+ fontWeight="600"
178
+ textAnchor="middle"
179
+ >
180
+ {valueFormatter(total)}
181
+ </SvgText>
182
+ <SvgText x={cx} y={cy + 16} fill={ink.text} fontSize={12} textAnchor="middle">
183
+ {text.total}
184
+ </SvgText>
185
+ </>
186
+ ) : null}
187
+ </Svg>
188
+ )
189
+ }}
190
+ </ChartFrame>
191
+ )
192
+ }
@@ -0,0 +1 @@
1
+ export { PieChart, type PieChartProps, type PieSlice } from './PieChart'
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ // Chart components. The shared internals in ./charts (frame, legend, tooltip,
2
+ // table view, scales and the SVG layer) are not part of the public API.
3
+ export * from './components/area-chart'
4
+ export * from './components/bar-chart'
5
+ export * from './components/line-chart'
6
+ export * from './components/pie-chart'