@sckyzo/cosmos-charts 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/README.md +107 -22
  3. package/THIRD_PARTY_NOTICES.md +81 -0
  4. package/dist/BarChart.cjs +137 -0
  5. package/dist/BarChart.cjs.map +1 -0
  6. package/dist/BarChart.js +135 -0
  7. package/dist/BarChart.js.map +1 -0
  8. package/dist/BoxPlotChart.cjs +214 -0
  9. package/dist/BoxPlotChart.cjs.map +1 -0
  10. package/dist/BoxPlotChart.js +212 -0
  11. package/dist/BoxPlotChart.js.map +1 -0
  12. package/dist/BumpChart.cjs +328 -0
  13. package/dist/BumpChart.cjs.map +1 -0
  14. package/dist/BumpChart.js +326 -0
  15. package/dist/BumpChart.js.map +1 -0
  16. package/dist/CalendarChart.cjs +216 -0
  17. package/dist/CalendarChart.cjs.map +1 -0
  18. package/dist/CalendarChart.js +214 -0
  19. package/dist/CalendarChart.js.map +1 -0
  20. package/dist/DonutChart.cjs +122 -0
  21. package/dist/DonutChart.cjs.map +1 -0
  22. package/dist/DonutChart.js +120 -0
  23. package/dist/DonutChart.js.map +1 -0
  24. package/dist/FunnelChart.cjs +422 -0
  25. package/dist/FunnelChart.cjs.map +1 -0
  26. package/dist/FunnelChart.js +420 -0
  27. package/dist/FunnelChart.js.map +1 -0
  28. package/dist/GradientRadial.cjs +51 -0
  29. package/dist/GradientRadial.cjs.map +1 -0
  30. package/dist/GradientRadial.js +49 -0
  31. package/dist/GradientRadial.js.map +1 -0
  32. package/dist/HeatmapChart.cjs +146 -0
  33. package/dist/HeatmapChart.cjs.map +1 -0
  34. package/dist/HeatmapChart.js +144 -0
  35. package/dist/HeatmapChart.js.map +1 -0
  36. package/dist/LineAreaChart.cjs +98 -0
  37. package/dist/LineAreaChart.cjs.map +1 -0
  38. package/dist/LineAreaChart.js +96 -0
  39. package/dist/LineAreaChart.js.map +1 -0
  40. package/dist/MixedChart.cjs +195 -0
  41. package/dist/MixedChart.cjs.map +1 -0
  42. package/dist/MixedChart.js +193 -0
  43. package/dist/MixedChart.js.map +1 -0
  44. package/dist/RadarChart.cjs +109 -0
  45. package/dist/RadarChart.cjs.map +1 -0
  46. package/dist/RadarChart.js +107 -0
  47. package/dist/RadarChart.js.map +1 -0
  48. package/dist/RadialBarChart.cjs +99 -0
  49. package/dist/RadialBarChart.cjs.map +1 -0
  50. package/dist/RadialBarChart.js +97 -0
  51. package/dist/RadialBarChart.js.map +1 -0
  52. package/dist/RangeBarChart.cjs +218 -0
  53. package/dist/RangeBarChart.cjs.map +1 -0
  54. package/dist/RangeBarChart.js +216 -0
  55. package/dist/RangeBarChart.js.map +1 -0
  56. package/dist/RealtimeChart.cjs +173 -0
  57. package/dist/RealtimeChart.cjs.map +1 -0
  58. package/dist/RealtimeChart.js +171 -0
  59. package/dist/RealtimeChart.js.map +1 -0
  60. package/dist/ScatterChart.cjs +134 -0
  61. package/dist/ScatterChart.cjs.map +1 -0
  62. package/dist/ScatterChart.js +131 -0
  63. package/dist/ScatterChart.js.map +1 -0
  64. package/dist/SemiCircleGauge.cjs +142 -0
  65. package/dist/SemiCircleGauge.cjs.map +1 -0
  66. package/dist/SemiCircleGauge.js +140 -0
  67. package/dist/SemiCircleGauge.js.map +1 -0
  68. package/dist/Sparkline.cjs +117 -0
  69. package/dist/Sparkline.cjs.map +1 -0
  70. package/dist/Sparkline.js +115 -0
  71. package/dist/Sparkline.js.map +1 -0
  72. package/dist/StrokedGauge.cjs +94 -0
  73. package/dist/StrokedGauge.cjs.map +1 -0
  74. package/dist/StrokedGauge.js +92 -0
  75. package/dist/StrokedGauge.js.map +1 -0
  76. package/dist/TreemapChart.cjs +263 -0
  77. package/dist/TreemapChart.cjs.map +1 -0
  78. package/dist/TreemapChart.js +261 -0
  79. package/dist/TreemapChart.js.map +1 -0
  80. package/dist/WaterfallChart.cjs +235 -0
  81. package/dist/WaterfallChart.cjs.map +1 -0
  82. package/dist/WaterfallChart.js +233 -0
  83. package/dist/WaterfallChart.js.map +1 -0
  84. package/dist/WorldMap.cjs +2088 -0
  85. package/dist/WorldMap.cjs.map +1 -0
  86. package/dist/WorldMap.js +603 -0
  87. package/dist/WorldMap.js.map +1 -0
  88. package/dist/chunk-3N43QT36.js +60 -0
  89. package/dist/chunk-3N43QT36.js.map +1 -0
  90. package/dist/chunk-5C2RLJYZ.js +11 -0
  91. package/dist/chunk-5C2RLJYZ.js.map +1 -0
  92. package/dist/chunk-6ALKZLN2.js +127 -0
  93. package/dist/chunk-6ALKZLN2.js.map +1 -0
  94. package/dist/chunk-6BKLL7LZ.cjs +30 -0
  95. package/dist/chunk-6BKLL7LZ.cjs.map +1 -0
  96. package/dist/chunk-6NRRABPF.cjs +64 -0
  97. package/dist/chunk-6NRRABPF.cjs.map +1 -0
  98. package/dist/chunk-AAYHG7YK.cjs +30 -0
  99. package/dist/chunk-AAYHG7YK.cjs.map +1 -0
  100. package/dist/chunk-AOSO5QHL.js +19 -0
  101. package/dist/chunk-AOSO5QHL.js.map +1 -0
  102. package/dist/chunk-BFEDLXVW.js +12 -0
  103. package/dist/chunk-BFEDLXVW.js.map +1 -0
  104. package/dist/chunk-DBZQI4HM.cjs +14 -0
  105. package/dist/chunk-DBZQI4HM.cjs.map +1 -0
  106. package/dist/chunk-F2PMFYJ5.cjs +40 -0
  107. package/dist/chunk-F2PMFYJ5.cjs.map +1 -0
  108. package/dist/chunk-FUZW3H5X.js +38 -0
  109. package/dist/chunk-FUZW3H5X.js.map +1 -0
  110. package/dist/chunk-GDZLYYL2.js +27 -0
  111. package/dist/chunk-GDZLYYL2.js.map +1 -0
  112. package/dist/chunk-GVTMZYOM.cjs +30 -0
  113. package/dist/chunk-GVTMZYOM.cjs.map +1 -0
  114. package/dist/chunk-GZRMVE4X.cjs +131 -0
  115. package/dist/chunk-GZRMVE4X.cjs.map +1 -0
  116. package/dist/chunk-HMH6DI7U.js +27 -0
  117. package/dist/chunk-HMH6DI7U.js.map +1 -0
  118. package/dist/chunk-ICL5K2CW.js +280 -0
  119. package/dist/chunk-ICL5K2CW.js.map +1 -0
  120. package/dist/chunk-IW6EWB26.cjs +21 -0
  121. package/dist/chunk-IW6EWB26.cjs.map +1 -0
  122. package/dist/chunk-K3R7JGOW.cjs +18 -0
  123. package/dist/chunk-K3R7JGOW.cjs.map +1 -0
  124. package/dist/chunk-LT3UC65O.cjs +68 -0
  125. package/dist/chunk-LT3UC65O.cjs.map +1 -0
  126. package/dist/chunk-MN4CDVOS.cjs +63 -0
  127. package/dist/chunk-MN4CDVOS.cjs.map +1 -0
  128. package/dist/chunk-OCD6JIIX.js +23 -0
  129. package/dist/chunk-OCD6JIIX.js.map +1 -0
  130. package/dist/chunk-RILUG7JB.js +44 -0
  131. package/dist/chunk-RILUG7JB.js.map +1 -0
  132. package/dist/chunk-RLHGPHC7.cjs +51 -0
  133. package/dist/chunk-RLHGPHC7.cjs.map +1 -0
  134. package/dist/chunk-SGG7XKOY.js +58 -0
  135. package/dist/chunk-SGG7XKOY.js.map +1 -0
  136. package/dist/chunk-T3K6Q34U.cjs +82 -0
  137. package/dist/chunk-T3K6Q34U.cjs.map +1 -0
  138. package/dist/chunk-TPH5T3DA.cjs +282 -0
  139. package/dist/chunk-TPH5T3DA.cjs.map +1 -0
  140. package/dist/chunk-TYQWZR3S.cjs +13 -0
  141. package/dist/chunk-TYQWZR3S.cjs.map +1 -0
  142. package/dist/chunk-UATB2IRY.js +51 -0
  143. package/dist/chunk-UATB2IRY.js.map +1 -0
  144. package/dist/chunk-UJIV5PVI.js +13 -0
  145. package/dist/chunk-UJIV5PVI.js.map +1 -0
  146. package/dist/chunk-URNXLVSK.js +44 -0
  147. package/dist/chunk-URNXLVSK.js.map +1 -0
  148. package/dist/chunk-VIOSQN4Z.js +79 -0
  149. package/dist/chunk-VIOSQN4Z.js.map +1 -0
  150. package/dist/chunk-X3YZP5WF.cjs +46 -0
  151. package/dist/chunk-X3YZP5WF.cjs.map +1 -0
  152. package/dist/chunk-YWYF5CCJ.js +61 -0
  153. package/dist/chunk-YWYF5CCJ.js.map +1 -0
  154. package/dist/chunk-Z4LZFMDH.cjs +60 -0
  155. package/dist/chunk-Z4LZFMDH.cjs.map +1 -0
  156. package/dist/index.cjs +154 -1166
  157. package/dist/index.cjs.map +1 -1
  158. package/dist/index.d.cts +470 -80
  159. package/dist/index.d.ts +470 -80
  160. package/dist/index.js +23 -1144
  161. package/dist/index.js.map +1 -1
  162. package/dist/theme.cjs +88 -0
  163. package/dist/theme.cjs.map +1 -0
  164. package/dist/theme.js +84 -0
  165. package/dist/theme.js.map +1 -0
  166. package/package.json +23 -12
@@ -0,0 +1,135 @@
1
+ "use client";
2
+ import { roundedBarShape, isOuterInStack } from './chunk-GDZLYYL2.js';
3
+ import { useCategoryKeys } from './chunk-FUZW3H5X.js';
4
+ import { referenceMarks } from './chunk-SGG7XKOY.js';
5
+ import { trimLabel, categoryAxis } from './chunk-HMH6DI7U.js';
6
+ import { useHiddenSeries, legendProps } from './chunk-6ALKZLN2.js';
7
+ import { ANIMATION } from './chunk-5C2RLJYZ.js';
8
+ import { useAxis, GRID_PROPS, xAxisTitle, yAxisTitle } from './chunk-RILUG7JB.js';
9
+ import { ChartTooltip } from './chunk-VIOSQN4Z.js';
10
+ import { hasNoData, seriesKey, toRows } from './chunk-UJIV5PVI.js';
11
+ import { ChartEmpty, frameProps } from './chunk-3N43QT36.js';
12
+ import { BORDER, seriesColor } from './chunk-UATB2IRY.js';
13
+ import { BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, Legend, Tooltip, Bar } from 'recharts';
14
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
15
+
16
+ var BarChart = ({
17
+ series,
18
+ categories,
19
+ orientation = "vertical",
20
+ stacked = false,
21
+ colors,
22
+ formatValue,
23
+ xTitle,
24
+ yTitle,
25
+ referenceLines,
26
+ referenceBands,
27
+ showLegend,
28
+ legendPosition = "top",
29
+ borderRadius = 4,
30
+ colorByValue,
31
+ distributed = false,
32
+ negativeColor,
33
+ emptyMessage = "No data",
34
+ ariaLabel,
35
+ children,
36
+ height = 320,
37
+ width
38
+ }) => {
39
+ const hidden = useHiddenSeries();
40
+ const axis = useAxis();
41
+ const categoryKeys = useCategoryKeys(orientation === "horizontal" ? "vertical" : "horizontal");
42
+ const name = ariaLabel ?? `Bar chart: ${series.map((s) => s.name).join(", ")}`;
43
+ if (hasNoData(series)) {
44
+ return /* @__PURE__ */ jsx(ChartEmpty, { message: emptyMessage, ariaLabel: name, height, width });
45
+ }
46
+ const horizontal = orientation === "horizontal";
47
+ const layout = horizontal ? "vertical" : "horizontal";
48
+ const fillFor = colorByValue || negativeColor !== void 0 || distributed ? (value, index) => colorByValue?.(value, index) ?? (negativeColor !== void 0 && value < 0 ? negativeColor : distributed ? seriesColor(index, colors) : void 0) : void 0;
49
+ const shown = series.map((_, i) => seriesKey(i)).filter((key) => !hidden.hidden.has(key));
50
+ return /* @__PURE__ */ jsxs(
51
+ BarChart$1,
52
+ {
53
+ ref: categoryKeys,
54
+ ...frameProps({ height, width, ariaLabel: name }),
55
+ data: toRows(categories, series),
56
+ layout,
57
+ stackOffset: "sign",
58
+ margin: { top: 4, right: 8, bottom: 0, left: 0 },
59
+ barGap: 4,
60
+ barCategoryGap: "22%",
61
+ children: [
62
+ /* @__PURE__ */ jsx(
63
+ CartesianGrid,
64
+ {
65
+ ...GRID_PROPS,
66
+ ...horizontal ? { horizontal: false, vertical: true } : {}
67
+ }
68
+ ),
69
+ horizontal ? /* @__PURE__ */ jsxs(Fragment, { children: [
70
+ /* @__PURE__ */ jsx(XAxis, { type: "number", tickFormatter: formatValue, ...axis, ...xAxisTitle(xTitle) }),
71
+ /* @__PURE__ */ jsx(
72
+ YAxis,
73
+ {
74
+ type: "category",
75
+ dataKey: "category",
76
+ width: "auto",
77
+ tickFormatter: trimLabel,
78
+ ...axis,
79
+ ...yAxisTitle(yTitle)
80
+ }
81
+ )
82
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
83
+ /* @__PURE__ */ jsx(
84
+ XAxis,
85
+ {
86
+ dataKey: "category",
87
+ ...axis,
88
+ ...xAxisTitle(xTitle),
89
+ ...categoryAxis(categories, xTitle)
90
+ }
91
+ ),
92
+ /* @__PURE__ */ jsx(YAxis, { width: "auto", tickFormatter: formatValue, ...axis, ...yAxisTitle(yTitle) })
93
+ ] }),
94
+ (showLegend ?? series.length > 1) && /* @__PURE__ */ jsx(Legend, { ...legendProps(legendPosition, hidden) }),
95
+ /* @__PURE__ */ jsx(
96
+ Tooltip,
97
+ {
98
+ content: /* @__PURE__ */ jsx(ChartTooltip, { format: formatValue, colorOf: fillFor }),
99
+ cursor: { fill: BORDER, fillOpacity: 0.35, radius: 8 },
100
+ animationDuration: 150
101
+ }
102
+ ),
103
+ series.map((s, i) => {
104
+ const key = seriesKey(i);
105
+ return /* @__PURE__ */ jsx(
106
+ Bar,
107
+ {
108
+ name: s.name,
109
+ dataKey: key,
110
+ fill: seriesColor(i, colors),
111
+ stackId: stacked ? "stack" : void 0,
112
+ maxBarSize: 44,
113
+ shape: roundedBarShape({
114
+ layout,
115
+ radius: borderRadius,
116
+ dataKey: key,
117
+ isOuter: stacked ? isOuterInStack(shown, key) : void 0,
118
+ fillFor
119
+ }),
120
+ hide: hidden.hidden.has(key),
121
+ ...ANIMATION
122
+ },
123
+ key
124
+ );
125
+ }),
126
+ referenceMarks({ referenceLines, referenceBands, axis: horizontal ? "x" : "y" }),
127
+ children
128
+ ]
129
+ }
130
+ );
131
+ };
132
+
133
+ export { BarChart };
134
+ //# sourceMappingURL=BarChart.js.map
135
+ //# sourceMappingURL=BarChart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/BarChart.tsx"],"names":["RechartsBarChart"],"mappings":"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","file":"BarChart.js","sourcesContent":["import {\n Bar,\n BarChart as RechartsBarChart,\n CartesianGrid,\n Legend,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\nimport { ANIMATION } from './core/animation';\nimport { GRID_PROPS, useAxis, xAxisTitle, yAxisTitle } from './core/axes';\nimport { categoryAxis, trimLabel } from './core/categoryAxis';\nimport { useCategoryKeys } from './core/categoryKeys';\nimport { ChartTooltip } from './core/ChartTooltip';\nimport { legendProps, useHiddenSeries } from './core/ChartLegend';\nimport { BORDER, seriesColor } from './core/colors';\nimport { hasNoData, seriesKey, toRows } from './core/data';\nimport { ChartEmpty, frameProps } from './core/frame';\nimport { referenceMarks } from './core/reference';\nimport { isOuterInStack, roundedBarShape } from './core/roundedBar';\nimport type {\n ChartAxisTitleProps,\n ChartEmptyProps,\n ChartLegendProps,\n ChartProps,\n ChartReferenceProps,\n} from './types';\n\nexport type BarChartOrientation = 'vertical' | 'horizontal';\n\nexport type BarChartProps = ChartProps &\n ChartEmptyProps &\n ChartLegendProps &\n ChartAxisTitleProps &\n ChartReferenceProps & {\n series: { name: string; data: number[] }[];\n categories: (string | number)[];\n /** `vertical` (default) draws bars upward; `horizontal` draws them rightward. */\n orientation?: BarChartOrientation;\n /** Stack multi-series bars instead of grouping them side-by-side. */\n stacked?: boolean;\n /** Override the default Cosmos palette. */\n colors?: string[];\n /** Format the numeric axis labels and the tooltip values. */\n formatValue?: (value: number) => string;\n /** Show the legend (auto-true when 2+ series). */\n showLegend?: boolean;\n /** Radius, in px, of the end of a bar away from the axis; only the outer end of a stack is rounded. Default 4. */\n borderRadius?: number;\n /**\n * The color of a bar from its value and the index of its category, for a threshold or a\n * ranking. Return `undefined` to keep the color the other rules give. Applies to every\n * series; the tooltip chip of a bar follows it, the legend keeps the series color.\n */\n colorByValue?: (value: number, index: number) => string | undefined;\n /** One palette color per category (`colors` cycles), instead of one per series. For a single series. */\n distributed?: boolean;\n /** The color of the bars below zero, for diverging bars. `colorByValue` wins over it. */\n negativeColor?: string;\n };\n\nexport const BarChart = ({\n series,\n categories,\n orientation = 'vertical',\n stacked = false,\n colors,\n formatValue,\n xTitle,\n yTitle,\n referenceLines,\n referenceBands,\n showLegend,\n legendPosition = 'top',\n borderRadius = 4,\n colorByValue,\n distributed = false,\n negativeColor,\n emptyMessage = 'No data',\n ariaLabel,\n children,\n height = 320,\n width,\n}: BarChartProps) => {\n const hidden = useHiddenSeries();\n const axis = useAxis();\n // Recharts names the layout after the axis the categories sit on.\n const categoryKeys = useCategoryKeys(orientation === 'horizontal' ? 'vertical' : 'horizontal');\n const name = ariaLabel ?? `Bar chart: ${series.map((s) => s.name).join(', ')}`;\n if (hasNoData(series)) {\n return <ChartEmpty message={emptyMessage} ariaLabel={name} height={height} width={width} />;\n }\n const horizontal = orientation === 'horizontal';\n // Recharts names the layout after the axis the categories sit on.\n const layout = horizontal ? 'vertical' : 'horizontal';\n // A bar's own color, in order of precedence: colorByValue, negativeColor, distributed.\n const fillFor =\n colorByValue || negativeColor !== undefined || distributed\n ? (value: number, index: number) =>\n colorByValue?.(value, index) ??\n (negativeColor !== undefined && value < 0\n ? negativeColor\n : distributed\n ? seriesColor(index, colors)\n : undefined)\n : undefined;\n const shown = series.map((_, i) => seriesKey(i)).filter((key) => !hidden.hidden.has(key));\n return (\n <RechartsBarChart\n ref={categoryKeys}\n {...frameProps({ height, width, ariaLabel: name })}\n data={toRows(categories, series)}\n layout={layout}\n // Stacks of both signs: the negative values stack down from zero, apart from the positive ones.\n stackOffset=\"sign\"\n margin={{ top: 4, right: 8, bottom: 0, left: 0 }}\n barGap={4}\n barCategoryGap=\"22%\"\n >\n <CartesianGrid\n {...GRID_PROPS}\n {...(horizontal ? { horizontal: false, vertical: true } : {})}\n />\n {horizontal ? (\n <>\n <XAxis type=\"number\" tickFormatter={formatValue} {...axis} {...xAxisTitle(xTitle)} />\n <YAxis\n type=\"category\"\n dataKey=\"category\"\n width=\"auto\"\n tickFormatter={trimLabel}\n {...axis}\n {...yAxisTitle(yTitle)}\n />\n </>\n ) : (\n <>\n <XAxis\n dataKey=\"category\"\n {...axis}\n {...xAxisTitle(xTitle)}\n {...categoryAxis(categories, xTitle)}\n />\n <YAxis width=\"auto\" tickFormatter={formatValue} {...axis} {...yAxisTitle(yTitle)} />\n </>\n )}\n {(showLegend ?? series.length > 1) && <Legend {...legendProps(legendPosition, hidden)} />}\n <Tooltip\n content={<ChartTooltip format={formatValue} colorOf={fillFor} />}\n cursor={{ fill: BORDER, fillOpacity: 0.35, radius: 8 }}\n animationDuration={150}\n />\n {series.map((s, i) => {\n const key = seriesKey(i);\n return (\n <Bar\n key={key}\n name={s.name}\n dataKey={key}\n fill={seriesColor(i, colors)}\n stackId={stacked ? 'stack' : undefined}\n maxBarSize={44}\n shape={roundedBarShape({\n layout,\n radius: borderRadius,\n dataKey: key,\n isOuter: stacked ? isOuterInStack(shown, key) : undefined,\n fillFor,\n })}\n hide={hidden.hidden.has(key)}\n {...ANIMATION}\n />\n );\n })}\n {referenceMarks({ referenceLines, referenceBands, axis: horizontal ? 'x' : 'y' })}\n {children}\n </RechartsBarChart>\n );\n};\n"]}
@@ -0,0 +1,214 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var chunkF2PMFYJ5_cjs = require('./chunk-F2PMFYJ5.cjs');
5
+ var chunkZ4LZFMDH_cjs = require('./chunk-Z4LZFMDH.cjs');
6
+ var chunk6BKLL7LZ_cjs = require('./chunk-6BKLL7LZ.cjs');
7
+ var chunkGZRMVE4X_cjs = require('./chunk-GZRMVE4X.cjs');
8
+ var chunkTYQWZR3S_cjs = require('./chunk-TYQWZR3S.cjs');
9
+ var chunkRLHGPHC7_cjs = require('./chunk-RLHGPHC7.cjs');
10
+ var chunkT3K6Q34U_cjs = require('./chunk-T3K6Q34U.cjs');
11
+ var chunkK3R7JGOW_cjs = require('./chunk-K3R7JGOW.cjs');
12
+ var chunk6NRRABPF_cjs = require('./chunk-6NRRABPF.cjs');
13
+ var chunkLT3UC65O_cjs = require('./chunk-LT3UC65O.cjs');
14
+ var recharts = require('recharts');
15
+ var jsxRuntime = require('react/jsx-runtime');
16
+
17
+ var ROWS = [
18
+ ["Max", 4],
19
+ ["Q3", 3],
20
+ ["Median", 2],
21
+ ["Q1", 1],
22
+ ["Min", 0]
23
+ ];
24
+ var summaryKey = (index) => `box${index}`;
25
+ var boxShape = (index, color, horizontal) => (props) => {
26
+ const { x, y, width, height } = props;
27
+ const row = props.payload;
28
+ const summary = row[summaryKey(index)];
29
+ if (!summary) return null;
30
+ const [min, q1, median, q3, max] = summary;
31
+ const span = max - min || 1;
32
+ const left = Math.min(x, x + width);
33
+ const top = Math.min(y, y + height);
34
+ const w = Math.abs(width);
35
+ const h = Math.abs(height);
36
+ const at = (v) => horizontal ? left + (v - min) / span * w : top + (max - v) / span * h;
37
+ const mid = horizontal ? top + h / 2 : left + w / 2;
38
+ const size = horizontal ? h : w;
39
+ const cap = size * 0.25;
40
+ const point = (value, across) => horizontal ? { x: at(value), y: across } : { x: across, y: at(value) };
41
+ const line = (from, to, key, wide = 1.5) => /* @__PURE__ */ jsxRuntime.jsx("line", { x1: from.x, y1: from.y, x2: to.x, y2: to.y, stroke: color, strokeWidth: wide }, key);
42
+ const [boxStart, boxEnd] = [at(q1), at(q3)];
43
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
44
+ line(point(min, mid), point(q1, mid), "lower"),
45
+ line(point(q3, mid), point(max, mid), "upper"),
46
+ line(point(min, mid - cap), point(min, mid + cap), "min"),
47
+ line(point(max, mid - cap), point(max, mid + cap), "max"),
48
+ /* @__PURE__ */ jsxRuntime.jsx(
49
+ "rect",
50
+ {
51
+ x: horizontal ? Math.min(boxStart, boxEnd) : mid - size / 2,
52
+ y: horizontal ? mid - size / 2 : Math.min(boxStart, boxEnd),
53
+ width: horizontal ? Math.abs(boxEnd - boxStart) : size,
54
+ height: horizontal ? size : Math.abs(boxEnd - boxStart),
55
+ rx: 2,
56
+ fill: color,
57
+ fillOpacity: 0.35,
58
+ stroke: color,
59
+ strokeWidth: 1.5
60
+ }
61
+ ),
62
+ line(point(median, mid - size / 2), point(median, mid + size / 2), "median", 2.5)
63
+ ] });
64
+ };
65
+ var BoxPlotChart = ({
66
+ series,
67
+ categories,
68
+ orientation = "vertical",
69
+ colors,
70
+ formatValue = String,
71
+ xTitle,
72
+ yTitle,
73
+ referenceLines,
74
+ referenceBands,
75
+ showLegend,
76
+ legendPosition = "top",
77
+ emptyMessage = "No data",
78
+ ariaLabel,
79
+ children,
80
+ height = 320,
81
+ width
82
+ }) => {
83
+ const hidden = chunkGZRMVE4X_cjs.useHiddenSeries();
84
+ const axis = chunkRLHGPHC7_cjs.useAxis();
85
+ const categoryKeys = chunkF2PMFYJ5_cjs.useCategoryKeys(orientation === "horizontal" ? "vertical" : "horizontal");
86
+ const name = ariaLabel ?? `Box plot: ${series.map((s) => s.name).join(", ")}`;
87
+ if (chunkK3R7JGOW_cjs.hasNoData(series)) {
88
+ return /* @__PURE__ */ jsxRuntime.jsx(chunk6NRRABPF_cjs.ChartEmpty, { message: emptyMessage, ariaLabel: name, height, width });
89
+ }
90
+ const horizontal = orientation === "horizontal";
91
+ const rows = categories.map((category, i) => ({
92
+ category,
93
+ ...Object.fromEntries(
94
+ series.flatMap((s, index) => {
95
+ const summary = s.data[i];
96
+ return summary ? [
97
+ [summaryKey(index), summary],
98
+ [chunkK3R7JGOW_cjs.seriesKey(index), [summary[0], summary[4]]]
99
+ ] : [];
100
+ })
101
+ )
102
+ }));
103
+ const tooltip = ({ active, payload, label }) => {
104
+ const row = payload?.[0]?.payload;
105
+ if (!active || !row) return null;
106
+ const lines = series.flatMap((s, index) => {
107
+ const summary = row[summaryKey(index)];
108
+ if (!summary || hidden.hidden.has(chunkK3R7JGOW_cjs.seriesKey(index))) return [];
109
+ const color = chunkLT3UC65O_cjs.seriesColor(index, colors);
110
+ return [
111
+ ...series.length > 1 ? [{ name: s.name, value: "", color }] : [],
112
+ ...ROWS.map(([title, at]) => ({
113
+ name: title,
114
+ value: formatValue(summary[at]),
115
+ color: series.length > 1 ? "transparent" : color
116
+ }))
117
+ ];
118
+ });
119
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkT3K6Q34U_cjs.TooltipCard, { title: label, rows: lines });
120
+ };
121
+ return /* @__PURE__ */ jsxRuntime.jsxs(
122
+ recharts.BarChart,
123
+ {
124
+ ref: categoryKeys,
125
+ ...chunk6NRRABPF_cjs.frameProps({ height, width, ariaLabel: name }),
126
+ data: rows,
127
+ layout: horizontal ? "vertical" : "horizontal",
128
+ margin: { top: 4, right: 12, bottom: 0, left: 0 },
129
+ barGap: 4,
130
+ barCategoryGap: "22%",
131
+ children: [
132
+ /* @__PURE__ */ jsxRuntime.jsx(
133
+ recharts.CartesianGrid,
134
+ {
135
+ ...chunkRLHGPHC7_cjs.GRID_PROPS,
136
+ ...horizontal ? { horizontal: false, vertical: true } : {}
137
+ }
138
+ ),
139
+ horizontal ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
140
+ /* @__PURE__ */ jsxRuntime.jsx(
141
+ recharts.XAxis,
142
+ {
143
+ type: "number",
144
+ domain: ["auto", "auto"],
145
+ tickFormatter: formatValue,
146
+ ...axis,
147
+ ...chunkRLHGPHC7_cjs.xAxisTitle(xTitle)
148
+ }
149
+ ),
150
+ /* @__PURE__ */ jsxRuntime.jsx(
151
+ recharts.YAxis,
152
+ {
153
+ type: "category",
154
+ dataKey: "category",
155
+ width: "auto",
156
+ tickFormatter: chunk6BKLL7LZ_cjs.trimLabel,
157
+ ...axis,
158
+ ...chunkRLHGPHC7_cjs.yAxisTitle(yTitle)
159
+ }
160
+ )
161
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
162
+ /* @__PURE__ */ jsxRuntime.jsx(
163
+ recharts.XAxis,
164
+ {
165
+ dataKey: "category",
166
+ ...axis,
167
+ ...chunkRLHGPHC7_cjs.xAxisTitle(xTitle),
168
+ ...chunk6BKLL7LZ_cjs.categoryAxis(categories, xTitle)
169
+ }
170
+ ),
171
+ /* @__PURE__ */ jsxRuntime.jsx(
172
+ recharts.YAxis,
173
+ {
174
+ type: "number",
175
+ domain: ["auto", "auto"],
176
+ width: "auto",
177
+ tickFormatter: formatValue,
178
+ ...axis,
179
+ ...chunkRLHGPHC7_cjs.yAxisTitle(yTitle)
180
+ }
181
+ )
182
+ ] }),
183
+ (showLegend ?? series.length > 1) && /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, { ...chunkGZRMVE4X_cjs.legendProps(legendPosition, hidden) }),
184
+ /* @__PURE__ */ jsxRuntime.jsx(
185
+ recharts.Tooltip,
186
+ {
187
+ content: tooltip,
188
+ cursor: { fill: chunkLT3UC65O_cjs.BORDER, fillOpacity: 0.35, radius: 8 },
189
+ animationDuration: 150
190
+ }
191
+ ),
192
+ series.map((s, index) => /* @__PURE__ */ jsxRuntime.jsx(
193
+ recharts.Bar,
194
+ {
195
+ name: s.name,
196
+ dataKey: chunkK3R7JGOW_cjs.seriesKey(index),
197
+ fill: chunkLT3UC65O_cjs.seriesColor(index, colors),
198
+ maxBarSize: 56,
199
+ shape: boxShape(index, chunkLT3UC65O_cjs.seriesColor(index, colors), horizontal),
200
+ hide: hidden.hidden.has(chunkK3R7JGOW_cjs.seriesKey(index)),
201
+ ...chunkTYQWZR3S_cjs.ANIMATION
202
+ },
203
+ chunkK3R7JGOW_cjs.seriesKey(index)
204
+ )),
205
+ chunkZ4LZFMDH_cjs.referenceMarks({ referenceLines, referenceBands, axis: horizontal ? "x" : "y" }),
206
+ children
207
+ ]
208
+ }
209
+ );
210
+ };
211
+
212
+ exports.BoxPlotChart = BoxPlotChart;
213
+ //# sourceMappingURL=BoxPlotChart.cjs.map
214
+ //# sourceMappingURL=BoxPlotChart.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/BoxPlotChart.tsx"],"names":["jsx","useHiddenSeries","useAxis","useCategoryKeys","hasNoData","ChartEmpty","seriesKey","seriesColor","TooltipCard","jsxs","BarChart","frameProps","CartesianGrid","GRID_PROPS","Fragment","XAxis","xAxisTitle","YAxis","trimLabel","yAxisTitle","categoryAxis","Legend","legendProps","Tooltip","BORDER","Bar","ANIMATION","referenceMarks"],"mappings":"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","file":"BoxPlotChart.cjs","sourcesContent":["import {\n Bar,\n BarChart,\n CartesianGrid,\n Legend,\n Tooltip,\n XAxis,\n YAxis,\n type BarShapeProps,\n type TooltipContentProps,\n} from 'recharts';\nimport { ANIMATION } from './core/animation';\nimport { GRID_PROPS, useAxis, xAxisTitle, yAxisTitle } from './core/axes';\nimport { categoryAxis, trimLabel } from './core/categoryAxis';\nimport { useCategoryKeys } from './core/categoryKeys';\nimport { TooltipCard, type TooltipRow } from './core/ChartTooltip';\nimport { legendProps, useHiddenSeries } from './core/ChartLegend';\nimport { BORDER, seriesColor } from './core/colors';\nimport { hasNoData, seriesKey } from './core/data';\nimport { ChartEmpty, frameProps } from './core/frame';\nimport { referenceMarks } from './core/reference';\nimport type {\n ChartAxisTitleProps,\n ChartEmptyProps,\n ChartLegendProps,\n ChartProps,\n ChartReferenceProps,\n} from './types';\n\nexport type BoxPlotChartOrientation = 'vertical' | 'horizontal';\n\n/** One box, the five-number summary of a distribution. */\nexport type BoxPlotSummary = [min: number, q1: number, median: number, q3: number, max: number];\n\nexport type BoxPlotChartProps = ChartProps &\n ChartEmptyProps &\n ChartLegendProps &\n ChartAxisTitleProps &\n ChartReferenceProps & {\n /** One summary per category, in the order of `categories`. */\n series: { name: string; data: BoxPlotSummary[] }[];\n categories: string[];\n /** `vertical` (default) draws boxes upward; `horizontal` draws them rightward. */\n orientation?: BoxPlotChartOrientation;\n /** Override the default Cosmos palette, one color per series. */\n colors?: string[];\n /** Format the value axis labels and the tooltip values. */\n formatValue?: (value: number) => string;\n /** Show the legend (auto-true when 2+ series). */\n showLegend?: boolean;\n };\n\n// Top to bottom, the way a vertical box reads.\nconst ROWS = [\n ['Max', 4],\n ['Q3', 3],\n ['Median', 2],\n ['Q1', 1],\n ['Min', 0],\n] as const;\n\nconst summaryKey = (index: number) => `box${index}`;\n\ntype Row = { category: string } & Record<string, unknown>;\n\n// A bar's value is the span of the whiskers, so Recharts sizes and places it\n// and fits the value axis to it; the shape draws the box, the median and the\n// whiskers at the same scale. Recharts has no box plot of its own.\nconst boxShape = (index: number, color: string, horizontal: boolean) => (props: BarShapeProps) => {\n const { x, y, width, height } = props;\n const row = props.payload as Row;\n const summary = row[summaryKey(index)] as BoxPlotSummary | undefined;\n if (!summary) return null;\n const [min, q1, median, q3, max] = summary;\n const span = max - min || 1;\n const left = Math.min(x, x + width);\n const top = Math.min(y, y + height);\n const w = Math.abs(width);\n const h = Math.abs(height);\n // Position of a value along the value axis, and the cross-axis center.\n const at = (v: number) =>\n horizontal ? left + ((v - min) / span) * w : top + ((max - v) / span) * h;\n const mid = horizontal ? top + h / 2 : left + w / 2;\n const size = horizontal ? h : w;\n const cap = size * 0.25;\n const point = (value: number, across: number) =>\n horizontal ? { x: at(value), y: across } : { x: across, y: at(value) };\n const line = (\n from: { x: number; y: number },\n to: { x: number; y: number },\n key: string,\n wide = 1.5\n ) => (\n <line key={key} x1={from.x} y1={from.y} x2={to.x} y2={to.y} stroke={color} strokeWidth={wide} />\n );\n const [boxStart, boxEnd] = [at(q1), at(q3)];\n return (\n <g>\n {line(point(min, mid), point(q1, mid), 'lower')}\n {line(point(q3, mid), point(max, mid), 'upper')}\n {line(point(min, mid - cap), point(min, mid + cap), 'min')}\n {line(point(max, mid - cap), point(max, mid + cap), 'max')}\n <rect\n x={horizontal ? Math.min(boxStart, boxEnd) : mid - size / 2}\n y={horizontal ? mid - size / 2 : Math.min(boxStart, boxEnd)}\n width={horizontal ? Math.abs(boxEnd - boxStart) : size}\n height={horizontal ? size : Math.abs(boxEnd - boxStart)}\n rx={2}\n fill={color}\n fillOpacity={0.35}\n stroke={color}\n strokeWidth={1.5}\n />\n {line(point(median, mid - size / 2), point(median, mid + size / 2), 'median', 2.5)}\n </g>\n );\n};\n\n/** Distributions per category (min, quartiles, median, max), e.g. response times per service. */\nexport const BoxPlotChart = ({\n series,\n categories,\n orientation = 'vertical',\n colors,\n formatValue = String,\n xTitle,\n yTitle,\n referenceLines,\n referenceBands,\n showLegend,\n legendPosition = 'top',\n emptyMessage = 'No data',\n ariaLabel,\n children,\n height = 320,\n width,\n}: BoxPlotChartProps) => {\n const hidden = useHiddenSeries();\n const axis = useAxis();\n // Recharts names the layout after the axis the categories sit on.\n const categoryKeys = useCategoryKeys(orientation === 'horizontal' ? 'vertical' : 'horizontal');\n const name = ariaLabel ?? `Box plot: ${series.map((s) => s.name).join(', ')}`;\n if (hasNoData(series)) {\n return <ChartEmpty message={emptyMessage} ariaLabel={name} height={height} width={width} />;\n }\n const horizontal = orientation === 'horizontal';\n const rows: Row[] = categories.map((category, i) => ({\n category,\n ...Object.fromEntries(\n series.flatMap((s, index) => {\n const summary = s.data[i];\n return summary\n ? [\n [summaryKey(index), summary],\n [seriesKey(index), [summary[0], summary[4]]],\n ]\n : [];\n })\n ),\n }));\n\n // The category, then the five numbers of each series shown, headed by its name when there are several.\n const tooltip = ({ active, payload, label }: Partial<TooltipContentProps>) => {\n const row = payload?.[0]?.payload as Row | undefined;\n if (!active || !row) return null;\n const lines = series.flatMap((s, index): TooltipRow[] => {\n const summary = row[summaryKey(index)] as BoxPlotSummary | undefined;\n if (!summary || hidden.hidden.has(seriesKey(index))) return [];\n const color = seriesColor(index, colors);\n return [\n ...(series.length > 1 ? [{ name: s.name, value: '', color }] : []),\n ...ROWS.map(([title, at]) => ({\n name: title,\n value: formatValue(summary[at]),\n color: series.length > 1 ? 'transparent' : color,\n })),\n ];\n });\n return <TooltipCard title={label} rows={lines} />;\n };\n\n return (\n <BarChart\n ref={categoryKeys}\n {...frameProps({ height, width, ariaLabel: name })}\n data={rows}\n // Recharts names the layout after the axis the categories sit on.\n layout={horizontal ? 'vertical' : 'horizontal'}\n margin={{ top: 4, right: 12, bottom: 0, left: 0 }}\n barGap={4}\n barCategoryGap=\"22%\"\n >\n <CartesianGrid\n {...GRID_PROPS}\n {...(horizontal ? { horizontal: false, vertical: true } : {})}\n />\n {horizontal ? (\n <>\n <XAxis\n type=\"number\"\n domain={['auto', 'auto']}\n tickFormatter={formatValue}\n {...axis}\n {...xAxisTitle(xTitle)}\n />\n <YAxis\n type=\"category\"\n dataKey=\"category\"\n width=\"auto\"\n tickFormatter={trimLabel}\n {...axis}\n {...yAxisTitle(yTitle)}\n />\n </>\n ) : (\n <>\n <XAxis\n dataKey=\"category\"\n {...axis}\n {...xAxisTitle(xTitle)}\n {...categoryAxis(categories, xTitle)}\n />\n <YAxis\n type=\"number\"\n domain={['auto', 'auto']}\n width=\"auto\"\n tickFormatter={formatValue}\n {...axis}\n {...yAxisTitle(yTitle)}\n />\n </>\n )}\n {(showLegend ?? series.length > 1) && <Legend {...legendProps(legendPosition, hidden)} />}\n <Tooltip\n content={tooltip}\n cursor={{ fill: BORDER, fillOpacity: 0.35, radius: 8 }}\n animationDuration={150}\n />\n {series.map((s, index) => (\n <Bar\n key={seriesKey(index)}\n name={s.name}\n dataKey={seriesKey(index)}\n fill={seriesColor(index, colors)}\n maxBarSize={56}\n shape={boxShape(index, seriesColor(index, colors), horizontal)}\n hide={hidden.hidden.has(seriesKey(index))}\n {...ANIMATION}\n />\n ))}\n {referenceMarks({ referenceLines, referenceBands, axis: horizontal ? 'x' : 'y' })}\n {children}\n </BarChart>\n );\n};\n"]}
@@ -0,0 +1,212 @@
1
+ "use client";
2
+ import { useCategoryKeys } from './chunk-FUZW3H5X.js';
3
+ import { referenceMarks } from './chunk-SGG7XKOY.js';
4
+ import { trimLabel, categoryAxis } from './chunk-HMH6DI7U.js';
5
+ import { useHiddenSeries, legendProps } from './chunk-6ALKZLN2.js';
6
+ import { ANIMATION } from './chunk-5C2RLJYZ.js';
7
+ import { useAxis, GRID_PROPS, xAxisTitle, yAxisTitle } from './chunk-RILUG7JB.js';
8
+ import { TooltipCard } from './chunk-VIOSQN4Z.js';
9
+ import { hasNoData, seriesKey } from './chunk-UJIV5PVI.js';
10
+ import { ChartEmpty, frameProps } from './chunk-3N43QT36.js';
11
+ import { BORDER, seriesColor } from './chunk-UATB2IRY.js';
12
+ import { BarChart, CartesianGrid, XAxis, YAxis, Legend, Tooltip, Bar } from 'recharts';
13
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
14
+
15
+ var ROWS = [
16
+ ["Max", 4],
17
+ ["Q3", 3],
18
+ ["Median", 2],
19
+ ["Q1", 1],
20
+ ["Min", 0]
21
+ ];
22
+ var summaryKey = (index) => `box${index}`;
23
+ var boxShape = (index, color, horizontal) => (props) => {
24
+ const { x, y, width, height } = props;
25
+ const row = props.payload;
26
+ const summary = row[summaryKey(index)];
27
+ if (!summary) return null;
28
+ const [min, q1, median, q3, max] = summary;
29
+ const span = max - min || 1;
30
+ const left = Math.min(x, x + width);
31
+ const top = Math.min(y, y + height);
32
+ const w = Math.abs(width);
33
+ const h = Math.abs(height);
34
+ const at = (v) => horizontal ? left + (v - min) / span * w : top + (max - v) / span * h;
35
+ const mid = horizontal ? top + h / 2 : left + w / 2;
36
+ const size = horizontal ? h : w;
37
+ const cap = size * 0.25;
38
+ const point = (value, across) => horizontal ? { x: at(value), y: across } : { x: across, y: at(value) };
39
+ const line = (from, to, key, wide = 1.5) => /* @__PURE__ */ jsx("line", { x1: from.x, y1: from.y, x2: to.x, y2: to.y, stroke: color, strokeWidth: wide }, key);
40
+ const [boxStart, boxEnd] = [at(q1), at(q3)];
41
+ return /* @__PURE__ */ jsxs("g", { children: [
42
+ line(point(min, mid), point(q1, mid), "lower"),
43
+ line(point(q3, mid), point(max, mid), "upper"),
44
+ line(point(min, mid - cap), point(min, mid + cap), "min"),
45
+ line(point(max, mid - cap), point(max, mid + cap), "max"),
46
+ /* @__PURE__ */ jsx(
47
+ "rect",
48
+ {
49
+ x: horizontal ? Math.min(boxStart, boxEnd) : mid - size / 2,
50
+ y: horizontal ? mid - size / 2 : Math.min(boxStart, boxEnd),
51
+ width: horizontal ? Math.abs(boxEnd - boxStart) : size,
52
+ height: horizontal ? size : Math.abs(boxEnd - boxStart),
53
+ rx: 2,
54
+ fill: color,
55
+ fillOpacity: 0.35,
56
+ stroke: color,
57
+ strokeWidth: 1.5
58
+ }
59
+ ),
60
+ line(point(median, mid - size / 2), point(median, mid + size / 2), "median", 2.5)
61
+ ] });
62
+ };
63
+ var BoxPlotChart = ({
64
+ series,
65
+ categories,
66
+ orientation = "vertical",
67
+ colors,
68
+ formatValue = String,
69
+ xTitle,
70
+ yTitle,
71
+ referenceLines,
72
+ referenceBands,
73
+ showLegend,
74
+ legendPosition = "top",
75
+ emptyMessage = "No data",
76
+ ariaLabel,
77
+ children,
78
+ height = 320,
79
+ width
80
+ }) => {
81
+ const hidden = useHiddenSeries();
82
+ const axis = useAxis();
83
+ const categoryKeys = useCategoryKeys(orientation === "horizontal" ? "vertical" : "horizontal");
84
+ const name = ariaLabel ?? `Box plot: ${series.map((s) => s.name).join(", ")}`;
85
+ if (hasNoData(series)) {
86
+ return /* @__PURE__ */ jsx(ChartEmpty, { message: emptyMessage, ariaLabel: name, height, width });
87
+ }
88
+ const horizontal = orientation === "horizontal";
89
+ const rows = categories.map((category, i) => ({
90
+ category,
91
+ ...Object.fromEntries(
92
+ series.flatMap((s, index) => {
93
+ const summary = s.data[i];
94
+ return summary ? [
95
+ [summaryKey(index), summary],
96
+ [seriesKey(index), [summary[0], summary[4]]]
97
+ ] : [];
98
+ })
99
+ )
100
+ }));
101
+ const tooltip = ({ active, payload, label }) => {
102
+ const row = payload?.[0]?.payload;
103
+ if (!active || !row) return null;
104
+ const lines = series.flatMap((s, index) => {
105
+ const summary = row[summaryKey(index)];
106
+ if (!summary || hidden.hidden.has(seriesKey(index))) return [];
107
+ const color = seriesColor(index, colors);
108
+ return [
109
+ ...series.length > 1 ? [{ name: s.name, value: "", color }] : [],
110
+ ...ROWS.map(([title, at]) => ({
111
+ name: title,
112
+ value: formatValue(summary[at]),
113
+ color: series.length > 1 ? "transparent" : color
114
+ }))
115
+ ];
116
+ });
117
+ return /* @__PURE__ */ jsx(TooltipCard, { title: label, rows: lines });
118
+ };
119
+ return /* @__PURE__ */ jsxs(
120
+ BarChart,
121
+ {
122
+ ref: categoryKeys,
123
+ ...frameProps({ height, width, ariaLabel: name }),
124
+ data: rows,
125
+ layout: horizontal ? "vertical" : "horizontal",
126
+ margin: { top: 4, right: 12, bottom: 0, left: 0 },
127
+ barGap: 4,
128
+ barCategoryGap: "22%",
129
+ children: [
130
+ /* @__PURE__ */ jsx(
131
+ CartesianGrid,
132
+ {
133
+ ...GRID_PROPS,
134
+ ...horizontal ? { horizontal: false, vertical: true } : {}
135
+ }
136
+ ),
137
+ horizontal ? /* @__PURE__ */ jsxs(Fragment, { children: [
138
+ /* @__PURE__ */ jsx(
139
+ XAxis,
140
+ {
141
+ type: "number",
142
+ domain: ["auto", "auto"],
143
+ tickFormatter: formatValue,
144
+ ...axis,
145
+ ...xAxisTitle(xTitle)
146
+ }
147
+ ),
148
+ /* @__PURE__ */ jsx(
149
+ YAxis,
150
+ {
151
+ type: "category",
152
+ dataKey: "category",
153
+ width: "auto",
154
+ tickFormatter: trimLabel,
155
+ ...axis,
156
+ ...yAxisTitle(yTitle)
157
+ }
158
+ )
159
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
160
+ /* @__PURE__ */ jsx(
161
+ XAxis,
162
+ {
163
+ dataKey: "category",
164
+ ...axis,
165
+ ...xAxisTitle(xTitle),
166
+ ...categoryAxis(categories, xTitle)
167
+ }
168
+ ),
169
+ /* @__PURE__ */ jsx(
170
+ YAxis,
171
+ {
172
+ type: "number",
173
+ domain: ["auto", "auto"],
174
+ width: "auto",
175
+ tickFormatter: formatValue,
176
+ ...axis,
177
+ ...yAxisTitle(yTitle)
178
+ }
179
+ )
180
+ ] }),
181
+ (showLegend ?? series.length > 1) && /* @__PURE__ */ jsx(Legend, { ...legendProps(legendPosition, hidden) }),
182
+ /* @__PURE__ */ jsx(
183
+ Tooltip,
184
+ {
185
+ content: tooltip,
186
+ cursor: { fill: BORDER, fillOpacity: 0.35, radius: 8 },
187
+ animationDuration: 150
188
+ }
189
+ ),
190
+ series.map((s, index) => /* @__PURE__ */ jsx(
191
+ Bar,
192
+ {
193
+ name: s.name,
194
+ dataKey: seriesKey(index),
195
+ fill: seriesColor(index, colors),
196
+ maxBarSize: 56,
197
+ shape: boxShape(index, seriesColor(index, colors), horizontal),
198
+ hide: hidden.hidden.has(seriesKey(index)),
199
+ ...ANIMATION
200
+ },
201
+ seriesKey(index)
202
+ )),
203
+ referenceMarks({ referenceLines, referenceBands, axis: horizontal ? "x" : "y" }),
204
+ children
205
+ ]
206
+ }
207
+ );
208
+ };
209
+
210
+ export { BoxPlotChart };
211
+ //# sourceMappingURL=BoxPlotChart.js.map
212
+ //# sourceMappingURL=BoxPlotChart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/BoxPlotChart.tsx"],"names":[],"mappings":"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","file":"BoxPlotChart.js","sourcesContent":["import {\n Bar,\n BarChart,\n CartesianGrid,\n Legend,\n Tooltip,\n XAxis,\n YAxis,\n type BarShapeProps,\n type TooltipContentProps,\n} from 'recharts';\nimport { ANIMATION } from './core/animation';\nimport { GRID_PROPS, useAxis, xAxisTitle, yAxisTitle } from './core/axes';\nimport { categoryAxis, trimLabel } from './core/categoryAxis';\nimport { useCategoryKeys } from './core/categoryKeys';\nimport { TooltipCard, type TooltipRow } from './core/ChartTooltip';\nimport { legendProps, useHiddenSeries } from './core/ChartLegend';\nimport { BORDER, seriesColor } from './core/colors';\nimport { hasNoData, seriesKey } from './core/data';\nimport { ChartEmpty, frameProps } from './core/frame';\nimport { referenceMarks } from './core/reference';\nimport type {\n ChartAxisTitleProps,\n ChartEmptyProps,\n ChartLegendProps,\n ChartProps,\n ChartReferenceProps,\n} from './types';\n\nexport type BoxPlotChartOrientation = 'vertical' | 'horizontal';\n\n/** One box, the five-number summary of a distribution. */\nexport type BoxPlotSummary = [min: number, q1: number, median: number, q3: number, max: number];\n\nexport type BoxPlotChartProps = ChartProps &\n ChartEmptyProps &\n ChartLegendProps &\n ChartAxisTitleProps &\n ChartReferenceProps & {\n /** One summary per category, in the order of `categories`. */\n series: { name: string; data: BoxPlotSummary[] }[];\n categories: string[];\n /** `vertical` (default) draws boxes upward; `horizontal` draws them rightward. */\n orientation?: BoxPlotChartOrientation;\n /** Override the default Cosmos palette, one color per series. */\n colors?: string[];\n /** Format the value axis labels and the tooltip values. */\n formatValue?: (value: number) => string;\n /** Show the legend (auto-true when 2+ series). */\n showLegend?: boolean;\n };\n\n// Top to bottom, the way a vertical box reads.\nconst ROWS = [\n ['Max', 4],\n ['Q3', 3],\n ['Median', 2],\n ['Q1', 1],\n ['Min', 0],\n] as const;\n\nconst summaryKey = (index: number) => `box${index}`;\n\ntype Row = { category: string } & Record<string, unknown>;\n\n// A bar's value is the span of the whiskers, so Recharts sizes and places it\n// and fits the value axis to it; the shape draws the box, the median and the\n// whiskers at the same scale. Recharts has no box plot of its own.\nconst boxShape = (index: number, color: string, horizontal: boolean) => (props: BarShapeProps) => {\n const { x, y, width, height } = props;\n const row = props.payload as Row;\n const summary = row[summaryKey(index)] as BoxPlotSummary | undefined;\n if (!summary) return null;\n const [min, q1, median, q3, max] = summary;\n const span = max - min || 1;\n const left = Math.min(x, x + width);\n const top = Math.min(y, y + height);\n const w = Math.abs(width);\n const h = Math.abs(height);\n // Position of a value along the value axis, and the cross-axis center.\n const at = (v: number) =>\n horizontal ? left + ((v - min) / span) * w : top + ((max - v) / span) * h;\n const mid = horizontal ? top + h / 2 : left + w / 2;\n const size = horizontal ? h : w;\n const cap = size * 0.25;\n const point = (value: number, across: number) =>\n horizontal ? { x: at(value), y: across } : { x: across, y: at(value) };\n const line = (\n from: { x: number; y: number },\n to: { x: number; y: number },\n key: string,\n wide = 1.5\n ) => (\n <line key={key} x1={from.x} y1={from.y} x2={to.x} y2={to.y} stroke={color} strokeWidth={wide} />\n );\n const [boxStart, boxEnd] = [at(q1), at(q3)];\n return (\n <g>\n {line(point(min, mid), point(q1, mid), 'lower')}\n {line(point(q3, mid), point(max, mid), 'upper')}\n {line(point(min, mid - cap), point(min, mid + cap), 'min')}\n {line(point(max, mid - cap), point(max, mid + cap), 'max')}\n <rect\n x={horizontal ? Math.min(boxStart, boxEnd) : mid - size / 2}\n y={horizontal ? mid - size / 2 : Math.min(boxStart, boxEnd)}\n width={horizontal ? Math.abs(boxEnd - boxStart) : size}\n height={horizontal ? size : Math.abs(boxEnd - boxStart)}\n rx={2}\n fill={color}\n fillOpacity={0.35}\n stroke={color}\n strokeWidth={1.5}\n />\n {line(point(median, mid - size / 2), point(median, mid + size / 2), 'median', 2.5)}\n </g>\n );\n};\n\n/** Distributions per category (min, quartiles, median, max), e.g. response times per service. */\nexport const BoxPlotChart = ({\n series,\n categories,\n orientation = 'vertical',\n colors,\n formatValue = String,\n xTitle,\n yTitle,\n referenceLines,\n referenceBands,\n showLegend,\n legendPosition = 'top',\n emptyMessage = 'No data',\n ariaLabel,\n children,\n height = 320,\n width,\n}: BoxPlotChartProps) => {\n const hidden = useHiddenSeries();\n const axis = useAxis();\n // Recharts names the layout after the axis the categories sit on.\n const categoryKeys = useCategoryKeys(orientation === 'horizontal' ? 'vertical' : 'horizontal');\n const name = ariaLabel ?? `Box plot: ${series.map((s) => s.name).join(', ')}`;\n if (hasNoData(series)) {\n return <ChartEmpty message={emptyMessage} ariaLabel={name} height={height} width={width} />;\n }\n const horizontal = orientation === 'horizontal';\n const rows: Row[] = categories.map((category, i) => ({\n category,\n ...Object.fromEntries(\n series.flatMap((s, index) => {\n const summary = s.data[i];\n return summary\n ? [\n [summaryKey(index), summary],\n [seriesKey(index), [summary[0], summary[4]]],\n ]\n : [];\n })\n ),\n }));\n\n // The category, then the five numbers of each series shown, headed by its name when there are several.\n const tooltip = ({ active, payload, label }: Partial<TooltipContentProps>) => {\n const row = payload?.[0]?.payload as Row | undefined;\n if (!active || !row) return null;\n const lines = series.flatMap((s, index): TooltipRow[] => {\n const summary = row[summaryKey(index)] as BoxPlotSummary | undefined;\n if (!summary || hidden.hidden.has(seriesKey(index))) return [];\n const color = seriesColor(index, colors);\n return [\n ...(series.length > 1 ? [{ name: s.name, value: '', color }] : []),\n ...ROWS.map(([title, at]) => ({\n name: title,\n value: formatValue(summary[at]),\n color: series.length > 1 ? 'transparent' : color,\n })),\n ];\n });\n return <TooltipCard title={label} rows={lines} />;\n };\n\n return (\n <BarChart\n ref={categoryKeys}\n {...frameProps({ height, width, ariaLabel: name })}\n data={rows}\n // Recharts names the layout after the axis the categories sit on.\n layout={horizontal ? 'vertical' : 'horizontal'}\n margin={{ top: 4, right: 12, bottom: 0, left: 0 }}\n barGap={4}\n barCategoryGap=\"22%\"\n >\n <CartesianGrid\n {...GRID_PROPS}\n {...(horizontal ? { horizontal: false, vertical: true } : {})}\n />\n {horizontal ? (\n <>\n <XAxis\n type=\"number\"\n domain={['auto', 'auto']}\n tickFormatter={formatValue}\n {...axis}\n {...xAxisTitle(xTitle)}\n />\n <YAxis\n type=\"category\"\n dataKey=\"category\"\n width=\"auto\"\n tickFormatter={trimLabel}\n {...axis}\n {...yAxisTitle(yTitle)}\n />\n </>\n ) : (\n <>\n <XAxis\n dataKey=\"category\"\n {...axis}\n {...xAxisTitle(xTitle)}\n {...categoryAxis(categories, xTitle)}\n />\n <YAxis\n type=\"number\"\n domain={['auto', 'auto']}\n width=\"auto\"\n tickFormatter={formatValue}\n {...axis}\n {...yAxisTitle(yTitle)}\n />\n </>\n )}\n {(showLegend ?? series.length > 1) && <Legend {...legendProps(legendPosition, hidden)} />}\n <Tooltip\n content={tooltip}\n cursor={{ fill: BORDER, fillOpacity: 0.35, radius: 8 }}\n animationDuration={150}\n />\n {series.map((s, index) => (\n <Bar\n key={seriesKey(index)}\n name={s.name}\n dataKey={seriesKey(index)}\n fill={seriesColor(index, colors)}\n maxBarSize={56}\n shape={boxShape(index, seriesColor(index, colors), horizontal)}\n hide={hidden.hidden.has(seriesKey(index))}\n {...ANIMATION}\n />\n ))}\n {referenceMarks({ referenceLines, referenceBands, axis: horizontal ? 'x' : 'y' })}\n {children}\n </BarChart>\n );\n};\n"]}