@rowsncolumns/charts 28.1.10 → 28.1.12
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/cjs/basic-chart/basic-chart.d.ts.map +1 -1
- package/dist/cjs/basic-chart/basic-chart.js +268 -173
- package/dist/cjs/plotly/basic-chart/basic-chart.d.ts.map +1 -1
- package/dist/cjs/plotly/basic-chart/basic-chart.js +140 -95
- package/dist/cjs/utils/hierarchy.d.ts +6 -0
- package/dist/cjs/utils/hierarchy.d.ts.map +1 -1
- package/dist/cjs/utils/hierarchy.js +23 -1
- package/dist/cjs/utils/histogram.d.ts +42 -3
- package/dist/cjs/utils/histogram.d.ts.map +1 -1
- package/dist/cjs/utils/histogram.js +193 -5
- package/dist/cjs/utils/overrides.d.ts +1 -1
- package/dist/cjs/utils/overrides.d.ts.map +1 -1
- package/dist/cjs/utils/overrides.js +44 -34
- package/dist/esm/basic-chart/basic-chart.d.ts.map +1 -1
- package/dist/esm/basic-chart/basic-chart.js +168 -40
- package/dist/esm/plotly/basic-chart/basic-chart.d.ts.map +1 -1
- package/dist/esm/plotly/basic-chart/basic-chart.js +63 -6
- package/dist/esm/utils/hierarchy.d.ts +6 -0
- package/dist/esm/utils/hierarchy.d.ts.map +1 -1
- package/dist/esm/utils/hierarchy.js +21 -0
- package/dist/esm/utils/histogram.d.ts +42 -3
- package/dist/esm/utils/histogram.d.ts.map +1 -1
- package/dist/esm/utils/histogram.js +171 -4
- package/dist/esm/utils/overrides.d.ts +1 -1
- package/dist/esm/utils/overrides.d.ts.map +1 -1
- package/dist/esm/utils/overrides.js +10 -3
- package/package.json +2 -2
|
@@ -23,12 +23,12 @@ import { applyEmptyCellsPolicy, connectsAcrossEmptyCells, isolatedPointIndexes,
|
|
|
23
23
|
import { getEchartsGlState, loadEchartsGl, } from "../utils/echarts-gl-loader";
|
|
24
24
|
import { echartsGroupedCategoryAxes, resolveCategoryLevels, } from "../utils/category-levels";
|
|
25
25
|
import { gradientToEcharts } from "../utils/gradient";
|
|
26
|
-
import { buildHierarchyTree, extractHierarchyRows, getHierarchyHeaderTitle, } from "../utils/hierarchy";
|
|
27
|
-
import { binHistogram, computePareto, isParetoSpec, } from "../utils/histogram";
|
|
26
|
+
import { buildHierarchyTree, contrastTextColor, extractHierarchyRows, getHierarchyHeaderTitle, } from "../utils/hierarchy";
|
|
27
|
+
import { aggregateByCategory, binHistogram, computePareto, isParetoSpec, } from "../utils/histogram";
|
|
28
28
|
import { categoryAxisNameGap, legendLabelsFrom, reserveEchartsLegendBand, } from "../utils/legend-layout";
|
|
29
29
|
import { clampSecondPieSize, isOfPieChartSpec, otherSliceHalfAngle, resolveOfPieType, splitOfPie, } from "../utils/of-pie";
|
|
30
30
|
import { clampDoughnutHole, doughnutRings } from "../utils/doughnut";
|
|
31
|
-
import { applyAxisOverrides, applyLegendOverrides, buildSeriesLabelOption, resolveSeriesDataLabels, } from "../utils/overrides";
|
|
31
|
+
import { applyAxisOverrides, dataLabelFormatter, applyLegendOverrides, buildSeriesLabelOption, resolveSeriesDataLabels, } from "../utils/overrides";
|
|
32
32
|
import { buildRadarIndicators, buildRadarSeriesData } from "../utils/radar";
|
|
33
33
|
import { buildRegionMapData, buildSequentialColorRamp, isRegionMapSpec, resolveGeoScope, warnOnceForUnmatchedRegions, } from "../utils/region-map";
|
|
34
34
|
import { loadRegionMapGeo } from "../utils/region-map-loader";
|
|
@@ -104,7 +104,8 @@ const isBubbleChartSpec = (spec) => BUBBLE_CHART_TYPES.has(spec.chartType);
|
|
|
104
104
|
const isHierarchyChartSpec = (spec) => HIERARCHY_CHART_TYPES.has(spec.chartType);
|
|
105
105
|
// Every level keeps the colour its node was given (one solid colour per
|
|
106
106
|
// top-level category, like Excel — no per-level saturation ramp); thin
|
|
107
|
-
// white gaps separate the cells.
|
|
107
|
+
// white gaps separate the cells. Index 0 is echarts' virtual root, 1 the
|
|
108
|
+
// top-level categories, 2+ the levels beneath them.
|
|
108
109
|
const HIERARCHY_LEVEL_STYLES = [
|
|
109
110
|
{
|
|
110
111
|
itemStyle: {
|
|
@@ -112,28 +113,55 @@ const HIERARCHY_LEVEL_STYLES = [
|
|
|
112
113
|
borderColor: "#ffffff",
|
|
113
114
|
borderWidth: 0,
|
|
114
115
|
},
|
|
115
|
-
upperLabel: { show: false },
|
|
116
116
|
},
|
|
117
117
|
{
|
|
118
118
|
itemStyle: {
|
|
119
|
-
gapWidth:
|
|
119
|
+
gapWidth: 2,
|
|
120
|
+
borderColor: "#ffffff",
|
|
121
|
+
borderWidth: 1,
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
itemStyle: {
|
|
126
|
+
gapWidth: 0,
|
|
120
127
|
borderColor: "#ffffff",
|
|
121
128
|
borderWidth: 1,
|
|
122
129
|
},
|
|
123
130
|
},
|
|
124
131
|
];
|
|
132
|
+
/** Height of the strip a treemap category name is drawn in (Excel's "Banner"). */
|
|
133
|
+
const TREEMAP_BANNER_HEIGHT = 20;
|
|
134
|
+
/**
|
|
135
|
+
* Excel's treemap `parentLabelLayout`: the top-level category names are
|
|
136
|
+
* drawn in a banner strip (or not at all); the levels between the categories
|
|
137
|
+
* and the leaves are never labelled, so small groups keep their height for
|
|
138
|
+
* the leaf cells (rowsncolumns/spreadsheet#1072). Excel's default
|
|
139
|
+
* `overlapping` writes the name over the group's top-left corner, which an
|
|
140
|
+
* echarts treemap cannot draw (an upper label always reserves its strip and
|
|
141
|
+
* is dropped when the strip is too small for the text), so it draws as a
|
|
142
|
+
* banner.
|
|
143
|
+
*/
|
|
144
|
+
const treemapBannerShown = (layout) => layout !== "none";
|
|
125
145
|
/**
|
|
126
146
|
* Colour a hierarchy like Excel: each top-level node takes the next
|
|
127
147
|
* palette colour and every descendant inherits it (#1072).
|
|
128
148
|
*/
|
|
129
|
-
const colorHierarchyNodes = (nodes, palette) => nodes.map((node, index) => {
|
|
149
|
+
const colorHierarchyNodes = (nodes, palette, options = {}) => nodes.map((node, index) => {
|
|
130
150
|
const color = chartPaletteColorAt(palette, index);
|
|
131
|
-
const paint = (n) => ({
|
|
151
|
+
const paint = (n, depth) => ({
|
|
132
152
|
...n,
|
|
133
|
-
|
|
134
|
-
|
|
153
|
+
// A top-level node's "border" is what echarts paints behind its
|
|
154
|
+
// banner strip: fill it with the category colour and write the name
|
|
155
|
+
// in a contrasting colour, like Excel's banner (#1086).
|
|
156
|
+
itemStyle: depth === 0 && options.banner
|
|
157
|
+
? { color, borderColor: color }
|
|
158
|
+
: { color },
|
|
159
|
+
...(depth === 0 && options.banner
|
|
160
|
+
? { upperLabel: { color: contrastTextColor(color) } }
|
|
161
|
+
: {}),
|
|
162
|
+
...(n.children ? { children: n.children.map((c) => paint(c, depth + 1)) } : {}),
|
|
135
163
|
});
|
|
136
|
-
return paint(node);
|
|
164
|
+
return paint(node, 0);
|
|
137
165
|
});
|
|
138
166
|
/** Sunburst rings: Excel leaves the centre empty, so even the first level is a ring (#1073). */
|
|
139
167
|
const SUNBURST_RADIUS = ["15%", "80%"];
|
|
@@ -170,17 +198,30 @@ const flattenChartDataValues = (chartData, extractor, hiddenStrategy, skipFirstR
|
|
|
170
198
|
});
|
|
171
199
|
return values;
|
|
172
200
|
};
|
|
173
|
-
const buildHierarchyLevels = (maxDepth) => {
|
|
201
|
+
const buildHierarchyLevels = (maxDepth, options) => {
|
|
174
202
|
if (maxDepth <= 0)
|
|
175
203
|
return undefined;
|
|
176
204
|
const levels = [];
|
|
177
|
-
|
|
205
|
+
// One entry per depth, the virtual root included, so every level's upper
|
|
206
|
+
// label is explicit: the categories' banner on level 1 only.
|
|
207
|
+
for (let i = 0; i <= maxDepth; i++) {
|
|
178
208
|
const baseStyle = HIERARCHY_LEVEL_STYLES[Math.min(i, HIERARCHY_LEVEL_STYLES.length - 1)];
|
|
179
209
|
levels.push({
|
|
180
210
|
...baseStyle,
|
|
181
211
|
itemStyle: {
|
|
182
212
|
...baseStyle.itemStyle,
|
|
183
213
|
},
|
|
214
|
+
...(options.treemap
|
|
215
|
+
? {
|
|
216
|
+
upperLabel: i === 1 && options.banner
|
|
217
|
+
? {
|
|
218
|
+
show: true,
|
|
219
|
+
height: TREEMAP_BANNER_HEIGHT,
|
|
220
|
+
padding: [0, 0, 0, 4],
|
|
221
|
+
}
|
|
222
|
+
: { show: false },
|
|
223
|
+
}
|
|
224
|
+
: {}),
|
|
184
225
|
});
|
|
185
226
|
}
|
|
186
227
|
return levels;
|
|
@@ -808,12 +849,35 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
808
849
|
theme.themeColors.accent5,
|
|
809
850
|
theme.themeColors.accent6,
|
|
810
851
|
]);
|
|
811
|
-
const
|
|
852
|
+
const isTreemap = spec.chartType === "treemap";
|
|
853
|
+
const banner = isTreemap && treemapBannerShown(spec.parentLabelLayout);
|
|
854
|
+
const hierarchyData = colorHierarchyNodes(buildHierarchyTree(hierarchyRows), hierarchyPalette, { banner });
|
|
812
855
|
const rootName = hierarchyData.length === 1 ? hierarchyData[0]?.name ?? "" : "";
|
|
813
856
|
const drillDown = Boolean(spec.drillDown);
|
|
814
857
|
const seriesDisplayName = explicitChartTitle ?? headerTitle ?? rootName ?? "";
|
|
815
858
|
const hierarchyDepth = getHierarchyDepth(hierarchyData);
|
|
816
|
-
const levels = buildHierarchyLevels(hierarchyDepth
|
|
859
|
+
const levels = buildHierarchyLevels(hierarchyDepth, {
|
|
860
|
+
treemap: isTreemap,
|
|
861
|
+
banner,
|
|
862
|
+
});
|
|
863
|
+
// Excel lists the top-level categories with their colours in the
|
|
864
|
+
// legend. An echarts legend cannot address treemap nodes, so each
|
|
865
|
+
// category gets a data-less placeholder series carrying its name and
|
|
866
|
+
// colour; `selectedMode: false` keeps the swatches from toggling
|
|
867
|
+
// anything.
|
|
868
|
+
const hierarchyLegend = applyLegendOverrides({ ...defaultLegendConfig, show: false }, spec.legend);
|
|
869
|
+
const legendShown = hierarchyLegend.show !== false;
|
|
870
|
+
const categoryLegendSeries = legendShown
|
|
871
|
+
? hierarchyData.map((node) => ({
|
|
872
|
+
type: "bar",
|
|
873
|
+
id: `rnc-hierarchy-legend-${node.id ?? node.name}`,
|
|
874
|
+
name: node.name,
|
|
875
|
+
data: [],
|
|
876
|
+
silent: true,
|
|
877
|
+
itemStyle: { color: node.itemStyle?.color },
|
|
878
|
+
tooltip: { show: false },
|
|
879
|
+
}))
|
|
880
|
+
: [];
|
|
817
881
|
// Sizes format like the cells they were read from (Excel's "Linked
|
|
818
882
|
// to source"), unless the data labels carry their own pattern.
|
|
819
883
|
const sizeNumberFormat = resolveSourceNumberFormat(spec.sizeData?.[0]
|
|
@@ -824,12 +888,45 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
824
888
|
: params.value ?? "";
|
|
825
889
|
return `${params.name}: ${formatAxisValue(sizeNumberFormat, value, locale)}`;
|
|
826
890
|
};
|
|
827
|
-
//
|
|
828
|
-
//
|
|
891
|
+
// Data labels: a treemap block's label always sits in its bottom-left
|
|
892
|
+
// corner (the bar placements mean nothing on a block) with each part
|
|
893
|
+
// — name, value — on its own line; `{ show: false }` turns the labels
|
|
894
|
+
// off entirely (#1086). Without `dataLabels` the block shows its name.
|
|
829
895
|
const hierarchyDataLabels = spec.dataLabels;
|
|
830
|
-
const
|
|
896
|
+
const hierarchyLabelOpts = hierarchyDataLabels && !hierarchyDataLabels.numberFormatPattern
|
|
831
897
|
? { ...hierarchyDataLabels, numberFormatPattern: sizeNumberFormat }
|
|
832
|
-
: hierarchyDataLabels
|
|
898
|
+
: hierarchyDataLabels;
|
|
899
|
+
const hierarchyLabel = hierarchyLabelOpts?.show === false
|
|
900
|
+
? { show: false }
|
|
901
|
+
: hierarchyLabelOpts?.show
|
|
902
|
+
? {
|
|
903
|
+
show: true,
|
|
904
|
+
formatter: dataLabelFormatter(hierarchyLabelOpts, locale, isTreemap ? "\n" : ": "),
|
|
905
|
+
...(isTreemap ? { position: "insideBottomLeft" } : {}),
|
|
906
|
+
}
|
|
907
|
+
: {
|
|
908
|
+
show: true,
|
|
909
|
+
formatter: "{b}",
|
|
910
|
+
...(isTreemap ? { position: "insideBottomLeft" } : {}),
|
|
911
|
+
};
|
|
912
|
+
// Reserve a band for the legend (and the title) so neither paints
|
|
913
|
+
// over the blocks (#1086), as the cartesian layout does.
|
|
914
|
+
const hierarchyBand = reserveEchartsLegendBand({
|
|
915
|
+
position: spec.legend?.position,
|
|
916
|
+
visible: legendShown && hierarchyData.length > 0,
|
|
917
|
+
labels: hierarchyData.map((node) => node.name),
|
|
918
|
+
legendFontSize: hierarchyLegend.textStyle?.fontSize ??
|
|
919
|
+
spec.legend?.textFormat?.fontSize ??
|
|
920
|
+
12,
|
|
921
|
+
legendItemWidth: defaultLegendConfig.itemWidth,
|
|
922
|
+
width: width ?? 0,
|
|
923
|
+
height: height ?? 0,
|
|
924
|
+
hasTitle: Boolean(explicitChartTitle ?? headerTitle),
|
|
925
|
+
titleFontSize: spec.titleTextFormat?.fontSize ?? 16,
|
|
926
|
+
hasBottomAxisTitle: false,
|
|
927
|
+
bottomAxisNameGap: 0,
|
|
928
|
+
hasLeftAxisTitle: false,
|
|
929
|
+
});
|
|
833
930
|
chartRef.current?.setOption({
|
|
834
931
|
xAxis: [
|
|
835
932
|
{
|
|
@@ -843,7 +940,12 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
843
940
|
show: false,
|
|
844
941
|
},
|
|
845
942
|
],
|
|
846
|
-
legend:
|
|
943
|
+
legend: {
|
|
944
|
+
...hierarchyLegend,
|
|
945
|
+
...hierarchyBand.legend,
|
|
946
|
+
data: hierarchyData.map((node) => node.name),
|
|
947
|
+
selectedMode: false,
|
|
948
|
+
},
|
|
847
949
|
grid: {
|
|
848
950
|
left: 0,
|
|
849
951
|
right: 0,
|
|
@@ -860,21 +962,22 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
860
962
|
name: seriesDisplayName,
|
|
861
963
|
rootName: rootName || seriesDisplayName || "",
|
|
862
964
|
data: hierarchyData,
|
|
863
|
-
label:
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
...(hierarchySeriesLabel ?? {}),
|
|
870
|
-
},
|
|
871
|
-
upperLabel: spec.chartType === "treemap"
|
|
965
|
+
label: hierarchyLabel,
|
|
966
|
+
// Only `levels[1]` (the categories) may carry a banner; see
|
|
967
|
+
// buildHierarchyLevels.
|
|
968
|
+
upperLabel: isTreemap ? { show: false } : undefined,
|
|
969
|
+
levels,
|
|
970
|
+
...(isTreemap
|
|
872
971
|
? {
|
|
873
|
-
|
|
874
|
-
|
|
972
|
+
// Excel has no wheel zoom / drag pan on a treemap; the
|
|
973
|
+
// sheet keeps scrolling under the pointer (#1086).
|
|
974
|
+
roam: drillDown,
|
|
975
|
+
left: hierarchyBand.grid.left,
|
|
976
|
+
right: hierarchyBand.grid.right,
|
|
977
|
+
top: hierarchyBand.grid.top,
|
|
978
|
+
bottom: hierarchyBand.grid.bottom,
|
|
875
979
|
}
|
|
876
|
-
:
|
|
877
|
-
levels,
|
|
980
|
+
: {}),
|
|
878
981
|
// Excel has no drill-down on either chart: zooming into a
|
|
879
982
|
// branch on click (and the treemap breadcrumb) is opt-in.
|
|
880
983
|
nodeClick: drillDown
|
|
@@ -882,10 +985,11 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
882
985
|
? "zoomToNode"
|
|
883
986
|
: "rootToNode"
|
|
884
987
|
: false,
|
|
885
|
-
...(
|
|
988
|
+
...(isTreemap
|
|
886
989
|
? { breadcrumb: { show: drillDown } }
|
|
887
990
|
: { radius: [...SUNBURST_RADIUS] }),
|
|
888
991
|
},
|
|
992
|
+
...categoryLegendSeries,
|
|
889
993
|
],
|
|
890
994
|
}, {
|
|
891
995
|
replaceMerge: [
|
|
@@ -898,7 +1002,7 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
898
1002
|
],
|
|
899
1003
|
});
|
|
900
1004
|
previousChartType.current = spec.chartType;
|
|
901
|
-
previousSeriesCount.current = 1;
|
|
1005
|
+
previousSeriesCount.current = 1 + categoryLegendSeries.length;
|
|
902
1006
|
return;
|
|
903
1007
|
}
|
|
904
1008
|
else {
|
|
@@ -2369,7 +2473,21 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
2369
2473
|
}
|
|
2370
2474
|
else if (spec.chartType === "histogram") {
|
|
2371
2475
|
const rawValues = flattenChartDataValues(spec.series, getSeriesValuesFromRange, spec.hiddenDimensionStrategy).map((v) => (typeof v === "number" ? v : Number(v)));
|
|
2372
|
-
|
|
2476
|
+
// A domain names a category column: Excel's "By Category" histogram
|
|
2477
|
+
// / Pareto over categories aggregates the values per category (sum
|
|
2478
|
+
// unless the series says otherwise) instead of binning them (#1087).
|
|
2479
|
+
const histogramDomainSource = spec.domains?.[0]?.sources?.[0];
|
|
2480
|
+
const histogramCategories = histogramDomainSource
|
|
2481
|
+
? (getDomainValuesFromRange(histogramDomainSource, spec.hiddenDimensionStrategy) ?? [])
|
|
2482
|
+
: [];
|
|
2483
|
+
let { labels, counts } = histogramCategories.length
|
|
2484
|
+
? aggregateByCategory(histogramCategories, rawValues, spec.series?.[0]?.aggregateType ?? "SUM")
|
|
2485
|
+
: binHistogram(rawValues, spec.binCount, {
|
|
2486
|
+
binSize: spec.binSize,
|
|
2487
|
+
intervalClosed: spec.intervalClosed,
|
|
2488
|
+
overflow: spec.overflow,
|
|
2489
|
+
underflow: spec.underflow,
|
|
2490
|
+
});
|
|
2373
2491
|
// Pareto — a histogram whose bins are sorted descending with a
|
|
2374
2492
|
// cumulative-% line overlaid on a secondary 0-100% axis. The
|
|
2375
2493
|
// authored type arrives as `sourceChartType: "PARETO"` on an
|
|
@@ -2399,7 +2517,10 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
2399
2517
|
type: "bar",
|
|
2400
2518
|
name: spec.series?.[0]?.dataLabel ?? "",
|
|
2401
2519
|
data: counts,
|
|
2402
|
-
|
|
2520
|
+
// Excel's histogram columns touch unless `gapWidth` says otherwise
|
|
2521
|
+
// (#1087); the gap maps like a column chart's.
|
|
2522
|
+
barCategoryGap: gapWidthToBarCategoryGap(spec.gapWidth ?? 0, { seriesCount: 1 }) ??
|
|
2523
|
+
"0%",
|
|
2403
2524
|
};
|
|
2404
2525
|
const histogramColor = spec.series?.[0]?.color;
|
|
2405
2526
|
if (histogramColor) {
|
|
@@ -2409,14 +2530,21 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
2409
2530
|
if (isPareto) {
|
|
2410
2531
|
// Cumulative-% overlay on the secondary axis (yAxisIndex 1);
|
|
2411
2532
|
// the matching 0-100% axis element is appended with the other
|
|
2412
|
-
// value axes below.
|
|
2533
|
+
// value axes below. Excel draws the Pareto line without markers.
|
|
2534
|
+
const paretoLineColor = spec.paretoLineColor;
|
|
2413
2535
|
chartSeries.push({
|
|
2414
2536
|
type: "line",
|
|
2415
2537
|
name: "Cumulative %",
|
|
2416
2538
|
data: cumulativePercents,
|
|
2417
2539
|
yAxisIndex: 1,
|
|
2418
|
-
|
|
2419
|
-
|
|
2540
|
+
showSymbol: false,
|
|
2541
|
+
symbol: "none",
|
|
2542
|
+
...(paretoLineColor
|
|
2543
|
+
? {
|
|
2544
|
+
itemStyle: { color: paretoLineColor },
|
|
2545
|
+
lineStyle: { color: paretoLineColor },
|
|
2546
|
+
}
|
|
2547
|
+
: {}),
|
|
2420
2548
|
});
|
|
2421
2549
|
}
|
|
2422
2550
|
legend.data = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"basic-chart.d.ts","sourceRoot":"","sources":["../../../../plotly/basic-chart/basic-chart.tsx"],"names":[],"mappings":"AAoCA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAEtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"basic-chart.d.ts","sourceRoot":"","sources":["../../../../plotly/basic-chart/basic-chart.tsx"],"names":[],"mappings":"AAoCA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAEtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AA+ZxD,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAmGnD,eAAO,MAAM,UAAU,GAAI,gPAkBxB,eAAe,sBA4nFjB,CAAC"}
|
|
@@ -25,7 +25,7 @@ import { resolvePlotlyClickSelection, wasDragged, } from "../../utils/plotly-cli
|
|
|
25
25
|
import { buildPlotlySurfaceTrace } from "../../utils/plotly-surface";
|
|
26
26
|
import { normalize3DSourceType, } from "../../utils/three-d";
|
|
27
27
|
import { extractHierarchyRows, getHierarchyHeaderTitle, hierarchyNodeColors, toPlotlyHierarchy, } from "../../utils/hierarchy";
|
|
28
|
-
import { binHistogram, computePareto, isParetoSpec, } from "../../utils/histogram";
|
|
28
|
+
import { aggregateByCategory, binHistogram, computePareto, hasExcelBinning, isParetoSpec, } from "../../utils/histogram";
|
|
29
29
|
import { clampSecondPieSize, isOfPieChartSpec, otherSliceHalfAngle, resolveOfPieType, splitOfPie, } from "../../utils/of-pie";
|
|
30
30
|
import { buildRadarIndicators } from "../../utils/radar";
|
|
31
31
|
import { buildSequentialColorRamp, isRegionMapSpec, resolveGeoScope, WORLD_GEO_SCOPE, } from "../../utils/region-map";
|
|
@@ -851,9 +851,28 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
851
851
|
...(isSunburst ? { line: { width: 1 } } : {}),
|
|
852
852
|
},
|
|
853
853
|
name: seriesName,
|
|
854
|
-
|
|
854
|
+
// `dataLabels: { show: false }` turns the labels off (#1086).
|
|
855
|
+
textinfo: spec.dataLabels?.show === false ? "none" : "label+value",
|
|
855
856
|
branchvalues: "total",
|
|
856
|
-
...(isSunburst
|
|
857
|
+
...(isSunburst || spec.dataLabels?.show === false
|
|
858
|
+
? {}
|
|
859
|
+
: {
|
|
860
|
+
textposition: "bottom left",
|
|
861
|
+
// Excel labels a treemap's top-level categories (in a header
|
|
862
|
+
// strip, or not at all with parentLabelLayout "none") and its
|
|
863
|
+
// leaves; the levels in between are never labelled (#1072).
|
|
864
|
+
text: hierarchyData.labels.map(() => ""),
|
|
865
|
+
texttemplate: hierarchyData.ids.map((id, i) => {
|
|
866
|
+
const isLeaf = !hierarchyData.parents.includes(id);
|
|
867
|
+
if (isLeaf)
|
|
868
|
+
return "%{label}<br>%{value}";
|
|
869
|
+
const isTopLevel = hierarchyData.depths[i] === 0;
|
|
870
|
+
return isTopLevel &&
|
|
871
|
+
spec.parentLabelLayout !== "none"
|
|
872
|
+
? "%{label}"
|
|
873
|
+
: "%{text}";
|
|
874
|
+
}),
|
|
875
|
+
}),
|
|
857
876
|
};
|
|
858
877
|
const layoutForHierarchy = {
|
|
859
878
|
title: {
|
|
@@ -1601,12 +1620,29 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
1601
1620
|
if (effectiveChartType === "histogram") {
|
|
1602
1621
|
const rawValues = seriesValuesOf(seriesData);
|
|
1603
1622
|
const binCount = spec.binCount;
|
|
1623
|
+
const binningOptions = {
|
|
1624
|
+
binSize: spec.binSize,
|
|
1625
|
+
intervalClosed: spec.intervalClosed,
|
|
1626
|
+
overflow: spec.overflow,
|
|
1627
|
+
underflow: spec.underflow,
|
|
1628
|
+
};
|
|
1629
|
+
// A domain names a category column: aggregate per category (Excel's
|
|
1630
|
+
// "By Category" / Pareto over categories) instead of binning
|
|
1631
|
+
// (#1087). Excel binning options also pre-bin with the shared util,
|
|
1632
|
+
// since plotly's native histogram cannot close intervals on the
|
|
1633
|
+
// right or add overflow bins.
|
|
1634
|
+
const categories = domainData;
|
|
1635
|
+
const prebinned = categories.length
|
|
1636
|
+
? aggregateByCategory(categories, rawValues, series.aggregateType ?? "SUM")
|
|
1637
|
+
: hasExcelBinning(binningOptions)
|
|
1638
|
+
? binHistogram(rawValues, binCount, binningOptions)
|
|
1639
|
+
: null;
|
|
1604
1640
|
if (isPareto) {
|
|
1605
1641
|
// Plotly's native histogram trace bins in axis order and
|
|
1606
1642
|
// can't reorder bins, so Pareto pre-bins with the shared
|
|
1607
1643
|
// util, sorts descending, and renders a bar trace plus the
|
|
1608
1644
|
// cumulative-% line pointed at the y2 overlay axis.
|
|
1609
|
-
const { labels, counts, cumulativePercents } = computePareto(binHistogram(rawValues, binCount));
|
|
1645
|
+
const { labels, counts, cumulativePercents } = computePareto(prebinned ?? binHistogram(rawValues, binCount));
|
|
1610
1646
|
const barTrace = {
|
|
1611
1647
|
type: "bar",
|
|
1612
1648
|
x: labels,
|
|
@@ -1620,16 +1656,34 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
1620
1656
|
effectiveChartType,
|
|
1621
1657
|
});
|
|
1622
1658
|
traces.push(barTrace);
|
|
1659
|
+
const paretoLineColor = spec.paretoLineColor;
|
|
1660
|
+
// Excel draws the Pareto line without markers.
|
|
1623
1661
|
traces.push({
|
|
1624
1662
|
type: "scatter",
|
|
1625
|
-
mode: "lines
|
|
1663
|
+
mode: "lines",
|
|
1626
1664
|
x: labels,
|
|
1627
1665
|
y: cumulativePercents,
|
|
1628
1666
|
name: "Cumulative %",
|
|
1629
1667
|
yaxis: "y2",
|
|
1668
|
+
...(paretoLineColor ? { line: { color: paretoLineColor } } : {}),
|
|
1630
1669
|
});
|
|
1631
1670
|
hasSecondaryAxis = true;
|
|
1632
1671
|
}
|
|
1672
|
+
else if (prebinned) {
|
|
1673
|
+
const barTrace = {
|
|
1674
|
+
type: "bar",
|
|
1675
|
+
x: prebinned.labels,
|
|
1676
|
+
y: prebinned.counts,
|
|
1677
|
+
name: dataLabel,
|
|
1678
|
+
};
|
|
1679
|
+
applyTraceColor(barTrace, series.color ?? undefined, {
|
|
1680
|
+
noFill: series.noFill,
|
|
1681
|
+
dataPointColors: series.dataPointColors,
|
|
1682
|
+
seriesIndex: currentSeriesIndex,
|
|
1683
|
+
effectiveChartType,
|
|
1684
|
+
});
|
|
1685
|
+
traces.push(barTrace);
|
|
1686
|
+
}
|
|
1633
1687
|
else {
|
|
1634
1688
|
const trace = {
|
|
1635
1689
|
type: "histogram",
|
|
@@ -2113,7 +2167,10 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
|
|
|
2113
2167
|
// gapWidth=150 (default) → ~0.4 bargap.
|
|
2114
2168
|
...(typeof spec.gapWidth === "number"
|
|
2115
2169
|
? { bargap: Math.max(0, Math.min(0.95, spec.gapWidth / 400)) }
|
|
2116
|
-
:
|
|
2170
|
+
: spec.chartType === "histogram"
|
|
2171
|
+
? // Excel's histogram columns touch by default (#1087).
|
|
2172
|
+
{ bargap: 0 }
|
|
2173
|
+
: {}),
|
|
2117
2174
|
font: {
|
|
2118
2175
|
family: "Untitled Sans, apple-system, sans-serif",
|
|
2119
2176
|
size: 12,
|
|
@@ -46,5 +46,11 @@ export declare const toPlotlyHierarchy: (rows: HierarchyRow[]) => PlotlyHierarch
|
|
|
46
46
|
* Returns the colour per node of `toPlotlyHierarchy`'s flat arrays.
|
|
47
47
|
*/
|
|
48
48
|
export declare const hierarchyNodeColors: (hierarchy: Pick<PlotlyHierarchy, "ids" | "parents">, palette: string[]) => string[];
|
|
49
|
+
/**
|
|
50
|
+
* Black or white, whichever reads on `background` (a `#rgb` / `#rrggbb`
|
|
51
|
+
* colour; anything else gets white) — for a treemap banner filled with
|
|
52
|
+
* its category's colour (rowsncolumns/spreadsheet#1086).
|
|
53
|
+
*/
|
|
54
|
+
export declare const contrastTextColor: (background: string | undefined) => string;
|
|
49
55
|
export {};
|
|
50
56
|
//# sourceMappingURL=hierarchy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hierarchy.d.ts","sourceRoot":"","sources":["../../../utils/hierarchy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EACT,UAAU,EACV,YAAY,EACb,MAAM,2BAA2B,CAAC;AAEnC,KAAK,SAAS,GAAG,CACf,KAAK,EAAE,UAAU,EACjB,cAAc,CAAC,EAAE,SAAS,CAAC,yBAAyB,CAAC,KAClD,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;AAEtD,MAAM,MAAM,YAAY,GAAG;IACzB,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;CAC5B,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,wBAAwB,EAAE,SAAS,CAAC;IACpC,wBAAwB,EAAE,SAAS,CAAC;IACpC,uBAAuB,CAAC,EAAE,SAAS,CAAC,yBAAyB,CAAC,CAAC;CAChE,CAAC;AA0CF,eAAO,MAAM,uBAAuB,GAClC,MAAM,YAAY,EAClB,SAAS,cAAc,KACtB,MAAM,GAAG,SAgBX,CAAC;AAyCF,eAAO,MAAM,oBAAoB,GAC/B,MAAM,YAAY,EAClB,SAAS,cAAc,KACtB,YAAY,EAiFd,CAAC;AAiDF,eAAO,MAAM,kBAAkB,GAAI,MAAM,YAAY,EAAE,KAAG,aAAa,EAmDtE,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,4BAA4B;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,6EAA6E;IAC7E,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,yCAAyC;IACzC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,oCAAoC;IACpC,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,MAAM,YAAY,EAAE,KAAG,eAwBxD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,WAAW,IAAI,CAAC,eAAe,EAAE,KAAK,GAAG,SAAS,CAAC,EACnD,SAAS,MAAM,EAAE,KAChB,MAAM,EAYR,CAAC"}
|
|
1
|
+
{"version":3,"file":"hierarchy.d.ts","sourceRoot":"","sources":["../../../utils/hierarchy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EACT,UAAU,EACV,YAAY,EACb,MAAM,2BAA2B,CAAC;AAEnC,KAAK,SAAS,GAAG,CACf,KAAK,EAAE,UAAU,EACjB,cAAc,CAAC,EAAE,SAAS,CAAC,yBAAyB,CAAC,KAClD,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;AAEtD,MAAM,MAAM,YAAY,GAAG;IACzB,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;CAC5B,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,wBAAwB,EAAE,SAAS,CAAC;IACpC,wBAAwB,EAAE,SAAS,CAAC;IACpC,uBAAuB,CAAC,EAAE,SAAS,CAAC,yBAAyB,CAAC,CAAC;CAChE,CAAC;AA0CF,eAAO,MAAM,uBAAuB,GAClC,MAAM,YAAY,EAClB,SAAS,cAAc,KACtB,MAAM,GAAG,SAgBX,CAAC;AAyCF,eAAO,MAAM,oBAAoB,GAC/B,MAAM,YAAY,EAClB,SAAS,cAAc,KACtB,YAAY,EAiFd,CAAC;AAiDF,eAAO,MAAM,kBAAkB,GAAI,MAAM,YAAY,EAAE,KAAG,aAAa,EAmDtE,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,4BAA4B;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,6EAA6E;IAC7E,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,yCAAyC;IACzC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,oCAAoC;IACpC,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,MAAM,YAAY,EAAE,KAAG,eAwBxD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,WAAW,IAAI,CAAC,eAAe,EAAE,KAAK,GAAG,SAAS,CAAC,EACnD,SAAS,MAAM,EAAE,KAChB,MAAM,EAYR,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,YAAY,MAAM,GAAG,SAAS,KAAG,MAelE,CAAC"}
|
|
@@ -266,3 +266,24 @@ export const hierarchyNodeColors = (hierarchy, palette) => {
|
|
|
266
266
|
return color;
|
|
267
267
|
});
|
|
268
268
|
};
|
|
269
|
+
/**
|
|
270
|
+
* Black or white, whichever reads on `background` (a `#rgb` / `#rrggbb`
|
|
271
|
+
* colour; anything else gets white) — for a treemap banner filled with
|
|
272
|
+
* its category's colour (rowsncolumns/spreadsheet#1086).
|
|
273
|
+
*/
|
|
274
|
+
export const contrastTextColor = (background) => {
|
|
275
|
+
const hex = (background ?? "").trim().replace(/^#/, "");
|
|
276
|
+
const full = hex.length === 3
|
|
277
|
+
? hex
|
|
278
|
+
.split("")
|
|
279
|
+
.map((c) => c + c)
|
|
280
|
+
.join("")
|
|
281
|
+
: hex;
|
|
282
|
+
if (!/^[0-9a-f]{6}$/i.test(full))
|
|
283
|
+
return "#ffffff";
|
|
284
|
+
const r = parseInt(full.slice(0, 2), 16);
|
|
285
|
+
const g = parseInt(full.slice(2, 4), 16);
|
|
286
|
+
const b = parseInt(full.slice(4, 6), 16);
|
|
287
|
+
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
288
|
+
return luminance > 0.6 ? "#000000" : "#ffffff";
|
|
289
|
+
};
|
|
@@ -39,8 +39,47 @@ export declare const isParetoSpec: (spec: {
|
|
|
39
39
|
*/
|
|
40
40
|
export declare const computePareto: (bins: HistogramBins) => ParetoData;
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
42
|
+
* Excel's `<cx:binning>` options (rowsncolumns/spreadsheet#1087). Any of
|
|
43
|
+
* them present switches the histogram to Excel's conventions: intervals
|
|
44
|
+
* closed on the right by default and automatic bins by Excel's rule.
|
|
44
45
|
*/
|
|
45
|
-
export
|
|
46
|
+
export type HistogramBinningOptions = {
|
|
47
|
+
/** Fixed bin width (`<cx:binSize>`); wins over `binCount`. */
|
|
48
|
+
binSize?: number | null;
|
|
49
|
+
/** Which side of an interval is closed (`intervalClosed`); Excel's default is `r`. */
|
|
50
|
+
intervalClosed?: "l" | "r" | null;
|
|
51
|
+
/** Values above this collect in a final `> overflow` bin. */
|
|
52
|
+
overflow?: number | null;
|
|
53
|
+
/** Values below this collect in a first `< underflow` bin. */
|
|
54
|
+
underflow?: number | null;
|
|
55
|
+
};
|
|
56
|
+
/** True when the spec authored any Excel binning option. */
|
|
57
|
+
export declare const hasExcelBinning: (options: HistogramBinningOptions | null | undefined) => boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Excel's automatic bin width: Scott's normal reference rule,
|
|
60
|
+
* 3.5 · σ / ∛n with the sample standard deviation, rounded up to two
|
|
61
|
+
* significant digits. For the 20 values 12 … 95 of #1087 (σ ≈ 23.86) that
|
|
62
|
+
* is 30.77 → 31, i.e. Excel's three bins [12, 43], (43, 74], (74, 105].
|
|
63
|
+
*/
|
|
64
|
+
export declare const excelAutoBinWidth: (numeric: number[]) => number;
|
|
65
|
+
/**
|
|
66
|
+
* Bin a set of numeric values into equal-width bins.
|
|
67
|
+
*
|
|
68
|
+
* Default (no Excel options): `binCount` bins over [min, max], closed on
|
|
69
|
+
* the left — or Sturges' rule, ceil(log2(n) + 1), when `binCount` is
|
|
70
|
+
* omitted. With Excel binning options (#1087): bins start at the minimum
|
|
71
|
+
* (or the underflow bound), are `binSize` wide — else (max − min) /
|
|
72
|
+
* `binCount`, else Excel's automatic width — closed on the right unless
|
|
73
|
+
* `intervalClosed` is `l`, and values beyond `overflow` / `underflow`
|
|
74
|
+
* collect in their own end bins.
|
|
75
|
+
*/
|
|
76
|
+
export declare const binHistogram: (values: (number | null | undefined)[], binCount?: number | null, options?: HistogramBinningOptions | null) => HistogramBins;
|
|
77
|
+
export type HistogramAggregateType = "SUM" | "AVERAGE" | "COUNT" | "MAX" | "MIN" | "MEDIAN";
|
|
78
|
+
/**
|
|
79
|
+
* Excel's histogram "By Category" / Pareto over categories
|
|
80
|
+
* (`<cx:aggregation/>`, #1087): one column per distinct category in order
|
|
81
|
+
* of first appearance, its value the aggregate (sum by default) of the
|
|
82
|
+
* series values of that category — instead of binning the values.
|
|
83
|
+
*/
|
|
84
|
+
export declare const aggregateByCategory: (categories: (string | number | null | undefined)[], values: (number | null | undefined)[], aggregateType?: HistogramAggregateType | null | undefined) => HistogramBins;
|
|
46
85
|
//# sourceMappingURL=histogram.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"histogram.d.ts","sourceRoot":"","sources":["../../../utils/histogram.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,gDAAgD;IAChD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,mEAAmE;IACnE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;;;OAIG;IACH,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,KAAG,OAGgD,CAAC;AAErD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,aAAa,KAAG,UAmBnD,CAAC;
|
|
1
|
+
{"version":3,"file":"histogram.d.ts","sourceRoot":"","sources":["../../../utils/histogram.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,gDAAgD;IAChD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,mEAAmE;IACnE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;;;OAIG;IACH,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,KAAG,OAGgD,CAAC;AAErD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,aAAa,KAAG,UAmBnD,CAAC;AAUF;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,sFAAsF;IACtF,cAAc,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC;IAClC,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAKF,4DAA4D;AAC5D,eAAO,MAAM,eAAe,GAC1B,SAAS,uBAAuB,GAAG,IAAI,GAAG,SAAS,KAClD,OAQA,CAAC;AASJ;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,EAAE,KAAG,MASrD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,GACvB,QAAQ,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,EACrC,WAAW,MAAM,GAAG,IAAI,EACxB,UAAU,uBAAuB,GAAG,IAAI,KACvC,aA4CF,CAAC;AAiFF,MAAM,MAAM,sBAAsB,GAC9B,KAAK,GACL,SAAS,GACT,OAAO,GACP,KAAK,GACL,KAAK,GACL,QAAQ,CAAC;AAEb;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC9B,YAAY,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,EAClD,QAAQ,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,EACrC,gBAAe,sBAAsB,GAAG,IAAI,GAAG,SAAiB,KAC/D,aA0CF,CAAC"}
|