@tetrascience-npm/tetrascience-react-ui 0.6.0-beta.94.1 → 0.6.0-beta.95.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 +1 @@
1
- {"version":3,"file":"ScatterGraph.cjs","sources":["../../../../src/components/charts/ScatterGraph/ScatterGraph.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\ninterface ScatterDataPoint {\n x: number;\n y: number;\n additionalInfo?: Record<string, string | number>;\n}\n\ninterface ScatterDataSeries {\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}\n\ninterface ScatterGraphProps {\n dataSeries: ScatterDataSeries[];\n width?: number;\n height?: number;\n xRange?: [number, number];\n yRange?: [number, number];\n xTitle?: string;\n yTitle?: string;\n title?: string;\n}\n\nconst ScatterGraph: React.FC<ScatterGraphProps> = ({\n dataSeries,\n width = 1000,\n height = 600,\n xRange,\n yRange,\n xTitle = \"Columns\",\n yTitle = \"Rows\",\n title = \"Scatter Plot\",\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const { bindTooltip, tooltipElement } = useChartTooltip({ xLabel: xTitle, yLabel: yTitle });\n\n const { xMin, xMax, 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 effectiveXRange = useMemo(\n () => xRange || [xMin, xMax],\n [xRange, xMin, xMax],\n );\n\n const effectiveYRange = useMemo(\n () => yRange || [yMin, yMax],\n [yRange, yMin, yMax],\n );\n\n const xTicks = useMemo(() => {\n const range = effectiveXRange[1] - effectiveXRange[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(effectiveXRange[0] / step) * step;\n while (current <= effectiveXRange[1]) {\n ticks.push(current);\n current += step;\n }\n return ticks;\n }, [effectiveXRange]);\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 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 x: series.x,\n y: series.y,\n type: \"scatter\" as const,\n mode: \"markers\" as const,\n name: series.name,\n marker: {\n color: seriesColor(index, series.color),\n size: 10,\n symbol: \"circle\" as const,\n },\n hoverinfo: \"none\" as const,\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 hovermode: \"closest\" as const,\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 // Crosshair guide lines through the hovered point. Drawn as layout shapes\n // with `layer: \"below\"` so they sit behind the markers — native Plotly\n // spikelines always render on top and can't be moved behind.\n const emitter = plotElement as unknown as Plotly.PlotlyHTMLElement;\n const crosshairLine = { color: theme.spikeColor, width: 2 };\n emitter.on(\"plotly_hover\", (eventData) => {\n const point = eventData.points[0];\n if (!point) return;\n void Plotly.relayout(plotElement, {\n shapes: [\n {\n type: \"line\",\n xref: \"x\",\n yref: \"paper\",\n x0: point.x,\n x1: point.x,\n y0: 0,\n y1: 1,\n line: crosshairLine,\n layer: \"below\",\n },\n {\n type: \"line\",\n xref: \"paper\",\n yref: \"y\",\n x0: 0,\n x1: 1,\n y0: point.y,\n y1: point.y,\n line: crosshairLine,\n layer: \"below\",\n },\n ],\n });\n });\n emitter.on(\"plotly_unhover\", () => {\n void Plotly.relayout(plotElement, { shapes: [] });\n });\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [dataSeries, width, height, xRange, yRange, xTitle, yTitle, title, effectiveXRange, effectiveYRange, xTicks, yTicks, tickOptions, theme, bindTooltip]);\n\n return (\n <div className=\"chart-container relative\">\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n {tooltipElement}\n </div>\n );\n};\n\nexport { ScatterGraph };\nexport type { ScatterDataPoint, ScatterDataSeries, ScatterGraphProps };\n"],"names":["ScatterGraph","dataSeries","width","height","xRange","yRange","xTitle","yTitle","title","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","xMin","xMax","yMin","yMax","useMemo","minX","maxX","minY","maxY","series","x","y","xPadding","yPadding","effectiveXRange","effectiveYRange","xTicks","range","step","ticks","current","yTicks","tickOptions","useEffect","plotData","index","seriesColor","layout","config","Plotly","plotElement","emitter","crosshairLine","eventData","point","jsxs","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"ScatterGraph.cjs","sources":["../../../../src/components/charts/ScatterGraph/ScatterGraph.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\ninterface ScatterDataPoint {\n x: number;\n y: number;\n additionalInfo?: Record<string, string | number>;\n}\n\ninterface ScatterDataSeries {\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}\n\ninterface ScatterGraphProps {\n dataSeries: ScatterDataSeries[];\n width?: number;\n height?: number;\n xRange?: [number, number];\n yRange?: [number, number];\n xTitle?: string;\n yTitle?: string;\n title?: string;\n}\n\nconst ScatterGraph: React.FC<ScatterGraphProps> = ({\n dataSeries,\n width = 1000,\n height = 600,\n xRange,\n yRange,\n xTitle = \"Columns\",\n yTitle = \"Rows\",\n title = \"Scatter Plot\",\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const { bindTooltip, tooltipElement } = useChartTooltip({ xLabel: xTitle, yLabel: yTitle });\n\n const { xMin, xMax, 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 effectiveXRange = useMemo(\n () => xRange || [xMin, xMax],\n [xRange, xMin, xMax],\n );\n\n const effectiveYRange = useMemo(\n () => yRange || [yMin, yMax],\n [yRange, yMin, yMax],\n );\n\n const xTicks = useMemo(() => {\n const range = effectiveXRange[1] - effectiveXRange[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(effectiveXRange[0] / step) * step;\n while (current <= effectiveXRange[1]) {\n ticks.push(current);\n current += step;\n }\n return ticks;\n }, [effectiveXRange]);\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 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 x: series.x,\n y: series.y,\n type: \"scatter\" as const,\n mode: \"markers\" as const,\n name: series.name,\n marker: {\n color: seriesColor(index, series.color),\n size: 10,\n symbol: \"circle\" as const,\n },\n hoverinfo: \"none\" as const,\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 hovermode: \"closest\" as const,\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 // Crosshair guide lines through the hovered point. Drawn as layout shapes\n // with `layer: \"below\"` so they sit behind the markers — native Plotly\n // spikelines always render on top and can't be moved behind.\n const emitter = plotElement as unknown as Plotly.PlotlyHTMLElement;\n const crosshairLine = { color: theme.spikeColor, width: 2 };\n emitter.on(\"plotly_hover\", (eventData) => {\n const point = eventData.points[0];\n if (!point) return;\n void Plotly.relayout(plotElement, {\n shapes: [\n {\n type: \"line\",\n xref: \"x\",\n yref: \"paper\",\n x0: point.x,\n x1: point.x,\n y0: 0,\n y1: 1,\n line: crosshairLine,\n layer: \"below\",\n },\n {\n type: \"line\",\n xref: \"paper\",\n yref: \"y\",\n x0: 0,\n x1: 1,\n y0: point.y,\n y1: point.y,\n line: crosshairLine,\n layer: \"below\",\n },\n ],\n });\n });\n emitter.on(\"plotly_unhover\", () => {\n void Plotly.relayout(plotElement, { shapes: [] });\n });\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [dataSeries, width, height, xRange, yRange, xTitle, yTitle, title, effectiveXRange, effectiveYRange, xTicks, yTicks, tickOptions, 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 { ScatterGraph };\nexport type { ScatterDataPoint, ScatterDataSeries, ScatterGraphProps };\n"],"names":["ScatterGraph","dataSeries","width","height","xRange","yRange","xTitle","yTitle","title","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","xMin","xMax","yMin","yMax","useMemo","minX","maxX","minY","maxY","series","x","y","xPadding","yPadding","effectiveXRange","effectiveYRange","xTicks","range","step","ticks","current","yTicks","tickOptions","useEffect","plotData","index","seriesColor","layout","config","Plotly","plotElement","emitter","crosshairLine","eventData","point","jsxs","jsx"],"mappings":"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"}
@@ -14,46 +14,46 @@ const q = ({
14
14
  yTitle: g = "Rows",
15
15
  title: b = "Scatter Plot"
16
16
  }) => {
17
- const p = X(null), e = B(), { bindTooltip: C, tooltipElement: N } = V({ xLabel: d, yLabel: g }), { xMin: E, xMax: I, yMin: _, yMax: z } = c(() => {
18
- let r = Number.MAX_VALUE, t = Number.MIN_VALUE, i = Number.MAX_VALUE, o = Number.MIN_VALUE;
17
+ const p = X(null), e = B(), { bindTooltip: C, tooltipElement: N } = V({ xLabel: d, yLabel: g }), { xMin: E, xMax: z, yMin: I, yMax: _ } = c(() => {
18
+ let r = Number.MAX_VALUE, t = Number.MIN_VALUE, n = Number.MAX_VALUE, o = Number.MIN_VALUE;
19
19
  u.forEach((l) => {
20
- l.x.forEach((n) => {
21
- r = Math.min(r, n), t = Math.max(t, n);
22
- }), l.y.forEach((n) => {
23
- i = Math.min(i, n), o = Math.max(o, n);
20
+ l.x.forEach((i) => {
21
+ r = Math.min(r, i), t = Math.max(t, i);
22
+ }), l.y.forEach((i) => {
23
+ n = Math.min(n, i), o = Math.max(o, i);
24
24
  });
25
25
  });
26
- const h = (t - r) * 0.1, y = (o - i) * 0.1;
26
+ const h = (t - r) * 0.1, y = (o - n) * 0.1;
27
27
  return {
28
28
  xMin: r - h,
29
29
  xMax: t + h,
30
- yMin: i - y,
30
+ yMin: n - y,
31
31
  yMax: o + y
32
32
  };
33
33
  }, [u]), s = c(
34
- () => f || [E, I],
35
- [f, E, I]
34
+ () => f || [E, z],
35
+ [f, E, z]
36
36
  ), a = c(
37
- () => m || [_, z],
38
- [m, _, z]
37
+ () => m || [I, _],
38
+ [m, I, _]
39
39
  ), M = c(() => {
40
40
  const r = s[1] - s[0];
41
41
  let t = Math.pow(10, Math.floor(Math.log10(r)));
42
42
  r / t > 10 && (t = t * 2), r / t < 4 && (t = t / 2);
43
- const i = [];
43
+ const n = [];
44
44
  let o = Math.ceil(s[0] / t) * t;
45
45
  for (; o <= s[1]; )
46
- i.push(o), o += t;
47
- return i;
46
+ n.push(o), o += t;
47
+ return n;
48
48
  }, [s]), L = c(() => {
49
49
  const r = a[1] - a[0];
50
50
  let t = Math.pow(10, Math.floor(Math.log10(r)));
51
51
  r / t > 10 && (t = t * 2), r / t < 4 && (t = t / 2);
52
- const i = [];
52
+ const n = [];
53
53
  let o = Math.ceil(a[0] / t) * t;
54
54
  for (; o <= a[1]; )
55
- i.push(o), o += t;
56
- return i;
55
+ n.push(o), o += t;
56
+ return n;
57
57
  }, [a]), k = c(
58
58
  () => ({
59
59
  tickcolor: e.tickColor,
@@ -75,14 +75,14 @@ const q = ({
75
75
  );
76
76
  return U(() => {
77
77
  if (!p.current) return;
78
- const r = u.map((l, n) => ({
78
+ const r = u.map((l, i) => ({
79
79
  x: l.x,
80
80
  y: l.y,
81
81
  type: "scatter",
82
82
  mode: "markers",
83
83
  name: l.name,
84
84
  marker: {
85
- color: Y(n, l.color),
85
+ color: Y(i, l.color),
86
86
  size: 10,
87
87
  symbol: "circle"
88
88
  },
@@ -159,23 +159,23 @@ const q = ({
159
159
  },
160
160
  showlegend: !0,
161
161
  hovermode: "closest"
162
- }, i = {
162
+ }, n = {
163
163
  responsive: !0,
164
164
  displayModeBar: !1,
165
165
  displaylogo: !1
166
166
  };
167
- x.newPlot(p.current, r, t, i), C(p.current);
167
+ x.newPlot(p.current, r, t, n), C(p.current);
168
168
  const o = p.current, h = o, y = { color: e.spikeColor, width: 2 };
169
169
  return h.on("plotly_hover", (l) => {
170
- const n = l.points[0];
171
- n && x.relayout(o, {
170
+ const i = l.points[0];
171
+ i && x.relayout(o, {
172
172
  shapes: [
173
173
  {
174
174
  type: "line",
175
175
  xref: "x",
176
176
  yref: "paper",
177
- x0: n.x,
178
- x1: n.x,
177
+ x0: i.x,
178
+ x1: i.x,
179
179
  y0: 0,
180
180
  y1: 1,
181
181
  line: y,
@@ -187,8 +187,8 @@ const q = ({
187
187
  yref: "y",
188
188
  x0: 0,
189
189
  x1: 1,
190
- y0: n.y,
191
- y1: n.y,
190
+ y0: i.y,
191
+ y1: i.y,
192
192
  line: y,
193
193
  layer: "below"
194
194
  }
@@ -199,7 +199,7 @@ const q = ({
199
199
  }), () => {
200
200
  o && x.purge(o);
201
201
  };
202
- }, [u, w, v, f, m, d, g, b, s, a, M, L, k, e, C]), /* @__PURE__ */ A("div", { className: "chart-container relative", children: [
202
+ }, [u, w, v, f, m, d, g, b, s, a, M, L, k, e, C]), /* @__PURE__ */ A("div", { className: "relative size-full", children: [
203
203
  /* @__PURE__ */ P("div", { ref: p, style: { width: "100%", height: "100%" } }),
204
204
  N
205
205
  ] });
@@ -1 +1 @@
1
- {"version":3,"file":"ScatterGraph.js","sources":["../../../../src/components/charts/ScatterGraph/ScatterGraph.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\ninterface ScatterDataPoint {\n x: number;\n y: number;\n additionalInfo?: Record<string, string | number>;\n}\n\ninterface ScatterDataSeries {\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}\n\ninterface ScatterGraphProps {\n dataSeries: ScatterDataSeries[];\n width?: number;\n height?: number;\n xRange?: [number, number];\n yRange?: [number, number];\n xTitle?: string;\n yTitle?: string;\n title?: string;\n}\n\nconst ScatterGraph: React.FC<ScatterGraphProps> = ({\n dataSeries,\n width = 1000,\n height = 600,\n xRange,\n yRange,\n xTitle = \"Columns\",\n yTitle = \"Rows\",\n title = \"Scatter Plot\",\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const { bindTooltip, tooltipElement } = useChartTooltip({ xLabel: xTitle, yLabel: yTitle });\n\n const { xMin, xMax, 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 effectiveXRange = useMemo(\n () => xRange || [xMin, xMax],\n [xRange, xMin, xMax],\n );\n\n const effectiveYRange = useMemo(\n () => yRange || [yMin, yMax],\n [yRange, yMin, yMax],\n );\n\n const xTicks = useMemo(() => {\n const range = effectiveXRange[1] - effectiveXRange[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(effectiveXRange[0] / step) * step;\n while (current <= effectiveXRange[1]) {\n ticks.push(current);\n current += step;\n }\n return ticks;\n }, [effectiveXRange]);\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 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 x: series.x,\n y: series.y,\n type: \"scatter\" as const,\n mode: \"markers\" as const,\n name: series.name,\n marker: {\n color: seriesColor(index, series.color),\n size: 10,\n symbol: \"circle\" as const,\n },\n hoverinfo: \"none\" as const,\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 hovermode: \"closest\" as const,\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 // Crosshair guide lines through the hovered point. Drawn as layout shapes\n // with `layer: \"below\"` so they sit behind the markers — native Plotly\n // spikelines always render on top and can't be moved behind.\n const emitter = plotElement as unknown as Plotly.PlotlyHTMLElement;\n const crosshairLine = { color: theme.spikeColor, width: 2 };\n emitter.on(\"plotly_hover\", (eventData) => {\n const point = eventData.points[0];\n if (!point) return;\n void Plotly.relayout(plotElement, {\n shapes: [\n {\n type: \"line\",\n xref: \"x\",\n yref: \"paper\",\n x0: point.x,\n x1: point.x,\n y0: 0,\n y1: 1,\n line: crosshairLine,\n layer: \"below\",\n },\n {\n type: \"line\",\n xref: \"paper\",\n yref: \"y\",\n x0: 0,\n x1: 1,\n y0: point.y,\n y1: point.y,\n line: crosshairLine,\n layer: \"below\",\n },\n ],\n });\n });\n emitter.on(\"plotly_unhover\", () => {\n void Plotly.relayout(plotElement, { shapes: [] });\n });\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [dataSeries, width, height, xRange, yRange, xTitle, yTitle, title, effectiveXRange, effectiveYRange, xTicks, yTicks, tickOptions, theme, bindTooltip]);\n\n return (\n <div className=\"chart-container relative\">\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n {tooltipElement}\n </div>\n );\n};\n\nexport { ScatterGraph };\nexport type { ScatterDataPoint, ScatterDataSeries, ScatterGraphProps };\n"],"names":["ScatterGraph","dataSeries","width","height","xRange","yRange","xTitle","yTitle","title","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","xMin","xMax","yMin","yMax","useMemo","minX","maxX","minY","maxY","series","x","y","xPadding","yPadding","effectiveXRange","effectiveYRange","xTicks","range","step","ticks","current","yTicks","tickOptions","useEffect","plotData","index","seriesColor","layout","config","Plotly","plotElement","emitter","crosshairLine","eventData","point","jsxs","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"ScatterGraph.js","sources":["../../../../src/components/charts/ScatterGraph/ScatterGraph.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\ninterface ScatterDataPoint {\n x: number;\n y: number;\n additionalInfo?: Record<string, string | number>;\n}\n\ninterface ScatterDataSeries {\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}\n\ninterface ScatterGraphProps {\n dataSeries: ScatterDataSeries[];\n width?: number;\n height?: number;\n xRange?: [number, number];\n yRange?: [number, number];\n xTitle?: string;\n yTitle?: string;\n title?: string;\n}\n\nconst ScatterGraph: React.FC<ScatterGraphProps> = ({\n dataSeries,\n width = 1000,\n height = 600,\n xRange,\n yRange,\n xTitle = \"Columns\",\n yTitle = \"Rows\",\n title = \"Scatter Plot\",\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const { bindTooltip, tooltipElement } = useChartTooltip({ xLabel: xTitle, yLabel: yTitle });\n\n const { xMin, xMax, 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 effectiveXRange = useMemo(\n () => xRange || [xMin, xMax],\n [xRange, xMin, xMax],\n );\n\n const effectiveYRange = useMemo(\n () => yRange || [yMin, yMax],\n [yRange, yMin, yMax],\n );\n\n const xTicks = useMemo(() => {\n const range = effectiveXRange[1] - effectiveXRange[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(effectiveXRange[0] / step) * step;\n while (current <= effectiveXRange[1]) {\n ticks.push(current);\n current += step;\n }\n return ticks;\n }, [effectiveXRange]);\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 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 x: series.x,\n y: series.y,\n type: \"scatter\" as const,\n mode: \"markers\" as const,\n name: series.name,\n marker: {\n color: seriesColor(index, series.color),\n size: 10,\n symbol: \"circle\" as const,\n },\n hoverinfo: \"none\" as const,\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 hovermode: \"closest\" as const,\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 // Crosshair guide lines through the hovered point. Drawn as layout shapes\n // with `layer: \"below\"` so they sit behind the markers — native Plotly\n // spikelines always render on top and can't be moved behind.\n const emitter = plotElement as unknown as Plotly.PlotlyHTMLElement;\n const crosshairLine = { color: theme.spikeColor, width: 2 };\n emitter.on(\"plotly_hover\", (eventData) => {\n const point = eventData.points[0];\n if (!point) return;\n void Plotly.relayout(plotElement, {\n shapes: [\n {\n type: \"line\",\n xref: \"x\",\n yref: \"paper\",\n x0: point.x,\n x1: point.x,\n y0: 0,\n y1: 1,\n line: crosshairLine,\n layer: \"below\",\n },\n {\n type: \"line\",\n xref: \"paper\",\n yref: \"y\",\n x0: 0,\n x1: 1,\n y0: point.y,\n y1: point.y,\n line: crosshairLine,\n layer: \"below\",\n },\n ],\n });\n });\n emitter.on(\"plotly_unhover\", () => {\n void Plotly.relayout(plotElement, { shapes: [] });\n });\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [dataSeries, width, height, xRange, yRange, xTitle, yTitle, title, effectiveXRange, effectiveYRange, xTicks, yTicks, tickOptions, 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 { ScatterGraph };\nexport type { ScatterDataPoint, ScatterDataSeries, ScatterGraphProps };\n"],"names":["ScatterGraph","dataSeries","width","height","xRange","yRange","xTitle","yTitle","title","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","xMin","xMax","yMin","yMax","useMemo","minX","maxX","minY","maxY","series","x","y","xPadding","yPadding","effectiveXRange","effectiveYRange","xTicks","range","step","ticks","current","yTicks","tickOptions","useEffect","plotData","index","seriesColor","layout","config","Plotly","plotElement","emitter","crosshairLine","eventData","point","jsxs","jsx"],"mappings":"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"}