@rowsncolumns/charts 28.1.8 → 28.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/cjs/basic-chart/basic-chart.d.ts.map +1 -1
  2. package/dist/cjs/basic-chart/basic-chart.js +538 -430
  3. package/dist/cjs/basic-chart/helpers.d.ts.map +1 -1
  4. package/dist/cjs/basic-chart/helpers.js +2 -0
  5. package/dist/cjs/plotly/basic-chart/basic-chart.d.ts.map +1 -1
  6. package/dist/cjs/plotly/basic-chart/basic-chart.js +333 -184
  7. package/dist/cjs/plotly/basic-chart/helpers.d.ts.map +1 -1
  8. package/dist/cjs/plotly/basic-chart/helpers.js +2 -0
  9. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  10. package/dist/cjs/utils/bubble.d.ts +34 -1
  11. package/dist/cjs/utils/bubble.d.ts.map +1 -1
  12. package/dist/cjs/utils/bubble.js +39 -13
  13. package/dist/cjs/utils/echarts-overlays.d.ts +46 -0
  14. package/dist/cjs/utils/echarts-overlays.d.ts.map +1 -0
  15. package/dist/cjs/utils/echarts-overlays.js +134 -0
  16. package/dist/cjs/utils/hierarchy.d.ts +23 -1
  17. package/dist/cjs/utils/hierarchy.d.ts.map +1 -1
  18. package/dist/cjs/utils/hierarchy.js +179 -55
  19. package/dist/cjs/utils/overrides.d.ts.map +1 -1
  20. package/dist/cjs/utils/overrides.js +15 -3
  21. package/dist/cjs/utils/trendline.d.ts +7 -1
  22. package/dist/cjs/utils/trendline.d.ts.map +1 -1
  23. package/dist/cjs/utils/trendline.js +82 -18
  24. package/dist/esm/basic-chart/basic-chart.d.ts.map +1 -1
  25. package/dist/esm/basic-chart/basic-chart.js +381 -251
  26. package/dist/esm/basic-chart/helpers.d.ts.map +1 -1
  27. package/dist/esm/basic-chart/helpers.js +2 -0
  28. package/dist/esm/plotly/basic-chart/basic-chart.d.ts.map +1 -1
  29. package/dist/esm/plotly/basic-chart/basic-chart.js +253 -58
  30. package/dist/esm/plotly/basic-chart/helpers.d.ts.map +1 -1
  31. package/dist/esm/plotly/basic-chart/helpers.js +2 -0
  32. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  33. package/dist/esm/utils/bubble.d.ts +34 -1
  34. package/dist/esm/utils/bubble.d.ts.map +1 -1
  35. package/dist/esm/utils/bubble.js +35 -11
  36. package/dist/esm/utils/echarts-overlays.d.ts +46 -0
  37. package/dist/esm/utils/echarts-overlays.d.ts.map +1 -0
  38. package/dist/esm/utils/echarts-overlays.js +135 -0
  39. package/dist/esm/utils/hierarchy.d.ts +23 -1
  40. package/dist/esm/utils/hierarchy.d.ts.map +1 -1
  41. package/dist/esm/utils/hierarchy.js +168 -50
  42. package/dist/esm/utils/overrides.d.ts.map +1 -1
  43. package/dist/esm/utils/overrides.js +15 -3
  44. package/dist/esm/utils/trendline.d.ts +7 -1
  45. package/dist/esm/utils/trendline.d.ts.map +1 -1
  46. package/dist/esm/utils/trendline.js +67 -14
  47. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../basic-chart/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,eAAO,MAAM,sBAAsB,GACjC,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,yGA6DzC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GACnC,QAAQ,MAAM,GAAG,SAAS,GAAG,IAAI,KAChC,MAAM,GAAG,SAuBX,CAAC;AAEF,uEAAuE;AACvE,eAAO,MAAM,mBAAmB,GAC9B,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,GAAG,SAAS,KACnD,OAAgD,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,aAAa,CAAC,OAAO,CAAC,KAC7B,MAAM,EAmBR,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC;;aASzC,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,YAejE,CAAC"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../basic-chart/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,eAAO,MAAM,sBAAsB,GACjC,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,yGA6DzC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GACnC,QAAQ,MAAM,GAAG,SAAS,GAAG,IAAI,KAChC,MAAM,GAAG,SAuBX,CAAC;AAEF,uEAAuE;AACvE,eAAO,MAAM,mBAAmB,GAC9B,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,GAAG,SAAS,KACnD,OAAgD,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,aAAa,CAAC,OAAO,CAAC,KAC7B,MAAM,EAmBR,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC;;aASzC,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,YAiBjE,CAAC"}
@@ -119,6 +119,8 @@ export const showXAxis = (type) => {
119
119
  type === "column" ||
120
120
  type === "bubble" ||
121
121
  type === "histogram" ||
122
+ // A waterfall's steps are categories (Opening, Sales, …) (#1070).
123
+ type === "waterfall" ||
122
124
  // Stock is line-derived and lives on a category x-axis. Radar is
123
125
  // axis-less (it uses a polar `radar` indicator instead).
124
126
  type === "stock") {
@@ -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;AAyZxD,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC;AA0FnD,eAAO,MAAM,UAAU,GAAI,gPAkBxB,eAAe,sBAq3EjB,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;AA6ZxD,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAmGnD,eAAO,MAAM,UAAU,GAAI,gPAkBxB,eAAe,sBAilFjB,CAAC"}
@@ -18,13 +18,13 @@ import { plotlyMulticategoryX, resolveCategoryLevels, } from "../../utils/catego
18
18
  import { gradientToPlotly } from "../../utils/gradient";
19
19
  import { BAND_GAP, legendLabelsFrom, measureTextWidth, reservePlotlyLegendBand, } from "../../utils/legend-layout";
20
20
  import { clampDoughnutHole, doughnutRings } from "../../utils/doughnut";
21
- import { resolveSeriesDataLabels } from "../../utils/overrides";
21
+ import { dataLabelFormatter, resolveSeriesDataLabels, } from "../../utils/overrides";
22
22
  import { plotlyTitleText } from "../../utils/plotly-title";
23
23
  import { explosionToPlotlyPull, resolveExplosion, } from "../../utils/pie-explosion";
24
24
  import { resolvePlotlyClickSelection, wasDragged, } from "../../utils/plotly-click";
25
25
  import { buildPlotlySurfaceTrace } from "../../utils/plotly-surface";
26
26
  import { normalize3DSourceType, } from "../../utils/three-d";
27
- import { extractHierarchyRows, getHierarchyHeaderTitle, toPlotlyHierarchy, } from "../../utils/hierarchy";
27
+ import { extractHierarchyRows, getHierarchyHeaderTitle, hierarchyNodeColors, toPlotlyHierarchy, } from "../../utils/hierarchy";
28
28
  import { binHistogram, computePareto, isParetoSpec, } from "../../utils/histogram";
29
29
  import { clampSecondPieSize, isOfPieChartSpec, otherSliceHalfAngle, resolveOfPieType, splitOfPie, } from "../../utils/of-pie";
30
30
  import { buildRadarIndicators } from "../../utils/radar";
@@ -339,6 +339,13 @@ const sanitizeChartValue = (value) => {
339
339
  * (Excel): every range's points in sequence. A single range passes through
340
340
  * untouched so the common path renders exactly as before.
341
341
  */
342
+ /**
343
+ * The plain value array of a series' data. (`"values" in seriesData` is
344
+ * true for an ARRAY too — `Array.prototype.values` — which handed the
345
+ * waterfall / funnel / histogram / boxplot branches that method instead
346
+ * of the numbers.)
347
+ */
348
+ const seriesValuesOf = (seriesData) => Array.isArray(seriesData) ? seriesData : seriesData.values;
342
349
  const mergeSeriesData = (parts) => {
343
350
  if (parts.length === 1)
344
351
  return parts[0];
@@ -389,6 +396,11 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
389
396
  // The plotted `<div>` plotly hands back on init — what `Plotly.toImage`
390
397
  // rasterises for Copy as Picture and the print preview.
391
398
  const graphDivRef = useRef(null);
399
+ // Plotly zooms a treemap / sunburst into the clicked branch by default;
400
+ // Excel has no drill-down, so the click handler cancels it unless the
401
+ // spec opts in (`drillDown`).
402
+ const drillDownRef = useRef(false);
403
+ drillDownRef.current = Boolean(spec.drillDown);
392
404
  const focusSheet = useFocusSheet();
393
405
  // Excel selects a data series (or one data point) when it is clicked
394
406
  // inside the chart and the grid highlights its source cells. The plot
@@ -516,8 +528,16 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
516
528
  sizeValues: sharedSizeValues,
517
529
  series: seriesInputs,
518
530
  });
519
- const sizeScale = createBubbleSizeScale(sizeValues);
531
+ // Bubble diameters scale from zero (area by default, width when
532
+ // `sizeRepresents` says so) and the largest bubble is a fraction of
533
+ // the plot area, which the margins below leave of the chart (#1068).
534
+ const sizeScale = createBubbleSizeScale(sizeValues, {
535
+ sizeRepresents: spec.sizeRepresents,
536
+ bubbleScale: spec.bubbleScale,
537
+ plotMinSide: Math.min((width ?? 0) - 80, (height ?? 0) - 100),
538
+ });
520
539
  const hasStringX = categories.length > 0;
540
+ const hasBubbleSecondaryAxis = (spec.series ?? []).some((seriesEntry) => seriesEntry?.useSecondaryAxis);
521
541
  const palette = getChartPalette(spec, [
522
542
  theme.themeColors.accent1,
523
543
  theme.themeColors.accent2,
@@ -553,16 +573,56 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
553
573
  const lineShapeFor = (style) => style === "smooth" || style === "smoothMarker"
554
574
  ? "spline"
555
575
  : "linear";
556
- const traces = preparedSeries.map((entry, index) => {
576
+ const traces = [];
577
+ preparedSeries.forEach((entry, index) => {
557
578
  const xValues = entry.points.map((point) => hasStringX
558
579
  ? point.xLabel ??
559
580
  categories[Math.round(point.value[0])] ??
560
581
  point.value[0]
561
582
  : point.value[0]);
562
583
  const yValues = entry.points.map((point) => point.value[1]);
563
- const labelValuesForSeries = entry.points.map((point) => point.name);
564
- const seriesColor = spec.series[index]?.color ?? chartPaletteColorAt(palette, index);
565
- const perSeriesMarker = spec.series[index]?.marker ?? undefined;
584
+ const rawSizes = entry.points.map((point) => point.value[2]);
585
+ const seriesSpec = spec.series[index];
586
+ const seriesColor = seriesSpec?.color ?? chartPaletteColorAt(palette, index);
587
+ const perSeriesMarker = seriesSpec?.marker ?? undefined;
588
+ // Per-point colours (`<c:dPt>`) key on the point's source row
589
+ // (`BubbleSeriesPoint.index` — points without a Y are skipped).
590
+ const pointColorOverrides = new Map();
591
+ for (const dp of seriesSpec?.dataPointColors ?? []) {
592
+ if (typeof dp?.idx === "number" && typeof dp?.color === "string") {
593
+ pointColorOverrides.set(dp.idx, dp.color);
594
+ }
595
+ }
596
+ const pointColors = (base) => pointColorOverrides.size
597
+ ? entry.points.map((point) => pointColorOverrides.get(point.index) ?? base)
598
+ : base;
599
+ // Hover reads the bubble label and size from `customdata`, leaving
600
+ // `text` to the data labels.
601
+ const customdata = entry.points.map((point) => [point.name, point.value[2]]);
602
+ const onSecondary = seriesSpec?.useSecondaryAxis ? { yaxis: "y2" } : {};
603
+ // This series' data labels: Y value by default, the bubble's size
604
+ // with `showBubbleSize`, the bubble label with `showCategoryName`.
605
+ const labelOpts = resolveSeriesDataLabels(spec.dataLabels, seriesSpec);
606
+ const labelText = labelOpts?.show
607
+ ? entry.points.map((point) => dataLabelFormatter(labelOpts, locale)({
608
+ value: point.value,
609
+ name: point.name,
610
+ seriesName: entry.name,
611
+ data: point,
612
+ }))
613
+ : undefined;
614
+ const labelPosition = labelOpts?.show
615
+ ? (labelOpts.position && PLOTLY_DLBL_POS_POINT[labelOpts.position]) ??
616
+ "top center"
617
+ : undefined;
618
+ const withLabels = (trace) => labelText
619
+ ? {
620
+ ...trace,
621
+ mode: withTextMode(trace.mode),
622
+ text: labelText,
623
+ textposition: labelPosition,
624
+ }
625
+ : trace;
566
626
  if (isScatter) {
567
627
  // Per-series marker.symbol = "none" → pure line (no markers).
568
628
  // Per-series marker.size overrides the default. Falls back to
@@ -574,14 +634,14 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
574
634
  : plotlyModeForScatterStyle(scatterStyle);
575
635
  const markerSize = perSeriesMarker?.size ?? 6;
576
636
  const markerColor = perSeriesMarker?.color ?? seriesColor;
577
- return {
637
+ traces.push(withLabels({
578
638
  type: "scatter",
579
639
  mode,
580
640
  x: xValues,
581
641
  y: yValues,
582
- text: labelValuesForSeries,
642
+ customdata,
583
643
  name: entry.name,
584
- hovertemplate: "%{text}<br>X: %{x}<br>Y: %{y}<extra></extra>",
644
+ hovertemplate: "%{customdata[0]}<br>X: %{x}<br>Y: %{y}<extra></extra>",
585
645
  line: {
586
646
  shape: lineShapeFor(scatterStyle),
587
647
  color: seriesColor,
@@ -592,31 +652,82 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
592
652
  : {
593
653
  marker: {
594
654
  size: markerSize,
595
- color: markerColor,
655
+ color: pointColors(markerColor),
596
656
  symbol: mapMarkerSymbolToPlotly(symbol),
597
657
  },
598
658
  }),
599
- };
659
+ ...onSecondary,
660
+ }));
661
+ }
662
+ else {
663
+ // Bubble — third dimension scaled into marker diameter.
664
+ const scaledSizes = rawSizes.map((value) => sizeScale(value));
665
+ traces.push(withLabels({
666
+ type: "scatter",
667
+ mode: "markers",
668
+ x: xValues,
669
+ y: yValues,
670
+ customdata,
671
+ name: entry.name,
672
+ hovertemplate: "%{customdata[0]}<br>X: %{x}<br>Y: %{y}<br>Size: %{customdata[1]}<extra></extra>",
673
+ marker: {
674
+ size: scaledSizes,
675
+ sizemode: "diameter",
676
+ color: pointColors(seriesColor),
677
+ opacity: 0.7,
678
+ },
679
+ ...onSecondary,
680
+ }));
681
+ }
682
+ // Trendlines on the real (x, y) points — a regression of Y on X,
683
+ // not on the point index — and native error bars (#1067).
684
+ const numericX = entry.points.map((point) => point.value[0]);
685
+ for (const tl of seriesSpec?.trendlines ?? []) {
686
+ const result = computeTrendline(yValues, {
687
+ type: tl.type,
688
+ order: tl.order,
689
+ period: tl.period,
690
+ forecastForward: tl.forecastForward,
691
+ forecastBackward: tl.forecastBackward,
692
+ }, numericX);
693
+ if (!result || result.points.length < 2)
694
+ continue;
695
+ const tlName = tl.name ??
696
+ `${entry.name ? entry.name + " " : ""}${tl.type ?? "linear"} trend`;
697
+ traces.push({
698
+ type: "scatter",
699
+ mode: "lines",
700
+ name: tlName,
701
+ x: result.points.map((p) => hasStringX
702
+ ? categories[Math.round(p.x)] ?? p.x
703
+ : p.x),
704
+ y: result.points.map((p) => p.y),
705
+ line: { color: tl.color ?? seriesColor, dash: "dash", width: 2 },
706
+ hoverinfo: "skip",
707
+ ...onSecondary,
708
+ });
709
+ }
710
+ if (seriesSpec?.errorBars) {
711
+ const direction = seriesSpec.errorBars.direction ?? "y";
712
+ // An X error bar sizes from the X values (a percentage or
713
+ // deviation of X).
714
+ const magnitudes = computeErrorBars(direction === "x" ? numericX : yValues, resolveCustomErrorBarValues(seriesSpec.errorBars, (range) => getSeriesValuesFromRange(range, spec.hiddenDimensionStrategy)));
715
+ if (magnitudes) {
716
+ const symmetric = magnitudes.plus.every((plus, i) => plus === magnitudes.minus[i]);
717
+ const errorConfig = {
718
+ type: "data",
719
+ symmetric,
720
+ array: magnitudes.plus,
721
+ ...(symmetric ? {} : { arrayminus: magnitudes.minus }),
722
+ color: seriesColor,
723
+ ...(seriesSpec.errorBars.noEndCap ? { width: 0 } : {}),
724
+ };
725
+ const target = traces[traces.length - 1 - (seriesSpec.trendlines?.length ?? 0)];
726
+ if (target) {
727
+ target[direction === "x" ? "error_x" : "error_y"] = errorConfig;
728
+ }
729
+ }
600
730
  }
601
- // Bubble — third dimension scaled into marker diameter.
602
- const rawSizes = entry.points.map((point) => point.value[2]);
603
- const scaledSizes = rawSizes.map((value) => sizeScale(value));
604
- return {
605
- type: "scatter",
606
- mode: "markers",
607
- x: xValues,
608
- y: yValues,
609
- text: labelValuesForSeries,
610
- customdata: rawSizes,
611
- name: entry.name,
612
- hovertemplate: "%{text}<br>X: %{x}<br>Y: %{y}<br>Size: %{customdata}<extra></extra>",
613
- marker: {
614
- size: scaledSizes,
615
- sizemode: "diameter",
616
- color: seriesColor,
617
- opacity: 0.7,
618
- },
619
- };
620
731
  });
621
732
  // Resolve text formats: chart-authored values (via OOXML <c:txPr>)
622
733
  // override the theme-derived defaults. `spec.titleTextFormat`,
@@ -636,7 +747,10 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
636
747
  x: 0.02,
637
748
  xanchor: "left",
638
749
  },
639
- xaxis: {
750
+ // Axis min / max / reverse / log / visibility from the spec
751
+ // (`categoryAxisOptions` is the X axis, as in the echarts
752
+ // renderer).
753
+ xaxis: applyAxisOverridesPlotly({
640
754
  title: {
641
755
  text: spec.horizontalAxisTitle ?? "",
642
756
  font: { color: xAxisFmt?.color ?? textColor },
@@ -648,8 +762,8 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
648
762
  ...(xAxisFmt?.fontSize ? { size: xAxisFmt.fontSize } : {}),
649
763
  },
650
764
  type: hasStringX ? "category" : "linear",
651
- },
652
- yaxis: {
765
+ }, spec.categoryAxisOptions),
766
+ yaxis: applyAxisOverridesPlotly({
653
767
  title: {
654
768
  text: spec.verticalAxisTitle ?? "",
655
769
  font: { color: yAxisFmt?.color ?? textColor },
@@ -660,7 +774,20 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
660
774
  ...(yAxisFmt?.fontFamily ? { family: yAxisFmt.fontFamily } : {}),
661
775
  ...(yAxisFmt?.fontSize ? { size: yAxisFmt.fontSize } : {}),
662
776
  },
663
- },
777
+ }, spec.valueAxisOptions),
778
+ // Secondary value axis on the right for the series that opt in
779
+ // (`useSecondaryAxis`), as the category layout has (#1067).
780
+ ...(hasBubbleSecondaryAxis
781
+ ? {
782
+ yaxis2: applyAxisOverridesPlotly({
783
+ overlaying: "y",
784
+ side: "right",
785
+ showgrid: false,
786
+ automargin: true,
787
+ tickfont: { color: yAxisFmt?.color ?? textColor },
788
+ }, spec.secondaryValueAxisOptions),
789
+ }
790
+ : {}),
664
791
  legend: {
665
792
  font: {
666
793
  color: legendFmt?.color ?? textColor,
@@ -671,7 +798,7 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
671
798
  paper_bgcolor: bgColor,
672
799
  plot_bgcolor: bgColor,
673
800
  showlegend: preparedSeries.length > 1,
674
- margin: { l: 60, r: 20, t: 50, b: 50 },
801
+ margin: { l: 60, r: hasBubbleSecondaryAxis ? 60 : 20, t: 50, b: 50 },
675
802
  };
676
803
  setPlotData(traces);
677
804
  setLayout(bubbleLayout);
@@ -693,14 +820,58 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
693
820
  const seriesName = hierarchyData.labels.length === 1
694
821
  ? hierarchyData.labels[0] ?? ""
695
822
  : explicitChartTitle ?? headerTitle ?? "";
823
+ // One solid colour per top-level category, inherited by its branch
824
+ // (#1072); nodes reference each other by id so a leaf name may
825
+ // repeat under different parents.
826
+ const hierarchyPalette = getChartPalette(spec, [
827
+ theme.themeColors.accent1,
828
+ theme.themeColors.accent2,
829
+ theme.themeColors.accent3,
830
+ theme.themeColors.accent4,
831
+ theme.themeColors.accent5,
832
+ theme.themeColors.accent6,
833
+ ]);
834
+ const nodeColors = hierarchyNodeColors(hierarchyData, hierarchyPalette);
835
+ const isSunburst = spec.chartType === "sunburst";
836
+ // Excel's sunburst leaves the centre empty — every level, the first
837
+ // included, is a ring (#1073). Plotly draws the top level as a ring
838
+ // only around a root node, so an invisible one holds the centre.
839
+ const SUNBURST_ROOT_ID = "__rnc_sunburst_root__";
840
+ const rootTotal = hierarchyData.values.reduce((sum, value, i) => (hierarchyData.parents[i] === "" ? sum + value : sum), 0);
696
841
  const hierarchyTrace = {
697
842
  type: chartType,
698
- labels: hierarchyData.labels,
699
- parents: hierarchyData.parents,
700
- values: hierarchyData.values,
843
+ labels: isSunburst ? ["", ...hierarchyData.labels] : hierarchyData.labels,
844
+ ids: isSunburst ? [SUNBURST_ROOT_ID, ...hierarchyData.ids] : hierarchyData.ids,
845
+ parents: isSunburst
846
+ ? ["", ...hierarchyData.parents.map((parent) => parent || SUNBURST_ROOT_ID)]
847
+ : hierarchyData.parents,
848
+ values: isSunburst ? [rootTotal, ...hierarchyData.values] : hierarchyData.values,
849
+ marker: {
850
+ colors: isSunburst ? ["rgba(0,0,0,0)", ...nodeColors] : nodeColors,
851
+ ...(isSunburst ? { line: { width: 1 } } : {}),
852
+ },
701
853
  name: seriesName,
702
854
  textinfo: "label+value",
703
855
  branchvalues: "total",
856
+ ...(isSunburst
857
+ ? {}
858
+ : {
859
+ textposition: "bottom left",
860
+ // Excel labels a treemap's top-level categories (in a header
861
+ // strip, or not at all with parentLabelLayout "none") and its
862
+ // leaves; the levels in between are never labelled (#1072).
863
+ text: hierarchyData.labels.map(() => ""),
864
+ texttemplate: hierarchyData.ids.map((id, i) => {
865
+ const isLeaf = !hierarchyData.parents.includes(id);
866
+ if (isLeaf)
867
+ return "%{label}<br>%{value}";
868
+ const isTopLevel = hierarchyData.depths[i] === 0;
869
+ return isTopLevel &&
870
+ spec.parentLabelLayout !== "none"
871
+ ? "%{label}"
872
+ : "%{text}";
873
+ }),
874
+ }),
704
875
  };
705
876
  const layoutForHierarchy = {
706
877
  title: {
@@ -1190,7 +1361,8 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
1190
1361
  // by category index, falling back to the series color for points
1191
1362
  // without an override.
1192
1363
  const isPie = chartTypeForStyling === "pie";
1193
- if ((isBarOrColumn || isPie) &&
1364
+ const isFunnel = chartTypeForStyling === "funnel";
1365
+ if ((isBarOrColumn || isPie || isFunnel) &&
1194
1366
  Array.isArray(options?.dataPointColors) &&
1195
1367
  options?.dataPointColors.length) {
1196
1368
  const overrides = new Map();
@@ -1445,9 +1617,7 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
1445
1617
  : {}),
1446
1618
  };
1447
1619
  if (effectiveChartType === "histogram") {
1448
- const rawValues = "values" in seriesData
1449
- ? seriesData.values
1450
- : seriesData;
1620
+ const rawValues = seriesValuesOf(seriesData);
1451
1621
  const binCount = spec.binCount;
1452
1622
  if (isPareto) {
1453
1623
  // Plotly's native histogram trace bins in axis order and
@@ -1497,9 +1667,7 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
1497
1667
  }
1498
1668
  }
1499
1669
  else if (effectiveChartType === "boxplot") {
1500
- const rawValues = "values" in seriesData
1501
- ? seriesData.values
1502
- : seriesData;
1670
+ const rawValues = seriesValuesOf(seriesData);
1503
1671
  const quartileMethod = spec.quartileMethod;
1504
1672
  const showOutliers = spec.showOutliers;
1505
1673
  const showMeanMarker = spec.showMeanMarker === true;
@@ -1566,37 +1734,51 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
1566
1734
  traces.push(trace);
1567
1735
  }
1568
1736
  else if (effectiveChartType === "waterfall") {
1569
- const rawValues = "values" in seriesData
1570
- ? seriesData.values
1571
- : seriesData;
1737
+ const rawValues = seriesValuesOf(seriesData);
1572
1738
  // Plotly's native waterfall draws connector lines itself and
1573
1739
  // renders "total" measures from the zero baseline with its
1574
1740
  // own distinct fill.
1575
1741
  const totalIndices = new Set(spec.totalIndices ?? []);
1742
+ // Increases take the series colour, decreases its negative colour
1743
+ // and totals the theme's third accent, as the echarts renderer and
1744
+ // Excel's default waterfall do (plotly's own defaults are green /
1745
+ // red / blue). Plotly paints a waterfall by measure, not per bar, so
1746
+ // `dataPointColors` cannot recolour one step here.
1747
+ const increaseColor = series.color ?? chartPaletteColorAt(themeColorPalette, currentSeriesIndex);
1576
1748
  const trace = {
1577
1749
  type: "waterfall",
1578
1750
  x: categoriesFor(series),
1579
1751
  y: rawValues.map((v) => (v ?? null)),
1580
1752
  measure: rawValues.map((_, i) => totalIndices.has(i) ? "total" : "relative"),
1581
1753
  name: dataLabel,
1754
+ increasing: { marker: { color: increaseColor } },
1755
+ decreasing: {
1756
+ marker: {
1757
+ color: series.negativeColor ?? theme.themeColors.accent2 ?? increaseColor,
1758
+ },
1759
+ },
1760
+ totals: { marker: { color: theme.themeColors.accent3 ?? increaseColor } },
1761
+ connector: {
1762
+ line: {
1763
+ color: isDarkMode ? "rgba(255,255,255,0.45)" : "#999999",
1764
+ width: 1,
1765
+ },
1766
+ },
1582
1767
  };
1583
- applyTraceColor(trace, series.color ?? undefined, {
1584
- noFill: series.noFill,
1585
- dataPointColors: series.dataPointColors,
1586
- seriesIndex: currentSeriesIndex,
1587
- effectiveChartType,
1588
- });
1589
1768
  traces.push(trace);
1590
1769
  }
1591
1770
  else if (effectiveChartType === "funnel") {
1592
- const rawValues = "values" in seriesData
1593
- ? seriesData.values
1594
- : seriesData;
1771
+ const rawValues = seriesValuesOf(seriesData);
1772
+ // Horizontal bars with the stage names on the category axis to
1773
+ // the left; the series colour (per-stage `<c:dPt>` overrides) and
1774
+ // the values inside the bars follow below (#1069).
1595
1775
  const trace = {
1596
1776
  type: "funnel",
1777
+ orientation: "h",
1597
1778
  y: categoriesFor(series),
1598
1779
  x: rawValues.map((v) => (v ?? null)),
1599
1780
  name: dataLabel,
1781
+ textinfo: "none",
1600
1782
  };
1601
1783
  applyTraceColor(trace, series.color ?? undefined, {
1602
1784
  noFill: series.noFill,
@@ -2088,6 +2270,14 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
2088
2270
  const formattedTraces = traces.map((trace) => {
2089
2271
  const pattern = traceNumberFormat(trace);
2090
2272
  let next = applyDataLabelsToTracePlotly(trace, traceDataLabels(trace), spec.chartType, pattern, locale);
2273
+ if (next.type === "funnel") {
2274
+ // The formatted values ride on `text`; a funnel prints its own
2275
+ // `value` unless told to draw the text (or nothing).
2276
+ next = {
2277
+ ...next,
2278
+ textinfo: traceDataLabels(trace)?.show ? "text" : "none",
2279
+ };
2280
+ }
2091
2281
  if (next.type === "pie") {
2092
2282
  // Plotly's pie prints every slice's percentage by default; Excel
2093
2283
  // draws nothing until data labels are on (#1062).
@@ -2278,5 +2468,10 @@ export const BasicChart = ({ width, height, chart, theme, isDarkMode, sheetId, r
2278
2468
  React.createElement("div", { className: "flex-1 rnc-plotly-chart-container", onPointerDownCapture: handlePointerDownCapture },
2279
2469
  React.createElement(Plot, { data: plotData, layout: plotLayout, config: config, onClick: handlePlotClick, onInitialized: (_figure, graphDiv) => {
2280
2470
  graphDivRef.current = graphDiv;
2471
+ const plotDiv = graphDiv;
2472
+ // Returning false from these handlers keeps the clicked branch
2473
+ // from becoming the new root.
2474
+ plotDiv.on?.("plotly_treemapclick", () => drillDownRef.current);
2475
+ plotDiv.on?.("plotly_sunburstclick", () => drillDownRef.current);
2281
2476
  }, style: { width: "100%", height: "100%" } }))));
2282
2477
  };
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../plotly/basic-chart/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,eAAO,MAAM,qBAAqB,GAChC,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,KACvC,MAmEF,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC;;;;;;;;;CAgBzC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAClC,QAAQ,MAAM,GAAG,SAAS,GAAG,IAAI,KAChC,MAAM,GAAG,SA0BX,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,YAejE,CAAC"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../plotly/basic-chart/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,eAAO,MAAM,qBAAqB,GAChC,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,KACvC,MAmEF,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC;;;;;;;;;CAgBzC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAClC,QAAQ,MAAM,GAAG,SAAS,GAAG,IAAI,KAChC,MAAM,GAAG,SA0BX,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,YAiBjE,CAAC"}
@@ -101,6 +101,8 @@ export const showXAxis = (type) => {
101
101
  type === "column" ||
102
102
  type === "bubble" ||
103
103
  type === "histogram" ||
104
+ // A waterfall's steps are categories (Opening, Sales, …) (#1070).
105
+ type === "waterfall" ||
104
106
  // Stock is line-derived on a category x-axis. Radar is polar and
105
107
  // does not use the cartesian x-axis.
106
108
  type === "stock") {
@@ -1 +1 @@
1
- {"root":["../../config.ts","../../echarts-gl.d.ts","../../geo-modules.d.ts","../../index.ts","../../plotly-dist.d.ts","../../types.ts","../../vitest.config.ts","../../atoms/editing-chart.atom.ts","../../atoms/pivot-chart.atom.ts","../../basic-chart/basic-chart.tsx","../../basic-chart/helpers.ts","../../basic-chart/index.tsx","../../components/dialogs/chart-editor-dialog.tsx","../../components/dialogs/pivot-chart-dialog.tsx","../../components/editors/chart-editor.tsx","../../components/editors/chart-range-input.tsx","../../hooks/use-chart-editor.ts","../../hooks/use-charts.ts","../../hooks/use-on-create-chart.ts","../../hooks/use-on-delete-chart.ts","../../hooks/use-on-move-chart-to-sheet.ts","../../hooks/use-on-move-chart.ts","../../hooks/use-on-resize-chart.ts","../../hooks/use-on-update-chart.ts","../../interface/create-chart.ts","../../interface/delete-chart.ts","../../interface/move-chart-to-sheet.ts","../../interface/move-chart.ts","../../interface/resize-chart.ts","../../interface/shift-chart-ranges.ts","../../interface/update-chart.ts","../../plotly/plot.ts","../../plotly/basic-chart/basic-chart.tsx","../../plotly/basic-chart/helpers.ts","../../plotly/basic-chart/index.tsx","../../utils/aggregation.ts","../../utils/axis-number-format.ts","../../utils/bar-layout.ts","../../utils/boxplot.ts","../../utils/bubble.ts","../../utils/category-levels.ts","../../utils/chart-image.ts","../../utils/chart-orientation.ts","../../utils/chart-spec-utils.ts","../../utils/chart-styles.ts","../../utils/doughnut.ts","../../utils/echarts-gl-loader.ts","../../utils/empty-cells.ts","../../utils/error-bars.ts","../../utils/gradient.ts","../../utils/hierarchy.ts","../../utils/histogram.ts","../../utils/legend-layout.ts","../../utils/of-pie.ts","../../utils/overrides.ts","../../utils/pie-explosion.ts","../../utils/plotly-click.ts","../../utils/plotly-surface.ts","../../utils/plotly-title.ts","../../utils/radar.ts","../../utils/region-map-loader.ts","../../utils/region-map.ts","../../utils/series-click.ts","../../utils/stock.ts","../../utils/three-d.ts","../../utils/trendline.ts","../../utils/waterfall.ts","../../utils/webgl.ts"],"version":"5.8.3"}
1
+ {"root":["../../config.ts","../../echarts-gl.d.ts","../../geo-modules.d.ts","../../index.ts","../../plotly-dist.d.ts","../../types.ts","../../vitest.config.ts","../../atoms/editing-chart.atom.ts","../../atoms/pivot-chart.atom.ts","../../basic-chart/basic-chart.tsx","../../basic-chart/helpers.ts","../../basic-chart/index.tsx","../../components/dialogs/chart-editor-dialog.tsx","../../components/dialogs/pivot-chart-dialog.tsx","../../components/editors/chart-editor.tsx","../../components/editors/chart-range-input.tsx","../../hooks/use-chart-editor.ts","../../hooks/use-charts.ts","../../hooks/use-on-create-chart.ts","../../hooks/use-on-delete-chart.ts","../../hooks/use-on-move-chart-to-sheet.ts","../../hooks/use-on-move-chart.ts","../../hooks/use-on-resize-chart.ts","../../hooks/use-on-update-chart.ts","../../interface/create-chart.ts","../../interface/delete-chart.ts","../../interface/move-chart-to-sheet.ts","../../interface/move-chart.ts","../../interface/resize-chart.ts","../../interface/shift-chart-ranges.ts","../../interface/update-chart.ts","../../plotly/plot.ts","../../plotly/basic-chart/basic-chart.tsx","../../plotly/basic-chart/helpers.ts","../../plotly/basic-chart/index.tsx","../../utils/aggregation.ts","../../utils/axis-number-format.ts","../../utils/bar-layout.ts","../../utils/boxplot.ts","../../utils/bubble.ts","../../utils/category-levels.ts","../../utils/chart-image.ts","../../utils/chart-orientation.ts","../../utils/chart-spec-utils.ts","../../utils/chart-styles.ts","../../utils/doughnut.ts","../../utils/echarts-gl-loader.ts","../../utils/echarts-overlays.ts","../../utils/empty-cells.ts","../../utils/error-bars.ts","../../utils/gradient.ts","../../utils/hierarchy.ts","../../utils/histogram.ts","../../utils/legend-layout.ts","../../utils/of-pie.ts","../../utils/overrides.ts","../../utils/pie-explosion.ts","../../utils/plotly-click.ts","../../utils/plotly-surface.ts","../../utils/plotly-title.ts","../../utils/radar.ts","../../utils/region-map-loader.ts","../../utils/region-map.ts","../../utils/series-click.ts","../../utils/stock.ts","../../utils/three-d.ts","../../utils/trendline.ts","../../utils/waterfall.ts","../../utils/webgl.ts"],"version":"5.8.3"}
@@ -1,6 +1,33 @@
1
1
  export declare const toLabelString: (value: unknown) => string;
2
2
  export declare const toNumericValue: (value: unknown) => number | null;
3
- export declare const createBubbleSizeScale: (values: number[]) => (value: number) => number;
3
+ export type BubbleSizeOptions = {
4
+ /**
5
+ * Whether a size value sets the bubble's area (Excel's default,
6
+ * diameter ∝ √value) or its width (diameter ∝ value).
7
+ */
8
+ sizeRepresents?: "area" | "width" | null;
9
+ /** Percent of the default size, 0-300 (Excel's `<c:bubbleScale>`). */
10
+ bubbleScale?: number | null;
11
+ /**
12
+ * The plot area's smaller side in pixels — the largest bubble's
13
+ * diameter is a fraction of it, so bubbles grow with the chart.
14
+ */
15
+ plotMinSide?: number | null;
16
+ };
17
+ /** The largest bubble's diameter at bubbleScale 100: a quarter of the plot area's smaller side. */
18
+ export declare const BUBBLE_MAX_DIAMETER_FRACTION = 0.25;
19
+ /**
20
+ * Pixel diameter per size value, scaled from ZERO like Excel: the largest
21
+ * absolute value gets the maximum diameter and every other bubble's area
22
+ * (or width) is its share of that value. Scaling from the minimum value
23
+ * instead made the ratio between bubbles depend on the spread of the
24
+ * data (100 and 101 drew as the smallest and largest bubble), and a
25
+ * linear diameter made the perceived area grow with the square of the
26
+ * value (rowsncolumns/spreadsheet#1068).
27
+ */
28
+ export declare const createBubbleSizeScale: (values: number[], options?: BubbleSizeOptions) => (value: number) => number;
29
+ /** The diameter of the largest bubble for these options. */
30
+ export declare const bubbleMaxDiameter: (options?: BubbleSizeOptions) => number;
4
31
  export type BubbleSeriesInput = {
5
32
  name?: string | null;
6
33
  values: (string | number | boolean | null | undefined)[];
@@ -23,6 +50,12 @@ export type BubbleSeriesPoint = {
23
50
  value: [number, number, number];
24
51
  name: string;
25
52
  xLabel?: string;
53
+ /**
54
+ * The point's row in the source ranges. Points with no Y are skipped,
55
+ * so this is not the point's position in the series — per-point
56
+ * colours (`dataPointColors[].idx`) key on it.
57
+ */
58
+ index: number;
26
59
  };
27
60
  export type PreparedBubbleSeries = {
28
61
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"bubble.d.ts","sourceRoot":"","sources":["../../../utils/bubble.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,MACU,CAAC;AAE1D,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,IAYxD,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,QAAQ,MAAM,EAAE,aAQrC,MAAM,WAOtB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;IACzD;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;IAC3D;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;CAC/D,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;;;OAKG;IACH,OAAO,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;IAC1D,WAAW,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;IAC9D;;OAEG;IACH,UAAU,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;IAC7D,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAwCF,eAAO,MAAM,uBAAuB,GAAI,+CAKrC,uBAAuB,KAAG,kBAsF5B,CAAC"}
1
+ {"version":3,"file":"bubble.d.ts","sourceRoot":"","sources":["../../../utils/bubble.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,MACU,CAAC;AAE1D,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,IAYxD,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACzC,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,CAAC;AAEF,mGAAmG;AACnG,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAMjD;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,MAAM,EAAE,EAChB,UAAS,iBAAsB,MAMvB,OAAO,MAAM,WAQtB,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,iBAAiB,GAAI,UAAS,iBAAsB,WAUhE,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;IACzD;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;IAC3D;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;CAC/D,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;;;OAKG;IACH,OAAO,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;IAC1D,WAAW,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;IAC9D;;OAEG;IACH,UAAU,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;IAC7D,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAwCF,eAAO,MAAM,uBAAuB,GAAI,+CAKrC,uBAAuB,KAAG,kBAuF5B,CAAC"}