@react-magma/charts 13.0.4-next.0 → 13.1.1-next.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 (35) hide show
  1. package/dist/charts.js +447 -27
  2. package/dist/charts.js.map +1 -1
  3. package/dist/charts.modern.module.js +443 -30
  4. package/dist/charts.modern.module.js.map +1 -1
  5. package/dist/charts.umd.js +1608 -228
  6. package/dist/charts.umd.js.map +1 -1
  7. package/dist/components/CarbonChart/CarbonChart.d.ts +41 -0
  8. package/dist/components/ChartTable/ChartDataTable.d.ts +19 -0
  9. package/dist/components/ChartTable/ChartFullscreenButton.d.ts +26 -0
  10. package/dist/components/ChartTable/ChartMoreOptionsButton.d.ts +18 -0
  11. package/dist/components/ChartTable/ChartTable.stories.d.ts +116 -0
  12. package/dist/components/ChartTable/ChartTable.test.d.ts +1 -0
  13. package/dist/components/ChartTable/ChartTableButton.d.ts +24 -0
  14. package/dist/components/ChartTable/ChartTableModal.d.ts +44 -0
  15. package/dist/components/ChartTable/ChartToolbar.d.ts +19 -0
  16. package/dist/components/ChartTable/chartToolbarI18n.d.ts +16 -0
  17. package/dist/components/ChartTable/index.d.ts +14 -0
  18. package/dist/components/LineChart/DataTable.d.ts +1 -1
  19. package/dist/index.d.ts +1 -0
  20. package/package.json +5 -5
  21. package/src/components/CarbonChart/CarbonChart.test.js +143 -2
  22. package/src/components/CarbonChart/CarbonChart.tsx +603 -15
  23. package/src/components/ChartTable/ChartDataTable.tsx +72 -0
  24. package/src/components/ChartTable/ChartFullscreenButton.tsx +59 -0
  25. package/src/components/ChartTable/ChartMoreOptionsButton.tsx +47 -0
  26. package/src/components/ChartTable/ChartTable.stories.tsx +152 -0
  27. package/src/components/ChartTable/ChartTable.test.tsx +444 -0
  28. package/src/components/ChartTable/ChartTableButton.tsx +55 -0
  29. package/src/components/ChartTable/ChartTableModal.tsx +135 -0
  30. package/src/components/ChartTable/ChartToolbar.tsx +50 -0
  31. package/src/components/ChartTable/chartToolbarI18n.ts +55 -0
  32. package/src/components/ChartTable/index.ts +23 -0
  33. package/src/components/LineChart/DataTable.tsx +3 -3
  34. package/src/components/LineChart/LineChart.tsx +1 -1
  35. package/src/index.ts +1 -0
@@ -0,0 +1,72 @@
1
+ import * as React from 'react';
2
+
3
+ import {
4
+ Table,
5
+ TableBody,
6
+ TableCell,
7
+ TableHead,
8
+ TableHeaderCell,
9
+ TableRow,
10
+ } from 'react-magma-dom';
11
+
12
+ export interface ChartDataTableColumn {
13
+ /** Header text for this column */
14
+ header: string;
15
+ /** Key to read from each row object */
16
+ key: string;
17
+ }
18
+
19
+ export interface ChartDataTableProps {
20
+ /** Column definitions (header + key). If omitted, columns are auto-derived from the dataset object keys with the first character capitalized (e.g. "group" → "Group"). */
21
+ columns?: ChartDataTableColumn[];
22
+ /** Array of data objects. Each object should have keys matching the column `key` values. */
23
+ dataSet: Array<Record<string, React.ReactNode>>;
24
+ /**
25
+ * If true, the table uses inverse (dark) styling.
26
+ * @default false
27
+ */
28
+ isInverse?: boolean;
29
+ }
30
+
31
+ function deriveColumns(
32
+ dataSet: Array<Record<string, React.ReactNode>>
33
+ ): ChartDataTableColumn[] {
34
+ if (!dataSet.length) return [];
35
+ return Object.keys(dataSet[0]).map(key => ({
36
+ header: key.charAt(0).toUpperCase() + key.slice(1),
37
+ key,
38
+ }));
39
+ }
40
+
41
+ export function ChartDataTable({
42
+ columns,
43
+ dataSet,
44
+ isInverse,
45
+ }: ChartDataTableProps) {
46
+ const resolvedColumns = columns || deriveColumns(dataSet);
47
+ return (
48
+ <Table isInverse={isInverse}>
49
+ <TableHead>
50
+ <TableRow>
51
+ {resolvedColumns.map(col => (
52
+ <TableHeaderCell key={col.key}>{col.header}</TableHeaderCell>
53
+ ))}
54
+ </TableRow>
55
+ </TableHead>
56
+ <TableBody>
57
+ {dataSet.map((row, index) => {
58
+ const rowKey = resolvedColumns
59
+ .map(col => String(row[col.key] ?? ''))
60
+ .join('-');
61
+ return (
62
+ <TableRow key={`${rowKey}-${index}`}>
63
+ {resolvedColumns.map(col => (
64
+ <TableCell key={col.key}>{row[col.key]}</TableCell>
65
+ ))}
66
+ </TableRow>
67
+ );
68
+ })}
69
+ </TableBody>
70
+ </Table>
71
+ );
72
+ }
@@ -0,0 +1,59 @@
1
+ import * as React from 'react';
2
+
3
+ import { ButtonVariant, IconButton, Tooltip } from 'react-magma-dom';
4
+
5
+ import { useChartToolbarI18n } from './chartToolbarI18n';
6
+
7
+ export interface ChartFullscreenButtonProps {
8
+ /** Accessible label for the button, e.g. "View Overall Performance in full screen" */
9
+ ariaLabel: string;
10
+ /** Icon rendered when not in fullscreen mode */
11
+ icon: React.ReactElement;
12
+ /** Icon rendered when in fullscreen mode. Falls back to `icon` if omitted. */
13
+ exitIcon?: React.ReactElement;
14
+ /**
15
+ * If true, the button uses inverse (dark) styling.
16
+ * @default false
17
+ */
18
+ isInverse?: boolean;
19
+ /** Whether the chart is currently in fullscreen mode */
20
+ isFullscreen: boolean;
21
+ /** Click handler – should toggle fullscreen */
22
+ onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
23
+ /** Optional ref forwarded to the underlying IconButton */
24
+ buttonRef?: React.Ref<HTMLButtonElement>;
25
+ /**
26
+ * Tooltip text shown on hover.
27
+ * @default "Make full screen" / "Exit full screen" based on state (i18n overridable)
28
+ */
29
+ tooltipContent?: string;
30
+ }
31
+
32
+ export function ChartFullscreenButton({
33
+ ariaLabel,
34
+ buttonRef,
35
+ exitIcon,
36
+ icon,
37
+ isInverse,
38
+ isFullscreen,
39
+ onClick,
40
+ tooltipContent,
41
+ }: ChartFullscreenButtonProps) {
42
+ const t = useChartToolbarI18n();
43
+ const resolvedTooltip =
44
+ tooltipContent ?? (isFullscreen ? t.exitFullScreen : t.makeFullScreen);
45
+ const resolvedIcon = isFullscreen && exitIcon ? exitIcon : icon;
46
+
47
+ return (
48
+ <Tooltip content={resolvedTooltip} isInverse={isInverse}>
49
+ <IconButton
50
+ aria-label={ariaLabel}
51
+ icon={resolvedIcon}
52
+ isInverse={isInverse}
53
+ onClick={onClick}
54
+ ref={buttonRef}
55
+ variant={ButtonVariant.link}
56
+ />
57
+ </Tooltip>
58
+ );
59
+ }
@@ -0,0 +1,47 @@
1
+ import * as React from 'react';
2
+
3
+ import {
4
+ ButtonVariant,
5
+ Dropdown,
6
+ DropdownButton,
7
+ DropdownContent,
8
+ } from 'react-magma-dom';
9
+
10
+ import { useChartToolbarI18n } from './chartToolbarI18n';
11
+
12
+ export interface ChartMoreOptionsButtonProps {
13
+ /**
14
+ * Accessible label for the trigger button.
15
+ * @default "More options" (i18n overridable)
16
+ */
17
+ ariaLabel?: string;
18
+ /** Menu items rendered inside the dropdown (DropdownMenuItem, DropdownDivider, etc.) */
19
+ children: React.ReactNode;
20
+ /** Icon element rendered inside the trigger button */
21
+ icon: React.ReactElement;
22
+ /**
23
+ * If true, the dropdown uses inverse (dark) styling.
24
+ * @default false
25
+ */
26
+ isInverse?: boolean;
27
+ }
28
+
29
+ export function ChartMoreOptionsButton({
30
+ ariaLabel,
31
+ children,
32
+ icon,
33
+ isInverse,
34
+ }: ChartMoreOptionsButtonProps) {
35
+ const t = useChartToolbarI18n();
36
+ const resolvedAriaLabel = ariaLabel ?? t.moreOptionsAriaLabel;
37
+ return (
38
+ <Dropdown isInverse={isInverse}>
39
+ <DropdownButton
40
+ aria-label={resolvedAriaLabel}
41
+ icon={icon}
42
+ variant={ButtonVariant.link}
43
+ />
44
+ <DropdownContent>{children}</DropdownContent>
45
+ </Dropdown>
46
+ );
47
+ }
@@ -0,0 +1,152 @@
1
+ import React from 'react';
2
+
3
+ import { StoryFn, Meta } from '@storybook/react/types-6-0';
4
+ import { Card } from 'react-magma-dom';
5
+
6
+ import { CarbonChart, CarbonChartProps, CarbonChartType } from '../CarbonChart';
7
+
8
+ export default {
9
+ component: CarbonChart,
10
+ title: 'CarbonChart/ChartToolbar',
11
+ argTypes: {
12
+ isInverse: {
13
+ control: { type: 'boolean' },
14
+ },
15
+ },
16
+ } as Meta;
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Shared data
20
+ // ---------------------------------------------------------------------------
21
+
22
+ const donutDataSet = [
23
+ { group: 'Not attempted', value: 5 },
24
+ { group: 'Poor performance (Score less than 33%)', value: 15 },
25
+ { group: 'High performance (Score greater than 66%)', value: 50 },
26
+ { group: 'Average performance (Score between 33% and 66%)', value: 30 },
27
+ ];
28
+
29
+ const barDataSet = [
30
+ { group: 'Chapter 1', value: 85 },
31
+ { group: 'Chapter 2', value: 72 },
32
+ { group: 'Chapter 3', value: 91 },
33
+ { group: 'Chapter 4', value: 64 },
34
+ ];
35
+
36
+ // ---------------------------------------------------------------------------
37
+ // Full toolbar – Donut chart (all buttons via chartToolbar prop)
38
+ // ---------------------------------------------------------------------------
39
+
40
+ /**
41
+ * Full toolbar with Show as Table, Full Screen, and More Options buttons,
42
+ * driven entirely by the `chartToolbar` prop on CarbonChart.
43
+ *
44
+ * Carbon's built-in toolbar is automatically disabled when `chartToolbar`
45
+ * is provided. The Magma toolbar renders accessible replacements with
46
+ * proper ARIA attributes, focus management, and heading semantics.
47
+ */
48
+ const FullToolbarTemplate: StoryFn<CarbonChartProps> = args => (
49
+ <Card isInverse={args.isInverse} style={{ padding: '12px' }}>
50
+ <CarbonChart {...args} />
51
+ </Card>
52
+ );
53
+
54
+ export const DonutWithToolbar = {
55
+ render: FullToolbarTemplate,
56
+ args: {
57
+ isInverse: false,
58
+ type: CarbonChartType.donut,
59
+ dataSet: donutDataSet,
60
+ options: {
61
+ title: 'Overall Activity Performance',
62
+ resizable: true,
63
+ height: '400px',
64
+ donut: {
65
+ center: { label: 'Questions' },
66
+ },
67
+ legend: {
68
+ truncation: { type: 'none' },
69
+ },
70
+ },
71
+ chartToolbar: {},
72
+ },
73
+ };
74
+
75
+ // ---------------------------------------------------------------------------
76
+ // Bar chart with custom table columns
77
+ // ---------------------------------------------------------------------------
78
+
79
+ export const BarWithToolbar = {
80
+ render: FullToolbarTemplate,
81
+ args: {
82
+ isInverse: false,
83
+ type: CarbonChartType.bar,
84
+ dataSet: barDataSet,
85
+ options: {
86
+ title: 'Chapter Performance',
87
+ axes: {
88
+ left: { mapsTo: 'value' },
89
+ bottom: { mapsTo: 'group', scaleType: 'labels' },
90
+ },
91
+ height: '400px',
92
+ },
93
+ chartToolbar: {
94
+ tableColumns: [
95
+ { header: 'Chapter', key: 'group' },
96
+ { header: 'Score (%)', key: 'value' },
97
+ ],
98
+ },
99
+ },
100
+ };
101
+
102
+ // ---------------------------------------------------------------------------
103
+ // Inverse theme
104
+ // ---------------------------------------------------------------------------
105
+
106
+ export const InverseTheme = {
107
+ render: FullToolbarTemplate,
108
+ args: {
109
+ isInverse: true,
110
+ type: CarbonChartType.donut,
111
+ dataSet: donutDataSet,
112
+ options: {
113
+ title: 'Inverse Theme Demo',
114
+ resizable: true,
115
+ height: '400px',
116
+ donut: {
117
+ center: { label: 'Questions' },
118
+ },
119
+ legend: {
120
+ truncation: { type: 'none' },
121
+ },
122
+ },
123
+ chartToolbar: {},
124
+ },
125
+ };
126
+
127
+ // ---------------------------------------------------------------------------
128
+ // Table only (no fullscreen or more options)
129
+ // ---------------------------------------------------------------------------
130
+
131
+ export const TableOnly = {
132
+ render: FullToolbarTemplate,
133
+ args: {
134
+ isInverse: false,
135
+ type: CarbonChartType.donut,
136
+ dataSet: donutDataSet,
137
+ options: {
138
+ title: 'Table Only (No Fullscreen)',
139
+ resizable: true,
140
+ height: '400px',
141
+ donut: {
142
+ center: { label: 'Questions' },
143
+ },
144
+ legend: {
145
+ truncation: { type: 'none' },
146
+ },
147
+ },
148
+ chartToolbar: {
149
+ fullscreen: false,
150
+ },
151
+ },
152
+ };