@automattic/charts 0.44.0 → 0.45.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 (110) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/{chunk-3O6FHD2T.js → chunk-A3PGOCJO.js} +46 -4
  3. package/dist/chunk-A3PGOCJO.js.map +1 -0
  4. package/dist/{chunk-G66WE3ON.js → chunk-BWEMZ72V.js} +41 -15
  5. package/dist/chunk-BWEMZ72V.js.map +1 -0
  6. package/dist/{chunk-BZ6UDD37.cjs → chunk-CNAKHZMW.cjs} +69 -31
  7. package/dist/chunk-CNAKHZMW.cjs.map +1 -0
  8. package/dist/{chunk-G4FX5I3V.cjs → chunk-EPHDZVIG.cjs} +80 -56
  9. package/dist/chunk-EPHDZVIG.cjs.map +1 -0
  10. package/dist/{chunk-MAV6SE6L.cjs → chunk-GEB4GELE.cjs} +24 -24
  11. package/dist/{chunk-MAV6SE6L.cjs.map → chunk-GEB4GELE.cjs.map} +1 -1
  12. package/dist/{chunk-KM62I6SD.js → chunk-HVWETEEV.js} +53 -15
  13. package/dist/chunk-HVWETEEV.js.map +1 -0
  14. package/dist/{chunk-HYHBAHIU.js → chunk-JGX3ZNK5.js} +3 -3
  15. package/dist/{chunk-W5RFMC3A.js → chunk-JI6OGGGF.js} +3 -3
  16. package/dist/{chunk-SHADFB3T.js → chunk-KEBKTDOQ.js} +2 -2
  17. package/dist/{chunk-2HUX2CAT.cjs → chunk-LSGYIUQX.cjs} +44 -2
  18. package/dist/chunk-LSGYIUQX.cjs.map +1 -0
  19. package/dist/{chunk-UHESRL2F.cjs → chunk-N36WJKYM.cjs} +6 -6
  20. package/dist/{chunk-UHESRL2F.cjs.map → chunk-N36WJKYM.cjs.map} +1 -1
  21. package/dist/{chunk-Q2LDRQN7.js → chunk-PFT2X4OW.js} +2 -2
  22. package/dist/{chunk-GK3XEXVI.cjs → chunk-PNSMPZ3E.cjs} +8 -8
  23. package/dist/{chunk-GK3XEXVI.cjs.map → chunk-PNSMPZ3E.cjs.map} +1 -1
  24. package/dist/{chunk-SC462VDM.cjs → chunk-QPHNEQCK.cjs} +11 -11
  25. package/dist/{chunk-SC462VDM.cjs.map → chunk-QPHNEQCK.cjs.map} +1 -1
  26. package/dist/{chunk-2HB55BRH.js → chunk-VM3CHO3G.js} +62 -38
  27. package/dist/chunk-VM3CHO3G.js.map +1 -0
  28. package/dist/{chunk-ZA7OWPY7.cjs → chunk-VOMSG7KV.cjs} +50 -24
  29. package/dist/chunk-VOMSG7KV.cjs.map +1 -0
  30. package/dist/{chunk-QLLKOSJ6.cjs → chunk-YKVKFUV7.cjs} +50 -24
  31. package/dist/chunk-YKVKFUV7.cjs.map +1 -0
  32. package/dist/{chunk-XDIWMJZD.js → chunk-ZSNO2BYX.js} +39 -13
  33. package/dist/chunk-ZSNO2BYX.js.map +1 -0
  34. package/dist/components/bar-chart/index.cjs +4 -4
  35. package/dist/components/bar-chart/index.d.cts +2 -1
  36. package/dist/components/bar-chart/index.d.ts +2 -1
  37. package/dist/components/bar-chart/index.js +3 -3
  38. package/dist/components/bar-list-chart/index.cjs +5 -5
  39. package/dist/components/bar-list-chart/index.d.cts +1 -1
  40. package/dist/components/bar-list-chart/index.d.ts +1 -1
  41. package/dist/components/bar-list-chart/index.js +4 -4
  42. package/dist/components/conversion-funnel-chart/index.cjs +3 -3
  43. package/dist/components/conversion-funnel-chart/index.d.cts +1 -1
  44. package/dist/components/conversion-funnel-chart/index.d.ts +1 -1
  45. package/dist/components/conversion-funnel-chart/index.js +2 -2
  46. package/dist/components/leaderboard-chart/index.cjs +4 -4
  47. package/dist/components/leaderboard-chart/index.d.cts +2 -2
  48. package/dist/components/leaderboard-chart/index.d.ts +2 -2
  49. package/dist/components/leaderboard-chart/index.js +3 -3
  50. package/dist/components/legend/index.cjs +3 -3
  51. package/dist/components/legend/index.d.cts +1 -1
  52. package/dist/components/legend/index.d.ts +1 -1
  53. package/dist/components/legend/index.js +2 -2
  54. package/dist/components/line-chart/index.cjs +4 -4
  55. package/dist/components/line-chart/index.d.cts +1 -1
  56. package/dist/components/line-chart/index.d.ts +1 -1
  57. package/dist/components/line-chart/index.js +3 -3
  58. package/dist/components/pie-chart/index.cjs +4 -4
  59. package/dist/components/pie-chart/index.d.cts +7 -1
  60. package/dist/components/pie-chart/index.d.ts +7 -1
  61. package/dist/components/pie-chart/index.js +3 -3
  62. package/dist/components/pie-semi-circle-chart/index.cjs +4 -4
  63. package/dist/components/pie-semi-circle-chart/index.d.cts +7 -1
  64. package/dist/components/pie-semi-circle-chart/index.d.ts +7 -1
  65. package/dist/components/pie-semi-circle-chart/index.js +3 -3
  66. package/dist/components/tooltip/index.d.cts +1 -1
  67. package/dist/components/tooltip/index.d.ts +1 -1
  68. package/dist/hooks/index.cjs +4 -2
  69. package/dist/hooks/index.cjs.map +1 -1
  70. package/dist/hooks/index.d.cts +79 -2
  71. package/dist/hooks/index.d.ts +79 -2
  72. package/dist/hooks/index.js +3 -1
  73. package/dist/index.cjs +10 -10
  74. package/dist/index.d.cts +3 -3
  75. package/dist/index.d.ts +3 -3
  76. package/dist/index.js +9 -9
  77. package/dist/{leaderboard-chart-rqyTz1m6.d.ts → leaderboard-chart-Cpg_k_Vg.d.ts} +1 -1
  78. package/dist/{leaderboard-chart-BWEheWCd.d.cts → leaderboard-chart-DOaY0V1U.d.cts} +1 -1
  79. package/dist/providers/index.cjs +2 -2
  80. package/dist/providers/index.d.cts +2 -2
  81. package/dist/providers/index.d.ts +2 -2
  82. package/dist/providers/index.js +1 -1
  83. package/dist/{themes-CGUHFZ5g.d.ts → themes-CN85BQM1.d.ts} +1 -1
  84. package/dist/{themes-B4swlmql.d.cts → themes-TIJq1lG_.d.cts} +1 -1
  85. package/dist/{types-cEbX_Q2K.d.ts → types-73KOEWs9.d.cts} +3 -1
  86. package/dist/{types-cEbX_Q2K.d.cts → types-73KOEWs9.d.ts} +3 -1
  87. package/package.json +1 -1
  88. package/src/components/bar-chart/bar-chart.tsx +57 -11
  89. package/src/components/bar-chart/test/bar-chart.test.tsx +114 -0
  90. package/src/components/pie-chart/pie-chart.tsx +130 -93
  91. package/src/components/pie-chart/test/pie-chart.test.tsx +174 -0
  92. package/src/components/pie-semi-circle-chart/pie-semi-circle-chart.tsx +96 -57
  93. package/src/components/pie-semi-circle-chart/test/pie-semi-circle-chart.test.tsx +84 -0
  94. package/src/hooks/index.ts +1 -0
  95. package/src/hooks/use-interactive-legend-data.ts +138 -0
  96. package/src/types.ts +3 -1
  97. package/dist/chunk-2HB55BRH.js.map +0 -1
  98. package/dist/chunk-2HUX2CAT.cjs.map +0 -1
  99. package/dist/chunk-3O6FHD2T.js.map +0 -1
  100. package/dist/chunk-BZ6UDD37.cjs.map +0 -1
  101. package/dist/chunk-G4FX5I3V.cjs.map +0 -1
  102. package/dist/chunk-G66WE3ON.js.map +0 -1
  103. package/dist/chunk-KM62I6SD.js.map +0 -1
  104. package/dist/chunk-QLLKOSJ6.cjs.map +0 -1
  105. package/dist/chunk-XDIWMJZD.js.map +0 -1
  106. package/dist/chunk-ZA7OWPY7.cjs.map +0 -1
  107. /package/dist/{chunk-HYHBAHIU.js.map → chunk-JGX3ZNK5.js.map} +0 -0
  108. /package/dist/{chunk-W5RFMC3A.js.map → chunk-JI6OGGGF.js.map} +0 -0
  109. /package/dist/{chunk-SHADFB3T.js.map → chunk-KEBKTDOQ.js.map} +0 -0
  110. /package/dist/{chunk-Q2LDRQN7.js.map → chunk-PFT2X4OW.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,11 @@ 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.45.0] - 2025-10-27
9
+ ### Added
10
+ - Add interactive legend support to BarChart. [#45561]
11
+ - Add interactive legend to pie charts. [#45580]
12
+
8
13
  ## [0.44.0] - 2025-10-21
9
14
  ### Changed
10
15
  - Improve legends toggling. [#45545]
@@ -523,6 +528,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
523
528
  - Fixed lints following ESLint rule changes for TS [#40584]
524
529
  - Fixing a bug in Chart storybook data. [#40640]
525
530
 
531
+ [0.45.0]: https://github.com/Automattic/charts/compare/v0.44.0...v0.45.0
526
532
  [0.44.0]: https://github.com/Automattic/charts/compare/v0.43.0...v0.44.0
527
533
  [0.43.0]: https://github.com/Automattic/charts/compare/v0.42.0...v0.43.0
528
534
  [0.42.0]: https://github.com/Automattic/charts/compare/v0.41.1...v0.42.0
@@ -674,7 +674,7 @@ var useChartId = (providedId) => {
674
674
  };
675
675
 
676
676
  // src/providers/chart-context/hooks/use-chart-registration.ts
677
- import { useEffect as useEffect2, useMemo as useMemo6 } from "react";
677
+ import { useEffect as useEffect2, useMemo as useMemo7 } from "react";
678
678
 
679
679
  // src/hooks/use-deep-memo.ts
680
680
  import isEqual from "fast-deep-equal";
@@ -909,6 +909,47 @@ var useZeroValueDisplay = (data, options = { enabled: false }) => {
909
909
  }, [data, enabled, minValueRatio, maxValueRatio]);
910
910
  };
911
911
 
912
+ // src/hooks/use-interactive-legend-data.ts
913
+ import { useMemo as useMemo6 } from "react";
914
+ var useInteractiveLegendData = ({
915
+ data,
916
+ chartId,
917
+ legendInteractive,
918
+ isSeriesVisible
919
+ }) => {
920
+ const visibleData = useMemo6(() => {
921
+ if (!chartId || !legendInteractive) {
922
+ return data;
923
+ }
924
+ const filtered = data.filter((segment) => isSeriesVisible(chartId, segment.label));
925
+ if (filtered.length === 0) {
926
+ return [];
927
+ }
928
+ const totalValue = filtered.reduce((sum, segment) => sum + segment.value, 0);
929
+ return filtered.map((segment) => ({
930
+ ...segment,
931
+ percentage: totalValue > 0 ? segment.value / totalValue * 100 : 0
932
+ }));
933
+ }, [data, chartId, isSeriesVisible, legendInteractive]);
934
+ const allSegmentsHidden = useMemo6(() => {
935
+ return legendInteractive && visibleData.length === 0;
936
+ }, [legendInteractive, visibleData]);
937
+ const legendData = useMemo6(() => {
938
+ if (!legendInteractive || !chartId) {
939
+ return data;
940
+ }
941
+ return data.map((segment) => {
942
+ const isVisible = isSeriesVisible(chartId, segment.label);
943
+ if (!isVisible) {
944
+ return segment;
945
+ }
946
+ const recalculated = visibleData.find((d) => d.label === segment.label);
947
+ return recalculated || segment;
948
+ });
949
+ }, [data, visibleData, legendInteractive, chartId, isSeriesVisible]);
950
+ return { visibleData, allSegmentsHidden, legendData };
951
+ };
952
+
912
953
  // src/providers/chart-context/hooks/use-chart-registration.ts
913
954
  var useChartRegistration = ({
914
955
  chartId,
@@ -919,7 +960,7 @@ var useChartRegistration = ({
919
960
  }) => {
920
961
  const { registerChart, unregisterChart } = useGlobalChartsContext();
921
962
  const stableLegendItems = useDeepMemo(legendItems);
922
- const memoizedMetadata = useMemo6(() => metadata, [metadata]);
963
+ const memoizedMetadata = useMemo7(() => metadata, [metadata]);
923
964
  useEffect2(() => {
924
965
  if (isDataValid) {
925
966
  registerChart(chartId, {
@@ -972,6 +1013,7 @@ export {
972
1013
  useChartMargin,
973
1014
  useElementHeight,
974
1015
  useTextTruncation,
975
- useZeroValueDisplay
1016
+ useZeroValueDisplay,
1017
+ useInteractiveLegendData
976
1018
  };
977
- //# sourceMappingURL=chunk-3O6FHD2T.js.map
1019
+ //# sourceMappingURL=chunk-A3PGOCJO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/providers/chart-context/global-charts-provider.tsx","../src/utils/create-composition.ts","../src/utils/date-parsing.ts","../src/utils/format-metric-value.ts","../src/utils/format-percentage.ts","../src/utils/get-longest-tick-width.ts","../src/utils/get-styles.ts","../src/utils/is-safari.ts","../src/utils/merge-themes.ts","../src/utils/color-utils.ts","../src/providers/chart-context/private/get-chart-color.ts","../src/providers/chart-context/themes.ts","../src/providers/chart-context/hooks/use-global-charts-context.ts","../src/providers/chart-context/hooks/use-chart-id.ts","../src/providers/chart-context/hooks/use-chart-registration.ts","../src/hooks/use-deep-memo.ts","../src/hooks/use-chart-mouse-handler.ts","../src/hooks/use-xychart-theme.ts","../src/hooks/use-chart-data-transform.ts","../src/hooks/use-chart-margin.tsx","../src/hooks/use-element-height.ts","../src/hooks/use-text-truncation.ts","../src/hooks/use-zero-value-display.ts","../src/hooks/use-interactive-legend-data.ts","../src/providers/chart-context/hooks/use-global-charts-theme.ts"],"sourcesContent":["import { createContext, useCallback, useMemo, useState, useEffect } from 'react';\nimport { getItemShapeStyles, getSeriesLineStyles, mergeThemes, hexToHsl } from '../../utils';\nimport { getChartColor, type ColorCache } from './private/get-chart-color';\nimport { defaultTheme } from './themes';\nimport type { GlobalChartsContextValue, ChartRegistration } from './types';\nimport type { ChartTheme, CompleteChartTheme } from '../../types';\nimport type { FC, ReactNode } from 'react';\n\nexport const GlobalChartsContext = createContext< GlobalChartsContextValue | null >( null );\n\nexport interface GlobalChartsProviderProps {\n\tchildren: ReactNode;\n\ttheme?: Partial< ChartTheme >;\n}\n\nexport const GlobalChartsProvider: FC< GlobalChartsProviderProps > = ( { children, theme } ) => {\n\tconst [ charts, setCharts ] = useState< Map< string, ChartRegistration > >( () => new Map() );\n\t// Track hidden series per chart: chartId -> Set<seriesLabel>\n\tconst [ hiddenSeries, setHiddenSeries ] = useState< Map< string, Set< string > > >(\n\t\t() => new Map()\n\t);\n\n\tconst providerTheme: CompleteChartTheme = useMemo( () => {\n\t\treturn theme ? mergeThemes( defaultTheme, theme ) : defaultTheme;\n\t}, [ theme ] );\n\n\t// Cache expensive color computations that only change when theme colors change\n\tconst colorCache: ColorCache = useMemo( () => {\n\t\tconst { colors } = providerTheme;\n\t\tconst hues: number[] = [];\n\t\tconst existingHslColors: Array< [ number, number, number ] > = [];\n\t\tlet minHue = 360;\n\t\tlet maxHue = 0;\n\n\t\t// Process all colors once and cache the results\n\t\tif ( Array.isArray( colors ) ) {\n\t\t\tfor ( const color of colors ) {\n\t\t\t\tif ( color && typeof color === 'string' && color.startsWith( '#' ) ) {\n\t\t\t\t\tconst hslColor = hexToHsl( color );\n\t\t\t\t\thues.push( hslColor[ 0 ] );\n\t\t\t\t\texistingHslColors.push( hslColor );\n\t\t\t\t\tminHue = Math.min( minHue, hslColor[ 0 ] );\n\t\t\t\t\tmaxHue = Math.max( maxHue, hslColor[ 0 ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tcolors: colors || [],\n\t\t\thues,\n\t\t\texistingHslColors,\n\t\t\tminHue,\n\t\t\tmaxHue,\n\t\t};\n\t}, [ providerTheme ] );\n\n\tconst [ groupToColorMap, setGroupToColorMap ] = useState< Map< string, string > >(\n\t\t() => new Map()\n\t);\n\n\t// Reset group color mappings when theme colors change\n\tuseEffect( () => {\n\t\t// Create a completely new Map instance to trigger dependencies, e.g. useChartLegendItems\n\t\tsetGroupToColorMap( new Map() );\n\t}, [ providerTheme.colors ] );\n\n\tconst registerChart = useCallback( ( id: string, data: ChartRegistration ) => {\n\t\tsetCharts( prev => new Map( prev ).set( id, data ) );\n\t}, [] );\n\n\tconst unregisterChart = useCallback( ( id: string ) => {\n\t\tsetCharts( prev => {\n\t\t\tconst newMap = new Map( prev );\n\t\t\tnewMap.delete( id );\n\t\t\treturn newMap;\n\t\t} );\n\t}, [] );\n\n\tconst getChartData = useCallback(\n\t\t( id: string ) => {\n\t\t\treturn charts.get( id );\n\t\t},\n\t\t[ charts ]\n\t);\n\n\tconst resolveColor = useCallback(\n\t\t( {\n\t\t\tgroup,\n\t\t\tindex,\n\t\t\toverrideColor,\n\t\t}: {\n\t\t\tgroup?: string;\n\t\t\tindex: number;\n\t\t\toverrideColor?: string;\n\t\t} ): string => {\n\t\t\t// Highest precedence: eg. explicit series stroke or chart color prop\n\t\t\tif ( overrideColor ) {\n\t\t\t\treturn overrideColor;\n\t\t\t}\n\n\t\t\t// If group provided, maintain a stable assignment\n\t\t\tif ( group ) {\n\t\t\t\tconst existing = groupToColorMap.get( group );\n\n\t\t\t\tif ( existing ) {\n\t\t\t\t\treturn existing;\n\t\t\t\t}\n\n\t\t\t\tconst assignedCount = groupToColorMap.size;\n\t\t\t\tconst color =\n\t\t\t\t\tcolorCache.colors.length > 0 ? getChartColor( assignedCount, colorCache ) : '#000000';\n\t\t\t\tgroupToColorMap.set( group, color );\n\n\t\t\t\treturn color;\n\t\t\t}\n\n\t\t\treturn colorCache.colors.length > 0 ? getChartColor( index, colorCache ) : '#000000';\n\t\t},\n\t\t[ colorCache, groupToColorMap ]\n\t);\n\n\tconst getElementStyles = useCallback< GlobalChartsContextValue[ 'getElementStyles' ] >(\n\t\t( { data, index, overrideColor, legendShape } ) => {\n\t\t\tconst isSeriesData = data && typeof data === 'object' && 'data' in data && 'options' in data;\n\t\t\tconst isPointPercentageData = data && typeof data === 'object' && 'percentage' in data;\n\n\t\t\treturn {\n\t\t\t\tcolor: resolveColor( {\n\t\t\t\t\tgroup: data?.group,\n\t\t\t\t\tindex,\n\t\t\t\t\toverrideColor:\n\t\t\t\t\t\toverrideColor ||\n\t\t\t\t\t\t( isSeriesData && data?.options?.stroke ) ||\n\t\t\t\t\t\t( isPointPercentageData && data?.color ),\n\t\t\t\t} ),\n\t\t\t\tlineStyles: isSeriesData ? getSeriesLineStyles( data, index, providerTheme ) : {},\n\t\t\t\tglyph: providerTheme.glyphs?.[ index ],\n\t\t\t\tshapeStyles: isSeriesData\n\t\t\t\t\t? getItemShapeStyles( data, index, providerTheme, legendShape )\n\t\t\t\t\t: {},\n\t\t\t};\n\t\t},\n\t\t[ providerTheme, resolveColor ]\n\t);\n\n\t// Series visibility management methods\n\tconst toggleSeriesVisibility = useCallback( ( chartId: string, seriesLabel: string ) => {\n\t\tsetHiddenSeries( prev => {\n\t\t\tconst newMap = new Map( prev );\n\t\t\tconst chartHidden = newMap.get( chartId ) || new Set();\n\t\t\tconst newSet = new Set( chartHidden );\n\n\t\t\tif ( newSet.has( seriesLabel ) ) {\n\t\t\t\tnewSet.delete( seriesLabel );\n\t\t\t} else {\n\t\t\t\tnewSet.add( seriesLabel );\n\t\t\t}\n\n\t\t\tif ( newSet.size === 0 ) {\n\t\t\t\tnewMap.delete( chartId );\n\t\t\t} else {\n\t\t\t\tnewMap.set( chartId, newSet );\n\t\t\t}\n\n\t\t\treturn newMap;\n\t\t} );\n\t}, [] );\n\n\tconst isSeriesVisible = useCallback(\n\t\t( chartId: string, seriesLabel: string ) => {\n\t\t\tconst chartHidden = hiddenSeries.get( chartId );\n\t\t\treturn ! chartHidden || ! chartHidden.has( seriesLabel );\n\t\t},\n\t\t[ hiddenSeries ]\n\t);\n\n\tconst getHiddenSeries = useCallback(\n\t\t( chartId: string ): Set< string > => {\n\t\t\tconst set = hiddenSeries.get( chartId );\n\t\t\treturn set ? new Set( set ) : new Set< string >();\n\t\t},\n\t\t[ hiddenSeries ]\n\t);\n\n\tconst value: GlobalChartsContextValue = useMemo(\n\t\t() => ( {\n\t\t\tcharts,\n\t\t\tregisterChart,\n\t\t\tunregisterChart,\n\t\t\tgetChartData,\n\t\t\ttheme: providerTheme,\n\t\t\tgetElementStyles,\n\t\t\ttoggleSeriesVisibility,\n\t\t\tisSeriesVisible,\n\t\t\tgetHiddenSeries,\n\t\t} ),\n\t\t[\n\t\t\tcharts,\n\t\t\tregisterChart,\n\t\t\tunregisterChart,\n\t\t\tgetChartData,\n\t\t\tproviderTheme,\n\t\t\tgetElementStyles,\n\t\t\ttoggleSeriesVisibility,\n\t\t\tisSeriesVisible,\n\t\t\tgetHiddenSeries,\n\t\t]\n\t);\n\n\treturn <GlobalChartsContext.Provider value={ value }>{ children }</GlobalChartsContext.Provider>;\n};\n","/**\n * Utility function to create chart components with composition API.\n *\n * This function attaches subcomponents to a chart component to enable\n * dot notation access like <Chart.Legend />, <Chart.Tooltip />, etc.\n *\n * @param Chart - The main chart component\n * @param subComponents - Object containing subcomponents to attach\n * @return Chart component with attached subcomponents\n */\nexport function attachSubComponents< TChart, TSubComponents extends Record< string, unknown > >(\n\tChart: TChart,\n\tsubComponents: TSubComponents\n): TChart & TSubComponents {\n\treturn Object.assign( Chart, subComponents );\n}\n","/**\n * @file Date parsing utilities using date-fns for local timezone handling\n *\n * This module provides utilities for parsing various date string formats and converting\n * them to local timezone dates using the battle-tested date-fns library. For formats\n * without timezone info, they're treated as local. For formats with timezone info,\n * they're converted to the equivalent local time.\n *\n * Note: And specifically it prevents format `YYYY-MM-DD` being parsed as UTC date.\n *\n * Key Features:\n * - All parsed dates are in local timezone\n * - Converts timezone-aware strings to local equivalent\n * - Robust input validation and error handling using date-fns\n * - TypeScript type safety\n * - Much smaller codebase than custom parsing\n *\n * Supported Formats:\n * - YYYY-MM-DD (treated as local)\n * - YYYY-MM-DD HH:mm:ss (treated as local)\n * - YYYY-MM-DD HH:mm (treated as local)\n * - YYYY-MM-DDTHH:mm:ss (treated as local)\n * - YYYY-MM-DDTHH:mm:ss.SSS (treated as local)\n * - YYYY-MM-DDTHH:mm (treated as local)\n * - YYYY-MM-DDTHH:mm:ssZ (converted to local)\n * - YYYY-MM-DDTHH:mm:ss±HH:mm (converted to local)\n *\n * @example\n * ```typescript\n * parseAsLocalDate(\"2025-01-01\"); // Local timezone\n * parseAsLocalDate(\"2025-01-01 14:30:00\"); // Local timezone\n * parseAsLocalDate(\"2025-01-01 14:30\"); // Local timezone\n * parseAsLocalDate(\"2025-01-01T14:30:45.123\"); // Local timezone\n * parseAsLocalDate(\"2025-01-01T14:30:00Z\"); // UTC 14:30 → Local equivalent\n * parseAsLocalDate(\"2025-01-01T14:30:00+05:00\"); // +05:00 14:30 → Local equivalent\n * ```\n */\n\nimport { parse, parseISO, isValid } from 'date-fns';\n\n/**\n * Checks if a date string contains timezone information\n * @param {string} dateString - The date string to check for timezone information\n * @return {boolean} True if the date string contains timezone information, false otherwise\n */\nconst hasTimezone = ( dateString: string ): boolean => {\n\treturn /T.*[Z]$|T.*[+-]\\d{2}:?\\d{2}$/.test( dateString );\n};\n\n/**\n * Parses any supported date string format and returns a local timezone date\n *\n * Uses date-fns for robust parsing and validation. For strings without timezone\n * info, treats as local timezone. For strings with timezone info, converts to\n * local timezone equivalent.\n *\n * Supports:\n * - YYYY-MM-DD (local)\n * - YYYY-MM-DD HH:mm:ss (local)\n * - YYYY-MM-DD HH:mm (local)\n * - YYYY-MM-DDTHH:mm:ss (local)\n * - YYYY-MM-DDTHH:mm:ss.SSS (local)\n * - YYYY-MM-DDTHH:mm (local)\n * - YYYY-MM-DDTHH:mm:ssZ (UTC → local)\n * - YYYY-MM-DDTHH:mm:ss±HH:mm (offset → local)\n * @param {string} dateString - The date string to parse into a local timezone date\n * @return {Date} A Date object representing the parsed date in local timezone, or an invalid Date if parsing fails\n */\nexport const parseAsLocalDate = ( dateString: string ): Date => {\n\tconst trimmedString = dateString.trim();\n\n\t// If it has timezone information, parse as ISO and convert to local\n\tif ( hasTimezone( trimmedString ) ) {\n\t\tconst isoDate = parseISO( trimmedString );\n\n\t\tif ( ! isValid( isoDate ) ) {\n\t\t\treturn new Date( NaN );\n\t\t}\n\n\t\t// parseISO automatically converts to local timezone\n\t\treturn isoDate;\n\t}\n\n\t// For naive strings, try different local formats\n\tconst formats = [\n\t\t'yyyy-MM-dd', // 2025-01-01\n\t\t'yyyy-MM-dd HH:mm:ss', // 2025-01-01 14:30:45\n\t\t'yyyy-MM-dd HH:mm', // 2025-01-01 14:30\n\t\t\"yyyy-MM-dd'T'HH:mm:ss\", // 2025-01-01T14:30:45\n\t\t\"yyyy-MM-dd'T'HH:mm:ss.SSS\", // 2025-01-01T14:30:45.123\n\t\t\"yyyy-MM-dd'T'HH:mm\", // 2025-01-01T14:30\n\t];\n\n\tfor ( const format of formats ) {\n\t\tconst result = parse( trimmedString, format, new Date() );\n\t\tif ( isValid( result ) ) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\t// If no format matched, return invalid date\n\treturn new Date( NaN );\n};\n","import { formatNumberCompact, formatNumber } from '@automattic/number-formatters';\n\n/**\n * Types for formatMetricValue\n */\nexport type MetricValueType = 'number' | 'average' | 'currency';\n\ntype FormatMetricValueOptions = {\n\tdecimals?: number;\n\tuseMultipliers?: boolean;\n\tsignDisplay?: Intl.NumberFormatOptions[ 'signDisplay' ];\n};\n\n/**\n * Format a numeric metric value based on type, precision and scale.\n * Supports currency, number and percentage, using @automattic/number-formatters.\n *\n * @param value - The value to format\n * @param type - The type of formatting to apply\n * @param options - Formatting options\n * @param options.decimals - Number of decimal places to show\n * @param options.useMultipliers - Whether to use K, M, B suffixes for large numbers\n * @param options.signDisplay - Controls when to display the sign (auto, always, never, exceptZero)\n * @return Formatted string\n */\nexport const formatMetricValue = (\n\tvalue: string | number,\n\ttype: MetricValueType = 'number',\n\t{ decimals, useMultipliers = false, signDisplay }: FormatMetricValueOptions = {}\n): string => {\n\tif ( value === null || value === undefined ) {\n\t\treturn '';\n\t}\n\n\tconst numericValue = Number( value );\n\tif ( isNaN( numericValue ) ) {\n\t\treturn '';\n\t}\n\n\tswitch ( type ) {\n\t\tcase 'currency': {\n\t\t\t// Basic currency formatting - can be enhanced with full currency support\n\t\t\tconst formatted = useMultipliers\n\t\t\t\t? formatNumberCompact( numericValue, {\n\t\t\t\t\t\tdecimals: decimals ?? 2,\n\t\t\t\t\t\tnumberFormatOptions: {\n\t\t\t\t\t\t\tmaximumFractionDigits: decimals ?? 2,\n\t\t\t\t\t\t\tsignDisplay,\n\t\t\t\t\t\t},\n\t\t\t\t } )\n\t\t\t\t: formatNumber( numericValue, {\n\t\t\t\t\t\tdecimals: decimals ?? 2,\n\t\t\t\t\t\tnumberFormatOptions: {\n\t\t\t\t\t\t\tsignDisplay,\n\t\t\t\t\t\t},\n\t\t\t\t } );\n\t\t\treturn `$${ formatted }`;\n\t\t}\n\n\t\tcase 'average': {\n\t\t\tif ( ! Number.isFinite( numericValue ) ) {\n\t\t\t\treturn '—';\n\t\t\t}\n\n\t\t\treturn formatNumber( numericValue, {\n\t\t\t\tdecimals: decimals ?? 0,\n\t\t\t\tnumberFormatOptions: {\n\t\t\t\t\tstyle: 'percent',\n\t\t\t\t\tsignDisplay: signDisplay ?? 'exceptZero',\n\t\t\t\t},\n\t\t\t} );\n\t\t}\n\n\t\tcase 'number':\n\t\tdefault: {\n\t\t\treturn useMultipliers\n\t\t\t\t? formatNumberCompact( numericValue, {\n\t\t\t\t\t\tdecimals: decimals ?? 0,\n\t\t\t\t\t\tnumberFormatOptions: {\n\t\t\t\t\t\t\tmaximumFractionDigits: decimals ?? 0,\n\t\t\t\t\t\t\tsignDisplay,\n\t\t\t\t\t\t},\n\t\t\t\t } )\n\t\t\t\t: formatNumber( numericValue, {\n\t\t\t\t\t\tdecimals: decimals ?? 0,\n\t\t\t\t\t\tnumberFormatOptions: {\n\t\t\t\t\t\t\tsignDisplay,\n\t\t\t\t\t\t},\n\t\t\t\t } );\n\t\t}\n\t}\n};\n","import { formatNumber } from '@automattic/number-formatters';\n\n/**\n * Format a percentage value with smart decimal handling.\n * Uses @automattic/number-formatters for consistent formatting.\n * Removes unnecessary trailing zeros and caps at 2 decimal places.\n *\n * @param value - The percentage value (0-100 range)\n * @return Formatted percentage string (e.g., \"30%\", \"30.1%\", \"30.25%\")\n */\nexport const formatPercentage = ( value: number ): string => {\n\t// Use formatNumber with percentage style, but convert from 0-100 range to 0-1 range\n\treturn formatNumber( value / 100, {\n\t\tnumberFormatOptions: {\n\t\t\tstyle: 'percent',\n\t\t\tminimumFractionDigits: 0,\n\t\t\tmaximumFractionDigits: 2,\n\t\t},\n\t} );\n};\n","import { getStringWidth } from '@visx/text';\nimport type { TickFormatter } from '@visx/axis';\nimport type { AnyD3Scale, ScaleInput } from '@visx/scale';\n\n/**\n * Returns the width of the longest tick.\n *\n * @param ticks - Ticks to get the width of.\n * @param formatTick - Function to format the tick.\n * @param {object} labelStyle - Style object for the label.\n * @return {number} - Width of the longest tick.\n */\nexport const getLongestTickWidth = < T extends AnyD3Scale >(\n\tticks: ScaleInput< T >[],\n\tformatTick: TickFormatter< ScaleInput< T > >,\n\tlabelStyle?: object\n) => {\n\tconst formattedTicks = ticks.map( tick => formatTick( tick, 0, [] ) );\n\tconst longestTick = formattedTicks.reduce(\n\t\t( longest, current ) => ( longest.length >= current.length ? longest : current ),\n\t\tformattedTicks[ 0 ]\n\t);\n\n\treturn getStringWidth( longestTick, labelStyle );\n};\n","import type { ChartTheme, SeriesData } from '../types';\nimport type { LegendShape } from '@visx/legend/lib/types';\nimport type { LineStyles } from '@visx/xychart';\n\n/**\n * Utility function to get consolidated line styles for a series\n * This consolidates the logic used by both LineChart and Legend components\n *\n * @param {SeriesData} seriesData - The series data containing styling options\n * @param {number} index - The index of the series in the data array\n * @param {ChartTheme} providerTheme - The chart theme configuration\n * @return {LineStyles} The consolidated line styles for the series\n */\nexport function getSeriesLineStyles(\n\tseriesData: SeriesData,\n\tindex: number,\n\tproviderTheme: ChartTheme\n): LineStyles {\n\t// Get theme-based line styles for line type\n\tconst themeSemanticLineStyle = providerTheme?.lineChart?.lineStyles?.[ seriesData.options?.type ];\n\n\t// Get theme-based line styles for index of series data\n\tconst themeSeriesLineStyle =\n\t\tproviderTheme?.seriesLineStyles?.[ index % providerTheme.seriesLineStyles.length ];\n\n\t// Priority order: custom series style > theme line type style > default theme series style\n\treturn (\n\t\tseriesData.options?.seriesLineStyle ?? themeSemanticLineStyle ?? themeSeriesLineStyle ?? {}\n\t);\n}\n\n/**\n * Utility function to get stroke color for a series\n *\n * @param {SeriesData} seriesData - The series data containing styling options\n * @param {number} index - The index of the series in the data array\n * @param {string[]} themeColors - Array of theme colors\n * @return {string} The stroke color for the series\n */\nexport function getSeriesStroke(\n\tseriesData: SeriesData,\n\tindex: number,\n\tthemeColors: string[]\n): string {\n\treturn seriesData.options?.stroke ?? themeColors[ index % themeColors.length ];\n}\n\n/**\n * Utility function to get shape styles for a legend item\n *\n * @param {SeriesData} series - The series data containing styling options\n * @param {number} index - The index of the series in the data array\n * @param {ChartTheme} theme - The chart theme configuration\n * @param {LegendShape} legendShape - The shape to use for the item (optional)\n * @return {Record< string, unknown >} The shape styles for the item\n */\nexport function getItemShapeStyles(\n\tseries: SeriesData,\n\tindex: number,\n\ttheme: ChartTheme,\n\tlegendShape?: LegendShape< SeriesData[], number >\n): Record< string, unknown > {\n\tconst seriesShapeStyles = series.options?.legendShapeStyle ?? {};\n\tconst lineStyles = legendShape === 'line' ? getSeriesLineStyles( series, index, theme ) : {};\n\tconst themeShapeStyles = theme.legendShapeStyles?.[ index ];\n\n\tconst itemShapeStyles = {\n\t\t...seriesShapeStyles,\n\t\t...lineStyles,\n\t};\n\n\t// Return item shape styles if they are not empty\n\tif (\n\t\tObject.values( itemShapeStyles ).some(\n\t\t\tvalue => value !== undefined && value !== null && value !== ''\n\t\t)\n\t) {\n\t\treturn itemShapeStyles;\n\t}\n\n\t// Fallback to theme shape styles if defined\n\treturn themeShapeStyles ?? {};\n}\n","export const isSafari = () => {\n\tif ( typeof navigator !== 'undefined' && navigator.userAgent ) {\n\t\treturn /^((?!chrome|android).)*safari/i.test( navigator.userAgent );\n\t}\n\treturn false;\n};\n","import deepmerge from 'deepmerge';\nimport type { ChartTheme, CompleteChartTheme } from '../types';\n\n/**\n * Merges chart themes with proper precedence.\n * The second theme (override) takes precedence over the first theme (base).\n *\n * @param baseTheme - Base theme object\n * @param overrideTheme - Theme to override base with (takes precedence)\n * @return Merged theme with overrideTheme values taking precedence\n */\nexport function mergeThemes(\n\tbaseTheme: CompleteChartTheme,\n\toverrideTheme: Partial< ChartTheme >\n): CompleteChartTheme;\nexport function mergeThemes(\n\tbaseTheme: ChartTheme,\n\toverrideTheme: Partial< ChartTheme >\n): ChartTheme;\nexport function mergeThemes(\n\tbaseTheme: ChartTheme,\n\toverrideTheme: Partial< ChartTheme >\n): ChartTheme {\n\t// Use deepmerge to properly merge nested objects, with overrideTheme taking precedence\n\treturn deepmerge( baseTheme, overrideTheme, {\n\t\t// Ensure arrays are replaced rather than concatenated\n\t\tarrayMerge: ( _destinationArray, sourceArray ) => sourceArray,\n\t} ) as ChartTheme;\n}\n","/**\n * Validate hex color format\n * @param hex - The hex color string to validate\n * @throws Error if hex string is malformed\n */\nconst validateHexColor = ( hex: string ): void => {\n\t// Validate hex format\n\tif ( typeof hex !== 'string' ) {\n\t\tthrow new Error( 'Hex color must be a string' );\n\t}\n\n\t// Check if hex starts with #\n\tif ( ! hex.startsWith( '#' ) ) {\n\t\tthrow new Error( 'Hex color must start with #' );\n\t}\n\n\t// Check length (should be 7 characters: # + 6 hex digits)\n\tif ( hex.length !== 7 ) {\n\t\tthrow new Error( 'Hex color must be 7 characters long (e.g., #ff0000)' );\n\t}\n\n\t// Check if all characters after # are valid hex digits\n\tconst hexDigits = hex.slice( 1 );\n\tif ( ! /^[0-9a-fA-F]{6}$/.test( hexDigits ) ) {\n\t\tthrow new Error( 'Hex color contains invalid characters. Only 0-9, a-f, A-F are allowed' );\n\t}\n};\n\n/**\n * Convert hex color to rgba with specified opacity\n * This is genuinely reusable across chart components\n * @param hex - The hex color string (e.g., '#ff0000')\n * @param alpha - The opacity value between 0 and 1\n * @return The rgba color string (e.g., 'rgba(255, 0, 0, 0.5)')\n * @throws Error if hex string is malformed\n */\nexport const hexToRgba = ( hex: string, alpha: number ): string => {\n\tvalidateHexColor( hex );\n\n\t// Validate alpha\n\tif ( typeof alpha !== 'number' || isNaN( alpha ) ) {\n\t\tthrow new Error( 'Alpha must be a number' );\n\t}\n\n\tconst r = parseInt( hex.slice( 1, 3 ), 16 );\n\tconst g = parseInt( hex.slice( 3, 5 ), 16 );\n\tconst b = parseInt( hex.slice( 5, 7 ), 16 );\n\treturn `rgba(${ r }, ${ g }, ${ b }, ${ alpha })`;\n};\n\n/**\n * Convert hex color to HSL\n * @param hex - hex color string\n * @return HSL values as [h, s, l]\n * @throws Error if hex string is malformed\n */\nexport const hexToHsl = ( hex: string ): [ number, number, number ] => {\n\tvalidateHexColor( hex );\n\n\tconst r = parseInt( hex.slice( 1, 3 ), 16 ) / 255;\n\tconst g = parseInt( hex.slice( 3, 5 ), 16 ) / 255;\n\tconst b = parseInt( hex.slice( 5, 7 ), 16 ) / 255;\n\n\tconst max = Math.max( r, g, b );\n\tconst min = Math.min( r, g, b );\n\tlet h = 0;\n\tlet s = 0;\n\tconst l = ( max + min ) / 2;\n\n\tif ( max !== min ) {\n\t\tconst d = max - min;\n\t\ts = l > 0.5 ? d / ( 2 - max - min ) : d / ( max + min );\n\n\t\tswitch ( max ) {\n\t\t\tcase r:\n\t\t\t\th = ( g - b ) / d + ( g < b ? 6 : 0 );\n\t\t\t\tbreak;\n\t\t\tcase g:\n\t\t\t\th = ( b - r ) / d + 2;\n\t\t\t\tbreak;\n\t\t\tcase b:\n\t\t\t\th = ( r - g ) / d + 4;\n\t\t\t\tbreak;\n\t\t}\n\t\th /= 6;\n\t}\n\n\treturn [ h * 360, s * 100, l * 100 ];\n};\n\n/**\n * Calculate the perceptual distance between two HSL colors\n * @param hsl1 - first color in HSL format [h, s, l]\n * @param hsl2 - second color in HSL format [h, s, l]\n * @return distance value (0-100+, lower means more similar)\n */\nexport const getColorDistance = (\n\thsl1: [ number, number, number ],\n\thsl2: [ number, number, number ]\n): number => {\n\tconst [ h1, s1, l1 ] = hsl1;\n\tconst [ h2, s2, l2 ] = hsl2;\n\n\t// Calculate hue difference, accounting for circular nature (0° = 360°)\n\tlet hueDiff = Math.abs( h1 - h2 );\n\thueDiff = Math.min( hueDiff, 360 - hueDiff );\n\n\t// Weight the differences: hue is most important, then lightness, then saturation\n\tconst hueWeight = 2;\n\tconst lightnessWeight = 1;\n\tconst saturationWeight = 0.5;\n\n\treturn Math.sqrt(\n\t\tMath.pow( hueDiff * hueWeight, 2 ) +\n\t\t\tMath.pow( ( l1 - l2 ) * lightnessWeight, 2 ) +\n\t\t\tMath.pow( ( s1 - s2 ) * saturationWeight, 2 )\n\t);\n};\n","import { getColorDistance } from '../../../utils';\n\nexport interface ColorCache {\n\tcolors: string[];\n\thues: number[];\n\texistingHslColors: Array< [ number, number, number ] >;\n\tminHue: number;\n\tmaxHue: number;\n}\n\n/**\n * Golden ratio for mathematically pleasing color distribution\n * Used to generate evenly spaced hues that are visually distinct\n */\nconst GOLDEN_RATIO = 0.618033988749;\n\n/**\n * Minimum perceptual distance between colors to ensure visual distinction\n * Based on weighted HSL distance calculation optimized for chart readability\n */\nconst MIN_COLOR_DISTANCE = 25;\n\n/**\n * Maximum attempts to find a sufficiently different color\n * Prevents infinite loops while allowing reasonable search space\n */\nconst MAX_COLOR_GENERATION_ATTEMPTS = 50;\n\n/**\n * Color variation attempt offset\n * Small increment to explore slightly different color variations per attempt\n */\nconst VARIATION_ATTEMPT_OFFSET = 0.1;\n\n// Saturation configuration for generated colors\n\n/**\n * Base saturation percentage for generated colors\n * 60% provides good color vibrancy without being overwhelming\n */\nconst BASE_SATURATION = 60;\n\n/**\n * Number of saturation variation steps\n * Creates 3 different saturation levels for variety\n */\nconst SATURATION_VARIATION_STEPS = 3;\n\n/**\n * Saturation increment per variation step\n * 15% increments provide noticeable but not jarring differences\n * Results in saturation levels: 60%, 75%, 90%\n */\nconst SATURATION_INCREMENT = 15;\n\n// Lightness configuration for WCAG AA accessibility compliance\n\n/**\n * Base lightness percentage for generated colors\n * 35% ensures sufficient contrast against white backgrounds for WCAG AA compliance\n * WCAG AA requires 4.5:1 contrast ratio for normal text\n */\nconst BASE_LIGHTNESS = 35;\n\n/**\n * Number of lightness variation steps\n * Creates 4 different lightness levels for variety\n */\nconst LIGHTNESS_VARIATION_STEPS = 4;\n\n/**\n * Lightness increment per variation step\n * 8% increments provide subtle lightness variation while maintaining accessibility\n * Results in lightness levels: 35%, 43%, 51%, 59%\n * All levels maintain WCAG AA compliance against white backgrounds\n */\nconst LIGHTNESS_INCREMENT = 8;\n\n// Hue range expansion and constraints\n\n/**\n * Minimum hue range in degrees to ensure sufficient color variety\n * 60 degrees provides reasonable color spread even for narrow palettes\n */\nconst MIN_HUE_RANGE_DEGREES = 60;\n\n/**\n * Hue range expansion factor\n * 1.3x expansion provides slightly more variety than the original palette\n */\nconst HUE_RANGE_EXPANSION_FACTOR = 1.3;\n\n/**\n * Threshold for detecting hue wrap-around (color wheel boundary crossing)\n * 180 degrees indicates the colors span more than half the color wheel\n */\nconst HUE_WRAP_THRESHOLD_DEGREES = 180;\n\n/**\n * Full color wheel rotation in degrees\n */\nconst FULL_HUE_ROTATION_DEGREES = 360;\n\n/**\n * Get a color from the colors array or generate a new color using the golden ratio\n *\n * @param index - the index of the color to get\n * @param colorCache - pre-computed color data for performance\n * @return a color from the colors array or a new color using the golden ratio\n */\nexport const getChartColor = ( index: number, colorCache: ColorCache ) => {\n\tconst {\n\t\tcolors,\n\t\thues,\n\t\texistingHslColors,\n\t\tminHue: cachedMinHue,\n\t\tmaxHue: cachedMaxHue,\n\t} = colorCache;\n\n\tif ( index < colors.length ) {\n\t\treturn colors[ index ];\n\t}\n\n\tlet minHue = cachedMinHue;\n\tlet maxHue = cachedMaxHue;\n\n\t// Generate additional colors using golden ratio, avoiding similar colors\n\tfor ( let attempt = 0; attempt < MAX_COLOR_GENERATION_ATTEMPTS; attempt++ ) {\n\t\t// Calculate hue using golden ratio distribution with variation per attempt\n\t\t// Formula: ((base_index + attempt_variation) * golden_ratio * 360°) mod 360°\n\t\t// This ensures mathematically pleasing spacing while allowing slight shifts per attempt\n\t\tlet hue =\n\t\t\t( ( index - colors.length + attempt * VARIATION_ATTEMPT_OFFSET ) *\n\t\t\t\tGOLDEN_RATIO *\n\t\t\t\tFULL_HUE_ROTATION_DEGREES ) %\n\t\t\tFULL_HUE_ROTATION_DEGREES;\n\n\t\t// If we have existing colors, constrain new colors to their hue range\n\t\tif ( hues.length > 0 ) {\n\t\t\t// Handle hue wrap-around (e.g., if colors span across 0 degrees)\n\t\t\tlet hueRange = maxHue - minHue;\n\n\t\t\t// If the range is very large, it might be wrapping around the color wheel\n\t\t\t// Check if a smaller range exists when considering wrap-around\n\t\t\tif ( hueRange > HUE_WRAP_THRESHOLD_DEGREES ) {\n\t\t\t\t// Try the alternative: wrap around the full rotation\n\t\t\t\tconst altMinHue = Math.min( ...hues.filter( h => h > HUE_WRAP_THRESHOLD_DEGREES ) );\n\t\t\t\tconst altMaxHue =\n\t\t\t\t\tMath.max( ...hues.filter( h => h < HUE_WRAP_THRESHOLD_DEGREES ) ) +\n\t\t\t\t\tFULL_HUE_ROTATION_DEGREES;\n\t\t\t\tconst altRange = altMaxHue - altMinHue;\n\n\t\t\t\tif ( altRange < hueRange ) {\n\t\t\t\t\tminHue = altMinHue;\n\t\t\t\t\tmaxHue = altMaxHue;\n\t\t\t\t\thueRange = altRange;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Expand the range slightly to provide some variation\n\t\t\tconst expandedRange = Math.max(\n\t\t\t\thueRange * HUE_RANGE_EXPANSION_FACTOR,\n\t\t\t\tMIN_HUE_RANGE_DEGREES\n\t\t\t);\n\t\t\tconst rangeCenter = ( minHue + maxHue ) / 2;\n\t\t\tconst expandedMin = rangeCenter - expandedRange / 2;\n\n\t\t\t// Map the generated hue to the expanded range\n\t\t\thue = expandedMin + ( hue / FULL_HUE_ROTATION_DEGREES ) * expandedRange;\n\n\t\t\t// Normalize to 0-360 range\n\t\t\thue =\n\t\t\t\t( ( hue % FULL_HUE_ROTATION_DEGREES ) + FULL_HUE_ROTATION_DEGREES ) %\n\t\t\t\tFULL_HUE_ROTATION_DEGREES;\n\t\t}\n\n\t\tconst saturation =\n\t\t\tBASE_SATURATION + ( ( index + attempt ) % SATURATION_VARIATION_STEPS ) * SATURATION_INCREMENT;\n\t\tconst lightness =\n\t\t\tBASE_LIGHTNESS + ( ( index + attempt ) % LIGHTNESS_VARIATION_STEPS ) * LIGHTNESS_INCREMENT;\n\n\t\tconst candidateHsl: [ number, number, number ] = [ hue, saturation, lightness ];\n\n\t\t// Check if this color is sufficiently different from existing colors\n\t\tlet isSufficientlyDifferent = true;\n\t\tfor ( const existingHsl of existingHslColors ) {\n\t\t\tif ( getColorDistance( candidateHsl, existingHsl ) < MIN_COLOR_DISTANCE ) {\n\t\t\t\tisSufficientlyDifferent = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ( isSufficientlyDifferent ) {\n\t\t\treturn `hsl(${ Math.round( hue ) }, ${ saturation }%, ${ lightness }%)`;\n\t\t}\n\t}\n\n\t// Fallback if we couldn't find a sufficiently different color\n\t// Formula: ((base_index) * golden_ratio * 360°) mod 360°\n\t// This ensures mathematically pleasing spacing while maintaining consistency\n\tconst fallbackHue =\n\t\t( ( index - colors.length ) * GOLDEN_RATIO * FULL_HUE_ROTATION_DEGREES ) %\n\t\tFULL_HUE_ROTATION_DEGREES;\n\tconst fallbackSaturation =\n\t\tBASE_SATURATION + ( index % SATURATION_VARIATION_STEPS ) * SATURATION_INCREMENT;\n\tconst fallbackLightness =\n\t\tBASE_LIGHTNESS + ( index % LIGHTNESS_VARIATION_STEPS ) * LIGHTNESS_INCREMENT;\n\treturn `hsl(${ Math.round( fallbackHue ) }, ${ fallbackSaturation }%, ${ fallbackLightness }%)`;\n};\n","import type { ChartTheme, CompleteChartTheme } from '../../types';\n\n/**\n * Default theme configuration\n */\nconst defaultTheme: CompleteChartTheme = {\n\tbackgroundColor: '#FFFFFF', // chart background color\n\tlabelBackgroundColor: 'transparent', // label background color (transparent by default)\n\tlabelTextColor: '#FFFFFF', // label text color (white to match original behavior)\n\tcolors: [ '#98C8DF', '#006DAB', '#A6DC80', '#1F9828', '#FF8C8F' ],\n\tgridStyles: {\n\t\tstroke: '#DCDCDE',\n\t\tstrokeWidth: 1,\n\t},\n\ttickLength: 4,\n\tgridColor: '',\n\tgridColorDark: '',\n\txTickLineStyles: { stroke: 'black' },\n\txAxisLineStyles: { stroke: '#DCDCDE', strokeWidth: 1 },\n\tlegendLabelStyles: {\n\t\tcolor: 'var(--jp-gray-80, #2c3338)',\n\t},\n\tlegendContainerStyles: {},\n\tseriesLineStyles: [],\n\tlegendShapeStyles: [],\n\tglyphs: [],\n\tsvgLabelSmall: { fill: 'var(--jp-gray-80, #2c3338)' },\n\tannotationStyles: {\n\t\tlabel: {\n\t\t\tanchorLineStroke: 'var(--jp-gray-80, #2c3338)',\n\t\t\tbackgroundFill: '#fff',\n\t\t},\n\t\tconnector: {\n\t\t\tstroke: 'var(--jp-gray-80, #2c3338)',\n\t\t},\n\t\tcircleSubject: {\n\t\t\tstroke: 'transparent',\n\t\t\tfill: 'var(--jp-gray-80, #2c3338)',\n\t\t\tradius: 5,\n\t\t},\n\t},\n\tleaderboardChart: {\n\t\trowGap: 12,\n\t\tcolumnGap: 4,\n\t\tlabelSpacing: 1.5,\n\t\tprimaryColor: '#006DAB',\n\t\tsecondaryColor: '#98C8DF',\n\t\tdeltaColors: [ '#FF8C8F', '#757575', '#1F9828' ], // [negative, neutral, positive]\n\t},\n\tconversionFunnelChart: {\n\t\tprimaryColor: '#006DAB',\n\t\tbackgroundColor: '#F3F4F6',\n\t\tpositiveChangeColor: '#1F9828',\n\t\tnegativeChangeColor: '#FF8C8F',\n\t},\n\tlineChart: {\n\t\tlineStyles: {\n\t\t\tcomparison: {\n\t\t\t\tstrokeDasharray: '4 4',\n\t\t\t\tstrokeLinecap: 'square',\n\t\t\t},\n\t\t},\n\t},\n};\n\n/**\n * Jetpack theme configuration\n */\nconst jetpackTheme: ChartTheme = {\n\tbackgroundColor: '#FFFFFF', // chart background color\n\tlabelBackgroundColor: 'transparent', // label background color (transparent by default)\n\tlabelTextColor: '#FFFFFF', // label text color (white to match original behavior)\n\tcolors: [ '#98C8DF', '#006DAB', '#A6DC80', '#1F9828', '#FF8C8F' ],\n\tgridStyles: {\n\t\tstroke: '#DCDCDE',\n\t\tstrokeWidth: 1,\n\t},\n\ttickLength: 4,\n\tgridColor: '',\n\tgridColorDark: '',\n\txTickLineStyles: { stroke: 'black' },\n\txAxisLineStyles: { stroke: '#DCDCDE', strokeWidth: 1 },\n\tlegendLabelStyles: {\n\t\tcolor: 'var(--jp-gray-80, #2c3338)',\n\t},\n\tsvgLabelSmall: { fill: 'var(--jp-gray-80, #2c3338)' },\n\tannotationStyles: {\n\t\tlabel: {\n\t\t\tanchorLineStroke: 'var(--jp-gray-80, #2c3338)',\n\t\t\tbackgroundFill: '#fff',\n\t\t},\n\t\tconnector: {\n\t\t\tstroke: 'var(--jp-gray-80, #2c3338)',\n\t\t},\n\t\tcircleSubject: {\n\t\t\tstroke: 'transparent',\n\t\t\tfill: 'var(--jp-gray-80, #2c3338)',\n\t\t\tradius: 5,\n\t\t},\n\t},\n\tleaderboardChart: {\n\t\trowGap: 12,\n\t\tcolumnGap: 4,\n\t\tlabelSpacing: 1.5,\n\t\tprimaryColor: '#006DAB',\n\t\tsecondaryColor: '#98C8DF',\n\t\tdeltaColors: [ '#FF8C8F', '#757575', '#1F9828' ], // [negative, neutral, positive]\n\t},\n\tconversionFunnelChart: {\n\t\tprimaryColor: '#006DAB',\n\t\tbackgroundColor: '#F3F4F6',\n\t\tpositiveChangeColor: '#1F9828',\n\t\tnegativeChangeColor: '#FF8C8F',\n\t},\n\tlineChart: {\n\t\tlineStyles: {\n\t\t\tcomparison: {\n\t\t\t\tstrokeDasharray: '4 4',\n\t\t\t\tstrokeLinecap: 'square',\n\t\t\t},\n\t\t},\n\t},\n};\n\n/**\n * Woo theme configuration\n */\nconst wooTheme: ChartTheme = {\n\tbackgroundColor: '#FFFFFF', // chart background color\n\tlabelBackgroundColor: 'transparent', // label background color (transparent by default)\n\tlabelTextColor: '#FFFFFF', // label text color (white to match original behavior)\n\tcolors: [\n\t\t'#3858E9', // WooCommerce brand blue\n\t\t'#66BDFF', // Light blue\n\t\t'#873EFF', // Purple\n\t\t'#7B90FF', // Periwinkle blue\n\t\t'#EB6594', // Pink/rose\n\t],\n\tgridStyles: {\n\t\tstroke: '#787C82',\n\t\tstrokeWidth: 1,\n\t},\n\ttickLength: 4,\n\tgridColor: '',\n\tgridColorDark: '',\n\tsvgLabelSmall: { fill: '#757575' },\n\txTickLineStyles: { stroke: 'black' },\n\txAxisLineStyles: { stroke: '#DCDCDE', strokeWidth: 1 },\n\tlegendLabelStyles: {\n\t\tfontSize: '12px',\n\t\tfontWeight: 400,\n\t\tcolor: '#757575',\n\t},\n\tlegendContainerStyles: {\n\t\tgap: '8px',\n\t},\n\tannotationStyles: {\n\t\tlabel: {\n\t\t\tanchorLineStroke: 'black',\n\t\t\tbackgroundFill: '#fff',\n\t\t},\n\t\tconnector: {\n\t\t\tstroke: 'black',\n\t\t},\n\t\tcircleSubject: {\n\t\t\tstroke: 'transparent',\n\t\t\tfill: 'black',\n\t\t\tradius: 5,\n\t\t},\n\t},\n\tleaderboardChart: {\n\t\trowGap: 12,\n\t\tcolumnGap: 4,\n\t\tlabelSpacing: 1.5,\n\t\tprimaryColor: '#3858E9',\n\t\tsecondaryColor: '#66BDFF',\n\t\tdeltaColors: [ '#D63638', '#757575', '#008A20' ], // [negative, neutral, positive]\n\t},\n\tconversionFunnelChart: {\n\t\tprimaryColor: '#3858E9',\n\t\tbackgroundColor: '#F3F4F6',\n\t\tpositiveChangeColor: '#008A20',\n\t\tnegativeChangeColor: '#D63638',\n\t},\n\tlineChart: {\n\t\tlineStyles: {\n\t\t\tcomparison: {\n\t\t\t\tstrokeDasharray: '4 4',\n\t\t\t\tstrokeWidth: 1.5,\n\t\t\t\tstrokeLinecap: 'square',\n\t\t\t},\n\t\t},\n\t},\n};\n\nexport { defaultTheme, jetpackTheme, wooTheme };\n","import { useContext } from 'react';\nimport { GlobalChartsContext } from '../global-charts-provider';\nimport type { GlobalChartsContextValue } from '../types';\n\nexport const useGlobalChartsContext = (): GlobalChartsContextValue => {\n\tconst context = useContext( GlobalChartsContext );\n\tif ( ! context ) {\n\t\tthrow new Error( 'useGlobalChartsContext must be used within a GlobalChartsProvider' );\n\t}\n\treturn context;\n};\n","import { useId } from 'react';\n\nexport const useChartId = ( providedId?: string ): string => {\n\tconst generatedId = useId();\n\treturn providedId || generatedId;\n};\n","import { useEffect, useMemo } from 'react';\nimport { useDeepMemo } from '../../../hooks';\nimport { useGlobalChartsContext } from './use-global-charts-context';\nimport type { BaseLegendItem } from '../../../components/legend';\n\nexport const useChartRegistration = ( {\n\tchartId,\n\tlegendItems,\n\tchartType,\n\tisDataValid,\n\tmetadata,\n}: {\n\tchartId: string;\n\tlegendItems: BaseLegendItem[];\n\tchartType: string;\n\tisDataValid: boolean;\n\tmetadata?: Record< string, unknown >;\n} ): void => {\n\tconst { registerChart, unregisterChart } = useGlobalChartsContext();\n\n\t// Memoize legendItems with deep comparison to prevent infinite loops\n\tconst stableLegendItems = useDeepMemo( legendItems );\n\n\t// Memoize metadata to prevent unnecessary re-renders\n\tconst memoizedMetadata = useMemo( () => metadata, [ metadata ] );\n\n\tuseEffect( () => {\n\t\t// Only register if data is valid\n\t\tif ( isDataValid ) {\n\t\t\tregisterChart( chartId, {\n\t\t\t\tlegendItems: stableLegendItems,\n\t\t\t\tchartType,\n\t\t\t\tmetadata: memoizedMetadata,\n\t\t\t} );\n\t\t}\n\n\t\treturn () => {\n\t\t\tunregisterChart( chartId );\n\t\t};\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [\n\t\tchartId,\n\t\tstableLegendItems,\n\t\tchartType,\n\t\tmemoizedMetadata,\n\t\tisDataValid,\n\t\t// Removed registerChart and unregisterChart from dependencies\n\t\t// They are stable functions created with useCallback and empty deps\n\t] );\n};\n","import isEqual from 'fast-deep-equal';\nimport { useRef } from 'react';\n\n/**\n * Custom hook to memoize a value using deep equality comparison.\n * Prevents unnecessary re-renders when objects have the same content but different references.\n *\n * @param value - The value to memoize with deep equality comparison\n * @return The memoized value that only changes when deeply different\n */\nexport const useDeepMemo = < T >( value: T ): T => {\n\tconst ref = useRef< T >( value );\n\n\tif ( ! isEqual( ref.current, value ) ) {\n\t\tref.current = value;\n\t}\n\n\treturn ref.current;\n};\n","import { localPoint } from '@visx/event';\nimport { useTooltip } from '@visx/tooltip';\nimport { useCallback, type MouseEvent } from 'react';\nimport type { DataPoint } from '../types';\n\ntype UseChartMouseHandlerProps = {\n\t/**\n\t * Whether tooltips are enabled\n\t */\n\twithTooltips: boolean;\n\t/**\n\t * Horizontal offset for tooltip positioning in pixels (default: 0)\n\t */\n\toffsetX?: number;\n\t/**\n\t * Vertical offset for tooltip positioning in pixels (default: -10)\n\t */\n\toffsetY?: number;\n};\n\ntype UseChartMouseHandlerReturn = {\n\t/**\n\t * Handler for mouse move events\n\t */\n\tonMouseMove: ( event: MouseEvent< SVGElement >, data: DataPoint ) => void;\n\t/**\n\t * Handler for mouse leave events\n\t */\n\tonMouseLeave: () => void;\n\t/**\n\t * Whether the tooltip is currently open\n\t */\n\ttooltipOpen: boolean;\n\t/**\n\t * The current tooltip data\n\t */\n\ttooltipData: DataPoint | null;\n\t/**\n\t * The current tooltip left position\n\t */\n\ttooltipLeft: number | undefined;\n\t/**\n\t * The current tooltip top position\n\t */\n\ttooltipTop: number | undefined;\n};\n\n/**\n * Hook to handle mouse interactions for chart components\n *\n * @param {UseChartMouseHandlerProps} props - Hook configuration\n * @return {UseChartMouseHandlerReturn} Object containing handlers and tooltip state\n */\nexport const useChartMouseHandler = ( {\n\twithTooltips,\n\toffsetX = 0,\n\toffsetY = -10,\n}: UseChartMouseHandlerProps ): UseChartMouseHandlerReturn => {\n\tconst { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, hideTooltip, showTooltip } =\n\t\tuseTooltip< DataPoint >();\n\n\tconst onMouseMove = useCallback(\n\t\t( event: MouseEvent< SVGElement >, data: DataPoint ) => {\n\t\t\tif ( ! withTooltips ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst coords = localPoint( event );\n\t\t\tif ( ! coords ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tshowTooltip( {\n\t\t\t\ttooltipData: data,\n\t\t\t\ttooltipLeft: coords.x + offsetX,\n\t\t\t\ttooltipTop: coords.y + offsetY,\n\t\t\t} );\n\t\t},\n\t\t[ withTooltips, showTooltip, offsetX, offsetY ]\n\t);\n\n\tconst onMouseLeave = useCallback( () => {\n\t\tif ( ! withTooltips ) {\n\t\t\treturn;\n\t\t}\n\t\thideTooltip();\n\t}, [ withTooltips, hideTooltip ] );\n\n\treturn {\n\t\tonMouseMove,\n\t\tonMouseLeave,\n\t\ttooltipOpen,\n\t\ttooltipData: tooltipData || null,\n\t\ttooltipLeft,\n\t\ttooltipTop,\n\t};\n};\n","import { buildChartTheme } from '@visx/xychart';\nimport { useMemo } from 'react';\nimport { useGlobalChartsTheme } from '../providers';\nimport type { SeriesData } from '../types';\n\nexport const useXYChartTheme = ( data: SeriesData[] ) => {\n\tconst theme = useGlobalChartsTheme();\n\n\treturn useMemo( () => {\n\t\tconst seriesColors = ( data ?? [] )\n\t\t\t.map( series => series.options?.stroke )\n\t\t\t.filter( ( color ): color is string => Boolean( color ) );\n\n\t\treturn buildChartTheme( {\n\t\t\t...theme,\n\t\t\tcolors: [ ...seriesColors, ...( theme.colors ?? [] ) ],\n\t\t} );\n\t}, [ theme, data ] );\n};\n","import { useMemo } from 'react';\nimport { parseAsLocalDate } from '../utils';\nimport type { SeriesData } from '../types';\n\n/**\n * Hook that transforms and sorts chart data, handling date parsing and sorting\n *\n * This hook extracts the common data transformation logic used in both line-chart\n * and bar-chart components. It:\n * 1. Parses date strings into Date objects using parseAsLocalDate\n * 2. Sorts data points by date when date properties are present\n * 3. Returns the original data unchanged when no date properties are found\n *\n * @param {SeriesData[]} data - The raw chart data to transform\n * @return {SeriesData[]} The transformed and sorted data\n */\nexport const useChartDataTransform = ( data: SeriesData[] ) => {\n\treturn useMemo( () => {\n\t\t// Check if the first data point has date or dateString properties\n\t\tconst firstPoint = data?.[ 0 ]?.data?.[ 0 ];\n\t\tconst hasDateProperties = firstPoint && ( 'date' in firstPoint || 'dateString' in firstPoint );\n\n\t\t// If no date properties found, return data unchanged\n\t\tif ( ! hasDateProperties ) {\n\t\t\treturn data;\n\t\t}\n\n\t\t// Transform and sort data with date properties\n\t\treturn data.map( series => ( {\n\t\t\t...series,\n\t\t\tdata: series.data\n\t\t\t\t.map( point => {\n\t\t\t\t\tlet date: Date | undefined;\n\n\t\t\t\t\tif ( 'date' in point && point.date ) {\n\t\t\t\t\t\tdate = point.date;\n\t\t\t\t\t} else if ( 'dateString' in point && point.dateString ) {\n\t\t\t\t\t\tdate = parseAsLocalDate( point.dateString );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...point,\n\t\t\t\t\t\tdate,\n\t\t\t\t\t};\n\t\t\t\t} )\n\t\t\t\t.sort( ( a, b ) => {\n\t\t\t\t\tif ( ! a.date || ! b.date ) return 0;\n\t\t\t\t\treturn a.date.getTime() - b.date.getTime();\n\t\t\t\t} ),\n\t\t} ) );\n\t}, [ data ] );\n};\n","import { createScale, getTicks } from '@visx/scale';\nimport { useMemo } from 'react';\nimport { getLongestTickWidth } from '../utils';\nimport type { BaseChartProps, DataPointDate, SeriesData } from '../types';\nimport type { XYChartTheme } from '@visx/xychart';\n\nexport const useChartMargin = (\n\theight: number,\n\toptions: BaseChartProps[ 'options' ],\n\tdata: SeriesData[],\n\ttheme: XYChartTheme,\n\thorizontal: boolean = false\n) => {\n\tconst yTicks = useMemo( () => {\n\t\tconst allDataPoints = data.flatMap( series => series.data as DataPointDate[] );\n\n\t\tif ( horizontal ) {\n\t\t\t// When horizontal, y ticks renders fixed tick labels.\n\t\t\treturn allDataPoints.map(\n\t\t\t\td => d.label || options.axis?.y?.tickFormat( d.date.getTime(), 0, [] )\n\t\t\t);\n\t\t}\n\n\t\tconst minY = Math.min( ...allDataPoints.map( d => d.value ) );\n\t\tconst maxY = Math.max( ...allDataPoints.map( d => d.value ) );\n\t\tconst yScale = createScale( {\n\t\t\t...options.yScale,\n\t\t\tdomain: [ minY, maxY ],\n\t\t\trange: [ height, 0 ],\n\t\t} );\n\n\t\treturn getTicks( yScale, options.axis?.y?.numTicks );\n\t}, [ options, data, height, horizontal ] );\n\n\treturn useMemo( () => {\n\t\t// Default margin is for bottom axis labels.\n\t\tconst defaultMargin = { top: 10, right: 20, bottom: 20, left: 20 };\n\t\tconst defaultTickWidth = 40;\n\n\t\t// Auto-calculate margin for y axis labels based on orientation and tick width.\n\t\tconst yAxisOrientation = options.axis?.y?.orientation;\n\t\tconst yAxisStyles =\n\t\t\tyAxisOrientation === 'right' ? theme.axisStyles.y.right : theme.axisStyles.y.left;\n\t\tconst yTickWidth = getLongestTickWidth(\n\t\t\tyTicks,\n\t\t\toptions.axis?.y?.tickFormat,\n\t\t\tyAxisStyles.axisLabel\n\t\t);\n\t\tconst yMarginValue = ( yTickWidth ?? defaultTickWidth ) + ( yAxisStyles?.tickLength ?? 0 );\n\n\t\tif ( yAxisOrientation === 'right' ) {\n\t\t\tdefaultMargin.right = yMarginValue;\n\t\t} else {\n\t\t\tdefaultMargin.left = yMarginValue;\n\t\t}\n\n\t\tif ( options.axis?.x?.orientation === 'top' ) {\n\t\t\tdefaultMargin.top = 20;\n\t\t\tdefaultMargin.bottom = 10;\n\t\t}\n\n\t\treturn defaultMargin;\n\t}, [ options, theme, yTicks ] );\n};\n","import { useState, useCallback, useRef } from 'react';\n\n/**\n * Hook to measure the height of a DOM element.\n * Returns a ref to attach to the element and the current height in pixels.\n *\n * @param {object} props - Optional props.\n * @param {number} props.initialHeight - The initial height to use.\n *\n * @return {[Function, number]} A tuple containing a ref to attach to the element and the current height in pixels\n */\nexport function useElementHeight< T extends HTMLElement = HTMLDivElement >( {\n\tinitialHeight = 0,\n}: {\n\tinitialHeight?: number;\n} = {} ): [ ( node: T | null ) => void, number ] {\n\tconst [ height, setHeight ] = useState( initialHeight );\n\tconst observerRef = useRef< ResizeObserver | null >( null );\n\n\tconst refCallback = useCallback( ( node: T | null ) => {\n\t\tif ( observerRef.current ) {\n\t\t\tobserverRef.current.disconnect();\n\t\t\tobserverRef.current = null;\n\t\t}\n\t\tif ( node ) {\n\t\t\tconst handleResize = () => {\n\t\t\t\tsetHeight( node.getBoundingClientRect().height || 0 );\n\t\t\t};\n\t\t\thandleResize();\n\t\t\tconst resizeObserver = new window.ResizeObserver( handleResize );\n\t\t\tresizeObserver.observe( node );\n\t\t\tobserverRef.current = resizeObserver;\n\t\t}\n\t}, [] );\n\n\treturn [ refCallback, height ];\n}\n","import { useCallback, useRef, useState } from 'react';\n\n/**\n * Hook to detect if text content is truncated within its container.\n * Uses ResizeObserver to dynamically track changes in element size.\n *\n * @param enabled - Whether truncation detection should be active. Defaults to true.\n * @return A tuple containing:\n * - [0] refCallback: Function to attach to the text element as a ref\n * - [1] isTruncated: Boolean indicating if the text is currently truncated\n *\n * @example\n * ```tsx\n * const [textRef, isTruncated] = useTextTruncation(true);\n *\n * return (\n * <span ref={textRef} title={isTruncated ? fullText : undefined}>\n * {text}\n * </span>\n * );\n * ```\n */\nexport function useTextTruncation(\n\tenabled: boolean = true\n): [ ( node: HTMLElement | null ) => void, boolean ] {\n\tconst [ isTruncated, setIsTruncated ] = useState( false );\n\tconst observerRef = useRef< ResizeObserver | null >( null );\n\n\tconst refCallback = useCallback(\n\t\t( node: HTMLElement | null ) => {\n\t\t\t// Cleanup existing observer\n\t\t\tif ( observerRef.current ) {\n\t\t\t\tobserverRef.current.disconnect();\n\t\t\t\tobserverRef.current = null;\n\t\t\t}\n\n\t\t\tif ( node && enabled ) {\n\t\t\t\tconst checkTruncation = () => {\n\t\t\t\t\t// Check if content width exceeds container width (indicates truncation)\n\t\t\t\t\tconst truncated = node.scrollWidth > node.clientWidth;\n\t\t\t\t\tsetIsTruncated( truncated );\n\t\t\t\t};\n\n\t\t\t\t// Initial check\n\t\t\t\tcheckTruncation();\n\n\t\t\t\t// Watch for size changes\n\t\t\t\tconst resizeObserver = new ResizeObserver( checkTruncation );\n\t\t\t\tresizeObserver.observe( node );\n\t\t\t\tobserverRef.current = resizeObserver;\n\t\t\t} else {\n\t\t\t\tsetIsTruncated( false );\n\t\t\t}\n\t\t},\n\t\t[ enabled ]\n\t);\n\n\treturn [ refCallback, isTruncated ];\n}\n","import { useMemo } from 'react';\nimport type { SeriesData, DataPointDate } from '../types';\n\nexport type EnhancedDataPoint = DataPointDate & {\n\tvisualValue?: number;\n};\n\nexport interface EnhancedSeriesData extends Omit< SeriesData, 'data' > {\n\tdata: EnhancedDataPoint[];\n}\n\nexport interface UseZeroValueDisplayOptions {\n\tenabled: boolean;\n\tminValueRatio?: number;\n\tmaxValueRatio?: number;\n}\n\nexport const useZeroValueDisplay = (\n\tdata: SeriesData[],\n\toptions: UseZeroValueDisplayOptions = { enabled: false }\n): SeriesData[] | EnhancedSeriesData[] => {\n\tconst { enabled, minValueRatio = 0.6, maxValueRatio = 0.008 } = options;\n\n\treturn useMemo( () => {\n\t\tif ( ! enabled ) return data;\n\n\t\t// Collect all non-zero, non-null values (both positive and negative)\n\t\tconst nonZeroValues: number[] = [];\n\n\t\tfor ( const series of data ) {\n\t\t\tfor ( const point of series.data ) {\n\t\t\t\tif ( point.value !== null && point.value !== 0 ) {\n\t\t\t\t\tnonZeroValues.push( point.value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( nonZeroValues.length === 0 ) return data;\n\n\t\t// Convert to absolute values to find the range\n\t\tconst absoluteValues = nonZeroValues.map( Math.abs );\n\n\t\t// Calculate min and max based on absolute values\n\t\tconst minAbsoluteValue = Math.min( ...absoluteValues );\n\t\tconst maxAbsoluteValue = Math.max( ...absoluteValues );\n\n\t\t// Calculate minimum visible value using absolute range\n\t\tconst minVisibleValue = Math.min(\n\t\t\tminAbsoluteValue * minValueRatio,\n\t\t\tmaxAbsoluteValue * maxValueRatio\n\t\t);\n\n\t\treturn data.map( series => ( {\n\t\t\t...series,\n\t\t\tdata: series.data.map( ( point ): EnhancedDataPoint => {\n\t\t\t\tif ( point.value === 0 ) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...point,\n\t\t\t\t\t\tvisualValue: minVisibleValue,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\treturn point;\n\t\t\t} ),\n\t\t} ) );\n\t}, [ data, enabled, minValueRatio, maxValueRatio ] );\n};\n","import { useMemo } from 'react';\n\n/**\n * Data point interface for charts with interactive legends.\n * Requires label for series identification, value for calculations, and percentage for display.\n */\ninterface DataPointWithPercentage {\n\tlabel: string;\n\tvalue: number;\n\tpercentage: number;\n}\n\n/**\n * Parameters for the useInteractiveLegendData hook.\n */\ninterface UseInteractiveLegendDataParams< T extends DataPointWithPercentage > {\n\t/** The chart data to filter based on legend visibility */\n\tdata: T[];\n\t/** Unique chart identifier, required for interactive legends */\n\tchartId: string | undefined;\n\t/** Whether interactive legend filtering is enabled */\n\tlegendInteractive: boolean;\n\t/** Function to check if a series is visible in the legend */\n\tisSeriesVisible: ( chartId: string, label: string ) => boolean;\n}\n\n/**\n * Return value from the useInteractiveLegendData hook.\n */\ninterface UseInteractiveLegendDataResult< T extends DataPointWithPercentage > {\n\t/** Filtered data array containing only visible segments with recalculated percentages */\n\tvisibleData: T[];\n\t/** Boolean indicating if all segments are hidden */\n\tallSegmentsHidden: boolean;\n\t/**\n\t * Legend data with recalculated percentages for visible items.\n\t * Uses original data for hidden items, but shows recalculated percentages for visible ones.\n\t * This ensures the legend displays accurate percentages while maintaining all entries.\n\t */\n\tlegendData: T[];\n}\n\n/**\n * Custom hook to filter and recalculate chart data for interactive legends.\n *\n * When interactive legends are enabled, this hook:\n * 1. Filters data to show only visible series based on legend selection\n * 2. Recalculates percentages so visible segments total 100%\n * 3. Tracks whether all segments are hidden to show empty state\n *\n * This is particularly useful for pie charts, donut charts, and semi-circle charts\n * where segment visibility and percentages need to be dynamically adjusted.\n *\n * @example\n * ```tsx\n * const { visibleData, allSegmentsHidden, legendData } = useInteractiveLegendData({\n * data: chartData,\n * chartId: 'my-pie-chart',\n * legendInteractive: true,\n * isSeriesVisible: (id, label) => context.isSeriesVisible(id, label),\n * });\n *\n * // Use legendData for creating legend items (shows recalculated percentages)\n * const legendItems = useChartLegendItems(legendData, legendOptions);\n *\n * if (allSegmentsHidden) {\n * return <EmptyState />;\n * }\n *\n * // Use visibleData for rendering the chart (only visible segments)\n * return <PieChart data={visibleData} />;\n * ```\n *\n * @param params - Configuration object for the hook\n * @param params.data - The chart data to filter\n * @param params.chartId - Unique identifier for the chart (required for interactive mode)\n * @param params.legendInteractive - Whether to enable interactive filtering\n * @param params.isSeriesVisible - Function to check series visibility\n * @return Object containing visibleData, allSegmentsHidden flag, and legendData with recalculated percentages\n */\nexport const useInteractiveLegendData = < T extends DataPointWithPercentage >( {\n\tdata,\n\tchartId,\n\tlegendInteractive,\n\tisSeriesVisible,\n}: UseInteractiveLegendDataParams< T > ): UseInteractiveLegendDataResult< T > => {\n\t// Filter and recalculate data for interactive legends\n\tconst visibleData = useMemo( () => {\n\t\t// If interactive mode is disabled or no chartId, return all data unchanged\n\t\tif ( ! chartId || ! legendInteractive ) {\n\t\t\treturn data;\n\t\t}\n\n\t\t// Filter to only visible segments based on legend state\n\t\tconst filtered = data.filter( segment => isSeriesVisible( chartId, segment.label ) );\n\n\t\t// If no segments are visible, return empty array\n\t\tif ( filtered.length === 0 ) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Recalculate percentages so visible segments total 100%\n\t\tconst totalValue = filtered.reduce( ( sum, segment ) => sum + segment.value, 0 );\n\n\t\treturn filtered.map( segment => ( {\n\t\t\t...segment,\n\t\t\tpercentage: totalValue > 0 ? ( segment.value / totalValue ) * 100 : 0,\n\t\t} ) );\n\t}, [ data, chartId, isSeriesVisible, legendInteractive ] );\n\n\t// Check if all segments are hidden (only relevant in interactive mode)\n\tconst allSegmentsHidden = useMemo( () => {\n\t\treturn legendInteractive && visibleData.length === 0;\n\t}, [ legendInteractive, visibleData ] );\n\n\t// Prepare legend data with recalculated percentages for visible items\n\t// This maintains all legend entries but shows updated percentages for visible segments\n\tconst legendData = useMemo( () => {\n\t\tif ( ! legendInteractive || ! chartId ) {\n\t\t\treturn data;\n\t\t}\n\n\t\t// Map original data to show recalculated percentages for visible items\n\t\treturn data.map( segment => {\n\t\t\tconst isVisible = isSeriesVisible( chartId, segment.label );\n\t\t\tif ( ! isVisible ) {\n\t\t\t\t// Return original data for hidden items\n\t\t\t\treturn segment;\n\t\t\t}\n\n\t\t\t// For visible items, find the recalculated percentage from visibleData\n\t\t\tconst recalculated = visibleData.find( d => d.label === segment.label );\n\t\t\treturn recalculated || segment;\n\t\t} );\n\t}, [ data, visibleData, legendInteractive, chartId, isSeriesVisible ] );\n\n\treturn { visibleData, allSegmentsHidden, legendData };\n};\n","import { useContext } from 'react';\nimport { GlobalChartsContext } from '../global-charts-provider';\nimport { defaultTheme } from '../themes';\nimport type { CompleteChartTheme } from '../../../types';\n\n/**\n * Hook to get the global chart theme from GlobalChartsProvider\n *\n * @return The global chart theme\n */\nexport const useGlobalChartsTheme = (): CompleteChartTheme => {\n\t// Get context but don't throw if it doesn't exist (for testing or standalone usage)\n\tconst context = useContext( GlobalChartsContext );\n\tconst globalTheme = context?.theme;\n\n\treturn globalTheme ?? defaultTheme;\n};\n"],"mappings":"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","names":["formatNumber","useEffect","useMemo","useCallback","useMemo","useMemo","useMemo","useMemo","useMemo","useMemo","useState","useCallback","useRef","useCallback","useRef","useState","useMemo","useMemo","useMemo","useEffect","useContext","useContext"]}
@@ -13,7 +13,7 @@ import {
13
13
  Legend,
14
14
  SingleChartContext,
15
15
  useChartLegendItems
16
- } from "./chunk-Q2LDRQN7.js";
16
+ } from "./chunk-PFT2X4OW.js";
17
17
  import {
18
18
  GlobalChartsContext,
19
19
  GlobalChartsProvider,
@@ -21,8 +21,9 @@ import {
21
21
  useChartId,
22
22
  useChartRegistration,
23
23
  useElementHeight,
24
- useGlobalChartsContext
25
- } from "./chunk-3O6FHD2T.js";
24
+ useGlobalChartsContext,
25
+ useInteractiveLegendData
26
+ } from "./chunk-A3PGOCJO.js";
26
27
 
27
28
  // src/components/pie-semi-circle-chart/pie-semi-circle-chart.tsx
28
29
  import { localPoint } from "@visx/event";
@@ -30,6 +31,7 @@ import { Group } from "@visx/group";
30
31
  import { Pie } from "@visx/shape";
31
32
  import { Text } from "@visx/text";
32
33
  import { useTooltip, useTooltipInPortal } from "@visx/tooltip";
34
+ import { __ } from "@wordpress/i18n";
33
35
  import clsx from "clsx";
34
36
  import { useCallback, useContext, useMemo } from "react";
35
37
 
@@ -41,7 +43,7 @@ var pie_semi_circle_chart_module_default = {
41
43
  };
42
44
 
43
45
  // src/components/pie-semi-circle-chart/pie-semi-circle-chart.tsx
44
- import { jsx, jsxs } from "react/jsx-runtime";
46
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
45
47
  var PAD_ANGLE = 0.03;
46
48
  var validateData = (data) => {
47
49
  if (!data.length) {
@@ -73,6 +75,7 @@ var PieSemiCircleChartInternal = ({
73
75
  legendItemClassName,
74
76
  legendShape = "circle",
75
77
  legendValueDisplay = "percentage",
78
+ legendInteractive = false,
76
79
  label,
77
80
  note,
78
81
  className,
@@ -112,7 +115,13 @@ var PieSemiCircleChartInternal = ({
112
115
  [handleMouseMove]
113
116
  );
114
117
  const { isValid, message } = validateData(data);
115
- const { getElementStyles } = useGlobalChartsContext();
118
+ const { getElementStyles, isSeriesVisible } = useGlobalChartsContext();
119
+ const { visibleData, allSegmentsHidden, legendData } = useInteractiveLegendData({
120
+ data,
121
+ chartId,
122
+ legendInteractive,
123
+ isSeriesVisible
124
+ });
116
125
  const accessors = useMemo(
117
126
  () => ({
118
127
  value: (d) => d.value,
@@ -125,7 +134,7 @@ var PieSemiCircleChartInternal = ({
125
134
  () => ({ showValues: true, legendValueDisplay }),
126
135
  [legendValueDisplay]
127
136
  );
128
- const legendItems = useChartLegendItems(data, legendOptions);
137
+ const legendItems = useChartLegendItems(legendData, legendOptions);
129
138
  const { svgChildren, htmlChildren, otherChildren } = useChartChildren(
130
139
  children,
131
140
  "PieSemiCircleChart"
@@ -151,10 +160,13 @@ var PieSemiCircleChartInternal = ({
151
160
  const chartHeight = height - (showLegend && legendPosition === "top" ? legendHeight : 0);
152
161
  const radius = Math.min(width / 2, chartHeight);
153
162
  const innerRadius = radius * (1 - thickness);
154
- const dataWithIndex = data.map((d, index) => ({
155
- ...d,
156
- index
157
- }));
163
+ const dataWithIndex = visibleData.map((d) => {
164
+ const originalIndex = data.findIndex((item) => item.label === d.label);
165
+ return {
166
+ ...d,
167
+ index: originalIndex >= 0 ? originalIndex : 0
168
+ };
169
+ });
158
170
  const startAngle = clockwise ? -Math.PI / 2 : Math.PI / 2;
159
171
  const endAngle = clockwise ? Math.PI / 2 : -Math.PI / 2;
160
172
  return /* @__PURE__ */ jsx(
@@ -183,7 +195,20 @@ var PieSemiCircleChartInternal = ({
183
195
  height: radius,
184
196
  viewBox: `0 0 ${width} ${chartHeight}`,
185
197
  "data-testid": "pie-chart-svg",
186
- children: /* @__PURE__ */ jsxs(Group, { top: chartHeight, left: width / 2, children: [
198
+ children: /* @__PURE__ */ jsx(Group, { top: chartHeight, left: width / 2, children: allSegmentsHidden ? /* @__PURE__ */ jsx(
199
+ "text",
200
+ {
201
+ textAnchor: "middle",
202
+ y: -radius / 2,
203
+ fill: "#ccc",
204
+ fontSize: "14",
205
+ fontFamily: "-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif",
206
+ children: __(
207
+ "All segments are hidden. Click legend items to show data.",
208
+ "jetpack-charts"
209
+ )
210
+ }
211
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
187
212
  /* @__PURE__ */ jsx(
188
213
  Pie,
189
214
  {
@@ -238,8 +263,8 @@ var PieSemiCircleChartInternal = ({
238
263
  }
239
264
  )
240
265
  ] }),
241
- svgChildren
242
- ] })
266
+ !allSegmentsHidden && svgChildren
267
+ ] }) })
243
268
  }
244
269
  ),
245
270
  withTooltips && tooltipOpen && tooltipData && /* @__PURE__ */ jsx(TooltipInPortal, { top: tooltipTop || 0, left: tooltipLeft || 0, children: /* @__PURE__ */ jsx("div", { role: "tooltip", children: /* @__PURE__ */ jsx(BaseTooltip, { data: tooltipData, top: 0, left: 0, renderContainer: false }) }) }),
@@ -254,7 +279,8 @@ var PieSemiCircleChartInternal = ({
254
279
  legendItemClassName,
255
280
  shape: legendShape,
256
281
  ref: legendRef,
257
- chartId
282
+ chartId,
283
+ interactive: legendInteractive
258
284
  }
259
285
  ),
260
286
  htmlChildren,
@@ -291,4 +317,4 @@ export {
291
317
  PieSemiCircleChart,
292
318
  PieSemiCircleChartResponsive
293
319
  };
294
- //# sourceMappingURL=chunk-G66WE3ON.js.map
320
+ //# sourceMappingURL=chunk-BWEMZ72V.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/pie-semi-circle-chart/pie-semi-circle-chart.tsx","../src/components/pie-semi-circle-chart/pie-semi-circle-chart.module.scss"],"sourcesContent":["import { localPoint } from '@visx/event';\nimport { Group } from '@visx/group';\nimport { Pie } from '@visx/shape';\nimport { Text } from '@visx/text';\nimport { useTooltip, useTooltipInPortal } from '@visx/tooltip';\nimport { __ } from '@wordpress/i18n';\nimport clsx from 'clsx';\nimport { useCallback, useContext, useMemo } from 'react';\nimport { useElementHeight, useInteractiveLegendData } from '../../hooks';\nimport {\n\tGlobalChartsProvider,\n\tuseChartId,\n\tuseChartRegistration,\n\tuseGlobalChartsContext,\n\tGlobalChartsContext,\n} from '../../providers';\nimport { attachSubComponents } from '../../utils';\nimport { Legend, useChartLegendItems } from '../legend';\nimport { ChartSVG, ChartHTML, useChartChildren } from '../private/chart-composition';\nimport { SingleChartContext } from '../private/single-chart-context';\nimport { withResponsive } from '../private/with-responsive';\nimport { BaseTooltip } from '../tooltip';\nimport styles from './pie-semi-circle-chart.module.scss';\nimport type { BaseChartProps, DataPointPercentage, Optional } from '../../types';\nimport type { LegendValueDisplay } from '../legend';\nimport type { ChartComponentWithComposition } from '../private/chart-composition';\nimport type { ResponsiveConfig } from '../private/with-responsive';\nimport type { PieArcDatum } from '@visx/shape/lib/shapes/Pie';\nimport type { FC, MouseEvent, ReactNode } from 'react';\n\nconst PAD_ANGLE = 0.03; // Padding between segments\n\nexport interface PieSemiCircleChartProps extends BaseChartProps< DataPointPercentage[] > {\n\t/**\n\t * Width of the chart in pixels; height would be half of this value calculated automatically.\n\t */\n\twidth?: number;\n\n\t/**\n\t * Thickness of the pie chart. A value between 0 and 1\n\t */\n\tthickness?: number;\n\n\t/**\n\t * Direction of chart rendering\n\t * true for clockwise, false for counter-clockwise\n\t */\n\tclockwise?: boolean;\n\n\t/**\n\t * Label text to display above the chart\n\t */\n\tlabel?: string;\n\n\t/**\n\t * Note text to display below the label\n\t */\n\tnote?: string;\n\n\t/**\n\t * Use the children prop to render additional elements on the chart.\n\t */\n\tchildren?: ReactNode;\n\n\t/**\n\t * What type of value to display in the legend when showValues is true.\n\t * - 'percentage': Shows percentage values (e.g., \"23%\") [default]\n\t * - 'value': Shows raw numeric values (e.g., \"30000\")\n\t * - 'valueDisplay': Shows formatted values (e.g., \"30K\")\n\t * - 'none': Shows no values, only labels\n\t */\n\tlegendValueDisplay?: LegendValueDisplay;\n\n\t/**\n\t * Enable interactive legend items that can toggle segment visibility.\n\t * Requires chartId and GlobalChartsProvider.\n\t * When segments are hidden, percentages are recalculated so visible segments total 100%.\n\t */\n\tlegendInteractive?: boolean;\n\n\t/**\n\t * Horizontal offset for tooltip positioning in pixels (default: 0)\n\t */\n\ttooltipOffsetX?: number;\n\n\t/**\n\t * Vertical offset for tooltip positioning in pixels (default: -15)\n\t */\n\ttooltipOffsetY?: number;\n}\n\n// Base props type with optional responsive properties\ntype PieSemiCircleChartBaseProps = Optional< PieSemiCircleChartProps, 'width' >;\n\n// Composition API types\ntype PieSemiCircleChartComponent = ChartComponentWithComposition< PieSemiCircleChartBaseProps >;\ntype PieSemiCircleChartResponsiveComponent = ChartComponentWithComposition<\n\tPieSemiCircleChartBaseProps & ResponsiveConfig\n>;\n\nexport type ArcData = PieArcDatum< DataPointPercentage >;\n\n/**\n * Validates the semi-circle pie chart data\n * @param data - The data to validate\n * @return Object containing validation result and error message\n */\nconst validateData = ( data: DataPointPercentage[] ) => {\n\tif ( ! data.length ) {\n\t\treturn { isValid: false, message: 'No data available' };\n\t}\n\n\t// Check for negative values\n\tconst hasNegativeValues = data.some( item => item.percentage < 0 || item.value < 0 );\n\tif ( hasNegativeValues ) {\n\t\treturn { isValid: false, message: 'Invalid data: Negative values are not allowed' };\n\t}\n\n\t// Validate total percentage is greater than 0\n\tconst totalPercentage = data.reduce( ( sum, item ) => sum + item.percentage, 0 );\n\tif ( totalPercentage <= 0 ) {\n\t\treturn { isValid: false, message: 'Invalid percentage total: Must be greater than 0' };\n\t}\n\n\treturn { isValid: true, message: '' };\n};\n\nconst PieSemiCircleChartInternal: FC< PieSemiCircleChartProps > = ( {\n\tdata,\n\tchartId: providedChartId,\n\twidth = 400,\n\tthickness = 0.4,\n\tclockwise = true,\n\twithTooltips = false,\n\tshowLegend = false,\n\tlegendOrientation = 'horizontal',\n\tlegendPosition = 'bottom',\n\tlegendAlignment = 'center',\n\tlegendMaxWidth,\n\tlegendTextOverflow = 'wrap',\n\tlegendItemClassName,\n\tlegendShape = 'circle',\n\tlegendValueDisplay = 'percentage',\n\tlegendInteractive = false,\n\tlabel,\n\tnote,\n\tclassName,\n\tchildren,\n\ttooltipOffsetX = 0,\n\ttooltipOffsetY = -15,\n} ) => {\n\tconst chartId = useChartId( providedChartId );\n\tconst [ legendRef, legendHeight ] = useElementHeight< HTMLDivElement >();\n\tconst { tooltipOpen, tooltipLeft, tooltipTop, tooltipData, hideTooltip, showTooltip } =\n\t\tuseTooltip< DataPointPercentage >();\n\n\t// Set up portal tooltip for better z-index handling\n\tconst { containerRef, TooltipInPortal } = useTooltipInPortal( {\n\t\tdetectBounds: true,\n\t\tscroll: true,\n\t\tdebounce: 0,\n\t} );\n\n\tconst handleMouseMove = useCallback(\n\t\t( event: MouseEvent< SVGElement >, arc: ArcData ) => {\n\t\t\t// Get coordinates relative to the current target element\n\t\t\tconst coords = localPoint( event );\n\t\t\tif ( coords ) {\n\t\t\t\t// Account for legend offset when legend is on top\n\t\t\t\tconst legendOffset = showLegend && legendPosition === 'top' ? legendHeight : 0;\n\t\t\t\tshowTooltip( {\n\t\t\t\t\ttooltipData: arc.data,\n\t\t\t\t\ttooltipLeft: coords.x + tooltipOffsetX,\n\t\t\t\t\ttooltipTop: coords.y + legendOffset + tooltipOffsetY,\n\t\t\t\t} );\n\t\t\t}\n\t\t},\n\t\t[ showTooltip, tooltipOffsetX, tooltipOffsetY, showLegend, legendPosition, legendHeight ]\n\t);\n\n\tconst handleMouseLeave = useCallback( () => {\n\t\thideTooltip();\n\t}, [ hideTooltip ] );\n\n\tconst handleArcMouseMove = useCallback(\n\t\t( arc: ArcData ) => ( event: MouseEvent< SVGElement > ) => {\n\t\t\thandleMouseMove( event, arc );\n\t\t},\n\t\t[ handleMouseMove ]\n\t);\n\n\t// Validate data first to get validation result\n\tconst { isValid, message } = validateData( data );\n\n\tconst { getElementStyles, isSeriesVisible } = useGlobalChartsContext();\n\n\t// Filter and recalculate data for interactive legends\n\tconst { visibleData, allSegmentsHidden, legendData } = useInteractiveLegendData( {\n\t\tdata,\n\t\tchartId,\n\t\tlegendInteractive,\n\t\tisSeriesVisible,\n\t} );\n\n\t// Define accessors with useMemo to avoid changing dependencies\n\tconst accessors = useMemo(\n\t\t() => ( {\n\t\t\tvalue: ( d: DataPointPercentage ) => d.value,\n\t\t\tsort: (\n\t\t\t\ta: DataPointPercentage & { index: number },\n\t\t\t\tb: DataPointPercentage & { index: number }\n\t\t\t) => b.value - a.value,\n\t\t\tfill: ( d: DataPointPercentage & { index: number } ) =>\n\t\t\t\tgetElementStyles( { data: d, index: d.index } ).color,\n\t\t} ),\n\t\t[ getElementStyles ]\n\t);\n\n\t// Memoize legend options to prevent unnecessary re-calculations\n\tconst legendOptions = useMemo(\n\t\t() => ( { showValues: true, legendValueDisplay } ),\n\t\t[ legendValueDisplay ]\n\t);\n\n\t// Create legend items using legendData (has recalculated percentages for visible items)\n\tconst legendItems = useChartLegendItems( legendData, legendOptions );\n\n\t// Process children to extract compound components\n\tconst { svgChildren, htmlChildren, otherChildren } = useChartChildren(\n\t\tchildren,\n\t\t'PieSemiCircleChart'\n\t);\n\n\t// Memoize metadata to prevent unnecessary re-registration\n\tconst chartMetadata = useMemo(\n\t\t() => ( {\n\t\t\tthickness,\n\t\t\tclockwise,\n\t\t} ),\n\t\t[ thickness, clockwise ]\n\t);\n\n\t// Register chart with context only if data is valid\n\tuseChartRegistration( {\n\t\tchartId,\n\t\tlegendItems,\n\t\tchartType: 'pie-semi-circle',\n\t\tisDataValid: isValid,\n\t\tmetadata: chartMetadata,\n\t} );\n\n\tif ( ! isValid ) {\n\t\treturn (\n\t\t\t<div className={ styles[ 'pie-semi-circle-chart' ] }>\n\t\t\t\t<svg width={ width } height={ width / 2 } data-testid=\"pie-chart-svg\">\n\t\t\t\t\t<text x=\"50%\" y=\"50%\" textAnchor=\"middle\" className={ styles.error }>\n\t\t\t\t\t\t{ message }\n\t\t\t\t\t</text>\n\t\t\t\t</svg>\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Calculate chart dimensions\n\t// TODO: we might want to accept height as a prop in the future, because the height of container might not always be enough.\n\tconst height = width / 2;\n\t// The chart only takes the height minus the legend height.\n\tconst chartHeight = height - ( showLegend && legendPosition === 'top' ? legendHeight : 0 );\n\tconst radius = Math.min( width / 2, chartHeight );\n\tconst innerRadius = radius * ( 1 - thickness );\n\n\t// Map data with index for color assignment\n\t// When interactive, we need to find the original index to maintain consistent colors\n\tconst dataWithIndex = visibleData.map( d => {\n\t\tconst originalIndex = data.findIndex( item => item.label === d.label );\n\t\treturn {\n\t\t\t...d,\n\t\t\tindex: originalIndex >= 0 ? originalIndex : 0,\n\t\t};\n\t} );\n\n\t// Configure pie angles based on clockwise direction\n\tconst startAngle = clockwise ? -Math.PI / 2 : Math.PI / 2;\n\tconst endAngle = clockwise ? Math.PI / 2 : -Math.PI / 2;\n\n\treturn (\n\t\t<SingleChartContext.Provider\n\t\t\tvalue={ {\n\t\t\t\tchartId,\n\t\t\t\tchartWidth: width,\n\t\t\t\tchartHeight: radius,\n\t\t\t} }\n\t\t>\n\t\t\t<div\n\t\t\t\tref={ containerRef }\n\t\t\t\tclassName={ clsx( 'pie-semi-circle-chart', styles[ 'pie-semi-circle-chart' ], className ) }\n\t\t\t\tdata-testid=\"pie-chart-container\"\n\t\t\t\tstyle={ {\n\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\tflexDirection: showLegend && legendPosition === 'top' ? 'column-reverse' : 'column',\n\t\t\t\t} }\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\twidth={ width }\n\t\t\t\t\theight={ radius }\n\t\t\t\t\tviewBox={ `0 0 ${ width } ${ chartHeight }` }\n\t\t\t\t\tdata-testid=\"pie-chart-svg\"\n\t\t\t\t>\n\t\t\t\t\t{ /* Main chart group centered horizontally and positioned at bottom */ }\n\t\t\t\t\t<Group top={ chartHeight } left={ width / 2 }>\n\t\t\t\t\t\t{ allSegmentsHidden ? (\n\t\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t\ttextAnchor=\"middle\"\n\t\t\t\t\t\t\t\ty={ -radius / 2 }\n\t\t\t\t\t\t\t\tfill=\"#ccc\"\n\t\t\t\t\t\t\t\tfontSize=\"14\"\n\t\t\t\t\t\t\t\tfontFamily=\"-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{ __(\n\t\t\t\t\t\t\t\t\t'All segments are hidden. Click legend items to show data.',\n\t\t\t\t\t\t\t\t\t'jetpack-charts'\n\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t</text>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t{ /* Pie chart */ }\n\t\t\t\t\t\t\t\t<Pie< DataPointPercentage & { index: number } >\n\t\t\t\t\t\t\t\t\tdata={ dataWithIndex }\n\t\t\t\t\t\t\t\t\tpieValue={ accessors.value }\n\t\t\t\t\t\t\t\t\touterRadius={ radius }\n\t\t\t\t\t\t\t\t\tinnerRadius={ innerRadius }\n\t\t\t\t\t\t\t\t\tcornerRadius={ 3 }\n\t\t\t\t\t\t\t\t\tpadAngle={ PAD_ANGLE }\n\t\t\t\t\t\t\t\t\tstartAngle={ startAngle }\n\t\t\t\t\t\t\t\t\tendAngle={ endAngle }\n\t\t\t\t\t\t\t\t\tpieSort={ accessors.sort }\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{ pie => {\n\t\t\t\t\t\t\t\t\t\treturn pie.arcs.map( arc => (\n\t\t\t\t\t\t\t\t\t\t\t<g\n\t\t\t\t\t\t\t\t\t\t\t\tkey={ arc.data.label }\n\t\t\t\t\t\t\t\t\t\t\t\tonMouseMove={ withTooltips ? handleArcMouseMove( arc ) : undefined }\n\t\t\t\t\t\t\t\t\t\t\t\tonMouseLeave={ withTooltips ? handleMouseLeave : undefined }\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\t\t\t\t\t\td={ pie.path( arc ) || '' }\n\t\t\t\t\t\t\t\t\t\t\t\t\tfill={ accessors.fill( arc.data ) }\n\t\t\t\t\t\t\t\t\t\t\t\t\tdata-testid=\"pie-segment\"\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t</g>\n\t\t\t\t\t\t\t\t\t\t) );\n\t\t\t\t\t\t\t\t\t} }\n\t\t\t\t\t\t\t\t</Pie>\n\n\t\t\t\t\t\t\t\t{ /* Label and note text */ }\n\t\t\t\t\t\t\t\t<Group>\n\t\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\t\ttextAnchor=\"middle\"\n\t\t\t\t\t\t\t\t\t\tverticalAnchor=\"start\"\n\t\t\t\t\t\t\t\t\t\ty={ -40 } // Position above the chart with space for note\n\t\t\t\t\t\t\t\t\t\tclassName={ styles.label }\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{ label }\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\t\ttextAnchor=\"middle\"\n\t\t\t\t\t\t\t\t\t\tverticalAnchor=\"start\"\n\t\t\t\t\t\t\t\t\t\ty={ -20 } // Position between label and chart\n\t\t\t\t\t\t\t\t\t\tclassName={ styles.note }\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{ note }\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t</Group>\n\n\t\t\t\t\t\t\t\t{ /* Render SVG children from composition API */ }\n\t\t\t\t\t\t\t\t{ ! allSegmentsHidden && svgChildren }\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) }\n\t\t\t\t\t</Group>\n\t\t\t\t</svg>\n\n\t\t\t\t{ withTooltips && tooltipOpen && tooltipData && (\n\t\t\t\t\t<TooltipInPortal top={ tooltipTop || 0 } left={ tooltipLeft || 0 }>\n\t\t\t\t\t\t<div role=\"tooltip\">\n\t\t\t\t\t\t\t<BaseTooltip data={ tooltipData } top={ 0 } left={ 0 } renderContainer={ false } />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</TooltipInPortal>\n\t\t\t\t) }\n\n\t\t\t\t{ showLegend && (\n\t\t\t\t\t<Legend\n\t\t\t\t\t\torientation={ legendOrientation }\n\t\t\t\t\t\tposition={ legendPosition }\n\t\t\t\t\t\talignment={ legendAlignment }\n\t\t\t\t\t\tmaxWidth={ legendMaxWidth }\n\t\t\t\t\t\ttextOverflow={ legendTextOverflow }\n\t\t\t\t\t\tlegendItemClassName={ legendItemClassName }\n\t\t\t\t\t\tshape={ legendShape }\n\t\t\t\t\t\tref={ legendRef }\n\t\t\t\t\t\tchartId={ chartId }\n\t\t\t\t\t\tinteractive={ legendInteractive }\n\t\t\t\t\t/>\n\t\t\t\t) }\n\n\t\t\t\t{ /* Render HTML children from composition API */ }\n\t\t\t\t{ htmlChildren }\n\n\t\t\t\t{ /* Render any other children that aren't compound components */ }\n\t\t\t\t{ otherChildren }\n\t\t\t</div>\n\t\t</SingleChartContext.Provider>\n\t);\n};\n\nconst PieSemiCircleChartWithProvider: FC< PieSemiCircleChartProps > = props => {\n\tconst existingContext = useContext( GlobalChartsContext );\n\n\t// If we're already in a GlobalChartsProvider context, don't create a new one\n\tif ( existingContext ) {\n\t\treturn <PieSemiCircleChartInternal { ...props } />;\n\t}\n\n\t// Otherwise, create our own GlobalChartsProvider\n\treturn (\n\t\t<GlobalChartsProvider>\n\t\t\t<PieSemiCircleChartInternal { ...props } />\n\t\t</GlobalChartsProvider>\n\t);\n};\n\nPieSemiCircleChartWithProvider.displayName = 'PieSemiCircleChart';\n\n// Create PieSemiCircleChart with composition API\nconst PieSemiCircleChart = attachSubComponents( PieSemiCircleChartWithProvider, {\n\tLegend: Legend,\n\tSVG: ChartSVG,\n\tHTML: ChartHTML,\n} ) as PieSemiCircleChartComponent;\n\n// Create responsive PieSemiCircleChart with composition API\nconst PieSemiCircleChartResponsive = attachSubComponents(\n\twithResponsive< PieSemiCircleChartProps >( PieSemiCircleChartWithProvider ),\n\t{\n\t\tLegend: Legend,\n\t\tSVG: ChartSVG,\n\t\tHTML: ChartHTML,\n\t}\n) as PieSemiCircleChartResponsiveComponent;\n\nexport {\n\tPieSemiCircleChartResponsive as default,\n\tPieSemiCircleChart as PieSemiCircleChartUnresponsive,\n};\n","import 'css-chunk:src/components/pie-semi-circle-chart/pie-semi-circle-chart.module.scss';export default {\n \"pie-semi-circle-chart\": \"a8ccharts-r5jk9c\",\n \"label\": \"a8ccharts-nPqOgD\",\n \"note\": \"a8ccharts-LpBZQh\"\n};"],"mappings":"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","names":[]}