@spteck/fluentui-react-charts 1.0.7 → 1.0.9

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 (105) hide show
  1. package/dist/charts/BarChart/BarChart.d.ts +2 -1
  2. package/dist/charts/ComboChart/ComboChart.d.ts +2 -1
  3. package/dist/charts/Doughnut/DoughnutChart.d.ts +2 -1
  4. package/dist/charts/PieChart/PieChart.d.ts +2 -1
  5. package/dist/charts/areaChart/AreaChart.d.ts +2 -1
  6. package/dist/charts/barHorizontalChart/BarHotizontalChart.d.ts +2 -1
  7. package/dist/charts/bubbleChart/BubbleChart.d.ts +2 -1
  8. package/dist/charts/floatBarChart/FloatBarChart.d.ts +2 -1
  9. package/dist/charts/index.d.ts +14 -0
  10. package/dist/charts/lineChart/LineChart.d.ts +2 -1
  11. package/dist/charts/polarChart/PolarChart.d.ts +2 -1
  12. package/dist/charts/radarChart/RadarChart.d.ts +2 -1
  13. package/dist/charts/scatterChart/ScatterChart.d.ts +2 -1
  14. package/dist/charts/stackedLineChart/StackedLineChart.d.ts +2 -1
  15. package/dist/charts/steamChart/SteamChart.d.ts +2 -1
  16. package/dist/components/index.d.ts +0 -14
  17. package/dist/fluentui-react-charts.cjs.development.js +1086 -1072
  18. package/dist/fluentui-react-charts.cjs.development.js.map +1 -1
  19. package/dist/fluentui-react-charts.cjs.production.min.js +1 -1
  20. package/dist/fluentui-react-charts.cjs.production.min.js.map +1 -1
  21. package/dist/fluentui-react-charts.esm.js +1074 -1074
  22. package/dist/fluentui-react-charts.esm.js.map +1 -1
  23. package/dist/index.d.ts +1 -0
  24. package/package.json +5 -5
  25. package/src/assets/sample1.png +0 -0
  26. package/src/assets/sample2.png +0 -0
  27. package/src/assets/sample3.png +0 -0
  28. package/src/charts/BarChart/BarChart.tsx +0 -227
  29. package/src/charts/BarChart/README.MD +0 -335
  30. package/src/charts/BarChart/index.ts +0 -1
  31. package/src/charts/ComboChart/ComboChart.tsx +0 -209
  32. package/src/charts/ComboChart/README.MD +0 -347
  33. package/src/charts/ComboChart/index.ts +0 -1
  34. package/src/charts/Doughnut/DoughnutChart.tsx +0 -152
  35. package/src/charts/Doughnut/README.MD +0 -296
  36. package/src/charts/Doughnut/index.ts +0 -1
  37. package/src/charts/PieChart/PieChart.tsx +0 -148
  38. package/src/charts/PieChart/README.MD +0 -315
  39. package/src/charts/PieChart/index.ts +0 -1
  40. package/src/charts/areaChart/AreaChart.tsx +0 -195
  41. package/src/charts/areaChart/README.MD +0 -236
  42. package/src/charts/areaChart/index.ts +0 -1
  43. package/src/charts/barHorizontalChart/BarHotizontalChart.tsx +0 -200
  44. package/src/charts/barHorizontalChart/README.MD +0 -278
  45. package/src/charts/barHorizontalChart/index.ts +0 -2
  46. package/src/charts/bubbleChart/BubbleChart.tsx +0 -184
  47. package/src/charts/bubbleChart/README.MD +0 -275
  48. package/src/charts/bubbleChart/index.ts +0 -1
  49. package/src/charts/floatBarChart/FloatBarChart.tsx +0 -178
  50. package/src/charts/floatBarChart/README.MD +0 -354
  51. package/src/charts/floatBarChart/index.ts +0 -1
  52. package/src/charts/lineChart/LineChart.tsx +0 -200
  53. package/src/charts/lineChart/README.MD +0 -354
  54. package/src/charts/lineChart/index.ts +0 -1
  55. package/src/charts/polarChart/PolarChart.tsx +0 -161
  56. package/src/charts/polarChart/README.MD +0 -336
  57. package/src/charts/polarChart/index.ts +0 -1
  58. package/src/charts/radarChart/README.MD +0 -388
  59. package/src/charts/radarChart/RadarChart.tsx +0 -173
  60. package/src/charts/radarChart/index.ts +0 -1
  61. package/src/charts/scatterChart/README.MD +0 -335
  62. package/src/charts/scatterChart/ScatterChart.tsx +0 -155
  63. package/src/charts/scatterChart/index.ts +0 -1
  64. package/src/charts/stackedLineChart/README.MD +0 -396
  65. package/src/charts/stackedLineChart/StackedLineChart.tsx +0 -188
  66. package/src/charts/stackedLineChart/index.ts +0 -1
  67. package/src/charts/steamChart/README.MD +0 -414
  68. package/src/charts/steamChart/SteamChart.tsx +0 -236
  69. package/src/charts/steamChart/index.ts +0 -1
  70. package/src/components/RenderLabel/RenderLabel.tsx +0 -39
  71. package/src/components/RenderLabel/index.ts +0 -2
  72. package/src/components/RenderLabel/useRenderLabelStylesStyles.ts +0 -25
  73. package/src/components/RenderLegend/RenderLegend.tsx +0 -40
  74. package/src/components/RenderTooltip/RenderTooltip.tsx +0 -111
  75. package/src/components/buttonMenu/ButtonMenu.tsx +0 -186
  76. package/src/components/buttonMenu/IButtonMenuOption.ts +0 -9
  77. package/src/components/buttonMenu/IButtonMenuProps.tsx +0 -40
  78. package/src/components/dashboard/DashBoard.tsx +0 -314
  79. package/src/components/dashboard/ExampleDashboardUsage.tsx +0 -114
  80. package/src/components/dashboard/IDashboardProps.tsx +0 -11
  81. package/src/components/dashboard/NoDashboards.tsx +0 -26
  82. package/src/components/dashboard/index.ts +0 -3
  83. package/src/components/dashboard/selectZoom/SelectZoom.tsx +0 -184
  84. package/src/components/dashboard/useDashboardStyles.ts +0 -76
  85. package/src/components/index.ts +0 -17
  86. package/src/components/legendContainer/LegendContainer.tsx +0 -118
  87. package/src/components/legendeButton/LegendButton.tsx +0 -57
  88. package/src/components/renderSliceLegend/RenderSliceLegend.tsx +0 -46
  89. package/src/components/renderValueLegend/RenderValueLegend.tsx +0 -43
  90. package/src/components/stack/IStackProps.tsx +0 -94
  91. package/src/components/stack/Stack.tsx +0 -103
  92. package/src/components/svgImages/BusinessReportIcon.tsx +0 -218
  93. package/src/components/themeProvider/ThemeProvider.tsx +0 -48
  94. package/src/constants/Constants.tsx +0 -23
  95. package/src/graphGlobalStyles/useGraphGlobalStyles.ts +0 -28
  96. package/src/hooks/index.ts +0 -1
  97. package/src/hooks/useChartFactory.tsx +0 -136
  98. package/src/hooks/useChartUtils.tsx +0 -187
  99. package/src/hooks/useIndexedDBCache.ts +0 -119
  100. package/src/hooks/useResponsiveLegend.ts +0 -35
  101. package/src/index.tsx +0 -5
  102. package/src/models/ChartDatum.ts +0 -4
  103. package/src/models/ICardChartContainer.tsx +0 -11
  104. package/src/models/IChart.ts +0 -50
  105. package/src/models/index.ts +0 -3
@@ -1,396 +0,0 @@
1
- # StackedLineChart Component
2
-
3
- A specialized stacked line chart component built with Chart.js and Fluent UI React. This component displays multiple data series as stacked areas with smooth line boundaries, making it perfect for visualizing cumulative data, part-to-whole relationships over time, and how different components contribute to a total value.
4
-
5
- ## Features
6
-
7
- - **Stacked Area Visualization**: Display multiple data series as cumulative stacked areas
8
- - **Smooth Line Boundaries**: Configurable line tension for smooth area transitions
9
- - **Interactive Legend**: Toggle series visibility with click interactions
10
- - **Cumulative Values**: Show how individual series contribute to total values
11
- - **Filled Areas**: Semi-transparent filled areas for better visual distinction
12
- - **Fluent UI Integration**: Seamless integration with Fluent UI themes and design system
13
- - **Data Labels**: Optional display of values directly on data points
14
- - **Responsive Design**: Automatically adapts to container dimensions
15
- - **TypeScript Support**: Full TypeScript support with generic types
16
- - **Custom Tooltips**: Rich tooltips showing detailed breakdown information
17
-
18
- ## Installation
19
-
20
- ```bash
21
- npm install chart.js react-chartjs-2 chartjs-plugin-datalabels @fluentui/react-components
22
- ```
23
-
24
- ## Basic Usage
25
-
26
- ```tsx
27
- import React from 'react';
28
- import { StackedLineChart } from './components/stackedLineChart/StackedLineChart';
29
- import { webLightTheme } from '@fluentui/react-components';
30
-
31
- interface RevenueData {
32
- month: string;
33
- subscriptions: number;
34
- oneTime: number;
35
- consulting: number;
36
- }
37
-
38
- const revenueData: RevenueData[] = [
39
- { month: 'Jan', subscriptions: 45000, oneTime: 12000, consulting: 8000 },
40
- { month: 'Feb', subscriptions: 48000, oneTime: 15000, consulting: 10000 },
41
- { month: 'Mar', subscriptions: 52000, oneTime: 18000, consulting: 12000 },
42
- { month: 'Apr', subscriptions: 55000, oneTime: 14000, consulting: 15000 },
43
- { month: 'May', subscriptions: 58000, oneTime: 16000, consulting: 18000 },
44
- { month: 'Jun', subscriptions: 62000, oneTime: 20000, consulting: 20000 },
45
- ];
46
-
47
- function App() {
48
- return (
49
- <div style={{ width: '800px', height: '500px' }}>
50
- <StackedLineChart
51
- data={[
52
- {
53
- label: 'Subscriptions',
54
- data: revenueData.map(d => ({ month: d.month, value: d.subscriptions }))
55
- },
56
- {
57
- label: 'One-time Sales',
58
- data: revenueData.map(d => ({ month: d.month, value: d.oneTime }))
59
- },
60
- {
61
- label: 'Consulting',
62
- data: revenueData.map(d => ({ month: d.month, value: d.consulting }))
63
- }
64
- ]}
65
- getPrimary={(datum) => datum.month}
66
- getSecondary={(datum) => datum.value}
67
- title="Revenue Breakdown Over Time"
68
- theme={webLightTheme}
69
- />
70
- </div>
71
- );
72
- }
73
- ```
74
-
75
- ## Props
76
-
77
- ### StackedLineChartProps<T>
78
-
79
- | Prop | Type | Required | Default | Description |
80
- |------|------|----------|---------|-------------|
81
- | `data` | `{ label: string; data: T[] }[]` | Yes | - | Array of data series with labels and data points |
82
- | `getPrimary` | `(datum: T) => string \| number` | Yes | - | Function to extract the x-axis category from each data point |
83
- | `getSecondary` | `(datum: T) => number` | Yes | - | Function to extract the y-axis value from each data point |
84
- | `title` | `string` | No | - | Chart title displayed at the top |
85
- | `showDataLabels` | `boolean` | No | `false` | Whether to show data values on data points |
86
- | `theme` | `Theme` | No | `webLightTheme` | Fluent UI theme object for styling |
87
-
88
- ## Advanced Usage
89
-
90
- ### Website Traffic Sources
91
-
92
- ```tsx
93
- interface TrafficData {
94
- date: string;
95
- organic: number;
96
- paid: number;
97
- social: number;
98
- direct: number;
99
- email: number;
100
- }
101
-
102
- const trafficData: TrafficData[] = [
103
- { date: '2024-01', organic: 12000, paid: 5000, social: 3000, direct: 8000, email: 2000 },
104
- { date: '2024-02', organic: 13500, paid: 5500, social: 3500, direct: 8500, email: 2200 },
105
- { date: '2024-03', organic: 15000, paid: 6000, social: 4000, direct: 9000, email: 2500 },
106
- { date: '2024-04', organic: 16500, paid: 6500, social: 4500, direct: 9500, email: 2800 },
107
- ];
108
-
109
- <StackedLineChart
110
- data={[
111
- {
112
- label: 'Organic Search',
113
- data: trafficData.map(d => ({ date: d.date, visitors: d.organic }))
114
- },
115
- {
116
- label: 'Paid Advertising',
117
- data: trafficData.map(d => ({ date: d.date, visitors: d.paid }))
118
- },
119
- {
120
- label: 'Social Media',
121
- data: trafficData.map(d => ({ date: d.date, visitors: d.social }))
122
- },
123
- {
124
- label: 'Direct Traffic',
125
- data: trafficData.map(d => ({ date: d.date, visitors: d.direct }))
126
- },
127
- {
128
- label: 'Email Marketing',
129
- data: trafficData.map(d => ({ date: d.date, visitors: d.email }))
130
- }
131
- ]}
132
- getPrimary={(datum) => datum.date}
133
- getSecondary={(datum) => datum.visitors}
134
- title="Website Traffic Sources Over Time"
135
- showDataLabels={true}
136
- theme={webLightTheme}
137
- />
138
- ```
139
-
140
- ### Expense Categories
141
-
142
- ```tsx
143
- interface ExpenseData {
144
- quarter: string;
145
- personnel: number;
146
- infrastructure: number;
147
- marketing: number;
148
- operations: number;
149
- research: number;
150
- }
151
-
152
- const expenseData: ExpenseData[] = [
153
- { quarter: 'Q1 2024', personnel: 150000, infrastructure: 45000, marketing: 35000, operations: 25000, research: 40000 },
154
- { quarter: 'Q2 2024', personnel: 165000, infrastructure: 50000, marketing: 40000, operations: 28000, research: 45000 },
155
- { quarter: 'Q3 2024', personnel: 180000, infrastructure: 55000, marketing: 45000, operations: 30000, research: 50000 },
156
- { quarter: 'Q4 2024', personnel: 195000, infrastructure: 60000, marketing: 50000, operations: 35000, research: 55000 },
157
- ];
158
-
159
- <StackedLineChart
160
- data={[
161
- {
162
- label: 'Personnel',
163
- data: expenseData.map(d => ({ quarter: d.quarter, amount: d.personnel }))
164
- },
165
- {
166
- label: 'Infrastructure',
167
- data: expenseData.map(d => ({ quarter: d.quarter, amount: d.infrastructure }))
168
- },
169
- {
170
- label: 'Marketing',
171
- data: expenseData.map(d => ({ quarter: d.quarter, amount: d.marketing }))
172
- },
173
- {
174
- label: 'Operations',
175
- data: expenseData.map(d => ({ quarter: d.quarter, amount: d.operations }))
176
- },
177
- {
178
- label: 'Research & Development',
179
- data: expenseData.map(d => ({ quarter: d.quarter, amount: d.research }))
180
- }
181
- ]}
182
- getPrimary={(datum) => datum.quarter}
183
- getSecondary={(datum) => datum.amount}
184
- title="Quarterly Expense Breakdown"
185
- theme={webLightTheme}
186
- />
187
- ```
188
-
189
- ### Population Demographics
190
-
191
- ```tsx
192
- interface DemographicData {
193
- year: number;
194
- age18_25: number;
195
- age26_35: number;
196
- age36_45: number;
197
- age46_55: number;
198
- age56_65: number;
199
- age65Plus: number;
200
- }
201
-
202
- const demographicData: DemographicData[] = [
203
- { year: 2020, age18_25: 15000, age26_35: 22000, age36_45: 18000, age46_55: 16000, age56_65: 12000, age65Plus: 8000 },
204
- { year: 2021, age18_25: 15500, age26_35: 23000, age36_45: 18500, age46_55: 16200, age56_65: 12500, age65Plus: 8500 },
205
- { year: 2022, age18_25: 16000, age26_35: 24000, age36_45: 19000, age46_55: 16500, age56_65: 13000, age65Plus: 9000 },
206
- { year: 2023, age18_25: 16500, age26_35: 25000, age36_45: 19500, age46_55: 16800, age56_65: 13500, age65Plus: 9500 },
207
- ];
208
-
209
- <StackedLineChart
210
- data={[
211
- {
212
- label: '18-25',
213
- data: demographicData.map(d => ({ year: d.year.toString(), count: d.age18_25 }))
214
- },
215
- {
216
- label: '26-35',
217
- data: demographicData.map(d => ({ year: d.year.toString(), count: d.age26_35 }))
218
- },
219
- {
220
- label: '36-45',
221
- data: demographicData.map(d => ({ year: d.year.toString(), count: d.age36_45 }))
222
- },
223
- {
224
- label: '46-55',
225
- data: demographicData.map(d => ({ year: d.year.toString(), count: d.age46_55 }))
226
- },
227
- {
228
- label: '56-65',
229
- data: demographicData.map(d => ({ year: d.year.toString(), count: d.age56_65 }))
230
- },
231
- {
232
- label: '65+',
233
- data: demographicData.map(d => ({ year: d.year.toString(), count: d.age65Plus }))
234
- }
235
- ]}
236
- getPrimary={(datum) => datum.year}
237
- getSecondary={(datum) => datum.count}
238
- title="Population by Age Group"
239
- showDataLabels={true}
240
- theme={webLightTheme}
241
- />
242
- ```
243
-
244
- ## Data Structure
245
-
246
- The component expects data in the following format:
247
-
248
- ```tsx
249
- interface ChartSeries<T> {
250
- label: string; // Series name (appears in legend)
251
- data: T[]; // Array of data points
252
- }
253
- ```
254
-
255
- Each data point `T` should contain:
256
-
257
- - A primary value (x-axis category) - string or number
258
- - A secondary value (y-axis value) - number
259
-
260
- ## Stacking Behavior
261
-
262
- ### Cumulative Values
263
-
264
- - Each series is stacked on top of the previous ones
265
- - The total height at any point represents the sum of all series values
266
- - Series order matters - bottom series appears first in the data array
267
-
268
- ### Visual Interpretation
269
-
270
- - **Area Size**: Represents the contribution of each series
271
- - **Total Height**: Shows the cumulative total across all series
272
- - **Trends**: Individual series trends are visible through area thickness changes
273
-
274
- ## Use Cases
275
-
276
- Stacked line charts are particularly effective for:
277
-
278
- ### Financial Analysis
279
-
280
- - **Revenue Breakdown**: Different revenue streams over time
281
- - **Expense Categories**: Cost distribution across departments
282
- - **Investment Portfolio**: Asset allocation changes over time
283
-
284
- ### Business Metrics
285
-
286
- - **Traffic Sources**: Website visitor sources and their evolution
287
- - **Sales Channels**: Performance of different sales channels
288
- - **Customer Segments**: Customer base composition over time
289
-
290
- ### Operational Data
291
-
292
- - **Resource Usage**: Computing resources, storage, bandwidth
293
- - **Production Output**: Different product lines or categories
294
- - **Team Performance**: Contribution of different teams to goals
295
-
296
- ### Market Analysis
297
-
298
- - **Market Share**: How different competitors' shares change
299
- - **Product Mix**: Sales composition by product category
300
- - **Geographic Performance**: Regional contribution to totals
301
-
302
- ## Interactive Features
303
-
304
- ### Legend Controls
305
-
306
- - Click legend items to show/hide data series
307
- - Visual feedback on hover states
308
- - At least one series must remain visible
309
- - Maintains stacking relationship when series are hidden
310
-
311
- ### Area Interactions
312
-
313
- - Hover effects on stacked areas
314
- - Rich tooltips showing breakdown of values
315
- - Smooth transitions and animations
316
-
317
- ### Responsive Layout
318
-
319
- - Chart automatically resizes to container dimensions
320
- - Legend positioning adapts to available space
321
- - Maintains readability across different screen sizes
322
-
323
- ## Styling and Theme Integration
324
-
325
- The component uses Fluent UI theme tokens:
326
-
327
- ```tsx
328
- // Area styling
329
- backgroundColor: seriesColor (semi-transparent fill)
330
- borderColor: seriesColor
331
- borderWidth: 2
332
- fill: true
333
- tension: 0.4 (smooth curves)
334
-
335
- // Points
336
- pointRadius: 3
337
- pointBackgroundColor: seriesColor
338
- pointBorderColor: seriesColor
339
-
340
- // Typography
341
- fontFamily: theme.fontFamilyBase
342
- fontSize: theme.fontSizeBase200
343
- fontWeight: theme.fontWeightSemibold
344
- color: theme.colorNeutralForeground1
345
-
346
- // Grid and axes
347
- labelColor: theme.colorNeutralForeground1
348
- gridColor: theme.colorNeutralStroke2
349
- ```
350
-
351
- ## Performance Optimizations
352
-
353
- The component includes several React optimizations:
354
-
355
- ````tsx
356
- // Memoized color calculations
357
- const seriesColors = useMemo(() => {
358
- return data.reduce((acc, series, idx) => {
359
- const base = getFluentPalette(theme)[
360
- idx % getFluentPalette(theme).length
361
- ];
362
- const color = lightenColor(base, 0.3);
363
- acc[series.label] = color;
364
- return acc;
365
- }, {} as Record<string, string>);
366
- }, [data, theme]);
367
-
368
- // Memoized category aggregation
369
- const allCategories = useMemo(() => {
370
- const set = new Set<string | number>();
371
- data.forEach(series => {
372
- series.data.forEach(d => set.add(getPrimary(d)));
373
- });
374
- return Array.from(set);
375
- }, [data, getPrimary]);
376
-
377
- // Memoized chart data transformation
378
- const chartData = useMemo(() => {
379
- return {
380
- labels: allCategories,
381
- datasets: data
382
- .filter(series => visibleSeries.includes(series.label))
383
- .map(series => ({
384
- label: series.label,
385
- data: allCategories.map(cat => {
386
- const match = series.data.find(d => getPrimary(d) === cat);
387
- return match ? getSecondary(match) : 0;
388
- }),
389
- borderColor: seriesColors[series.label],
390
- backgroundColor: seriesColors[series.label],
391
- fill: true,
392
- tension: 0.4,
393
- pointRadius: 3,
394
- })),
395
- };
396
- }, [data, visibleSeries, allCategories, getPrimary, getSecondary, seriesColors]);
@@ -1,188 +0,0 @@
1
- import {
2
- CategoryScale,
3
- Chart as ChartJS,
4
- ChartOptions,
5
- Legend,
6
- LineElement,
7
- LinearScale,
8
- PointElement,
9
- Title,
10
- Tooltip,
11
- } from 'chart.js';
12
- import React, { useMemo, useState } from 'react';
13
- import { Theme, webLightTheme } from '@fluentui/react-components';
14
-
15
- import ChartDataLabels from 'chartjs-plugin-datalabels';
16
- import { Line } from 'react-chartjs-2';
17
- import RenderLegend from '../../components/RenderLegend/RenderLegend';
18
- import { useChartUtils } from '../../hooks/useChartUtils';
19
- import { useGraphGlobalStyles } from '../../graphGlobalStyles/useGraphGlobalStyles';
20
-
21
- ChartJS.register(ChartDataLabels);
22
- ChartJS.register(
23
- CategoryScale,
24
- LinearScale,
25
- LineElement,
26
- PointElement,
27
- Tooltip,
28
- Legend,
29
- Title
30
- );
31
-
32
- export interface StackedLineChartProps<T> {
33
- data: { label: string; data: T[] }[];
34
- getPrimary: (datum: T) => string | number;
35
- getSecondary: (datum: T) => number;
36
- title?: string;
37
- showDataLabels?: boolean;
38
- theme?: Theme;
39
- }
40
-
41
- export default function StackedLineChart<T extends object>({
42
- data,
43
- getPrimary,
44
- getSecondary,
45
- title,
46
- showDataLabels = false,
47
- theme = webLightTheme,
48
- }: StackedLineChartProps<T>) {
49
- const [visibleSeries, setVisibleSeries] = useState(() =>
50
- data.length > 1 ? data.map(s => s.label) : [data[0]?.label]
51
- );
52
-
53
- const styles = useGraphGlobalStyles();
54
- const { lightenColor, getFluentPalette, createFluentTooltip } = useChartUtils(theme);
55
-
56
- const seriesColors = useMemo(() => {
57
- return data.reduce((acc, series, idx) => {
58
- const base = getFluentPalette(theme)[
59
- idx % getFluentPalette(theme).length
60
- ];
61
- const color = lightenColor(base, 0.3);
62
- acc[series.label] = color;
63
- return acc;
64
- }, {} as Record<string, string>);
65
- }, [data, theme]);
66
-
67
- const toggleSeries = (label: string) => {
68
- setVisibleSeries(prev => {
69
- const isVisible = prev.includes(label);
70
- const next = isVisible ? prev.filter(l => l !== label) : [...prev, label];
71
- return next.length === 0 && data.length > 0 ? [data[0].label] : next;
72
- });
73
- };
74
-
75
- const allCategories = useMemo(() => {
76
- const set = new Set<string | number>();
77
- data.forEach(series => {
78
- series.data.forEach(d => set.add(getPrimary(d)));
79
- });
80
- return Array.from(set);
81
- }, [data, getPrimary]);
82
-
83
- const chartData = useMemo(() => {
84
- return {
85
- labels: allCategories,
86
- datasets: data
87
- .filter(series => visibleSeries.includes(series.label))
88
- .map(series => ({
89
- label: series.label,
90
- data: allCategories.map(cat => {
91
- const match = series.data.find(d => getPrimary(d) === cat);
92
- return match ? getSecondary(match) : 0;
93
- }),
94
- borderColor: seriesColors[series.label],
95
- backgroundColor: seriesColors[series.label],
96
- fill: true,
97
- tension: 0.4,
98
- pointRadius: 3,
99
- })),
100
- };
101
- }, [
102
- data,
103
- visibleSeries,
104
- allCategories,
105
- getPrimary,
106
- getSecondary,
107
- seriesColors,
108
- ]);
109
-
110
- const { fontFamily, fontSize, labelColor, gridColor } = useMemo(() => ({
111
- fontFamily: theme.fontFamilyBase,
112
- fontSize: parseInt(theme.fontSizeBase200.replace('px', '')) || 14,
113
- labelColor: theme.colorNeutralForeground1,
114
- gridColor: theme.colorNeutralStroke2,
115
- }), [theme]);
116
-
117
- const options = useMemo<ChartOptions<'line'>>(() => ({
118
- responsive: true,
119
- maintainAspectRatio: false,
120
- plugins: {
121
- title: {
122
- display: !!title,
123
- text: title,
124
- font: {
125
- size: 14,
126
- family: theme.fontFamilyBase,
127
- weight: theme.fontWeightSemibold,
128
- },
129
- color: theme.colorNeutralForeground1,
130
- padding: {
131
- top: 20,
132
- bottom: 20,
133
- },
134
- },
135
- datalabels: {
136
- display: showDataLabels,
137
- color: theme.colorNeutralForeground1,
138
- font: {
139
- family: theme.fontFamilyBase,
140
- size: parseInt(theme.fontSizeBase200.replace('px', '')) || 14,
141
- },
142
- },
143
- legend: { display: false },
144
- tooltip: createFluentTooltip<'line'>(theme),
145
- },
146
- scales: {
147
- x: {
148
- stacked: true,
149
- ticks: {
150
- color: labelColor,
151
- font: { family: fontFamily, size: fontSize },
152
- },
153
- grid: { color: gridColor },
154
- },
155
- y: {
156
- stacked: true,
157
- ticks: {
158
- color: labelColor,
159
- font: { family: fontFamily, size: fontSize },
160
- },
161
- grid: { color: gridColor },
162
- },
163
- },
164
- }), [
165
- theme,
166
- title,
167
- showDataLabels,
168
- createFluentTooltip,
169
- labelColor,
170
- fontFamily,
171
- fontSize,
172
- gridColor,
173
- ]);
174
-
175
- return (
176
- <div className={styles.chartWithLegend}>
177
- <div className={styles.chartArea}>
178
- <Line data={chartData} options={options} />
179
- </div>
180
- <RenderLegend
181
- data={data}
182
- visibleSeries={visibleSeries}
183
- seriesColors={seriesColors}
184
- toggleSeries={toggleSeries}
185
- />
186
- </div>
187
- );
188
- }
@@ -1 +0,0 @@
1
- export * from './StackedLineChart';