@automattic/charts 2.0.1 → 3.1.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 (102) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/TOKENS.md +109 -50
  3. package/dist/index.cjs +529 -233
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.css +118 -55
  6. package/dist/index.d.cts +90 -48
  7. package/dist/index.d.ts +90 -48
  8. package/dist/index.js +527 -235
  9. package/dist/index.js.map +1 -1
  10. package/package.json +1 -1
  11. package/src/charts/area-chart/area-chart.module.scss +8 -3
  12. package/src/charts/area-chart/area-chart.tsx +25 -25
  13. package/src/charts/area-chart/private/overlays.tsx +3 -3
  14. package/src/charts/area-chart/test/area-chart.test.tsx +301 -11
  15. package/src/charts/area-chart/types.ts +4 -3
  16. package/src/charts/bar-chart/bar-chart.module.scss +14 -6
  17. package/src/charts/bar-chart/bar-chart.tsx +21 -15
  18. package/src/charts/bar-chart/test/bar-chart.test.tsx +255 -2
  19. package/src/charts/conversion-funnel-chart/conversion-funnel-chart.module.scss +23 -18
  20. package/src/charts/conversion-funnel-chart/conversion-funnel-chart.tsx +107 -86
  21. package/src/charts/conversion-funnel-chart/test/chart-scope.test.tsx +36 -0
  22. package/src/charts/geo-chart/geo-chart.module.scss +8 -0
  23. package/src/charts/geo-chart/geo-chart.tsx +12 -4
  24. package/src/charts/heatmap-chart/heatmap-chart.module.scss +22 -9
  25. package/src/charts/heatmap-chart/heatmap-chart.tsx +43 -13
  26. package/src/charts/heatmap-chart/private/build-calendar-data.ts +65 -5
  27. package/src/charts/heatmap-chart/test/build-calendar-data.test.ts +125 -0
  28. package/src/charts/heatmap-chart/types.ts +8 -0
  29. package/src/charts/leaderboard-chart/leaderboard-chart.module.scss +13 -7
  30. package/src/charts/leaderboard-chart/leaderboard-chart.tsx +17 -22
  31. package/src/charts/leaderboard-chart/test/leaderboard-chart.test.tsx +107 -1
  32. package/src/charts/leaderboard-chart/types.ts +0 -2
  33. package/src/charts/line-chart/line-chart.module.scss +12 -7
  34. package/src/charts/line-chart/line-chart.tsx +32 -28
  35. package/src/charts/line-chart/private/line-chart-annotation.tsx +4 -4
  36. package/src/charts/line-chart/private/line-chart-annotations-overlay.tsx +2 -2
  37. package/src/charts/line-chart/test/line-chart.test.tsx +262 -5
  38. package/src/charts/line-chart/types.ts +4 -3
  39. package/src/charts/pie-chart/pie-chart.tsx +12 -14
  40. package/src/charts/pie-chart/test/pie-chart.test.tsx +73 -1
  41. package/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.module.scss +2 -2
  42. package/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.tsx +12 -14
  43. package/src/charts/private/{single-chart-context/single-chart-context.tsx → chart-instance-context/chart-instance-context.ts} +1 -5
  44. package/src/charts/private/chart-instance-context/index.ts +3 -0
  45. package/src/charts/private/{single-chart-context/use-single-chart-context.ts → chart-instance-context/use-chart-instance-context.ts} +1 -3
  46. package/src/charts/private/svg-empty-state/get-all-hidden-message.ts +41 -0
  47. package/src/charts/private/svg-empty-state/index.ts +1 -0
  48. package/src/charts/private/svg-empty-state/svg-empty-state.module.scss +1 -1
  49. package/src/charts/private/svg-empty-state/test/get-all-hidden-message.test.ts +15 -0
  50. package/src/charts/private/with-responsive/test/with-responsive.test.tsx +16 -0
  51. package/src/charts/private/with-responsive/with-responsive.tsx +18 -11
  52. package/src/charts/private/x-zoom/test/x-zoom.test.tsx +2 -2
  53. package/src/charts/private/x-zoom/x-zoom.module.scss +3 -3
  54. package/src/charts/private/x-zoom/x-zoom.tsx +2 -2
  55. package/src/components/legend/legend.tsx +4 -4
  56. package/src/components/legend/private/base-legend.module.scss +1 -1
  57. package/src/components/legend/private/base-legend.tsx +70 -19
  58. package/src/components/legend/test/legend.test.tsx +100 -4
  59. package/src/components/tooltip/accessible-tooltip.tsx +17 -4
  60. package/src/components/tooltip/base-tooltip.tsx +8 -1
  61. package/src/components/trend-indicator/test/trend-indicator.test.tsx +20 -0
  62. package/src/components/trend-indicator/trend-indicator.module.scss +4 -7
  63. package/src/components/trend-indicator/trend-indicator.tsx +3 -0
  64. package/src/hooks/index.ts +1 -1
  65. package/src/hooks/test/use-xychart-theme-provider-override.test.tsx +28 -0
  66. package/src/hooks/test/use-xychart-theme-style-reads.test.tsx +19 -13
  67. package/src/hooks/test/use-xychart-theme.test.tsx +25 -0
  68. package/src/hooks/{use-interactive-legend-data.ts → use-legend-visibility-data.ts} +29 -30
  69. package/src/hooks/use-xychart-theme.ts +6 -4
  70. package/src/index.ts +12 -3
  71. package/src/providers/chart-context/global-charts-provider.tsx +127 -30
  72. package/src/providers/chart-context/hooks/use-default-hidden-series.ts +47 -0
  73. package/src/providers/chart-context/private/theme-override-vars.ts +87 -0
  74. package/src/providers/chart-context/private/with-catalog-pointers.ts +50 -0
  75. package/src/providers/chart-context/test/chart-context.test.tsx +142 -40
  76. package/src/providers/chart-context/test/chart-scope-class.test.tsx +19 -0
  77. package/src/providers/chart-context/test/sparse-theme.test.ts +35 -0
  78. package/src/providers/chart-context/test/theme-override-vars-guard.test.tsx +29 -0
  79. package/src/providers/chart-context/test/theme-override-vars.test.ts +118 -0
  80. package/src/providers/chart-context/test/use-default-hidden-series-paint.test.tsx +56 -0
  81. package/src/providers/chart-context/test/use-default-hidden-series.ssr.test.tsx +39 -0
  82. package/src/providers/chart-context/test/use-default-hidden-series.test.tsx +222 -0
  83. package/src/providers/chart-context/test/with-catalog-pointers.test.ts +47 -0
  84. package/src/providers/chart-context/themes.ts +18 -27
  85. package/src/providers/chart-context/types.ts +7 -4
  86. package/src/providers/chart-scope/chart-scope-context.ts +8 -0
  87. package/src/providers/chart-scope/index.ts +3 -0
  88. package/src/providers/chart-scope/test/chart-scope.test.tsx +24 -0
  89. package/src/providers/chart-scope/test/use-standalone-scope-class.test.tsx +20 -0
  90. package/src/providers/chart-scope/use-chart-scope-element.ts +9 -0
  91. package/src/providers/chart-scope/use-standalone-scope-class.ts +13 -0
  92. package/src/providers/index.ts +1 -0
  93. package/src/styles/chart-scope-class.ts +6 -0
  94. package/src/styles/chart-scope.scss +83 -0
  95. package/src/styles/test/chart-scope.test.ts +165 -0
  96. package/src/styles/test/wpds-fallbacks.test.ts +131 -0
  97. package/src/types.ts +12 -34
  98. package/src/charts/private/grid-control/grid-control.module.scss +0 -8
  99. package/src/charts/private/grid-control/grid-control.tsx +0 -26
  100. package/src/charts/private/grid-control/index.ts +0 -1
  101. package/src/charts/private/grid-control/test/grid-control.test.tsx +0 -56
  102. package/src/charts/private/single-chart-context/index.ts +0 -8
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { getStringWidth as getStringWidth$1 } from "./visx/text/index.js";
2
2
  import { formatNumber, formatNumberCompact } from "@automattic/number-formatters";
3
3
  import { AnimatedAreaSeries, AnimatedAreaStack, AreaSeries, Axis, BarGroup, BarSeries, DataContext, Grid, Tooltip, TooltipContext, XYChart, buildChartTheme } from "@visx/xychart";
4
- import { __, sprintf } from "@wordpress/i18n";
4
+ import { __, _x, sprintf } from "@wordpress/i18n";
5
5
  import clsx from "clsx";
6
6
  import * as React from "react";
7
7
  import { Children, Fragment, createContext, createContext as createContext$1, createElement, forwardRef, forwardRef as forwardRef$1, isValidElement, memo, useCallback, useCallback as useCallback$1, useContext, useContext as useContext$1, useEffect, useEffect as useEffect$1, useId, useImperativeHandle, useLayoutEffect, useMemo, useMemo as useMemo$1, useRef, useRef as useRef$1, useState, useState as useState$1 } from "react";
@@ -50,17 +50,23 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
50
50
  enumerable: true
51
51
  }) : target, mod));
52
52
  //#endregion
53
- //#region src/charts/private/single-chart-context/single-chart-context.tsx
53
+ //#region src/charts/private/chart-instance-context/chart-instance-context.ts
54
54
  const ChartInstanceContext = createContext(null);
55
- const SingleChartContext = ChartInstanceContext;
56
55
  //#endregion
57
- //#region src/charts/private/single-chart-context/use-single-chart-context.ts
56
+ //#region src/charts/private/chart-instance-context/use-chart-instance-context.ts
58
57
  const useChartInstanceContext = () => {
59
58
  const context = useContext(ChartInstanceContext);
60
59
  if (!context) throw new Error("useChartInstanceContext must be used within a Chart component");
61
60
  return context;
62
61
  };
63
- const useSingleChartContext = useChartInstanceContext;
62
+ //#endregion
63
+ //#region src/styles/chart-scope-class.ts
64
+ /**
65
+ * Stable class that carries the `--a8c-charts-*` catalog. Applied to the `GlobalChartsProvider` wrapper, to portal-rendered surfaces (which sit outside the provider tree), and to standalone components when no provider is above them.
66
+ *
67
+ * Deliberately unhashed: consumers are documented as being able to target it to override a token on the provider element.
68
+ */
69
+ const CHART_SCOPE_CLASS = "a8c-charts-scope";
64
70
  //#endregion
65
71
  //#region src/utils/create-composition.ts
66
72
  /**
@@ -618,6 +624,14 @@ const resolveFontSize = (val) => {
618
624
  }
619
625
  };
620
626
  //#endregion
627
+ //#region src/providers/chart-scope/chart-scope-context.ts
628
+ /**
629
+ * The nearest chart element, published so JS token resolution reads the same CSS cascade that paints the chart's own colours.
630
+ *
631
+ * All JS token resolution reads this element rather than `document.documentElement`, so a `getComputedStyle` call sees the same `--a8c-charts-*` values — including any override set inside the provider tree — that a CSS-painted sibling element does.
632
+ */
633
+ const ChartScopeContext = createContext(null);
634
+ //#endregion
621
635
  //#region src/providers/chart-context/private/get-chart-color.ts
622
636
  /**
623
637
  * Golden ratio for mathematically pleasing color distribution
@@ -747,12 +761,75 @@ const getChartColor = (index, colorCache) => {
747
761
  return hsl(Math.round(fallbackHue), fallbackSaturation / 100, fallbackLightness / 100).formatHex();
748
762
  };
749
763
  //#endregion
764
+ //#region src/providers/chart-context/private/theme-override-vars.ts
765
+ const ROLE_FOR_FIELD = [
766
+ ["--a8c-charts-color-background", (theme) => theme.backgroundColor],
767
+ ["--a8c-charts-color-grid", (theme) => theme.gridStyles?.stroke],
768
+ ["--a8c-charts-color-axis", (theme) => theme.xAxisLineStyles?.stroke],
769
+ ["--a8c-charts-color-tick", (theme) => theme.xTickLineStyles?.stroke],
770
+ ["--a8c-charts-color-label-axis", (theme) => theme.svgLabelSmall?.fill]
771
+ ];
772
+ /**
773
+ * The variable a `theme` prop override is published as, one layer outside the role itself.
774
+ *
775
+ * `chart-scope.scss` declares each of these roles as `var(<role>-theme, <catalog default>)`, so an override that is invalid at computed-value time — a fallback-less `var()` naming a token the host never set — only invalidates this variable, and the role still resolves its mapped `--wpds-*` token. Published as the role directly, such a value took the role and every bare `var(<role>)` read site down with it.
776
+ *
777
+ * @param role - The catalog role being overridden.
778
+ * @return The custom property carrying the consumer's value.
779
+ */
780
+ const themeLayerVar = (role) => `${role}-theme`;
781
+ ROLE_FOR_FIELD.map(([role]) => role);
782
+ /**
783
+ * Whether a value reads the role it is being published for, which would make the catalog entry depend on itself.
784
+ *
785
+ * The dependency runs `<role>: var(<role>-theme, …)`, so a value naming `<role>` closes a cycle through the catalog entry. CSS marks every custom property in a cycle invalid at computed-value time — the role's own fallback is *not* used, so the token resolves to nothing and every chart loses that colour. Verified in Chrome: `--role-theme: var(--role, blue); --role: var(--role-theme, green)` leaves `--role` empty, not `green`.
786
+ *
787
+ * Three things this has to get right, none of which a plain substring test gets:
788
+ *
789
+ * `var()` permits whitespace after the opening paren, so testing for `var(<role>` misses `var( --a8c-charts-color-grid, … )`.
790
+ *
791
+ * Several roles are prefixes of others (`--a8c-charts-color-label` of `--a8c-charts-color-label-secondary`), and every role is a prefix of its own theme layer. A prefix match would read a legitimate cross-role pointer as a self-reference and silently drop the override, so the role must be followed by something that cannot continue an identifier — `-` included. A value naming `<role>-theme` is therefore not treated as a self-reference: that cycle is confined to the theme layer, which leaves the role free to fall back to the catalog default.
792
+ *
793
+ * `resolveCssVariable` also accepts a bare custom-property name with no `var()` wrapper (`--a8c-charts-color-grid`), so that is legal `theme` input too. It forms no cycle — custom properties accept arbitrary token streams — so it survives as a literal string and drops silently at the use site instead of falling back to the catalog default.
794
+ *
795
+ * @param value - The consumer's value for the field.
796
+ * @param role - The catalog role this value would override.
797
+ * @return True when the value reads `role`, so it must not be published.
798
+ */
799
+ const readsOwnRole = (value, role) => value.trim() === role || new RegExp(`var\\(\\s*${role.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`).test(value);
800
+ /**
801
+ * Maps a sparse consumer theme onto the theme-layer variables its overridden catalog roles read, so CSS-painted and JS-resolved colours read one source.
802
+ *
803
+ * A value that reads the role it would override is left unpublished — that is the default theme's own pointer surviving `mergeThemes`, and publishing it would invalidate the role. The role is still reported in `roles`: `withCatalogPointers` restores its theme field to the catalog pointer either way, so CSS and visx agree on the catalog default rather than visx painting a literal CSS never sees.
804
+ *
805
+ * @param theme - The consumer's `theme` prop, before merging with the default theme.
806
+ * @return The wrapper's custom properties, and the roles the consumer overrode.
807
+ */
808
+ const themeOverrideVars = (theme) => {
809
+ if (!theme) return {
810
+ vars: {},
811
+ roles: []
812
+ };
813
+ const vars = {};
814
+ const roles = [];
815
+ for (const [role, read] of ROLE_FOR_FIELD) {
816
+ const value = read(theme);
817
+ if (typeof value !== "string" || value === "") continue;
818
+ roles.push(role);
819
+ if (!readsOwnRole(value, role)) vars[themeLayerVar(role)] = value;
820
+ }
821
+ return {
822
+ vars,
823
+ roles
824
+ };
825
+ };
826
+ //#endregion
750
827
  //#region src/providers/chart-context/themes.ts
751
828
  /**
752
829
  * Default theme configuration
753
830
  */
754
831
  const defaultTheme = {
755
- backgroundColor: "var(--a8c-charts-color-background, var(--wpds-color-background-surface-neutral-strong, #fff))",
832
+ backgroundColor: "var(--a8c-charts-color-background, #fff)",
756
833
  labelBackgroundColor: "transparent",
757
834
  labelTextColor: "var(--a8c-charts-color-label-on-fill, #FFFFFF)",
758
835
  colors: [
@@ -763,59 +840,59 @@ const defaultTheme = {
763
840
  "#FF8C8F"
764
841
  ],
765
842
  gridStyles: {
766
- stroke: "var(--a8c-charts-color-grid, var(--wpds-color-stroke-surface-neutral, #dbdbdb))",
843
+ stroke: "var(--a8c-charts-color-grid, #dbdbdb)",
767
844
  strokeWidth: 1
768
845
  },
769
846
  tickLength: 4,
770
847
  gridColor: "",
771
848
  gridColorDark: "",
772
849
  xTickLineStyles: {
773
- stroke: "var(--a8c-charts-color-tick, var(--wpds-color-stroke-surface-neutral, #dbdbdb))",
850
+ stroke: "var(--a8c-charts-color-tick, #dbdbdb)",
774
851
  strokeWidth: 1
775
852
  },
776
853
  xAxisLineStyles: {
777
- stroke: "var(--a8c-charts-color-axis, var(--wpds-color-stroke-surface-neutral, #dbdbdb))",
854
+ stroke: "var(--a8c-charts-color-axis, #dbdbdb)",
778
855
  strokeWidth: 1
779
856
  },
780
857
  legend: {
781
- labelStyles: { color: "var(--a8c-charts-color-label, var(--wpds-color-foreground-content-neutral, #1e1e1e))" },
858
+ labelStyles: { color: "var(--a8c-charts-color-label, #1e1e1e)" },
782
859
  containerStyles: {},
783
860
  shapeStyles: []
784
861
  },
785
862
  seriesLineStyles: [],
786
863
  glyphs: [],
787
864
  svgLabelSmall: {
788
- fill: "var(--a8c-charts-color-label, var(--wpds-color-foreground-content-neutral, #1e1e1e))",
865
+ fill: "var(--a8c-charts-color-label-axis, #1e1e1e)",
789
866
  fontFamily: "inherit"
790
867
  },
791
868
  svgLabelBig: { fontFamily: "inherit" },
792
869
  annotationStyles: {
793
870
  label: {
794
- anchorLineStroke: "var(--a8c-charts-color-annotation, var(--wpds-color-foreground-content-neutral, #1e1e1e))",
795
- backgroundFill: "var(--a8c-charts-color-background, var(--wpds-color-background-surface-neutral-strong, #fff))"
871
+ anchorLineStroke: "var(--a8c-charts-color-annotation, #1e1e1e)",
872
+ backgroundFill: "var(--a8c-charts-color-surface, #fff)"
796
873
  },
797
- connector: { stroke: "var(--a8c-charts-color-annotation, var(--wpds-color-foreground-content-neutral, #1e1e1e))" },
874
+ connector: { stroke: "var(--a8c-charts-color-annotation, #1e1e1e)" },
798
875
  circleSubject: {
799
876
  stroke: "transparent",
800
- fill: "var(--a8c-charts-color-annotation, var(--wpds-color-foreground-content-neutral, #1e1e1e))",
877
+ fill: "var(--a8c-charts-color-annotation, #1e1e1e)",
801
878
  radius: 5
802
879
  }
803
880
  },
804
- geoChart: { featureFillColor: "var(--a8c-charts-color-surface-secondary, var(--wpds-color-background-surface-neutral-weak, #f4f4f4))" },
881
+ geoChart: { featureFillColor: "var(--a8c-charts-color-surface-secondary, #f4f4f4)" },
805
882
  leaderboardChart: {
806
883
  rowGap: 12,
807
884
  columnGap: 4,
808
885
  labelSpacing: "xs",
809
886
  deltaColors: [
810
- "var(--a8c-charts-color-trend-down, var(--wpds-color-foreground-content-error-weak, #cc1818))",
811
- "var(--a8c-charts-color-trend-neutral, var(--wpds-color-foreground-content-neutral-weak, #707070))",
812
- "var(--a8c-charts-color-trend-up, var(--wpds-color-foreground-content-success-weak, #008030))"
887
+ "var(--a8c-charts-color-trend-down, #cc1818)",
888
+ "var(--a8c-charts-color-trend-neutral, #707070)",
889
+ "var(--a8c-charts-color-trend-up, #008030)"
813
890
  ]
814
891
  },
815
892
  conversionFunnelChart: {
816
- backgroundColor: "var(--a8c-charts-color-surface-secondary, var(--wpds-color-background-surface-neutral-weak, #f4f4f4))",
817
- positiveChangeColor: "var(--a8c-charts-color-trend-up, var(--wpds-color-foreground-content-success-weak, #008030))",
818
- negativeChangeColor: "var(--a8c-charts-color-trend-down, var(--wpds-color-foreground-content-error-weak, #cc1818))"
893
+ backgroundColor: "var(--a8c-charts-color-surface-secondary, #f4f4f4)",
894
+ positiveChangeColor: "var(--a8c-charts-color-trend-up, #008030)",
895
+ negativeChangeColor: "var(--a8c-charts-color-trend-down, #cc1818)"
819
896
  },
820
897
  lineChart: { lineStyles: { comparison: {
821
898
  strokeDasharray: "4 4",
@@ -840,15 +917,66 @@ const defaultTheme = {
840
917
  }
841
918
  };
842
919
  //#endregion
920
+ //#region src/providers/chart-context/private/with-catalog-pointers.ts
921
+ const CATALOG_RESTORE_FOR_ROLE = {
922
+ "--a8c-charts-color-background": () => ({ backgroundColor: defaultTheme.backgroundColor }),
923
+ "--a8c-charts-color-grid": (theme) => ({ gridStyles: {
924
+ ...theme.gridStyles,
925
+ stroke: defaultTheme.gridStyles.stroke
926
+ } }),
927
+ "--a8c-charts-color-axis": (theme) => ({ xAxisLineStyles: {
928
+ ...theme.xAxisLineStyles,
929
+ stroke: defaultTheme.xAxisLineStyles.stroke
930
+ } }),
931
+ "--a8c-charts-color-tick": (theme) => ({ xTickLineStyles: {
932
+ ...theme.xTickLineStyles,
933
+ stroke: defaultTheme.xTickLineStyles.stroke
934
+ } }),
935
+ "--a8c-charts-color-label-axis": (theme) => ({ svgLabelSmall: {
936
+ ...theme.svgLabelSmall,
937
+ fill: defaultTheme.svgLabelSmall.fill
938
+ } })
939
+ };
940
+ /**
941
+ * Restores the mapped theme fields of `overriddenRoles` to their catalog pointer, so the theme-layer variable `themeOverrideVars` writes on the provider wrapper is the only carrier for an overridden role — CSS and the JS bridge (`useXYChartTheme`) then resolve it through the same cascade instead of visx reading a baked literal that can disagree with a closer CSS override.
942
+ *
943
+ * This covers roles `themeOverrideVars` deliberately left unpublished as well as the ones it published. A value that reads its own role is not publishable, but leaving visx the consumer's literal is what the whole mechanism exists to prevent: `theme={ { gridStyles: { stroke: 'var(--brand, var(--a8c-charts-color-grid, red))' } } }` would have CSS paint the catalog default while visx painted `--brand`.
944
+ *
945
+ * Every field outside the five mapped roles is left exactly as `merged` provided it: those aren't published as theme-layer vars, so rewriting them would erase a consumer's override with no replacement carrier.
946
+ *
947
+ * @param merged - The consumer theme merged onto `defaultTheme` (`mergeThemes` output).
948
+ * @param overriddenRoles - The catalog roles the consumer overrode, from `themeOverrideVars`.
949
+ * @return A new theme object; `merged` is not mutated.
950
+ */
951
+ const withCatalogPointers = (merged, overriddenRoles) => {
952
+ let result = merged;
953
+ for (const role of overriddenRoles) {
954
+ const restore = CATALOG_RESTORE_FOR_ROLE[role];
955
+ if (restore) result = {
956
+ ...result,
957
+ ...restore(result)
958
+ };
959
+ }
960
+ return result;
961
+ };
962
+ //#endregion
843
963
  //#region src/providers/chart-context/global-charts-provider.tsx
844
964
  const GlobalChartsContext = createContext(null);
845
965
  const GlobalChartsProvider = ({ children, theme }) => {
846
966
  const [charts, setCharts] = useState(() => /* @__PURE__ */ new Map());
847
967
  const [hiddenSeries, setHiddenSeries] = useState(() => /* @__PURE__ */ new Map());
968
+ const seededCharts = useRef(/* @__PURE__ */ new Set());
848
969
  const wrapperRef = useRef(null);
970
+ const [scopeNode, setScopeNode] = useState(null);
971
+ const setWrapperNode = useCallback((node) => {
972
+ wrapperRef.current = node;
973
+ setScopeNode(node);
974
+ }, []);
975
+ const { vars: overrideVars, roles: overriddenRoles } = useMemo(() => themeOverrideVars(theme), [theme]);
849
976
  const providerTheme = useMemo(() => {
850
- return theme ? mergeThemes(defaultTheme, theme) : defaultTheme;
851
- }, [theme]);
977
+ if (!theme) return defaultTheme;
978
+ return withCatalogPointers(mergeThemes(defaultTheme, theme), overriddenRoles);
979
+ }, [theme, overriddenRoles]);
852
980
  const [colorCache, setColorCache] = useState(() => ({
853
981
  colors: [],
854
982
  hues: [],
@@ -925,7 +1053,6 @@ const GlobalChartsProvider = ({ children, theme }) => {
925
1053
  }
926
1054
  return getChartColor(index, colorCache);
927
1055
  }, [colorCache, groupToColorMap]);
928
- const resolveThemeColor = useCallback((value) => value ? normalizeColorToHex(value, wrapperRef.current, resolveCssVariable) : "", []);
929
1056
  const getElementStyles = useCallback(({ data, index, overrideColor, legendShape }) => {
930
1057
  const isSeriesData = data && typeof data === "object" && "data" in data && "options" in data;
931
1058
  const isPointPercentageData = data && typeof data === "object" && "value" in data && typeof data.value === "number" && !("data" in data);
@@ -941,18 +1068,41 @@ const GlobalChartsProvider = ({ children, theme }) => {
941
1068
  shapeStyles: isSeriesData ? getItemShapeStyles(data, index, providerTheme, legendShape) : {}
942
1069
  };
943
1070
  }, [providerTheme, resolveColor]);
944
- const toggleSeriesVisibility = useCallback((chartId, seriesLabel) => {
1071
+ const updateHiddenSeries = useCallback((chartId, update) => {
945
1072
  setHiddenSeries((prev) => {
1073
+ const current = prev.get(chartId);
1074
+ const next = update(new Set(current ?? []));
1075
+ if (!current && next.size === 0) return prev;
1076
+ if (current && current.size === next.size && [...next].every((label) => current.has(label))) return prev;
946
1077
  const newMap = new Map(prev);
947
- const chartHidden = newMap.get(chartId) || /* @__PURE__ */ new Set();
948
- const newSet = new Set(chartHidden);
949
- if (newSet.has(seriesLabel)) newSet.delete(seriesLabel);
950
- else newSet.add(seriesLabel);
951
- if (newSet.size === 0) newMap.delete(chartId);
952
- else newMap.set(chartId, newSet);
1078
+ if (next.size === 0) newMap.delete(chartId);
1079
+ else newMap.set(chartId, next);
953
1080
  return newMap;
954
1081
  });
955
1082
  }, []);
1083
+ const toggleSeriesVisibility = useCallback((chartId, seriesLabel) => {
1084
+ updateHiddenSeries(chartId, (current) => {
1085
+ if (current.has(seriesLabel)) current.delete(seriesLabel);
1086
+ else current.add(seriesLabel);
1087
+ return current;
1088
+ });
1089
+ }, [updateHiddenSeries]);
1090
+ const setSeriesVisibility = useCallback((chartId, seriesLabel, visible) => {
1091
+ updateHiddenSeries(chartId, (current) => {
1092
+ if (visible) current.delete(seriesLabel);
1093
+ else current.add(seriesLabel);
1094
+ return current;
1095
+ });
1096
+ }, [updateHiddenSeries]);
1097
+ const setChartHiddenSeries = useCallback((chartId, seriesLabels) => {
1098
+ updateHiddenSeries(chartId, () => new Set(seriesLabels));
1099
+ }, [updateHiddenSeries]);
1100
+ const hasSeededChart = useCallback((chartId) => seededCharts.current.has(chartId), []);
1101
+ const seedChartHiddenSeries = useCallback((chartId, seriesLabels) => {
1102
+ if (seededCharts.current.has(chartId)) return;
1103
+ seededCharts.current.add(chartId);
1104
+ setChartHiddenSeries(chartId, seriesLabels);
1105
+ }, [setChartHiddenSeries]);
956
1106
  const isSeriesVisible = useCallback((chartId, seriesLabel) => {
957
1107
  const chartHidden = hiddenSeries.get(chartId);
958
1108
  return !chartHidden || !chartHidden.has(seriesLabel);
@@ -968,8 +1118,11 @@ const GlobalChartsProvider = ({ children, theme }) => {
968
1118
  getChartData,
969
1119
  theme: providerTheme,
970
1120
  getElementStyles,
971
- resolveThemeColor,
972
1121
  toggleSeriesVisibility,
1122
+ setSeriesVisibility,
1123
+ setChartHiddenSeries,
1124
+ seedChartHiddenSeries,
1125
+ hasSeededChart,
973
1126
  isSeriesVisible,
974
1127
  getHiddenSeries,
975
1128
  isColorPaletteResolved
@@ -980,8 +1133,11 @@ const GlobalChartsProvider = ({ children, theme }) => {
980
1133
  getChartData,
981
1134
  providerTheme,
982
1135
  getElementStyles,
983
- resolveThemeColor,
984
1136
  toggleSeriesVisibility,
1137
+ setSeriesVisibility,
1138
+ setChartHiddenSeries,
1139
+ seedChartHiddenSeries,
1140
+ hasSeededChart,
985
1141
  isSeriesVisible,
986
1142
  getHiddenSeries,
987
1143
  isColorPaletteResolved
@@ -989,9 +1145,16 @@ const GlobalChartsProvider = ({ children, theme }) => {
989
1145
  return /* @__PURE__ */ jsx(GlobalChartsContext.Provider, {
990
1146
  value,
991
1147
  children: /* @__PURE__ */ jsx("div", {
992
- ref: wrapperRef,
993
- style: { display: "contents" },
994
- children
1148
+ ref: setWrapperNode,
1149
+ className: CHART_SCOPE_CLASS,
1150
+ style: {
1151
+ display: "contents",
1152
+ ...overrideVars
1153
+ },
1154
+ children: /* @__PURE__ */ jsx(ChartScopeContext.Provider, {
1155
+ value: scopeNode,
1156
+ children
1157
+ })
995
1158
  })
996
1159
  });
997
1160
  };
@@ -1051,12 +1214,31 @@ const useDeepMemo = (value) => {
1051
1214
  return ref.current;
1052
1215
  };
1053
1216
  //#endregion
1217
+ //#region src/providers/chart-scope/use-chart-scope-element.ts
1218
+ /**
1219
+ * Returns the nearest chart scope element, or `null` when rendered outside any scope (and during SSR, before the ref is attached).
1220
+ *
1221
+ * @return {HTMLElement | null} The nearest chart scope element, or `null`.
1222
+ */
1223
+ const useChartScopeElement = () => useContext(ChartScopeContext);
1224
+ //#endregion
1225
+ //#region src/providers/chart-scope/use-standalone-scope-class.ts
1226
+ /**
1227
+ * Returns the catalog class when there is no `GlobalChartsProvider` above this component, and `undefined` when there is.
1228
+ *
1229
+ * Standalone components need the catalog to resolve at all, but inside a provider the tokens already inherit — re-declaring them there would shadow a consumer override set anywhere in the tree.
1230
+ *
1231
+ * @return The scope class name, or undefined when a provider is present.
1232
+ */
1233
+ const useStandaloneScopeClass = () => useContext(GlobalChartsContext) ? void 0 : CHART_SCOPE_CLASS;
1234
+ //#endregion
1054
1235
  //#region src/hooks/use-xychart-theme.ts
1055
1236
  const useXYChartTheme = (data) => {
1056
1237
  const theme = useGlobalChartsTheme();
1238
+ const scopeElement = useChartScopeElement();
1057
1239
  const seriesColorKey = JSON.stringify((data ?? []).map((series) => series.options?.stroke).filter((color) => Boolean(color)));
1058
1240
  return useMemo(() => {
1059
- const resolve = createCssVariableResolver();
1241
+ const resolve = createCssVariableResolver(scopeElement);
1060
1242
  const resolveColor = (value) => value ? resolve(value) ?? value : value;
1061
1243
  const seriesColors = JSON.parse(seriesColorKey);
1062
1244
  return buildChartTheme({
@@ -1080,7 +1262,11 @@ const useXYChartTheme = (data) => {
1080
1262
  fill: resolveColor(theme.svgLabelSmall.fill)
1081
1263
  }
1082
1264
  });
1083
- }, [theme, seriesColorKey]);
1265
+ }, [
1266
+ theme,
1267
+ seriesColorKey,
1268
+ scopeElement
1269
+ ]);
1084
1270
  };
1085
1271
  //#endregion
1086
1272
  //#region src/hooks/use-chart-data-transform.ts
@@ -1350,12 +1536,12 @@ const useDataWithPercentages = (data) => {
1350
1536
  }, [data]);
1351
1537
  };
1352
1538
  //#endregion
1353
- //#region src/hooks/use-interactive-legend-data.ts
1539
+ //#region src/hooks/use-legend-visibility-data.ts
1354
1540
  /**
1355
- * Custom hook to filter and recalculate chart data for interactive legends.
1541
+ * Custom hook to filter and recalculate chart data based on series visibility.
1356
1542
  *
1357
- * When interactive legends are enabled, this hook:
1358
- * 1. Filters data to show only visible series based on legend selection
1543
+ * Regardless of whether the legend is interactive (clickable), this hook:
1544
+ * 1. Filters data to show only visible series (visibility can also be set programmatically)
1359
1545
  * 2. Recalculates percentages so visible segments total 100%
1360
1546
  * 3. Tracks whether all segments are hidden to show empty state
1361
1547
  *
@@ -1364,10 +1550,9 @@ const useDataWithPercentages = (data) => {
1364
1550
  *
1365
1551
  * @example
1366
1552
  * ```tsx
1367
- * const { visibleData, allSegmentsHidden, legendData } = useInteractiveLegendData({
1553
+ * const { visibleData, allSegmentsHidden, legendData } = useLegendVisibilityData({
1368
1554
  * data: chartData,
1369
1555
  * chartId: 'my-pie-chart',
1370
- * legendInteractive: true,
1371
1556
  * isSeriesVisible: (id, label) => context.isSeriesVisible(id, label),
1372
1557
  * });
1373
1558
  *
@@ -1382,16 +1567,15 @@ const useDataWithPercentages = (data) => {
1382
1567
  * return <PieChart data={visibleData} />;
1383
1568
  * ```
1384
1569
  *
1385
- * @param params - Configuration object for the hook
1386
- * @param params.data - The chart data to filter
1387
- * @param params.chartId - Unique identifier for the chart (required for interactive mode)
1388
- * @param params.legendInteractive - Whether to enable interactive filtering
1389
- * @param params.isSeriesVisible - Function to check series visibility
1570
+ * @param params - Configuration object for the hook
1571
+ * @param params.data - The chart data to filter
1572
+ * @param params.chartId - Unique identifier for the chart (required for filtering)
1573
+ * @param params.isSeriesVisible - Function to check series visibility
1390
1574
  * @return Object containing visibleData, allSegmentsHidden flag, and legendData with recalculated percentages
1391
1575
  */
1392
- const useInteractiveLegendData = ({ data, chartId, legendInteractive, isSeriesVisible }) => {
1576
+ const useLegendVisibilityData = ({ data, chartId, isSeriesVisible }) => {
1393
1577
  const visibleData = useMemo(() => {
1394
- if (!chartId || !legendInteractive) return data;
1578
+ if (!chartId) return data;
1395
1579
  const filtered = data.filter((segment) => isSeriesVisible(chartId, segment.label));
1396
1580
  if (filtered.length === 0) return [];
1397
1581
  const totalValue = filtered.reduce((sum, segment) => sum + segment.value, 0);
@@ -1402,16 +1586,15 @@ const useInteractiveLegendData = ({ data, chartId, legendInteractive, isSeriesVi
1402
1586
  }, [
1403
1587
  data,
1404
1588
  chartId,
1405
- isSeriesVisible,
1406
- legendInteractive
1589
+ isSeriesVisible
1407
1590
  ]);
1408
1591
  return {
1409
1592
  visibleData,
1410
1593
  allSegmentsHidden: useMemo(() => {
1411
- return legendInteractive && visibleData.length === 0;
1412
- }, [legendInteractive, visibleData]),
1594
+ return visibleData.length === 0 && data.length > 0;
1595
+ }, [visibleData, data]),
1413
1596
  legendData: useMemo(() => {
1414
- if (!legendInteractive || !chartId) return data;
1597
+ if (!chartId) return data;
1415
1598
  const visibleDataMap = new Map(visibleData.map((d) => [d.label, d]));
1416
1599
  return data.map((segment) => {
1417
1600
  if (!isSeriesVisible(chartId, segment.label)) return segment;
@@ -1420,7 +1603,6 @@ const useInteractiveLegendData = ({ data, chartId, legendInteractive, isSeriesVi
1420
1603
  }, [
1421
1604
  data,
1422
1605
  visibleData,
1423
- legendInteractive,
1424
1606
  chartId,
1425
1607
  isSeriesVisible
1426
1608
  ])
@@ -1550,12 +1732,23 @@ const LegendText = ({ text, textOverflow, maxWidth }) => {
1550
1732
  children: text
1551
1733
  });
1552
1734
  };
1735
+ const getLegendItemAriaLabel = (text, value, visible, interactive) => {
1736
+ const accessibleText = value != null && value !== "" ? sprintf(_x("%1$s, %2$s", "legend item label and value", "jetpack-charts"), text, String(value)) : text;
1737
+ if (interactive) {
1738
+ if (visible) return sprintf(_x("%s: visible. Toggle visibility.", "visible interactive legend item", "jetpack-charts"), accessibleText);
1739
+ return sprintf(_x("%s: hidden. Toggle visibility.", "hidden interactive legend item", "jetpack-charts"), accessibleText);
1740
+ }
1741
+ if (visible) return;
1742
+ return sprintf(_x("%s: hidden", "hidden non-interactive legend item", "jetpack-charts"), accessibleText);
1743
+ };
1553
1744
  const BaseLegend = forwardRef(({ items, className, orientation = "horizontal", alignment = "center", shape = "rect", fill = valueOrIdentityString, size = valueOrIdentityString, labelFormat = valueOrIdentity, labelTransform = labelTransformFactory, itemStyles, itemClassName, labelStyles, labelClassName, shapeStyles, render, interactive = false, chartId }, ref) => {
1554
1745
  const { margin: itemMargin = "0", flexDirection: itemDirection = "row" } = itemStyles ?? {};
1555
1746
  const { justifyContent: labelJustifyContent = "flex-start", flex: labelFlex = "0 0 auto", margin: labelMargin = "0 4px", maxWidth, textOverflow = "wrap" } = labelStyles ?? {};
1556
1747
  const { width: shapeWidth = 16, height: shapeHeight = 16, margin: shapeMargin = "2px 4px 2px 0" } = shapeStyles ?? {};
1557
1748
  const theme = useGlobalChartsTheme();
1558
1749
  const context = useContext(GlobalChartsContext);
1750
+ const chartInstanceContext = useContext(ChartInstanceContext);
1751
+ const standaloneScopeClass = useStandaloneScopeClass();
1559
1752
  const legendScale = scaleOrdinal({
1560
1753
  domain: items.map((item) => item.label),
1561
1754
  range: items.map((item) => item.color)
@@ -1565,9 +1758,7 @@ const BaseLegend = forwardRef(({ items, className, orientation = "horizontal", a
1565
1758
  const handleLegendClick = useCallback((seriesLabels) => {
1566
1759
  if (interactive && chartId && context) {
1567
1760
  const representativeVisible = context.isSeriesVisible(chartId, seriesLabels[0]);
1568
- seriesLabels.forEach((label) => {
1569
- if (context.isSeriesVisible(chartId, label) === representativeVisible) context.toggleSeriesVisibility(chartId, label);
1570
- });
1761
+ seriesLabels.forEach((label) => context.setSeriesVisibility(chartId, label, !representativeVisible));
1571
1762
  }
1572
1763
  }, [
1573
1764
  interactive,
@@ -1575,11 +1766,12 @@ const BaseLegend = forwardRef(({ items, className, orientation = "horizontal", a
1575
1766
  context
1576
1767
  ]);
1577
1768
  const isSeriesVisible = useCallback((seriesLabel) => {
1578
- if (!interactive || !chartId || !context) return true;
1769
+ if (chartInstanceContext?.isSeriesVisible) return chartInstanceContext.isSeriesVisible(seriesLabel);
1770
+ if (!chartId || !context) return true;
1579
1771
  return context.isSeriesVisible(chartId, seriesLabel);
1580
1772
  }, [
1581
- interactive,
1582
1773
  chartId,
1774
+ chartInstanceContext,
1583
1775
  context
1584
1776
  ]);
1585
1777
  const createClickHandler = useCallback((seriesLabels) => {
@@ -1607,8 +1799,8 @@ const BaseLegend = forwardRef(({ items, className, orientation = "horizontal", a
1607
1799
  align: orientation === "vertical" ? flexAlignment : void 0,
1608
1800
  justify: orientation === "horizontal" ? flexAlignment : void 0,
1609
1801
  wrap: orientation === "horizontal" ? "wrap" : void 0,
1610
- role: "list",
1611
- className: clsx(base_legend_module_default.legend, className),
1802
+ role: interactive ? void 0 : "list",
1803
+ className: clsx(standaloneScopeClass, base_legend_module_default.legend, className),
1612
1804
  style: theme.legend?.containerStyles,
1613
1805
  children: labels.map((label, i) => {
1614
1806
  const matchedItem = items[i];
@@ -1622,10 +1814,10 @@ const BaseLegend = forwardRef(({ items, className, orientation = "horizontal", a
1622
1814
  flexDirection: orientation === "vertical" && alignment === "end" ? "row-reverse" : itemDirection,
1623
1815
  onClick: handleClick,
1624
1816
  onKeyDown: handleKeyDown,
1625
- role: interactive ? "button" : void 0,
1817
+ role: interactive ? "button" : "listitem",
1626
1818
  tabIndex: interactive ? 0 : void 0,
1627
1819
  "aria-pressed": interactive ? visible : void 0,
1628
- "aria-label": interactive ? `${label.text}: ${visible ? "visible" : "hidden"}. Toggle visibility.` : void 0,
1820
+ "aria-label": getLegendItemAriaLabel(label.text, matchedItem?.value, visible, interactive),
1629
1821
  children: [items[i]?.renderGlyph ? /* @__PURE__ */ jsx("svg", {
1630
1822
  width: items[i]?.glyphSize * 2,
1631
1823
  height: items[i]?.glyphSize * 2,
@@ -1687,8 +1879,8 @@ const defaultShapeByChartType = {
1687
1879
  };
1688
1880
  const Legend = forwardRef(({ chartId, items, shape, ...props }, ref) => {
1689
1881
  const context = useContext(GlobalChartsContext);
1690
- const singleChartContext = useContext(SingleChartContext);
1691
- const contextChartId = chartId ?? singleChartContext?.chartId;
1882
+ const chartInstanceContext = useContext(ChartInstanceContext);
1883
+ const contextChartId = chartId ?? chartInstanceContext?.chartId;
1692
1884
  const chartData = useMemo(() => contextChartId && context ? context.getChartData(contextChartId) : void 0, [contextChartId, context]);
1693
1885
  const contextItems = chartData?.legendItems;
1694
1886
  const resolvedShape = shape ?? (chartData?.chartType ? defaultShapeByChartType[chartData.chartType] : void 0);
@@ -1895,9 +2087,10 @@ const BaseTooltip = ({ data, top, left, component: Component = DefaultTooltipCon
1895
2087
  data,
1896
2088
  className
1897
2089
  });
2090
+ const standaloneScopeClass = useStandaloneScopeClass();
1898
2091
  if (!renderContainer) return content;
1899
2092
  return /* @__PURE__ */ jsx("div", {
1900
- className: base_tooltip_module_default.tooltip,
2093
+ className: clsx(standaloneScopeClass, base_tooltip_module_default.tooltip),
1901
2094
  style: {
1902
2095
  top,
1903
2096
  left,
@@ -1927,11 +2120,16 @@ const AccessibleTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardF
1927
2120
  }
1928
2121
  return flattened;
1929
2122
  }, [series, mode]);
2123
+ const hasKeyboardSelection = useRef(false);
1930
2124
  useEffect(() => {
1931
2125
  if (selectedIndex === void 0) {
1932
- tooltipContext?.hideTooltip();
2126
+ if (hasKeyboardSelection.current) {
2127
+ hasKeyboardSelection.current = false;
2128
+ tooltipContext?.hideTooltip();
2129
+ }
1933
2130
  return;
1934
2131
  }
2132
+ hasKeyboardSelection.current = true;
1935
2133
  if (mode === "group") series.forEach((s, index) => {
1936
2134
  if (selectedIndex < s.data.length) {
1937
2135
  const datum = s.data[selectedIndex];
@@ -1966,10 +2164,11 @@ const AccessibleTooltip = ({ renderTooltip, selectedIndex, tooltipRef, keyboardF
1966
2164
  tabIndex: -1,
1967
2165
  role: "tooltip",
1968
2166
  "aria-atomic": "true",
1969
- className: keyboardFocusedClassName,
2167
+ className: clsx(CHART_SCOPE_CLASS, keyboardFocusedClassName),
1970
2168
  children: tooltipContent
1971
2169
  }, `chart-tooltip-${selectedIndex}`);
1972
2170
  return /* @__PURE__ */ jsx("div", {
2171
+ className: CHART_SCOPE_CLASS,
1973
2172
  role: "tooltip",
1974
2173
  "aria-live": "polite",
1975
2174
  children: tooltipContent
@@ -2038,6 +2237,43 @@ const useKeyboardNavigation = ({ selectedIndex, setSelectedIndex, isNavigating,
2038
2237
  };
2039
2238
  };
2040
2239
  //#endregion
2240
+ //#region src/providers/chart-context/hooks/use-default-hidden-series.ts
2241
+ const useIsomorphicLayoutEffect$1 = typeof window !== "undefined" ? useLayoutEffect : useEffect;
2242
+ /**
2243
+ * Seeds a chart's hidden series once per chart ID, the first time the provider
2244
+ * sees that ID.
2245
+ *
2246
+ * The provider owns the record of what has been seeded, not this hook: a
2247
+ * mount-scoped one would re-apply the defaults on every remount, and a chart
2248
+ * remounts for reasons the reader never thinks of as a new chart — switching
2249
+ * between line and bar, tabbing away and back, a resize flipping tabs into a
2250
+ * dropdown. Each of those would throw away the series they had just revealed.
2251
+ *
2252
+ * @param chartId - The chart ID passed to the provider's visibility methods.
2253
+ * @param seriesLabels - Labels to hide when this chart ID is first seen. Later values are ignored.
2254
+ * @return The resolved hidden-series set.
2255
+ */
2256
+ const useDefaultHiddenSeries = (chartId, seriesLabels) => {
2257
+ const { getHiddenSeries, seedChartHiddenSeries, hasSeededChart } = useGlobalChartsContext();
2258
+ const labelsRef = useRef(seriesLabels);
2259
+ labelsRef.current = seriesLabels;
2260
+ const hasSeriesLabels = seriesLabels !== void 0;
2261
+ const shouldUseDefaults = hasSeriesLabels && !hasSeededChart(chartId);
2262
+ useIsomorphicLayoutEffect$1(() => {
2263
+ if (labelsRef.current === void 0) return;
2264
+ seedChartHiddenSeries(chartId, labelsRef.current);
2265
+ }, [
2266
+ chartId,
2267
+ hasSeriesLabels,
2268
+ seedChartHiddenSeries
2269
+ ]);
2270
+ return useMemo(() => shouldUseDefaults ? new Set(labelsRef.current) : getHiddenSeries(chartId), [
2271
+ shouldUseDefaults,
2272
+ getHiddenSeries,
2273
+ chartId
2274
+ ]);
2275
+ };
2276
+ //#endregion
2041
2277
  //#region src/charts/private/chart-composition/chart-svg.tsx
2042
2278
  /**
2043
2279
  * Compound component for SVG children in charts.
@@ -2251,6 +2487,27 @@ const SvgEmptyState = ({ x, y, width, height, children }) => {
2251
2487
  });
2252
2488
  };
2253
2489
  //#endregion
2490
+ //#region src/charts/private/svg-empty-state/get-all-hidden-message.ts
2491
+ /**
2492
+ * Return the empty-state message for a chart whose items are all hidden.
2493
+ *
2494
+ * Each translation call has a distinct gettext context. This prevents Terser
2495
+ * from folding conditional calls into one call with a conditional msgid, which
2496
+ * would make the strings unavailable to static translation extraction.
2497
+ *
2498
+ * @param interactive - Whether the legend can be used to show hidden items.
2499
+ * @param itemType - The chart-specific name for its data items.
2500
+ * @return The translated empty-state message.
2501
+ */
2502
+ const getAllHiddenMessage = (interactive, itemType) => {
2503
+ if (itemType === "segments") {
2504
+ if (interactive) return _x("All segments are hidden. Click legend items to show data.", "chart empty state: interactive segments", "jetpack-charts");
2505
+ return _x("All segments are hidden.", "chart empty state: segments", "jetpack-charts");
2506
+ }
2507
+ if (interactive) return _x("All series are hidden. Click legend items to show data.", "chart empty state: interactive series", "jetpack-charts");
2508
+ return _x("All series are hidden.", "chart empty state: series", "jetpack-charts");
2509
+ };
2510
+ //#endregion
2254
2511
  //#region src/charts/private/time-axis.ts
2255
2512
  const X_TICK_WIDTH = 60;
2256
2513
  const getCurveType = (type, smoothing) => {
@@ -2422,9 +2679,11 @@ function withResponsive(WrappedComponent) {
2422
2679
  enableDebounceLeadingCall: true
2423
2680
  });
2424
2681
  const hasAspectRatio = aspectRatio !== void 0 && aspectRatio > 0;
2682
+ const [scopeNode, setScopeNode] = useState(null);
2425
2683
  const wrapperRef = useRef(null);
2426
2684
  const setWrapperRef = useCallback((node) => {
2427
2685
  wrapperRef.current = node;
2686
+ setScopeNode(node);
2428
2687
  if (typeof parentRef === "function") parentRef(node);
2429
2688
  else if (parentRef) parentRef.current = node;
2430
2689
  }, [parentRef]);
@@ -2470,14 +2729,17 @@ function withResponsive(WrappedComponent) {
2470
2729
  ...width !== void 0 ? { width } : null,
2471
2730
  ...height !== void 0 ? { height } : null
2472
2731
  },
2473
- children: hasAspectRatio ? /* @__PURE__ */ jsx("div", {
2474
- className: with_responsive_module_default.content,
2475
- style: {
2476
- width: boxWidth,
2477
- height: boxHeight
2478
- },
2479
- children: wrappedComponent
2480
- }) : wrappedComponent
2732
+ children: /* @__PURE__ */ jsx(ChartScopeContext.Provider, {
2733
+ value: scopeNode,
2734
+ children: hasAspectRatio ? /* @__PURE__ */ jsx("div", {
2735
+ className: with_responsive_module_default.content,
2736
+ style: {
2737
+ width: boxWidth,
2738
+ height: boxHeight
2739
+ },
2740
+ children: wrappedComponent
2741
+ }) : wrappedComponent
2742
+ })
2481
2743
  });
2482
2744
  };
2483
2745
  }
@@ -2773,7 +3035,7 @@ const LineChartAnnotationLabelWithPopover = ({ title, subtitle, renderLabel, ren
2773
3035
  //#endregion
2774
3036
  //#region src/charts/line-chart/private/line-chart-annotations-overlay.tsx
2775
3037
  const LineChartAnnotationsOverlay = ({ children }) => {
2776
- const { chartRef, chartWidth, chartHeight } = useSingleChartContext();
3038
+ const { chartRef, chartWidth, chartHeight } = useChartInstanceContext();
2777
3039
  const [scales, setScales] = useState(null);
2778
3040
  const [scalesStable, setScalesStable] = useState(false);
2779
3041
  const createScaleSignature = useCallback((scaleData) => {
@@ -2912,11 +3174,12 @@ const getVerticalAnchor = (subjectType, isFlippedVertically, y, yMax, height) =>
2912
3174
  };
2913
3175
  const LineChartAnnotation = ({ datum, title, subtitle, subjectType = "circle", styles: datumStyles, testId, renderLabel, renderLabelPopover }) => {
2914
3176
  const providerTheme = useGlobalChartsTheme();
3177
+ const scopeElement = useChartScopeElement();
2915
3178
  const { xScale, yScale } = useContext(DataContext) || {};
2916
3179
  const labelRef = useRef(null);
2917
3180
  const [height, setHeight] = useState(null);
2918
3181
  const styles = deepmerge(providerTheme.annotationStyles ?? {}, datumStyles ?? {});
2919
- const resolveColor = (value) => value ? resolveCssVariable(value) ?? value : value;
3182
+ const resolveColor = (value) => value ? resolveCssVariable(value, scopeElement) ?? value : value;
2920
3183
  useEffect(() => {
2921
3184
  if (labelRef.current?.getBBox) {
2922
3185
  const bbox = labelRef.current.getBBox();
@@ -3157,7 +3420,7 @@ const LineChartScalesRef = ({ chartRef, width, height, margin }) => {
3157
3420
  ]);
3158
3421
  return null;
3159
3422
  };
3160
- const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, height, className, margin, withTooltips = true, withTooltipCrosshairs, showLegend = false, legend = {}, renderGlyph = defaultRenderGlyph, glyphStyle = {}, withLegendGlyph = false, withGradientFill = false, smoothing = true, curveType, renderTooltip = renderDefaultTooltip, withStartGlyphs = false, withEndGlyphs = false, animation, options = {}, onPointerDown = void 0, onPointerUp = void 0, onPointerMove = void 0, onPointerOut = void 0, zoomable = false, rescaleYOnVisibilityChange = true, children, gridVisibility, gap = "md" }, ref) => {
3423
+ const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, height, className, margin, withTooltips = true, withTooltipCrosshairs, showLegend = false, legend = {}, renderGlyph = defaultRenderGlyph, glyphStyle = {}, withLegendGlyph = false, withGradientFill = false, smoothing = true, curveType, renderTooltip = renderDefaultTooltip, withStartGlyphs = false, withEndGlyphs = false, animation, options = {}, onPointerDown = void 0, onPointerUp = void 0, onPointerMove = void 0, onPointerOut = void 0, zoomable = false, rescaleYOnVisibilityChange = true, defaultHiddenSeries, children, gridVisibility, gap = "md" }, ref) => {
3161
3424
  const legendInteractive = legend.interactive ?? false;
3162
3425
  const legendCollapseGroups = legend.collapseGroups ?? false;
3163
3426
  const legendShape = legend.shape ?? "line";
@@ -3166,6 +3429,8 @@ const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
3166
3429
  const theme = useXYChartTheme(data);
3167
3430
  const resolvedBackgroundColor = theme.backgroundColor ?? providerTheme.backgroundColor;
3168
3431
  const chartId = useChartId(providedChartId);
3432
+ const hiddenSeries = useDefaultHiddenSeries(chartId, defaultHiddenSeries);
3433
+ const isSeriesVisible = useCallback((seriesLabel) => !hiddenSeries.has(seriesLabel), [hiddenSeries]);
3169
3434
  const chartRef = useRef(null);
3170
3435
  const [selectedIndex, setSelectedIndex] = useState(void 0);
3171
3436
  const [isNavigating, setIsNavigating] = useState(false);
@@ -3193,29 +3458,19 @@ const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
3193
3458
  }
3194
3459
  }), [internalChartRef]);
3195
3460
  const dataSorted = useChartDataTransform(data);
3196
- const { getElementStyles, isSeriesVisible } = useGlobalChartsContext();
3461
+ const { getElementStyles } = useGlobalChartsContext();
3197
3462
  const seriesWithVisibility = useMemo(() => {
3198
- if (!chartId || !legendInteractive) return dataSorted.map((series, index) => ({
3199
- series,
3200
- index,
3201
- isVisible: true
3202
- }));
3203
3463
  return dataSorted.map((series, index) => ({
3204
3464
  series,
3205
3465
  index,
3206
- isVisible: isSeriesVisible(chartId, series.label)
3466
+ isVisible: !hiddenSeries.has(series.label)
3207
3467
  }));
3208
- }, [
3209
- dataSorted,
3210
- chartId,
3211
- isSeriesVisible,
3212
- legendInteractive
3213
- ]);
3468
+ }, [dataSorted, hiddenSeries]);
3214
3469
  const allSeriesHidden = useMemo(() => {
3215
3470
  return seriesWithVisibility.every(({ isVisible }) => !isVisible);
3216
3471
  }, [seriesWithVisibility]);
3217
3472
  const stableYDomain = useMemo(() => {
3218
- if (!legendInteractive || rescaleYOnVisibilityChange) return;
3473
+ if (rescaleYOnVisibilityChange) return;
3219
3474
  let min = Infinity;
3220
3475
  let max = -Infinity;
3221
3476
  for (const series of dataSorted) for (const point of series.data ?? []) {
@@ -3226,11 +3481,7 @@ const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
3226
3481
  }
3227
3482
  }
3228
3483
  return min < max ? [min, max] : void 0;
3229
- }, [
3230
- legendInteractive,
3231
- rescaleYOnVisibilityChange,
3232
- dataSorted
3233
- ]);
3484
+ }, [rescaleYOnVisibilityChange, dataSorted]);
3234
3485
  const { tooltipRef, onChartFocus, onChartBlur, onChartKeyDown } = useKeyboardNavigation({
3235
3486
  selectedIndex,
3236
3487
  setSelectedIndex,
@@ -3354,10 +3605,11 @@ const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
3354
3605
  chartId,
3355
3606
  interactive: legendInteractive
3356
3607
  });
3357
- return /* @__PURE__ */ jsx(SingleChartContext.Provider, {
3608
+ return /* @__PURE__ */ jsx(ChartInstanceContext.Provider, {
3358
3609
  value: {
3359
3610
  chartId,
3360
3611
  chartRef: internalChartRef,
3612
+ isSeriesVisible,
3361
3613
  chartWidth: width,
3362
3614
  chartHeight: measuredChartHeight || 0
3363
3615
  },
@@ -3412,7 +3664,7 @@ const LineChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
3412
3664
  y: chartHeight / 2,
3413
3665
  width,
3414
3666
  height: chartHeight,
3415
- children: __("All series are hidden. Click legend items to show data.", "jetpack-charts")
3667
+ children: getAllHiddenMessage(legendInteractive, "series")
3416
3668
  }) : null,
3417
3669
  /* @__PURE__ */ jsx(ZoomClip, {
3418
3670
  active: zoomable && !!zoom.domain,
@@ -3614,7 +3866,7 @@ const HoverGlyphs = ({ visibleSeries, stacked, stackOffset, getElementStyles, st
3614
3866
  };
3615
3867
  //#endregion
3616
3868
  //#region src/charts/area-chart/area-chart.tsx
3617
- const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, height, className, margin, withTooltips = true, withTooltipCrosshairs, showLegend = false, legend = {}, stacked = true, stackOffset = "none", smoothing = true, curveType, fillOpacity, withStroke, renderTooltip = renderDefaultTooltip, animation, options = {}, onPointerDown, onPointerUp, onPointerMove, onPointerOut, zoomable = false, rescaleYOnVisibilityChange, rescaleYOnLegendToggle, children, gridVisibility, gap = "md" }, ref) => {
3869
+ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, height, className, margin, withTooltips = true, withTooltipCrosshairs, showLegend = false, legend = {}, stacked = true, stackOffset = "none", smoothing = true, curveType, fillOpacity, withStroke, renderTooltip = renderDefaultTooltip, animation, options = {}, onPointerDown, onPointerUp, onPointerMove, onPointerOut, zoomable = false, rescaleYOnVisibilityChange, rescaleYOnLegendToggle, defaultHiddenSeries, children, gridVisibility, gap = "md" }, ref) => {
3618
3870
  const legendInteractive = legend.interactive ?? false;
3619
3871
  const legendShape = legend.shape ?? "rect";
3620
3872
  const legendPosition = legend.position ?? "bottom";
@@ -3622,6 +3874,8 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
3622
3874
  const providerTheme = useGlobalChartsTheme();
3623
3875
  const theme = useXYChartTheme(data);
3624
3876
  const chartId = useChartId(providedChartId);
3877
+ const hiddenSeries = useDefaultHiddenSeries(chartId, defaultHiddenSeries);
3878
+ const isSeriesVisible = useCallback((seriesLabel) => !hiddenSeries.has(seriesLabel), [hiddenSeries]);
3625
3879
  const chartRef = useRef(null);
3626
3880
  const [selectedIndex, setSelectedIndex] = useState(void 0);
3627
3881
  const [isNavigating, setIsNavigating] = useState(false);
@@ -3649,24 +3903,14 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
3649
3903
  }
3650
3904
  }), [internalChartRef]);
3651
3905
  const dataSorted = useChartDataTransform(data);
3652
- const { getElementStyles, isSeriesVisible } = useGlobalChartsContext();
3906
+ const { getElementStyles } = useGlobalChartsContext();
3653
3907
  const seriesWithVisibility = useMemo(() => {
3654
- if (!chartId || !legendInteractive) return dataSorted.map((series, index) => ({
3655
- series,
3656
- index,
3657
- isVisible: true
3658
- }));
3659
3908
  return dataSorted.map((series, index) => ({
3660
3909
  series,
3661
3910
  index,
3662
- isVisible: isSeriesVisible(chartId, series.label)
3911
+ isVisible: !hiddenSeries.has(series.label)
3663
3912
  }));
3664
- }, [
3665
- dataSorted,
3666
- chartId,
3667
- isSeriesVisible,
3668
- legendInteractive
3669
- ]);
3913
+ }, [dataSorted, hiddenSeries]);
3670
3914
  const allSeriesHidden = useMemo(() => seriesWithVisibility.every(({ isVisible }) => !isVisible), [seriesWithVisibility]);
3671
3915
  const { tooltipRef, onChartFocus, onChartBlur, onChartKeyDown } = useKeyboardNavigation({
3672
3916
  selectedIndex,
@@ -3677,7 +3921,7 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
3677
3921
  totalPoints: dataSorted[0]?.data.length || 0
3678
3922
  });
3679
3923
  const fixedYDomain = useMemo(() => {
3680
- if (rescaleYOnVisibility || !legendInteractive || !dataSorted.length || !dataSorted[0].data.length || stacked && stackOffset !== "none") return;
3924
+ if (rescaleYOnVisibility || !dataSorted.length || !dataSorted[0].data.length || stacked && stackOffset !== "none") return;
3681
3925
  if (stacked) {
3682
3926
  const numPoints = Math.max(...dataSorted.map((s) => s.data.length));
3683
3927
  let posMax = 0;
@@ -3711,7 +3955,6 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
3711
3955
  dataSorted,
3712
3956
  stacked,
3713
3957
  stackOffset,
3714
- legendInteractive,
3715
3958
  rescaleYOnVisibility
3716
3959
  ]);
3717
3960
  const chartOptions = useMemo(() => {
@@ -3788,7 +4031,6 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
3788
4031
  const zeroYAccessor = useCallback(() => 0, []);
3789
4032
  const visibleLabels = useMemo(() => new Set(seriesWithVisibility.filter((s) => s.isVisible).map((s) => s.series.label)), [seriesWithVisibility]);
3790
4033
  const filteredRenderTooltip = useCallback((params) => {
3791
- if (!legendInteractive) return renderTooltip(params);
3792
4034
  const datumByKey = params?.tooltipData?.datumByKey;
3793
4035
  if (!datumByKey) return renderTooltip(params);
3794
4036
  const filtered = Object.fromEntries(Object.entries(datumByKey).filter(([key]) => visibleLabels.has(key)));
@@ -3806,11 +4048,7 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
3806
4048
  nearestDatum: nextNearest
3807
4049
  }
3808
4050
  });
3809
- }, [
3810
- renderTooltip,
3811
- legendInteractive,
3812
- visibleLabels
3813
- ]);
4051
+ }, [renderTooltip, visibleLabels]);
3814
4052
  const resolvedFillOpacity = fillOpacity ?? (stacked ? .85 : .4);
3815
4053
  const resolvedWithStroke = withStroke ?? !stacked;
3816
4054
  if (error) return /* @__PURE__ */ jsx("div", {
@@ -3841,7 +4079,7 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
3841
4079
  dataKey: seriesData?.label,
3842
4080
  data: seriesData.data,
3843
4081
  xAccessor: accessors.xAccessor,
3844
- yAccessor: isVisible || !legendInteractive ? accessors.yAccessor : zeroYAccessor,
4082
+ yAccessor: isVisible ? accessors.yAccessor : zeroYAccessor,
3845
4083
  fill: color,
3846
4084
  fillOpacity: resolvedFillOpacity,
3847
4085
  ...stacked ? {} : {
@@ -3854,10 +4092,11 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
3854
4092
  }
3855
4093
  }, seriesData?.label || index);
3856
4094
  };
3857
- return /* @__PURE__ */ jsx(SingleChartContext.Provider, {
4095
+ return /* @__PURE__ */ jsx(ChartInstanceContext.Provider, {
3858
4096
  value: {
3859
4097
  chartId,
3860
4098
  chartRef: internalChartRef,
4099
+ isSeriesVisible,
3861
4100
  chartWidth: width,
3862
4101
  chartHeight: measuredChartHeight || 0
3863
4102
  },
@@ -3912,7 +4151,7 @@ const AreaChartInternal = forwardRef(({ data, chartId: providedChartId, width, h
3912
4151
  y: chartHeight / 2,
3913
4152
  width,
3914
4153
  height: chartHeight,
3915
- children: __("All series are hidden. Click legend items to show data.", "jetpack-charts")
4154
+ children: getAllHiddenMessage(legendInteractive, "series")
3916
4155
  }) : null,
3917
4156
  /* @__PURE__ */ jsxs(ZoomClip, {
3918
4157
  active: zoomable,
@@ -4466,11 +4705,13 @@ const renderTooltipRow = (label, value) => /* @__PURE__ */ jsx("div", {
4466
4705
  className: bar_chart_module_default["bar-chart__tooltip-row"],
4467
4706
  children: sprintf(__("%1$s: %2$s", "jetpack-charts"), label, value)
4468
4707
  });
4469
- const BarChartInternal = ({ data, chartId: providedChartId, width, height, className, margin, withTooltips = false, showLegend = false, legend = {}, gridVisibility: gridVisibilityProp, renderTooltip, options = {}, orientation = "vertical", withPatterns = false, showZeroValues = false, animation, children, gap = "md" }) => {
4708
+ const BarChartInternal = ({ data, chartId: providedChartId, width, height, className, margin, withTooltips = false, showLegend = false, legend = {}, gridVisibility: gridVisibilityProp, renderTooltip, options = {}, orientation = "vertical", withPatterns = false, showZeroValues = false, defaultHiddenSeries, animation, children, gap = "md" }) => {
4470
4709
  const legendInteractive = legend.interactive ?? false;
4471
4710
  const legendCollapseGroups = legend.collapseGroups ?? false;
4472
4711
  const horizontal = orientation === "horizontal";
4473
4712
  const chartId = useChartId(providedChartId);
4713
+ const hiddenSeries = useDefaultHiddenSeries(chartId, defaultHiddenSeries);
4714
+ const isSeriesVisible = useCallback((seriesLabel) => !hiddenSeries.has(seriesLabel), [hiddenSeries]);
4474
4715
  const theme = useXYChartTheme(data);
4475
4716
  const dataSorted = useChartDataTransform(data);
4476
4717
  const dataWithVisibleZeros = useZeroValueDisplay(dataSorted, {
@@ -4478,12 +4719,8 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
4478
4719
  valueAxisLength: horizontal ? width : height
4479
4720
  });
4480
4721
  const legendItems = useChartLegendItems(dataSorted, useMemo(() => ({ collapseGroups: legendCollapseGroups }), [legendCollapseGroups]));
4481
- const { getElementStyles, isSeriesVisible } = useGlobalChartsContext();
4482
- const isSeriesRendered = useCallback((series) => !chartId || !legendInteractive || isSeriesVisible(chartId, series.label), [
4483
- chartId,
4484
- legendInteractive,
4485
- isSeriesVisible
4486
- ]);
4722
+ const { getElementStyles } = useGlobalChartsContext();
4723
+ const isSeriesRendered = useCallback((series) => isSeriesVisible(series.label), [isSeriesVisible]);
4487
4724
  const chartOptions = useBarChartOptions(dataWithVisibleZeros, horizontal, options, isSeriesRendered);
4488
4725
  const defaultMargin = useChartMargin(height, chartOptions, dataSorted, theme, horizontal);
4489
4726
  const chartRef = useRef(null);
@@ -4719,9 +4956,10 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
4719
4956
  chartId,
4720
4957
  interactive: legendInteractive
4721
4958
  });
4722
- return /* @__PURE__ */ jsx(SingleChartContext.Provider, {
4959
+ return /* @__PURE__ */ jsx(ChartInstanceContext.Provider, {
4723
4960
  value: {
4724
4961
  chartId,
4962
+ isSeriesVisible,
4725
4963
  chartWidth: width,
4726
4964
  chartHeight: measuredChartHeight || 0
4727
4965
  },
@@ -4780,7 +5018,7 @@ const BarChartInternal = ({ data, chartId: providedChartId, width, height, class
4780
5018
  y: chartHeight / 2,
4781
5019
  width,
4782
5020
  height: chartHeight,
4783
- children: __("All series are hidden. Click legend items to show data.", "jetpack-charts")
5021
+ children: getAllHiddenMessage(legendInteractive, "series")
4784
5022
  }) : null,
4785
5023
  /* @__PURE__ */ jsx(ComparisonBars, {
4786
5024
  comparisonEntries,
@@ -5067,12 +5305,22 @@ const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loadi
5067
5305
  const { getElementStyles, isColorPaletteResolved } = useGlobalChartsContext();
5068
5306
  const chartRef = useRef(null);
5069
5307
  const selectedBarRef = useRef(null);
5308
+ const [scopeNode, setScopeNode] = useState(null);
5070
5309
  const { tooltipData, tooltipLeft, tooltipTop, tooltipOpen, showTooltip, hideTooltip } = useTooltip();
5071
5310
  const { handleBarClick, handleBarKeyDown, clearSelection, getStepState } = useFunnelSelection(hideTooltip);
5072
5311
  const { containerRef: portalContainerRef, TooltipInPortal, containerBounds } = useTooltipInPortal({
5073
5312
  detectBounds: true,
5074
5313
  scroll: true
5075
5314
  });
5315
+ const portalContainerRefRef = useRef(portalContainerRef);
5316
+ useEffect(() => {
5317
+ portalContainerRefRef.current = portalContainerRef;
5318
+ }, [portalContainerRef]);
5319
+ const setChartRef = useCallback((node) => {
5320
+ portalContainerRefRef.current(node);
5321
+ chartRef.current = node;
5322
+ setScopeNode(node);
5323
+ }, []);
5076
5324
  const clearSelectionAndRef = useCallback(() => {
5077
5325
  clearSelection();
5078
5326
  selectedBarRef.current = null;
@@ -5218,6 +5466,7 @@ const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loadi
5218
5466
  direction: "column",
5219
5467
  align: "center",
5220
5468
  justify: "center",
5469
+ ref: setScopeNode,
5221
5470
  className: clsx(conversion_funnel_chart_module_default["conversion-funnel-chart"], loading && conversion_funnel_chart_module_default["conversion-funnel-chart--loading"], className),
5222
5471
  style: {
5223
5472
  ...style,
@@ -5229,80 +5478,80 @@ const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loadi
5229
5478
  })
5230
5479
  });
5231
5480
  const maxRate = Math.max(...steps.map((step) => step.rate));
5232
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Stack, {
5481
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Stack, {
5233
5482
  direction: "column",
5234
5483
  gap: "xl",
5235
- ref: (node) => {
5236
- portalContainerRef(node);
5237
- chartRef.current = node;
5238
- },
5484
+ ref: setChartRef,
5239
5485
  className: clsx(conversion_funnel_chart_module_default["conversion-funnel-chart"], loading && conversion_funnel_chart_module_default["conversion-funnel-chart--loading"], className),
5240
5486
  style: {
5241
5487
  ...style,
5242
5488
  height: resolvedHeight
5243
5489
  },
5244
- children: [renderMainMetric ? renderMainMetric({
5245
- mainRate,
5246
- changeIndicator,
5247
- className: conversion_funnel_chart_module_default["main-metric"],
5248
- changeColor
5249
- }) : /* @__PURE__ */ jsx(Stack, {
5250
- direction: "row",
5251
- align: "baseline",
5252
- gap: "sm",
5253
- className: conversion_funnel_chart_module_default["main-metric"],
5254
- children: renderDefaultMainMetric()
5255
- }), /* @__PURE__ */ jsx(Stack, {
5256
- direction: "row",
5257
- align: "flex-end",
5258
- gap: "lg",
5259
- className: conversion_funnel_chart_module_default["funnel-container"],
5260
- children: steps.map((step, index) => {
5261
- const barHeight = step.rate / maxRate * 100;
5262
- const { isBlurred } = getStepState(step.id);
5263
- return /* @__PURE__ */ jsxs(Stack, {
5264
- direction: "column",
5265
- className: clsx(conversion_funnel_chart_module_default["funnel-step"], isColorPaletteResolved && conversion_funnel_chart_module_default["funnel-step--animated"], isBlurred && conversion_funnel_chart_module_default["funnel-step--blurred"]),
5266
- gap: "xl",
5267
- children: [/* @__PURE__ */ jsxs(Stack, {
5490
+ children: /* @__PURE__ */ jsxs(ChartScopeContext.Provider, {
5491
+ value: scopeNode,
5492
+ children: [renderMainMetric ? renderMainMetric({
5493
+ mainRate,
5494
+ changeIndicator,
5495
+ className: conversion_funnel_chart_module_default["main-metric"],
5496
+ changeColor
5497
+ }) : /* @__PURE__ */ jsx(Stack, {
5498
+ direction: "row",
5499
+ align: "baseline",
5500
+ gap: "sm",
5501
+ className: conversion_funnel_chart_module_default["main-metric"],
5502
+ children: renderDefaultMainMetric()
5503
+ }), /* @__PURE__ */ jsx(Stack, {
5504
+ direction: "row",
5505
+ align: "flex-end",
5506
+ gap: "lg",
5507
+ className: conversion_funnel_chart_module_default["funnel-container"],
5508
+ children: steps.map((step, index) => {
5509
+ const barHeight = step.rate / maxRate * 100;
5510
+ const { isBlurred } = getStepState(step.id);
5511
+ return /* @__PURE__ */ jsxs(Stack, {
5268
5512
  direction: "column",
5269
- gap: "xs",
5270
- children: [renderStepLabel ? renderStepLabel({
5271
- step,
5272
- index,
5273
- className: conversion_funnel_chart_module_default["step-label"]
5274
- }) : /* @__PURE__ */ jsx("span", {
5275
- className: conversion_funnel_chart_module_default["step-label"],
5276
- children: step.label
5277
- }), renderStepRate ? renderStepRate({
5278
- step,
5279
- index,
5280
- className: conversion_funnel_chart_module_default["step-rate"]
5281
- }) : /* @__PURE__ */ jsx("span", {
5282
- className: conversion_funnel_chart_module_default["step-rate"],
5283
- children: formatPercentage(step.rate)
5513
+ className: clsx(conversion_funnel_chart_module_default["funnel-step"], isColorPaletteResolved && conversion_funnel_chart_module_default["funnel-step--animated"], isBlurred && conversion_funnel_chart_module_default["funnel-step--blurred"]),
5514
+ gap: "xl",
5515
+ children: [/* @__PURE__ */ jsxs(Stack, {
5516
+ direction: "column",
5517
+ gap: "xs",
5518
+ children: [renderStepLabel ? renderStepLabel({
5519
+ step,
5520
+ index,
5521
+ className: conversion_funnel_chart_module_default["step-label"]
5522
+ }) : /* @__PURE__ */ jsx("span", {
5523
+ className: conversion_funnel_chart_module_default["step-label"],
5524
+ children: step.label
5525
+ }), renderStepRate ? renderStepRate({
5526
+ step,
5527
+ index,
5528
+ className: conversion_funnel_chart_module_default["step-rate"]
5529
+ }) : /* @__PURE__ */ jsx("span", {
5530
+ className: conversion_funnel_chart_module_default["step-rate"],
5531
+ children: formatPercentage(step.rate)
5532
+ })]
5533
+ }), /* @__PURE__ */ jsx(Stack, {
5534
+ direction: "column",
5535
+ justify: "flex-end",
5536
+ className: conversion_funnel_chart_module_default["bar-container"],
5537
+ onClick: stepHandlers.get(step.id)?.onClick,
5538
+ onKeyDown: stepHandlers.get(step.id)?.onKeyDown,
5539
+ role: "button",
5540
+ tabIndex: isBlurred ? -1 : 0,
5541
+ "aria-label": step.label,
5542
+ style: { backgroundColor: barBackgroundColor },
5543
+ children: /* @__PURE__ */ jsx("div", {
5544
+ className: clsx(conversion_funnel_chart_module_default["funnel-bar"], { [conversion_funnel_chart_module_default["funnel-bar--animated"]]: animation && !loading && !prefersReducedMotion }),
5545
+ style: {
5546
+ height: `${barHeight}%`,
5547
+ backgroundColor: barColor
5548
+ }
5549
+ })
5284
5550
  })]
5285
- }), /* @__PURE__ */ jsx(Stack, {
5286
- direction: "column",
5287
- justify: "flex-end",
5288
- className: conversion_funnel_chart_module_default["bar-container"],
5289
- onClick: stepHandlers.get(step.id)?.onClick,
5290
- onKeyDown: stepHandlers.get(step.id)?.onKeyDown,
5291
- role: "button",
5292
- tabIndex: isBlurred ? -1 : 0,
5293
- "aria-label": step.label,
5294
- style: { backgroundColor: barBackgroundColor },
5295
- children: /* @__PURE__ */ jsx("div", {
5296
- className: clsx(conversion_funnel_chart_module_default["funnel-bar"], { [conversion_funnel_chart_module_default["funnel-bar--animated"]]: animation && !loading && !prefersReducedMotion }),
5297
- style: {
5298
- height: `${barHeight}%`,
5299
- backgroundColor: barColor
5300
- }
5301
- })
5302
- })]
5303
- }, step.id);
5304
- })
5305
- })]
5551
+ }, step.id);
5552
+ })
5553
+ })]
5554
+ })
5306
5555
  }), tooltipOpen && tooltipData && (() => {
5307
5556
  const tooltipContent = renderTooltip ? renderTooltip({
5308
5557
  step: tooltipData,
@@ -5315,7 +5564,7 @@ const ConversionFunnelChartInternal = ({ mainRate, changeIndicator, steps, loadi
5315
5564
  return /* @__PURE__ */ jsx(TooltipInPortal, {
5316
5565
  top: tooltipTop,
5317
5566
  left: tooltipLeft,
5318
- className: conversion_funnel_chart_module_default["tooltip-wrapper"],
5567
+ className: clsx("a8c-charts-scope", conversion_funnel_chart_module_default["tooltip-wrapper"]),
5319
5568
  children: tooltipContent
5320
5569
  }, Math.random());
5321
5570
  })()] });
@@ -5465,6 +5714,7 @@ function normalizeGeoChartError(eventArgs) {
5465
5714
  */
5466
5715
  const GeoChartInternal = ({ className, data, width, height, region = "world", resolution = "countries", onError, renderPlaceholder }) => {
5467
5716
  const { getElementStyles, theme: { geoChart: { featureFillColor }, backgroundColor } } = useGlobalChartsContext();
5717
+ const scopeElement = useChartScopeElement();
5468
5718
  const containerRef = useRef(null);
5469
5719
  const reportedErrorIdsRef = useRef(/* @__PURE__ */ new Set());
5470
5720
  useEffect(() => {
@@ -5497,8 +5747,8 @@ const GeoChartInternal = ({ className, data, width, height, region = "world", re
5497
5747
  });
5498
5748
  const fullColorHex = getElementStyles({ index: 0 }).color;
5499
5749
  const lightColorHex = lightenHexColor(fullColorHex, .8);
5500
- const backgroundColorHex = normalizeColorToHex(backgroundColor, null, resolveCssVariable) || DEFAULT_BACKGROUND_COLOR;
5501
- const defaultFillColorHex = normalizeColorToHex(featureFillColor, null, resolveCssVariable) || DEFAULT_FEATURE_FILL_COLOR;
5750
+ const backgroundColorHex = normalizeColorToHex(backgroundColor, scopeElement, resolveCssVariable) || DEFAULT_BACKGROUND_COLOR;
5751
+ const defaultFillColorHex = normalizeColorToHex(featureFillColor, scopeElement, resolveCssVariable) || DEFAULT_FEATURE_FILL_COLOR;
5502
5752
  const sanitizedData = useMemo(() => {
5503
5753
  if (data.length === 0) return {
5504
5754
  data,
@@ -5581,12 +5831,27 @@ const GeoChartWithProvider = (props) => {
5581
5831
  GeoChartWithProvider.displayName = "GeoChart";
5582
5832
  const GeoChartResponsive = withResponsive(GeoChartWithProvider);
5583
5833
  //#endregion
5834
+ //#region src/types.ts
5835
+ let GoogleDataTableColumnRoleType = /* @__PURE__ */ function(GoogleDataTableColumnRoleType) {
5836
+ GoogleDataTableColumnRoleType["annotation"] = "annotation";
5837
+ GoogleDataTableColumnRoleType["annotationText"] = "annotationText";
5838
+ GoogleDataTableColumnRoleType["certainty"] = "certainty";
5839
+ GoogleDataTableColumnRoleType["emphasis"] = "emphasis";
5840
+ GoogleDataTableColumnRoleType["interval"] = "interval";
5841
+ GoogleDataTableColumnRoleType["scope"] = "scope";
5842
+ GoogleDataTableColumnRoleType["style"] = "style";
5843
+ GoogleDataTableColumnRoleType["tooltip"] = "tooltip";
5844
+ GoogleDataTableColumnRoleType["domain"] = "domain";
5845
+ return GoogleDataTableColumnRoleType;
5846
+ }({});
5847
+ //#endregion
5584
5848
  //#region src/charts/heatmap-chart/heatmap-chart.module.scss
5585
5849
  var heatmap_chart_module_default = {
5586
5850
  "heatmap-chart": "a8ccharts-O3YMOW-heatmap-chart",
5587
5851
  "heatmap-chart__cell": "a8ccharts-O3YMOW-heatmap-chart__cell",
5588
5852
  "heatmap-chart__cell--filled": "a8ccharts-O3YMOW-heatmap-chart__cell--filled",
5589
5853
  "heatmap-chart__cell--hidden": "a8ccharts-O3YMOW-heatmap-chart__cell--hidden",
5854
+ "heatmap-chart__cell--placeholder": "a8ccharts-O3YMOW-heatmap-chart__cell--placeholder",
5590
5855
  "heatmap-chart__cell--selected": "a8ccharts-O3YMOW-heatmap-chart__cell--selected",
5591
5856
  "heatmap-chart__cell--strong": "a8ccharts-O3YMOW-heatmap-chart__cell--strong",
5592
5857
  "heatmap-chart__cell-value": "a8ccharts-O3YMOW-heatmap-chart__cell-value",
@@ -5642,6 +5907,22 @@ const LABELLED_ROWS = [
5642
5907
  2,
5643
5908
  4
5644
5909
  ];
5910
+ /**
5911
+ * Resolve one grid bound: an unparseable or narrowing value falls back to the
5912
+ * series' own bound, so the grid can only ever be widened.
5913
+ *
5914
+ * @param bound - Requested bound as `yyyy-MM-dd`, if any.
5915
+ * @param fallback - The series' own bound on this side.
5916
+ * @param direction - Which way the bound is allowed to move.
5917
+ * @return The bound to draw to.
5918
+ */
5919
+ const widenTo = (bound, fallback, direction) => {
5920
+ if (!bound) return fallback;
5921
+ const parsed = parseISO(bound);
5922
+ if (isNaN(parsed.getTime())) return fallback;
5923
+ if (direction === "earlier") return parsed < fallback ? parsed : fallback;
5924
+ return parsed > fallback ? parsed : fallback;
5925
+ };
5645
5926
  const toDate = (point) => {
5646
5927
  if (point.date instanceof Date && !isNaN(point.date.getTime())) return point.date;
5647
5928
  if (point.dateString) {
@@ -5669,10 +5950,14 @@ const buildCalendarHeatmapData = (series, options = {}) => {
5669
5950
  if (date < minDate) minDate = date;
5670
5951
  if (date > maxDate) maxDate = date;
5671
5952
  }
5672
- const gridStart = startOfWeek(minDate, { weekStartsOn });
5673
- const weekCount = differenceInCalendarWeeks(maxDate, gridStart, { weekStartsOn }) + 1;
5674
5953
  const minDayKey = format(minDate, "yyyy-MM-dd");
5675
5954
  const maxDayKey = format(maxDate, "yyyy-MM-dd");
5955
+ const gridMinDate = widenTo(options.gridSpan?.start, minDate, "earlier");
5956
+ const gridMaxDate = widenTo(options.gridSpan?.end, maxDate, "later");
5957
+ const gridMaxDayKey = format(gridMaxDate, "yyyy-MM-dd");
5958
+ const gridStart = startOfWeek(gridMinDate, { weekStartsOn });
5959
+ const gridMinDayKey = format(gridMinDate < minDate ? gridStart : gridMinDate, "yyyy-MM-dd");
5960
+ const weekCount = differenceInCalendarWeeks(gridMaxDate, gridStart, { weekStartsOn }) + 1;
5676
5961
  const rowLabels = Array.from({ length: 7 }, (_, row) => LABELLED_ROWS.includes(row) ? format(addDays(gridStart, row), "EEE") : "");
5677
5962
  const MIN_FIRST_MONTH_WEEKS = 2;
5678
5963
  const firstMonth = gridStart.getMonth();
@@ -5694,7 +5979,9 @@ const buildCalendarHeatmapData = (series, options = {}) => {
5694
5979
  label: format(day, "EEE, MMM d, yyyy"),
5695
5980
  value: valueByDay.has(key) ? valueByDay.get(key) : null
5696
5981
  };
5697
- if (hideOutOfRangeDays && (key < minDayKey || key > maxDayKey)) cell.hidden = true;
5982
+ if (key < gridMinDayKey || key > gridMaxDayKey) {
5983
+ if (hideOutOfRangeDays) cell.hidden = true;
5984
+ } else if (key < minDayKey || key > maxDayKey) cell.placeholder = true;
5698
5985
  cells.push(cell);
5699
5986
  }
5700
5987
  data.push({
@@ -5758,7 +6045,8 @@ const HeatmapLegend = ({ steps = 5, lessLabel, moreLabel }) => {
5758
6045
  const CELL_MIX_FLOOR = .15;
5759
6046
  const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, height = 0, className, compact = false, showValues, maxCellWidth, maxCellHeight, minCellWidth, minCellHeight, rowLabels = [], primaryColor, gap = "md", withTooltips = false, renderTooltip, children }) => {
5760
6047
  const chartId = useChartId(providedChartId);
5761
- const { getElementStyles, resolveThemeColor, theme } = useGlobalChartsContext();
6048
+ const { getElementStyles, theme } = useGlobalChartsContext();
6049
+ const scopeElement = useChartScopeElement();
5762
6050
  const { heatmapChart: heatmapChartSettings } = theme;
5763
6051
  const { nonLegendChildren } = useChartChildren(children, "HeatmapChart");
5764
6052
  const [selectedIndex, setSelectedIndex] = useState();
@@ -5773,7 +6061,7 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
5773
6061
  index: 0,
5774
6062
  overrideColor: primaryColor || heatmapChartSettings.primaryColor
5775
6063
  });
5776
- const chartBackgroundHex = resolveThemeColor(theme.backgroundColor);
6064
+ const chartBackgroundHex = normalizeColorToHex(theme.backgroundColor, scopeElement, resolveCssVariable);
5777
6065
  const primaryHex = normalizeColorToHex(primaryColorHex);
5778
6066
  const cellHasLightText = (intensity) => isValidHexColor(primaryHex) && isValidHexColor(chartBackgroundHex) && prefersLightText(mixHexColors(primaryHex, chartBackgroundHex, 1 - (CELL_MIX_FLOOR + (1 - CELL_MIX_FLOOR) * intensity)));
5779
6067
  const extent = useMemo(() => getValueExtent(data), [data]);
@@ -5800,7 +6088,10 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
5800
6088
  setSelectedIndex(void 0);
5801
6089
  hideTooltip();
5802
6090
  }, [hideTooltip]);
5803
- const isCellHidden = useCallback((col, row) => data[col]?.data[row]?.hidden === true, [data]);
6091
+ const isCellInert = useCallback((col, row) => {
6092
+ const cell = data[col]?.data[row];
6093
+ return cell?.hidden === true || cell?.placeholder === true;
6094
+ }, [data]);
5804
6095
  const onChartKeyDown = useCallback((event) => {
5805
6096
  if (![
5806
6097
  "ArrowLeft",
@@ -5817,7 +6108,7 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
5817
6108
  }
5818
6109
  event.preventDefault();
5819
6110
  if (selectedIndex === void 0) {
5820
- for (let index = 0; index < columns * rows; index++) if (!isCellHidden(Math.floor(index / rows), index % rows)) {
6111
+ for (let index = 0; index < columns * rows; index++) if (!isCellInert(Math.floor(index / rows), index % rows)) {
5821
6112
  setSelectedIndex(index);
5822
6113
  return;
5823
6114
  }
@@ -5834,7 +6125,7 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
5834
6125
  do {
5835
6126
  col += stepCol;
5836
6127
  row += stepRow;
5837
- } while (col >= 0 && col < columns && row >= 0 && row < rows && isCellHidden(col, row));
6128
+ } while (col >= 0 && col < columns && row >= 0 && row < rows && isCellInert(col, row));
5838
6129
  if (col < 0 || col >= columns || row < 0 || row >= rows) return;
5839
6130
  setSelectedIndex(col * rows + row);
5840
6131
  }, [
@@ -5842,7 +6133,7 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
5842
6133
  columns,
5843
6134
  selectedIndex,
5844
6135
  hideTooltip,
5845
- isCellHidden
6136
+ isCellInert
5846
6137
  ]);
5847
6138
  const handleCellMouseMove = useCallback((event) => {
5848
6139
  if (!withTooltips) return;
@@ -5914,7 +6205,7 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
5914
6205
  const heightCapped = !compact && Boolean(maxCellHeight);
5915
6206
  return /* @__PURE__ */ jsx(HeatmapContext.Provider, {
5916
6207
  value: heatmapContext,
5917
- children: /* @__PURE__ */ jsx(SingleChartContext.Provider, {
6208
+ children: /* @__PURE__ */ jsx(ChartInstanceContext.Provider, {
5918
6209
  value: { chartId },
5919
6210
  children: /* @__PURE__ */ jsxs(ChartLayout, {
5920
6211
  legendPosition: "bottom",
@@ -5966,6 +6257,10 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
5966
6257
  "aria-hidden": "true",
5967
6258
  className: clsx(heatmap_chart_module_default["heatmap-chart__cell"], heatmap_chart_module_default["heatmap-chart__cell--hidden"])
5968
6259
  }, `cell-${columnIndex}-${rowIndex}`);
6260
+ if (cell?.placeholder) return /* @__PURE__ */ jsx("div", {
6261
+ "aria-hidden": "true",
6262
+ className: clsx(heatmap_chart_module_default["heatmap-chart__cell"], heatmap_chart_module_default["heatmap-chart__cell--placeholder"])
6263
+ }, `cell-${columnIndex}-${rowIndex}`);
5969
6264
  const value = cell?.value ?? null;
5970
6265
  const present = isPresent(value);
5971
6266
  const normalized = present ? getNormalizedValue(value, extent) : 0;
@@ -6000,6 +6295,7 @@ const HeatmapChartInternal = ({ data, chartId: providedChartId, width = 0, heigh
6000
6295
  top: tooltipTop,
6001
6296
  left: tooltipLeft,
6002
6297
  children: /* @__PURE__ */ jsx("div", {
6298
+ className: "a8c-charts-scope",
6003
6299
  role: "tooltip",
6004
6300
  tabIndex: -1,
6005
6301
  children: (renderTooltip ?? defaultRenderTooltip)(tooltipData)
@@ -8598,29 +8894,25 @@ const LeaderboardChartInternal = ({ data, chartId: providedChartId, width: propW
8598
8894
  legendLabels
8599
8895
  });
8600
8896
  const isPrimaryVisible = useMemo(() => {
8601
- if (!chartId || !legendInteractive || legendItems.length === 0) return true;
8897
+ if (legendItems.length === 0) return true;
8602
8898
  return isSeriesVisible(chartId, legendItems[0].label);
8603
8899
  }, [
8604
8900
  chartId,
8605
- legendInteractive,
8606
8901
  legendItems,
8607
8902
  isSeriesVisible
8608
8903
  ]);
8609
8904
  const isComparisonVisible = useMemo(() => {
8610
- if (!chartId || !legendInteractive || legendItems.length < 2) return true;
8905
+ if (legendItems.length < 2) return true;
8611
8906
  return isSeriesVisible(chartId, legendItems[1].label);
8612
8907
  }, [
8613
8908
  chartId,
8614
- legendInteractive,
8615
8909
  legendItems,
8616
8910
  isSeriesVisible
8617
8911
  ]);
8618
8912
  const allSeriesHidden = useMemo(() => {
8619
- if (!legendInteractive) return false;
8620
8913
  if (withComparison && !withOverlayLabel) return !isPrimaryVisible && !isComparisonVisible;
8621
8914
  return !isPrimaryVisible;
8622
8915
  }, [
8623
- legendInteractive,
8624
8916
  isPrimaryVisible,
8625
8917
  isComparisonVisible,
8626
8918
  withComparison,
@@ -8639,7 +8931,7 @@ const LeaderboardChartInternal = ({ data, chartId: providedChartId, width: propW
8639
8931
  const prefersReducedMotion = usePrefersReducedMotion();
8640
8932
  const { contentRef, fittedCount, isMeasurable } = useFittedRowCount(fitRows && !allSeriesHidden, data?.length ?? 0, data);
8641
8933
  const shouldFitRows = fitRows && isMeasurable;
8642
- if (!data || data.length === 0) return /* @__PURE__ */ jsx(SingleChartContext.Provider, {
8934
+ if (!data || data.length === 0) return /* @__PURE__ */ jsx(ChartInstanceContext.Provider, {
8643
8935
  value: { chartId },
8644
8936
  children: /* @__PURE__ */ jsx(ChartLayout, {
8645
8937
  legendPosition,
@@ -8674,7 +8966,7 @@ const LeaderboardChartInternal = ({ data, chartId: providedChartId, width: propW
8674
8966
  chartId,
8675
8967
  interactive: legendInteractive
8676
8968
  });
8677
- return /* @__PURE__ */ jsx(SingleChartContext.Provider, {
8969
+ return /* @__PURE__ */ jsx(ChartInstanceContext.Provider, {
8678
8970
  value: { chartId },
8679
8971
  children: /* @__PURE__ */ jsx(ChartLayout, {
8680
8972
  legendPosition,
@@ -8699,7 +8991,7 @@ const LeaderboardChartInternal = ({ data, chartId: providedChartId, width: propW
8699
8991
  children: __("Not enough space to display data", "jetpack-charts")
8700
8992
  }), allSeriesHidden ? /* @__PURE__ */ jsx("div", {
8701
8993
  className: leaderboard_chart_module_default.emptyState,
8702
- children: __("All series are hidden. Click legend items to show data.", "jetpack-charts")
8994
+ children: getAllHiddenMessage(legendInteractive, "series")
8703
8995
  }) : /* @__PURE__ */ jsx(component_default, {
8704
8996
  templateColumns: "minmax(0, 1fr) auto",
8705
8997
  rowGap,
@@ -8889,10 +9181,9 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
8889
9181
  hideTooltip();
8890
9182
  }, [withTooltips, hideTooltip]);
8891
9183
  const { getElementStyles, isSeriesVisible } = useGlobalChartsContext();
8892
- const { visibleData, allSegmentsHidden, legendData } = useInteractiveLegendData({
9184
+ const { visibleData, allSegmentsHidden, legendData } = useLegendVisibilityData({
8893
9185
  data: useDataWithPercentages(data),
8894
9186
  chartId,
8895
- legendInteractive,
8896
9187
  isSeriesVisible
8897
9188
  });
8898
9189
  const legendItems = useChartLegendItems(legendData, useMemo(() => ({
@@ -8953,7 +9244,7 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
8953
9244
  chartId,
8954
9245
  interactive: legendInteractive
8955
9246
  });
8956
- return /* @__PURE__ */ jsx(SingleChartContext.Provider, {
9247
+ return /* @__PURE__ */ jsx(ChartInstanceContext.Provider, {
8957
9248
  value: { chartId },
8958
9249
  children: /* @__PURE__ */ jsx(ChartLayout, {
8959
9250
  legendPosition,
@@ -8970,6 +9261,7 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
8970
9261
  top: tooltipTop || 0,
8971
9262
  left: tooltipLeft || 0,
8972
9263
  children: /* @__PURE__ */ jsx("div", {
9264
+ className: "a8c-charts-scope",
8973
9265
  role: "tooltip",
8974
9266
  children: renderTooltip({ tooltipData })
8975
9267
  })
@@ -9009,7 +9301,7 @@ const PieChartInternal = ({ data, chartId: providedChartId, withTooltips = false
9009
9301
  y: 0,
9010
9302
  width,
9011
9303
  height,
9012
- children: __("All segments are hidden. Click legend items to show data.", "jetpack-charts")
9304
+ children: getAllHiddenMessage(legendInteractive, "segments")
9013
9305
  }) : /* @__PURE__ */ jsx(Pie, {
9014
9306
  data: dataWithIndex,
9015
9307
  pieValue: accessors.value,
@@ -9181,10 +9473,9 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
9181
9473
  }, [handleMouseMove]);
9182
9474
  const { isValid, message } = validateData(data);
9183
9475
  const { getElementStyles, isSeriesVisible } = useGlobalChartsContext();
9184
- const { visibleData, allSegmentsHidden, legendData } = useInteractiveLegendData({
9476
+ const { visibleData, allSegmentsHidden, legendData } = useLegendVisibilityData({
9185
9477
  data: useDataWithPercentages(data),
9186
9478
  chartId,
9187
- legendInteractive,
9188
9479
  isSeriesVisible
9189
9480
  });
9190
9481
  const accessors = useMemo(() => ({
@@ -9251,7 +9542,7 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
9251
9542
  chartId,
9252
9543
  interactive: legendInteractive
9253
9544
  });
9254
- return /* @__PURE__ */ jsx(SingleChartContext.Provider, {
9545
+ return /* @__PURE__ */ jsx(ChartInstanceContext.Provider, {
9255
9546
  value: { chartId },
9256
9547
  children: /* @__PURE__ */ jsx(ChartLayout, {
9257
9548
  legendPosition,
@@ -9268,6 +9559,7 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
9268
9559
  top: tooltipTop || 0,
9269
9560
  left: tooltipLeft || 0,
9270
9561
  children: /* @__PURE__ */ jsx("div", {
9562
+ className: "a8c-charts-scope",
9271
9563
  role: "tooltip",
9272
9564
  children: renderTooltip({ tooltipData })
9273
9565
  })
@@ -9303,7 +9595,7 @@ const PieSemiCircleChartInternal = ({ data, chartId: providedChartId, width: pro
9303
9595
  y: -radius / 2,
9304
9596
  width,
9305
9597
  height,
9306
- children: __("All segments are hidden. Click legend items to show data.", "jetpack-charts")
9598
+ children: getAllHiddenMessage(legendInteractive, "segments")
9307
9599
  }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
9308
9600
  /* @__PURE__ */ jsx(Pie, {
9309
9601
  data: dataWithIndex,
@@ -9555,7 +9847,7 @@ const Icon$1 = ({ direction }) => {
9555
9847
  function TrendIndicator({ direction, value, className, style, showIcon = true }) {
9556
9848
  const ariaLabel = `${DIRECTION_LABELS[direction]}: ${value}`;
9557
9849
  return /* @__PURE__ */ jsxs("span", {
9558
- className: clsx(trend_indicator_module_default["trend-indicator"], trend_indicator_module_default[`trend-indicator--${direction}`], className),
9850
+ className: clsx(useStandaloneScopeClass(), trend_indicator_module_default["trend-indicator"], trend_indicator_module_default[`trend-indicator--${direction}`], className),
9559
9851
  style,
9560
9852
  "aria-label": ariaLabel,
9561
9853
  children: [showIcon && /* @__PURE__ */ jsx(Icon$1, { direction }), /* @__PURE__ */ jsx("span", {
@@ -9565,6 +9857,6 @@ function TrendIndicator({ direction, value, className, style, showIcon = true })
9565
9857
  });
9566
9858
  }
9567
9859
  //#endregion
9568
- export { AccessibleTooltip, AreaChartResponsive as AreaChart, AreaChart as AreaChartUnresponsive, BarChartResponsive as BarChart, BarChart as BarChartUnresponsive, BarListChartResponsive as BarListChart, BarListChart as BarListChartUnresponsive, BaseTooltip, ConversionFunnelChartWithProvider as ConversionFunnelChart, GeoChartResponsive as GeoChart, GeoChartWithProvider as GeoChartUnresponsive, GlobalChartsContext, GlobalChartsProvider, GlobalChartsProvider as ThemeProvider, HeatmapChartResponsive as HeatmapChart, HeatmapChart as HeatmapChartUnresponsive, LeaderboardChartResponsive as LeaderboardChart, LeaderboardChart as LeaderboardChartUnresponsive, Legend, LineChartResponsive as LineChart, LineChart as LineChartUnresponsive, PieChartResponsive as PieChart, PieChart as PieChartUnresponsive, PieSemiCircleChartResponsive as PieSemiCircleChart, PieSemiCircleChart as PieSemiCircleChartUnresponsive, Sparkline, SparklineUnresponsive, TrendIndicator, buildCalendarHeatmapData, defaultTheme, formatMetricValue, formatPercentage, getColorDistance, hexToRgba, isValidHexColor, lightenHexColor, mergeThemes, mixHexColors, normalizeColorToHex, parseAsLocalDate, parseHslString, parseRgbString, prefersLightText, relativeLuminance, useChartLegendItems, useGlobalChartsContext, useGlobalChartsTheme, useLeaderboardLegendItems, validateHexColor };
9860
+ export { AccessibleTooltip, AreaChartResponsive as AreaChart, AreaChart as AreaChartUnresponsive, BarChartResponsive as BarChart, BarChart as BarChartUnresponsive, BarListChartResponsive as BarListChart, BarListChart as BarListChartUnresponsive, BaseTooltip, ConversionFunnelChartWithProvider as ConversionFunnelChart, GeoChartResponsive as GeoChart, GeoChartWithProvider as GeoChartUnresponsive, GlobalChartsContext, GlobalChartsProvider, GlobalChartsProvider as ThemeProvider, GoogleDataTableColumnRoleType, HeatmapChartResponsive as HeatmapChart, HeatmapChart as HeatmapChartUnresponsive, LeaderboardChartResponsive as LeaderboardChart, LeaderboardChart as LeaderboardChartUnresponsive, Legend, LineChartResponsive as LineChart, LineChart as LineChartUnresponsive, PieChartResponsive as PieChart, PieChart as PieChartUnresponsive, PieSemiCircleChartResponsive as PieSemiCircleChart, PieSemiCircleChart as PieSemiCircleChartUnresponsive, Sparkline, SparklineUnresponsive, TrendIndicator, buildCalendarHeatmapData, defaultTheme, formatMetricValue, formatPercentage, getColorDistance, hexToRgba, isValidHexColor, lightenHexColor, mergeThemes, mixHexColors, normalizeColorToHex, parseAsLocalDate, parseHslString, parseRgbString, prefersLightText, relativeLuminance, resolveCssVariable, useChartLegendItems, useChartRegistration, useChartScopeElement, useGlobalChartsContext, useGlobalChartsTheme, useLeaderboardLegendItems, validateHexColor };
9569
9861
 
9570
9862
  //# sourceMappingURL=index.js.map