@tetrascience-npm/tetrascience-react-ui 0.6.0-beta.95.1 → 0.6.0-beta.97.1

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.
@@ -1,52 +1,53 @@
1
- import { jsxs as v, jsx as A } from "react/jsx-runtime";
2
- import L from "plotly.js-dist";
3
- import { useRef as P, useMemo as c, useEffect as U } from "react";
1
+ import { jsxs as v, jsx as X } from "react/jsx-runtime";
2
+ import A from "plotly.js-dist";
3
+ import { useRef as O, useMemo as c, useEffect as U } from "react";
4
4
  import { useChartTooltip as V } from "../ChartTooltip/ChartTooltip.js";
5
- import { usePlotlyTheme as X } from "../../../hooks/use-plotly-theme.js";
6
- import { seriesColor as B } from "../../../utils/colors.js";
7
- const q = ({
8
- dataSeries: l,
9
- width: M = 1e3,
10
- height: w = 600,
11
- xRange: d,
5
+ import { usePlotlyTheme as B } from "../../../hooks/use-plotly-theme.js";
6
+ import { seriesColor as G } from "../../../utils/colors.js";
7
+ const Y = 60, j = 30, K = ({
8
+ dataSeries: s,
9
+ width: b = 1e3,
10
+ height: _ = 600,
11
+ xRange: M,
12
12
  yRange: m,
13
13
  variant: f = "lines",
14
- xTitle: y = "Columns",
15
- yTitle: g = "Rows",
16
- title: b = "Line Graph"
14
+ xTitle: x = "Columns",
15
+ yTitle: k = "Rows",
16
+ title: h,
17
+ xTickText: d
17
18
  }) => {
18
- const p = P(null), o = X(), { bindTooltip: C, tooltipElement: N } = V({ xLabel: y, yLabel: g }), { yMin: E, yMax: _ } = c(() => {
19
- let r = Number.MAX_VALUE, t = Number.MIN_VALUE, i = Number.MAX_VALUE, e = Number.MIN_VALUE;
20
- l.forEach((a) => {
19
+ const p = O(null), r = B(), { bindTooltip: E, tooltipElement: P } = V({ xLabel: x, yLabel: k }), { yMin: I, yMax: C } = c(() => {
20
+ let t = Number.MAX_VALUE, o = Number.MIN_VALUE, l = Number.MAX_VALUE, e = Number.MIN_VALUE;
21
+ s.forEach((a) => {
21
22
  a.x.forEach((u) => {
22
- r = Math.min(r, u), t = Math.max(t, u);
23
+ t = Math.min(t, u), o = Math.max(o, u);
23
24
  }), a.y.forEach((u) => {
24
- i = Math.min(i, u), e = Math.max(e, u);
25
+ l = Math.min(l, u), e = Math.max(e, u);
25
26
  });
26
27
  });
27
- const n = (t - r) * 0.1, h = (e - i) * 0.1;
28
+ const n = (o - t) * 0.1, g = (e - l) * 0.1;
28
29
  return {
29
- xMin: r - n,
30
- xMax: t + n,
31
- yMin: i - h,
32
- yMax: e + h
30
+ xMin: t - n,
31
+ xMax: o + n,
32
+ yMin: l - g,
33
+ yMax: e + g
33
34
  };
34
- }, [l]), s = c(
35
- () => m || [E, _],
36
- [m, E, _]
37
- ), z = c(() => {
38
- const r = s[1] - s[0];
39
- let t = Math.pow(10, Math.floor(Math.log10(r)));
40
- r / t > 10 && (t = t * 2), r / t < 4 && (t = t / 2);
41
- const i = [];
42
- let e = Math.ceil(s[0] / t) * t;
43
- for (; e <= s[1]; )
44
- i.push(e), e += t;
45
- return i;
46
- }, [s]), x = c(
47
- () => [...new Set(l.flatMap((r) => r.x))],
48
- [l]
49
- ), I = c(() => {
35
+ }, [s]), i = c(
36
+ () => m || [I, C],
37
+ [m, I, C]
38
+ ), N = c(() => {
39
+ const t = i[1] - i[0];
40
+ let o = Math.pow(10, Math.floor(Math.log10(t)));
41
+ t / o > 10 && (o = o * 2), t / o < 4 && (o = o / 2);
42
+ const l = [];
43
+ let e = Math.ceil(i[0] / o) * o;
44
+ for (; e <= i[1]; )
45
+ l.push(e), e += o;
46
+ return l;
47
+ }, [i]), y = c(
48
+ () => [...new Set(s.flatMap((t) => t.x))].sort((t, o) => t - o),
49
+ [s]
50
+ ), L = !!d && d.length === y.length, z = c(() => {
50
51
  switch (f) {
51
52
  case "lines+markers":
52
53
  case "lines+markers+error_bars":
@@ -54,34 +55,34 @@ const q = ({
54
55
  default:
55
56
  return "lines";
56
57
  }
57
- }, [f]), k = c(
58
+ }, [f]), w = c(
58
59
  () => ({
59
- tickcolor: o.tickColor,
60
+ tickcolor: r.tickColor,
60
61
  ticklen: 12,
61
62
  tickwidth: 1,
62
63
  ticks: "outside",
63
64
  tickfont: {
64
65
  size: 16,
65
- color: o.textColor,
66
+ color: r.textColor,
66
67
  family: "Inter, sans-serif",
67
68
  weight: 400
68
69
  },
69
- linecolor: o.lineColor,
70
+ linecolor: r.lineColor,
70
71
  linewidth: 1,
71
72
  position: 0,
72
73
  zeroline: !1
73
74
  }),
74
- [o]
75
+ [r]
75
76
  );
76
77
  return U(() => {
77
78
  if (!p.current) return;
78
- const r = l.map((n, h) => {
79
- const a = B(h, n.color);
79
+ const t = s.map((n, g) => {
80
+ const a = G(g, n.color);
80
81
  return {
81
82
  x: n.x,
82
83
  y: n.y,
83
84
  type: "scatter",
84
- mode: I,
85
+ mode: z,
85
86
  name: n.name,
86
87
  hoverinfo: "none",
87
88
  line: {
@@ -102,62 +103,70 @@ const q = ({
102
103
  width: 5
103
104
  } : void 0
104
105
  };
105
- }), t = {
106
- title: {
107
- text: b,
108
- font: {
109
- size: 32,
110
- family: "Inter, sans-serif",
111
- color: o.textColor
106
+ }), o = {
107
+ ...h ? {
108
+ title: {
109
+ text: h,
110
+ font: {
111
+ size: 32,
112
+ family: "Inter, sans-serif",
113
+ color: r.textColor
114
+ }
112
115
  }
116
+ } : {},
117
+ width: b,
118
+ height: _,
119
+ margin: {
120
+ l: 80,
121
+ r: 30,
122
+ b: 80,
123
+ t: h ? Y : j,
124
+ pad: 10
113
125
  },
114
- width: M,
115
- height: w,
116
- margin: { l: 80, r: 30, b: 80, t: 60, pad: 10 },
117
- paper_bgcolor: o.paperBg,
118
- plot_bgcolor: o.plotBg,
126
+ paper_bgcolor: r.paperBg,
127
+ plot_bgcolor: r.plotBg,
119
128
  font: {
120
129
  family: "Inter, sans-serif"
121
130
  },
122
131
  dragmode: !1,
123
132
  xaxis: {
124
133
  title: {
125
- text: y,
134
+ text: x,
126
135
  font: {
127
136
  size: 16,
128
- color: o.textSecondary,
137
+ color: r.textSecondary,
129
138
  family: "Inter, sans-serif",
130
139
  weight: 400
131
140
  },
132
141
  standoff: 32
133
142
  },
134
- gridcolor: o.gridColor,
135
- range: d,
136
- autorange: !d,
143
+ gridcolor: r.gridColor,
144
+ range: M,
145
+ autorange: !M,
137
146
  tickmode: "array",
138
- tickvals: x,
139
- ticktext: x.map(String),
147
+ tickvals: y,
148
+ ticktext: L ? d : y.map(String),
140
149
  showgrid: !0,
141
- ...k
150
+ ...w
142
151
  },
143
152
  yaxis: {
144
153
  title: {
145
- text: g,
154
+ text: k,
146
155
  font: {
147
156
  size: 16,
148
- color: o.textSecondary,
157
+ color: r.textSecondary,
149
158
  family: "Inter, sans-serif",
150
159
  weight: 400
151
160
  },
152
161
  standoff: 30
153
162
  },
154
- gridcolor: o.gridColor,
163
+ gridcolor: r.gridColor,
155
164
  range: m,
156
165
  autorange: !m,
157
166
  tickmode: "array",
158
- tickvals: z,
167
+ tickvals: N,
159
168
  showgrid: !0,
160
- ...k
169
+ ...w
161
170
  },
162
171
  legend: {
163
172
  x: 0.5,
@@ -167,28 +176,28 @@ const q = ({
167
176
  orientation: "h",
168
177
  font: {
169
178
  size: 16,
170
- color: o.legendColor,
179
+ color: r.legendColor,
171
180
  family: "Inter, sans-serif",
172
181
  weight: 500
173
182
  }
174
183
  },
175
184
  showlegend: !0
176
- }, i = {
185
+ }, l = {
177
186
  responsive: !0,
178
187
  displayModeBar: !1,
179
188
  displaylogo: !1
180
189
  };
181
- L.newPlot(p.current, r, t, i), C(p.current);
190
+ A.newPlot(p.current, t, o, l), E(p.current);
182
191
  const e = p.current;
183
192
  return () => {
184
- e && L.purge(e);
193
+ e && A.purge(e);
185
194
  };
186
- }, [l, M, w, d, m, y, g, b, I, k, x, z, s, f, o, C]), /* @__PURE__ */ v("div", { className: "relative size-full", children: [
187
- /* @__PURE__ */ A("div", { ref: p, style: { width: "100%", height: "100%" } }),
188
- N
195
+ }, [s, b, _, M, m, x, k, h, z, w, y, N, L, d, i, f, r, E]), /* @__PURE__ */ v("div", { className: "relative size-full", children: [
196
+ /* @__PURE__ */ X("div", { ref: p, style: { width: "100%", height: "100%" } }),
197
+ P
189
198
  ] });
190
199
  };
191
200
  export {
192
- q as LineGraph
201
+ K as LineGraph
193
202
  };
194
203
  //# sourceMappingURL=LineGraph.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LineGraph.js","sources":["../../../../src/components/charts/LineGraph/LineGraph.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { useChartTooltip } from \"../ChartTooltip\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { seriesColor } from \"@/utils/colors\";\n\ntype MarkerSymbol =\n | \"circle\"\n | \"circle-open\"\n | \"circle-dot\"\n | \"circle-open-dot\"\n | \"square\"\n | \"square-open\"\n | \"square-dot\"\n | \"square-open-dot\"\n | \"diamond\"\n | \"diamond-open\"\n | \"diamond-dot\"\n | \"diamond-open-dot\"\n | \"cross\"\n | \"cross-open\"\n | \"cross-dot\"\n | \"cross-open-dot\"\n | \"x\"\n | \"x-open\"\n | \"x-dot\"\n | \"x-open-dot\"\n | \"triangle-up\"\n | \"triangle-up-open\"\n | \"triangle-up-dot\"\n | \"triangle-up-open-dot\"\n | \"triangle-down\"\n | \"triangle-down-open\"\n | \"triangle-down-dot\"\n | \"triangle-down-open-dot\"\n | \"triangle-left\"\n | \"triangle-left-open\"\n | \"triangle-left-dot\"\n | \"triangle-left-open-dot\"\n | \"triangle-right\"\n | \"triangle-right-open\"\n | \"triangle-right-dot\"\n | \"triangle-right-open-dot\"\n | \"triangle-ne\"\n | \"triangle-ne-open\"\n | \"triangle-ne-dot\"\n | \"triangle-ne-open-dot\"\n | \"triangle-se\"\n | \"triangle-se-open\"\n | \"triangle-se-dot\"\n | \"triangle-se-open-dot\"\n | \"triangle-sw\"\n | \"triangle-sw-open\"\n | \"triangle-sw-dot\"\n | \"triangle-sw-open-dot\"\n | \"triangle-nw\"\n | \"triangle-nw-open\"\n | \"triangle-nw-dot\"\n | \"triangle-nw-open-dot\"\n | \"pentagon\"\n | \"pentagon-open\"\n | \"pentagon-dot\"\n | \"pentagon-open-dot\"\n | \"hexagon\"\n | \"hexagon-open\"\n | \"hexagon-dot\"\n | \"hexagon-open-dot\"\n | \"hexagon2\"\n | \"hexagon2-open\"\n | \"hexagon2-dot\"\n | \"hexagon2-open-dot\"\n | \"octagon\"\n | \"octagon-open\"\n | \"octagon-dot\"\n | \"octagon-open-dot\"\n | \"star\"\n | \"star-open\"\n | \"star-dot\"\n | \"star-open-dot\"\n | \"hexagram\"\n | \"hexagram-open\"\n | \"hexagram-dot\"\n | \"hexagram-open-dot\"\n | \"star-triangle-up\"\n | \"star-triangle-up-open\"\n | \"star-triangle-up-dot\"\n | \"star-triangle-up-open-dot\"\n | \"star-triangle-down\"\n | \"star-triangle-down-open\"\n | \"star-triangle-down-dot\"\n | \"star-triangle-down-open-dot\"\n | \"star-square\"\n | \"star-square-open\"\n | \"star-square-dot\"\n | \"star-square-open-dot\"\n | \"star-diamond\"\n | \"star-diamond-open\"\n | \"star-diamond-dot\"\n | \"star-diamond-open-dot\"\n | \"diamond-tall\"\n | \"diamond-tall-open\"\n | \"diamond-tall-dot\"\n | \"diamond-tall-open-dot\"\n | \"diamond-wide\"\n | \"diamond-wide-open\"\n | \"diamond-wide-dot\"\n | \"diamond-wide-open-dot\"\n | \"hourglass\"\n | \"hourglass-open\"\n | \"bowtie\"\n | \"bowtie-open\"\n | \"circle-cross\"\n | \"circle-cross-open\"\n | \"circle-x\"\n | \"circle-x-open\"\n | \"square-cross\"\n | \"square-cross-open\"\n | \"square-x\"\n | \"square-x-open\"\n | \"diamond-cross\"\n | \"diamond-cross-open\"\n | \"diamond-x\"\n | \"diamond-x-open\"\n | \"cross-thin\"\n | \"cross-thin-open\"\n | \"x-thin\"\n | \"x-thin-open\"\n | \"asterisk\"\n | \"asterisk-open\"\n | \"hash\"\n | \"hash-open\"\n | \"hash-dot\"\n | \"hash-open-dot\"\n | \"y-up\"\n | \"y-up-open\"\n | \"y-down\"\n | \"y-down-open\"\n | \"y-left\"\n | \"y-left-open\"\n | \"y-right\"\n | \"y-right-open\"\n | \"line-ew\"\n | \"line-ew-open\"\n | \"line-ns\"\n | \"line-ns-open\"\n | \"line-ne\"\n | \"line-ne-open\"\n | \"line-nw\"\n | \"line-nw-open\"\n | \"arrow\"\n | \"arrow-open\"\n | \"arrow-wide\"\n | \"arrow-wide-open\";\n\ninterface LineDataSeries {\n x: number[];\n y: number[];\n name: string;\n /** Optional color override (auto-assigned from CHART_COLORS if not provided) */\n color?: string;\n symbol?: MarkerSymbol;\n error_y?: {\n type: \"data\";\n array: number[];\n visible: boolean;\n };\n}\n\ntype LineGraphVariant = \"lines\" | \"lines+markers\" | \"lines+markers+error_bars\";\n\ntype LineGraphProps = {\n dataSeries: LineDataSeries[];\n width?: number;\n height?: number;\n xRange?: [number, number];\n yRange?: [number, number];\n variant?: LineGraphVariant;\n xTitle?: string;\n yTitle?: string;\n title?: string;\n};\n\nconst LineGraph: React.FC<LineGraphProps> = ({\n dataSeries,\n width = 1000,\n height = 600,\n xRange,\n yRange,\n variant = \"lines\",\n xTitle = \"Columns\",\n yTitle = \"Rows\",\n title = \"Line Graph\",\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const { bindTooltip, tooltipElement } = useChartTooltip({ xLabel: xTitle, yLabel: yTitle });\n\n const { yMin, yMax } = useMemo(() => {\n let minX = Number.MAX_VALUE;\n let maxX = Number.MIN_VALUE;\n let minY = Number.MAX_VALUE;\n let maxY = Number.MIN_VALUE;\n\n dataSeries.forEach((series) => {\n series.x.forEach((x) => {\n minX = Math.min(minX, x);\n maxX = Math.max(maxX, x);\n });\n series.y.forEach((y) => {\n minY = Math.min(minY, y);\n maxY = Math.max(maxY, y);\n });\n });\n\n const xPadding = (maxX - minX) * 0.1;\n const yPadding = (maxY - minY) * 0.1;\n\n return {\n xMin: minX - xPadding,\n xMax: maxX + xPadding,\n yMin: minY - yPadding,\n yMax: maxY + yPadding,\n };\n }, [dataSeries]);\n\n const effectiveYRange = useMemo(\n () => yRange || [yMin, yMax],\n [yRange, yMin, yMax],\n );\n\n const yTicks = useMemo(() => {\n const range = effectiveYRange[1] - effectiveYRange[0];\n let step = Math.pow(10, Math.floor(Math.log10(range)));\n\n if (range / step > 10) step = step * 2;\n if (range / step < 4) step = step / 2;\n\n const ticks = [];\n let current = Math.ceil(effectiveYRange[0] / step) * step;\n while (current <= effectiveYRange[1]) {\n ticks.push(current);\n current += step;\n }\n return ticks;\n }, [effectiveYRange]);\n\n const xTicks = useMemo(\n () => [...new Set(dataSeries.flatMap((s) => s.x))],\n [dataSeries],\n );\n\n const mode = useMemo((): \"lines\" | \"lines+markers\" => {\n switch (variant) {\n case \"lines+markers\":\n case \"lines+markers+error_bars\":\n return \"lines+markers\";\n default:\n return \"lines\";\n }\n }, [variant]);\n\n const tickOptions = useMemo(\n () => ({\n tickcolor: theme.tickColor,\n ticklen: 12,\n tickwidth: 1,\n ticks: \"outside\" as const,\n tickfont: {\n size: 16,\n color: theme.textColor,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n linecolor: theme.lineColor,\n linewidth: 1,\n position: 0,\n zeroline: false,\n }),\n [theme],\n );\n\n useEffect(() => {\n if (!plotRef.current) return;\n\n const plotData = dataSeries.map((series, index) => {\n const color = seriesColor(index, series.color);\n return {\n x: series.x,\n y: series.y,\n type: \"scatter\" as const,\n mode: mode,\n name: series.name,\n hoverinfo: \"none\" as const,\n line: {\n color,\n width: 1.5,\n },\n marker:\n variant === \"lines\"\n ? { opacity: 0 }\n : {\n color,\n size: 8,\n symbol: series.symbol || \"triangle-up\",\n },\n error_y:\n variant === \"lines+markers+error_bars\"\n ? series.error_y || {\n type: \"data\" as const,\n array: series.y.map(() => 10),\n visible: true,\n color,\n thickness: 1,\n width: 5,\n }\n : undefined,\n };\n });\n\n const layout = {\n title: {\n text: title,\n font: {\n size: 32,\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n },\n },\n width,\n height,\n margin: { l: 80, r: 30, b: 80, t: 60, pad: 10 },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: {\n family: \"Inter, sans-serif\",\n },\n dragmode: false as const,\n xaxis: {\n title: {\n text: xTitle,\n font: {\n size: 16,\n color: theme.textSecondary,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n standoff: 32,\n },\n gridcolor: theme.gridColor,\n range: xRange,\n autorange: !xRange,\n tickmode: \"array\" as const,\n tickvals: xTicks,\n ticktext: xTicks.map(String),\n showgrid: true,\n ...tickOptions,\n },\n yaxis: {\n title: {\n text: yTitle,\n font: {\n size: 16,\n color: theme.textSecondary,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n standoff: 30,\n },\n gridcolor: theme.gridColor,\n range: yRange,\n autorange: !yRange,\n tickmode: \"array\" as const,\n tickvals: yTicks,\n showgrid: true,\n ...tickOptions,\n },\n legend: {\n x: 0.5,\n y: -0.2,\n xanchor: \"center\" as const,\n yanchor: \"top\" as const,\n orientation: \"h\" as const,\n font: {\n size: 16,\n color: theme.legendColor,\n family: \"Inter, sans-serif\",\n weight: 500,\n },\n },\n showlegend: true,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, plotData, layout, config);\n bindTooltip(plotRef.current);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [dataSeries, width, height, xRange, yRange, xTitle, yTitle, title, mode, tickOptions, xTicks, yTicks, effectiveYRange, variant, theme, bindTooltip]);\n\n return (\n <div className=\"relative size-full\">\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n {tooltipElement}\n </div>\n );\n};\n\nexport { LineGraph };\nexport type { LineDataSeries, LineGraphVariant, LineGraphProps, MarkerSymbol };\n"],"names":["LineGraph","dataSeries","width","height","xRange","yRange","variant","xTitle","yTitle","title","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","yMin","yMax","useMemo","minX","maxX","minY","maxY","series","x","y","xPadding","yPadding","effectiveYRange","yTicks","range","step","ticks","current","xTicks","s","mode","tickOptions","useEffect","plotData","index","color","seriesColor","layout","config","Plotly","plotElement","jsxs","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"LineGraph.js","sources":["../../../../src/components/charts/LineGraph/LineGraph.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { useChartTooltip } from \"../ChartTooltip\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { seriesColor } from \"@/utils/colors\";\n\ntype MarkerSymbol =\n | \"circle\"\n | \"circle-open\"\n | \"circle-dot\"\n | \"circle-open-dot\"\n | \"square\"\n | \"square-open\"\n | \"square-dot\"\n | \"square-open-dot\"\n | \"diamond\"\n | \"diamond-open\"\n | \"diamond-dot\"\n | \"diamond-open-dot\"\n | \"cross\"\n | \"cross-open\"\n | \"cross-dot\"\n | \"cross-open-dot\"\n | \"x\"\n | \"x-open\"\n | \"x-dot\"\n | \"x-open-dot\"\n | \"triangle-up\"\n | \"triangle-up-open\"\n | \"triangle-up-dot\"\n | \"triangle-up-open-dot\"\n | \"triangle-down\"\n | \"triangle-down-open\"\n | \"triangle-down-dot\"\n | \"triangle-down-open-dot\"\n | \"triangle-left\"\n | \"triangle-left-open\"\n | \"triangle-left-dot\"\n | \"triangle-left-open-dot\"\n | \"triangle-right\"\n | \"triangle-right-open\"\n | \"triangle-right-dot\"\n | \"triangle-right-open-dot\"\n | \"triangle-ne\"\n | \"triangle-ne-open\"\n | \"triangle-ne-dot\"\n | \"triangle-ne-open-dot\"\n | \"triangle-se\"\n | \"triangle-se-open\"\n | \"triangle-se-dot\"\n | \"triangle-se-open-dot\"\n | \"triangle-sw\"\n | \"triangle-sw-open\"\n | \"triangle-sw-dot\"\n | \"triangle-sw-open-dot\"\n | \"triangle-nw\"\n | \"triangle-nw-open\"\n | \"triangle-nw-dot\"\n | \"triangle-nw-open-dot\"\n | \"pentagon\"\n | \"pentagon-open\"\n | \"pentagon-dot\"\n | \"pentagon-open-dot\"\n | \"hexagon\"\n | \"hexagon-open\"\n | \"hexagon-dot\"\n | \"hexagon-open-dot\"\n | \"hexagon2\"\n | \"hexagon2-open\"\n | \"hexagon2-dot\"\n | \"hexagon2-open-dot\"\n | \"octagon\"\n | \"octagon-open\"\n | \"octagon-dot\"\n | \"octagon-open-dot\"\n | \"star\"\n | \"star-open\"\n | \"star-dot\"\n | \"star-open-dot\"\n | \"hexagram\"\n | \"hexagram-open\"\n | \"hexagram-dot\"\n | \"hexagram-open-dot\"\n | \"star-triangle-up\"\n | \"star-triangle-up-open\"\n | \"star-triangle-up-dot\"\n | \"star-triangle-up-open-dot\"\n | \"star-triangle-down\"\n | \"star-triangle-down-open\"\n | \"star-triangle-down-dot\"\n | \"star-triangle-down-open-dot\"\n | \"star-square\"\n | \"star-square-open\"\n | \"star-square-dot\"\n | \"star-square-open-dot\"\n | \"star-diamond\"\n | \"star-diamond-open\"\n | \"star-diamond-dot\"\n | \"star-diamond-open-dot\"\n | \"diamond-tall\"\n | \"diamond-tall-open\"\n | \"diamond-tall-dot\"\n | \"diamond-tall-open-dot\"\n | \"diamond-wide\"\n | \"diamond-wide-open\"\n | \"diamond-wide-dot\"\n | \"diamond-wide-open-dot\"\n | \"hourglass\"\n | \"hourglass-open\"\n | \"bowtie\"\n | \"bowtie-open\"\n | \"circle-cross\"\n | \"circle-cross-open\"\n | \"circle-x\"\n | \"circle-x-open\"\n | \"square-cross\"\n | \"square-cross-open\"\n | \"square-x\"\n | \"square-x-open\"\n | \"diamond-cross\"\n | \"diamond-cross-open\"\n | \"diamond-x\"\n | \"diamond-x-open\"\n | \"cross-thin\"\n | \"cross-thin-open\"\n | \"x-thin\"\n | \"x-thin-open\"\n | \"asterisk\"\n | \"asterisk-open\"\n | \"hash\"\n | \"hash-open\"\n | \"hash-dot\"\n | \"hash-open-dot\"\n | \"y-up\"\n | \"y-up-open\"\n | \"y-down\"\n | \"y-down-open\"\n | \"y-left\"\n | \"y-left-open\"\n | \"y-right\"\n | \"y-right-open\"\n | \"line-ew\"\n | \"line-ew-open\"\n | \"line-ns\"\n | \"line-ns-open\"\n | \"line-ne\"\n | \"line-ne-open\"\n | \"line-nw\"\n | \"line-nw-open\"\n | \"arrow\"\n | \"arrow-open\"\n | \"arrow-wide\"\n | \"arrow-wide-open\";\n\ninterface LineDataSeries {\n x: number[];\n y: number[];\n name: string;\n /** Optional color override (auto-assigned from CHART_COLORS if not provided) */\n color?: string;\n symbol?: MarkerSymbol;\n error_y?: {\n type: \"data\";\n array: number[];\n visible: boolean;\n };\n}\n\ntype LineGraphVariant = \"lines\" | \"lines+markers\" | \"lines+markers+error_bars\";\n\n/** Top margin reserving room for the 32px title; reduced when no title is set */\nconst TITLE_MARGIN_TOP = 60;\nconst NO_TITLE_MARGIN_TOP = 30;\n\ntype LineGraphProps = {\n dataSeries: LineDataSeries[];\n width?: number;\n height?: number;\n xRange?: [number, number];\n yRange?: [number, number];\n variant?: LineGraphVariant;\n xTitle?: string;\n yTitle?: string;\n title?: string;\n /**\n * Categorical labels for the x-axis ticks. When provided, the x data values\n * still drive line positioning but the displayed tick labels match these\n * strings in order (e.g. [\"Mon\", \"Tue\", …]). Should align 1:1 with the\n * unique, ordered x values across all series.\n */\n xTickText?: string[];\n};\n\nconst LineGraph: React.FC<LineGraphProps> = ({\n dataSeries,\n width = 1000,\n height = 600,\n xRange,\n yRange,\n variant = \"lines\",\n xTitle = \"Columns\",\n yTitle = \"Rows\",\n title,\n xTickText,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const { bindTooltip, tooltipElement } = useChartTooltip({ xLabel: xTitle, yLabel: yTitle });\n\n const { yMin, yMax } = useMemo(() => {\n let minX = Number.MAX_VALUE;\n let maxX = Number.MIN_VALUE;\n let minY = Number.MAX_VALUE;\n let maxY = Number.MIN_VALUE;\n\n dataSeries.forEach((series) => {\n series.x.forEach((x) => {\n minX = Math.min(minX, x);\n maxX = Math.max(maxX, x);\n });\n series.y.forEach((y) => {\n minY = Math.min(minY, y);\n maxY = Math.max(maxY, y);\n });\n });\n\n const xPadding = (maxX - minX) * 0.1;\n const yPadding = (maxY - minY) * 0.1;\n\n return {\n xMin: minX - xPadding,\n xMax: maxX + xPadding,\n yMin: minY - yPadding,\n yMax: maxY + yPadding,\n };\n }, [dataSeries]);\n\n const effectiveYRange = useMemo(\n () => yRange || [yMin, yMax],\n [yRange, yMin, yMax],\n );\n\n const yTicks = useMemo(() => {\n const range = effectiveYRange[1] - effectiveYRange[0];\n let step = Math.pow(10, Math.floor(Math.log10(range)));\n\n if (range / step > 10) step = step * 2;\n if (range / step < 4) step = step / 2;\n\n const ticks = [];\n let current = Math.ceil(effectiveYRange[0] / step) * step;\n while (current <= effectiveYRange[1]) {\n ticks.push(current);\n current += step;\n }\n return ticks;\n }, [effectiveYRange]);\n\n const xTicks = useMemo(\n () => [...new Set(dataSeries.flatMap((s) => s.x))].sort((a, b) => a - b),\n [dataSeries],\n );\n\n // Only apply categorical labels when they align 1:1 with the tick positions;\n // a mismatch would silently mis-label ticks, so fall back to numeric ticks.\n const useCategoricalX = !!xTickText && xTickText.length === xTicks.length;\n\n const mode = useMemo((): \"lines\" | \"lines+markers\" => {\n switch (variant) {\n case \"lines+markers\":\n case \"lines+markers+error_bars\":\n return \"lines+markers\";\n default:\n return \"lines\";\n }\n }, [variant]);\n\n const tickOptions = useMemo(\n () => ({\n tickcolor: theme.tickColor,\n ticklen: 12,\n tickwidth: 1,\n ticks: \"outside\" as const,\n tickfont: {\n size: 16,\n color: theme.textColor,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n linecolor: theme.lineColor,\n linewidth: 1,\n position: 0,\n zeroline: false,\n }),\n [theme],\n );\n\n useEffect(() => {\n if (!plotRef.current) return;\n\n const plotData = dataSeries.map((series, index) => {\n const color = seriesColor(index, series.color);\n return {\n x: series.x,\n y: series.y,\n type: \"scatter\" as const,\n mode: mode,\n name: series.name,\n hoverinfo: \"none\" as const,\n line: {\n color,\n width: 1.5,\n },\n marker:\n variant === \"lines\"\n ? { opacity: 0 }\n : {\n color,\n size: 8,\n symbol: series.symbol || \"triangle-up\",\n },\n error_y:\n variant === \"lines+markers+error_bars\"\n ? series.error_y || {\n type: \"data\" as const,\n array: series.y.map(() => 10),\n visible: true,\n color,\n thickness: 1,\n width: 5,\n }\n : undefined,\n };\n });\n\n const layout = {\n ...(title\n ? {\n title: {\n text: title,\n font: {\n size: 32,\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n },\n },\n }\n : {}),\n width,\n height,\n margin: {\n l: 80,\n r: 30,\n b: 80,\n t: title ? TITLE_MARGIN_TOP : NO_TITLE_MARGIN_TOP,\n pad: 10,\n },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: {\n family: \"Inter, sans-serif\",\n },\n dragmode: false as const,\n xaxis: {\n title: {\n text: xTitle,\n font: {\n size: 16,\n color: theme.textSecondary,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n standoff: 32,\n },\n gridcolor: theme.gridColor,\n range: xRange,\n autorange: !xRange,\n tickmode: \"array\" as const,\n tickvals: xTicks,\n ticktext: useCategoricalX ? xTickText : xTicks.map(String),\n showgrid: true,\n ...tickOptions,\n },\n yaxis: {\n title: {\n text: yTitle,\n font: {\n size: 16,\n color: theme.textSecondary,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n standoff: 30,\n },\n gridcolor: theme.gridColor,\n range: yRange,\n autorange: !yRange,\n tickmode: \"array\" as const,\n tickvals: yTicks,\n showgrid: true,\n ...tickOptions,\n },\n legend: {\n x: 0.5,\n y: -0.2,\n xanchor: \"center\" as const,\n yanchor: \"top\" as const,\n orientation: \"h\" as const,\n font: {\n size: 16,\n color: theme.legendColor,\n family: \"Inter, sans-serif\",\n weight: 500,\n },\n },\n showlegend: true,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, plotData, layout, config);\n bindTooltip(plotRef.current);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [dataSeries, width, height, xRange, yRange, xTitle, yTitle, title, mode, tickOptions, xTicks, yTicks, useCategoricalX, xTickText, effectiveYRange, variant, theme, bindTooltip]);\n\n return (\n <div className=\"relative size-full\">\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n {tooltipElement}\n </div>\n );\n};\n\nexport { LineGraph };\nexport type { LineDataSeries, LineGraphVariant, LineGraphProps, MarkerSymbol };\n"],"names":["TITLE_MARGIN_TOP","NO_TITLE_MARGIN_TOP","LineGraph","dataSeries","width","height","xRange","yRange","variant","xTitle","yTitle","title","xTickText","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","yMin","yMax","useMemo","minX","maxX","minY","maxY","series","x","y","xPadding","yPadding","effectiveYRange","yTicks","range","step","ticks","current","xTicks","s","a","b","useCategoricalX","mode","tickOptions","useEffect","plotData","index","color","seriesColor","layout","config","Plotly","plotElement","jsxs","jsx"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react/jsx-runtime"),j=require("plotly.js-dist"),a=require("react"),N=require("../ChartTooltip/ChartTooltip.cjs"),P=require("../../../hooks/use-plotly-theme.cjs"),T=require("../../../utils/colors.cjs"),v=T.CHART_COLORS,R=({dataSeries:e,width:u=400,height:f=400,title:g="Pie Chart",textInfo:x="percent",hole:h=0,rotation:d=0})=>{const r=a.useRef(null),i=P.usePlotlyTheme(),{bindTooltip:b,tooltipElement:w}=N.useChartTooltip({followCursor:!0}),m=a.useMemo(()=>{if(e.colors&&e.colors.length>=e.labels.length)return e.colors;const s=[...e.colors||[]],n=e.labels.length-s.length;if(n<=0)return s;for(let t=0;t<n;t++)s.push(v[t%v.length]);return s},[e.colors,e.labels.length]);a.useEffect(()=>{if(!r.current)return;const s=[{type:"pie",labels:e.labels,values:e.values,name:e.name,marker:{colors:m},textinfo:x,hoverinfo:"none",insidetextfont:{size:0,family:"Inter, sans-serif",color:"transparent"},hole:h,rotation:d}],n={width:u,height:f,font:{family:"Inter, sans-serif",color:i.textColor},showlegend:!1,margin:{l:40,r:40,b:40,t:40},paper_bgcolor:i.paperBg,plot_bgcolor:i.plotBg},t={responsive:!0,displayModeBar:!1,displaylogo:!1};j.newPlot(r.current,s,n,t),b(r.current);const c=r.current;return()=>{c&&j.purge(c)}},[m,e.labels,e.name,e.values,u,f,x,h,d,i,b]);const C=({labels:s,colors:n})=>{const t=s.map((o,p)=>l.jsx(a.Fragment,{children:l.jsxs("div",{className:"flex items-center text-[13px] leading-[18px] font-medium",children:[l.jsx("span",{"data-slot":"pie-legend-swatch",className:"mr-1.5 inline-block size-3 rounded-[4px]",style:{background:n[p]}}),o,p<s.length-1&&l.jsx("span",{className:"mx-3 inline-block h-6 w-0.5 bg-border"})]})},`${o}-${p}`)),c=6,y=[];for(let o=0;o<t.length;o+=c)y.push(l.jsx("div",{className:"mb-2 flex w-full max-w-full flex-wrap items-center justify-center gap-y-3 break-words px-10",children:t.slice(o,o+c)},o));return l.jsx("div",{"data-slot":"pie-legend",className:"flex w-full flex-wrap text-foreground",children:y})};return l.jsxs("div",{className:"relative",style:{width:u},children:[l.jsxs("div",{className:"size-full",children:[g&&l.jsx("div",{className:"px-10 text-center",children:l.jsx("h2",{className:"m-0 text-[32px] leading-tight font-semibold",children:g})}),l.jsx("div",{ref:r,style:{width:"100%",height:"100%",margin:"0"}}),l.jsx(C,{labels:e.labels,colors:m})]}),w]})};exports.PieChart=R;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react/jsx-runtime"),j=require("plotly.js-dist"),u=require("react"),N=require("../ChartTooltip/ChartTooltip.cjs"),P=require("../../../hooks/use-plotly-theme.cjs"),T=require("../../../utils/colors.cjs"),v=T.CHART_COLORS,R=({dataSeries:e,width:a=400,height:f=400,title:g,textInfo:x="percent",hole:h=0,rotation:d=0})=>{const r=u.useRef(null),i=P.usePlotlyTheme(),{bindTooltip:b,tooltipElement:w}=N.useChartTooltip({followCursor:!0}),m=u.useMemo(()=>{if(e.colors&&e.colors.length>=e.labels.length)return e.colors;const s=[...e.colors||[]],n=e.labels.length-s.length;if(n<=0)return s;for(let t=0;t<n;t++)s.push(v[t%v.length]);return s},[e.colors,e.labels.length]);u.useEffect(()=>{if(!r.current)return;const s=[{type:"pie",labels:e.labels,values:e.values,name:e.name,marker:{colors:m},textinfo:x,hoverinfo:"none",insidetextfont:{size:0,family:"Inter, sans-serif",color:"transparent"},hole:h,rotation:d}],n={width:a,height:f,font:{family:"Inter, sans-serif",color:i.textColor},showlegend:!1,margin:{l:40,r:40,b:40,t:40},paper_bgcolor:i.paperBg,plot_bgcolor:i.plotBg},t={responsive:!0,displayModeBar:!1,displaylogo:!1};j.newPlot(r.current,s,n,t),b(r.current);const c=r.current;return()=>{c&&j.purge(c)}},[m,e.labels,e.name,e.values,a,f,x,h,d,i,b]);const C=({labels:s,colors:n})=>{const t=s.map((o,p)=>l.jsx(u.Fragment,{children:l.jsxs("div",{className:"flex items-center text-[13px] leading-[18px] font-medium",children:[l.jsx("span",{"data-slot":"pie-legend-swatch",className:"mr-1.5 inline-block size-3 rounded-[4px]",style:{background:n[p]}}),o,p<s.length-1&&l.jsx("span",{className:"mx-3 inline-block h-6 w-0.5 bg-border"})]})},`${o}-${p}`)),c=6,y=[];for(let o=0;o<t.length;o+=c)y.push(l.jsx("div",{className:"mb-2 flex w-full max-w-full flex-wrap items-center justify-center gap-y-3 break-words px-10",children:t.slice(o,o+c)},o));return l.jsx("div",{"data-slot":"pie-legend",className:"flex w-full flex-wrap text-foreground",children:y})};return l.jsxs("div",{className:"relative",style:{width:a},children:[l.jsxs("div",{className:"size-full",children:[g&&l.jsx("div",{className:"px-10 text-center",children:l.jsx("h2",{className:"m-0 text-[32px] leading-tight font-semibold",children:g})}),l.jsx("div",{ref:r,style:{width:"100%",height:"100%",margin:"0"}}),l.jsx(C,{labels:e.labels,colors:m})]}),w]})};exports.PieChart=R;
2
2
  //# sourceMappingURL=PieChart.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"PieChart.cjs","sources":["../../../../src/components/charts/PieChart/PieChart.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { useChartTooltip } from \"../ChartTooltip\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { CHART_COLORS } from \"@/utils/colors\";\n\ninterface PieDataSeries {\n labels: string[];\n values: number[];\n name: string;\n colors?: string[];\n}\n\ntype PieTextInfo =\n | \"none\"\n | \"label\"\n | \"percent\"\n | \"value\"\n | \"label+percent\"\n | \"label+value\"\n | \"value+percent\"\n | \"label+value+percent\";\n\ntype PieChartProps = {\n dataSeries: PieDataSeries;\n width?: number;\n height?: number;\n title?: string;\n textInfo?: PieTextInfo;\n hole?: number;\n rotation?: number;\n};\n\nconst DEFAULT_COLORS = CHART_COLORS;\n\nconst PieChart: React.FC<PieChartProps> = ({\n dataSeries,\n width = 400,\n height = 400,\n title = \"Pie Chart\",\n textInfo = \"percent\",\n hole = 0,\n rotation = 0,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n // Slices are large hover targets, so the tooltip tracks the cursor (clamped\n // to the viewport) rather than pinning to the slice centroid\n const { bindTooltip, tooltipElement } = useChartTooltip({ followCursor: true });\n\n const colors = useMemo(() => {\n if (\n dataSeries.colors &&\n dataSeries.colors.length >= dataSeries.labels.length\n ) {\n return dataSeries.colors;\n }\n\n const result = [...(dataSeries.colors || [])];\n const missingColors = dataSeries.labels.length - result.length;\n\n if (missingColors <= 0) return result;\n\n for (let i = 0; i < missingColors; i++) {\n result.push(DEFAULT_COLORS[i % DEFAULT_COLORS.length]);\n }\n\n return result;\n }, [dataSeries.colors, dataSeries.labels.length]);\n\n useEffect(() => {\n if (!plotRef.current) return;\n\n const plotData = [\n {\n type: \"pie\" as const,\n labels: dataSeries.labels,\n values: dataSeries.values,\n name: dataSeries.name,\n marker: {\n colors: colors,\n },\n textinfo: textInfo,\n hoverinfo: \"none\" as const,\n insidetextfont: {\n size: 0,\n family: \"Inter, sans-serif\",\n color: \"transparent\",\n },\n hole: hole,\n rotation: rotation,\n },\n ];\n\n const layout = {\n width,\n height,\n font: {\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n },\n showlegend: false,\n margin: { l: 40, r: 40, b: 40, t: 40 },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, plotData, layout, config);\n bindTooltip(plotRef.current);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [colors, dataSeries.labels, dataSeries.name, dataSeries.values, width, height, textInfo, hole, rotation, theme, bindTooltip]);\n\n const PieChartLegend: React.FC<{ labels: string[]; colors: string[] }> = ({\n labels,\n colors,\n }) => {\n const items = labels.map((label, i) => (\n <React.Fragment key={`${label}-${i}`}>\n <div className=\"flex items-center text-[13px] leading-[18px] font-medium\">\n <span\n data-slot=\"pie-legend-swatch\"\n className=\"mr-1.5 inline-block size-3 rounded-[4px]\"\n style={{ background: colors[i] }}\n />\n {label}\n {i < labels.length - 1 && (\n <span className=\"mx-3 inline-block h-6 w-0.5 bg-border\" />\n )}\n </div>\n </React.Fragment>\n ));\n\n const rowSize = 6;\n const rows = [];\n for (let i = 0; i < items.length; i += rowSize) {\n rows.push(\n <div\n className=\"mb-2 flex w-full max-w-full flex-wrap items-center justify-center gap-y-3 break-words px-10\"\n key={i}\n >\n {items.slice(i, i + rowSize)}\n </div>\n );\n }\n return (\n <div data-slot=\"pie-legend\" className=\"flex w-full flex-wrap text-foreground\">\n {rows}\n </div>\n );\n };\n\n return (\n <div className=\"relative\" style={{ width: width }}>\n <div className=\"size-full\">\n {title && (\n <div className=\"px-10 text-center\">\n <h2 className=\"m-0 text-[32px] leading-tight font-semibold\">{title}</h2>\n </div>\n )}\n <div\n ref={plotRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n margin: \"0\",\n }}\n />\n <PieChartLegend labels={dataSeries.labels} colors={colors} />\n </div>\n {tooltipElement}\n </div>\n );\n};\n\nexport { PieChart };\nexport type { PieDataSeries, PieTextInfo, PieChartProps };\n"],"names":["DEFAULT_COLORS","CHART_COLORS","PieChart","dataSeries","width","height","title","textInfo","hole","rotation","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","colors","useMemo","result","missingColors","i","useEffect","plotData","layout","config","Plotly","plotElement","PieChartLegend","labels","items","label","jsx","React","jsxs","rowSize","rows"],"mappings":"0SAmCMA,EAAiBC,EAAAA,aAEjBC,EAAoC,CAAC,CACzC,WAAAC,EACA,MAAAC,EAAQ,IACR,OAAAC,EAAS,IACT,MAAAC,EAAQ,YACR,SAAAC,EAAW,UACX,KAAAC,EAAO,EACP,SAAAC,EAAW,CACb,IAAM,CACJ,MAAMC,EAAUC,EAAAA,OAAuB,IAAI,EACrCC,EAAQC,EAAAA,eAAA,EAGR,CAAE,YAAAC,EAAa,eAAAC,CAAA,EAAmBC,EAAAA,gBAAgB,CAAE,aAAc,GAAM,EAExEC,EAASC,EAAAA,QAAQ,IAAM,CAC3B,GACEf,EAAW,QACXA,EAAW,OAAO,QAAUA,EAAW,OAAO,OAE9C,OAAOA,EAAW,OAGpB,MAAMgB,EAAS,CAAC,GAAIhB,EAAW,QAAU,CAAA,CAAG,EACtCiB,EAAgBjB,EAAW,OAAO,OAASgB,EAAO,OAExD,GAAIC,GAAiB,EAAG,OAAOD,EAE/B,QAASE,EAAI,EAAGA,EAAID,EAAeC,IACjCF,EAAO,KAAKnB,EAAeqB,EAAIrB,EAAe,MAAM,CAAC,EAGvD,OAAOmB,CACT,EAAG,CAAChB,EAAW,OAAQA,EAAW,OAAO,MAAM,CAAC,EAEhDmB,EAAAA,UAAU,IAAM,CACd,GAAI,CAACZ,EAAQ,QAAS,OAEtB,MAAMa,EAAW,CACf,CACE,KAAM,MACN,OAAQpB,EAAW,OACnB,OAAQA,EAAW,OACnB,KAAMA,EAAW,KACjB,OAAQ,CACN,OAAAc,CAAA,EAEF,SAAUV,EACV,UAAW,OACX,eAAgB,CACd,KAAM,EACN,OAAQ,oBACR,MAAO,aAAA,EAET,KAAAC,EACA,SAAAC,CAAA,CACF,EAGIe,EAAS,CACb,MAAApB,EACA,OAAAC,EACA,KAAM,CACJ,OAAQ,oBACR,MAAOO,EAAM,SAAA,EAEf,WAAY,GACZ,OAAQ,CAAE,EAAG,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,EAAA,EAClC,cAAeA,EAAM,QACrB,aAAcA,EAAM,MAAA,EAGhBa,EAAS,CACb,WAAY,GACZ,eAAgB,GAChB,YAAa,EAAA,EAGfC,EAAO,QAAQhB,EAAQ,QAASa,EAAUC,EAAQC,CAAM,EACxDX,EAAYJ,EAAQ,OAAO,EAG3B,MAAMiB,EAAcjB,EAAQ,QAE5B,MAAO,IAAM,CACPiB,GACFD,EAAO,MAAMC,CAAW,CAE5B,CACF,EAAG,CAACV,EAAQd,EAAW,OAAQA,EAAW,KAAMA,EAAW,OAAQC,EAAOC,EAAQE,EAAUC,EAAMC,EAAUG,EAAOE,CAAW,CAAC,EAE/H,MAAMc,EAAmE,CAAC,CACxE,OAAAC,EACA,OAAAZ,CAAA,IACI,CACJ,MAAMa,EAAQD,EAAO,IAAI,CAACE,EAAOV,IAC/BW,MAACC,EAAM,SAAN,CACC,SAAAC,OAAC,MAAA,CAAI,UAAU,2DACb,SAAA,CAAAF,EAAAA,IAAC,OAAA,CACC,YAAU,oBACV,UAAU,2CACV,MAAO,CAAE,WAAYf,EAAOI,CAAC,CAAA,CAAE,CAAA,EAEhCU,EACAV,EAAIQ,EAAO,OAAS,GACnBG,EAAAA,IAAC,OAAA,CAAK,UAAU,uCAAA,CAAwC,CAAA,CAAA,CAE5D,GAXmB,GAAGD,CAAK,IAAIV,CAAC,EAYlC,CACD,EAEKc,EAAU,EACVC,EAAO,CAAA,EACb,QAASf,EAAI,EAAGA,EAAIS,EAAM,OAAQT,GAAKc,EACrCC,EAAK,KACHJ,EAAAA,IAAC,MAAA,CACC,UAAU,8FAGT,SAAAF,EAAM,MAAMT,EAAGA,EAAIc,CAAO,CAAA,EAFtBd,CAAA,CAGP,EAGJ,aACG,MAAA,CAAI,YAAU,aAAa,UAAU,wCACnC,SAAAe,EACH,CAEJ,EAEA,cACG,MAAA,CAAI,UAAU,WAAW,MAAO,CAAE,MAAAhC,GACjC,SAAA,CAAA8B,EAAAA,KAAC,MAAA,CAAI,UAAU,YACZ,SAAA,CAAA5B,GACC0B,EAAAA,IAAC,OAAI,UAAU,oBACb,eAAC,KAAA,CAAG,UAAU,8CAA+C,SAAA1B,CAAA,CAAM,CAAA,CACrE,EAEF0B,EAAAA,IAAC,MAAA,CACC,IAAKtB,EACL,MAAO,CACL,MAAO,OACP,OAAQ,OACR,OAAQ,GAAA,CACV,CAAA,EAEFsB,EAAAA,IAACJ,EAAA,CAAe,OAAQzB,EAAW,OAAQ,OAAAc,CAAA,CAAgB,CAAA,EAC7D,EACCF,CAAA,EACH,CAEJ"}
1
+ {"version":3,"file":"PieChart.cjs","sources":["../../../../src/components/charts/PieChart/PieChart.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { useChartTooltip } from \"../ChartTooltip\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { CHART_COLORS } from \"@/utils/colors\";\n\ninterface PieDataSeries {\n labels: string[];\n values: number[];\n name: string;\n colors?: string[];\n}\n\ntype PieTextInfo =\n | \"none\"\n | \"label\"\n | \"percent\"\n | \"value\"\n | \"label+percent\"\n | \"label+value\"\n | \"value+percent\"\n | \"label+value+percent\";\n\ntype PieChartProps = {\n dataSeries: PieDataSeries;\n width?: number;\n height?: number;\n title?: string;\n textInfo?: PieTextInfo;\n hole?: number;\n rotation?: number;\n};\n\nconst DEFAULT_COLORS = CHART_COLORS;\n\nconst PieChart: React.FC<PieChartProps> = ({\n dataSeries,\n width = 400,\n height = 400,\n title,\n textInfo = \"percent\",\n hole = 0,\n rotation = 0,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n // Slices are large hover targets, so the tooltip tracks the cursor (clamped\n // to the viewport) rather than pinning to the slice centroid\n const { bindTooltip, tooltipElement } = useChartTooltip({ followCursor: true });\n\n const colors = useMemo(() => {\n if (\n dataSeries.colors &&\n dataSeries.colors.length >= dataSeries.labels.length\n ) {\n return dataSeries.colors;\n }\n\n const result = [...(dataSeries.colors || [])];\n const missingColors = dataSeries.labels.length - result.length;\n\n if (missingColors <= 0) return result;\n\n for (let i = 0; i < missingColors; i++) {\n result.push(DEFAULT_COLORS[i % DEFAULT_COLORS.length]);\n }\n\n return result;\n }, [dataSeries.colors, dataSeries.labels.length]);\n\n useEffect(() => {\n if (!plotRef.current) return;\n\n const plotData = [\n {\n type: \"pie\" as const,\n labels: dataSeries.labels,\n values: dataSeries.values,\n name: dataSeries.name,\n marker: {\n colors: colors,\n },\n textinfo: textInfo,\n hoverinfo: \"none\" as const,\n insidetextfont: {\n size: 0,\n family: \"Inter, sans-serif\",\n color: \"transparent\",\n },\n hole: hole,\n rotation: rotation,\n },\n ];\n\n const layout = {\n width,\n height,\n font: {\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n },\n showlegend: false,\n margin: { l: 40, r: 40, b: 40, t: 40 },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, plotData, layout, config);\n bindTooltip(plotRef.current);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [colors, dataSeries.labels, dataSeries.name, dataSeries.values, width, height, textInfo, hole, rotation, theme, bindTooltip]);\n\n const PieChartLegend: React.FC<{ labels: string[]; colors: string[] }> = ({\n labels,\n colors,\n }) => {\n const items = labels.map((label, i) => (\n <React.Fragment key={`${label}-${i}`}>\n <div className=\"flex items-center text-[13px] leading-[18px] font-medium\">\n <span\n data-slot=\"pie-legend-swatch\"\n className=\"mr-1.5 inline-block size-3 rounded-[4px]\"\n style={{ background: colors[i] }}\n />\n {label}\n {i < labels.length - 1 && (\n <span className=\"mx-3 inline-block h-6 w-0.5 bg-border\" />\n )}\n </div>\n </React.Fragment>\n ));\n\n const rowSize = 6;\n const rows = [];\n for (let i = 0; i < items.length; i += rowSize) {\n rows.push(\n <div\n className=\"mb-2 flex w-full max-w-full flex-wrap items-center justify-center gap-y-3 break-words px-10\"\n key={i}\n >\n {items.slice(i, i + rowSize)}\n </div>\n );\n }\n return (\n <div data-slot=\"pie-legend\" className=\"flex w-full flex-wrap text-foreground\">\n {rows}\n </div>\n );\n };\n\n return (\n <div className=\"relative\" style={{ width: width }}>\n <div className=\"size-full\">\n {title && (\n <div className=\"px-10 text-center\">\n <h2 className=\"m-0 text-[32px] leading-tight font-semibold\">{title}</h2>\n </div>\n )}\n <div\n ref={plotRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n margin: \"0\",\n }}\n />\n <PieChartLegend labels={dataSeries.labels} colors={colors} />\n </div>\n {tooltipElement}\n </div>\n );\n};\n\nexport { PieChart };\nexport type { PieDataSeries, PieTextInfo, PieChartProps };\n"],"names":["DEFAULT_COLORS","CHART_COLORS","PieChart","dataSeries","width","height","title","textInfo","hole","rotation","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","colors","useMemo","result","missingColors","i","useEffect","plotData","layout","config","Plotly","plotElement","PieChartLegend","labels","items","label","jsx","React","jsxs","rowSize","rows"],"mappings":"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"}
@@ -8,7 +8,7 @@ const w = T, F = ({
8
8
  dataSeries: e,
9
9
  width: m = 400,
10
10
  height: u = 400,
11
- title: g = "Pie Chart",
11
+ title: g,
12
12
  textInfo: h = "percent",
13
13
  hole: d = 0,
14
14
  rotation: x = 0
@@ -1 +1 @@
1
- {"version":3,"file":"PieChart.js","sources":["../../../../src/components/charts/PieChart/PieChart.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { useChartTooltip } from \"../ChartTooltip\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { CHART_COLORS } from \"@/utils/colors\";\n\ninterface PieDataSeries {\n labels: string[];\n values: number[];\n name: string;\n colors?: string[];\n}\n\ntype PieTextInfo =\n | \"none\"\n | \"label\"\n | \"percent\"\n | \"value\"\n | \"label+percent\"\n | \"label+value\"\n | \"value+percent\"\n | \"label+value+percent\";\n\ntype PieChartProps = {\n dataSeries: PieDataSeries;\n width?: number;\n height?: number;\n title?: string;\n textInfo?: PieTextInfo;\n hole?: number;\n rotation?: number;\n};\n\nconst DEFAULT_COLORS = CHART_COLORS;\n\nconst PieChart: React.FC<PieChartProps> = ({\n dataSeries,\n width = 400,\n height = 400,\n title = \"Pie Chart\",\n textInfo = \"percent\",\n hole = 0,\n rotation = 0,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n // Slices are large hover targets, so the tooltip tracks the cursor (clamped\n // to the viewport) rather than pinning to the slice centroid\n const { bindTooltip, tooltipElement } = useChartTooltip({ followCursor: true });\n\n const colors = useMemo(() => {\n if (\n dataSeries.colors &&\n dataSeries.colors.length >= dataSeries.labels.length\n ) {\n return dataSeries.colors;\n }\n\n const result = [...(dataSeries.colors || [])];\n const missingColors = dataSeries.labels.length - result.length;\n\n if (missingColors <= 0) return result;\n\n for (let i = 0; i < missingColors; i++) {\n result.push(DEFAULT_COLORS[i % DEFAULT_COLORS.length]);\n }\n\n return result;\n }, [dataSeries.colors, dataSeries.labels.length]);\n\n useEffect(() => {\n if (!plotRef.current) return;\n\n const plotData = [\n {\n type: \"pie\" as const,\n labels: dataSeries.labels,\n values: dataSeries.values,\n name: dataSeries.name,\n marker: {\n colors: colors,\n },\n textinfo: textInfo,\n hoverinfo: \"none\" as const,\n insidetextfont: {\n size: 0,\n family: \"Inter, sans-serif\",\n color: \"transparent\",\n },\n hole: hole,\n rotation: rotation,\n },\n ];\n\n const layout = {\n width,\n height,\n font: {\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n },\n showlegend: false,\n margin: { l: 40, r: 40, b: 40, t: 40 },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, plotData, layout, config);\n bindTooltip(plotRef.current);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [colors, dataSeries.labels, dataSeries.name, dataSeries.values, width, height, textInfo, hole, rotation, theme, bindTooltip]);\n\n const PieChartLegend: React.FC<{ labels: string[]; colors: string[] }> = ({\n labels,\n colors,\n }) => {\n const items = labels.map((label, i) => (\n <React.Fragment key={`${label}-${i}`}>\n <div className=\"flex items-center text-[13px] leading-[18px] font-medium\">\n <span\n data-slot=\"pie-legend-swatch\"\n className=\"mr-1.5 inline-block size-3 rounded-[4px]\"\n style={{ background: colors[i] }}\n />\n {label}\n {i < labels.length - 1 && (\n <span className=\"mx-3 inline-block h-6 w-0.5 bg-border\" />\n )}\n </div>\n </React.Fragment>\n ));\n\n const rowSize = 6;\n const rows = [];\n for (let i = 0; i < items.length; i += rowSize) {\n rows.push(\n <div\n className=\"mb-2 flex w-full max-w-full flex-wrap items-center justify-center gap-y-3 break-words px-10\"\n key={i}\n >\n {items.slice(i, i + rowSize)}\n </div>\n );\n }\n return (\n <div data-slot=\"pie-legend\" className=\"flex w-full flex-wrap text-foreground\">\n {rows}\n </div>\n );\n };\n\n return (\n <div className=\"relative\" style={{ width: width }}>\n <div className=\"size-full\">\n {title && (\n <div className=\"px-10 text-center\">\n <h2 className=\"m-0 text-[32px] leading-tight font-semibold\">{title}</h2>\n </div>\n )}\n <div\n ref={plotRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n margin: \"0\",\n }}\n />\n <PieChartLegend labels={dataSeries.labels} colors={colors} />\n </div>\n {tooltipElement}\n </div>\n );\n};\n\nexport { PieChart };\nexport type { PieDataSeries, PieTextInfo, PieChartProps };\n"],"names":["DEFAULT_COLORS","CHART_COLORS","PieChart","dataSeries","width","height","title","textInfo","hole","rotation","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","colors","useMemo","result","missingColors","i","useEffect","plotData","layout","config","Plotly","plotElement","jsxs","jsx","labels","items","label","React","rowSize","rows"],"mappings":"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"}
1
+ {"version":3,"file":"PieChart.js","sources":["../../../../src/components/charts/PieChart/PieChart.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { useChartTooltip } from \"../ChartTooltip\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { CHART_COLORS } from \"@/utils/colors\";\n\ninterface PieDataSeries {\n labels: string[];\n values: number[];\n name: string;\n colors?: string[];\n}\n\ntype PieTextInfo =\n | \"none\"\n | \"label\"\n | \"percent\"\n | \"value\"\n | \"label+percent\"\n | \"label+value\"\n | \"value+percent\"\n | \"label+value+percent\";\n\ntype PieChartProps = {\n dataSeries: PieDataSeries;\n width?: number;\n height?: number;\n title?: string;\n textInfo?: PieTextInfo;\n hole?: number;\n rotation?: number;\n};\n\nconst DEFAULT_COLORS = CHART_COLORS;\n\nconst PieChart: React.FC<PieChartProps> = ({\n dataSeries,\n width = 400,\n height = 400,\n title,\n textInfo = \"percent\",\n hole = 0,\n rotation = 0,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n // Slices are large hover targets, so the tooltip tracks the cursor (clamped\n // to the viewport) rather than pinning to the slice centroid\n const { bindTooltip, tooltipElement } = useChartTooltip({ followCursor: true });\n\n const colors = useMemo(() => {\n if (\n dataSeries.colors &&\n dataSeries.colors.length >= dataSeries.labels.length\n ) {\n return dataSeries.colors;\n }\n\n const result = [...(dataSeries.colors || [])];\n const missingColors = dataSeries.labels.length - result.length;\n\n if (missingColors <= 0) return result;\n\n for (let i = 0; i < missingColors; i++) {\n result.push(DEFAULT_COLORS[i % DEFAULT_COLORS.length]);\n }\n\n return result;\n }, [dataSeries.colors, dataSeries.labels.length]);\n\n useEffect(() => {\n if (!plotRef.current) return;\n\n const plotData = [\n {\n type: \"pie\" as const,\n labels: dataSeries.labels,\n values: dataSeries.values,\n name: dataSeries.name,\n marker: {\n colors: colors,\n },\n textinfo: textInfo,\n hoverinfo: \"none\" as const,\n insidetextfont: {\n size: 0,\n family: \"Inter, sans-serif\",\n color: \"transparent\",\n },\n hole: hole,\n rotation: rotation,\n },\n ];\n\n const layout = {\n width,\n height,\n font: {\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n },\n showlegend: false,\n margin: { l: 40, r: 40, b: 40, t: 40 },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, plotData, layout, config);\n bindTooltip(plotRef.current);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [colors, dataSeries.labels, dataSeries.name, dataSeries.values, width, height, textInfo, hole, rotation, theme, bindTooltip]);\n\n const PieChartLegend: React.FC<{ labels: string[]; colors: string[] }> = ({\n labels,\n colors,\n }) => {\n const items = labels.map((label, i) => (\n <React.Fragment key={`${label}-${i}`}>\n <div className=\"flex items-center text-[13px] leading-[18px] font-medium\">\n <span\n data-slot=\"pie-legend-swatch\"\n className=\"mr-1.5 inline-block size-3 rounded-[4px]\"\n style={{ background: colors[i] }}\n />\n {label}\n {i < labels.length - 1 && (\n <span className=\"mx-3 inline-block h-6 w-0.5 bg-border\" />\n )}\n </div>\n </React.Fragment>\n ));\n\n const rowSize = 6;\n const rows = [];\n for (let i = 0; i < items.length; i += rowSize) {\n rows.push(\n <div\n className=\"mb-2 flex w-full max-w-full flex-wrap items-center justify-center gap-y-3 break-words px-10\"\n key={i}\n >\n {items.slice(i, i + rowSize)}\n </div>\n );\n }\n return (\n <div data-slot=\"pie-legend\" className=\"flex w-full flex-wrap text-foreground\">\n {rows}\n </div>\n );\n };\n\n return (\n <div className=\"relative\" style={{ width: width }}>\n <div className=\"size-full\">\n {title && (\n <div className=\"px-10 text-center\">\n <h2 className=\"m-0 text-[32px] leading-tight font-semibold\">{title}</h2>\n </div>\n )}\n <div\n ref={plotRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n margin: \"0\",\n }}\n />\n <PieChartLegend labels={dataSeries.labels} colors={colors} />\n </div>\n {tooltipElement}\n </div>\n );\n};\n\nexport { PieChart };\nexport type { PieDataSeries, PieTextInfo, PieChartProps };\n"],"names":["DEFAULT_COLORS","CHART_COLORS","PieChart","dataSeries","width","height","title","textInfo","hole","rotation","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","colors","useMemo","result","missingColors","i","useEffect","plotData","layout","config","Plotly","plotElement","jsxs","jsx","labels","items","label","React","rowSize","rows"],"mappings":";;;;;;AAmCA,MAAMA,IAAiBC,GAEjBC,IAAoC,CAAC;AAAA,EACzC,YAAAC;AAAA,EACA,OAAAC,IAAQ;AAAA,EACR,QAAAC,IAAS;AAAA,EACT,OAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,MAAAC,IAAO;AAAA,EACP,UAAAC,IAAW;AACb,MAAM;AACJ,QAAMC,IAAUC,EAAuB,IAAI,GACrCC,IAAQC,EAAA,GAGR,EAAE,aAAAC,GAAa,gBAAAC,EAAA,IAAmBC,EAAgB,EAAE,cAAc,IAAM,GAExEC,IAASC,EAAQ,MAAM;AAC3B,QACEf,EAAW,UACXA,EAAW,OAAO,UAAUA,EAAW,OAAO;AAE9C,aAAOA,EAAW;AAGpB,UAAMgB,IAAS,CAAC,GAAIhB,EAAW,UAAU,CAAA,CAAG,GACtCiB,IAAgBjB,EAAW,OAAO,SAASgB,EAAO;AAExD,QAAIC,KAAiB,EAAG,QAAOD;AAE/B,aAASE,IAAI,GAAGA,IAAID,GAAeC;AACjC,MAAAF,EAAO,KAAKnB,EAAeqB,IAAIrB,EAAe,MAAM,CAAC;AAGvD,WAAOmB;AAAA,EACT,GAAG,CAAChB,EAAW,QAAQA,EAAW,OAAO,MAAM,CAAC;AAEhD,SAAAmB,EAAU,MAAM;AACd,QAAI,CAACZ,EAAQ,QAAS;AAEtB,UAAMa,IAAW;AAAA,MACf;AAAA,QACE,MAAM;AAAA,QACN,QAAQpB,EAAW;AAAA,QACnB,QAAQA,EAAW;AAAA,QACnB,MAAMA,EAAW;AAAA,QACjB,QAAQ;AAAA,UACN,QAAAc;AAAA,QAAA;AAAA,QAEF,UAAUV;AAAA,QACV,WAAW;AAAA,QACX,gBAAgB;AAAA,UACd,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,OAAO;AAAA,QAAA;AAAA,QAET,MAAAC;AAAA,QACA,UAAAC;AAAA,MAAA;AAAA,IACF,GAGIe,IAAS;AAAA,MACb,OAAApB;AAAA,MACA,QAAAC;AAAA,MACA,MAAM;AAAA,QACJ,QAAQ;AAAA,QACR,OAAOO,EAAM;AAAA,MAAA;AAAA,MAEf,YAAY;AAAA,MACZ,QAAQ,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,GAAA;AAAA,MAClC,eAAeA,EAAM;AAAA,MACrB,cAAcA,EAAM;AAAA,IAAA,GAGhBa,IAAS;AAAA,MACb,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,IAAA;AAGf,IAAAC,EAAO,QAAQhB,EAAQ,SAASa,GAAUC,GAAQC,CAAM,GACxDX,EAAYJ,EAAQ,OAAO;AAG3B,UAAMiB,IAAcjB,EAAQ;AAE5B,WAAO,MAAM;AACX,MAAIiB,KACFD,EAAO,MAAMC,CAAW;AAAA,IAE5B;AAAA,EACF,GAAG,CAACV,GAAQd,EAAW,QAAQA,EAAW,MAAMA,EAAW,QAAQC,GAAOC,GAAQE,GAAUC,GAAMC,GAAUG,GAAOE,CAAW,CAAC,qBA0C5H,OAAA,EAAI,WAAU,YAAW,OAAO,EAAE,OAAAV,KACjC,UAAA;AAAA,IAAA,gBAAAwB,EAAC,OAAA,EAAI,WAAU,aACZ,UAAA;AAAA,MAAAtB,KACC,gBAAAuB,EAAC,SAAI,WAAU,qBACb,4BAAC,MAAA,EAAG,WAAU,+CAA+C,UAAAvB,EAAA,CAAM,EAAA,CACrE;AAAA,MAEF,gBAAAuB;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAKnB;AAAA,UACL,OAAO;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,QAAQ;AAAA,UAAA;AAAA,QACV;AAAA,MAAA;AAAA,MAEF,gBAAAmB,EAvDmE,CAAC;AAAA,QACxE,QAAAC;AAAA,QACA,QAAAb;AAAAA,MAAA,MACI;AACJ,cAAMc,IAAQD,EAAO,IAAI,CAACE,GAAOX,MAC/B,gBAAAQ,EAACI,EAAM,UAAN,EACC,UAAA,gBAAAL,EAAC,OAAA,EAAI,WAAU,4DACb,UAAA;AAAA,UAAA,gBAAAC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,aAAU;AAAA,cACV,WAAU;AAAA,cACV,OAAO,EAAE,YAAYZ,EAAOI,CAAC,EAAA;AAAA,YAAE;AAAA,UAAA;AAAA,UAEhCW;AAAA,UACAX,IAAIS,EAAO,SAAS,KACnB,gBAAAD,EAAC,QAAA,EAAK,WAAU,wCAAA,CAAwC;AAAA,QAAA,EAAA,CAE5D,KAXmB,GAAGG,CAAK,IAAIX,CAAC,EAYlC,CACD,GAEKa,IAAU,GACVC,IAAO,CAAA;AACb,iBAASd,IAAI,GAAGA,IAAIU,EAAM,QAAQV,KAAKa;AACrC,UAAAC,EAAK;AAAA,YACH,gBAAAN;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBAGT,UAAAE,EAAM,MAAMV,GAAGA,IAAIa,CAAO;AAAA,cAAA;AAAA,cAFtBb;AAAA,YAAA;AAAA,UAGP;AAGJ,iCACG,OAAA,EAAI,aAAU,cAAa,WAAU,yCACnC,UAAAc,GACH;AAAA,MAEJ,GAkBO,EAAe,QAAQhC,EAAW,QAAQ,QAAAc,EAAA,CAAgB;AAAA,IAAA,GAC7D;AAAA,IACCF;AAAA,EAAA,GACH;AAEJ;"}
package/dist/index.d.ts CHANGED
@@ -144,6 +144,13 @@ export declare interface AreaGraphProps {
144
144
  xTitle?: string;
145
145
  yTitle?: string;
146
146
  title?: string;
147
+ /**
148
+ * Categorical labels for the x-axis ticks. When provided, the x data values
149
+ * still drive area positioning but the displayed tick labels match these
150
+ * strings in order (e.g. ["Mon", "Tue", …]). Should align 1:1 with the
151
+ * unique, ordered x values across all series.
152
+ */
153
+ xTickText?: string[];
147
154
  }
148
155
 
149
156
  export declare type AreaGraphVariant = "normal" | "stacked";
@@ -316,6 +323,13 @@ export declare interface BarGraphProps {
316
323
  yTitle?: string;
317
324
  title?: string;
318
325
  barWidth?: number;
326
+ /**
327
+ * Categorical labels for the x-axis ticks. When provided, the x data values
328
+ * still drive bar positioning but the displayed tick labels match these
329
+ * strings in order (e.g. ["Mon", "Tue", …]). Should align 1:1 with the
330
+ * unique, ordered x values across all series.
331
+ */
332
+ xTickText?: string[];
319
333
  }
320
334
 
321
335
  export declare type BarGraphVariant = "group" | "stack" | "overlay";
@@ -1843,6 +1857,13 @@ export declare type LineGraphProps = {
1843
1857
  xTitle?: string;
1844
1858
  yTitle?: string;
1845
1859
  title?: string;
1860
+ /**
1861
+ * Categorical labels for the x-axis ticks. When provided, the x data values
1862
+ * still drive line positioning but the displayed tick labels match these
1863
+ * strings in order (e.g. ["Mon", "Tue", …]). Should align 1:1 with the
1864
+ * unique, ordered x values across all series.
1865
+ */
1866
+ xTickText?: string[];
1846
1867
  };
1847
1868
 
1848
1869
  export declare type LineGraphVariant = "lines" | "lines+markers" | "lines+markers+error_bars";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tetrascience-npm/tetrascience-react-ui",
3
- "version": "0.6.0-beta.95.1",
3
+ "version": "0.6.0-beta.97.1",
4
4
  "description": "TetraScience React UI",
5
5
  "type": "module",
6
6
  "author": "TetraScience",