@sproutsocial/seeds-react-data-viz 0.3.1 → 0.4.1
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/README.md +2 -0
- package/dist/esm/index.js +511 -85
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +146 -19
- package/dist/index.d.ts +146 -19
- package/dist/index.js +518 -85
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -51,18 +51,25 @@ __export(index_exports, {
|
|
|
51
51
|
LineChart: () => LineChart,
|
|
52
52
|
NetworkColorBox: () => NetworkColorBox,
|
|
53
53
|
TIME_SERIES_CHART_HEIGHT: () => TIME_SERIES_CHART_HEIGHT,
|
|
54
|
+
VERTICAL_BAR_CHART_DEFAULT_SERIES_LIMIT: () => VERTICAL_BAR_CHART_DEFAULT_SERIES_LIMIT,
|
|
54
55
|
areaChartOptions: () => areaChartOptions,
|
|
55
56
|
areaChartStyles: () => areaChartStyles,
|
|
56
57
|
baseChartOptions: () => baseChartOptions,
|
|
57
58
|
baseChartStyles: () => baseChartStyles,
|
|
59
|
+
columnChartOptions: () => columnChartOptions,
|
|
58
60
|
donutChartOptions: () => donutChartOptions,
|
|
59
61
|
donutChartStyles: () => donutChartStyles,
|
|
60
62
|
generateChartTooltipPortalId: () => generateChartTooltipPortalId,
|
|
61
63
|
getDatavizColor: () => getDatavizColor,
|
|
62
64
|
getDatavizColorWithAlpha: () => getDatavizColorWithAlpha,
|
|
63
65
|
getDatavizOpacity: () => getDatavizOpacity,
|
|
66
|
+
getStorybookCategoricalData: () => getStorybookCategoricalData,
|
|
67
|
+
getStorybookSparseTimelineData: () => getStorybookSparseTimelineData,
|
|
68
|
+
isCategoricalHourData: () => isCategoricalHourData,
|
|
69
|
+
isHourlyTimeData: () => isHourlyTimeData,
|
|
64
70
|
lineChartOptions: () => lineChartOptions,
|
|
65
71
|
lineChartStyles: () => lineChartStyles,
|
|
72
|
+
timeSeriesChartOptions: () => timeSeriesChartOptions,
|
|
66
73
|
timeSeriesChartStyles: () => timeSeriesChartStyles,
|
|
67
74
|
transformDataToSeries: () => transformDataToSeries,
|
|
68
75
|
transformTimeSeriesTooltipData: () => transformTimeSeriesTooltipData,
|
|
@@ -611,7 +618,12 @@ var ChartXAnnotationMarkerPortal = (0, import_react14.memo)(
|
|
|
611
618
|
);
|
|
612
619
|
|
|
613
620
|
// src/helpers/transformDataToSeries.ts
|
|
614
|
-
var transformDataToSeries = ({
|
|
621
|
+
var transformDataToSeries = ({
|
|
622
|
+
data
|
|
623
|
+
}, type) => {
|
|
624
|
+
const hasCategoricalData = data.some(
|
|
625
|
+
(series) => series.points.some((point) => typeof point.x === "string")
|
|
626
|
+
);
|
|
615
627
|
return data.map((dataItem, dataIndex) => {
|
|
616
628
|
const points = dataItem.points || [];
|
|
617
629
|
const dataPoints = points.map((point, pointsIndex) => {
|
|
@@ -628,12 +640,14 @@ var transformDataToSeries = ({ data }, type) => {
|
|
|
628
640
|
enableMarker = true;
|
|
629
641
|
}
|
|
630
642
|
return {
|
|
631
|
-
x: point.x,
|
|
643
|
+
x: hasCategoricalData ? pointsIndex : point.x,
|
|
632
644
|
y: point.y,
|
|
633
645
|
marker: {
|
|
634
646
|
enabled: enableMarker ? enableMarker : void 0,
|
|
635
647
|
symbol: enableMarker ? "circle" : void 0
|
|
636
|
-
}
|
|
648
|
+
},
|
|
649
|
+
// For categorical data, store the original category name
|
|
650
|
+
...hasCategoricalData && { name: point.x }
|
|
637
651
|
};
|
|
638
652
|
});
|
|
639
653
|
return {
|
|
@@ -663,6 +677,42 @@ var transformTimeSeriesTooltipData = ({
|
|
|
663
677
|
});
|
|
664
678
|
};
|
|
665
679
|
|
|
680
|
+
// src/helpers/yAxisLabelFormatter.ts
|
|
681
|
+
var import_seeds_react_duration2 = require("@sproutsocial/seeds-react-duration");
|
|
682
|
+
var import_seeds_react_numeral2 = require("@sproutsocial/seeds-react-numeral");
|
|
683
|
+
var yAxisLabelFormatter = ({
|
|
684
|
+
numberLocale,
|
|
685
|
+
textLocale,
|
|
686
|
+
tickPositions,
|
|
687
|
+
value,
|
|
688
|
+
currency = "USD",
|
|
689
|
+
numberFormat = "decimal"
|
|
690
|
+
}) => {
|
|
691
|
+
const numberValue = Number(value);
|
|
692
|
+
if (numberValue === 0) {
|
|
693
|
+
return (0, import_seeds_react_numeral2.formatNumeral)({
|
|
694
|
+
locale: numberLocale,
|
|
695
|
+
number: numberValue
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
if (numberFormat === "duration") {
|
|
699
|
+
return (0, import_seeds_react_duration2.formatDuration)({
|
|
700
|
+
display: "narrow",
|
|
701
|
+
locale: textLocale,
|
|
702
|
+
milliseconds: numberValue
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
const maxValue = tickPositions && tickPositions.length > 0 ? tickPositions[tickPositions.length - 1] : void 0;
|
|
706
|
+
const abbreviate = typeof maxValue === "number" && maxValue > 9999 ? 1e3 : true;
|
|
707
|
+
return (0, import_seeds_react_numeral2.formatNumeral)({
|
|
708
|
+
abbreviate,
|
|
709
|
+
currency,
|
|
710
|
+
format: numberFormat,
|
|
711
|
+
locale: numberLocale,
|
|
712
|
+
number: numberValue
|
|
713
|
+
});
|
|
714
|
+
};
|
|
715
|
+
|
|
666
716
|
// src/helpers/xAxisLabelFormatter.ts
|
|
667
717
|
var xAxisLabelFormatter = ({
|
|
668
718
|
textLocale,
|
|
@@ -672,6 +722,9 @@ var xAxisLabelFormatter = ({
|
|
|
672
722
|
// optional
|
|
673
723
|
timeFormat = "12"
|
|
674
724
|
}) => {
|
|
725
|
+
if (typeof value === "string") {
|
|
726
|
+
return `<span>${value}</span>`;
|
|
727
|
+
}
|
|
675
728
|
const tickIndex = tickPositions.indexOf(value);
|
|
676
729
|
const isFirst = tickIndex === 0;
|
|
677
730
|
const previousValue = tickPositions[tickIndex - 1];
|
|
@@ -717,39 +770,227 @@ var xAxisLabelFormatter = ({
|
|
|
717
770
|
return `<span>${firstPart}</span>${secondPart ? `<span>${secondPart}</span>` : ""}`;
|
|
718
771
|
};
|
|
719
772
|
|
|
720
|
-
// src/helpers/
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
773
|
+
// src/helpers/isHourlyTimeData.ts
|
|
774
|
+
function isHourlyTimeData(data) {
|
|
775
|
+
if (!data.length) return false;
|
|
776
|
+
const xVals = data.flatMap((series) => series.points.map((p) => p.x));
|
|
777
|
+
if (!xVals.length) return false;
|
|
778
|
+
if (xVals.some((x) => typeof x === "string")) return false;
|
|
779
|
+
const dates = xVals.map((x) => {
|
|
780
|
+
const d = new Date(x);
|
|
781
|
+
return `${d.getUTCFullYear()}-${d.getUTCMonth()}-${d.getUTCDate()}`;
|
|
782
|
+
});
|
|
783
|
+
const uniqueDates = new Set(dates);
|
|
784
|
+
if (uniqueDates.size !== 1) return false;
|
|
785
|
+
return xVals.every((x) => {
|
|
786
|
+
const d = new Date(x);
|
|
787
|
+
const hour = d.getUTCHours();
|
|
788
|
+
const minutes = d.getUTCMinutes();
|
|
789
|
+
const seconds = d.getUTCSeconds();
|
|
790
|
+
return hour >= 0 && hour <= 23 && minutes === 0 && seconds === 0;
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// src/helpers/isCategoricalHourData.ts
|
|
795
|
+
function isCategoricalHourData(data) {
|
|
796
|
+
if (!data.length) return false;
|
|
797
|
+
const xVals = data.flatMap((series) => series.points.map((p) => p.x));
|
|
798
|
+
if (!xVals.length) return false;
|
|
799
|
+
if (xVals.some((x) => typeof x !== "string")) return false;
|
|
800
|
+
const hour12Pattern = /^\d{1,2} (AM|PM)$/;
|
|
801
|
+
const hour24Pattern = /^([01]?\d|2[0-3]):([0-5]\d)$/;
|
|
802
|
+
const stringValues = xVals;
|
|
803
|
+
const allMatch12Hour = stringValues.every((x) => hour12Pattern.test(x));
|
|
804
|
+
const allMatch24Hour = stringValues.every((x) => hour24Pattern.test(x));
|
|
805
|
+
return allMatch12Hour || allMatch24Hour;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// src/helpers/getStorybookRandomColor.ts
|
|
809
|
+
var getStorybookRandomColor = () => {
|
|
810
|
+
const letters = "0123456789ABCDEF";
|
|
811
|
+
let color = "#";
|
|
812
|
+
for (let i = 0; i < 6; i++) {
|
|
813
|
+
color += letters[Math.floor(Math.random() * 16)];
|
|
744
814
|
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
815
|
+
return color;
|
|
816
|
+
};
|
|
817
|
+
|
|
818
|
+
// src/helpers/getStorybookCategoricalData.ts
|
|
819
|
+
var getStorybookCategoricalData = ({
|
|
820
|
+
showNulls,
|
|
821
|
+
showNegativeValues,
|
|
822
|
+
numberOfSeries,
|
|
823
|
+
yAxisMax,
|
|
824
|
+
showCustomColors,
|
|
825
|
+
showDashedLines,
|
|
826
|
+
categoryType
|
|
827
|
+
}) => {
|
|
828
|
+
const categoryOptions = {
|
|
829
|
+
hours: [
|
|
830
|
+
"12 AM",
|
|
831
|
+
"1 AM",
|
|
832
|
+
"2 AM",
|
|
833
|
+
"3 AM",
|
|
834
|
+
"4 AM",
|
|
835
|
+
"5 AM",
|
|
836
|
+
"6 AM",
|
|
837
|
+
"7 AM",
|
|
838
|
+
"8 AM",
|
|
839
|
+
"9 AM",
|
|
840
|
+
"10 AM",
|
|
841
|
+
"11 AM",
|
|
842
|
+
"12 PM",
|
|
843
|
+
"1 PM",
|
|
844
|
+
"2 PM",
|
|
845
|
+
"3 PM",
|
|
846
|
+
"4 PM",
|
|
847
|
+
"5 PM",
|
|
848
|
+
"6 PM",
|
|
849
|
+
"7 PM",
|
|
850
|
+
"8 PM",
|
|
851
|
+
"9 PM",
|
|
852
|
+
"10 PM",
|
|
853
|
+
"11 PM"
|
|
854
|
+
],
|
|
855
|
+
hours24: [
|
|
856
|
+
"00:00",
|
|
857
|
+
"01:00",
|
|
858
|
+
"02:00",
|
|
859
|
+
"03:00",
|
|
860
|
+
"04:00",
|
|
861
|
+
"05:00",
|
|
862
|
+
"06:00",
|
|
863
|
+
"07:00",
|
|
864
|
+
"08:00",
|
|
865
|
+
"09:00",
|
|
866
|
+
"10:00",
|
|
867
|
+
"11:00",
|
|
868
|
+
"12:00",
|
|
869
|
+
"13:00",
|
|
870
|
+
"14:00",
|
|
871
|
+
"15:00",
|
|
872
|
+
"16:00",
|
|
873
|
+
"17:00",
|
|
874
|
+
"18:00",
|
|
875
|
+
"19:00",
|
|
876
|
+
"20:00",
|
|
877
|
+
"21:00",
|
|
878
|
+
"22:00",
|
|
879
|
+
"23:00"
|
|
880
|
+
],
|
|
881
|
+
days: [
|
|
882
|
+
"Monday",
|
|
883
|
+
"Tuesday",
|
|
884
|
+
"Wednesday",
|
|
885
|
+
"Thursday",
|
|
886
|
+
"Friday",
|
|
887
|
+
"Saturday",
|
|
888
|
+
"Sunday"
|
|
889
|
+
],
|
|
890
|
+
months: [
|
|
891
|
+
"January",
|
|
892
|
+
"February",
|
|
893
|
+
"March",
|
|
894
|
+
"April",
|
|
895
|
+
"May",
|
|
896
|
+
"June",
|
|
897
|
+
"July",
|
|
898
|
+
"August",
|
|
899
|
+
"September",
|
|
900
|
+
"October",
|
|
901
|
+
"November",
|
|
902
|
+
"December"
|
|
903
|
+
],
|
|
904
|
+
custom: [
|
|
905
|
+
"Category A",
|
|
906
|
+
"Category B",
|
|
907
|
+
"Category C",
|
|
908
|
+
"Category D",
|
|
909
|
+
"Category E"
|
|
910
|
+
]
|
|
911
|
+
};
|
|
912
|
+
const categories = categoryOptions[categoryType];
|
|
913
|
+
const numberOfPoints = categories.length;
|
|
914
|
+
return [...Array(numberOfSeries).keys()].map((seriesIndex) => {
|
|
915
|
+
let nullsArray = [];
|
|
916
|
+
if (showNulls) {
|
|
917
|
+
const nullsArrayLength = Math.floor(numberOfPoints / 5);
|
|
918
|
+
nullsArray = [...Array(nullsArrayLength)].map(
|
|
919
|
+
() => Math.floor(Math.random() * numberOfPoints)
|
|
920
|
+
);
|
|
921
|
+
}
|
|
922
|
+
return {
|
|
923
|
+
points: categories.map((category, pointIndex) => {
|
|
924
|
+
const showNull = nullsArray && nullsArray.length > 0 ? nullsArray.includes(pointIndex) : false;
|
|
925
|
+
const randomValue = Math.random();
|
|
926
|
+
const positiveOrNegativeYAxisMax = showNegativeValues ? randomValue < 0.5 ? -yAxisMax : yAxisMax : yAxisMax;
|
|
927
|
+
return {
|
|
928
|
+
x: category,
|
|
929
|
+
y: showNull ? null : Math.floor(randomValue * positiveOrNegativeYAxisMax)
|
|
930
|
+
};
|
|
931
|
+
}),
|
|
932
|
+
name: `Series ${seriesIndex + 1}`,
|
|
933
|
+
styles: {
|
|
934
|
+
color: showCustomColors ? getStorybookRandomColor() : void 0,
|
|
935
|
+
pattern: showDashedLines ? "dashed" : "solid"
|
|
936
|
+
}
|
|
937
|
+
};
|
|
938
|
+
});
|
|
939
|
+
};
|
|
940
|
+
|
|
941
|
+
// src/helpers/getStorybookSparseTimelineData.ts
|
|
942
|
+
var getStorybookSparseTimelineData = ({
|
|
943
|
+
showNulls,
|
|
944
|
+
showNegativeValues,
|
|
945
|
+
numberOfSeries,
|
|
946
|
+
yAxisMax,
|
|
947
|
+
showCustomColors,
|
|
948
|
+
showDashedLines,
|
|
949
|
+
numberOfPoints = 5,
|
|
950
|
+
timeSpanHours = 24
|
|
951
|
+
}) => {
|
|
952
|
+
const seriesNames = [
|
|
953
|
+
"Posts Published",
|
|
954
|
+
"Comments",
|
|
955
|
+
"Likes",
|
|
956
|
+
"Shares",
|
|
957
|
+
"Clicks",
|
|
958
|
+
"Views",
|
|
959
|
+
"Saves",
|
|
960
|
+
"Reposts",
|
|
961
|
+
"Mentions",
|
|
962
|
+
"Reactions"
|
|
963
|
+
];
|
|
964
|
+
const baseDate = /* @__PURE__ */ new Date("2024-01-01T00:00:00Z");
|
|
965
|
+
const timeSpanMs = timeSpanHours * 60 * 60 * 1e3;
|
|
966
|
+
return [...Array(numberOfSeries).keys()].map((seriesIndex) => {
|
|
967
|
+
let nullsArray = [];
|
|
968
|
+
if (showNulls) {
|
|
969
|
+
const nullsArrayLength = Math.floor(numberOfPoints / 5);
|
|
970
|
+
nullsArray = [...Array(nullsArrayLength)].map(
|
|
971
|
+
() => Math.floor(Math.random() * numberOfPoints)
|
|
972
|
+
);
|
|
973
|
+
}
|
|
974
|
+
const timestamps = [...Array(numberOfPoints)].map(() => {
|
|
975
|
+
const randomOffset = Math.random() * timeSpanMs;
|
|
976
|
+
return baseDate.getTime() + randomOffset;
|
|
977
|
+
}).sort((a, b) => a - b);
|
|
978
|
+
return {
|
|
979
|
+
points: timestamps.map((timestamp, pointIndex) => {
|
|
980
|
+
const showNull = nullsArray && nullsArray.length > 0 ? nullsArray.includes(pointIndex) : false;
|
|
981
|
+
const randomValue = Math.random();
|
|
982
|
+
const positiveOrNegativeYAxisMax = showNegativeValues ? randomValue < 0.5 ? -yAxisMax : yAxisMax : yAxisMax;
|
|
983
|
+
return {
|
|
984
|
+
x: timestamp,
|
|
985
|
+
y: showNull ? null : Math.floor(randomValue * positiveOrNegativeYAxisMax)
|
|
986
|
+
};
|
|
987
|
+
}),
|
|
988
|
+
name: seriesNames[seriesIndex] || `Series ${seriesIndex + 1}`,
|
|
989
|
+
styles: {
|
|
990
|
+
color: showCustomColors ? getStorybookRandomColor() : void 0,
|
|
991
|
+
pattern: showDashedLines ? "dashed" : "solid"
|
|
992
|
+
}
|
|
993
|
+
};
|
|
753
994
|
});
|
|
754
995
|
};
|
|
755
996
|
|
|
@@ -839,7 +1080,20 @@ var timeSeriesChartOptions = import_lodash.default.merge({}, baseChartOptions, {
|
|
|
839
1080
|
softMin: 0,
|
|
840
1081
|
title: {
|
|
841
1082
|
text: void 0
|
|
842
|
-
}
|
|
1083
|
+
},
|
|
1084
|
+
plotLines: [
|
|
1085
|
+
/* Adds a custom plotLine at y=0 to represent the chart baseline.
|
|
1086
|
+
This approach allows full control over the line's appearance (e.g., color, z-index),
|
|
1087
|
+
unlike relying on the default xAxis line, which always renders at the bottom of the chart
|
|
1088
|
+
even when y=0 appears elsewhere (e.g., with negative values).
|
|
1089
|
+
*/
|
|
1090
|
+
{
|
|
1091
|
+
className: "y-axis-zero-line",
|
|
1092
|
+
value: 0,
|
|
1093
|
+
zIndex: 3
|
|
1094
|
+
// ensures the line appears over the default y=0 line, which we can't seleect as specifically
|
|
1095
|
+
}
|
|
1096
|
+
]
|
|
843
1097
|
}
|
|
844
1098
|
});
|
|
845
1099
|
var lineChartOptions = import_lodash.default.merge({}, timeSeriesChartOptions, {
|
|
@@ -853,6 +1107,30 @@ var areaChartOptions = import_lodash.default.merge({}, timeSeriesChartOptions, {
|
|
|
853
1107
|
}
|
|
854
1108
|
}
|
|
855
1109
|
});
|
|
1110
|
+
var columnChartOptions = import_lodash.default.merge({}, timeSeriesChartOptions, {
|
|
1111
|
+
plotOptions: {
|
|
1112
|
+
column: {
|
|
1113
|
+
stacking: "normal",
|
|
1114
|
+
pointPadding: 0.25,
|
|
1115
|
+
groupPadding: 0.25,
|
|
1116
|
+
borderRadius: 4
|
|
1117
|
+
}
|
|
1118
|
+
},
|
|
1119
|
+
xAxis: {
|
|
1120
|
+
crosshair: false
|
|
1121
|
+
},
|
|
1122
|
+
yAxis: {
|
|
1123
|
+
plotLines: [
|
|
1124
|
+
{
|
|
1125
|
+
// For stacked column charts with visible borders (e.g., white for contrast),
|
|
1126
|
+
// we raise the zIndex of the y=0 plotLine to ensure it remains visible
|
|
1127
|
+
// and isn't visually covered by overlapping column borders.
|
|
1128
|
+
zIndex: 5
|
|
1129
|
+
}
|
|
1130
|
+
]
|
|
1131
|
+
}
|
|
1132
|
+
});
|
|
1133
|
+
var VERTICAL_BAR_CHART_DEFAULT_SERIES_LIMIT = 10;
|
|
856
1134
|
var DONUT_CHART_HALO_SIZE = 10;
|
|
857
1135
|
var DONUT_CHART_HEIGHT = 250 + DONUT_CHART_HALO_SIZE * 2;
|
|
858
1136
|
var DONUT_CHART_WIDTH = DONUT_CHART_HEIGHT;
|
|
@@ -887,7 +1165,8 @@ var useTimeSeriesChartOptions = ({
|
|
|
887
1165
|
numberFormat = "decimal",
|
|
888
1166
|
yAxisLabelFormatter: yAxisLabelFormatter2,
|
|
889
1167
|
onClick,
|
|
890
|
-
timeFormat = "12"
|
|
1168
|
+
timeFormat = "12",
|
|
1169
|
+
xAxisLabelFormatter: xAxisLabelFormatter2
|
|
891
1170
|
}) => {
|
|
892
1171
|
const [chart, setChart] = (0, import_react15.useState)(null);
|
|
893
1172
|
const callback = (0, import_react15.useCallback)((chartInstance) => {
|
|
@@ -921,7 +1200,24 @@ var useTimeSeriesChartOptions = ({
|
|
|
921
1200
|
}
|
|
922
1201
|
};
|
|
923
1202
|
const chartMarginTop = xAnnotations ? 24 : null;
|
|
924
|
-
const
|
|
1203
|
+
const getBaseChartOptions = (type) => {
|
|
1204
|
+
switch (type) {
|
|
1205
|
+
case "areaspline":
|
|
1206
|
+
return areaChartOptions;
|
|
1207
|
+
case "spline":
|
|
1208
|
+
return lineChartOptions;
|
|
1209
|
+
case "column":
|
|
1210
|
+
return columnChartOptions;
|
|
1211
|
+
default:
|
|
1212
|
+
return lineChartOptions;
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
const baseChartOptions2 = getBaseChartOptions(seriesType);
|
|
1216
|
+
const hasCategoricalData = data.some(
|
|
1217
|
+
(series) => series.points.some((point) => typeof point.x === "string")
|
|
1218
|
+
);
|
|
1219
|
+
const categories = hasCategoricalData ? data[0]?.points.map((point) => point.x) || [] : [];
|
|
1220
|
+
const hasSparseTimelineData = !hasCategoricalData && seriesType === "column";
|
|
925
1221
|
const options = (0, import_react15.useMemo)(() => {
|
|
926
1222
|
return (0, import_lodash2.merge)({}, baseChartOptions2, {
|
|
927
1223
|
accessibility: {
|
|
@@ -962,6 +1258,61 @@ var useTimeSeriesChartOptions = ({
|
|
|
962
1258
|
return onClick({ x: event.point.x });
|
|
963
1259
|
} : void 0
|
|
964
1260
|
}
|
|
1261
|
+
},
|
|
1262
|
+
column: {
|
|
1263
|
+
// For sparse timeline data, set explicit point width to make columns wider
|
|
1264
|
+
...hasSparseTimelineData && {
|
|
1265
|
+
pointWidth: 20
|
|
1266
|
+
// Fixed width in pixels for sparse timeline data
|
|
1267
|
+
},
|
|
1268
|
+
point: {
|
|
1269
|
+
events: {
|
|
1270
|
+
/*
|
|
1271
|
+
Custom hover behavior for multi-series column charts.
|
|
1272
|
+
|
|
1273
|
+
In multi-series column charts, multiple columns
|
|
1274
|
+
can share the same x-axis position (stacked or grouped). When hovering
|
|
1275
|
+
over one column, we want ALL columns at that x-position to highlight
|
|
1276
|
+
together for better visual feedback. Simple CSS :hover only affects the
|
|
1277
|
+
individual element being hovered, not related columns at the same position.
|
|
1278
|
+
|
|
1279
|
+
This custom behavior ensures that when you hover over any column at a
|
|
1280
|
+
specific x-position, all columns at that same position get the "column-hover"
|
|
1281
|
+
class, creating a unified highlight effect across all series.
|
|
1282
|
+
*/
|
|
1283
|
+
mouseOver: function() {
|
|
1284
|
+
const x = this.x;
|
|
1285
|
+
if (this.series && this.series.chart && this.series.chart.series) {
|
|
1286
|
+
this.series.chart.series.forEach((series) => {
|
|
1287
|
+
if (series.type === "column") {
|
|
1288
|
+
series.data.forEach((point) => {
|
|
1289
|
+
if (point.x === x) {
|
|
1290
|
+
const el = point.graphic && point.graphic.element;
|
|
1291
|
+
if (el) {
|
|
1292
|
+
el.classList.add("column-hover");
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
},
|
|
1300
|
+
mouseOut: function() {
|
|
1301
|
+
if (this.series && this.series.chart && this.series.chart.series) {
|
|
1302
|
+
this.series.chart.series.forEach((series) => {
|
|
1303
|
+
if (series.type === "column") {
|
|
1304
|
+
series.data.forEach((point) => {
|
|
1305
|
+
const el = point.graphic && point.graphic.element;
|
|
1306
|
+
if (el) {
|
|
1307
|
+
el.classList.remove("column-hover");
|
|
1308
|
+
}
|
|
1309
|
+
});
|
|
1310
|
+
}
|
|
1311
|
+
});
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
965
1316
|
}
|
|
966
1317
|
},
|
|
967
1318
|
series: transformDataToSeries({ data }, seriesType),
|
|
@@ -971,14 +1322,37 @@ var useTimeSeriesChartOptions = ({
|
|
|
971
1322
|
xAxis: {
|
|
972
1323
|
labels: {
|
|
973
1324
|
formatter: function() {
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1325
|
+
const tickPositions = (this.axis.tickPositions || []).map(
|
|
1326
|
+
Number
|
|
1327
|
+
);
|
|
1328
|
+
const value = this.value;
|
|
1329
|
+
const unitName = this.tickPositionInfo?.unitName;
|
|
1330
|
+
if (typeof xAxisLabelFormatter2 === "function") {
|
|
1331
|
+
return xAxisLabelFormatter2({
|
|
1332
|
+
textLocale,
|
|
1333
|
+
tickPositions,
|
|
1334
|
+
timeFormat,
|
|
1335
|
+
unitName,
|
|
1336
|
+
value
|
|
1337
|
+
});
|
|
1338
|
+
}
|
|
1339
|
+
if (typeof xAxisLabelFormatterDefault === "function") {
|
|
1340
|
+
return xAxisLabelFormatterDefault({
|
|
1341
|
+
textLocale,
|
|
1342
|
+
tickPositions,
|
|
1343
|
+
timeFormat,
|
|
1344
|
+
unitName,
|
|
1345
|
+
value
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
return "";
|
|
981
1349
|
}
|
|
1350
|
+
},
|
|
1351
|
+
// Override xAxis type for categorical data
|
|
1352
|
+
...hasCategoricalData && {
|
|
1353
|
+
type: "category",
|
|
1354
|
+
categories,
|
|
1355
|
+
crosshair: false
|
|
982
1356
|
}
|
|
983
1357
|
},
|
|
984
1358
|
yAxis: {
|
|
@@ -1001,8 +1375,11 @@ var useTimeSeriesChartOptions = ({
|
|
|
1001
1375
|
});
|
|
1002
1376
|
}, [
|
|
1003
1377
|
baseChartOptions2,
|
|
1378
|
+
categories,
|
|
1004
1379
|
currency,
|
|
1005
1380
|
data,
|
|
1381
|
+
hasCategoricalData,
|
|
1382
|
+
hasSparseTimelineData,
|
|
1006
1383
|
numberFormat,
|
|
1007
1384
|
numberLocale,
|
|
1008
1385
|
onClick,
|
|
@@ -1010,10 +1387,12 @@ var useTimeSeriesChartOptions = ({
|
|
|
1010
1387
|
textLocale,
|
|
1011
1388
|
timeFormat,
|
|
1012
1389
|
xAnnotations,
|
|
1013
|
-
yAxisLabelFormatter2
|
|
1390
|
+
yAxisLabelFormatter2,
|
|
1391
|
+
xAxisLabelFormatter2
|
|
1014
1392
|
]);
|
|
1015
1393
|
return { options, chart, callback };
|
|
1016
1394
|
};
|
|
1395
|
+
var xAxisLabelFormatterDefault = xAxisLabelFormatter;
|
|
1017
1396
|
|
|
1018
1397
|
// src/styles/chartStyles.ts
|
|
1019
1398
|
var import_styled_components7 = require("styled-components");
|
|
@@ -1032,6 +1411,8 @@ var GlobalChartStyleOverrides = import_styled_components7.createGlobalStyle`
|
|
|
1032
1411
|
}
|
|
1033
1412
|
`;
|
|
1034
1413
|
var baseChartStyles = import_styled_components7.css`
|
|
1414
|
+
--highcharts-background-color: ${({ theme: theme14 }) => theme14.colors.container.background.base};
|
|
1415
|
+
|
|
1035
1416
|
// set color variables and map to each series
|
|
1036
1417
|
${({ $colors }) => $colors.map((color, index) => {
|
|
1037
1418
|
const chartColor = color || import_seeds_react_theme7.theme.colors.DATAVIZ_COLORS_LIST[index];
|
|
@@ -1075,9 +1456,11 @@ var timeSeriesChartStyles = import_styled_components7.css`
|
|
|
1075
1456
|
.highcharts-grid-line {
|
|
1076
1457
|
stroke: ${({ theme: theme14 }) => theme14.colors.container.border.base};
|
|
1077
1458
|
}
|
|
1459
|
+
|
|
1078
1460
|
.highcharts-axis-line {
|
|
1079
1461
|
stroke: ${({ theme: theme14 }) => theme14.colors.container.border.base};
|
|
1080
1462
|
}
|
|
1463
|
+
|
|
1081
1464
|
.highcharts-tick {
|
|
1082
1465
|
stroke: none;
|
|
1083
1466
|
}
|
|
@@ -1118,6 +1501,10 @@ var timeSeriesChartStyles = import_styled_components7.css`
|
|
|
1118
1501
|
fill: transparent;
|
|
1119
1502
|
cursor: pointer;
|
|
1120
1503
|
}`}
|
|
1504
|
+
|
|
1505
|
+
path.highcharts-plot-line.y-axis-zero-line {
|
|
1506
|
+
stroke: ${({ theme: theme14 }) => theme14.colors.container.border.decorative.neutral};
|
|
1507
|
+
}
|
|
1121
1508
|
`;
|
|
1122
1509
|
var lineChartStyles = import_styled_components7.css`
|
|
1123
1510
|
${timeSeriesChartStyles}
|
|
@@ -1166,6 +1553,19 @@ var donutChartStyles = import_styled_components7.css`
|
|
|
1166
1553
|
.highcharts-point-hover {
|
|
1167
1554
|
fill-opacity: none;
|
|
1168
1555
|
}
|
|
1556
|
+
|
|
1557
|
+
// apply cursor pointer when click functionality is turned on
|
|
1558
|
+
${({ $hasOnClick }) => $hasOnClick && `
|
|
1559
|
+
.highcharts-series,
|
|
1560
|
+
.highcharts-point {
|
|
1561
|
+
cursor: pointer;
|
|
1562
|
+
}
|
|
1563
|
+
.highcharts-plot-background,
|
|
1564
|
+
.highcharts-crosshair,
|
|
1565
|
+
.highcharts-grid-line {
|
|
1566
|
+
fill: transparent;
|
|
1567
|
+
cursor: pointer;
|
|
1568
|
+
}`}
|
|
1169
1569
|
`;
|
|
1170
1570
|
|
|
1171
1571
|
// src/components/AreaChart/AreaChart.tsx
|
|
@@ -1308,6 +1708,7 @@ var DonutChartLegend = (0, import_react17.memo)(
|
|
|
1308
1708
|
var import_react18 = require("react");
|
|
1309
1709
|
var import_seeds_react_box10 = require("@sproutsocial/seeds-react-box");
|
|
1310
1710
|
var import_seeds_react_duration3 = require("@sproutsocial/seeds-react-duration");
|
|
1711
|
+
var import_seeds_react_icon2 = require("@sproutsocial/seeds-react-icon");
|
|
1311
1712
|
var import_seeds_react_numeral3 = require("@sproutsocial/seeds-react-numeral");
|
|
1312
1713
|
var import_seeds_react_text5 = require("@sproutsocial/seeds-react-text");
|
|
1313
1714
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
@@ -1321,7 +1722,9 @@ var DonutChartTooltip = (0, import_react18.memo)(
|
|
|
1321
1722
|
value,
|
|
1322
1723
|
currency,
|
|
1323
1724
|
icon,
|
|
1324
|
-
numberFormat
|
|
1725
|
+
numberFormat,
|
|
1726
|
+
onClick,
|
|
1727
|
+
tooltipClickLabel
|
|
1325
1728
|
}) {
|
|
1326
1729
|
const rows = [
|
|
1327
1730
|
{
|
|
@@ -1356,7 +1759,13 @@ var DonutChartTooltip = (0, import_react18.memo)(
|
|
|
1356
1759
|
]
|
|
1357
1760
|
}
|
|
1358
1761
|
];
|
|
1359
|
-
return /* @__PURE__ */ (0, import_jsx_runtime18.
|
|
1762
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(ChartTooltip, { children: [
|
|
1763
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ChartTooltipTable, { rows }),
|
|
1764
|
+
onClick && tooltipClickLabel ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ChartTooltipFooter, { children: typeof tooltipClickLabel === "string" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_seeds_react_box10.Box, { display: "flex", alignItems: "center", gap: 300, children: [
|
|
1765
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_seeds_react_icon2.Icon, { name: "hand-pointer-clicking-outline", color: "icon.base" }),
|
|
1766
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_seeds_react_text5.Text, { color: "text.subtext", fontSize: 200, children: tooltipClickLabel })
|
|
1767
|
+
] }) : tooltipClickLabel }) : null
|
|
1768
|
+
] });
|
|
1360
1769
|
}
|
|
1361
1770
|
);
|
|
1362
1771
|
|
|
@@ -1397,7 +1806,9 @@ var DonutChartWithData = (0, import_react19.memo)(
|
|
|
1397
1806
|
disableTooltips = false,
|
|
1398
1807
|
hideLegend = false,
|
|
1399
1808
|
numberFormat = "decimal",
|
|
1400
|
-
tooltip
|
|
1809
|
+
tooltip,
|
|
1810
|
+
onClick,
|
|
1811
|
+
tooltipClickLabel
|
|
1401
1812
|
}) {
|
|
1402
1813
|
const [options, setOptions] = (0, import_react19.useState)(donutChartOptions);
|
|
1403
1814
|
const [chart, setChart] = (0, import_react19.useState)(null);
|
|
@@ -1438,7 +1849,12 @@ var DonutChartWithData = (0, import_react19.memo)(
|
|
|
1438
1849
|
return {
|
|
1439
1850
|
name: item.name,
|
|
1440
1851
|
y: item.value,
|
|
1441
|
-
colorIndex: index
|
|
1852
|
+
colorIndex: index,
|
|
1853
|
+
events: onClick ? {
|
|
1854
|
+
click: function() {
|
|
1855
|
+
onClick({ x: item.name });
|
|
1856
|
+
}
|
|
1857
|
+
} : void 0
|
|
1442
1858
|
};
|
|
1443
1859
|
})
|
|
1444
1860
|
}
|
|
@@ -1453,40 +1869,50 @@ var DonutChartWithData = (0, import_react19.memo)(
|
|
|
1453
1869
|
);
|
|
1454
1870
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
1455
1871
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(GlobalChartStyleOverrides, {}),
|
|
1456
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
icon,
|
|
1477
|
-
name,
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1872
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
1873
|
+
StyledBox4,
|
|
1874
|
+
{
|
|
1875
|
+
$colors: colors,
|
|
1876
|
+
$hasOnClick: Boolean(onClick),
|
|
1877
|
+
bg: "container.background.base",
|
|
1878
|
+
children: [
|
|
1879
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1880
|
+
import_highcharts_react_official2.HighchartsReact,
|
|
1881
|
+
{
|
|
1882
|
+
highcharts: import_highcharts4.default,
|
|
1883
|
+
options,
|
|
1884
|
+
callback
|
|
1885
|
+
}
|
|
1886
|
+
),
|
|
1887
|
+
chart && !disableTooltips ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1888
|
+
ChartTooltipPortal,
|
|
1889
|
+
{
|
|
1890
|
+
chart,
|
|
1891
|
+
renderContent: (context) => {
|
|
1892
|
+
const { color, icon, name, percent, value } = transformDonutChartTooltipData({ context, data });
|
|
1893
|
+
return tooltip ? tooltip({ color, icon, name, percent, value }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1894
|
+
DonutChartTooltip,
|
|
1895
|
+
{
|
|
1896
|
+
color,
|
|
1897
|
+
currency,
|
|
1898
|
+
icon,
|
|
1899
|
+
name,
|
|
1900
|
+
numberFormat,
|
|
1901
|
+
numberLocale,
|
|
1902
|
+
percent,
|
|
1903
|
+
textLocale,
|
|
1904
|
+
value,
|
|
1905
|
+
onClick,
|
|
1906
|
+
tooltipClickLabel
|
|
1907
|
+
}
|
|
1908
|
+
);
|
|
1483
1909
|
}
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1910
|
+
}
|
|
1911
|
+
) : null,
|
|
1912
|
+
hideLegend ? null : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_seeds_react_box11.Box, { mt: 350, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DonutChartLegend, { data }) })
|
|
1913
|
+
]
|
|
1914
|
+
}
|
|
1915
|
+
)
|
|
1490
1916
|
] });
|
|
1491
1917
|
}
|
|
1492
1918
|
);
|
|
@@ -1611,7 +2037,7 @@ var LineChartLegend = (0, import_react21.memo)(
|
|
|
1611
2037
|
var import_react22 = require("react");
|
|
1612
2038
|
var import_seeds_react_box13 = require("@sproutsocial/seeds-react-box");
|
|
1613
2039
|
var import_seeds_react_duration5 = require("@sproutsocial/seeds-react-duration");
|
|
1614
|
-
var
|
|
2040
|
+
var import_seeds_react_icon3 = require("@sproutsocial/seeds-react-icon");
|
|
1615
2041
|
var import_seeds_react_numeral5 = require("@sproutsocial/seeds-react-numeral");
|
|
1616
2042
|
var import_seeds_react_text7 = require("@sproutsocial/seeds-react-text");
|
|
1617
2043
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
@@ -1657,7 +2083,7 @@ var LineChartTooltip = (0, import_react22.memo)(
|
|
|
1657
2083
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ChartTooltipTitle, { children: tooltipDateFormatter({ x }) }),
|
|
1658
2084
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ChartTooltipTable, { rows }),
|
|
1659
2085
|
onClick && tooltipClickLabel ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ChartTooltipFooter, { children: typeof tooltipClickLabel === "string" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_seeds_react_box13.Box, { display: "flex", alignItems: "center", gap: 300, children: [
|
|
1660
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2086
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_seeds_react_icon3.Icon, { name: "hand-pointer-clicking-outline", color: "icon.base" }),
|
|
1661
2087
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_seeds_react_text7.Text, { color: "text.subtext", fontSize: 200, children: tooltipClickLabel })
|
|
1662
2088
|
] }) : tooltipClickLabel }) : null
|
|
1663
2089
|
] });
|
|
@@ -1803,18 +2229,25 @@ var LineChartWithData = (0, import_react23.memo)(function LineChartWithData2({
|
|
|
1803
2229
|
LineChart,
|
|
1804
2230
|
NetworkColorBox,
|
|
1805
2231
|
TIME_SERIES_CHART_HEIGHT,
|
|
2232
|
+
VERTICAL_BAR_CHART_DEFAULT_SERIES_LIMIT,
|
|
1806
2233
|
areaChartOptions,
|
|
1807
2234
|
areaChartStyles,
|
|
1808
2235
|
baseChartOptions,
|
|
1809
2236
|
baseChartStyles,
|
|
2237
|
+
columnChartOptions,
|
|
1810
2238
|
donutChartOptions,
|
|
1811
2239
|
donutChartStyles,
|
|
1812
2240
|
generateChartTooltipPortalId,
|
|
1813
2241
|
getDatavizColor,
|
|
1814
2242
|
getDatavizColorWithAlpha,
|
|
1815
2243
|
getDatavizOpacity,
|
|
2244
|
+
getStorybookCategoricalData,
|
|
2245
|
+
getStorybookSparseTimelineData,
|
|
2246
|
+
isCategoricalHourData,
|
|
2247
|
+
isHourlyTimeData,
|
|
1816
2248
|
lineChartOptions,
|
|
1817
2249
|
lineChartStyles,
|
|
2250
|
+
timeSeriesChartOptions,
|
|
1818
2251
|
timeSeriesChartStyles,
|
|
1819
2252
|
transformDataToSeries,
|
|
1820
2253
|
transformTimeSeriesTooltipData,
|