@tetrascience-npm/tetrascience-react-ui 0.6.0-beta.82.1 → 0.6.0-beta.84.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.
Files changed (87) hide show
  1. package/dist/components/charts/AreaGraph/AreaGraph.cjs +1 -1
  2. package/dist/components/charts/AreaGraph/AreaGraph.cjs.map +1 -1
  3. package/dist/components/charts/AreaGraph/AreaGraph.js +132 -98
  4. package/dist/components/charts/AreaGraph/AreaGraph.js.map +1 -1
  5. package/dist/components/charts/BarGraph/BarGraph.cjs +1 -1
  6. package/dist/components/charts/BarGraph/BarGraph.cjs.map +1 -1
  7. package/dist/components/charts/BarGraph/BarGraph.js +63 -57
  8. package/dist/components/charts/BarGraph/BarGraph.js.map +1 -1
  9. package/dist/components/charts/Boxplot/Boxplot.cjs +1 -1
  10. package/dist/components/charts/Boxplot/Boxplot.cjs.map +1 -1
  11. package/dist/components/charts/Boxplot/Boxplot.js +83 -74
  12. package/dist/components/charts/Boxplot/Boxplot.js.map +1 -1
  13. package/dist/components/charts/ChartTooltip/ChartTooltip.cjs +2 -0
  14. package/dist/components/charts/ChartTooltip/ChartTooltip.cjs.map +1 -0
  15. package/dist/components/charts/ChartTooltip/ChartTooltip.js +163 -0
  16. package/dist/components/charts/ChartTooltip/ChartTooltip.js.map +1 -0
  17. package/dist/components/charts/ChartTooltip/lines.cjs +2 -0
  18. package/dist/components/charts/ChartTooltip/lines.cjs.map +1 -0
  19. package/dist/components/charts/ChartTooltip/lines.js +29 -0
  20. package/dist/components/charts/ChartTooltip/lines.js.map +1 -0
  21. package/dist/components/charts/Chromatogram/Chromatogram.cjs +1 -1
  22. package/dist/components/charts/Chromatogram/Chromatogram.cjs.map +1 -1
  23. package/dist/components/charts/Chromatogram/Chromatogram.js +75 -61
  24. package/dist/components/charts/Chromatogram/Chromatogram.js.map +1 -1
  25. package/dist/components/charts/ChromatogramChart/ChromatogramChart.cjs +1 -1
  26. package/dist/components/charts/ChromatogramChart/ChromatogramChart.cjs.map +1 -1
  27. package/dist/components/charts/ChromatogramChart/ChromatogramChart.js +116 -108
  28. package/dist/components/charts/ChromatogramChart/ChromatogramChart.js.map +1 -1
  29. package/dist/components/charts/ChromatogramChart/annotations.cjs +1 -1
  30. package/dist/components/charts/ChromatogramChart/annotations.cjs.map +1 -1
  31. package/dist/components/charts/ChromatogramChart/annotations.js +32 -32
  32. package/dist/components/charts/ChromatogramChart/annotations.js.map +1 -1
  33. package/dist/components/charts/ChromatogramChart/boundaryMarkers.cjs +1 -1
  34. package/dist/components/charts/ChromatogramChart/boundaryMarkers.cjs.map +1 -1
  35. package/dist/components/charts/ChromatogramChart/boundaryMarkers.js +6 -6
  36. package/dist/components/charts/ChromatogramChart/boundaryMarkers.js.map +1 -1
  37. package/dist/components/charts/ChromatogramChart/constants.cjs +1 -1
  38. package/dist/components/charts/ChromatogramChart/constants.cjs.map +1 -1
  39. package/dist/components/charts/ChromatogramChart/constants.js +11 -5
  40. package/dist/components/charts/ChromatogramChart/constants.js.map +1 -1
  41. package/dist/components/charts/ChromatogramChart/dataProcessing.cjs +1 -1
  42. package/dist/components/charts/ChromatogramChart/dataProcessing.cjs.map +1 -1
  43. package/dist/components/charts/ChromatogramChart/dataProcessing.js +38 -49
  44. package/dist/components/charts/ChromatogramChart/dataProcessing.js.map +1 -1
  45. package/dist/components/charts/DotPlot/DotPlot.cjs +1 -1
  46. package/dist/components/charts/DotPlot/DotPlot.cjs.map +1 -1
  47. package/dist/components/charts/DotPlot/DotPlot.js +57 -63
  48. package/dist/components/charts/DotPlot/DotPlot.js.map +1 -1
  49. package/dist/components/charts/Histogram/Histogram.cjs +1 -1
  50. package/dist/components/charts/Histogram/Histogram.cjs.map +1 -1
  51. package/dist/components/charts/Histogram/Histogram.js +98 -104
  52. package/dist/components/charts/Histogram/Histogram.js.map +1 -1
  53. package/dist/components/charts/LineGraph/LineGraph.cjs +1 -1
  54. package/dist/components/charts/LineGraph/LineGraph.cjs.map +1 -1
  55. package/dist/components/charts/LineGraph/LineGraph.js +97 -88
  56. package/dist/components/charts/LineGraph/LineGraph.js.map +1 -1
  57. package/dist/components/charts/PieChart/PieChart.cjs +1 -1
  58. package/dist/components/charts/PieChart/PieChart.cjs.map +1 -1
  59. package/dist/components/charts/PieChart/PieChart.js +65 -68
  60. package/dist/components/charts/PieChart/PieChart.js.map +1 -1
  61. package/dist/components/charts/PlateMap/PlateMap.cjs +1 -1
  62. package/dist/components/charts/PlateMap/PlateMap.cjs.map +1 -1
  63. package/dist/components/charts/PlateMap/PlateMap.js +271 -256
  64. package/dist/components/charts/PlateMap/PlateMap.js.map +1 -1
  65. package/dist/components/charts/PlateMap/constants.cjs +1 -1
  66. package/dist/components/charts/PlateMap/constants.cjs.map +1 -1
  67. package/dist/components/charts/PlateMap/constants.js +20 -29
  68. package/dist/components/charts/PlateMap/constants.js.map +1 -1
  69. package/dist/components/charts/ScatterGraph/ScatterGraph.cjs +1 -1
  70. package/dist/components/charts/ScatterGraph/ScatterGraph.cjs.map +1 -1
  71. package/dist/components/charts/ScatterGraph/ScatterGraph.js +113 -89
  72. package/dist/components/charts/ScatterGraph/ScatterGraph.js.map +1 -1
  73. package/dist/hooks/use-plotly-theme.cjs +1 -1
  74. package/dist/hooks/use-plotly-theme.cjs.map +1 -1
  75. package/dist/hooks/use-plotly-theme.js +4 -2
  76. package/dist/hooks/use-plotly-theme.js.map +1 -1
  77. package/dist/index.cjs +1 -1
  78. package/dist/index.css +1 -1
  79. package/dist/index.d.ts +156 -76
  80. package/dist/index.js +587 -581
  81. package/dist/index.js.map +1 -1
  82. package/dist/index.tailwind.css +1 -1
  83. package/dist/utils/colors.cjs +1 -1
  84. package/dist/utils/colors.cjs.map +1 -1
  85. package/dist/utils/colors.js +38 -93
  86. package/dist/utils/colors.js.map +1 -1
  87. package/package.json +1 -1
@@ -1,80 +1,93 @@
1
- import { jsx as p, jsxs as _ } from "react/jsx-runtime";
2
- import B from "plotly.js-dist";
3
- import { useRef as D, useMemo as n, useEffect as O } from "react";
4
- import { usePlotlyTheme as j } from "../../../hooks/use-plotly-theme.js";
1
+ import { jsx as p, jsxs as G } from "react/jsx-runtime";
2
+ import L from "plotly.js-dist";
3
+ import { useRef as F, useMemo as s, useEffect as $ } from "react";
4
+ import { useChartTooltip as D } from "../ChartTooltip/ChartTooltip.js";
5
+ import { usePlotlyTheme as H } from "../../../hooks/use-plotly-theme.js";
6
+ import { CHART_COLORS as b } from "../../../utils/colors.js";
5
7
  /* empty css */
6
- const $ = 75, L = 1.05, R = (e) => {
8
+ const I = 75, V = 1.05, z = (e) => {
7
9
  const r = {
8
10
  A: e.peakA,
9
11
  T: e.peakT,
10
12
  G: e.peakG,
11
13
  C: e.peakC
12
14
  }, m = Object.values(r);
13
- if (m.every((i) => i === m[0]))
15
+ if (m.every((a) => a === m[0]))
14
16
  return "";
15
17
  let h = "", u = 0;
16
- return Object.entries(r).forEach(([i, f]) => {
17
- f > u && (h = i, u = f);
18
+ return Object.entries(r).forEach(([a, f]) => {
19
+ f > u && (h = a, u = f);
18
20
  }), h;
19
- }, Y = ({
21
+ }, ee = ({
20
22
  data: e = [],
21
23
  width: r = 900,
22
24
  height: m = 600,
23
- positionInterval: d = 10,
24
- colorA: h = "#2D9CDB",
25
- colorT: u = "#A1C63C",
26
- colorG: i = "#FF5C64",
27
- colorC: f = "#FFA62E"
25
+ positionInterval: x = 10,
26
+ colorA: h = b[0],
27
+ // blue
28
+ colorT: u = b[2],
29
+ // teal/green
30
+ colorG: a = b[3],
31
+ // red
32
+ colorC: f = b[1]
33
+ // orange
28
34
  }) => {
29
- const x = D(null), y = j(), s = n(() => e.map((t) => t.position), [e]), G = n(() => e.map((t) => R(t)), [e]), k = n(() => e.map((t) => t.peakA), [e]), P = n(() => e.map((t) => t.peakT), [e]), T = n(() => e.map((t) => t.peakG), [e]), C = n(() => e.map((t) => t.peakC), [e]), b = n(
35
+ const g = F(null), y = H(), { bindTooltip: M, tooltipElement: B } = D({
36
+ xLabel: "Position",
37
+ yLabel: "Intensity"
38
+ }), n = s(() => e.map((t) => t.position), [e]), R = s(() => e.map((t) => z(t)), [e]), T = s(() => e.map((t) => t.peakA), [e]), k = s(() => e.map((t) => t.peakT), [e]), P = s(() => e.map((t) => t.peakG), [e]), v = s(() => e.map((t) => t.peakC), [e]), q = s(
30
39
  () => ({
31
- x: s,
32
- y: k,
40
+ x: n,
41
+ y: T,
33
42
  type: "scatter",
34
43
  mode: "lines",
44
+ hoverinfo: "none",
35
45
  name: "A",
36
46
  line: { color: h, width: 2, shape: "spline" }
37
47
  }),
38
- [s, k, h]
39
- ), q = n(
48
+ [n, T, h]
49
+ ), w = s(
40
50
  () => ({
41
- x: s,
42
- y: P,
51
+ x: n,
52
+ y: k,
43
53
  type: "scatter",
44
54
  mode: "lines",
55
+ hoverinfo: "none",
45
56
  name: "T",
46
57
  line: { color: u, width: 2, shape: "spline" }
47
58
  }),
48
- [s, P, u]
49
- ), v = n(
59
+ [n, k, u]
60
+ ), A = s(
50
61
  () => ({
51
- x: s,
52
- y: T,
62
+ x: n,
63
+ y: P,
53
64
  type: "scatter",
54
65
  mode: "lines",
66
+ hoverinfo: "none",
55
67
  name: "G",
56
- line: { color: i, width: 2, shape: "spline" }
68
+ line: { color: a, width: 2, shape: "spline" }
57
69
  }),
58
- [s, T, i]
59
- ), w = n(
70
+ [n, P, a]
71
+ ), E = s(
60
72
  () => ({
61
- x: s,
62
- y: C,
73
+ x: n,
74
+ y: v,
63
75
  type: "scatter",
64
76
  mode: "lines",
77
+ hoverinfo: "none",
65
78
  name: "C",
66
79
  line: { color: f, width: 2, shape: "spline" }
67
80
  }),
68
- [s, C, f]
69
- ), A = n(
70
- () => Math.max(...k, ...P, ...T, ...C),
71
- [k, P, T, C]
81
+ [n, v, f]
82
+ ), _ = s(
83
+ () => Math.max(...T, ...k, ...P, ...v),
84
+ [T, k, P, v]
72
85
  );
73
- return O(() => {
74
- if (!x.current || e.length === 0) return;
75
- const t = [b, q, v, w], N = {
86
+ return $(() => {
87
+ if (!g.current || e.length === 0) return;
88
+ const t = [q, w, A, E], N = {
76
89
  width: r,
77
- height: m - $,
90
+ height: m - I,
78
91
  margin: { l: 0, r: 0, b: 20, t: 10, pad: 0 },
79
92
  paper_bgcolor: y.paperBg,
80
93
  plot_bgcolor: y.plotBg,
@@ -87,7 +100,7 @@ const $ = 75, L = 1.05, R = (e) => {
87
100
  zeroline: !1,
88
101
  showticklabels: !1,
89
102
  showline: !1,
90
- range: [Math.min(...s), Math.max(...s)],
103
+ range: [Math.min(...n), Math.max(...n)],
91
104
  fixedrange: !0
92
105
  },
93
106
  yaxis: {
@@ -95,54 +108,54 @@ const $ = 75, L = 1.05, R = (e) => {
95
108
  zeroline: !1,
96
109
  showticklabels: !1,
97
110
  showline: !1,
98
- range: [0, A * L],
111
+ range: [0, _ * V],
99
112
  fixedrange: !0
100
113
  }
101
- }, a = {
114
+ }, i = {
102
115
  responsive: !0,
103
116
  displayModeBar: !1,
104
117
  displaylogo: !1,
105
118
  fillFrame: !0
106
119
  };
107
- B.newPlot(x.current, t, N, a);
108
- const c = x.current;
120
+ L.newPlot(g.current, t, N, i), M(g.current);
121
+ const l = g.current;
109
122
  return () => {
110
- c && B.purge(c);
123
+ l && L.purge(l);
111
124
  };
112
- }, [e, r, m, b, q, v, w, A, s, y]), e.length === 0 ? /* @__PURE__ */ p("div", { className: "chart-container", children: "No data available" }) : /* @__PURE__ */ _("div", { className: "chromatogram-container", style: { width: r, height: m }, children: [
125
+ }, [e, r, m, q, w, A, E, _, n, y, M]), e.length === 0 ? /* @__PURE__ */ p("div", { className: "chart-container", children: "No data available" }) : /* @__PURE__ */ G("div", { className: "chromatogram-container relative", style: { width: r, height: m }, children: [
113
126
  (() => {
114
127
  const t = () => {
115
- const a = Math.min(...s), c = Math.max(...s), M = r;
116
- return /* @__PURE__ */ p("div", { className: "sequence-letters-container", children: G.map((l, g) => {
117
- const o = s[g], E = l === "A" ? h : l === "T" ? u : l === "G" ? i : l === "C" ? f : y.textColor, S = (o - a) / (c - a) * M;
128
+ const i = Math.min(...n), l = Math.max(...n), C = r;
129
+ return /* @__PURE__ */ p("div", { className: "sequence-letters-container", children: R.map((c, d) => {
130
+ const o = n[d], O = c === "A" ? h : c === "T" ? u : c === "G" ? a : c === "C" ? f : y.textColor, j = (o - i) / (l - i) * C;
118
131
  return /* @__PURE__ */ p(
119
132
  "span",
120
133
  {
121
134
  className: "sequence-letter",
122
135
  style: {
123
- left: `${S}px`,
124
- color: E
136
+ left: `${j}px`,
137
+ color: O
125
138
  },
126
- children: l
139
+ children: c
127
140
  },
128
- `base-${g}`
141
+ `base-${d}`
129
142
  );
130
143
  }) });
131
144
  }, N = () => {
132
- const a = Math.min(...s), c = Math.max(...s), M = r, l = Math.ceil(a / d) * d, g = [];
133
- for (let o = l; o <= c; o += d)
134
- g.push({
145
+ const i = Math.min(...n), l = Math.max(...n), C = r, c = Math.ceil(i / x) * x, d = [];
146
+ for (let o = c; o <= l; o += x)
147
+ d.push({
135
148
  position: o,
136
149
  label: o.toString()
137
150
  });
138
- return /* @__PURE__ */ p("div", { className: "position-numbers-container", children: g.map((o) => {
139
- const F = (o.position - a) / (c - a) * M;
151
+ return /* @__PURE__ */ p("div", { className: "position-numbers-container", children: d.map((o) => {
152
+ const S = (o.position - i) / (l - i) * C;
140
153
  return /* @__PURE__ */ p(
141
154
  "span",
142
155
  {
143
156
  className: "position-number",
144
157
  style: {
145
- left: `${F}px`
158
+ left: `${S}px`
146
159
  },
147
160
  children: o.label
148
161
  },
@@ -150,15 +163,16 @@ const $ = 75, L = 1.05, R = (e) => {
150
163
  );
151
164
  }) });
152
165
  };
153
- return /* @__PURE__ */ _("div", { className: "sequence-header", children: [
166
+ return /* @__PURE__ */ G("div", { className: "sequence-header", children: [
154
167
  t(),
155
168
  N()
156
169
  ] });
157
170
  })(),
158
- /* @__PURE__ */ p("div", { className: "chromatogram-chart", children: /* @__PURE__ */ p("div", { ref: x, style: { width: "100%", height: "100%" } }) })
171
+ /* @__PURE__ */ p("div", { className: "chromatogram-chart", children: /* @__PURE__ */ p("div", { ref: g, style: { width: "100%", height: "100%" } }) }),
172
+ B
159
173
  ] });
160
174
  };
161
175
  export {
162
- Y as Chromatogram
176
+ ee as Chromatogram
163
177
  };
164
178
  //# sourceMappingURL=Chromatogram.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Chromatogram.js","sources":["../../../../src/components/charts/Chromatogram/Chromatogram.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport \"./Chromatogram.scss\";\n\n/** Height offset for the plot area in pixels */\nconst PLOT_HEIGHT_OFFSET = 75;\n/** Scale factor for y-axis range to add padding above max value */\nconst Y_AXIS_PADDING_FACTOR = 1.05;\n\ninterface PeakData {\n position: number;\n base?: string;\n peakA: number;\n peakT: number;\n peakG: number;\n peakC: number;\n}\n\ninterface ChromatogramProps {\n data?: PeakData[];\n width?: number;\n height?: number;\n positionInterval?: number;\n colorA?: string;\n colorT?: string;\n colorG?: string;\n colorC?: string;\n}\n\nconst determineBase = (item: PeakData): string => {\n const peakValues = {\n A: item.peakA,\n T: item.peakT,\n G: item.peakG,\n C: item.peakC,\n };\n\n const values = Object.values(peakValues);\n const allEqual = values.every((val) => val === values[0]);\n\n if (allEqual) {\n return \"\";\n }\n\n let highestBase = \"\";\n let highestValue = 0;\n\n Object.entries(peakValues).forEach(([base, value]) => {\n if (value > highestValue) {\n highestBase = base;\n highestValue = value;\n }\n });\n\n return highestBase;\n};\n\nconst Chromatogram: React.FC<ChromatogramProps> = ({\n data = [],\n width = 900,\n height = 600,\n positionInterval = 10,\n colorA = \"#2D9CDB\",\n colorT = \"#A1C63C\",\n colorG = \"#FF5C64\",\n colorC = \"#FFA62E\",\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n\n const positions = useMemo(() => data.map((item) => item.position), [data]);\n const sequence = useMemo(() => data.map((item) => determineBase(item)), [data]);\n const peakA = useMemo(() => data.map((item) => item.peakA), [data]);\n const peakT = useMemo(() => data.map((item) => item.peakT), [data]);\n const peakG = useMemo(() => data.map((item) => item.peakG), [data]);\n const peakC = useMemo(() => data.map((item) => item.peakC), [data]);\n\n const aTrace = useMemo(\n () => ({\n x: positions,\n y: peakA,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n name: \"A\",\n line: { color: colorA, width: 2, shape: \"spline\" as const },\n }),\n [positions, peakA, colorA],\n );\n\n const tTrace = useMemo(\n () => ({\n x: positions,\n y: peakT,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n name: \"T\",\n line: { color: colorT, width: 2, shape: \"spline\" as const },\n }),\n [positions, peakT, colorT],\n );\n\n const gTrace = useMemo(\n () => ({\n x: positions,\n y: peakG,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n name: \"G\",\n line: { color: colorG, width: 2, shape: \"spline\" as const },\n }),\n [positions, peakG, colorG],\n );\n\n const cTrace = useMemo(\n () => ({\n x: positions,\n y: peakC,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n name: \"C\",\n line: { color: colorC, width: 2, shape: \"spline\" as const },\n }),\n [positions, peakC, colorC],\n );\n\n const maxValue = useMemo(\n () => Math.max(...peakA, ...peakT, ...peakG, ...peakC),\n [peakA, peakT, peakG, peakC],\n );\n\n useEffect(() => {\n if (!plotRef.current || data.length === 0) return;\n\n const plotData = [aTrace, tTrace, gTrace, cTrace];\n\n const layout: Partial<Plotly.Layout> = {\n width: width,\n height: height - PLOT_HEIGHT_OFFSET,\n margin: { l: 0, r: 0, b: 20, t: 10, pad: 0 },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: {\n family: \"Inter, sans-serif\",\n },\n showlegend: false,\n xaxis: {\n showgrid: false,\n zeroline: false,\n showticklabels: false,\n showline: false,\n range: [Math.min(...positions), Math.max(...positions)],\n fixedrange: true,\n },\n yaxis: {\n showgrid: false,\n zeroline: false,\n showticklabels: false,\n showline: false,\n range: [0, maxValue * Y_AXIS_PADDING_FACTOR],\n fixedrange: true,\n },\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n fillFrame: true,\n };\n\n Plotly.newPlot(plotRef.current, plotData, layout, config);\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 }, [data, width, height, aTrace, tTrace, gTrace, cTrace, maxValue, positions, theme]);\n\n if (data.length === 0) {\n return <div className=\"chart-container\">No data available</div>;\n }\n\n const renderSequence = () => {\n const renderSequenceLetters = () => {\n const minPosition = Math.min(...positions);\n const maxPosition = Math.max(...positions);\n const chartWidth = width;\n\n return (\n <div className=\"sequence-letters-container\">\n {sequence.map((base, index) => {\n const position = positions[index];\n const color =\n base === \"A\"\n ? colorA\n : base === \"T\"\n ? colorT\n : base === \"G\"\n ? colorG\n : base === \"C\"\n ? colorC\n : theme.textColor;\n\n const percentage =\n (position - minPosition) / (maxPosition - minPosition);\n const leftPosition = percentage * chartWidth;\n\n return (\n <span\n key={`base-${index}`}\n className=\"sequence-letter\"\n style={{\n left: `${leftPosition}px`,\n color,\n }}\n >\n {base}\n </span>\n );\n })}\n </div>\n );\n };\n\n const renderPositionNumbers = () => {\n const minPosition = Math.min(...positions);\n const maxPosition = Math.max(...positions);\n const chartWidth = width;\n\n const startPos =\n Math.ceil(minPosition / positionInterval) * positionInterval;\n\n const regularPositionLabels: Array<{ position: number; label: string }> =\n [];\n\n for (let pos = startPos; pos <= maxPosition; pos += positionInterval) {\n regularPositionLabels.push({\n position: pos,\n label: pos.toString(),\n });\n }\n\n return (\n <div className=\"position-numbers-container\">\n {regularPositionLabels.map((label) => {\n const percentage =\n (label.position - minPosition) / (maxPosition - minPosition);\n const leftPosition = percentage * chartWidth;\n\n return (\n <span\n key={`pos-${label.position}`}\n className=\"position-number\"\n style={{\n left: `${leftPosition}px`,\n }}\n >\n {label.label}\n </span>\n );\n })}\n </div>\n );\n };\n\n return (\n <div className=\"sequence-header\">\n {renderSequenceLetters()}\n {renderPositionNumbers()}\n </div>\n );\n };\n\n return (\n <div className=\"chromatogram-container\" style={{ width, height }}>\n {renderSequence()}\n <div className=\"chromatogram-chart\">\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n </div>\n </div>\n );\n};\n\nexport { Chromatogram };\nexport type { PeakData, ChromatogramProps };\n"],"names":["PLOT_HEIGHT_OFFSET","Y_AXIS_PADDING_FACTOR","determineBase","item","peakValues","values","val","highestBase","highestValue","base","value","Chromatogram","data","width","height","positionInterval","colorA","colorT","colorG","colorC","plotRef","useRef","theme","usePlotlyTheme","positions","useMemo","sequence","peakA","peakT","peakG","peakC","aTrace","tTrace","gTrace","cTrace","maxValue","useEffect","plotData","layout","config","Plotly","plotElement","jsx","jsxs","renderSequenceLetters","minPosition","maxPosition","chartWidth","index","position","color","leftPosition","renderPositionNumbers","startPos","regularPositionLabels","pos","label"],"mappings":"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"}
1
+ {"version":3,"file":"Chromatogram.js","sources":["../../../../src/components/charts/Chromatogram/Chromatogram.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\";\nimport \"./Chromatogram.scss\";\n\n/** Height offset for the plot area in pixels */\nconst PLOT_HEIGHT_OFFSET = 75;\n/** Scale factor for y-axis range to add padding above max value */\nconst Y_AXIS_PADDING_FACTOR = 1.05;\n\ninterface PeakData {\n position: number;\n base?: string;\n peakA: number;\n peakT: number;\n peakG: number;\n peakC: number;\n}\n\ninterface ChromatogramProps {\n data?: PeakData[];\n width?: number;\n height?: number;\n positionInterval?: number;\n colorA?: string;\n colorT?: string;\n colorG?: string;\n colorC?: string;\n}\n\nconst determineBase = (item: PeakData): string => {\n const peakValues = {\n A: item.peakA,\n T: item.peakT,\n G: item.peakG,\n C: item.peakC,\n };\n\n const values = Object.values(peakValues);\n const allEqual = values.every((val) => val === values[0]);\n\n if (allEqual) {\n return \"\";\n }\n\n let highestBase = \"\";\n let highestValue = 0;\n\n Object.entries(peakValues).forEach(([base, value]) => {\n if (value > highestValue) {\n highestBase = base;\n highestValue = value;\n }\n });\n\n return highestBase;\n};\n\nconst Chromatogram: React.FC<ChromatogramProps> = ({\n data = [],\n width = 900,\n height = 600,\n positionInterval = 10,\n colorA = CHART_COLORS[0], // blue\n colorT = CHART_COLORS[2], // teal/green\n colorG = CHART_COLORS[3], // red\n colorC = CHART_COLORS[1], // orange\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const { bindTooltip, tooltipElement } = useChartTooltip({\n xLabel: \"Position\",\n yLabel: \"Intensity\",\n });\n\n const positions = useMemo(() => data.map((item) => item.position), [data]);\n const sequence = useMemo(() => data.map((item) => determineBase(item)), [data]);\n const peakA = useMemo(() => data.map((item) => item.peakA), [data]);\n const peakT = useMemo(() => data.map((item) => item.peakT), [data]);\n const peakG = useMemo(() => data.map((item) => item.peakG), [data]);\n const peakC = useMemo(() => data.map((item) => item.peakC), [data]);\n\n const aTrace = useMemo(\n () => ({\n x: positions,\n y: peakA,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n hoverinfo: \"none\" as const,\n name: \"A\",\n line: { color: colorA, width: 2, shape: \"spline\" as const },\n }),\n [positions, peakA, colorA],\n );\n\n const tTrace = useMemo(\n () => ({\n x: positions,\n y: peakT,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n hoverinfo: \"none\" as const,\n name: \"T\",\n line: { color: colorT, width: 2, shape: \"spline\" as const },\n }),\n [positions, peakT, colorT],\n );\n\n const gTrace = useMemo(\n () => ({\n x: positions,\n y: peakG,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n hoverinfo: \"none\" as const,\n name: \"G\",\n line: { color: colorG, width: 2, shape: \"spline\" as const },\n }),\n [positions, peakG, colorG],\n );\n\n const cTrace = useMemo(\n () => ({\n x: positions,\n y: peakC,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n hoverinfo: \"none\" as const,\n name: \"C\",\n line: { color: colorC, width: 2, shape: \"spline\" as const },\n }),\n [positions, peakC, colorC],\n );\n\n const maxValue = useMemo(\n () => Math.max(...peakA, ...peakT, ...peakG, ...peakC),\n [peakA, peakT, peakG, peakC],\n );\n\n useEffect(() => {\n if (!plotRef.current || data.length === 0) return;\n\n const plotData = [aTrace, tTrace, gTrace, cTrace];\n\n const layout: Partial<Plotly.Layout> = {\n width: width,\n height: height - PLOT_HEIGHT_OFFSET,\n margin: { l: 0, r: 0, b: 20, t: 10, pad: 0 },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: {\n family: \"Inter, sans-serif\",\n },\n showlegend: false,\n xaxis: {\n showgrid: false,\n zeroline: false,\n showticklabels: false,\n showline: false,\n range: [Math.min(...positions), Math.max(...positions)],\n fixedrange: true,\n },\n yaxis: {\n showgrid: false,\n zeroline: false,\n showticklabels: false,\n showline: false,\n range: [0, maxValue * Y_AXIS_PADDING_FACTOR],\n fixedrange: true,\n },\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n fillFrame: true,\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 }, [data, width, height, aTrace, tTrace, gTrace, cTrace, maxValue, positions, theme, bindTooltip]);\n\n if (data.length === 0) {\n return <div className=\"chart-container\">No data available</div>;\n }\n\n const renderSequence = () => {\n const renderSequenceLetters = () => {\n const minPosition = Math.min(...positions);\n const maxPosition = Math.max(...positions);\n const chartWidth = width;\n\n return (\n <div className=\"sequence-letters-container\">\n {sequence.map((base, index) => {\n const position = positions[index];\n const color =\n base === \"A\"\n ? colorA\n : base === \"T\"\n ? colorT\n : base === \"G\"\n ? colorG\n : base === \"C\"\n ? colorC\n : theme.textColor;\n\n const percentage =\n (position - minPosition) / (maxPosition - minPosition);\n const leftPosition = percentage * chartWidth;\n\n return (\n <span\n key={`base-${index}`}\n className=\"sequence-letter\"\n style={{\n left: `${leftPosition}px`,\n color,\n }}\n >\n {base}\n </span>\n );\n })}\n </div>\n );\n };\n\n const renderPositionNumbers = () => {\n const minPosition = Math.min(...positions);\n const maxPosition = Math.max(...positions);\n const chartWidth = width;\n\n const startPos =\n Math.ceil(minPosition / positionInterval) * positionInterval;\n\n const regularPositionLabels: Array<{ position: number; label: string }> =\n [];\n\n for (let pos = startPos; pos <= maxPosition; pos += positionInterval) {\n regularPositionLabels.push({\n position: pos,\n label: pos.toString(),\n });\n }\n\n return (\n <div className=\"position-numbers-container\">\n {regularPositionLabels.map((label) => {\n const percentage =\n (label.position - minPosition) / (maxPosition - minPosition);\n const leftPosition = percentage * chartWidth;\n\n return (\n <span\n key={`pos-${label.position}`}\n className=\"position-number\"\n style={{\n left: `${leftPosition}px`,\n }}\n >\n {label.label}\n </span>\n );\n })}\n </div>\n );\n };\n\n return (\n <div className=\"sequence-header\">\n {renderSequenceLetters()}\n {renderPositionNumbers()}\n </div>\n );\n };\n\n return (\n <div className=\"chromatogram-container relative\" style={{ width, height }}>\n {renderSequence()}\n <div className=\"chromatogram-chart\">\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n </div>\n {tooltipElement}\n </div>\n );\n};\n\nexport { Chromatogram };\nexport type { PeakData, ChromatogramProps };\n"],"names":["PLOT_HEIGHT_OFFSET","Y_AXIS_PADDING_FACTOR","determineBase","item","peakValues","values","val","highestBase","highestValue","base","value","Chromatogram","data","width","height","positionInterval","colorA","CHART_COLORS","colorT","colorG","colorC","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","positions","useMemo","sequence","peakA","peakT","peakG","peakC","aTrace","tTrace","gTrace","cTrace","maxValue","useEffect","plotData","layout","config","Plotly","plotElement","jsx","jsxs","renderSequenceLetters","minPosition","maxPosition","chartWidth","index","position","color","leftPosition","renderPositionNumbers","startPos","regularPositionLabels","pos","label"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("react/jsx-runtime"),Y=require("plotly.js-dist"),u=require("react"),j=require("../../../utils/colors.cjs"),D=require("./annotations.cjs"),K=require("./boundaryMarkers.cjs"),s=require("./constants.cjs"),f=require("./dataProcessing.cjs"),Q=require("./peakDetection.cjs"),V=require("../../../hooks/use-plotly-theme.cjs"),Z=({series:a,width:A=900,height:T=500,title:d,xAxisTitle:R="Retention Time (min)",yAxisTitle:k="Signal (mAU)",annotations:m=[],xRange:M,yRange:O,showLegend:P=!0,showGridX:v=!0,showGridY:G=!0,showMarkers:C=!1,markerSize:H=4,showCrosshairs:p=!1,baselineCorrection:q="none",baselineWindowSize:L=50,peakDetectionOptions:l,showPeakAreas:b=!1,boundaryMarkers:z="none",annotationOverlapThreshold:B=.4,showExportButton:x=!0})=>{const g=l!==void 0,N=u.useRef(null),e=V.usePlotlyTheme(),n=u.useMemo(()=>a.map(t=>{const r=f.validateSeriesData(t.x,t.y);return{...t,x:r.x,y:f.applyBaselineCorrection(r.y,q,L)}}),[a,q,L]),I=u.useMemo(()=>{if(m.length===0||n.length===0)return m;const{x:t,y:r}=n[0];return f.processUserAnnotations(m,t,r)},[m,n]),_=u.useMemo(()=>{const t=[];return g&&l&&n.forEach((r,c)=>{const y=Q.detectPeaks(r.x,r.y,l);y.length>0&&t.push({peaks:y,seriesIndex:c})}),t},[n,g,l]);return u.useEffect(()=>{const t=N.current;if(!t||a.length===0)return;const r=n.map((o,i)=>{const h=o.color||j.CHART_COLORS[i%j.CHART_COLORS.length],J=f.buildHoverExtraContent(o.name,o.metadata),E={x:o.x,y:o.y,type:"scatter",mode:C?"lines+markers":"lines",name:o.name,line:{color:h,width:1.5},hovertemplate:`%{x:.2f} ${R}<br>%{y:.2f} ${k}<extra>${J}</extra>`};return C&&(E.marker={size:H,color:h}),E});if(z!=="none"){const o=f.collectPeaksWithBoundaryData(_,I,n);if(o.length>0){const i=K.createBoundaryMarkerTraces(o);r.push(...i)}}const c=[];I.forEach(o=>{c.push({peak:o,seriesIndex:-1})}),b&&g&&_.forEach(({peaks:o,seriesIndex:i})=>{o.forEach(h=>{c.push({peak:h,seriesIndex:i})})});const y=D.groupOverlappingPeaks(c,B),U=[];for(const o of y)U.push(...D.createGroupAnnotations(o));const W={title:d?{text:d,font:{size:20,family:"Inter, sans-serif",color:e.textColor}}:void 0,width:A,height:T,margin:{l:s.CHROMATOGRAM_LAYOUT.MARGIN_LEFT,r:s.CHROMATOGRAM_LAYOUT.MARGIN_RIGHT,b:s.CHROMATOGRAM_LAYOUT.MARGIN_BOTTOM,t:d?s.CHROMATOGRAM_LAYOUT.MARGIN_TOP_WITH_TITLE:s.CHROMATOGRAM_LAYOUT.MARGIN_TOP_NO_TITLE,pad:s.CHROMATOGRAM_LAYOUT.MARGIN_PAD},paper_bgcolor:e.paperBg,plot_bgcolor:e.plotBg,font:{family:"Inter, sans-serif"},hovermode:p?"x":"x unified",dragmode:"zoom",xaxis:{title:{text:R,font:{size:14,color:e.textSecondary,family:"Inter, sans-serif"},standoff:15},showgrid:v,gridcolor:e.gridColor,linecolor:e.lineColor,linewidth:1,range:M,autorange:!M,zeroline:!1,tickfont:{size:12,color:e.textColor,family:"Inter, sans-serif"},showspikes:p,spikemode:"across",spikesnap:"cursor",spikecolor:e.spikeColor,spikethickness:1,spikedash:"dot"},yaxis:{title:{text:k,font:{size:14,color:e.textSecondary,family:"Inter, sans-serif"},standoff:10},showgrid:G,gridcolor:e.gridColor,linecolor:e.lineColor,linewidth:1,range:O,autorange:!O,zeroline:!1,tickfont:{size:12,color:e.textColor,family:"Inter, sans-serif"},showspikes:p,spikemode:"across",spikesnap:"cursor",spikecolor:e.spikeColor,spikethickness:1,spikedash:"dot"},legend:{x:.5,y:-.15,xanchor:"center",yanchor:"top",orientation:"h",font:{size:12,color:e.textColor,family:"Inter, sans-serif"}},showlegend:P&&a.length>1,annotations:U},F={responsive:!0,displayModeBar:!0,displaylogo:!1,modeBarButtonsToRemove:["lasso2d","select2d",...x?[]:["toImage"]],...x&&{toImageButtonOptions:{format:"png",filename:"chromatogram",width:A,height:T}}};return Y.newPlot(t,r,W,F),()=>{t&&Y.purge(t)}},[n,_,a.length,A,T,d,R,k,I,M,O,P,v,G,C,H,p,g,l,b,z,B,x,e]),S.jsx("div",{className:"chromatogram-chart-container",children:S.jsx("div",{ref:N,style:{width:"100%",height:"100%"}})})};exports.ChromatogramChart=Z;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Y=require("react/jsx-runtime"),j=require("plotly.js-dist"),u=require("react"),K=require("../../../utils/colors.cjs"),Q=require("../ChartTooltip/ChartTooltip.cjs"),D=require("./annotations.cjs"),V=require("./boundaryMarkers.cjs"),s=require("./constants.cjs"),T=require("./dataProcessing.cjs"),Z=require("./peakDetection.cjs"),X=require("../../../hooks/use-plotly-theme.cjs"),w=[],$=({series:a,width:h=900,height:A=500,title:f,xAxisTitle:M="Retention Time (min)",yAxisTitle:k="Signal (mAU)",annotations:d=w,xRange:O,yRange:I,showLegend:P=!0,showGridX:v=!0,showGridY:G=!0,showMarkers:R=!1,markerSize:q=4,showCrosshairs:p=!1,baselineCorrection:N="none",baselineWindowSize:L=50,peakDetectionOptions:l,showPeakAreas:b=!1,boundaryMarkers:z="none",annotationOverlapThreshold:B=.4,showExportButton:C=!0})=>{const m=l!==void 0,E=u.useRef(null),e=X.usePlotlyTheme(),{bindTooltip:H,tooltipElement:W}=Q.useChartTooltip({xLabel:M,yLabel:k}),n=u.useMemo(()=>a.map(o=>{const r=T.validateSeriesData(o.x,o.y);return{...o,x:r.x,y:T.applyBaselineCorrection(r.y,N,L)}}),[a,N,L]),x=u.useMemo(()=>{if(d.length===0||n.length===0)return d;const{x:o,y:r}=n[0];return T.processUserAnnotations(d,o,r)},[d,n]),_=u.useMemo(()=>{const o=[];return m&&l&&n.forEach((r,c)=>{const g=Z.detectPeaks(r.x,r.y,l);g.length>0&&o.push({peaks:g,seriesIndex:c})}),o},[n,m,l]);return u.useEffect(()=>{const o=E.current;if(!o||a.length===0)return;const r=n.map((t,i)=>{const y=K.seriesColor(i,t.color),S={x:t.x,y:t.y,type:"scatter",mode:R?"lines+markers":"lines",name:t.name,line:{color:y,width:1.5},hoverinfo:"none"};return R&&(S.marker={size:q,color:y}),S});if(z!=="none"){const t=T.collectPeaksWithBoundaryData(_,x,n);if(t.length>0){const i=V.createBoundaryMarkerTraces(t);r.push(...i)}}const c=[];x.forEach(t=>{c.push({peak:t,seriesIndex:-1})}),b&&m&&_.forEach(({peaks:t,seriesIndex:i})=>{t.forEach(y=>{c.push({peak:y,seriesIndex:i})})});const g=D.groupOverlappingPeaks(c,B),U=[];for(const t of g)U.push(...D.createGroupAnnotations(t));const F={title:f?{text:f,font:{size:20,family:"Inter, sans-serif",color:e.textColor}}:void 0,width:h,height:A,margin:{l:s.CHROMATOGRAM_LAYOUT.MARGIN_LEFT,r:s.CHROMATOGRAM_LAYOUT.MARGIN_RIGHT,b:s.CHROMATOGRAM_LAYOUT.MARGIN_BOTTOM,t:f?s.CHROMATOGRAM_LAYOUT.MARGIN_TOP_WITH_TITLE:s.CHROMATOGRAM_LAYOUT.MARGIN_TOP_NO_TITLE,pad:s.CHROMATOGRAM_LAYOUT.MARGIN_PAD},paper_bgcolor:e.paperBg,plot_bgcolor:e.plotBg,font:{family:"Inter, sans-serif"},hovermode:p?"x":"x unified",dragmode:"zoom",xaxis:{title:{text:M,font:{size:14,color:e.textSecondary,family:"Inter, sans-serif"},standoff:15},showgrid:v,gridcolor:e.gridColor,linecolor:e.lineColor,linewidth:1,range:O,autorange:!O,zeroline:!1,tickfont:{size:12,color:e.textColor,family:"Inter, sans-serif"},showspikes:p,spikemode:"across",spikesnap:"cursor",spikecolor:e.spikeColor,spikethickness:1,spikedash:"dot"},yaxis:{title:{text:k,font:{size:14,color:e.textSecondary,family:"Inter, sans-serif"},standoff:10},showgrid:G,gridcolor:e.gridColor,linecolor:e.lineColor,linewidth:1,range:I,autorange:!I,zeroline:!1,tickfont:{size:12,color:e.textColor,family:"Inter, sans-serif"},showspikes:p,spikemode:"across",spikesnap:"cursor",spikecolor:e.spikeColor,spikethickness:1,spikedash:"dot"},legend:{x:.5,y:-.15,xanchor:"center",yanchor:"top",orientation:"h",font:{size:12,color:e.textColor,family:"Inter, sans-serif"}},showlegend:P&&a.length>1,annotations:U},J={responsive:!0,displayModeBar:!0,displaylogo:!1,modeBarButtonsToRemove:["lasso2d","select2d",...C?[]:["toImage"]],...C&&{toImageButtonOptions:{format:"png",filename:"chromatogram",width:h,height:A}}};return j.newPlot(o,r,F,J),H(o),()=>{o&&j.purge(o)}},[n,_,a.length,h,A,f,M,k,x,O,I,P,v,G,R,q,p,m,l,b,z,B,C,e,H]),Y.jsxs("div",{className:"chromatogram-chart-container relative",children:[Y.jsx("div",{ref:E,style:{width:"100%",height:"100%"}}),W]})};exports.ChromatogramChart=$;
2
2
  //# sourceMappingURL=ChromatogramChart.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChromatogramChart.cjs","sources":["../../../../src/components/charts/ChromatogramChart/ChromatogramChart.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useMemo, useRef } from \"react\";\n\nimport { CHART_COLORS } from \"../../../utils/colors\";\n\n\nimport {\n groupOverlappingPeaks,\n createGroupAnnotations,\n} from \"./annotations\";\nimport { createBoundaryMarkerTraces } from \"./boundaryMarkers\";\nimport { CHROMATOGRAM_LAYOUT } from \"./constants\";\nimport {\n validateSeriesData,\n applyBaselineCorrection,\n buildHoverExtraContent,\n collectPeaksWithBoundaryData,\n processUserAnnotations,\n} from \"./dataProcessing\";\nimport { detectPeaks } from \"./peakDetection\";\n\nimport type {\n ChromatogramSeries,\n PeakAnnotation,\n BaselineCorrectionMethod,\n BoundaryMarkerStyle,\n BoundaryMarkerType,\n PeakDetectionOptions,\n ChromatogramChartProps,\n PeakWithMeta,\n} from \"./types\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\n\n// Re-export types for external use\nexport type {\n ChromatogramSeries,\n PeakAnnotation,\n BaselineCorrectionMethod,\n BoundaryMarkerStyle,\n BoundaryMarkerType,\n PeakDetectionOptions,\n ChromatogramChartProps,\n};\n\n\nconst ChromatogramChart: React.FC<ChromatogramChartProps> = ({\n series,\n width = 900,\n height = 500,\n title,\n xAxisTitle = \"Retention Time (min)\",\n yAxisTitle = \"Signal (mAU)\",\n annotations = [],\n xRange,\n yRange,\n showLegend = true,\n showGridX = true,\n showGridY = true,\n showMarkers = false,\n markerSize = 4,\n showCrosshairs = false,\n baselineCorrection = \"none\",\n baselineWindowSize = 50,\n peakDetectionOptions,\n showPeakAreas = false,\n boundaryMarkers = \"none\",\n annotationOverlapThreshold = 0.4,\n showExportButton = true,\n}) => {\n // Derive peak detection state from options\n const enablePeakDetection = peakDetectionOptions !== undefined;\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n\n // Memoize processed series with baseline correction\n const processedSeries = useMemo(() => {\n return series.map((s) => {\n const validated = validateSeriesData(s.x, s.y);\n return {\n ...s,\n x: validated.x,\n y: applyBaselineCorrection(validated.y, baselineCorrection, baselineWindowSize),\n };\n });\n }, [series, baselineCorrection, baselineWindowSize]);\n\n // Process user annotations to convert startX/endX to indices and compute areas\n const processedAnnotations = useMemo(() => {\n if (annotations.length === 0 || processedSeries.length === 0) {\n return annotations;\n }\n // Use first series data for index lookup (user annotations apply to first series)\n const { x, y } = processedSeries[0];\n return processUserAnnotations(annotations, x, y);\n }, [annotations, processedSeries]);\n\n // Memoize peak detection results\n const allDetectedPeaks = useMemo(() => {\n const peaks: { peaks: PeakAnnotation[]; seriesIndex: number }[] = [];\n if (enablePeakDetection && peakDetectionOptions) {\n processedSeries.forEach((s, index) => {\n const detected = detectPeaks(s.x, s.y, peakDetectionOptions);\n if (detected.length > 0) {\n peaks.push({ peaks: detected, seriesIndex: index });\n }\n });\n }\n return peaks;\n }, [processedSeries, enablePeakDetection, peakDetectionOptions]);\n\n useEffect(() => {\n const currentRef = plotRef.current;\n if (!currentRef || series.length === 0) return;\n\n // Build trace data with auto-assigned colors\n const plotData: Plotly.Data[] = processedSeries.map((s, index) => {\n const traceColor = s.color || CHART_COLORS[index % CHART_COLORS.length];\n const extraContent = buildHoverExtraContent(s.name, s.metadata);\n\n const trace: Plotly.Data = {\n x: s.x,\n y: s.y,\n type: \"scatter\" as const,\n mode: showMarkers ? \"lines+markers\" as const : \"lines\" as const,\n name: s.name,\n line: {\n color: traceColor,\n width: 1.5,\n },\n hovertemplate: `%{x:.2f} ${xAxisTitle}<br>%{y:.2f} ${yAxisTitle}<extra>${extraContent}</extra>`,\n };\n if (showMarkers) {\n trace.marker = {\n size: markerSize,\n color: traceColor,\n };\n }\n return trace;\n });\n\n // Add peak boundary markers if enabled\n if (boundaryMarkers !== \"none\") {\n const peaksWithData = collectPeaksWithBoundaryData(allDetectedPeaks, processedAnnotations, processedSeries);\n if (peaksWithData.length > 0) {\n const boundaryTraces = createBoundaryMarkerTraces(peaksWithData);\n plotData.push(...boundaryTraces);\n }\n }\n\n // Collect all peaks for unified staggering logic\n const allPeaksWithMeta: PeakWithMeta[] = [];\n\n // Add user-defined annotations (seriesIndex -1 indicates user-defined)\n processedAnnotations.forEach((ann) => {\n allPeaksWithMeta.push({ peak: ann, seriesIndex: -1 });\n });\n\n // Add auto-detected peaks if enabled\n if (showPeakAreas && enablePeakDetection) {\n allDetectedPeaks.forEach(({ peaks, seriesIndex }) => {\n peaks.forEach((peak) => {\n allPeaksWithMeta.push({ peak, seriesIndex });\n });\n });\n }\n\n // Group all overlapping peaks and create annotations with staggering\n const groups = groupOverlappingPeaks(allPeaksWithMeta, annotationOverlapThreshold);\n const plotlyAnnotations: Partial<Plotly.Annotations>[] = [];\n\n for (const group of groups) {\n plotlyAnnotations.push(...createGroupAnnotations(group));\n }\n\n const layout: Partial<Plotly.Layout> = {\n title: title\n ? {\n text: title,\n font: {\n size: 20,\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n },\n }\n : undefined,\n width,\n height,\n margin: {\n l: CHROMATOGRAM_LAYOUT.MARGIN_LEFT,\n r: CHROMATOGRAM_LAYOUT.MARGIN_RIGHT,\n b: CHROMATOGRAM_LAYOUT.MARGIN_BOTTOM,\n t: title ? CHROMATOGRAM_LAYOUT.MARGIN_TOP_WITH_TITLE : CHROMATOGRAM_LAYOUT.MARGIN_TOP_NO_TITLE,\n pad: CHROMATOGRAM_LAYOUT.MARGIN_PAD,\n },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: { family: \"Inter, sans-serif\" },\n hovermode: showCrosshairs ? \"x\" as const : \"x unified\" as const,\n dragmode: \"zoom\" as const,\n xaxis: {\n title: {\n text: xAxisTitle,\n font: { size: 14, color: theme.textSecondary, family: \"Inter, sans-serif\" },\n standoff: 15,\n },\n showgrid: showGridX,\n gridcolor: theme.gridColor,\n linecolor: theme.lineColor,\n linewidth: 1,\n range: xRange,\n autorange: !xRange,\n zeroline: false,\n tickfont: { size: 12, color: theme.textColor, family: \"Inter, sans-serif\" },\n showspikes: showCrosshairs,\n spikemode: \"across\" as const,\n spikesnap: \"cursor\" as const,\n spikecolor: theme.spikeColor,\n spikethickness: 1,\n spikedash: \"dot\" as const,\n },\n yaxis: {\n title: {\n text: yAxisTitle,\n font: { size: 14, color: theme.textSecondary, family: \"Inter, sans-serif\" },\n standoff: 10,\n },\n showgrid: showGridY,\n gridcolor: theme.gridColor,\n linecolor: theme.lineColor,\n linewidth: 1,\n range: yRange,\n autorange: !yRange,\n zeroline: false,\n tickfont: { size: 12, color: theme.textColor, family: \"Inter, sans-serif\" },\n showspikes: showCrosshairs,\n spikemode: \"across\" as const,\n spikesnap: \"cursor\" as const,\n spikecolor: theme.spikeColor,\n spikethickness: 1,\n spikedash: \"dot\" as const,\n },\n legend: {\n x: 0.5,\n y: -0.15,\n xanchor: \"center\" as const,\n yanchor: \"top\" as const,\n orientation: \"h\" as const,\n font: { size: 12, color: theme.textColor, family: \"Inter, sans-serif\" },\n },\n showlegend: showLegend && series.length > 1,\n annotations: plotlyAnnotations,\n };\n\n const config: Partial<Plotly.Config> = {\n responsive: true,\n displayModeBar: true,\n displaylogo: false,\n modeBarButtonsToRemove: [\n \"lasso2d\",\n \"select2d\",\n ...(showExportButton ? [] : [\"toImage\"] as Plotly.ModeBarDefaultButtons[]),\n ] as Plotly.ModeBarDefaultButtons[],\n ...(showExportButton && {\n toImageButtonOptions: {\n format: \"png\",\n filename: \"chromatogram\",\n width: width,\n height: height,\n },\n }),\n };\n\n Plotly.newPlot(currentRef, plotData, layout, config);\n\n return () => {\n if (currentRef) {\n Plotly.purge(currentRef);\n }\n };\n }, [\n processedSeries, allDetectedPeaks, series.length, width, height, title, xAxisTitle, yAxisTitle,\n processedAnnotations, xRange, yRange, showLegend, showGridX, showGridY, showMarkers, markerSize,\n showCrosshairs, enablePeakDetection, peakDetectionOptions, showPeakAreas, boundaryMarkers,\n annotationOverlapThreshold, showExportButton, theme,\n ]);\n\n return (\n <div className=\"chromatogram-chart-container\">\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n </div>\n );\n};\n\nexport { ChromatogramChart };\n\n"],"names":["ChromatogramChart","series","width","height","title","xAxisTitle","yAxisTitle","annotations","xRange","yRange","showLegend","showGridX","showGridY","showMarkers","markerSize","showCrosshairs","baselineCorrection","baselineWindowSize","peakDetectionOptions","showPeakAreas","boundaryMarkers","annotationOverlapThreshold","showExportButton","enablePeakDetection","plotRef","useRef","theme","usePlotlyTheme","processedSeries","useMemo","s","validated","validateSeriesData","applyBaselineCorrection","processedAnnotations","x","y","processUserAnnotations","allDetectedPeaks","peaks","index","detected","detectPeaks","useEffect","currentRef","plotData","traceColor","CHART_COLORS","extraContent","buildHoverExtraContent","trace","peaksWithData","collectPeaksWithBoundaryData","boundaryTraces","createBoundaryMarkerTraces","allPeaksWithMeta","ann","seriesIndex","peak","groups","groupOverlappingPeaks","plotlyAnnotations","group","createGroupAnnotations","layout","CHROMATOGRAM_LAYOUT","config","Plotly","jsx"],"mappings":"8ZA8CMA,EAAsD,CAAC,CAC3D,OAAAC,EACA,MAAAC,EAAQ,IACR,OAAAC,EAAS,IACT,MAAAC,EACA,WAAAC,EAAa,uBACb,WAAAC,EAAa,eAAA,YACbC,EAAc,CAAA,EACd,OAAAC,EACA,OAAAC,EACA,WAAAC,EAAa,GACb,UAAAC,EAAY,GACZ,UAAAC,EAAY,GACZ,YAAAC,EAAc,GACd,WAAAC,EAAa,EACb,eAAAC,EAAiB,GACjB,mBAAAC,EAAqB,OACrB,mBAAAC,EAAqB,GACrB,qBAAAC,EACA,cAAAC,EAAgB,GAAA,gBAChBC,EAAkB,OAClB,2BAAAC,EAA6B,GAC7B,iBAAAC,EAAmB,EACrB,IAAM,CAEJ,MAAMC,EAAsBL,IAAyB,OAC/CM,EAAUC,EAAAA,OAAuB,IAAI,EACrCC,EAAQC,EAAAA,eAAA,EAGRC,EAAkBC,EAAAA,QAAQ,IACvB5B,EAAO,IAAK6B,GAAM,CACvB,MAAMC,EAAYC,EAAAA,mBAAmBF,EAAE,EAAGA,EAAE,CAAC,EAC7C,MAAO,CACL,GAAGA,EACH,EAAGC,EAAU,EACb,EAAGE,EAAAA,wBAAwBF,EAAU,EAAGf,EAAoBC,CAAkB,CAAA,CAElF,CAAC,EACA,CAAChB,EAAQe,EAAoBC,CAAkB,CAAC,EAG7CiB,EAAuBL,EAAAA,QAAQ,IAAM,CACzC,GAAItB,EAAY,SAAW,GAAKqB,EAAgB,SAAW,EACzD,OAAOrB,EAGT,KAAM,CAAE,EAAA4B,EAAG,EAAAC,GAAMR,EAAgB,CAAC,EAClC,OAAOS,yBAAuB9B,EAAa4B,EAAGC,CAAC,CACjD,EAAG,CAAC7B,EAAaqB,CAAe,CAAC,EAG3BU,EAAmBT,EAAAA,QAAQ,IAAM,CACrC,MAAMU,EAA4D,CAAA,EAClE,OAAIhB,GAAuBL,GACzBU,EAAgB,QAAQ,CAACE,EAAGU,IAAU,CACpC,MAAMC,EAAWC,EAAAA,YAAYZ,EAAE,EAAGA,EAAE,EAAGZ,CAAoB,EACvDuB,EAAS,OAAS,GACpBF,EAAM,KAAK,CAAE,MAAOE,EAAU,YAAaD,EAAO,CAEtD,CAAC,EAEID,CACT,EAAG,CAACX,EAAiBL,EAAqBL,CAAoB,CAAC,EAE/DyB,OAAAA,EAAAA,UAAU,IAAM,CACd,MAAMC,EAAapB,EAAQ,QAC3B,GAAI,CAACoB,GAAc3C,EAAO,SAAW,EAAG,OAGxC,MAAM4C,EAA0BjB,EAAgB,IAAI,CAACE,EAAGU,IAAU,CAChE,MAAMM,EAAahB,EAAE,OAASiB,EAAAA,aAAaP,EAAQO,EAAAA,aAAa,MAAM,EAChEC,EAAeC,EAAAA,uBAAuBnB,EAAE,KAAMA,EAAE,QAAQ,EAExDoB,EAAqB,CACzB,EAAGpB,EAAE,EACL,EAAGA,EAAE,EACL,KAAM,UACN,KAAMjB,EAAc,gBAA2B,QAC/C,KAAMiB,EAAE,KACR,KAAM,CACJ,MAAOgB,EACP,MAAO,GAAA,EAET,cAAe,YAAYzC,CAAU,gBAAgBC,CAAU,UAAU0C,CAAY,UAAA,EAEvF,OAAInC,IACFqC,EAAM,OAAS,CACb,KAAMpC,EACN,MAAOgC,CAAA,GAGJI,CACT,CAAC,EAGD,GAAI9B,IAAoB,OAAQ,CAC9B,MAAM+B,EAAgBC,EAAAA,6BAA6Bd,EAAkBJ,EAAsBN,CAAe,EAC1G,GAAIuB,EAAc,OAAS,EAAG,CAC5B,MAAME,EAAiBC,EAAAA,2BAA2BH,CAAa,EAC/DN,EAAS,KAAK,GAAGQ,CAAc,CACjC,CACF,CAGA,MAAME,EAAmC,CAAA,EAGzCrB,EAAqB,QAASsB,GAAQ,CACpCD,EAAiB,KAAK,CAAE,KAAMC,EAAK,YAAa,GAAI,CACtD,CAAC,EAGGrC,GAAiBI,GACnBe,EAAiB,QAAQ,CAAC,CAAE,MAAAC,EAAO,YAAAkB,KAAkB,CACnDlB,EAAM,QAASmB,GAAS,CACtBH,EAAiB,KAAK,CAAE,KAAAG,EAAM,YAAAD,CAAA,CAAa,CAC7C,CAAC,CACH,CAAC,EAIH,MAAME,EAASC,EAAAA,sBAAsBL,EAAkBlC,CAA0B,EAC3EwC,EAAmD,CAAA,EAEzD,UAAWC,KAASH,EAClBE,EAAkB,KAAK,GAAGE,EAAAA,uBAAuBD,CAAK,CAAC,EAGzD,MAAME,EAAiC,CACrC,MAAO5D,EACH,CACE,KAAMA,EACN,KAAM,CACJ,KAAM,GACN,OAAQ,oBACR,MAAOsB,EAAM,SAAA,CACf,EAEF,OACJ,MAAAxB,EACA,OAAAC,EACA,OAAQ,CACN,EAAG8D,EAAAA,oBAAoB,YACvB,EAAGA,EAAAA,oBAAoB,aACvB,EAAGA,EAAAA,oBAAoB,cACvB,EAAG7D,EAAQ6D,EAAAA,oBAAoB,sBAAwBA,EAAAA,oBAAoB,oBAC3E,IAAKA,EAAAA,oBAAoB,UAAA,EAE3B,cAAevC,EAAM,QACrB,aAAcA,EAAM,OACpB,KAAM,CAAE,OAAQ,mBAAA,EAChB,UAAWX,EAAiB,IAAe,YAC3C,SAAU,OACV,MAAO,CACL,MAAO,CACL,KAAMV,EACN,KAAM,CAAE,KAAM,GAAI,MAAOqB,EAAM,cAAe,OAAQ,mBAAA,EACtD,SAAU,EAAA,EAEZ,SAAUf,EACV,UAAWe,EAAM,UACjB,UAAWA,EAAM,UACjB,UAAW,EACX,MAAOlB,EACP,UAAW,CAACA,EACZ,SAAU,GACV,SAAU,CAAE,KAAM,GAAI,MAAOkB,EAAM,UAAW,OAAQ,mBAAA,EACtD,WAAYX,EACZ,UAAW,SACX,UAAW,SACX,WAAYW,EAAM,WAClB,eAAgB,EAChB,UAAW,KAAA,EAEb,MAAO,CACL,MAAO,CACL,KAAMpB,EACN,KAAM,CAAE,KAAM,GAAI,MAAOoB,EAAM,cAAe,OAAQ,mBAAA,EACtD,SAAU,EAAA,EAEZ,SAAUd,EACV,UAAWc,EAAM,UACjB,UAAWA,EAAM,UACjB,UAAW,EACX,MAAOjB,EACP,UAAW,CAACA,EACZ,SAAU,GACV,SAAU,CAAE,KAAM,GAAI,MAAOiB,EAAM,UAAW,OAAQ,mBAAA,EACtD,WAAYX,EACZ,UAAW,SACX,UAAW,SACX,WAAYW,EAAM,WAClB,eAAgB,EAChB,UAAW,KAAA,EAEb,OAAQ,CACN,EAAG,GACH,EAAG,KACH,QAAS,SACT,QAAS,MACT,YAAa,IACb,KAAM,CAAE,KAAM,GAAI,MAAOA,EAAM,UAAW,OAAQ,mBAAA,CAAoB,EAExE,WAAYhB,GAAcT,EAAO,OAAS,EAC1C,YAAa4D,CAAA,EAGTK,EAAiC,CACrC,WAAY,GACZ,eAAgB,GAChB,YAAa,GACb,uBAAwB,CACtB,UACA,WACA,GAAI5C,EAAmB,CAAA,EAAK,CAAC,SAAS,CAAA,EAExC,GAAIA,GAAoB,CACtB,qBAAsB,CACpB,OAAQ,MACR,SAAU,eACV,MAAApB,EACA,OAAAC,CAAA,CACF,CACF,EAGF,OAAAgE,EAAO,QAAQvB,EAAYC,EAAUmB,EAAQE,CAAM,EAE5C,IAAM,CACPtB,GACFuB,EAAO,MAAMvB,CAAU,CAE3B,CACF,EAAG,CACDhB,EAAiBU,EAAkBrC,EAAO,OAAQC,EAAOC,EAAQC,EAAOC,EAAYC,EACpF4B,EAAsB1B,EAAQC,EAAQC,EAAYC,EAAWC,EAAWC,EAAaC,EACrFC,EAAgBQ,EAAqBL,EAAsBC,EAAeC,EAC1EC,EAA4BC,EAAkBI,CAAA,CAC/C,EAGC0C,EAAAA,IAAC,MAAA,CAAI,UAAU,+BACb,eAAC,MAAA,CAAI,IAAK5C,EAAS,MAAO,CAAE,MAAO,OAAQ,OAAQ,MAAA,EAAU,EAC/D,CAEJ"}
1
+ {"version":3,"file":"ChromatogramChart.cjs","sources":["../../../../src/components/charts/ChromatogramChart/ChromatogramChart.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useMemo, useRef } from \"react\";\n\nimport { seriesColor } from \"../../../utils/colors\";\nimport { useChartTooltip } from \"../ChartTooltip\";\n\nimport {\n groupOverlappingPeaks,\n createGroupAnnotations,\n} from \"./annotations\";\nimport { createBoundaryMarkerTraces } from \"./boundaryMarkers\";\nimport { CHROMATOGRAM_LAYOUT } from \"./constants\";\nimport {\n validateSeriesData,\n applyBaselineCorrection,\n collectPeaksWithBoundaryData,\n processUserAnnotations,\n} from \"./dataProcessing\";\nimport { detectPeaks } from \"./peakDetection\";\n\nimport type {\n ChromatogramSeries,\n PeakAnnotation,\n BaselineCorrectionMethod,\n BoundaryMarkerStyle,\n BoundaryMarkerType,\n PeakDetectionOptions,\n ChromatogramChartProps,\n PeakWithMeta,\n} from \"./types\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\n\n// Re-export types for external use\nexport type {\n ChromatogramSeries,\n PeakAnnotation,\n BaselineCorrectionMethod,\n BoundaryMarkerStyle,\n BoundaryMarkerType,\n PeakDetectionOptions,\n ChromatogramChartProps,\n};\n\n\n// Stable default so the no-annotations case keeps a constant identity; an\n// inline `[]` default would change every render, re-running the plot effect\n// (and tearing down the hover tooltip) on each re-render.\nconst EMPTY_ANNOTATIONS: PeakAnnotation[] = [];\n\nconst ChromatogramChart: React.FC<ChromatogramChartProps> = ({\n series,\n width = 900,\n height = 500,\n title,\n xAxisTitle = \"Retention Time (min)\",\n yAxisTitle = \"Signal (mAU)\",\n annotations = EMPTY_ANNOTATIONS,\n xRange,\n yRange,\n showLegend = true,\n showGridX = true,\n showGridY = true,\n showMarkers = false,\n markerSize = 4,\n showCrosshairs = false,\n baselineCorrection = \"none\",\n baselineWindowSize = 50,\n peakDetectionOptions,\n showPeakAreas = false,\n boundaryMarkers = \"none\",\n annotationOverlapThreshold = 0.4,\n showExportButton = true,\n}) => {\n // Derive peak detection state from options\n const enablePeakDetection = peakDetectionOptions !== undefined;\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const { bindTooltip, tooltipElement } = useChartTooltip({\n xLabel: xAxisTitle,\n yLabel: yAxisTitle,\n });\n\n // Memoize processed series with baseline correction\n const processedSeries = useMemo(() => {\n return series.map((s) => {\n const validated = validateSeriesData(s.x, s.y);\n return {\n ...s,\n x: validated.x,\n y: applyBaselineCorrection(validated.y, baselineCorrection, baselineWindowSize),\n };\n });\n }, [series, baselineCorrection, baselineWindowSize]);\n\n // Process user annotations to convert startX/endX to indices and compute areas\n const processedAnnotations = useMemo(() => {\n if (annotations.length === 0 || processedSeries.length === 0) {\n return annotations;\n }\n // Use first series data for index lookup (user annotations apply to first series)\n const { x, y } = processedSeries[0];\n return processUserAnnotations(annotations, x, y);\n }, [annotations, processedSeries]);\n\n // Memoize peak detection results\n const allDetectedPeaks = useMemo(() => {\n const peaks: { peaks: PeakAnnotation[]; seriesIndex: number }[] = [];\n if (enablePeakDetection && peakDetectionOptions) {\n processedSeries.forEach((s, index) => {\n const detected = detectPeaks(s.x, s.y, peakDetectionOptions);\n if (detected.length > 0) {\n peaks.push({ peaks: detected, seriesIndex: index });\n }\n });\n }\n return peaks;\n }, [processedSeries, enablePeakDetection, peakDetectionOptions]);\n\n useEffect(() => {\n const currentRef = plotRef.current;\n if (!currentRef || series.length === 0) return;\n\n // Build trace data with auto-assigned colors\n const plotData: Plotly.Data[] = processedSeries.map((s, index) => {\n const traceColor = seriesColor(index, s.color);\n\n const trace: Plotly.Data = {\n x: s.x,\n y: s.y,\n type: \"scatter\" as const,\n mode: showMarkers ? \"lines+markers\" as const : \"lines\" as const,\n name: s.name,\n line: {\n color: traceColor,\n width: 1.5,\n },\n hoverinfo: \"none\" as const,\n };\n if (showMarkers) {\n trace.marker = {\n size: markerSize,\n color: traceColor,\n };\n }\n return trace;\n });\n\n // Add peak boundary markers if enabled\n if (boundaryMarkers !== \"none\") {\n const peaksWithData = collectPeaksWithBoundaryData(allDetectedPeaks, processedAnnotations, processedSeries);\n if (peaksWithData.length > 0) {\n const boundaryTraces = createBoundaryMarkerTraces(peaksWithData);\n plotData.push(...boundaryTraces);\n }\n }\n\n // Collect all peaks for unified staggering logic\n const allPeaksWithMeta: PeakWithMeta[] = [];\n\n // Add user-defined annotations (seriesIndex -1 indicates user-defined)\n processedAnnotations.forEach((ann) => {\n allPeaksWithMeta.push({ peak: ann, seriesIndex: -1 });\n });\n\n // Add auto-detected peaks if enabled\n if (showPeakAreas && enablePeakDetection) {\n allDetectedPeaks.forEach(({ peaks, seriesIndex }) => {\n peaks.forEach((peak) => {\n allPeaksWithMeta.push({ peak, seriesIndex });\n });\n });\n }\n\n // Group all overlapping peaks and create annotations with staggering\n const groups = groupOverlappingPeaks(allPeaksWithMeta, annotationOverlapThreshold);\n const plotlyAnnotations: Partial<Plotly.Annotations>[] = [];\n\n for (const group of groups) {\n plotlyAnnotations.push(...createGroupAnnotations(group));\n }\n\n const layout: Partial<Plotly.Layout> = {\n title: title\n ? {\n text: title,\n font: {\n size: 20,\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n },\n }\n : undefined,\n width,\n height,\n margin: {\n l: CHROMATOGRAM_LAYOUT.MARGIN_LEFT,\n r: CHROMATOGRAM_LAYOUT.MARGIN_RIGHT,\n b: CHROMATOGRAM_LAYOUT.MARGIN_BOTTOM,\n t: title ? CHROMATOGRAM_LAYOUT.MARGIN_TOP_WITH_TITLE : CHROMATOGRAM_LAYOUT.MARGIN_TOP_NO_TITLE,\n pad: CHROMATOGRAM_LAYOUT.MARGIN_PAD,\n },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: { family: \"Inter, sans-serif\" },\n hovermode: showCrosshairs ? \"x\" as const : \"x unified\" as const,\n dragmode: \"zoom\" as const,\n xaxis: {\n title: {\n text: xAxisTitle,\n font: { size: 14, color: theme.textSecondary, family: \"Inter, sans-serif\" },\n standoff: 15,\n },\n showgrid: showGridX,\n gridcolor: theme.gridColor,\n linecolor: theme.lineColor,\n linewidth: 1,\n range: xRange,\n autorange: !xRange,\n zeroline: false,\n tickfont: { size: 12, color: theme.textColor, family: \"Inter, sans-serif\" },\n showspikes: showCrosshairs,\n spikemode: \"across\" as const,\n spikesnap: \"cursor\" as const,\n spikecolor: theme.spikeColor,\n spikethickness: 1,\n spikedash: \"dot\" as const,\n },\n yaxis: {\n title: {\n text: yAxisTitle,\n font: { size: 14, color: theme.textSecondary, family: \"Inter, sans-serif\" },\n standoff: 10,\n },\n showgrid: showGridY,\n gridcolor: theme.gridColor,\n linecolor: theme.lineColor,\n linewidth: 1,\n range: yRange,\n autorange: !yRange,\n zeroline: false,\n tickfont: { size: 12, color: theme.textColor, family: \"Inter, sans-serif\" },\n showspikes: showCrosshairs,\n spikemode: \"across\" as const,\n spikesnap: \"cursor\" as const,\n spikecolor: theme.spikeColor,\n spikethickness: 1,\n spikedash: \"dot\" as const,\n },\n legend: {\n x: 0.5,\n y: -0.15,\n xanchor: \"center\" as const,\n yanchor: \"top\" as const,\n orientation: \"h\" as const,\n font: { size: 12, color: theme.textColor, family: \"Inter, sans-serif\" },\n },\n showlegend: showLegend && series.length > 1,\n annotations: plotlyAnnotations,\n };\n\n const config: Partial<Plotly.Config> = {\n responsive: true,\n displayModeBar: true,\n displaylogo: false,\n modeBarButtonsToRemove: [\n \"lasso2d\",\n \"select2d\",\n ...(showExportButton ? [] : [\"toImage\"] as Plotly.ModeBarDefaultButtons[]),\n ] as Plotly.ModeBarDefaultButtons[],\n ...(showExportButton && {\n toImageButtonOptions: {\n format: \"png\",\n filename: \"chromatogram\",\n width: width,\n height: height,\n },\n }),\n };\n\n Plotly.newPlot(currentRef, plotData, layout, config);\n bindTooltip(currentRef);\n\n return () => {\n if (currentRef) {\n Plotly.purge(currentRef);\n }\n };\n }, [\n processedSeries, allDetectedPeaks, series.length, width, height, title, xAxisTitle, yAxisTitle,\n processedAnnotations, xRange, yRange, showLegend, showGridX, showGridY, showMarkers, markerSize,\n showCrosshairs, enablePeakDetection, peakDetectionOptions, showPeakAreas, boundaryMarkers,\n annotationOverlapThreshold, showExportButton, theme, bindTooltip,\n ]);\n\n return (\n <div className=\"chromatogram-chart-container relative\">\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n {tooltipElement}\n </div>\n );\n};\n\nexport { ChromatogramChart };\n\n"],"names":["EMPTY_ANNOTATIONS","ChromatogramChart","series","width","height","title","xAxisTitle","yAxisTitle","annotations","xRange","yRange","showLegend","showGridX","showGridY","showMarkers","markerSize","showCrosshairs","baselineCorrection","baselineWindowSize","peakDetectionOptions","showPeakAreas","boundaryMarkers","annotationOverlapThreshold","showExportButton","enablePeakDetection","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","processedSeries","useMemo","s","validated","validateSeriesData","applyBaselineCorrection","processedAnnotations","x","y","processUserAnnotations","allDetectedPeaks","peaks","index","detected","detectPeaks","useEffect","currentRef","plotData","traceColor","seriesColor","trace","peaksWithData","collectPeaksWithBoundaryData","boundaryTraces","createBoundaryMarkerTraces","allPeaksWithMeta","ann","seriesIndex","peak","groups","groupOverlappingPeaks","plotlyAnnotations","group","createGroupAnnotations","layout","CHROMATOGRAM_LAYOUT","config","Plotly","jsxs","jsx"],"mappings":"4cAgDMA,EAAsC,CAAA,EAEtCC,EAAsD,CAAC,CAC3D,OAAAC,EACA,MAAAC,EAAQ,IACR,OAAAC,EAAS,IACT,MAAAC,EACA,WAAAC,EAAa,uBACb,WAAAC,EAAa,eAAA,YACbC,EAAcR,EACd,OAAAS,EACA,OAAAC,EACA,WAAAC,EAAa,GACb,UAAAC,EAAY,GACZ,UAAAC,EAAY,GACZ,YAAAC,EAAc,GACd,WAAAC,EAAa,EACb,eAAAC,EAAiB,GACjB,mBAAAC,EAAqB,OACrB,mBAAAC,EAAqB,GACrB,qBAAAC,EACA,cAAAC,EAAgB,GAAA,gBAChBC,EAAkB,OAClB,2BAAAC,EAA6B,GAC7B,iBAAAC,EAAmB,EACrB,IAAM,CAEJ,MAAMC,EAAsBL,IAAyB,OAC/CM,EAAUC,EAAAA,OAAuB,IAAI,EACrCC,EAAQC,EAAAA,eAAA,EACR,CAAE,YAAAC,EAAa,eAAAC,CAAA,EAAmBC,kBAAgB,CACtD,OAAQzB,EACR,OAAQC,CAAA,CACT,EAGKyB,EAAkBC,EAAAA,QAAQ,IACvB/B,EAAO,IAAKgC,GAAM,CACvB,MAAMC,EAAYC,EAAAA,mBAAmBF,EAAE,EAAGA,EAAE,CAAC,EAC7C,MAAO,CACL,GAAGA,EACH,EAAGC,EAAU,EACb,EAAGE,EAAAA,wBAAwBF,EAAU,EAAGlB,EAAoBC,CAAkB,CAAA,CAElF,CAAC,EACA,CAAChB,EAAQe,EAAoBC,CAAkB,CAAC,EAG7CoB,EAAuBL,EAAAA,QAAQ,IAAM,CACzC,GAAIzB,EAAY,SAAW,GAAKwB,EAAgB,SAAW,EACzD,OAAOxB,EAGT,KAAM,CAAE,EAAA+B,EAAG,EAAAC,GAAMR,EAAgB,CAAC,EAClC,OAAOS,yBAAuBjC,EAAa+B,EAAGC,CAAC,CACjD,EAAG,CAAChC,EAAawB,CAAe,CAAC,EAG3BU,EAAmBT,EAAAA,QAAQ,IAAM,CACrC,MAAMU,EAA4D,CAAA,EAClE,OAAInB,GAAuBL,GACzBa,EAAgB,QAAQ,CAACE,EAAGU,IAAU,CACpC,MAAMC,EAAWC,EAAAA,YAAYZ,EAAE,EAAGA,EAAE,EAAGf,CAAoB,EACvD0B,EAAS,OAAS,GACpBF,EAAM,KAAK,CAAE,MAAOE,EAAU,YAAaD,EAAO,CAEtD,CAAC,EAEID,CACT,EAAG,CAACX,EAAiBR,EAAqBL,CAAoB,CAAC,EAE/D4B,OAAAA,EAAAA,UAAU,IAAM,CACd,MAAMC,EAAavB,EAAQ,QAC3B,GAAI,CAACuB,GAAc9C,EAAO,SAAW,EAAG,OAGxC,MAAM+C,EAA0BjB,EAAgB,IAAI,CAACE,EAAGU,IAAU,CAChE,MAAMM,EAAaC,EAAAA,YAAYP,EAAOV,EAAE,KAAK,EAEvCkB,EAAqB,CACzB,EAAGlB,EAAE,EACL,EAAGA,EAAE,EACL,KAAM,UACN,KAAMpB,EAAc,gBAA2B,QAC/C,KAAMoB,EAAE,KACR,KAAM,CACJ,MAAOgB,EACP,MAAO,GAAA,EAET,UAAW,MAAA,EAEb,OAAIpC,IACFsC,EAAM,OAAS,CACb,KAAMrC,EACN,MAAOmC,CAAA,GAGJE,CACT,CAAC,EAGD,GAAI/B,IAAoB,OAAQ,CAC9B,MAAMgC,EAAgBC,EAAAA,6BAA6BZ,EAAkBJ,EAAsBN,CAAe,EAC1G,GAAIqB,EAAc,OAAS,EAAG,CAC5B,MAAME,EAAiBC,EAAAA,2BAA2BH,CAAa,EAC/DJ,EAAS,KAAK,GAAGM,CAAc,CACjC,CACF,CAGA,MAAME,EAAmC,CAAA,EAGzCnB,EAAqB,QAASoB,GAAQ,CACpCD,EAAiB,KAAK,CAAE,KAAMC,EAAK,YAAa,GAAI,CACtD,CAAC,EAGGtC,GAAiBI,GACnBkB,EAAiB,QAAQ,CAAC,CAAE,MAAAC,EAAO,YAAAgB,KAAkB,CACnDhB,EAAM,QAASiB,GAAS,CACtBH,EAAiB,KAAK,CAAE,KAAAG,EAAM,YAAAD,CAAA,CAAa,CAC7C,CAAC,CACH,CAAC,EAIH,MAAME,EAASC,EAAAA,sBAAsBL,EAAkBnC,CAA0B,EAC3EyC,EAAmD,CAAA,EAEzD,UAAWC,KAASH,EAClBE,EAAkB,KAAK,GAAGE,EAAAA,uBAAuBD,CAAK,CAAC,EAGzD,MAAME,EAAiC,CACrC,MAAO7D,EACH,CACE,KAAMA,EACN,KAAM,CACJ,KAAM,GACN,OAAQ,oBACR,MAAOsB,EAAM,SAAA,CACf,EAEF,OACJ,MAAAxB,EACA,OAAAC,EACA,OAAQ,CACN,EAAG+D,EAAAA,oBAAoB,YACvB,EAAGA,EAAAA,oBAAoB,aACvB,EAAGA,EAAAA,oBAAoB,cACvB,EAAG9D,EAAQ8D,EAAAA,oBAAoB,sBAAwBA,EAAAA,oBAAoB,oBAC3E,IAAKA,EAAAA,oBAAoB,UAAA,EAE3B,cAAexC,EAAM,QACrB,aAAcA,EAAM,OACpB,KAAM,CAAE,OAAQ,mBAAA,EAChB,UAAWX,EAAiB,IAAe,YAC3C,SAAU,OACV,MAAO,CACL,MAAO,CACL,KAAMV,EACN,KAAM,CAAE,KAAM,GAAI,MAAOqB,EAAM,cAAe,OAAQ,mBAAA,EACtD,SAAU,EAAA,EAEZ,SAAUf,EACV,UAAWe,EAAM,UACjB,UAAWA,EAAM,UACjB,UAAW,EACX,MAAOlB,EACP,UAAW,CAACA,EACZ,SAAU,GACV,SAAU,CAAE,KAAM,GAAI,MAAOkB,EAAM,UAAW,OAAQ,mBAAA,EACtD,WAAYX,EACZ,UAAW,SACX,UAAW,SACX,WAAYW,EAAM,WAClB,eAAgB,EAChB,UAAW,KAAA,EAEb,MAAO,CACL,MAAO,CACL,KAAMpB,EACN,KAAM,CAAE,KAAM,GAAI,MAAOoB,EAAM,cAAe,OAAQ,mBAAA,EACtD,SAAU,EAAA,EAEZ,SAAUd,EACV,UAAWc,EAAM,UACjB,UAAWA,EAAM,UACjB,UAAW,EACX,MAAOjB,EACP,UAAW,CAACA,EACZ,SAAU,GACV,SAAU,CAAE,KAAM,GAAI,MAAOiB,EAAM,UAAW,OAAQ,mBAAA,EACtD,WAAYX,EACZ,UAAW,SACX,UAAW,SACX,WAAYW,EAAM,WAClB,eAAgB,EAChB,UAAW,KAAA,EAEb,OAAQ,CACN,EAAG,GACH,EAAG,KACH,QAAS,SACT,QAAS,MACT,YAAa,IACb,KAAM,CAAE,KAAM,GAAI,MAAOA,EAAM,UAAW,OAAQ,mBAAA,CAAoB,EAExE,WAAYhB,GAAcT,EAAO,OAAS,EAC1C,YAAa6D,CAAA,EAGTK,EAAiC,CACrC,WAAY,GACZ,eAAgB,GAChB,YAAa,GACb,uBAAwB,CACtB,UACA,WACA,GAAI7C,EAAmB,CAAA,EAAK,CAAC,SAAS,CAAA,EAExC,GAAIA,GAAoB,CACtB,qBAAsB,CACpB,OAAQ,MACR,SAAU,eACV,MAAApB,EACA,OAAAC,CAAA,CACF,CACF,EAGF,OAAAiE,EAAO,QAAQrB,EAAYC,EAAUiB,EAAQE,CAAM,EACnDvC,EAAYmB,CAAU,EAEf,IAAM,CACPA,GACFqB,EAAO,MAAMrB,CAAU,CAE3B,CACF,EAAG,CACDhB,EAAiBU,EAAkBxC,EAAO,OAAQC,EAAOC,EAAQC,EAAOC,EAAYC,EACpF+B,EAAsB7B,EAAQC,EAAQC,EAAYC,EAAWC,EAAWC,EAAaC,EACrFC,EAAgBQ,EAAqBL,EAAsBC,EAAeC,EAC1EC,EAA4BC,EAAkBI,EAAOE,CAAA,CACtD,EAGCyC,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACb,SAAA,CAAAC,EAAAA,IAAC,MAAA,CAAI,IAAK9C,EAAS,MAAO,CAAE,MAAO,OAAQ,OAAQ,MAAA,CAAO,CAAG,EAC5DK,CAAA,EACH,CAEJ"}