@sckyzo/cosmos-charts 0.1.1 → 0.2.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.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  var react = require('react');
4
4
  require('apexcharts/line');
5
- var ReactApexChart = require('react-apexcharts/core');
5
+ var ReactApexChart13 = require('react-apexcharts/core');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
  require('apexcharts/features/annotations');
8
8
  require('apexcharts/radialBar');
@@ -10,14 +10,28 @@ require('apexcharts/donut');
10
10
  require('apexcharts/features/legend');
11
11
  require('apexcharts/treemap');
12
12
  require('apexcharts/bar');
13
+ require('apexcharts/heatmap');
14
+ require('apexcharts/radar');
15
+ require('apexcharts/boxPlot');
16
+ require('apexcharts/rangeBar');
13
17
 
14
18
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
15
19
 
16
- var ReactApexChart__default = /*#__PURE__*/_interopDefault(ReactApexChart);
20
+ var ReactApexChart13__default = /*#__PURE__*/_interopDefault(ReactApexChart13);
17
21
 
18
22
  var COSMOS_BRAND = "#465fff";
19
23
  var COSMOS_PALETTE = ["#465fff", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6"];
20
24
  var DARK_THEME_CLASSES = ["dark", "deep-blue"];
25
+ var BRAND_SCALE_LIGHT = [100, 300, 400, 500, 700];
26
+ var BRAND_SCALE_DARK = [900, 700, 500, 400, 300];
27
+ var BLUE_STEPS = {
28
+ 100: "#dde9ff",
29
+ 300: "#9cb9ff",
30
+ 400: "#7592ff",
31
+ 500: COSMOS_BRAND,
32
+ 700: "#2a31d8",
33
+ 900: "#262e89"
34
+ };
21
35
  var detectDark = () => {
22
36
  if (typeof document === "undefined") return false;
23
37
  const { classList } = document.documentElement;
@@ -32,6 +46,11 @@ var readChartColors = () => {
32
46
  return {
33
47
  dark,
34
48
  brand: readCssVar("--color-brand-500", COSMOS_BRAND),
49
+ brandScale: (dark ? BRAND_SCALE_DARK : BRAND_SCALE_LIGHT).map(
50
+ (step) => readCssVar(`--color-brand-${step}`, BLUE_STEPS[step])
51
+ ),
52
+ // The card background (`bg-white dark:bg-gray-900`).
53
+ surface: dark ? readCssVar("--color-gray-900", "#111827") : readCssVar("--color-white", "#fff"),
35
54
  grid: dark ? readCssVar("--color-gray-800", "#1f2937") : readCssVar("--color-gray-200", "#e5e7eb"),
36
55
  axis: dark ? readCssVar("--color-gray-400", "#9ca3af") : readCssVar("--color-gray-500", "#6b7280")
37
56
  };
@@ -51,7 +70,14 @@ var useHtmlAppearance = (read) => {
51
70
  };
52
71
  var useDarkMode = () => useHtmlAppearance(detectDark);
53
72
  var useChartTheme = () => {
54
- const { dark, brand, grid: gridColor, axis } = useHtmlAppearance(readChartColors);
73
+ const {
74
+ dark,
75
+ brand,
76
+ brandScale,
77
+ surface,
78
+ grid: gridColor,
79
+ axis
80
+ } = useHtmlAppearance(readChartColors);
55
81
  const grid = {
56
82
  borderColor: gridColor,
57
83
  strokeDashArray: 4
@@ -63,7 +89,15 @@ var useChartTheme = () => {
63
89
  fontFamily: "inherit"
64
90
  }
65
91
  };
66
- return { dark, grid, axisLabels, brand, palette: [brand, ...COSMOS_PALETTE.slice(1)] };
92
+ return {
93
+ dark,
94
+ grid,
95
+ axisLabels,
96
+ brand,
97
+ brandScale,
98
+ surface,
99
+ palette: [brand, ...COSMOS_PALETTE.slice(1)]
100
+ };
67
101
  };
68
102
 
69
103
  // src/escape.ts
@@ -115,7 +149,7 @@ var LineAreaChart = ({
115
149
  y: { title: { formatter: (name) => `${escapeHtml(name)}: ` } }
116
150
  }
117
151
  };
118
- return /* @__PURE__ */ jsxRuntime.jsx(ReactApexChart__default.default, { type: "area", options, series, height, width });
152
+ return /* @__PURE__ */ jsxRuntime.jsx(ReactApexChart13__default.default, { type: "area", options, series, height, width });
119
153
  };
120
154
  var defaultGenerator = /* @__PURE__ */ (() => {
121
155
  let last = 50;
@@ -178,7 +212,7 @@ var RealtimeChart = ({
178
212
  tooltip: { theme: "dark" }
179
213
  };
180
214
  return /* @__PURE__ */ jsxRuntime.jsx(
181
- ReactApexChart__default.default,
215
+ ReactApexChart13__default.default,
182
216
  {
183
217
  type: "line",
184
218
  options,
@@ -215,7 +249,7 @@ var RadialBarChart = ({
215
249
  }
216
250
  };
217
251
  return /* @__PURE__ */ jsxRuntime.jsx(
218
- ReactApexChart__default.default,
252
+ ReactApexChart13__default.default,
219
253
  {
220
254
  type: "radialBar",
221
255
  options,
@@ -260,7 +294,7 @@ var GradientRadial = ({
260
294
  labels: [label]
261
295
  };
262
296
  return /* @__PURE__ */ jsxRuntime.jsx(
263
- ReactApexChart__default.default,
297
+ ReactApexChart13__default.default,
264
298
  {
265
299
  type: "radialBar",
266
300
  options,
@@ -295,7 +329,7 @@ var SemiCircleGauge = ({
295
329
  labels: [label]
296
330
  };
297
331
  return /* @__PURE__ */ jsxRuntime.jsx(
298
- ReactApexChart__default.default,
332
+ ReactApexChart13__default.default,
299
333
  {
300
334
  type: "radialBar",
301
335
  options,
@@ -329,7 +363,7 @@ var StrokedGauge = ({
329
363
  labels: [label]
330
364
  };
331
365
  return /* @__PURE__ */ jsxRuntime.jsx(
332
- ReactApexChart__default.default,
366
+ ReactApexChart13__default.default,
333
367
  {
334
368
  type: "radialBar",
335
369
  options,
@@ -361,7 +395,7 @@ var DonutChart = ({
361
395
  }
362
396
  }
363
397
  };
364
- return /* @__PURE__ */ jsxRuntime.jsx(ReactApexChart__default.default, { type: "donut", options, series, height, width });
398
+ return /* @__PURE__ */ jsxRuntime.jsx(ReactApexChart13__default.default, { type: "donut", options, series, height, width });
365
399
  };
366
400
  var DonutRightLegend = (props) => /* @__PURE__ */ jsxRuntime.jsx(DonutChart, { ...props, rightLegend: true });
367
401
  var Sparkline = ({
@@ -380,7 +414,7 @@ var Sparkline = ({
380
414
  tooltip: { fixed: { enabled: false }, x: { show: false }, marker: { show: false } }
381
415
  };
382
416
  return /* @__PURE__ */ jsxRuntime.jsx(
383
- ReactApexChart__default.default,
417
+ ReactApexChart13__default.default,
384
418
  {
385
419
  type: variant,
386
420
  options,
@@ -426,7 +460,7 @@ var TreemapChart = ({ series, height = 320, width = "100%" }) => {
426
460
  plotOptions: { treemap: { distributed: true, enableShades: false } }
427
461
  };
428
462
  return /* @__PURE__ */ jsxRuntime.jsx(
429
- ReactApexChart__default.default,
463
+ ReactApexChart13__default.default,
430
464
  {
431
465
  type: "treemap",
432
466
  options,
@@ -506,18 +540,629 @@ var BarChart = ({
506
540
  fill: { opacity: 1 },
507
541
  stroke: { show: false }
508
542
  };
509
- return /* @__PURE__ */ jsxRuntime.jsx(ReactApexChart__default.default, { type: "bar", options, series, height, width });
543
+ return /* @__PURE__ */ jsxRuntime.jsx(ReactApexChart13__default.default, { type: "bar", options, series, height, width });
544
+ };
545
+ var NICE_STEPS = [1, 2, 2.5, 3, 4, 5, 6, 8, 10];
546
+ var niceStep = (value) => {
547
+ const magnitude = 10 ** Math.floor(Math.log10(value));
548
+ const step = NICE_STEPS.find((m) => m * magnitude >= value) ?? 10;
549
+ return step * magnitude;
550
+ };
551
+ var round = (value) => Number(value.toPrecision(12));
552
+ var evenRanges = (values, colors) => {
553
+ const finite = values.filter(Number.isFinite);
554
+ if (finite.length === 0 || colors.length === 0) return [];
555
+ const min = finite.reduce((a, b) => Math.min(a, b));
556
+ const max = finite.reduce((a, b) => Math.max(a, b));
557
+ let step = niceStep((max - min) / colors.length || Math.abs(max) || 1);
558
+ let start = Math.floor(min / step) * step;
559
+ while (start + step * colors.length < max) {
560
+ step = niceStep(step * 1.001);
561
+ start = Math.floor(min / step) * step;
562
+ }
563
+ return colors.map((color, i) => ({
564
+ from: round(start + step * i),
565
+ to: round(start + step * (i + 1)),
566
+ color
567
+ }));
568
+ };
569
+ var textColorOn = (color) => {
570
+ const hex = /^#([0-9a-f]{6})$/i.exec(color)?.[1];
571
+ if (!hex) return void 0;
572
+ const [r, g, b] = [0, 2, 4].map((i) => {
573
+ const c = parseInt(hex.slice(i, i + 2), 16) / 255;
574
+ return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
575
+ });
576
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b > 0.2 ? "#101828" : "#ffffff";
577
+ };
578
+ var HeatmapChart = ({
579
+ series,
580
+ categories,
581
+ colors,
582
+ ranges,
583
+ formatValue,
584
+ showValues = false,
585
+ showLegend = true,
586
+ height = 320,
587
+ width = "100%"
588
+ }) => {
589
+ const { axisLabels, brandScale, surface } = useChartTheme();
590
+ const valueFormatter = formatValue ?? ((v) => String(v));
591
+ const colorRanges = (ranges ?? evenRanges(
592
+ series.flatMap((s) => s.data),
593
+ colors ?? brandScale
594
+ )).map((range) => ({
595
+ ...range,
596
+ name: range.name ?? `${valueFormatter(range.from)} \u2013 ${valueFormatter(range.to)}`,
597
+ foreColor: textColorOn(range.color)
598
+ }));
599
+ const options = {
600
+ chart: {
601
+ type: "heatmap",
602
+ toolbar: { show: false },
603
+ fontFamily: "inherit"
604
+ },
605
+ dataLabels: {
606
+ enabled: showValues,
607
+ formatter: (v) => valueFormatter(Number(v)),
608
+ style: { fontSize: "11px", fontWeight: 500 }
609
+ },
610
+ plotOptions: {
611
+ heatmap: {
612
+ radius: 3,
613
+ // The ranges carry the exact colors: no shading on top of them.
614
+ enableShades: false,
615
+ colorScale: { ranges: colorRanges }
616
+ }
617
+ },
618
+ // Gaps between the cells, in the card's color.
619
+ stroke: { width: 2, colors: [surface] },
620
+ grid: { show: false },
621
+ // One labels object per axis: ApexCharts mutates them. Narrow columns
622
+ // skip the labels that would overlap instead of rotating them into a
623
+ // pile; the tooltip still names every column.
624
+ xaxis: {
625
+ categories,
626
+ labels: { ...axisLabels, rotate: 0 },
627
+ axisBorder: { show: false },
628
+ axisTicks: { show: false },
629
+ tooltip: { enabled: false }
630
+ },
631
+ // ApexCharts draws the first series at the bottom; read top-down instead.
632
+ yaxis: { reversed: true, labels: { ...axisLabels } },
633
+ legend: {
634
+ show: showLegend,
635
+ position: "top",
636
+ horizontalAlign: "right",
637
+ labels: { colors: axisLabels.style.colors },
638
+ // The default stroke outlines the swatches in white, glaring in dark themes.
639
+ markers: { size: 5, strokeWidth: 0 },
640
+ formatter: (name) => escapeHtml(name)
641
+ },
642
+ // The tooltip and the legend are HTML: escape row names, categories,
643
+ // range names and values. The title is the hovered column's category.
644
+ tooltip: {
645
+ theme: "dark",
646
+ x: {
647
+ show: true,
648
+ formatter: (v, opts) => escapeHtml(opts === void 0 ? v : categories[opts.dataPointIndex] ?? v)
649
+ },
650
+ y: {
651
+ formatter: (v) => escapeHtml(valueFormatter(Number(v))),
652
+ title: { formatter: (name) => `${escapeHtml(name)}: ` }
653
+ }
654
+ }
655
+ };
656
+ return /* @__PURE__ */ jsxRuntime.jsx(
657
+ ReactApexChart13__default.default,
658
+ {
659
+ type: "heatmap",
660
+ options,
661
+ series,
662
+ height,
663
+ width
664
+ }
665
+ );
666
+ };
667
+ var RadarChart = ({
668
+ series,
669
+ categories,
670
+ colors,
671
+ formatValue,
672
+ showLegend,
673
+ max,
674
+ height = 340,
675
+ width = "100%"
676
+ }) => {
677
+ const { grid, axisLabels, palette } = useChartTheme();
678
+ const legendVisible = showLegend ?? series.length > 1;
679
+ const valueFormatter = formatValue ?? ((v) => String(v));
680
+ const options = {
681
+ chart: {
682
+ type: "radar",
683
+ toolbar: { show: false },
684
+ fontFamily: "inherit"
685
+ },
686
+ colors: colors ?? palette,
687
+ dataLabels: { enabled: false },
688
+ stroke: { width: 2 },
689
+ fill: { opacity: 0.15 },
690
+ // The tooltip is hit-tested on the markers: keep them.
691
+ markers: { size: 3, strokeWidth: 0 },
692
+ // ApexCharts reserves part of an axis name's width only, so on a narrow
693
+ // chart the names at the side vertices ran off the edge. No effect on a
694
+ // wide chart: its size follows the height.
695
+ grid: { padding: { left: 24, right: 24 } },
696
+ plotOptions: {
697
+ radar: {
698
+ polygons: {
699
+ strokeColors: grid?.borderColor,
700
+ connectorColors: grid?.borderColor,
701
+ fill: { colors: ["transparent"] }
702
+ }
703
+ }
704
+ },
705
+ // One labels object per axis: ApexCharts mutates them.
706
+ xaxis: { categories, labels: { ...axisLabels } },
707
+ yaxis: {
708
+ max,
709
+ labels: { ...axisLabels, formatter: (val) => valueFormatter(Number(val)) }
710
+ },
711
+ legend: {
712
+ show: legendVisible,
713
+ position: "top",
714
+ horizontalAlign: "right",
715
+ labels: { colors: axisLabels.style.colors },
716
+ // The default stroke outlines the swatches in white, glaring in dark themes.
717
+ markers: { size: 5, strokeWidth: 0 },
718
+ formatter: (name) => escapeHtml(name)
719
+ },
720
+ // The tooltip and the legend are HTML: escape names, categories and
721
+ // values. The title is the hovered axis.
722
+ tooltip: {
723
+ theme: "dark",
724
+ x: {
725
+ formatter: (v, opts) => escapeHtml(opts === void 0 ? v : categories[opts.dataPointIndex] ?? v)
726
+ },
727
+ y: {
728
+ formatter: (v) => escapeHtml(valueFormatter(Number(v))),
729
+ title: { formatter: (name) => `${escapeHtml(name)}: ` }
730
+ }
731
+ }
732
+ };
733
+ return /* @__PURE__ */ jsxRuntime.jsx(ReactApexChart13__default.default, { type: "radar", options, series, height, width });
734
+ };
735
+
736
+ // src/tooltip.ts
737
+ var line = (content) => `<div class="apexcharts-tooltip-series-group apexcharts-active" style="display:flex">${content}</div>`;
738
+ var tooltipHtml = ({ title, series, rows }) => (title === void 0 ? "" : `<div class="apexcharts-tooltip-title">${escapeHtml(title)}</div>`) + (series === void 0 ? "" : line(
739
+ `<span class="apexcharts-tooltip-marker" style="background-color:${escapeHtml(series.color)};border-radius:50%"></span><span class="apexcharts-tooltip-text-y-label">${escapeHtml(series.name)}</span>`
740
+ )) + rows.map(
741
+ ([label, value]) => line(
742
+ `<span class="apexcharts-tooltip-text-y-label">${escapeHtml(label)}:</span><span class="apexcharts-tooltip-text-y-value">${escapeHtml(value)}</span>`
743
+ )
744
+ ).join("");
745
+ var formatNumber = (value) => String(Number(value.toFixed(2)));
746
+ var niceAxis = (values, pad = 0, ticks = 5) => {
747
+ const low = Math.min(...values);
748
+ const high = Math.max(...values);
749
+ const margin = (high - low) * pad;
750
+ const min = low >= 0 ? Math.max(low - margin, 0) : low - margin;
751
+ const max = high <= 0 ? Math.min(high + margin, 0) : high + margin;
752
+ if (!(max > min)) return {};
753
+ const rough = (max - min) / ticks;
754
+ const magnitude = 10 ** Math.floor(Math.log10(rough));
755
+ const step = [1, 2, 2.5, 5, 10].map((f) => f * magnitude).find((s) => s >= rough) ?? rough;
756
+ const round2 = (value) => Number(value.toPrecision(12));
757
+ const niceMin = round2(Math.floor(min / step) * step);
758
+ const niceMax = round2(Math.ceil(max / step) * step);
759
+ return { min: niceMin, max: niceMax, tickAmount: Math.round((niceMax - niceMin) / step) };
760
+ };
761
+ var xyOptions = ({ grid, axisLabels, palette }, {
762
+ series,
763
+ xTitle,
764
+ yTitle,
765
+ colors,
766
+ formatX = formatNumber,
767
+ formatY = formatNumber,
768
+ showLegend
769
+ }, { pad = 0, extraRows = () => [] } = {}) => {
770
+ const seriesColors = colors ?? palette;
771
+ const points = series.flatMap(({ data }) => data);
772
+ const axisTitle = (text) => text === void 0 ? void 0 : {
773
+ text,
774
+ style: {
775
+ color: axisLabels.style.colors,
776
+ fontSize: "12px",
777
+ fontFamily: "inherit",
778
+ fontWeight: 500
779
+ }
780
+ };
781
+ return {
782
+ chart: { toolbar: { show: false }, zoom: { enabled: false }, fontFamily: "inherit" },
783
+ colors: seriesColors,
784
+ dataLabels: { enabled: false },
785
+ grid,
786
+ // One labels object per axis: ApexCharts writes formatters onto them.
787
+ // Axis labels and titles are SVG text and stay unescaped.
788
+ xaxis: {
789
+ type: "numeric",
790
+ ...niceAxis(
791
+ points.map(({ x }) => x),
792
+ pad
793
+ ),
794
+ title: axisTitle(xTitle),
795
+ labels: { ...axisLabels, formatter: (value) => formatX(Number(value)) },
796
+ axisBorder: { show: false },
797
+ axisTicks: { show: false },
798
+ // The x-axis tooltip is HTML and repeats the x value of the tooltip.
799
+ tooltip: { enabled: false }
800
+ },
801
+ yaxis: {
802
+ ...niceAxis(
803
+ points.map(({ y }) => y),
804
+ pad
805
+ ),
806
+ title: axisTitle(yTitle),
807
+ labels: { ...axisLabels, formatter: (value) => formatY(value) }
808
+ },
809
+ legend: {
810
+ show: showLegend ?? series.length > 1,
811
+ position: "top",
812
+ horizontalAlign: "right",
813
+ labels: { colors: axisLabels.style.colors },
814
+ markers: { size: 5 },
815
+ formatter: (name) => escapeHtml(name)
816
+ },
817
+ // The tooltip is HTML: tooltipHtml escapes the label, the series name and
818
+ // the values.
819
+ tooltip: {
820
+ theme: "dark",
821
+ custom: ({ seriesIndex, dataPointIndex }) => {
822
+ const { name, data } = series[seriesIndex];
823
+ const point = data[dataPointIndex];
824
+ return tooltipHtml({
825
+ title: point.label,
826
+ series: { name, color: seriesColors[seriesIndex % seriesColors.length] },
827
+ rows: [
828
+ [xTitle ?? "x", formatX(point.x)],
829
+ [yTitle ?? "y", formatY(point.y)],
830
+ ...extraRows(point)
831
+ ]
832
+ });
833
+ }
834
+ }
835
+ };
836
+ };
837
+ var ScatterChart = ({ height = 320, width = "100%", ...props }) => {
838
+ const base = xyOptions(useChartTheme(), props);
839
+ const options = {
840
+ ...base,
841
+ chart: { ...base.chart, type: "scatter" },
842
+ markers: { size: 6, strokeWidth: 0, hover: { sizeOffset: 2 } }
843
+ };
844
+ return /* @__PURE__ */ jsxRuntime.jsx(
845
+ ReactApexChart13__default.default,
846
+ {
847
+ type: "scatter",
848
+ options,
849
+ series: props.series,
850
+ height,
851
+ width
852
+ }
853
+ );
854
+ };
855
+ var BubbleChart = ({
856
+ sizeTitle = "Size",
857
+ formatSize = formatNumber,
858
+ height = 320,
859
+ width = "100%",
860
+ ...props
861
+ }) => {
862
+ const theme = useChartTheme();
863
+ const base = xyOptions(theme, props, {
864
+ // Room for the bubbles at the edges of the plot.
865
+ pad: 0.08,
866
+ extraRows: (point) => [[sizeTitle, formatSize(point.z)]]
867
+ });
868
+ const options = {
869
+ ...base,
870
+ chart: { ...base.chart, type: "bubble" },
871
+ plotOptions: { bubble: { minBubbleRadius: 4 } },
872
+ // Translucent bubbles, outlined in their own color (ApexCharts' white
873
+ // outline glares on the dark themes), keep the overlapping ones readable.
874
+ fill: { opacity: 0.55 },
875
+ markers: { strokeWidth: 1, strokeColors: props.colors ?? theme.palette }
876
+ };
877
+ return /* @__PURE__ */ jsxRuntime.jsx(
878
+ ReactApexChart13__default.default,
879
+ {
880
+ type: "bubble",
881
+ options,
882
+ series: props.series,
883
+ height,
884
+ width
885
+ }
886
+ );
887
+ };
888
+ var ROWS = [
889
+ ["Max", 4],
890
+ ["Q3", 3],
891
+ ["Median", 2],
892
+ ["Q1", 1],
893
+ ["Min", 0]
894
+ ];
895
+ var BoxPlotChart = ({
896
+ series,
897
+ categories,
898
+ orientation = "vertical",
899
+ colors,
900
+ formatValue,
901
+ showLegend,
902
+ height = 320,
903
+ width = "100%"
904
+ }) => {
905
+ const { grid, axisLabels, palette } = useChartTheme();
906
+ const horizontal = orientation === "horizontal";
907
+ const seriesColors = colors ?? palette;
908
+ const valueFormatter = formatValue ?? ((v) => String(v));
909
+ const categoryLabels = () => ({ ...axisLabels });
910
+ const valueLabels = () => ({
911
+ ...axisLabels,
912
+ formatter: (value) => valueFormatter(Number(value))
913
+ });
914
+ const options = {
915
+ chart: {
916
+ type: "boxPlot",
917
+ toolbar: { show: false },
918
+ zoom: { enabled: false },
919
+ fontFamily: "inherit"
920
+ },
921
+ colors: seriesColors,
922
+ plotOptions: {
923
+ bar: { horizontal, columnWidth: "50%", barHeight: "50%" },
924
+ // Both halves take the series color: a translucent fill, and an outline,
925
+ // median and whiskers drawn in the full color (ApexCharts' defaults are
926
+ // fixed colors, with a near-black stroke lost on the dark themes).
927
+ boxPlot: { colors: { upper: seriesColors, lower: seriesColors } }
928
+ },
929
+ fill: { opacity: 0.35 },
930
+ stroke: { width: 1.5, colors: seriesColors },
931
+ grid,
932
+ xaxis: {
933
+ labels: horizontal ? valueLabels() : categoryLabels(),
934
+ axisBorder: { show: false },
935
+ axisTicks: { show: false },
936
+ // The x-axis tooltip is HTML and repeats the tooltip title.
937
+ tooltip: { enabled: false }
938
+ },
939
+ yaxis: { labels: horizontal ? categoryLabels() : valueLabels() },
940
+ // Horizontal, the value labels sit side by side and run into each other
941
+ // on a phone: keep three of them.
942
+ responsive: horizontal ? [{ breakpoint: 640, options: { xaxis: { tickAmount: 2 } } }] : [],
943
+ legend: {
944
+ show: showLegend ?? series.length > 1,
945
+ position: "top",
946
+ horizontalAlign: "right",
947
+ labels: { colors: axisLabels.style.colors },
948
+ markers: { size: 5 },
949
+ formatter: (name) => escapeHtml(name)
950
+ },
951
+ // ApexCharts' own box plot tooltip prints the values raw. This one is
952
+ // HTML too: tooltipHtml escapes the category, the series name and values.
953
+ tooltip: {
954
+ theme: "dark",
955
+ custom: ({ seriesIndex, dataPointIndex }) => {
956
+ const { name, data } = series[seriesIndex];
957
+ const summary = data[dataPointIndex];
958
+ return tooltipHtml({
959
+ title: categories[dataPointIndex],
960
+ series: series.length > 1 ? { name, color: seriesColors[seriesIndex % seriesColors.length] } : void 0,
961
+ rows: ROWS.map(([label, index]) => [label, valueFormatter(summary[index])])
962
+ });
963
+ }
964
+ }
965
+ };
966
+ const chartSeries = series.map(({ name, data }) => ({
967
+ name,
968
+ data: data.map((y, index) => ({ x: categories[index], y }))
969
+ }));
970
+ return /* @__PURE__ */ jsxRuntime.jsx(
971
+ ReactApexChart13__default.default,
972
+ {
973
+ type: "boxPlot",
974
+ options,
975
+ series: chartSeries,
976
+ height,
977
+ width
978
+ }
979
+ );
980
+ };
981
+ var UTC_DATE_TIME = new Intl.DateTimeFormat("en-GB", {
982
+ day: "2-digit",
983
+ month: "short",
984
+ hour: "2-digit",
985
+ minute: "2-digit",
986
+ hourCycle: "h23",
987
+ timeZone: "UTC"
988
+ });
989
+ var defaultFormatDate = (timestamp) => UTC_DATE_TIME.format(timestamp);
990
+ var RangeBarChart = ({
991
+ series,
992
+ groupRows = false,
993
+ colors,
994
+ formatDate = defaultFormatDate,
995
+ showLegend,
996
+ height = 320,
997
+ width = "100%"
998
+ }) => {
999
+ const { grid, axisLabels, palette } = useChartTheme();
1000
+ const seriesColors = colors ?? palette;
1001
+ const legendVisible = showLegend ?? series.length > 1;
1002
+ const lanes = groupRows ? 1 : series.length;
1003
+ const tooltip = ({
1004
+ seriesIndex,
1005
+ dataPointIndex
1006
+ }) => {
1007
+ const s = series[seriesIndex];
1008
+ const point = s?.data[dataPointIndex];
1009
+ if (!point) return "";
1010
+ const [start, end] = point.y;
1011
+ return tooltipHtml({
1012
+ title: point.x,
1013
+ series: { name: s.name, color: seriesColors[seriesIndex % seriesColors.length] },
1014
+ rows: [
1015
+ ["Start", formatDate(start)],
1016
+ ["End", formatDate(end)]
1017
+ ]
1018
+ });
1019
+ };
1020
+ const options = {
1021
+ chart: {
1022
+ type: "rangeBar",
1023
+ toolbar: { show: false },
1024
+ zoom: { enabled: false },
1025
+ fontFamily: "inherit"
1026
+ },
1027
+ colors: seriesColors,
1028
+ dataLabels: { enabled: false },
1029
+ plotOptions: {
1030
+ bar: {
1031
+ horizontal: true,
1032
+ // Without groupRows each series gets its own lane in the row: give
1033
+ // the bars more of their (thinner) lane.
1034
+ barHeight: lanes > 1 ? "80%" : "60%",
1035
+ borderRadius: 3,
1036
+ borderRadiusApplication: "around",
1037
+ rangeBarGroupRows: groupRows
1038
+ }
1039
+ },
1040
+ // Time runs left to right: vertical grid lines, plus a line between rows.
1041
+ grid: { ...grid, xaxis: { lines: { show: true } }, yaxis: { lines: { show: true } } },
1042
+ // One labels object per axis: ApexCharts mutates them.
1043
+ xaxis: {
1044
+ type: "datetime",
1045
+ labels: { ...axisLabels, datetimeUTC: true },
1046
+ axisBorder: { show: false },
1047
+ axisTicks: { show: false }
1048
+ },
1049
+ yaxis: { labels: { ...axisLabels } },
1050
+ legend: {
1051
+ show: legendVisible,
1052
+ position: "top",
1053
+ horizontalAlign: "right",
1054
+ labels: { colors: axisLabels.style.colors },
1055
+ markers: { size: 5 },
1056
+ formatter: (name) => escapeHtml(name)
1057
+ },
1058
+ tooltip: { theme: "dark", custom: tooltip },
1059
+ fill: { opacity: 1 }
1060
+ };
1061
+ return /* @__PURE__ */ jsxRuntime.jsx(
1062
+ ReactApexChart13__default.default,
1063
+ {
1064
+ type: "rangeBar",
1065
+ options,
1066
+ series,
1067
+ height,
1068
+ width
1069
+ }
1070
+ );
1071
+ };
1072
+ var SIDES = ["left", "right"];
1073
+ var axisOf = (s) => s.axis ?? "left";
1074
+ var MixedChart = ({
1075
+ series,
1076
+ categories,
1077
+ colors,
1078
+ formatValue,
1079
+ formatRightValue,
1080
+ showLegend,
1081
+ height = 320,
1082
+ width = "100%"
1083
+ }) => {
1084
+ const { grid, axisLabels, palette } = useChartTheme();
1085
+ const legendVisible = showLegend ?? series.length > 1;
1086
+ const formatters = { left: formatValue, right: formatRightValue };
1087
+ const usedSides = SIDES.filter((side) => series.some((s) => axisOf(s) === side));
1088
+ const sides = usedSides.length > 0 ? usedSides : SIDES.slice(0, 1);
1089
+ const yaxis = sides.map((side) => ({
1090
+ seriesName: sides.length > 1 ? series.filter((s) => axisOf(s) === side).map((s) => s.name) : void 0,
1091
+ opposite: side === "right",
1092
+ labels: { ...axisLabels, formatter: formatters[side] }
1093
+ }));
1094
+ const options = {
1095
+ chart: {
1096
+ type: "line",
1097
+ toolbar: { show: false },
1098
+ zoom: { enabled: false },
1099
+ fontFamily: "inherit"
1100
+ },
1101
+ colors: colors ?? palette,
1102
+ dataLabels: { enabled: false },
1103
+ // Lines only: columns have no stroke. monotoneCubic stays smooth without
1104
+ // overshooting the samples, so a latency line never dips below its data.
1105
+ stroke: { width: series.map((s) => s.type === "line" ? 3 : 0), curve: "monotoneCubic" },
1106
+ plotOptions: {
1107
+ bar: { columnWidth: "55%", borderRadius: 4, borderRadiusApplication: "end" }
1108
+ },
1109
+ grid,
1110
+ xaxis: {
1111
+ categories,
1112
+ labels: { ...axisLabels },
1113
+ axisBorder: { show: false },
1114
+ axisTicks: { show: false }
1115
+ },
1116
+ yaxis,
1117
+ legend: {
1118
+ show: legendVisible,
1119
+ position: "top",
1120
+ horizontalAlign: "right",
1121
+ labels: { colors: axisLabels.style.colors },
1122
+ markers: { size: 5 },
1123
+ // ApexCharts stacks the series of each y axis in a column of their own:
1124
+ // keep one row, like the other charts.
1125
+ clusterGroupedSeries: false,
1126
+ formatter: (name) => escapeHtml(name)
1127
+ },
1128
+ // The tooltip is HTML: escape the category, the series names and the
1129
+ // values. ApexCharts hands the x formatter the point's position on a line
1130
+ // chart's axis, not its category, so read the category back by index.
1131
+ tooltip: {
1132
+ theme: "dark",
1133
+ x: {
1134
+ formatter: (v, opts) => escapeHtml(opts === void 0 ? v : categories[opts.dataPointIndex] ?? v)
1135
+ },
1136
+ y: {
1137
+ formatter: (v, opts) => {
1138
+ const s = opts && series[opts.seriesIndex];
1139
+ const format = (s && formatters[axisOf(s)]) ?? String;
1140
+ return escapeHtml(format(Number(v)));
1141
+ },
1142
+ title: { formatter: (name) => `${escapeHtml(name)}: ` }
1143
+ }
1144
+ },
1145
+ fill: { opacity: 1 }
1146
+ };
1147
+ return /* @__PURE__ */ jsxRuntime.jsx(ReactApexChart13__default.default, { type: "line", options, series, height, width });
510
1148
  };
511
1149
 
512
1150
  exports.BarChart = BarChart;
1151
+ exports.BoxPlotChart = BoxPlotChart;
1152
+ exports.BubbleChart = BubbleChart;
513
1153
  exports.COSMOS_BRAND = COSMOS_BRAND;
514
1154
  exports.COSMOS_PALETTE = COSMOS_PALETTE;
515
1155
  exports.DonutChart = DonutChart;
516
1156
  exports.DonutRightLegend = DonutRightLegend;
517
1157
  exports.GradientRadial = GradientRadial;
1158
+ exports.HeatmapChart = HeatmapChart;
518
1159
  exports.LineAreaChart = LineAreaChart;
1160
+ exports.MixedChart = MixedChart;
1161
+ exports.RadarChart = RadarChart;
519
1162
  exports.RadialBarChart = RadialBarChart;
1163
+ exports.RangeBarChart = RangeBarChart;
520
1164
  exports.RealtimeChart = RealtimeChart;
1165
+ exports.ScatterChart = ScatterChart;
521
1166
  exports.SemiCircleGauge = SemiCircleGauge;
522
1167
  exports.Sparkline = Sparkline;
523
1168
  exports.SparklineGroup = SparklineGroup;