@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.
- package/CHANGELOG.md +29 -0
- package/TOKENS.md +109 -50
- package/dist/index.cjs +529 -233
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +118 -55
- package/dist/index.d.cts +90 -48
- package/dist/index.d.ts +90 -48
- package/dist/index.js +527 -235
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/charts/area-chart/area-chart.module.scss +8 -3
- package/src/charts/area-chart/area-chart.tsx +25 -25
- package/src/charts/area-chart/private/overlays.tsx +3 -3
- package/src/charts/area-chart/test/area-chart.test.tsx +301 -11
- package/src/charts/area-chart/types.ts +4 -3
- package/src/charts/bar-chart/bar-chart.module.scss +14 -6
- package/src/charts/bar-chart/bar-chart.tsx +21 -15
- package/src/charts/bar-chart/test/bar-chart.test.tsx +255 -2
- package/src/charts/conversion-funnel-chart/conversion-funnel-chart.module.scss +23 -18
- package/src/charts/conversion-funnel-chart/conversion-funnel-chart.tsx +107 -86
- package/src/charts/conversion-funnel-chart/test/chart-scope.test.tsx +36 -0
- package/src/charts/geo-chart/geo-chart.module.scss +8 -0
- package/src/charts/geo-chart/geo-chart.tsx +12 -4
- package/src/charts/heatmap-chart/heatmap-chart.module.scss +22 -9
- package/src/charts/heatmap-chart/heatmap-chart.tsx +43 -13
- package/src/charts/heatmap-chart/private/build-calendar-data.ts +65 -5
- package/src/charts/heatmap-chart/test/build-calendar-data.test.ts +125 -0
- package/src/charts/heatmap-chart/types.ts +8 -0
- package/src/charts/leaderboard-chart/leaderboard-chart.module.scss +13 -7
- package/src/charts/leaderboard-chart/leaderboard-chart.tsx +17 -22
- package/src/charts/leaderboard-chart/test/leaderboard-chart.test.tsx +107 -1
- package/src/charts/leaderboard-chart/types.ts +0 -2
- package/src/charts/line-chart/line-chart.module.scss +12 -7
- package/src/charts/line-chart/line-chart.tsx +32 -28
- package/src/charts/line-chart/private/line-chart-annotation.tsx +4 -4
- package/src/charts/line-chart/private/line-chart-annotations-overlay.tsx +2 -2
- package/src/charts/line-chart/test/line-chart.test.tsx +262 -5
- package/src/charts/line-chart/types.ts +4 -3
- package/src/charts/pie-chart/pie-chart.tsx +12 -14
- package/src/charts/pie-chart/test/pie-chart.test.tsx +73 -1
- package/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.module.scss +2 -2
- package/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.tsx +12 -14
- package/src/charts/private/{single-chart-context/single-chart-context.tsx → chart-instance-context/chart-instance-context.ts} +1 -5
- package/src/charts/private/chart-instance-context/index.ts +3 -0
- package/src/charts/private/{single-chart-context/use-single-chart-context.ts → chart-instance-context/use-chart-instance-context.ts} +1 -3
- package/src/charts/private/svg-empty-state/get-all-hidden-message.ts +41 -0
- package/src/charts/private/svg-empty-state/index.ts +1 -0
- package/src/charts/private/svg-empty-state/svg-empty-state.module.scss +1 -1
- package/src/charts/private/svg-empty-state/test/get-all-hidden-message.test.ts +15 -0
- package/src/charts/private/with-responsive/test/with-responsive.test.tsx +16 -0
- package/src/charts/private/with-responsive/with-responsive.tsx +18 -11
- package/src/charts/private/x-zoom/test/x-zoom.test.tsx +2 -2
- package/src/charts/private/x-zoom/x-zoom.module.scss +3 -3
- package/src/charts/private/x-zoom/x-zoom.tsx +2 -2
- package/src/components/legend/legend.tsx +4 -4
- package/src/components/legend/private/base-legend.module.scss +1 -1
- package/src/components/legend/private/base-legend.tsx +70 -19
- package/src/components/legend/test/legend.test.tsx +100 -4
- package/src/components/tooltip/accessible-tooltip.tsx +17 -4
- package/src/components/tooltip/base-tooltip.tsx +8 -1
- package/src/components/trend-indicator/test/trend-indicator.test.tsx +20 -0
- package/src/components/trend-indicator/trend-indicator.module.scss +4 -7
- package/src/components/trend-indicator/trend-indicator.tsx +3 -0
- package/src/hooks/index.ts +1 -1
- package/src/hooks/test/use-xychart-theme-provider-override.test.tsx +28 -0
- package/src/hooks/test/use-xychart-theme-style-reads.test.tsx +19 -13
- package/src/hooks/test/use-xychart-theme.test.tsx +25 -0
- package/src/hooks/{use-interactive-legend-data.ts → use-legend-visibility-data.ts} +29 -30
- package/src/hooks/use-xychart-theme.ts +6 -4
- package/src/index.ts +12 -3
- package/src/providers/chart-context/global-charts-provider.tsx +127 -30
- package/src/providers/chart-context/hooks/use-default-hidden-series.ts +47 -0
- package/src/providers/chart-context/private/theme-override-vars.ts +87 -0
- package/src/providers/chart-context/private/with-catalog-pointers.ts +50 -0
- package/src/providers/chart-context/test/chart-context.test.tsx +142 -40
- package/src/providers/chart-context/test/chart-scope-class.test.tsx +19 -0
- package/src/providers/chart-context/test/sparse-theme.test.ts +35 -0
- package/src/providers/chart-context/test/theme-override-vars-guard.test.tsx +29 -0
- package/src/providers/chart-context/test/theme-override-vars.test.ts +118 -0
- package/src/providers/chart-context/test/use-default-hidden-series-paint.test.tsx +56 -0
- package/src/providers/chart-context/test/use-default-hidden-series.ssr.test.tsx +39 -0
- package/src/providers/chart-context/test/use-default-hidden-series.test.tsx +222 -0
- package/src/providers/chart-context/test/with-catalog-pointers.test.ts +47 -0
- package/src/providers/chart-context/themes.ts +18 -27
- package/src/providers/chart-context/types.ts +7 -4
- package/src/providers/chart-scope/chart-scope-context.ts +8 -0
- package/src/providers/chart-scope/index.ts +3 -0
- package/src/providers/chart-scope/test/chart-scope.test.tsx +24 -0
- package/src/providers/chart-scope/test/use-standalone-scope-class.test.tsx +20 -0
- package/src/providers/chart-scope/use-chart-scope-element.ts +9 -0
- package/src/providers/chart-scope/use-standalone-scope-class.ts +13 -0
- package/src/providers/index.ts +1 -0
- package/src/styles/chart-scope-class.ts +6 -0
- package/src/styles/chart-scope.scss +83 -0
- package/src/styles/test/chart-scope.test.ts +165 -0
- package/src/styles/test/wpds-fallbacks.test.ts +131 -0
- package/src/types.ts +12 -34
- package/src/charts/private/grid-control/grid-control.module.scss +0 -8
- package/src/charts/private/grid-control/grid-control.tsx +0 -26
- package/src/charts/private/grid-control/index.ts +0 -1
- package/src/charts/private/grid-control/test/grid-control.test.tsx +0 -56
- 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/
|
|
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/
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
850
|
+
stroke: "var(--a8c-charts-color-tick, #dbdbdb)",
|
|
774
851
|
strokeWidth: 1
|
|
775
852
|
},
|
|
776
853
|
xAxisLineStyles: {
|
|
777
|
-
stroke: "var(--a8c-charts-color-axis,
|
|
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,
|
|
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
|
|
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,
|
|
795
|
-
backgroundFill: "var(--a8c-charts-color-
|
|
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,
|
|
874
|
+
connector: { stroke: "var(--a8c-charts-color-annotation, #1e1e1e)" },
|
|
798
875
|
circleSubject: {
|
|
799
876
|
stroke: "transparent",
|
|
800
|
-
fill: "var(--a8c-charts-color-annotation,
|
|
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,
|
|
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,
|
|
811
|
-
"var(--a8c-charts-color-trend-neutral,
|
|
812
|
-
"var(--a8c-charts-color-trend-up,
|
|
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,
|
|
817
|
-
positiveChangeColor: "var(--a8c-charts-color-trend-up,
|
|
818
|
-
negativeChangeColor: "var(--a8c-charts-color-trend-down,
|
|
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
|
-
|
|
851
|
-
|
|
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
|
|
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
|
-
|
|
948
|
-
|
|
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:
|
|
993
|
-
|
|
994
|
-
|
|
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
|
-
}, [
|
|
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-
|
|
1539
|
+
//#region src/hooks/use-legend-visibility-data.ts
|
|
1354
1540
|
/**
|
|
1355
|
-
* Custom hook to filter and recalculate chart data
|
|
1541
|
+
* Custom hook to filter and recalculate chart data based on series visibility.
|
|
1356
1542
|
*
|
|
1357
|
-
*
|
|
1358
|
-
* 1. Filters data to show only visible series
|
|
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 } =
|
|
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
|
|
1386
|
-
* @param params.data
|
|
1387
|
-
* @param params.chartId
|
|
1388
|
-
* @param params.
|
|
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
|
|
1576
|
+
const useLegendVisibilityData = ({ data, chartId, isSeriesVisible }) => {
|
|
1393
1577
|
const visibleData = useMemo(() => {
|
|
1394
|
-
if (!chartId
|
|
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
|
|
1412
|
-
}, [
|
|
1594
|
+
return visibleData.length === 0 && data.length > 0;
|
|
1595
|
+
}, [visibleData, data]),
|
|
1413
1596
|
legendData: useMemo(() => {
|
|
1414
|
-
if (!
|
|
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 (
|
|
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" :
|
|
1817
|
+
role: interactive ? "button" : "listitem",
|
|
1626
1818
|
tabIndex: interactive ? 0 : void 0,
|
|
1627
1819
|
"aria-pressed": interactive ? visible : void 0,
|
|
1628
|
-
"aria-label":
|
|
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
|
|
1691
|
-
const contextChartId = 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
|
-
|
|
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:
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
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 } =
|
|
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
|
|
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:
|
|
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 (
|
|
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(
|
|
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:
|
|
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
|
|
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:
|
|
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 || !
|
|
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
|
|
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(
|
|
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:
|
|
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
|
|
4482
|
-
const isSeriesRendered = useCallback((series) =>
|
|
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(
|
|
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:
|
|
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__ */
|
|
5481
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Stack, {
|
|
5233
5482
|
direction: "column",
|
|
5234
5483
|
gap: "xl",
|
|
5235
|
-
ref:
|
|
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:
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
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
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
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
|
-
}
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
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,
|
|
5501
|
-
const defaultFillColorHex = normalizeColorToHex(featureFillColor,
|
|
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 (
|
|
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,
|
|
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 =
|
|
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
|
|
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 (!
|
|
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 &&
|
|
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
|
-
|
|
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(
|
|
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 (
|
|
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 (
|
|
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(
|
|
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(
|
|
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:
|
|
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 } =
|
|
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(
|
|
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:
|
|
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 } =
|
|
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(
|
|
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:
|
|
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
|