@opendata-ai/openchart-core 7.2.3 → 7.3.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/dist/index.d.ts +60 -11
- package/dist/index.js +440 -132
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +8 -0
- package/src/labels/collision.ts +7 -1
- package/src/labels/index.ts +1 -0
- package/src/layout/__tests__/text-measure.test.ts +7 -8
- package/src/layout/index.ts +2 -0
- package/src/layout/text-measure.ts +331 -38
- package/src/responsive/index.ts +5 -0
- package/src/responsive/metrics.ts +37 -0
- package/src/theme/defaults.ts +2 -1
- package/src/types/index.ts +1 -0
- package/src/types/layout.ts +24 -0
package/dist/index.js
CHANGED
|
@@ -813,6 +813,433 @@ var DIVERGING_PALETTES = {
|
|
|
813
813
|
brownTeal: [...DIVERGING_BROWN_TEAL.stops]
|
|
814
814
|
};
|
|
815
815
|
|
|
816
|
+
// src/layout/text-measure.ts
|
|
817
|
+
var CHAR_WIDTHS_400 = {
|
|
818
|
+
" ": 0.278,
|
|
819
|
+
"!": 0.278,
|
|
820
|
+
'"': 0.355,
|
|
821
|
+
"#": 0.556,
|
|
822
|
+
$: 0.556,
|
|
823
|
+
"%": 0.889,
|
|
824
|
+
"&": 0.667,
|
|
825
|
+
"'": 0.191,
|
|
826
|
+
"(": 0.333,
|
|
827
|
+
")": 0.333,
|
|
828
|
+
"*": 0.389,
|
|
829
|
+
"+": 0.584,
|
|
830
|
+
",": 0.278,
|
|
831
|
+
"-": 0.333,
|
|
832
|
+
".": 0.278,
|
|
833
|
+
"/": 0.278,
|
|
834
|
+
"0": 0.556,
|
|
835
|
+
"1": 0.556,
|
|
836
|
+
"2": 0.556,
|
|
837
|
+
"3": 0.556,
|
|
838
|
+
"4": 0.556,
|
|
839
|
+
"5": 0.556,
|
|
840
|
+
"6": 0.556,
|
|
841
|
+
"7": 0.556,
|
|
842
|
+
"8": 0.556,
|
|
843
|
+
"9": 0.556,
|
|
844
|
+
":": 0.278,
|
|
845
|
+
";": 0.278,
|
|
846
|
+
"<": 0.584,
|
|
847
|
+
"=": 0.584,
|
|
848
|
+
">": 0.584,
|
|
849
|
+
"?": 0.556,
|
|
850
|
+
"@": 1.015,
|
|
851
|
+
A: 0.667,
|
|
852
|
+
B: 0.667,
|
|
853
|
+
C: 0.722,
|
|
854
|
+
D: 0.722,
|
|
855
|
+
E: 0.667,
|
|
856
|
+
F: 0.611,
|
|
857
|
+
G: 0.778,
|
|
858
|
+
H: 0.722,
|
|
859
|
+
I: 0.278,
|
|
860
|
+
J: 0.5,
|
|
861
|
+
K: 0.667,
|
|
862
|
+
L: 0.556,
|
|
863
|
+
M: 0.833,
|
|
864
|
+
N: 0.722,
|
|
865
|
+
O: 0.778,
|
|
866
|
+
P: 0.667,
|
|
867
|
+
Q: 0.778,
|
|
868
|
+
R: 0.722,
|
|
869
|
+
S: 0.667,
|
|
870
|
+
T: 0.611,
|
|
871
|
+
U: 0.722,
|
|
872
|
+
V: 0.667,
|
|
873
|
+
W: 0.944,
|
|
874
|
+
X: 0.667,
|
|
875
|
+
Y: 0.667,
|
|
876
|
+
Z: 0.611,
|
|
877
|
+
"[": 0.278,
|
|
878
|
+
"\\": 0.278,
|
|
879
|
+
"]": 0.278,
|
|
880
|
+
"^": 0.469,
|
|
881
|
+
_: 0.556,
|
|
882
|
+
"`": 0.333,
|
|
883
|
+
a: 0.556,
|
|
884
|
+
b: 0.556,
|
|
885
|
+
c: 0.5,
|
|
886
|
+
d: 0.556,
|
|
887
|
+
e: 0.556,
|
|
888
|
+
f: 0.278,
|
|
889
|
+
g: 0.556,
|
|
890
|
+
h: 0.556,
|
|
891
|
+
i: 0.222,
|
|
892
|
+
j: 0.222,
|
|
893
|
+
k: 0.5,
|
|
894
|
+
l: 0.222,
|
|
895
|
+
m: 0.833,
|
|
896
|
+
n: 0.556,
|
|
897
|
+
o: 0.556,
|
|
898
|
+
p: 0.556,
|
|
899
|
+
q: 0.556,
|
|
900
|
+
r: 0.333,
|
|
901
|
+
s: 0.5,
|
|
902
|
+
t: 0.278,
|
|
903
|
+
u: 0.556,
|
|
904
|
+
v: 0.5,
|
|
905
|
+
w: 0.722,
|
|
906
|
+
x: 0.5,
|
|
907
|
+
y: 0.5,
|
|
908
|
+
z: 0.5,
|
|
909
|
+
"{": 0.334,
|
|
910
|
+
"|": 0.26,
|
|
911
|
+
"}": 0.334,
|
|
912
|
+
"~": 0.584,
|
|
913
|
+
"\u20B9": 0.52,
|
|
914
|
+
"\u20A9": 1.022,
|
|
915
|
+
"\xA5": 0.556,
|
|
916
|
+
"\uFFE5": 1,
|
|
917
|
+
"\u20AC": 0.744,
|
|
918
|
+
"\xA3": 0.556,
|
|
919
|
+
"\xA2": 0.556,
|
|
920
|
+
"\xA7": 0.556,
|
|
921
|
+
"\xA9": 0.737,
|
|
922
|
+
"\xAE": 0.737,
|
|
923
|
+
"\u2122": 1,
|
|
924
|
+
"\xB0": 0.4,
|
|
925
|
+
"\u2013": 0.556,
|
|
926
|
+
"\u2014": 1,
|
|
927
|
+
"\u2018": 0.222,
|
|
928
|
+
"\u2019": 0.222,
|
|
929
|
+
"\u201C": 0.333,
|
|
930
|
+
"\u201D": 0.333,
|
|
931
|
+
"\u2026": 1,
|
|
932
|
+
"\xB1": 0.549,
|
|
933
|
+
"\xD7": 0.584,
|
|
934
|
+
"\xF7": 0.549
|
|
935
|
+
};
|
|
936
|
+
var AVG_CHAR_WIDTH_400 = 0.53;
|
|
937
|
+
var CHAR_WIDTHS_700 = {
|
|
938
|
+
" ": 0.278,
|
|
939
|
+
"!": 0.333,
|
|
940
|
+
'"': 0.474,
|
|
941
|
+
"#": 0.556,
|
|
942
|
+
$: 0.556,
|
|
943
|
+
"%": 0.889,
|
|
944
|
+
"&": 0.722,
|
|
945
|
+
"'": 0.238,
|
|
946
|
+
"(": 0.333,
|
|
947
|
+
")": 0.333,
|
|
948
|
+
"*": 0.389,
|
|
949
|
+
"+": 0.584,
|
|
950
|
+
",": 0.278,
|
|
951
|
+
"-": 0.333,
|
|
952
|
+
".": 0.278,
|
|
953
|
+
"/": 0.278,
|
|
954
|
+
"0": 0.556,
|
|
955
|
+
"1": 0.556,
|
|
956
|
+
"2": 0.556,
|
|
957
|
+
"3": 0.556,
|
|
958
|
+
"4": 0.556,
|
|
959
|
+
"5": 0.556,
|
|
960
|
+
"6": 0.556,
|
|
961
|
+
"7": 0.556,
|
|
962
|
+
"8": 0.556,
|
|
963
|
+
"9": 0.556,
|
|
964
|
+
":": 0.333,
|
|
965
|
+
";": 0.333,
|
|
966
|
+
"<": 0.584,
|
|
967
|
+
"=": 0.584,
|
|
968
|
+
">": 0.584,
|
|
969
|
+
"?": 0.611,
|
|
970
|
+
"@": 0.975,
|
|
971
|
+
A: 0.722,
|
|
972
|
+
B: 0.722,
|
|
973
|
+
C: 0.722,
|
|
974
|
+
D: 0.722,
|
|
975
|
+
E: 0.667,
|
|
976
|
+
F: 0.611,
|
|
977
|
+
G: 0.778,
|
|
978
|
+
H: 0.722,
|
|
979
|
+
I: 0.278,
|
|
980
|
+
J: 0.556,
|
|
981
|
+
K: 0.722,
|
|
982
|
+
L: 0.611,
|
|
983
|
+
M: 0.833,
|
|
984
|
+
N: 0.722,
|
|
985
|
+
O: 0.778,
|
|
986
|
+
P: 0.667,
|
|
987
|
+
Q: 0.778,
|
|
988
|
+
R: 0.722,
|
|
989
|
+
S: 0.667,
|
|
990
|
+
T: 0.611,
|
|
991
|
+
U: 0.722,
|
|
992
|
+
V: 0.667,
|
|
993
|
+
W: 0.944,
|
|
994
|
+
X: 0.667,
|
|
995
|
+
Y: 0.667,
|
|
996
|
+
Z: 0.611,
|
|
997
|
+
"[": 0.333,
|
|
998
|
+
"\\": 0.278,
|
|
999
|
+
"]": 0.333,
|
|
1000
|
+
"^": 0.584,
|
|
1001
|
+
_: 0.556,
|
|
1002
|
+
"`": 0.333,
|
|
1003
|
+
a: 0.556,
|
|
1004
|
+
b: 0.611,
|
|
1005
|
+
c: 0.556,
|
|
1006
|
+
d: 0.611,
|
|
1007
|
+
e: 0.556,
|
|
1008
|
+
f: 0.333,
|
|
1009
|
+
g: 0.611,
|
|
1010
|
+
h: 0.611,
|
|
1011
|
+
i: 0.278,
|
|
1012
|
+
j: 0.278,
|
|
1013
|
+
k: 0.556,
|
|
1014
|
+
l: 0.278,
|
|
1015
|
+
m: 0.889,
|
|
1016
|
+
n: 0.611,
|
|
1017
|
+
o: 0.611,
|
|
1018
|
+
p: 0.611,
|
|
1019
|
+
q: 0.611,
|
|
1020
|
+
r: 0.389,
|
|
1021
|
+
s: 0.556,
|
|
1022
|
+
t: 0.333,
|
|
1023
|
+
u: 0.611,
|
|
1024
|
+
v: 0.556,
|
|
1025
|
+
w: 0.778,
|
|
1026
|
+
x: 0.556,
|
|
1027
|
+
y: 0.556,
|
|
1028
|
+
z: 0.5,
|
|
1029
|
+
"{": 0.389,
|
|
1030
|
+
"|": 0.28,
|
|
1031
|
+
"}": 0.389,
|
|
1032
|
+
"~": 0.584,
|
|
1033
|
+
"\u20B9": 0.553,
|
|
1034
|
+
"\u20A9": 1.024,
|
|
1035
|
+
"\xA5": 0.556,
|
|
1036
|
+
"\uFFE5": 1,
|
|
1037
|
+
"\u20AC": 0.744,
|
|
1038
|
+
"\xA3": 0.556,
|
|
1039
|
+
"\xA2": 0.556,
|
|
1040
|
+
"\xA7": 0.556,
|
|
1041
|
+
"\xA9": 0.737,
|
|
1042
|
+
"\xAE": 0.737,
|
|
1043
|
+
"\u2122": 1,
|
|
1044
|
+
"\xB0": 0.4,
|
|
1045
|
+
"\u2013": 0.556,
|
|
1046
|
+
"\u2014": 1,
|
|
1047
|
+
"\u2018": 0.278,
|
|
1048
|
+
"\u2019": 0.278,
|
|
1049
|
+
"\u201C": 0.5,
|
|
1050
|
+
"\u201D": 0.5,
|
|
1051
|
+
"\u2026": 1,
|
|
1052
|
+
"\xB1": 0.549,
|
|
1053
|
+
"\xD7": 0.584,
|
|
1054
|
+
"\xF7": 0.549
|
|
1055
|
+
};
|
|
1056
|
+
var AVG_CHAR_WIDTH_700 = 0.554;
|
|
1057
|
+
var WEIGHT_ADJUSTMENT = {
|
|
1058
|
+
100: 0.9,
|
|
1059
|
+
200: 0.92,
|
|
1060
|
+
300: 0.95,
|
|
1061
|
+
400: 1,
|
|
1062
|
+
500: 1.02,
|
|
1063
|
+
600: 1.05,
|
|
1064
|
+
700: 1,
|
|
1065
|
+
// uses CHAR_WIDTHS_700 directly
|
|
1066
|
+
800: 1.1,
|
|
1067
|
+
900: 1.12
|
|
1068
|
+
};
|
|
1069
|
+
function resolveTable(fontWeight) {
|
|
1070
|
+
if (fontWeight >= 650) {
|
|
1071
|
+
return {
|
|
1072
|
+
table: CHAR_WIDTHS_700,
|
|
1073
|
+
avg: AVG_CHAR_WIDTH_700,
|
|
1074
|
+
scale: WEIGHT_ADJUSTMENT[fontWeight] ?? 1
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
return {
|
|
1078
|
+
table: CHAR_WIDTHS_400,
|
|
1079
|
+
avg: AVG_CHAR_WIDTH_400,
|
|
1080
|
+
scale: WEIGHT_ADJUSTMENT[fontWeight] ?? 1
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
function charWidthRatio(ch, table, avg) {
|
|
1084
|
+
const direct = table[ch];
|
|
1085
|
+
if (direct !== void 0) return direct;
|
|
1086
|
+
const code = ch.codePointAt(0) ?? 0;
|
|
1087
|
+
if (code >= 768 && code <= 879 || code >= 6832 && code <= 6911) return 0;
|
|
1088
|
+
if (code >= 4352 && code <= 4607 || code >= 11904 && code <= 40959 || code >= 44032 && code <= 55215 || code >= 63744 && code <= 64255 || code >= 65280 && code <= 65376)
|
|
1089
|
+
return 1;
|
|
1090
|
+
return avg;
|
|
1091
|
+
}
|
|
1092
|
+
function estimateCharWidth(fontSize, fontWeight = 400) {
|
|
1093
|
+
const { avg, scale } = resolveTable(fontWeight);
|
|
1094
|
+
return fontSize * avg * scale;
|
|
1095
|
+
}
|
|
1096
|
+
function estimateTextWidth(text, fontSize, fontWeight = 400) {
|
|
1097
|
+
const { table, avg, scale } = resolveTable(fontWeight);
|
|
1098
|
+
const measureLine = (line) => {
|
|
1099
|
+
let sum = 0;
|
|
1100
|
+
for (const ch of line) {
|
|
1101
|
+
sum += charWidthRatio(ch, table, avg);
|
|
1102
|
+
}
|
|
1103
|
+
return sum * fontSize * scale;
|
|
1104
|
+
};
|
|
1105
|
+
if (text.includes("\n")) {
|
|
1106
|
+
let maxWidth = 0;
|
|
1107
|
+
for (const line of text.split("\n")) {
|
|
1108
|
+
const w = measureLine(line);
|
|
1109
|
+
if (w > maxWidth) maxWidth = w;
|
|
1110
|
+
}
|
|
1111
|
+
return maxWidth;
|
|
1112
|
+
}
|
|
1113
|
+
return measureLine(text);
|
|
1114
|
+
}
|
|
1115
|
+
var BRAND_RESERVE_WIDTH = 130;
|
|
1116
|
+
var BRAND_FONT_SIZE = 12;
|
|
1117
|
+
var BRAND_MIN_WIDTH = 120;
|
|
1118
|
+
var COMPACT_WIDTH = 420;
|
|
1119
|
+
function estimateTextHeight(fontSize, lineCount = 1, lineHeight = 1.3) {
|
|
1120
|
+
return fontSize * lineHeight * lineCount;
|
|
1121
|
+
}
|
|
1122
|
+
var heuristicMeasure = (text, fontSize, fontWeight) => ({
|
|
1123
|
+
width: estimateTextWidth(text, fontSize, fontWeight),
|
|
1124
|
+
height: estimateTextHeight(fontSize)
|
|
1125
|
+
});
|
|
1126
|
+
function resolveMeasurer(measureText) {
|
|
1127
|
+
return measureText ?? heuristicMeasure;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
// src/responsive/breakpoints.ts
|
|
1131
|
+
var BREAKPOINT_COMPACT_MAX = 400;
|
|
1132
|
+
var BREAKPOINT_MEDIUM_MAX = 700;
|
|
1133
|
+
function getBreakpoint(width) {
|
|
1134
|
+
if (width < BREAKPOINT_COMPACT_MAX) return "compact";
|
|
1135
|
+
if (width <= BREAKPOINT_MEDIUM_MAX) return "medium";
|
|
1136
|
+
return "full";
|
|
1137
|
+
}
|
|
1138
|
+
var HEIGHT_CRAMPED_MAX = 200;
|
|
1139
|
+
var HEIGHT_SHORT_MAX = 350;
|
|
1140
|
+
function getHeightClass(height) {
|
|
1141
|
+
if (height < HEIGHT_CRAMPED_MAX) return "cramped";
|
|
1142
|
+
if (height <= HEIGHT_SHORT_MAX) return "short";
|
|
1143
|
+
return "normal";
|
|
1144
|
+
}
|
|
1145
|
+
function getWidthStrategy(breakpoint) {
|
|
1146
|
+
switch (breakpoint) {
|
|
1147
|
+
case "compact":
|
|
1148
|
+
return {
|
|
1149
|
+
labelMode: "none",
|
|
1150
|
+
legendPosition: "top",
|
|
1151
|
+
annotationPosition: "tooltip-only",
|
|
1152
|
+
axisLabelDensity: "minimal",
|
|
1153
|
+
chromeMode: "full",
|
|
1154
|
+
legendMaxHeight: -1
|
|
1155
|
+
};
|
|
1156
|
+
case "medium":
|
|
1157
|
+
return {
|
|
1158
|
+
labelMode: "important",
|
|
1159
|
+
legendPosition: "top",
|
|
1160
|
+
annotationPosition: "inline",
|
|
1161
|
+
axisLabelDensity: "reduced",
|
|
1162
|
+
chromeMode: "full",
|
|
1163
|
+
legendMaxHeight: -1
|
|
1164
|
+
};
|
|
1165
|
+
case "full":
|
|
1166
|
+
return {
|
|
1167
|
+
labelMode: "all",
|
|
1168
|
+
legendPosition: "right",
|
|
1169
|
+
annotationPosition: "inline",
|
|
1170
|
+
axisLabelDensity: "full",
|
|
1171
|
+
chromeMode: "full",
|
|
1172
|
+
legendMaxHeight: -1
|
|
1173
|
+
};
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
function applyHeightConstraints(strategy, heightClass) {
|
|
1177
|
+
if (heightClass === "normal") return strategy;
|
|
1178
|
+
if (heightClass === "cramped") {
|
|
1179
|
+
return {
|
|
1180
|
+
...strategy,
|
|
1181
|
+
chromeMode: "hidden",
|
|
1182
|
+
legendMaxHeight: 0,
|
|
1183
|
+
labelMode: "none",
|
|
1184
|
+
annotationPosition: "tooltip-only"
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
return {
|
|
1188
|
+
...strategy,
|
|
1189
|
+
chromeMode: "compact",
|
|
1190
|
+
legendMaxHeight: 0.15
|
|
1191
|
+
};
|
|
1192
|
+
}
|
|
1193
|
+
function getLayoutStrategy(breakpoint, heightClass = "normal") {
|
|
1194
|
+
const base = getWidthStrategy(breakpoint);
|
|
1195
|
+
return applyHeightConstraints(base, heightClass);
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
// src/responsive/metrics.ts
|
|
1199
|
+
var AXIS_TITLE_OFFSET_COMPACT = 35;
|
|
1200
|
+
var AXIS_TITLE_OFFSET_DEFAULT = 45;
|
|
1201
|
+
function getAxisTitleOffset(width) {
|
|
1202
|
+
return width < BREAKPOINT_COMPACT_MAX ? AXIS_TITLE_OFFSET_COMPACT : AXIS_TITLE_OFFSET_DEFAULT;
|
|
1203
|
+
}
|
|
1204
|
+
var HPAD_COMPACT_FRACTION = 0.5;
|
|
1205
|
+
var HPAD_COMPACT_MIN = 4;
|
|
1206
|
+
var TICK_LABEL_OFFSET = 6;
|
|
1207
|
+
var AXIS_TITLE_TRAILING_PAD = 4;
|
|
1208
|
+
var AXIS_TITLE_GAP = 7;
|
|
1209
|
+
function axisTitleOffset(maxTickLabelWidth, titleFontSize, width) {
|
|
1210
|
+
const halfTitleGlyph = Math.ceil(titleFontSize / 2);
|
|
1211
|
+
const dynamic = TICK_LABEL_OFFSET + maxTickLabelWidth + AXIS_TITLE_GAP + halfTitleGlyph;
|
|
1212
|
+
return Math.max(dynamic, getAxisTitleOffset(width));
|
|
1213
|
+
}
|
|
1214
|
+
var NARROW_VIEWPORT_MAX = 500;
|
|
1215
|
+
var TOP_PAD_EXTRA_NARROW = 10;
|
|
1216
|
+
var TOP_PAD_NARROW_MAX = NARROW_VIEWPORT_MAX;
|
|
1217
|
+
var LABEL_GAP_COMPACT = 8;
|
|
1218
|
+
var LABEL_GAP_DEFAULT = 12;
|
|
1219
|
+
var LABEL_GAP_NARROW_MAX = NARROW_VIEWPORT_MAX;
|
|
1220
|
+
var MAX_LEFT_LABEL_FRACTION_MEDIUM_MAX = 600;
|
|
1221
|
+
var MAX_LEFT_LABEL_FRACTION_COMPACT = 0.45;
|
|
1222
|
+
var MAX_LEFT_LABEL_FRACTION_MEDIUM = 0.55;
|
|
1223
|
+
var MAX_LEFT_LABEL_FRACTION_DEFAULT = 1;
|
|
1224
|
+
var X_AXIS_BAND_HEIGHT = 26;
|
|
1225
|
+
var X_AXIS_TITLE_BAND = 22;
|
|
1226
|
+
var X_AXIS_TITLE_BAND_ROTATED = 20;
|
|
1227
|
+
function computeXAxisExtentFromLabels(input) {
|
|
1228
|
+
const measure = input.measure ?? estimateTextWidth;
|
|
1229
|
+
const baseHeight = input.xAxisHeight ?? X_AXIS_BAND_HEIGHT;
|
|
1230
|
+
if (input.tickAngle && Math.abs(input.tickAngle) > 10) {
|
|
1231
|
+
const angleRad = Math.abs(input.tickAngle) * (Math.PI / 180);
|
|
1232
|
+
let maxLabelWidth = 40;
|
|
1233
|
+
for (const label of input.labels) {
|
|
1234
|
+
const w = measure(label, input.tickFontSize, input.tickFontWeight);
|
|
1235
|
+
if (w > maxLabelWidth) maxLabelWidth = w;
|
|
1236
|
+
}
|
|
1237
|
+
const rotatedHeight = Math.min(maxLabelWidth * Math.sin(angleRad) + 6, 120);
|
|
1238
|
+
return input.hasTitle ? rotatedHeight + X_AXIS_TITLE_BAND_ROTATED : rotatedHeight;
|
|
1239
|
+
}
|
|
1240
|
+
return input.hasTitle ? baseHeight + X_AXIS_TITLE_BAND : baseHeight;
|
|
1241
|
+
}
|
|
1242
|
+
|
|
816
1243
|
// src/theme/defaults.ts
|
|
817
1244
|
var DEFAULT_THEME = {
|
|
818
1245
|
colors: {
|
|
@@ -856,7 +1283,7 @@ var DEFAULT_THEME = {
|
|
|
856
1283
|
chromeToChart: 8,
|
|
857
1284
|
chartToFooter: 8,
|
|
858
1285
|
axisMargin: 6,
|
|
859
|
-
xAxisHeight:
|
|
1286
|
+
xAxisHeight: X_AXIS_BAND_HEIGHT,
|
|
860
1287
|
// Gap (px) between the x-axis line and the TOP of the tick labels. The
|
|
861
1288
|
// renderer anchors x-tick labels at their top edge (hanging baseline), so
|
|
862
1289
|
// this is a literal top gap that holds regardless of font size.
|
|
@@ -1164,42 +1591,6 @@ function resolveTheme(userTheme, base = DEFAULT_THEME) {
|
|
|
1164
1591
|
};
|
|
1165
1592
|
}
|
|
1166
1593
|
|
|
1167
|
-
// src/layout/text-measure.ts
|
|
1168
|
-
var AVG_CHAR_WIDTH_RATIO = 0.57;
|
|
1169
|
-
var WEIGHT_ADJUSTMENT = {
|
|
1170
|
-
100: 0.9,
|
|
1171
|
-
200: 0.92,
|
|
1172
|
-
300: 0.95,
|
|
1173
|
-
400: 1,
|
|
1174
|
-
500: 1.02,
|
|
1175
|
-
600: 1.05,
|
|
1176
|
-
700: 1.08,
|
|
1177
|
-
800: 1.1,
|
|
1178
|
-
900: 1.12
|
|
1179
|
-
};
|
|
1180
|
-
function estimateCharWidth(fontSize, fontWeight = 400) {
|
|
1181
|
-
const weightFactor = WEIGHT_ADJUSTMENT[fontWeight] ?? 1;
|
|
1182
|
-
return fontSize * AVG_CHAR_WIDTH_RATIO * weightFactor;
|
|
1183
|
-
}
|
|
1184
|
-
function estimateTextWidth(text, fontSize, fontWeight = 400) {
|
|
1185
|
-
const charWidth = estimateCharWidth(fontSize, fontWeight);
|
|
1186
|
-
if (text.includes("\n")) {
|
|
1187
|
-
let maxLen = 0;
|
|
1188
|
-
for (const line of text.split("\n")) {
|
|
1189
|
-
if (line.length > maxLen) maxLen = line.length;
|
|
1190
|
-
}
|
|
1191
|
-
return maxLen * charWidth;
|
|
1192
|
-
}
|
|
1193
|
-
return text.length * charWidth;
|
|
1194
|
-
}
|
|
1195
|
-
var BRAND_RESERVE_WIDTH = 130;
|
|
1196
|
-
var BRAND_FONT_SIZE = 12;
|
|
1197
|
-
var BRAND_MIN_WIDTH = 120;
|
|
1198
|
-
var COMPACT_WIDTH = 420;
|
|
1199
|
-
function estimateTextHeight(fontSize, lineCount = 1, lineHeight = 1.3) {
|
|
1200
|
-
return fontSize * lineHeight * lineCount;
|
|
1201
|
-
}
|
|
1202
|
-
|
|
1203
1594
|
// src/layout/chrome.ts
|
|
1204
1595
|
function normalizeChromeText(value) {
|
|
1205
1596
|
if (value === void 0) return null;
|
|
@@ -1505,101 +1896,6 @@ function wrapText(text, fontSize, fontWeight, maxWidth, measureText) {
|
|
|
1505
1896
|
return lines;
|
|
1506
1897
|
}
|
|
1507
1898
|
|
|
1508
|
-
// src/responsive/breakpoints.ts
|
|
1509
|
-
var BREAKPOINT_COMPACT_MAX = 400;
|
|
1510
|
-
var BREAKPOINT_MEDIUM_MAX = 700;
|
|
1511
|
-
function getBreakpoint(width) {
|
|
1512
|
-
if (width < BREAKPOINT_COMPACT_MAX) return "compact";
|
|
1513
|
-
if (width <= BREAKPOINT_MEDIUM_MAX) return "medium";
|
|
1514
|
-
return "full";
|
|
1515
|
-
}
|
|
1516
|
-
var HEIGHT_CRAMPED_MAX = 200;
|
|
1517
|
-
var HEIGHT_SHORT_MAX = 350;
|
|
1518
|
-
function getHeightClass(height) {
|
|
1519
|
-
if (height < HEIGHT_CRAMPED_MAX) return "cramped";
|
|
1520
|
-
if (height <= HEIGHT_SHORT_MAX) return "short";
|
|
1521
|
-
return "normal";
|
|
1522
|
-
}
|
|
1523
|
-
function getWidthStrategy(breakpoint) {
|
|
1524
|
-
switch (breakpoint) {
|
|
1525
|
-
case "compact":
|
|
1526
|
-
return {
|
|
1527
|
-
labelMode: "none",
|
|
1528
|
-
legendPosition: "top",
|
|
1529
|
-
annotationPosition: "tooltip-only",
|
|
1530
|
-
axisLabelDensity: "minimal",
|
|
1531
|
-
chromeMode: "full",
|
|
1532
|
-
legendMaxHeight: -1
|
|
1533
|
-
};
|
|
1534
|
-
case "medium":
|
|
1535
|
-
return {
|
|
1536
|
-
labelMode: "important",
|
|
1537
|
-
legendPosition: "top",
|
|
1538
|
-
annotationPosition: "inline",
|
|
1539
|
-
axisLabelDensity: "reduced",
|
|
1540
|
-
chromeMode: "full",
|
|
1541
|
-
legendMaxHeight: -1
|
|
1542
|
-
};
|
|
1543
|
-
case "full":
|
|
1544
|
-
return {
|
|
1545
|
-
labelMode: "all",
|
|
1546
|
-
legendPosition: "right",
|
|
1547
|
-
annotationPosition: "inline",
|
|
1548
|
-
axisLabelDensity: "full",
|
|
1549
|
-
chromeMode: "full",
|
|
1550
|
-
legendMaxHeight: -1
|
|
1551
|
-
};
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
|
-
function applyHeightConstraints(strategy, heightClass) {
|
|
1555
|
-
if (heightClass === "normal") return strategy;
|
|
1556
|
-
if (heightClass === "cramped") {
|
|
1557
|
-
return {
|
|
1558
|
-
...strategy,
|
|
1559
|
-
chromeMode: "hidden",
|
|
1560
|
-
legendMaxHeight: 0,
|
|
1561
|
-
labelMode: "none",
|
|
1562
|
-
annotationPosition: "tooltip-only"
|
|
1563
|
-
};
|
|
1564
|
-
}
|
|
1565
|
-
return {
|
|
1566
|
-
...strategy,
|
|
1567
|
-
chromeMode: "compact",
|
|
1568
|
-
legendMaxHeight: 0.15
|
|
1569
|
-
};
|
|
1570
|
-
}
|
|
1571
|
-
function getLayoutStrategy(breakpoint, heightClass = "normal") {
|
|
1572
|
-
const base = getWidthStrategy(breakpoint);
|
|
1573
|
-
return applyHeightConstraints(base, heightClass);
|
|
1574
|
-
}
|
|
1575
|
-
|
|
1576
|
-
// src/responsive/metrics.ts
|
|
1577
|
-
var AXIS_TITLE_OFFSET_COMPACT = 35;
|
|
1578
|
-
var AXIS_TITLE_OFFSET_DEFAULT = 45;
|
|
1579
|
-
function getAxisTitleOffset(width) {
|
|
1580
|
-
return width < BREAKPOINT_COMPACT_MAX ? AXIS_TITLE_OFFSET_COMPACT : AXIS_TITLE_OFFSET_DEFAULT;
|
|
1581
|
-
}
|
|
1582
|
-
var HPAD_COMPACT_FRACTION = 0.5;
|
|
1583
|
-
var HPAD_COMPACT_MIN = 4;
|
|
1584
|
-
var TICK_LABEL_OFFSET = 6;
|
|
1585
|
-
var AXIS_TITLE_TRAILING_PAD = 4;
|
|
1586
|
-
var AXIS_TITLE_GAP = 7;
|
|
1587
|
-
function axisTitleOffset(maxTickLabelWidth, titleFontSize, width) {
|
|
1588
|
-
const halfTitleGlyph = Math.ceil(titleFontSize / 2);
|
|
1589
|
-
const dynamic = TICK_LABEL_OFFSET + maxTickLabelWidth + AXIS_TITLE_GAP + halfTitleGlyph;
|
|
1590
|
-
return Math.max(dynamic, getAxisTitleOffset(width));
|
|
1591
|
-
}
|
|
1592
|
-
var NARROW_VIEWPORT_MAX = 500;
|
|
1593
|
-
var TOP_PAD_EXTRA_NARROW = 10;
|
|
1594
|
-
var TOP_PAD_NARROW_MAX = NARROW_VIEWPORT_MAX;
|
|
1595
|
-
var LABEL_GAP_COMPACT = 8;
|
|
1596
|
-
var LABEL_GAP_DEFAULT = 12;
|
|
1597
|
-
var LABEL_GAP_NARROW_MAX = NARROW_VIEWPORT_MAX;
|
|
1598
|
-
var MAX_LEFT_LABEL_FRACTION_MEDIUM_MAX = 600;
|
|
1599
|
-
var MAX_LEFT_LABEL_FRACTION_COMPACT = 0.45;
|
|
1600
|
-
var MAX_LEFT_LABEL_FRACTION_MEDIUM = 0.55;
|
|
1601
|
-
var MAX_LEFT_LABEL_FRACTION_DEFAULT = 1;
|
|
1602
|
-
|
|
1603
1899
|
// src/labels/collision.ts
|
|
1604
1900
|
var PRIORITY_ORDER = {
|
|
1605
1901
|
data: 0,
|
|
@@ -1609,6 +1905,11 @@ var PRIORITY_ORDER = {
|
|
|
1609
1905
|
function detectCollision(a, b) {
|
|
1610
1906
|
return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y;
|
|
1611
1907
|
}
|
|
1908
|
+
function overlapArea(a, b) {
|
|
1909
|
+
const w = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);
|
|
1910
|
+
const h = Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y);
|
|
1911
|
+
return w > 0 && h > 0 ? w * h : 0;
|
|
1912
|
+
}
|
|
1612
1913
|
var OFFSET_STRATEGIES = [
|
|
1613
1914
|
{ dx: 0, dy: 0 },
|
|
1614
1915
|
// original position
|
|
@@ -3093,6 +3394,9 @@ export {
|
|
|
3093
3394
|
TICK_LABEL_OFFSET,
|
|
3094
3395
|
TOP_PAD_EXTRA_NARROW,
|
|
3095
3396
|
TOP_PAD_NARROW_MAX,
|
|
3397
|
+
X_AXIS_BAND_HEIGHT,
|
|
3398
|
+
X_AXIS_TITLE_BAND,
|
|
3399
|
+
X_AXIS_TITLE_BAND_ROTATED,
|
|
3096
3400
|
abbreviateNumber,
|
|
3097
3401
|
adaptColorForDarkMode,
|
|
3098
3402
|
adaptTheme,
|
|
@@ -3105,6 +3409,7 @@ export {
|
|
|
3105
3409
|
columnChart,
|
|
3106
3410
|
computeChrome,
|
|
3107
3411
|
computeLabelBounds,
|
|
3412
|
+
computeXAxisExtentFromLabels,
|
|
3108
3413
|
contrastRatio,
|
|
3109
3414
|
dataTable,
|
|
3110
3415
|
detectCollision,
|
|
@@ -3123,6 +3428,7 @@ export {
|
|
|
3123
3428
|
getHeightClass,
|
|
3124
3429
|
getLayoutStrategy,
|
|
3125
3430
|
getRepresentativeColor,
|
|
3431
|
+
heuristicMeasure,
|
|
3126
3432
|
inferFieldType,
|
|
3127
3433
|
isBarListSpec,
|
|
3128
3434
|
isChartSpec,
|
|
@@ -3139,11 +3445,13 @@ export {
|
|
|
3139
3445
|
isTileMapSpec,
|
|
3140
3446
|
lineChart,
|
|
3141
3447
|
meetsAA,
|
|
3448
|
+
overlapArea,
|
|
3142
3449
|
pickLabelColor,
|
|
3143
3450
|
pieChart,
|
|
3144
3451
|
resolveCollisions,
|
|
3145
3452
|
resolveMarkDef,
|
|
3146
3453
|
resolveMarkType,
|
|
3454
|
+
resolveMeasurer,
|
|
3147
3455
|
resolveTheme,
|
|
3148
3456
|
scatterChart,
|
|
3149
3457
|
simulateColorBlindness,
|