@automattic/charts 0.26.0 → 0.28.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 (62) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/cjs/components/bar-chart/bar-chart.js +16 -6
  3. package/dist/cjs/components/leaderboard-chart/leaderboard-chart.js +23 -14
  4. package/dist/cjs/components/leaderboard-chart/leaderboard-chart.module.scss.js +1 -1
  5. package/dist/cjs/components/legend/base-legend.js +6 -2
  6. package/dist/cjs/components/legend/use-chart-legend-data.js +6 -2
  7. package/dist/cjs/components/line-chart/line-chart-annotation.js +7 -4
  8. package/dist/cjs/components/line-chart/line-chart.js +16 -6
  9. package/dist/cjs/components/pie-chart/index.js +1 -0
  10. package/dist/cjs/components/pie-chart/pie-chart.js +115 -31
  11. package/dist/cjs/components/pie-semi-circle-chart/pie-semi-circle-chart.js +111 -19
  12. package/dist/cjs/hooks/use-chart-mouse-handler.js +1 -3
  13. package/dist/cjs/hooks/use-deep-memo.js +21 -0
  14. package/dist/cjs/hooks/use-global-chart-theme.js +28 -0
  15. package/dist/cjs/hooks/use-xychart-theme.js +20 -0
  16. package/dist/cjs/index.js +9 -1
  17. package/dist/cjs/providers/chart-context/global-charts-provider.js +5 -2
  18. package/dist/cjs/providers/chart-context/utils.js +11 -5
  19. package/dist/cjs/providers/theme/index.js +0 -1
  20. package/dist/cjs/providers/theme/theme-provider.js +2 -18
  21. package/dist/cjs/style.css +1 -1
  22. package/dist/cjs/utils/merge-themes.js +21 -0
  23. package/dist/mjs/components/bar-chart/bar-chart.js +15 -5
  24. package/dist/mjs/components/leaderboard-chart/leaderboard-chart.js +24 -15
  25. package/dist/mjs/components/leaderboard-chart/leaderboard-chart.module.scss.js +1 -1
  26. package/dist/mjs/components/legend/base-legend.js +6 -2
  27. package/dist/mjs/components/legend/use-chart-legend-data.js +6 -2
  28. package/dist/mjs/components/line-chart/line-chart-annotation.js +7 -4
  29. package/dist/mjs/components/line-chart/line-chart.js +15 -5
  30. package/dist/mjs/components/pie-chart/index.js +1 -1
  31. package/dist/mjs/components/pie-chart/pie-chart.js +116 -33
  32. package/dist/mjs/components/pie-semi-circle-chart/pie-semi-circle-chart.js +114 -22
  33. package/dist/mjs/hooks/use-chart-mouse-handler.js +1 -1
  34. package/dist/mjs/hooks/use-deep-memo.js +19 -0
  35. package/dist/mjs/hooks/use-global-chart-theme.js +26 -0
  36. package/dist/mjs/hooks/use-xychart-theme.js +18 -0
  37. package/dist/mjs/index.js +5 -1
  38. package/dist/mjs/providers/chart-context/global-charts-provider.js +6 -3
  39. package/dist/mjs/providers/chart-context/utils.js +11 -5
  40. package/dist/mjs/providers/theme/index.js +1 -1
  41. package/dist/mjs/providers/theme/theme-provider.js +4 -19
  42. package/dist/mjs/style.css +1 -1
  43. package/dist/mjs/utils/merge-themes.js +19 -0
  44. package/dist/types/components/bar-list-chart/bar-list-chart.d.ts +1 -1
  45. package/dist/types/components/leaderboard-chart/leaderboard-chart.d.ts +22 -13
  46. package/dist/types/components/legend/base-legend.d.ts +9 -9
  47. package/dist/types/components/legend/use-chart-legend-data.d.ts +2 -3
  48. package/dist/types/components/pie-chart/index.d.ts +1 -1
  49. package/dist/types/components/pie-chart/pie-chart.d.ts +14 -5
  50. package/dist/types/components/pie-semi-circle-chart/pie-semi-circle-chart.d.ts +16 -4
  51. package/dist/types/hooks/use-chart-mouse-handler.d.ts +1 -1
  52. package/dist/types/hooks/use-deep-memo.d.ts +10 -0
  53. package/dist/types/hooks/use-global-chart-theme.d.ts +14 -0
  54. package/dist/types/hooks/use-xychart-theme.d.ts +6 -0
  55. package/dist/types/index.d.ts +5 -1
  56. package/dist/types/providers/chart-context/global-charts-provider.d.ts +3 -0
  57. package/dist/types/providers/chart-context/types.d.ts +2 -1
  58. package/dist/types/providers/chart-context/utils.d.ts +7 -2
  59. package/dist/types/providers/theme/index.d.ts +1 -1
  60. package/dist/types/providers/theme/theme-provider.d.ts +3 -5
  61. package/dist/types/utils/merge-themes.d.ts +13 -0
  62. package/package.json +2 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.28.0] - 2025-08-21
9
+ ### Added
10
+ - Charts: adds composition legend to pie family charts [#44796]
11
+ - Charts: Add theme to global context and use instead of that from theme provider [#44809]
12
+
13
+ ## [0.27.0] - 2025-08-18
14
+ ### Added
15
+ - Add support for custom labels in the leaderboard chart for greater flexibility. [#44751]
16
+
8
17
  ## [0.26.0] - 2025-08-14
9
18
  ### Added
10
19
  - Bar Chart: Add composition API. [#44771]
@@ -371,6 +380,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
371
380
  - Fixed lints following ESLint rule changes for TS [#40584]
372
381
  - Fixing a bug in Chart storybook data. [#40640]
373
382
 
383
+ [0.28.0]: https://github.com/Automattic/charts/compare/v0.27.0...v0.28.0
384
+ [0.27.0]: https://github.com/Automattic/charts/compare/v0.26.0...v0.27.0
374
385
  [0.26.0]: https://github.com/Automattic/charts/compare/v0.25.0...v0.26.0
375
386
  [0.25.0]: https://github.com/Automattic/charts/compare/v0.24.0...v0.25.0
376
387
  [0.24.0]: https://github.com/Automattic/charts/compare/v0.23.1...v0.24.0
@@ -8,9 +8,13 @@ var xychart = require('@visx/xychart');
8
8
  var i18n = require('@wordpress/i18n');
9
9
  var clsx = require('clsx');
10
10
  var react = require('react');
11
+ require('fast-deep-equal');
12
+ var useGlobalChartTheme = require('../../hooks/use-global-chart-theme.js');
13
+ require('@visx/event');
14
+ require('@visx/tooltip');
15
+ var useXychartTheme = require('../../hooks/use-xychart-theme.js');
11
16
  var globalChartsProvider = require('../../providers/chart-context/global-charts-provider.js');
12
17
  var utils = require('../../providers/chart-context/utils.js');
13
- var themeProvider = require('../../providers/theme/theme-provider.js');
14
18
  var createComposition = require('../../utils/create-composition.js');
15
19
  var legend = require('../legend/legend.js');
16
20
  require('../legend/base-legend.js');
@@ -42,15 +46,15 @@ const getPatternId = (chartId, index) => `bar-pattern-${chartId}-${index}`;
42
46
  const BarChartInternal = ({ data, chartId: providedChartId, width, height = 400, className, margin, withTooltips = false, showLegend = false, legendOrientation = 'horizontal', legendPosition = 'bottom', legendAlignment = 'center', legendShape = 'rect', gridVisibility: gridVisibilityProp, renderTooltip, options = {}, orientation = 'vertical', withPatterns = false, showZeroValues = false, children, }) => {
43
47
  const horizontal = orientation === 'horizontal';
44
48
  const chartId = utils.useChartId(providedChartId);
45
- const providerTheme = themeProvider.useChartTheme();
46
- const theme = themeProvider.useXYChartTheme(data);
49
+ const providerTheme = useGlobalChartTheme.useGlobalChartTheme();
50
+ const theme = useXychartTheme.useXYChartTheme(data);
47
51
  const dataSorted = useChartDataTransform.useChartDataTransform(data);
48
52
  // Transform data to add a small value for zero bars to make them visible
49
53
  const dataWithVisibleZeros = useZeroValueDisplay.useZeroValueDisplay(dataSorted, {
50
54
  enabled: showZeroValues,
51
55
  });
52
56
  // Create legend items using the reusable hook
53
- const legendItems = useChartLegendData.useChartLegendData(dataSorted, providerTheme);
57
+ const legendItems = useChartLegendData.useChartLegendData(dataSorted);
54
58
  const chartOptions = useBarChartOptions.useBarChartOptions(dataWithVisibleZeros, horizontal, options);
55
59
  const defaultMargin = useChartMargin.useChartMargin(height, chartOptions, dataSorted, theme, horizontal);
56
60
  const [legendRef, legendHeight] = useElementHeight.useElementHeight();
@@ -67,7 +71,7 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height = 400,
67
71
  chartRef,
68
72
  totalPoints,
69
73
  });
70
- const getColor = react.useCallback((seriesData, index) => seriesData?.options?.stroke || theme.colors[index % theme.colors.length], [theme]);
74
+ const getColor = react.useCallback((seriesData, index) => seriesData?.options?.stroke || providerTheme.colors[index % providerTheme.colors.length], [providerTheme]);
71
75
  const getBarBackground = react.useCallback((index) => () => withPatterns
72
76
  ? `url(#${getPatternId(chartId, index)})`
73
77
  : getColor(dataSorted[index], index), [withPatterns, getColor, dataSorted, chartId]);
@@ -146,7 +150,13 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height = 400,
146
150
  withPatterns,
147
151
  }), [orientation, withPatterns]);
148
152
  // Register chart with context only if data is valid
149
- utils.useChartRegistration(chartId, legendItems, providerTheme, 'bar', isDataValid, chartMetadata);
153
+ utils.useChartRegistration({
154
+ chartId,
155
+ legendItems,
156
+ chartType: 'bar',
157
+ isDataValid,
158
+ metadata: chartMetadata,
159
+ });
150
160
  if (error) {
151
161
  return jsxRuntime.jsx("div", { className: clsx('bar-chart', barChart_module.default['bar-chart']), children: error });
152
162
  }
@@ -7,7 +7,11 @@ var components = require('@wordpress/components');
7
7
  var element = require('@wordpress/element');
8
8
  var clsx = require('clsx');
9
9
  require('react');
10
- var themeProvider = require('../../providers/theme/theme-provider.js');
10
+ require('fast-deep-equal');
11
+ var useGlobalChartTheme = require('../../hooks/use-global-chart-theme.js');
12
+ require('@visx/event');
13
+ require('@visx/tooltip');
14
+ require('@visx/xychart');
11
15
  var formatMetricValue = require('../shared/format-metric-value.js');
12
16
  var leaderboardChart_module = require('./leaderboard-chart.module.scss.js');
13
17
 
@@ -46,24 +50,27 @@ const defaultDeltaFormatter = (value) => {
46
50
  signDisplay: 'exceptZero',
47
51
  });
48
52
  };
53
+ const ProgressBarWithOverlayLabel = ({ entry }) => (jsxRuntime.jsxs("div", { className: leaderboardChart_module.default.progressContainerWithOverlayLabel, children: [typeof entry.label === 'string' ? (jsxRuntime.jsx(components.__experimentalText, { className: leaderboardChart_module.default.progressBarLabel, children: entry.label })) : (entry.label), jsxRuntime.jsx("div", { className: leaderboardChart_module.default.progressBar, style: { width: entry.currentShare + '%' } })] }));
54
+ const ProgressBarWithLabel = ({ entry, withComparison, }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [typeof entry.label === 'string' ? jsxRuntime.jsx(components.__experimentalText, { children: entry.label }) : entry.label, jsxRuntime.jsxs("div", { className: leaderboardChart_module.default.progressContainer, children: [jsxRuntime.jsx(components.ProgressBar, { value: entry.currentShare, className: clsx(leaderboardChart_module.default.progressBar, leaderboardChart_module.default.primaryBar) }), withComparison && (jsxRuntime.jsx(components.ProgressBar, { value: entry.previousShare, className: clsx(leaderboardChart_module.default.progressBar, leaderboardChart_module.default.secondaryBar) }))] })] }));
49
55
  /**
50
56
  * LeaderboardChart component displays a ranked list of data with progress bars
51
57
  * and optional comparison values.
52
58
  *
53
- * @param props - Component props
54
- * @param props.data - Array of leaderboard entries to display
55
- * @param props.withComparison - Whether to show comparison data
56
- * @param props.primaryColor - Primary color for current period bars
57
- * @param props.secondaryColor - Secondary color for comparison period bars
58
- * @param props.valueFormatter - Custom formatter for values
59
- * @param props.deltaFormatter - Custom formatter for delta values
60
- * @param props.loading - Whether the chart is in loading state
61
- * @param props.className - Additional CSS class name
62
- * @param props.style - Custom styling for the chart container
59
+ * @param props - Component props
60
+ * @param props.data - Array of leaderboard entries to display
61
+ * @param props.withComparison - Whether to show comparison data
62
+ * @param props.withOverlayLabel - Whether to overlay the label on top of the bar
63
+ * @param props.primaryColor - Primary color for current period bars
64
+ * @param props.secondaryColor - Secondary color for comparison period bars
65
+ * @param props.valueFormatter - Custom formatter for values
66
+ * @param props.deltaFormatter - Custom formatter for delta values
67
+ * @param props.loading - Whether the chart is in loading state
68
+ * @param props.className - Additional CSS class name
69
+ * @param props.style - Custom styling for the chart container
63
70
  * @return JSX element representing the leaderboard chart
64
71
  */
65
- const LeaderboardChart = ({ data, withComparison = false, primaryColor, secondaryColor, valueFormatter = defaultValueFormatter, deltaFormatter = defaultDeltaFormatter, loading = false, className, style, }) => {
66
- const theme = themeProvider.useChartTheme();
72
+ const LeaderboardChart = ({ data, withComparison = false, withOverlayLabel = false, primaryColor, secondaryColor, valueFormatter = defaultValueFormatter, deltaFormatter = defaultDeltaFormatter, loading = false, className, style, }) => {
73
+ const theme = useGlobalChartTheme.useGlobalChartTheme();
67
74
  // Get component settings from theme with fallbacks
68
75
  const leaderboardSettings = theme.leaderboardChart;
69
76
  const labelSpacing = leaderboardSettings?.labelSpacing ?? DEFAULT_LEADERBOARD_SETTINGS.labelSpacing;
@@ -88,7 +95,9 @@ const LeaderboardChart = ({ data, withComparison = false, primaryColor, secondar
88
95
  return (jsxRuntime.jsx(components.__experimentalGrid, { className: clsx(leaderboardChart_module.default.leaderboardChart, loading && leaderboardChart_module.default.loading, className), templateColumns: "minmax(0, 1fr) auto", rowGap: rowGap, columnGap: columnGap, style: chartStyle, children: data.map(entry => {
89
96
  const colorIndex = Math.sign(entry.delta) + 1;
90
97
  const deltaColor = signColors[colorIndex];
91
- return (jsxRuntime.jsxs(element.Fragment, { children: [jsxRuntime.jsxs(components.__experimentalVStack, { spacing: labelSpacing, children: [jsxRuntime.jsx(components.__experimentalText, { children: entry.label }), jsxRuntime.jsxs("div", { className: leaderboardChart_module.default.progressContainer, children: [jsxRuntime.jsx(components.ProgressBar, { value: entry.currentShare, className: clsx(leaderboardChart_module.default.progressBar, leaderboardChart_module.default.primaryBar) }), withComparison && (jsxRuntime.jsx(components.ProgressBar, { value: entry.previousShare, className: clsx(leaderboardChart_module.default.progressBar, leaderboardChart_module.default.secondaryBar) }))] })] }), jsxRuntime.jsxs("div", { className: leaderboardChart_module.default.valueContainer, children: [jsxRuntime.jsx(components.__experimentalText, { children: valueFormatter(entry.currentValue) }), withComparison && (jsxRuntime.jsx(components.__experimentalText, { style: { color: deltaColor }, children: deltaFormatter(entry.delta) }))] })] }, entry.id));
98
+ return (jsxRuntime.jsxs(element.Fragment, { children: [jsxRuntime.jsx(components.__experimentalVStack, { spacing: labelSpacing, children: withOverlayLabel ? (jsxRuntime.jsx(ProgressBarWithOverlayLabel, { entry: entry })) : (jsxRuntime.jsx(ProgressBarWithLabel, { entry: entry, withComparison: withComparison })) }), jsxRuntime.jsxs("div", { className: clsx(leaderboardChart_module.default.valueContainer, {
99
+ [leaderboardChart_module.default.overlayLabel]: withOverlayLabel,
100
+ }), children: [jsxRuntime.jsx(components.__experimentalText, { children: valueFormatter(entry.currentValue) }), withComparison && (jsxRuntime.jsx(components.__experimentalText, { style: { color: deltaColor }, children: deltaFormatter(entry.delta) }))] })] }, entry.id));
92
101
  }) }));
93
102
  };
94
103
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var styles = {"leaderboardChart":"leaderboard-chart-module_leaderboardChart__zxakP","loading":"leaderboard-chart-module_loading__-AGv-","progressContainer":"leaderboard-chart-module_progressContainer__BZGbj","progressBar":"leaderboard-chart-module_progressBar__LAQaj","primaryBar":"leaderboard-chart-module_primaryBar__iybII","secondaryBar":"leaderboard-chart-module_secondaryBar__A7tLz","valueContainer":"leaderboard-chart-module_valueContainer__ZlLh4","emptyState":"leaderboard-chart-module_emptyState__0dkfy"};
5
+ var styles = {"leaderboardChart":"leaderboard-chart-module_leaderboardChart__zxakP","loading":"leaderboard-chart-module_loading__-AGv-","progressContainerWithOverlayLabel":"leaderboard-chart-module_progressContainerWithOverlayLabel__YFPY0","progressBar":"leaderboard-chart-module_progressBar__LAQaj","progressBarLabel":"leaderboard-chart-module_progressBarLabel__24t-j","progressContainer":"leaderboard-chart-module_progressContainer__BZGbj","primaryBar":"leaderboard-chart-module_primaryBar__iybII","secondaryBar":"leaderboard-chart-module_secondaryBar__A7tLz","valueContainer":"leaderboard-chart-module_valueContainer__ZlLh4","overlayLabel":"leaderboard-chart-module_overlayLabel__pRqSh","emptyState":"leaderboard-chart-module_emptyState__0dkfy"};
6
6
 
7
7
  exports.default = styles;
@@ -6,7 +6,11 @@ var legend = require('@visx/legend');
6
6
  var scale = require('@visx/scale');
7
7
  var clsx = require('clsx');
8
8
  var react = require('react');
9
- var themeProvider = require('../../providers/theme/theme-provider.js');
9
+ require('fast-deep-equal');
10
+ var useGlobalChartTheme = require('../../hooks/use-global-chart-theme.js');
11
+ require('@visx/event');
12
+ require('@visx/tooltip');
13
+ require('@visx/xychart');
10
14
  var legend_module = require('./legend.module.scss.js');
11
15
  var utils = require('./utils.js');
12
16
 
@@ -20,7 +24,7 @@ const orientationToFlexDirection = {
20
24
  */
21
25
  const BaseLegend = react.forwardRef(({ items, className, orientation = 'horizontal', position = 'bottom', alignment = 'center', shape = 'rect', fill = utils.valueOrIdentityString, size = utils.valueOrIdentityString, labelFormat = utils.valueOrIdentity, labelTransform = utils.labelTransformFactory, shapeWidth = 16, shapeHeight = 16, shapeMargin = '2px 4px 2px 0', labelAlign = 'left', labelFlex = '0 0 auto', // Use natural width instead of expanding to fill space
22
26
  labelMargin = '0 4px', itemMargin = '0', itemDirection = 'row', legendLabelProps, ...legendItemProps }, ref) => {
23
- const theme = themeProvider.useChartTheme();
27
+ const theme = useGlobalChartTheme.useGlobalChartTheme();
24
28
  const legendScale = scale.scaleOrdinal({
25
29
  domain: items.map(item => item.label),
26
30
  range: items.map(item => item.color),
@@ -2,6 +2,10 @@
2
2
 
3
3
  require('@visx/xychart');
4
4
  var react = require('react');
5
+ require('fast-deep-equal');
6
+ var useGlobalChartTheme = require('../../hooks/use-global-chart-theme.js');
7
+ require('@visx/event');
8
+ require('@visx/tooltip');
5
9
  var getStyles = require('../../utils/get-styles.js');
6
10
 
7
11
  /**
@@ -92,13 +96,13 @@ function processPointData(pointData, theme, showValues, withGlyph, glyphSize, re
92
96
  /**
93
97
  * Hook to transform chart data into legend items
94
98
  * @param data - The chart data to transform
95
- * @param theme - The chart theme for colors
96
99
  * @param options - Configuration options for legend generation
97
100
  * @param legendShape - The shape type for legend items (string literal or React component)
98
101
  * @return Array of legend items ready for display
99
102
  */
100
- function useChartLegendData(data, theme, options = {}, legendShape) {
103
+ function useChartLegendData(data, options = {}, legendShape) {
101
104
  const { showValues = false, withGlyph = false, glyphSize = 8, renderGlyph } = options;
105
+ const theme = useGlobalChartTheme.useGlobalChartTheme();
102
106
  return react.useMemo(() => {
103
107
  if (!data || !Array.isArray(data) || data.length === 0) {
104
108
  return [];
@@ -5,9 +5,12 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var annotation = require('@visx/annotation');
7
7
  var xychart = require('@visx/xychart');
8
- var merge = require('deepmerge');
8
+ var deepmerge = require('deepmerge');
9
9
  var react = require('react');
10
- var themeProvider = require('../../providers/theme/theme-provider.js');
10
+ require('fast-deep-equal');
11
+ var useGlobalChartTheme = require('../../hooks/use-global-chart-theme.js');
12
+ require('@visx/event');
13
+ require('@visx/tooltip');
11
14
  var utils = require('../shared/utils.js');
12
15
  var lineChartAnnotationLabelPopover = require('./line-chart-annotation-label-popover.js');
13
16
 
@@ -91,12 +94,12 @@ const getVerticalAnchor = (subjectType, isFlippedVertically, y, yMax, height) =>
91
94
  return undefined;
92
95
  };
93
96
  const LineChartAnnotation = ({ datum, title, subtitle, subjectType = 'circle', styles: datumStyles, testId, renderLabel, renderLabelPopover, }) => {
94
- const providerTheme = themeProvider.useChartTheme();
97
+ const providerTheme = useGlobalChartTheme.useGlobalChartTheme();
95
98
  const { xScale, yScale } = react.useContext(xychart.DataContext) || {};
96
99
  const labelRef = react.useRef(null);
97
100
  const [height, setHeight] = react.useState(null);
98
101
  // Deep merge styles to preserve nested object properties
99
- const styles = merge(providerTheme.annotationStyles ?? {}, datumStyles ?? {});
102
+ const styles = deepmerge(providerTheme.annotationStyles ?? {}, datumStyles ?? {});
100
103
  // Measure the label height once after initial render
101
104
  react.useEffect(() => {
102
105
  if (labelRef.current?.getBBox) {
@@ -10,9 +10,13 @@ var gradient = require('@visx/gradient');
10
10
  var xychart = require('@visx/xychart');
11
11
  var i18n = require('@wordpress/i18n');
12
12
  var clsx = require('clsx');
13
+ require('fast-deep-equal');
14
+ var useGlobalChartTheme = require('../../hooks/use-global-chart-theme.js');
15
+ require('@visx/event');
16
+ require('@visx/tooltip');
17
+ var useXychartTheme = require('../../hooks/use-xychart-theme.js');
13
18
  var globalChartsProvider = require('../../providers/chart-context/global-charts-provider.js');
14
19
  var utils = require('../../providers/chart-context/utils.js');
15
- var themeProvider = require('../../providers/theme/theme-provider.js');
16
20
  var createComposition = require('../../utils/create-composition.js');
17
21
  var getStyles = require('../../utils/get-styles.js');
18
22
  var legend = require('../legend/legend.js');
@@ -137,8 +141,8 @@ const LineChartScalesRef = ({ chartRef, width, height, margin }) => {
137
141
  return null; // This component only provides the ref interface
138
142
  };
139
143
  const LineChartInternal = react.forwardRef(({ data, chartId: providedChartId, width, height, className, margin, withTooltips = true, withTooltipCrosshairs, showLegend = false, legendOrientation = 'horizontal', legendAlignment = 'center', legendPosition = 'bottom', renderGlyph = defaultRenderGlyph, glyphStyle = {}, legendShape = 'line', withLegendGlyph = false, withGradientFill = false, smoothing = true, curveType, renderTooltip = renderDefaultTooltip, withStartGlyphs = false, options = {}, onPointerDown = undefined, onPointerUp = undefined, onPointerMove = undefined, onPointerOut = undefined, children, }, ref) => {
140
- const providerTheme = themeProvider.useChartTheme();
141
- const theme = themeProvider.useXYChartTheme(data);
144
+ const providerTheme = useGlobalChartTheme.useGlobalChartTheme();
145
+ const theme = useXychartTheme.useXYChartTheme(data);
142
146
  const chartId = utils.useChartId(providedChartId);
143
147
  const [legendRef, legendHeight] = useElementHeight.useElementHeight();
144
148
  const chartRef = react.useRef(null);
@@ -206,7 +210,7 @@ const LineChartInternal = react.forwardRef(({ data, chartId: providedChartId, wi
206
210
  renderGlyph,
207
211
  }), [withLegendGlyph, glyphStyle?.radius, renderGlyph]);
208
212
  // Create legend items using the reusable hook
209
- const legendItems = useChartLegendData.useChartLegendData(dataSorted, providerTheme, legendOptions, legendShape);
213
+ const legendItems = useChartLegendData.useChartLegendData(dataSorted, legendOptions, legendShape);
210
214
  // Memoize metadata to prevent unnecessary re-registration
211
215
  const chartMetadata = react.useMemo(() => ({
212
216
  withGradientFill,
@@ -216,7 +220,13 @@ const LineChartInternal = react.forwardRef(({ data, chartId: providedChartId, wi
216
220
  withLegendGlyph,
217
221
  }), [withGradientFill, smoothing, curveType, withStartGlyphs, withLegendGlyph]);
218
222
  // Register chart with context only if data is valid
219
- utils.useChartRegistration(chartId, legendItems, providerTheme, 'line', isDataValid, chartMetadata);
223
+ utils.useChartRegistration({
224
+ chartId,
225
+ legendItems,
226
+ chartType: 'line',
227
+ isDataValid,
228
+ metadata: chartMetadata,
229
+ });
220
230
  const accessors = {
221
231
  xAccessor: (d) => d?.date,
222
232
  yAccessor: (d) => d?.value,
@@ -250,7 +260,7 @@ const LineChartInternal = react.forwardRef(({ data, chartId: providedChartId, wi
250
260
  stroke,
251
261
  ...lineStyles,
252
262
  };
253
- return (jsxRuntime.jsxs("g", { children: [withStartGlyphs && (jsxRuntime.jsx(StartGlyph, { index: index, data: seriesData, color: stroke, renderGlyph: providerTheme.glyphs?.[index] ?? renderGlyph, accessors: accessors, glyphStyle: glyphStyle })), withGradientFill && (jsxRuntime.jsx(gradient.LinearGradient, { id: `area-gradient-${chartId}-${index + 1}`, from: stroke, fromOpacity: 0.4, toOpacity: 0.1, to: theme.backgroundColor, ...seriesData.options?.gradient, "data-testid": "line-gradient" })), jsxRuntime.jsx(xychart.AreaSeries, { dataKey: seriesData?.label, data: seriesData.data, ...accessors, fill: withGradientFill
263
+ return (jsxRuntime.jsxs("g", { children: [withStartGlyphs && (jsxRuntime.jsx(StartGlyph, { index: index, data: seriesData, color: stroke, renderGlyph: providerTheme.glyphs?.[index] ?? renderGlyph, accessors: accessors, glyphStyle: glyphStyle })), withGradientFill && (jsxRuntime.jsx(gradient.LinearGradient, { id: `area-gradient-${chartId}-${index + 1}`, from: stroke, fromOpacity: 0.4, toOpacity: 0.1, to: providerTheme.backgroundColor, ...seriesData.options?.gradient, "data-testid": "line-gradient" })), jsxRuntime.jsx(xychart.AreaSeries, { dataKey: seriesData?.label, data: seriesData.data, ...accessors, fill: withGradientFill
254
264
  ? `url(#area-gradient-${chartId}-${index + 1})`
255
265
  : 'transparent', renderLine: true, curve: getCurveType(curveType, smoothing), lineProps: lineProps }, seriesData?.label)] }, seriesData?.label || index));
256
266
  }), withTooltips && (jsxRuntime.jsx(accessibleTooltip.AccessibleTooltip, { detectBounds: true, snapTooltipToDatumX: true, snapTooltipToDatumY: true, showSeriesGlyphs: true, renderTooltip: renderTooltip, renderGlyph: tooltipRenderGlyph, glyphStyle: glyphStyle, showVerticalCrosshair: withTooltipCrosshairs?.showVertical, showHorizontalCrosshair: withTooltipCrosshairs?.showHorizontal, selectedIndex: selectedIndex, tooltipRef: tooltipRef, keyboardFocusedClassName: lineChart_module.default['line-chart__tooltip--keyboard-focused'], series: dataSorted })), jsxRuntime.jsx(LineChartScalesRef, { chartRef: internalChartRef, width: width, height: height, margin: margin })] }) }), showLegend && (jsxRuntime.jsx(legend.Legend, { items: legendItems, orientation: legendOrientation, alignment: legendAlignment, position: legendPosition, className: lineChart_module.default['line-chart-legend'], shape: legendShape, chartId: chartId, ref: legendRef })), children] }) }));
@@ -5,3 +5,4 @@ var pieChart = require('./pie-chart.js');
5
5
 
6
6
 
7
7
  exports.PieChart = pieChart.default;
8
+ exports.PieChartUnresponsive = pieChart.PieChartUnresponsive;
@@ -7,14 +7,17 @@ var group = require('@visx/group');
7
7
  var shape = require('@visx/shape');
8
8
  var clsx = require('clsx');
9
9
  var react = require('react');
10
+ require('fast-deep-equal');
11
+ var useGlobalChartTheme = require('../../hooks/use-global-chart-theme.js');
10
12
  var useChartMouseHandler = require('../../hooks/use-chart-mouse-handler.js');
13
+ require('@visx/xychart');
11
14
  var globalChartsProvider = require('../../providers/chart-context/global-charts-provider.js');
12
15
  var utils = require('../../providers/chart-context/utils.js');
13
- var themeProvider = require('../../providers/theme/theme-provider.js');
14
- var themes = require('../../providers/theme/themes.js');
16
+ var createComposition = require('../../utils/create-composition.js');
15
17
  var legend = require('../legend/legend.js');
16
18
  require('../legend/base-legend.js');
17
19
  var useChartLegendData = require('../legend/use-chart-legend-data.js');
20
+ var singleChartContext = require('../shared/single-chart-context.js');
18
21
  var useElementHeight = require('../shared/use-element-height.js');
19
22
  var withResponsive = require('../shared/with-responsive.js');
20
23
  var baseTooltip = require('../tooltip/base-tooltip.js');
@@ -42,6 +45,32 @@ const validateData = (data) => {
42
45
  }
43
46
  return { isValid: true, message: '' };
44
47
  };
48
+ /**
49
+ * Compound component for SVG children in the PieChart
50
+ * @param {PropsWithChildren} props - Component props
51
+ * @param {ReactNode} props.children - Child elements to render
52
+ * @return {JSX.Element} The children wrapped in a fragment
53
+ */
54
+ const PieChartSVG = ({ children }) => {
55
+ // This component doesn't render directly - its children are extracted by PieChart
56
+ // We just return the children as-is
57
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: children });
58
+ };
59
+ // Set displayName for better debugging and type checking
60
+ PieChartSVG.displayName = 'PieChart.SVG';
61
+ /**
62
+ * Compound component for HTML children in the PieChart
63
+ * @param {PropsWithChildren} props - Component props
64
+ * @param {ReactNode} props.children - Child elements to render
65
+ * @return {JSX.Element} The children wrapped in a fragment
66
+ */
67
+ const PieChartHTML = ({ children }) => {
68
+ // This component doesn't render directly - its children are extracted by PieChart
69
+ // We just return the children as-is
70
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: children });
71
+ };
72
+ // Set displayName for better debugging and type checking
73
+ PieChartHTML.displayName = 'PieChart.HTML';
45
74
  /**
46
75
  * Renders a pie or donut chart using the provided data.
47
76
  *
@@ -49,17 +78,50 @@ const validateData = (data) => {
49
78
  * @return {JSX.Element} The rendered chart component
50
79
  */
51
80
  const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false, className, showLegend = false, legendOrientation = 'horizontal', legendPosition = 'bottom', legendAlignment = 'center', legendShape = 'circle', size, thickness = 1, padding = 20, gapScale = 0, cornerScale = 0, children = null, }) => {
52
- const providerTheme = themeProvider.useChartTheme();
81
+ const providerTheme = useGlobalChartTheme.useGlobalChartTheme();
53
82
  const chartId = utils.useChartId(providedChartId);
54
83
  const [legendRef, legendHeight] = useElementHeight.useElementHeight();
55
- const { onMouseMove, onMouseLeave, tooltipOpen, tooltipData, tooltipLeft, tooltipTop } = useChartMouseHandler.default({
84
+ const { onMouseMove, onMouseLeave, tooltipOpen, tooltipData, tooltipLeft, tooltipTop } = useChartMouseHandler.useChartMouseHandler({
56
85
  withTooltips,
57
86
  });
58
87
  // Memoize legend options to prevent unnecessary re-calculations
59
88
  const legendOptions = react.useMemo(() => ({ showValues: true }), []);
60
89
  // Create legend items using the reusable hook
61
- const legendItems = useChartLegendData.useChartLegendData(data, providerTheme, legendOptions);
90
+ const legendItems = useChartLegendData.useChartLegendData(data, legendOptions);
62
91
  const { isValid, message } = validateData(data);
92
+ // Process children to extract compound components
93
+ const { svgChildren, htmlChildren, otherChildren } = react.useMemo(() => {
94
+ const svg = [];
95
+ const html = [];
96
+ const other = [];
97
+ react.Children.forEach(children, child => {
98
+ if (react.isValidElement(child)) {
99
+ // Check displayName for compound components
100
+ const childType = child.type;
101
+ const displayName = childType?.displayName;
102
+ if (displayName === 'PieChart.SVG') {
103
+ // Extract children from PieChart.SVG
104
+ react.Children.forEach(child.props.children, svgChild => {
105
+ svg.push(svgChild);
106
+ });
107
+ }
108
+ else if (displayName === 'PieChart.HTML') {
109
+ // Extract children from PieChart.HTML
110
+ react.Children.forEach(child.props.children, htmlChild => {
111
+ html.push(htmlChild);
112
+ });
113
+ }
114
+ else if (child.type === group.Group) {
115
+ // Legacy support: still check for Group type for backward compatibility
116
+ svg.push(child);
117
+ }
118
+ else {
119
+ other.push(child);
120
+ }
121
+ }
122
+ });
123
+ return { svgChildren: svg, htmlChildren: html, otherChildren: other };
124
+ }, [children]);
63
125
  // Memoize metadata to prevent unnecessary re-registration
64
126
  const chartMetadata = react.useMemo(() => ({
65
127
  thickness,
@@ -67,7 +129,13 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
67
129
  cornerScale,
68
130
  }), [thickness, gapScale, cornerScale]);
69
131
  // Register chart with context only if data is valid
70
- utils.useChartRegistration(chartId, legendItems, providerTheme, 'pie', isValid, chartMetadata);
132
+ utils.useChartRegistration({
133
+ chartId,
134
+ legendItems,
135
+ chartType: 'pie',
136
+ isDataValid: isValid,
137
+ metadata: chartMetadata,
138
+ });
71
139
  if (!isValid) {
72
140
  return (jsxRuntime.jsx("div", { className: clsx('pie-chart', pieChart_module.default['pie-chart'], className), children: jsxRuntime.jsx("div", { className: pieChart_module.default['error-message'], children: message }) }));
73
141
  }
@@ -95,29 +163,33 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
95
163
  // Use the color property from the data object as a last resort. The theme provides colours by default.
96
164
  fill: (d) => d?.color || providerTheme.colors[d.index],
97
165
  };
98
- return (jsxRuntime.jsxs("div", { className: clsx('pie-chart', pieChart_module.default['pie-chart'], className), style: {
99
- display: 'flex',
100
- flexDirection: showLegend && legendPosition === 'top' ? 'column-reverse' : 'column',
101
- }, children: [jsxRuntime.jsx("svg", { viewBox: `0 0 ${size} ${adjustedHeight}`, preserveAspectRatio: "xMidYMid meet", width: size, height: adjustedHeight, children: jsxRuntime.jsxs(group.Group, { top: centerY, left: centerX, children: [jsxRuntime.jsx(shape.Pie, { data: dataWithIndex, pieValue: accessors.value, outerRadius: outerRadius, innerRadius: innerRadius, padAngle: padAngle, cornerRadius: cornerRadius, children: pie => {
102
- return pie.arcs.map((arc, index) => {
103
- const [centroidX, centroidY] = pie.path.centroid(arc);
104
- const hasSpaceForLabel = arc.endAngle - arc.startAngle >= 0.25;
105
- const handleMouseMove = (event) => onMouseMove(event, arc.data);
106
- const pathProps = {
107
- d: pie.path(arc) || '',
108
- fill: accessors.fill(arc.data),
109
- };
110
- if (withTooltips) {
111
- pathProps.onMouseMove = handleMouseMove;
112
- pathProps.onMouseLeave = onMouseLeave;
113
- }
114
- return (jsxRuntime.jsxs("g", { children: [jsxRuntime.jsx("path", { ...pathProps }), hasSpaceForLabel && (jsxRuntime.jsx("text", { x: centroidX, y: centroidY, dy: ".33em", fill: providerTheme.labelBackgroundColor || themes.defaultTheme.labelBackgroundColor, fontSize: 12, textAnchor: "middle", pointerEvents: "none", children: arc.data.label }))] }, `arc-${index}`));
115
- });
116
- } }), children] }) }), showLegend && (jsxRuntime.jsx(legend.Legend, { items: legendItems, orientation: legendOrientation, position: legendPosition, alignment: legendAlignment, className: pieChart_module.default['pie-chart-legend'], shape: legendShape, ref: legendRef, chartId: chartId })), withTooltips && tooltipOpen && tooltipData && (jsxRuntime.jsx(baseTooltip.BaseTooltip, { data: tooltipData, top: tooltipTop || 0, left: tooltipLeft || 0, style: {
117
- transform: 'translate(-50%, -100%)',
118
- } }))] }));
166
+ return (jsxRuntime.jsx(singleChartContext.SingleChartContext.Provider, { value: {
167
+ chartId,
168
+ chartWidth: size,
169
+ chartHeight: adjustedHeight,
170
+ }, children: jsxRuntime.jsxs("div", { className: clsx('pie-chart', pieChart_module.default['pie-chart'], className), style: {
171
+ display: 'flex',
172
+ flexDirection: showLegend && legendPosition === 'top' ? 'column-reverse' : 'column',
173
+ }, children: [jsxRuntime.jsx("svg", { viewBox: `0 0 ${size} ${adjustedHeight}`, preserveAspectRatio: "xMidYMid meet", width: size, height: adjustedHeight, children: jsxRuntime.jsxs(group.Group, { top: centerY, left: centerX, children: [jsxRuntime.jsx(shape.Pie, { data: dataWithIndex, pieValue: accessors.value, outerRadius: outerRadius, innerRadius: innerRadius, padAngle: padAngle, cornerRadius: cornerRadius, children: pie => {
174
+ return pie.arcs.map((arc, index) => {
175
+ const [centroidX, centroidY] = pie.path.centroid(arc);
176
+ const hasSpaceForLabel = arc.endAngle - arc.startAngle >= 0.25;
177
+ const handleMouseMove = (event) => onMouseMove(event, arc.data);
178
+ const pathProps = {
179
+ d: pie.path(arc) || '',
180
+ fill: accessors.fill(arc.data),
181
+ };
182
+ if (withTooltips) {
183
+ pathProps.onMouseMove = handleMouseMove;
184
+ pathProps.onMouseLeave = onMouseLeave;
185
+ }
186
+ return (jsxRuntime.jsxs("g", { children: [jsxRuntime.jsx("path", { ...pathProps }), hasSpaceForLabel && (jsxRuntime.jsx("text", { x: centroidX, y: centroidY, dy: ".33em", fill: providerTheme.labelBackgroundColor || '#333', fontSize: 12, textAnchor: "middle", pointerEvents: "none", children: arc.data.label }))] }, `arc-${index}`));
187
+ });
188
+ } }), svgChildren] }) }), showLegend && (jsxRuntime.jsx(legend.Legend, { items: legendItems, orientation: legendOrientation, position: legendPosition, alignment: legendAlignment, className: pieChart_module.default['pie-chart-legend'], shape: legendShape, ref: legendRef, chartId: chartId })), withTooltips && tooltipOpen && tooltipData && (jsxRuntime.jsx(baseTooltip.BaseTooltip, { data: tooltipData, top: tooltipTop || 0, left: tooltipLeft || 0, style: {
189
+ transform: 'translate(-50%, -100%)',
190
+ } })), htmlChildren, otherChildren] }) }));
119
191
  };
120
- const PieChart = (props) => {
192
+ const PieChartWithProvider = props => {
121
193
  const existingContext = react.useContext(globalChartsProvider.GlobalChartsContext);
122
194
  // If we're already in a GlobalChartsProvider context, don't create a new one
123
195
  if (existingContext) {
@@ -126,7 +198,19 @@ const PieChart = (props) => {
126
198
  // Otherwise, create our own GlobalChartsProvider
127
199
  return (jsxRuntime.jsx(globalChartsProvider.GlobalChartsProvider, { children: jsxRuntime.jsx(PieChartInternal, { ...props }) }));
128
200
  };
129
- PieChart.displayName = 'PieChart';
130
- var pieChart = withResponsive.withResponsive(PieChart);
201
+ PieChartWithProvider.displayName = 'PieChart';
202
+ // Create PieChart with composition API
203
+ const PieChart = createComposition.attachSubComponents(PieChartWithProvider, {
204
+ Legend: legend.Legend,
205
+ SVG: PieChartSVG,
206
+ HTML: PieChartHTML,
207
+ });
208
+ // Create responsive PieChart with composition API
209
+ const PieChartResponsive = createComposition.attachSubComponents(withResponsive.withResponsive(PieChartWithProvider), {
210
+ Legend: legend.Legend,
211
+ SVG: PieChartSVG,
212
+ HTML: PieChartHTML,
213
+ });
131
214
 
132
- exports.default = pieChart;
215
+ exports.PieChartUnresponsive = PieChart;
216
+ exports.default = PieChartResponsive;