@tetrascience-npm/tetrascience-react-ui 0.6.0-beta.83.1 → 0.6.0-beta.85.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.
- package/README.md +55 -0
- package/dist/components/charts/AreaGraph/AreaGraph.cjs +1 -1
- package/dist/components/charts/AreaGraph/AreaGraph.cjs.map +1 -1
- package/dist/components/charts/AreaGraph/AreaGraph.js +112 -82
- package/dist/components/charts/AreaGraph/AreaGraph.js.map +1 -1
- package/dist/components/charts/BarGraph/BarGraph.cjs +1 -1
- package/dist/components/charts/BarGraph/BarGraph.cjs.map +1 -1
- package/dist/components/charts/BarGraph/BarGraph.js +53 -48
- package/dist/components/charts/BarGraph/BarGraph.js.map +1 -1
- package/dist/components/charts/Boxplot/Boxplot.cjs +1 -1
- package/dist/components/charts/Boxplot/Boxplot.cjs.map +1 -1
- package/dist/components/charts/Boxplot/Boxplot.js +65 -60
- package/dist/components/charts/Boxplot/Boxplot.js.map +1 -1
- package/dist/components/charts/ChartTooltip/ChartTooltip.cjs +2 -0
- package/dist/components/charts/ChartTooltip/ChartTooltip.cjs.map +1 -0
- package/dist/components/charts/ChartTooltip/ChartTooltip.js +163 -0
- package/dist/components/charts/ChartTooltip/ChartTooltip.js.map +1 -0
- package/dist/components/charts/ChartTooltip/lines.cjs +2 -0
- package/dist/components/charts/ChartTooltip/lines.cjs.map +1 -0
- package/dist/components/charts/ChartTooltip/lines.js +29 -0
- package/dist/components/charts/ChartTooltip/lines.js.map +1 -0
- package/dist/components/charts/Chromatogram/Chromatogram.cjs +1 -1
- package/dist/components/charts/Chromatogram/Chromatogram.cjs.map +1 -1
- package/dist/components/charts/Chromatogram/Chromatogram.js +75 -66
- package/dist/components/charts/Chromatogram/Chromatogram.js.map +1 -1
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.cjs +1 -1
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.cjs.map +1 -1
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.js +107 -99
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.js.map +1 -1
- package/dist/components/charts/ChromatogramChart/dataProcessing.cjs +1 -1
- package/dist/components/charts/ChromatogramChart/dataProcessing.cjs.map +1 -1
- package/dist/components/charts/ChromatogramChart/dataProcessing.js +38 -49
- package/dist/components/charts/ChromatogramChart/dataProcessing.js.map +1 -1
- package/dist/components/charts/DotPlot/DotPlot.cjs +1 -1
- package/dist/components/charts/DotPlot/DotPlot.cjs.map +1 -1
- package/dist/components/charts/DotPlot/DotPlot.js +52 -48
- package/dist/components/charts/DotPlot/DotPlot.js.map +1 -1
- package/dist/components/charts/Histogram/Histogram.cjs +1 -1
- package/dist/components/charts/Histogram/Histogram.cjs.map +1 -1
- package/dist/components/charts/Histogram/Histogram.js +96 -92
- package/dist/components/charts/Histogram/Histogram.js.map +1 -1
- package/dist/components/charts/LineGraph/LineGraph.cjs +1 -1
- package/dist/components/charts/LineGraph/LineGraph.cjs.map +1 -1
- package/dist/components/charts/LineGraph/LineGraph.js +44 -39
- package/dist/components/charts/LineGraph/LineGraph.js.map +1 -1
- package/dist/components/charts/PieChart/PieChart.cjs +1 -1
- package/dist/components/charts/PieChart/PieChart.cjs.map +1 -1
- package/dist/components/charts/PieChart/PieChart.js +58 -54
- package/dist/components/charts/PieChart/PieChart.js.map +1 -1
- package/dist/components/charts/PlateMap/PlateMap.cjs +1 -1
- package/dist/components/charts/PlateMap/PlateMap.cjs.map +1 -1
- package/dist/components/charts/PlateMap/PlateMap.js +271 -256
- package/dist/components/charts/PlateMap/PlateMap.js.map +1 -1
- package/dist/components/charts/ScatterGraph/ScatterGraph.cjs +1 -1
- package/dist/components/charts/ScatterGraph/ScatterGraph.cjs.map +1 -1
- package/dist/components/charts/ScatterGraph/ScatterGraph.js +112 -89
- package/dist/components/charts/ScatterGraph/ScatterGraph.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +130 -0
- package/dist/index.js +585 -580
- package/dist/index.js.map +1 -1
- package/dist/index.tailwind.css +1 -1
- package/package.json +18 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataProcessing.js","sources":["../../../../src/components/charts/ChromatogramChart/dataProcessing.ts"],"sourcesContent":["/**\n * Data processing utilities for ChromatogramChart\n */\n\nimport { calculatePeakArea } from \"./peakDetection\";\n\nimport type { BaselineCorrectionMethod, PeakAnnotation } from \"./types\";\n\n/**\n * Data structure for peaks with their associated series data\n */\nexport type PeakDataWithSeries = {\n peaks: PeakAnnotation[];\n seriesIndex: number;\n x: number[];\n y: number[];\n};\n\n/**\n * Find the closest index in an array for a given target value.\n * Uses binary search for efficiency.\n */\nexport function findClosestIndex(arr: number[], target: number): number {\n if (arr.length === 0) return 0;\n if (arr.length === 1) return 0;\n\n let left = 0;\n let right = arr.length - 1;\n\n while (left < right) {\n const mid = Math.floor((left + right) / 2);\n if (arr[mid] < target) {\n left = mid + 1;\n } else {\n right = mid;\n }\n }\n\n // Check if left-1 is closer\n if (left > 0 && Math.abs(arr[left - 1] - target) < Math.abs(arr[left] - target)) {\n return left - 1;\n }\n return left;\n}\n\n/**\n * Process user annotations to convert startX/endX to startIndex/endIndex\n * and compute area if boundaries are provided.\n */\nexport function processUserAnnotations(\n annotations: PeakAnnotation[],\n xArray: number[],\n yArray: number[]\n): PeakAnnotation[] {\n return annotations.map((ann) => {\n // If startX/endX are provided, convert to indices\n if (ann.startX !== undefined && ann.endX !== undefined) {\n const startIndex = findClosestIndex(xArray, ann.startX);\n const endIndex = findClosestIndex(xArray, ann.endX);\n const index = findClosestIndex(xArray, ann.x);\n\n // Calculate area if not provided\n const area = ann._computed?.area ?? calculatePeakArea(xArray, yArray, startIndex, endIndex);\n\n return {\n ...ann,\n _computed: {\n ...ann._computed,\n index,\n startIndex,\n endIndex,\n area,\n },\n };\n }\n return ann;\n });\n}\n\n/**\n * Collect peaks with boundary information from both auto-detected peaks and user-provided annotations.\n * User-provided annotations with startIndex/endIndex or startX/endX are included for boundary marker rendering.\n */\nexport function collectPeaksWithBoundaryData(\n allDetectedPeaks: { peaks: PeakAnnotation[]; seriesIndex: number }[],\n annotations: PeakAnnotation[],\n processedSeries: { x: number[]; y: number[] }[]\n): PeakDataWithSeries[] {\n const peaksWithData: PeakDataWithSeries[] = [];\n\n // Add auto-detected peaks\n allDetectedPeaks.forEach(({ peaks, seriesIndex }) => {\n peaksWithData.push({\n peaks,\n seriesIndex,\n x: processedSeries[seriesIndex].x,\n y: processedSeries[seriesIndex].y,\n });\n });\n\n // Add user-provided annotations that have boundary info (_computed.startIndex and _computed.endIndex)\n // Note: annotations with startX/endX should already be processed to have _computed fields\n const annotationsWithBoundaries = annotations.filter(\n (ann) => ann._computed?.startIndex !== undefined && ann._computed?.endIndex !== undefined\n );\n if (annotationsWithBoundaries.length > 0 && processedSeries.length > 0) {\n peaksWithData.push({\n peaks: annotationsWithBoundaries,\n seriesIndex: 0, // User annotations apply to first series by default\n x: processedSeries[0].x,\n y: processedSeries[0].y,\n });\n }\n\n return peaksWithData;\n}\n\n/**\n * Build the extra content for Plotly hovertemplate from series metadata.\n * Displays all metadata fields as key: value pairs.\n */\nexport function buildHoverExtraContent(\n seriesName: string,\n metadata?: Record<string, unknown>\n): string {\n if (!metadata) return seriesName;\n\n const metaLines: string[] = [];\n for (const [key, value] of Object.entries(metadata)) {\n if (value !== undefined && value !== null && value !== \"\") {\n // Format the key as Title Case (e.g., \"sampleName\" -> \"Sample Name\")\n const formattedKey = key\n .replace(/([A-Z])/g, \" $1\")\n .replace(/^./, (s) => s.toUpperCase())\n .trim();\n metaLines.push(`${formattedKey}: ${String(value)}`);\n }\n }\n\n if (metaLines.length > 0) {\n return `${seriesName}<br>${metaLines.join(\"<br>\")}`;\n }\n return seriesName;\n}\n\n/**\n * Validate and sanitize series data.\n * - Ensures x and y arrays have the same length (truncates to shorter)\n * - Replaces NaN and Infinity values with 0\n */\nexport function validateSeriesData(\n x: number[],\n y: number[]\n): { x: number[]; y: number[] } {\n // Ensure arrays have same length\n const length = Math.min(x.length, y.length);\n const validX = x.slice(0, length);\n const validY = y.slice(0, length);\n\n // Sanitize NaN and Infinity values\n const sanitizedY = validY.map((val) => (Number.isFinite(val) ? val : 0));\n const sanitizedX = validX.map((val) => (Number.isFinite(val) ? val : 0));\n\n return { x: sanitizedX, y: sanitizedY };\n}\n\n/**\n * Apply baseline correction to signal data\n */\nexport function applyBaselineCorrection(\n y: number[],\n method: BaselineCorrectionMethod,\n windowSize: number = 50\n): number[] {\n if (method === \"none\" || y.length === 0) return y;\n\n if (method === \"linear\") {\n // Linear baseline from first to last point\n // Handle single-point case to avoid division by zero\n if (y.length === 1) {\n return [0]; // Single point baseline-corrected to zero\n }\n const slope = (y[y.length - 1] - y[0]) / (y.length - 1);\n return y.map((val, i) => val - (y[0] + slope * i));\n }\n\n if (method === \"rolling\") {\n // Rolling minimum baseline\n const baseline: number[] = [];\n const halfWindow = Math.floor(windowSize / 2);\n\n for (let i = 0; i < y.length; i++) {\n const start = Math.max(0, i - halfWindow);\n const end = Math.min(y.length, i + halfWindow + 1);\n const windowSlice = y.slice(start, end);\n baseline.push(Math.min(...windowSlice));\n }\n\n return y.map((val, i) => val - baseline[i]);\n }\n\n return y;\n}\n\n"],"names":["findClosestIndex","arr","target","left","right","mid","processUserAnnotations","annotations","xArray","yArray","ann","startIndex","endIndex","index","area","calculatePeakArea","collectPeaksWithBoundaryData","allDetectedPeaks","processedSeries","peaksWithData","peaks","seriesIndex","annotationsWithBoundaries","
|
|
1
|
+
{"version":3,"file":"dataProcessing.js","sources":["../../../../src/components/charts/ChromatogramChart/dataProcessing.ts"],"sourcesContent":["/**\n * Data processing utilities for ChromatogramChart\n */\n\nimport { calculatePeakArea } from \"./peakDetection\";\n\nimport type { BaselineCorrectionMethod, PeakAnnotation } from \"./types\";\n\n/**\n * Data structure for peaks with their associated series data\n */\nexport type PeakDataWithSeries = {\n peaks: PeakAnnotation[];\n seriesIndex: number;\n x: number[];\n y: number[];\n};\n\n/**\n * Find the closest index in an array for a given target value.\n * Uses binary search for efficiency.\n */\nexport function findClosestIndex(arr: number[], target: number): number {\n if (arr.length === 0) return 0;\n if (arr.length === 1) return 0;\n\n let left = 0;\n let right = arr.length - 1;\n\n while (left < right) {\n const mid = Math.floor((left + right) / 2);\n if (arr[mid] < target) {\n left = mid + 1;\n } else {\n right = mid;\n }\n }\n\n // Check if left-1 is closer\n if (left > 0 && Math.abs(arr[left - 1] - target) < Math.abs(arr[left] - target)) {\n return left - 1;\n }\n return left;\n}\n\n/**\n * Process user annotations to convert startX/endX to startIndex/endIndex\n * and compute area if boundaries are provided.\n */\nexport function processUserAnnotations(\n annotations: PeakAnnotation[],\n xArray: number[],\n yArray: number[]\n): PeakAnnotation[] {\n return annotations.map((ann) => {\n // If startX/endX are provided, convert to indices\n if (ann.startX !== undefined && ann.endX !== undefined) {\n const startIndex = findClosestIndex(xArray, ann.startX);\n const endIndex = findClosestIndex(xArray, ann.endX);\n const index = findClosestIndex(xArray, ann.x);\n\n // Calculate area if not provided\n const area = ann._computed?.area ?? calculatePeakArea(xArray, yArray, startIndex, endIndex);\n\n return {\n ...ann,\n _computed: {\n ...ann._computed,\n index,\n startIndex,\n endIndex,\n area,\n },\n };\n }\n return ann;\n });\n}\n\n/**\n * Collect peaks with boundary information from both auto-detected peaks and user-provided annotations.\n * User-provided annotations with startIndex/endIndex or startX/endX are included for boundary marker rendering.\n */\nexport function collectPeaksWithBoundaryData(\n allDetectedPeaks: { peaks: PeakAnnotation[]; seriesIndex: number }[],\n annotations: PeakAnnotation[],\n processedSeries: { x: number[]; y: number[] }[]\n): PeakDataWithSeries[] {\n const peaksWithData: PeakDataWithSeries[] = [];\n\n // Add auto-detected peaks\n allDetectedPeaks.forEach(({ peaks, seriesIndex }) => {\n peaksWithData.push({\n peaks,\n seriesIndex,\n x: processedSeries[seriesIndex].x,\n y: processedSeries[seriesIndex].y,\n });\n });\n\n // Add user-provided annotations that have boundary info (_computed.startIndex and _computed.endIndex)\n // Note: annotations with startX/endX should already be processed to have _computed fields\n const annotationsWithBoundaries = annotations.filter(\n (ann) => ann._computed?.startIndex !== undefined && ann._computed?.endIndex !== undefined\n );\n if (annotationsWithBoundaries.length > 0 && processedSeries.length > 0) {\n peaksWithData.push({\n peaks: annotationsWithBoundaries,\n seriesIndex: 0, // User annotations apply to first series by default\n x: processedSeries[0].x,\n y: processedSeries[0].y,\n });\n }\n\n return peaksWithData;\n}\n\n/**\n * Build the extra content for Plotly hovertemplate from series metadata.\n * Displays all metadata fields as key: value pairs.\n */\nexport function buildHoverExtraContent(\n seriesName: string,\n metadata?: Record<string, unknown>\n): string {\n if (!metadata) return seriesName;\n\n const metaLines: string[] = [];\n for (const [key, value] of Object.entries(metadata)) {\n if (value !== undefined && value !== null && value !== \"\") {\n // Format the key as Title Case (e.g., \"sampleName\" -> \"Sample Name\")\n const formattedKey = key\n .replace(/([A-Z])/g, \" $1\")\n .replace(/^./, (s) => s.toUpperCase())\n .trim();\n metaLines.push(`${formattedKey}: ${String(value)}`);\n }\n }\n\n if (metaLines.length > 0) {\n return `${seriesName}<br>${metaLines.join(\"<br>\")}`;\n }\n return seriesName;\n}\n\n/**\n * Validate and sanitize series data.\n * - Ensures x and y arrays have the same length (truncates to shorter)\n * - Replaces NaN and Infinity values with 0\n */\nexport function validateSeriesData(\n x: number[],\n y: number[]\n): { x: number[]; y: number[] } {\n // Ensure arrays have same length\n const length = Math.min(x.length, y.length);\n const validX = x.slice(0, length);\n const validY = y.slice(0, length);\n\n // Sanitize NaN and Infinity values\n const sanitizedY = validY.map((val) => (Number.isFinite(val) ? val : 0));\n const sanitizedX = validX.map((val) => (Number.isFinite(val) ? val : 0));\n\n return { x: sanitizedX, y: sanitizedY };\n}\n\n/**\n * Apply baseline correction to signal data\n */\nexport function applyBaselineCorrection(\n y: number[],\n method: BaselineCorrectionMethod,\n windowSize: number = 50\n): number[] {\n if (method === \"none\" || y.length === 0) return y;\n\n if (method === \"linear\") {\n // Linear baseline from first to last point\n // Handle single-point case to avoid division by zero\n if (y.length === 1) {\n return [0]; // Single point baseline-corrected to zero\n }\n const slope = (y[y.length - 1] - y[0]) / (y.length - 1);\n return y.map((val, i) => val - (y[0] + slope * i));\n }\n\n if (method === \"rolling\") {\n // Rolling minimum baseline\n const baseline: number[] = [];\n const halfWindow = Math.floor(windowSize / 2);\n\n for (let i = 0; i < y.length; i++) {\n const start = Math.max(0, i - halfWindow);\n const end = Math.min(y.length, i + halfWindow + 1);\n const windowSlice = y.slice(start, end);\n baseline.push(Math.min(...windowSlice));\n }\n\n return y.map((val, i) => val - baseline[i]);\n }\n\n return y;\n}\n\n"],"names":["findClosestIndex","arr","target","left","right","mid","processUserAnnotations","annotations","xArray","yArray","ann","startIndex","endIndex","index","area","calculatePeakArea","collectPeaksWithBoundaryData","allDetectedPeaks","processedSeries","peaksWithData","peaks","seriesIndex","annotationsWithBoundaries","validateSeriesData","x","y","length","validX","sanitizedY","val","applyBaselineCorrection","method","windowSize","slope","baseline","halfWindow","start","end","windowSlice","i"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const M=require("react/jsx-runtime"),P=require("plotly.js-dist"),e=require("react"),q=require("../ChartTooltip/ChartTooltip.cjs"),R=require("../../../hooks/use-plotly-theme.cjs"),I=require("../../../utils/colors.cjs"),v=({dataSeries:l,width:i=1e3,height:p=600,title:d="Dot Plot",xTitle:c="Columns",yTitle:a="Rows",variant:g="default",markerSize:u=8})=>{const r=e.useRef(null),t=R.usePlotlyTheme(),{bindTooltip:h,tooltipElement:k}=q.useChartTooltip({xLabel:c,yLabel:a}),x=e.useMemo(()=>Array.isArray(l)?l:[l],[l]),n=I.CHART_COLORS,f=e.useMemo(()=>["circle","square","diamond","triangle-up","triangle-down","star"],[]),b=e.useMemo(()=>x.map((o,s)=>g==="default"?{...o,color:o.color||n[0],symbol:"circle",size:o.size||u}:{...o,color:o.color||n[s%n.length],symbol:o.symbol||f[s%f.length],size:o.size||u}),[x,g,u,n,f]),m=t.gridColor,C=e.useMemo(()=>b.map(o=>({type:"scatter",x:o.x,y:o.y,mode:"markers",name:o.name,marker:{color:o.color,size:o.size,symbol:o.symbol,line:{color:t.paperBg,width:1}},hoverinfo:"none"})),[b,t]),y=e.useMemo(()=>({tickcolor:t.tickColor,ticklen:12,tickwidth:1,ticks:"outside",tickfont:{size:16,color:t.textColor,family:"Inter, sans-serif",weight:400},linecolor:t.lineColor,linewidth:1,position:0,zeroline:!1}),[t]),w=e.useMemo(()=>({text:d,x:.5,y:.95,xanchor:"center",yanchor:"top",font:{size:32,weight:600,family:"Inter, sans-serif",color:t.textColor,lineheight:1.2,standoff:30}}),[d,t]);return e.useEffect(()=>{if(!r.current)return;const o={width:i,height:p,font:{family:"Inter, sans-serif"},title:w,margin:{l:80,r:40,b:80,t:80,pad:0},showlegend:!0,legend:{x:.5,y:-.2,xanchor:"center",yanchor:"top",orientation:"h",font:{size:13,color:t.legendColor,family:"Inter, sans-serif",weight:500,lineheight:18}},xaxis:{title:{text:c,font:{size:16,color:t.textSecondary,family:"Inter, sans-serif",weight:400},standoff:15},gridcolor:m,...y},yaxis:{title:{text:a,font:{size:16,color:t.textSecondary,family:"Inter, sans-serif",weight:400},standoff:15},gridcolor:m,...y},paper_bgcolor:t.paperBg,plot_bgcolor:t.plotBg},s={responsive:!0,displayModeBar:!1,displaylogo:!1};P.newPlot(r.current,C,o,s),h(r.current);const z=r.current;return()=>{z&&P.purge(z)}},[i,p,c,a,C,w,y,m,t,h]),M.jsxs("div",{className:"dotplot-container relative",style:{width:i},children:[M.jsx("div",{ref:r,style:{width:"100%",height:"100%",margin:"0"}}),k]})};exports.DotPlot=v;
|
|
2
2
|
//# sourceMappingURL=DotPlot.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DotPlot.cjs","sources":["../../../../src/components/charts/DotPlot/DotPlot.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { CHART_COLORS } from \"@/utils/colors\";\n\ntype MarkerSymbol =\n | \"circle\"\n | \"square\"\n | \"diamond\"\n | \"triangle-up\"\n | \"triangle-down\"\n | \"star\";\n\ninterface DotPlotDataSeries {\n x: number[];\n y: number[];\n name: string;\n color?: string;\n symbol?: MarkerSymbol;\n size?: number;\n}\n\ntype DotPlotVariant = \"default\" | \"stacked\";\n\ntype DotPlotProps = {\n dataSeries: DotPlotDataSeries | DotPlotDataSeries[];\n width?: number;\n height?: number;\n title?: string;\n xTitle?: string;\n yTitle?: string;\n variant?: DotPlotVariant;\n markerSize?: number;\n};\n\nconst DotPlot: React.FC<DotPlotProps> = ({\n dataSeries,\n width = 1000,\n height = 600,\n title = \"Dot Plot\",\n xTitle = \"Columns\",\n yTitle = \"Rows\",\n variant = \"default\",\n markerSize = 8,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const seriesArray = useMemo(\n () => (Array.isArray(dataSeries) ? dataSeries : [dataSeries]),\n [dataSeries],\n );\n\n const defaultColors = CHART_COLORS;\n\n const defaultSymbols: MarkerSymbol[] = useMemo(\n () => [\n \"circle\",\n \"square\",\n \"diamond\",\n \"triangle-up\",\n \"triangle-down\",\n \"star\",\n ],\n [],\n );\n\n const seriesWithColors = useMemo(() => {\n return seriesArray.map((series, index) => {\n if (variant === \"default\") {\n // Default variant: all circles, use first color or series color\n return {\n ...series,\n color: series.color || defaultColors[0],\n symbol: \"circle\" as MarkerSymbol,\n size: series.size || markerSize,\n };\n } else {\n // Stacked variant: different symbols and colors for each series\n return {\n ...series,\n color: series.color || defaultColors[index % defaultColors.length],\n symbol:\n series.symbol || defaultSymbols[index % defaultSymbols.length],\n size: series.size || markerSize,\n };\n }\n });\n }, [seriesArray, variant, markerSize, defaultColors, defaultSymbols]);\n\n const gridColor = theme.gridColor;\n\n const plotData = useMemo(\n () =>\n seriesWithColors.map((series) => ({\n type: \"scatter\" as const,\n x: series.x,\n y: series.y,\n mode: \"markers\" as const,\n name: series.name,\n marker: {\n color: series.color,\n size: series.size,\n symbol: series.symbol,\n line: {\n color: theme.paperBg,\n width: 1,\n },\n },\n
|
|
1
|
+
{"version":3,"file":"DotPlot.cjs","sources":["../../../../src/components/charts/DotPlot/DotPlot.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { useChartTooltip } from \"../ChartTooltip\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { CHART_COLORS } from \"@/utils/colors\";\n\ntype MarkerSymbol =\n | \"circle\"\n | \"square\"\n | \"diamond\"\n | \"triangle-up\"\n | \"triangle-down\"\n | \"star\";\n\ninterface DotPlotDataSeries {\n x: number[];\n y: number[];\n name: string;\n color?: string;\n symbol?: MarkerSymbol;\n size?: number;\n}\n\ntype DotPlotVariant = \"default\" | \"stacked\";\n\ntype DotPlotProps = {\n dataSeries: DotPlotDataSeries | DotPlotDataSeries[];\n width?: number;\n height?: number;\n title?: string;\n xTitle?: string;\n yTitle?: string;\n variant?: DotPlotVariant;\n markerSize?: number;\n};\n\nconst DotPlot: React.FC<DotPlotProps> = ({\n dataSeries,\n width = 1000,\n height = 600,\n title = \"Dot Plot\",\n xTitle = \"Columns\",\n yTitle = \"Rows\",\n variant = \"default\",\n markerSize = 8,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const { bindTooltip, tooltipElement } = useChartTooltip({ xLabel: xTitle, yLabel: yTitle });\n const seriesArray = useMemo(\n () => (Array.isArray(dataSeries) ? dataSeries : [dataSeries]),\n [dataSeries],\n );\n\n const defaultColors = CHART_COLORS;\n\n const defaultSymbols: MarkerSymbol[] = useMemo(\n () => [\n \"circle\",\n \"square\",\n \"diamond\",\n \"triangle-up\",\n \"triangle-down\",\n \"star\",\n ],\n [],\n );\n\n const seriesWithColors = useMemo(() => {\n return seriesArray.map((series, index) => {\n if (variant === \"default\") {\n // Default variant: all circles, use first color or series color\n return {\n ...series,\n color: series.color || defaultColors[0],\n symbol: \"circle\" as MarkerSymbol,\n size: series.size || markerSize,\n };\n } else {\n // Stacked variant: different symbols and colors for each series\n return {\n ...series,\n color: series.color || defaultColors[index % defaultColors.length],\n symbol:\n series.symbol || defaultSymbols[index % defaultSymbols.length],\n size: series.size || markerSize,\n };\n }\n });\n }, [seriesArray, variant, markerSize, defaultColors, defaultSymbols]);\n\n const gridColor = theme.gridColor;\n\n const plotData = useMemo(\n () =>\n seriesWithColors.map((series) => ({\n type: \"scatter\" as const,\n x: series.x,\n y: series.y,\n mode: \"markers\" as const,\n name: series.name,\n marker: {\n color: series.color,\n size: series.size,\n symbol: series.symbol,\n line: {\n color: theme.paperBg,\n width: 1,\n },\n },\n hoverinfo: \"none\" as const,\n })),\n [seriesWithColors, theme],\n );\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 const titleOptions = useMemo(\n () => ({\n text: title,\n x: 0.5,\n y: 0.95,\n xanchor: \"center\" as const,\n yanchor: \"top\" as const,\n font: {\n size: 32,\n weight: 600,\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n lineheight: 1.2,\n standoff: 30,\n },\n }),\n [title, theme],\n );\n\n useEffect(() => {\n if (!plotRef.current) return;\n\n const layout = {\n width,\n height,\n font: {\n family: \"Inter, sans-serif\",\n },\n title: titleOptions,\n margin: { l: 80, r: 40, b: 80, t: 80, pad: 0 },\n showlegend: true,\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: 13,\n color: theme.legendColor,\n family: \"Inter, sans-serif\",\n weight: 500,\n lineheight: 18,\n },\n },\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: 15,\n },\n gridcolor: gridColor,\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: 15,\n },\n gridcolor: gridColor,\n ...tickOptions,\n },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, plotData, layout, config);\n bindTooltip(plotRef.current);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [width, height, xTitle, yTitle, plotData, titleOptions, tickOptions, gridColor, theme, bindTooltip]);\n\n return (\n <div className=\"dotplot-container relative\" style={{ width: width }}>\n <div\n ref={plotRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n margin: \"0\",\n }}\n />\n {tooltipElement}\n </div>\n );\n};\n\nexport { DotPlot };\nexport type { DotPlotDataSeries, DotPlotProps, DotPlotVariant, MarkerSymbol };\n"],"names":["DotPlot","dataSeries","width","height","title","xTitle","yTitle","variant","markerSize","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","seriesArray","useMemo","defaultColors","CHART_COLORS","defaultSymbols","seriesWithColors","series","index","gridColor","plotData","tickOptions","titleOptions","useEffect","layout","config","Plotly","plotElement","jsx"],"mappings":"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"}
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
import { jsx as
|
|
1
|
+
import { jsxs as P, jsx as R } from "react/jsx-runtime";
|
|
2
2
|
import k from "plotly.js-dist";
|
|
3
|
-
import { useRef as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
import { useRef as v, useMemo as e, useEffect as A } from "react";
|
|
4
|
+
import { useChartTooltip as B } from "../ChartTooltip/ChartTooltip.js";
|
|
5
|
+
import { usePlotlyTheme as O } from "../../../hooks/use-plotly-theme.js";
|
|
6
|
+
import { CHART_COLORS as D } from "../../../utils/colors.js";
|
|
7
|
+
const H = ({
|
|
8
|
+
dataSeries: l,
|
|
9
|
+
width: s = 1e3,
|
|
10
|
+
height: d = 600,
|
|
11
|
+
title: g = "Dot Plot",
|
|
12
|
+
xTitle: c = "Columns",
|
|
13
|
+
yTitle: a = "Rows",
|
|
13
14
|
variant: u = "default",
|
|
14
15
|
markerSize: f = 8
|
|
15
16
|
}) => {
|
|
16
|
-
const
|
|
17
|
-
() => Array.isArray(
|
|
18
|
-
[
|
|
19
|
-
),
|
|
17
|
+
const r = v(null), t = O(), { bindTooltip: h, tooltipElement: I } = B({ xLabel: c, yLabel: a }), x = e(
|
|
18
|
+
() => Array.isArray(l) ? l : [l],
|
|
19
|
+
[l]
|
|
20
|
+
), n = D, m = e(
|
|
20
21
|
() => [
|
|
21
22
|
"circle",
|
|
22
23
|
"square",
|
|
@@ -26,18 +27,18 @@ const $ = ({
|
|
|
26
27
|
"star"
|
|
27
28
|
],
|
|
28
29
|
[]
|
|
29
|
-
),
|
|
30
|
+
), C = e(() => x.map((o, i) => u === "default" ? {
|
|
30
31
|
...o,
|
|
31
|
-
color: o.color ||
|
|
32
|
+
color: o.color || n[0],
|
|
32
33
|
symbol: "circle",
|
|
33
34
|
size: o.size || f
|
|
34
35
|
} : {
|
|
35
36
|
...o,
|
|
36
|
-
color: o.color ||
|
|
37
|
-
symbol: o.symbol || m[
|
|
37
|
+
color: o.color || n[i % n.length],
|
|
38
|
+
symbol: o.symbol || m[i % m.length],
|
|
38
39
|
size: o.size || f
|
|
39
|
-
}), [
|
|
40
|
-
() =>
|
|
40
|
+
}), [x, u, f, n, m]), p = t.gridColor, b = e(
|
|
41
|
+
() => C.map((o) => ({
|
|
41
42
|
type: "scatter",
|
|
42
43
|
x: o.x,
|
|
43
44
|
y: o.y,
|
|
@@ -52,10 +53,10 @@ const $ = ({
|
|
|
52
53
|
width: 1
|
|
53
54
|
}
|
|
54
55
|
},
|
|
55
|
-
|
|
56
|
+
hoverinfo: "none"
|
|
56
57
|
})),
|
|
57
|
-
[
|
|
58
|
-
), y =
|
|
58
|
+
[C, t]
|
|
59
|
+
), y = e(
|
|
59
60
|
() => ({
|
|
60
61
|
tickcolor: t.tickColor,
|
|
61
62
|
ticklen: 12,
|
|
@@ -73,9 +74,9 @@ const $ = ({
|
|
|
73
74
|
zeroline: !1
|
|
74
75
|
}),
|
|
75
76
|
[t]
|
|
76
|
-
), w =
|
|
77
|
+
), w = e(
|
|
77
78
|
() => ({
|
|
78
|
-
text:
|
|
79
|
+
text: g,
|
|
79
80
|
x: 0.5,
|
|
80
81
|
y: 0.95,
|
|
81
82
|
xanchor: "center",
|
|
@@ -89,13 +90,13 @@ const $ = ({
|
|
|
89
90
|
standoff: 30
|
|
90
91
|
}
|
|
91
92
|
}),
|
|
92
|
-
[
|
|
93
|
+
[g, t]
|
|
93
94
|
);
|
|
94
|
-
return
|
|
95
|
-
if (!
|
|
95
|
+
return A(() => {
|
|
96
|
+
if (!r.current) return;
|
|
96
97
|
const o = {
|
|
97
|
-
width:
|
|
98
|
-
height:
|
|
98
|
+
width: s,
|
|
99
|
+
height: d,
|
|
99
100
|
font: {
|
|
100
101
|
family: "Inter, sans-serif"
|
|
101
102
|
},
|
|
@@ -118,7 +119,7 @@ const $ = ({
|
|
|
118
119
|
},
|
|
119
120
|
xaxis: {
|
|
120
121
|
title: {
|
|
121
|
-
text:
|
|
122
|
+
text: c,
|
|
122
123
|
font: {
|
|
123
124
|
size: 16,
|
|
124
125
|
color: t.textSecondary,
|
|
@@ -132,7 +133,7 @@ const $ = ({
|
|
|
132
133
|
},
|
|
133
134
|
yaxis: {
|
|
134
135
|
title: {
|
|
135
|
-
text:
|
|
136
|
+
text: a,
|
|
136
137
|
font: {
|
|
137
138
|
size: 16,
|
|
138
139
|
color: t.textSecondary,
|
|
@@ -146,29 +147,32 @@ const $ = ({
|
|
|
146
147
|
},
|
|
147
148
|
paper_bgcolor: t.paperBg,
|
|
148
149
|
plot_bgcolor: t.plotBg
|
|
149
|
-
},
|
|
150
|
+
}, i = {
|
|
150
151
|
responsive: !0,
|
|
151
152
|
displayModeBar: !1,
|
|
152
153
|
displaylogo: !1
|
|
153
154
|
};
|
|
154
|
-
k.newPlot(
|
|
155
|
-
const
|
|
155
|
+
k.newPlot(r.current, b, o, i), h(r.current);
|
|
156
|
+
const z = r.current;
|
|
156
157
|
return () => {
|
|
157
|
-
|
|
158
|
+
z && k.purge(z);
|
|
158
159
|
};
|
|
159
|
-
}, [
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
160
|
+
}, [s, d, c, a, b, w, y, p, t, h]), /* @__PURE__ */ P("div", { className: "dotplot-container relative", style: { width: s }, children: [
|
|
161
|
+
/* @__PURE__ */ R(
|
|
162
|
+
"div",
|
|
163
|
+
{
|
|
164
|
+
ref: r,
|
|
165
|
+
style: {
|
|
166
|
+
width: "100%",
|
|
167
|
+
height: "100%",
|
|
168
|
+
margin: "0"
|
|
169
|
+
}
|
|
167
170
|
}
|
|
168
|
-
|
|
169
|
-
|
|
171
|
+
),
|
|
172
|
+
I
|
|
173
|
+
] });
|
|
170
174
|
};
|
|
171
175
|
export {
|
|
172
|
-
|
|
176
|
+
H as DotPlot
|
|
173
177
|
};
|
|
174
178
|
//# sourceMappingURL=DotPlot.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DotPlot.js","sources":["../../../../src/components/charts/DotPlot/DotPlot.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { CHART_COLORS } from \"@/utils/colors\";\n\ntype MarkerSymbol =\n | \"circle\"\n | \"square\"\n | \"diamond\"\n | \"triangle-up\"\n | \"triangle-down\"\n | \"star\";\n\ninterface DotPlotDataSeries {\n x: number[];\n y: number[];\n name: string;\n color?: string;\n symbol?: MarkerSymbol;\n size?: number;\n}\n\ntype DotPlotVariant = \"default\" | \"stacked\";\n\ntype DotPlotProps = {\n dataSeries: DotPlotDataSeries | DotPlotDataSeries[];\n width?: number;\n height?: number;\n title?: string;\n xTitle?: string;\n yTitle?: string;\n variant?: DotPlotVariant;\n markerSize?: number;\n};\n\nconst DotPlot: React.FC<DotPlotProps> = ({\n dataSeries,\n width = 1000,\n height = 600,\n title = \"Dot Plot\",\n xTitle = \"Columns\",\n yTitle = \"Rows\",\n variant = \"default\",\n markerSize = 8,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const seriesArray = useMemo(\n () => (Array.isArray(dataSeries) ? dataSeries : [dataSeries]),\n [dataSeries],\n );\n\n const defaultColors = CHART_COLORS;\n\n const defaultSymbols: MarkerSymbol[] = useMemo(\n () => [\n \"circle\",\n \"square\",\n \"diamond\",\n \"triangle-up\",\n \"triangle-down\",\n \"star\",\n ],\n [],\n );\n\n const seriesWithColors = useMemo(() => {\n return seriesArray.map((series, index) => {\n if (variant === \"default\") {\n // Default variant: all circles, use first color or series color\n return {\n ...series,\n color: series.color || defaultColors[0],\n symbol: \"circle\" as MarkerSymbol,\n size: series.size || markerSize,\n };\n } else {\n // Stacked variant: different symbols and colors for each series\n return {\n ...series,\n color: series.color || defaultColors[index % defaultColors.length],\n symbol:\n series.symbol || defaultSymbols[index % defaultSymbols.length],\n size: series.size || markerSize,\n };\n }\n });\n }, [seriesArray, variant, markerSize, defaultColors, defaultSymbols]);\n\n const gridColor = theme.gridColor;\n\n const plotData = useMemo(\n () =>\n seriesWithColors.map((series) => ({\n type: \"scatter\" as const,\n x: series.x,\n y: series.y,\n mode: \"markers\" as const,\n name: series.name,\n marker: {\n color: series.color,\n size: series.size,\n symbol: series.symbol,\n line: {\n color: theme.paperBg,\n width: 1,\n },\n },\n hovertemplate: `${xTitle}: %{x}<br>${yTitle}: %{y}<extra>${series.name}</extra>`,\n })),\n [seriesWithColors, xTitle, yTitle, theme],\n );\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 const titleOptions = useMemo(\n () => ({\n text: title,\n x: 0.5,\n y: 0.95,\n xanchor: \"center\" as const,\n yanchor: \"top\" as const,\n font: {\n size: 32,\n weight: 600,\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n lineheight: 1.2,\n standoff: 30,\n },\n }),\n [title, theme],\n );\n\n useEffect(() => {\n if (!plotRef.current) return;\n\n const layout = {\n width,\n height,\n font: {\n family: \"Inter, sans-serif\",\n },\n title: titleOptions,\n margin: { l: 80, r: 40, b: 80, t: 80, pad: 0 },\n showlegend: true,\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: 13,\n color: theme.legendColor,\n family: \"Inter, sans-serif\",\n weight: 500,\n lineheight: 18,\n },\n },\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: 15,\n },\n gridcolor: gridColor,\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: 15,\n },\n gridcolor: gridColor,\n ...tickOptions,\n },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, plotData, layout, config);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [width, height, xTitle, yTitle, plotData, titleOptions, tickOptions, gridColor, theme]);\n\n return (\n <div className=\"dotplot-container\" style={{ width: width }}>\n <div\n ref={plotRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n margin: \"0\",\n }}\n />\n </div>\n );\n};\n\nexport { DotPlot };\nexport type { DotPlotDataSeries, DotPlotProps, DotPlotVariant, MarkerSymbol };\n"],"names":["DotPlot","dataSeries","width","height","title","xTitle","yTitle","variant","markerSize","plotRef","useRef","theme","usePlotlyTheme","seriesArray","useMemo","defaultColors","CHART_COLORS","defaultSymbols","seriesWithColors","series","index","gridColor","plotData","tickOptions","titleOptions","useEffect","layout","config","Plotly","plotElement","jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DotPlot.js","sources":["../../../../src/components/charts/DotPlot/DotPlot.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { useChartTooltip } from \"../ChartTooltip\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { CHART_COLORS } from \"@/utils/colors\";\n\ntype MarkerSymbol =\n | \"circle\"\n | \"square\"\n | \"diamond\"\n | \"triangle-up\"\n | \"triangle-down\"\n | \"star\";\n\ninterface DotPlotDataSeries {\n x: number[];\n y: number[];\n name: string;\n color?: string;\n symbol?: MarkerSymbol;\n size?: number;\n}\n\ntype DotPlotVariant = \"default\" | \"stacked\";\n\ntype DotPlotProps = {\n dataSeries: DotPlotDataSeries | DotPlotDataSeries[];\n width?: number;\n height?: number;\n title?: string;\n xTitle?: string;\n yTitle?: string;\n variant?: DotPlotVariant;\n markerSize?: number;\n};\n\nconst DotPlot: React.FC<DotPlotProps> = ({\n dataSeries,\n width = 1000,\n height = 600,\n title = \"Dot Plot\",\n xTitle = \"Columns\",\n yTitle = \"Rows\",\n variant = \"default\",\n markerSize = 8,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const { bindTooltip, tooltipElement } = useChartTooltip({ xLabel: xTitle, yLabel: yTitle });\n const seriesArray = useMemo(\n () => (Array.isArray(dataSeries) ? dataSeries : [dataSeries]),\n [dataSeries],\n );\n\n const defaultColors = CHART_COLORS;\n\n const defaultSymbols: MarkerSymbol[] = useMemo(\n () => [\n \"circle\",\n \"square\",\n \"diamond\",\n \"triangle-up\",\n \"triangle-down\",\n \"star\",\n ],\n [],\n );\n\n const seriesWithColors = useMemo(() => {\n return seriesArray.map((series, index) => {\n if (variant === \"default\") {\n // Default variant: all circles, use first color or series color\n return {\n ...series,\n color: series.color || defaultColors[0],\n symbol: \"circle\" as MarkerSymbol,\n size: series.size || markerSize,\n };\n } else {\n // Stacked variant: different symbols and colors for each series\n return {\n ...series,\n color: series.color || defaultColors[index % defaultColors.length],\n symbol:\n series.symbol || defaultSymbols[index % defaultSymbols.length],\n size: series.size || markerSize,\n };\n }\n });\n }, [seriesArray, variant, markerSize, defaultColors, defaultSymbols]);\n\n const gridColor = theme.gridColor;\n\n const plotData = useMemo(\n () =>\n seriesWithColors.map((series) => ({\n type: \"scatter\" as const,\n x: series.x,\n y: series.y,\n mode: \"markers\" as const,\n name: series.name,\n marker: {\n color: series.color,\n size: series.size,\n symbol: series.symbol,\n line: {\n color: theme.paperBg,\n width: 1,\n },\n },\n hoverinfo: \"none\" as const,\n })),\n [seriesWithColors, theme],\n );\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 const titleOptions = useMemo(\n () => ({\n text: title,\n x: 0.5,\n y: 0.95,\n xanchor: \"center\" as const,\n yanchor: \"top\" as const,\n font: {\n size: 32,\n weight: 600,\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n lineheight: 1.2,\n standoff: 30,\n },\n }),\n [title, theme],\n );\n\n useEffect(() => {\n if (!plotRef.current) return;\n\n const layout = {\n width,\n height,\n font: {\n family: \"Inter, sans-serif\",\n },\n title: titleOptions,\n margin: { l: 80, r: 40, b: 80, t: 80, pad: 0 },\n showlegend: true,\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: 13,\n color: theme.legendColor,\n family: \"Inter, sans-serif\",\n weight: 500,\n lineheight: 18,\n },\n },\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: 15,\n },\n gridcolor: gridColor,\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: 15,\n },\n gridcolor: gridColor,\n ...tickOptions,\n },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, plotData, layout, config);\n bindTooltip(plotRef.current);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [width, height, xTitle, yTitle, plotData, titleOptions, tickOptions, gridColor, theme, bindTooltip]);\n\n return (\n <div className=\"dotplot-container relative\" style={{ width: width }}>\n <div\n ref={plotRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n margin: \"0\",\n }}\n />\n {tooltipElement}\n </div>\n );\n};\n\nexport { DotPlot };\nexport type { DotPlotDataSeries, DotPlotProps, DotPlotVariant, MarkerSymbol };\n"],"names":["DotPlot","dataSeries","width","height","title","xTitle","yTitle","variant","markerSize","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","seriesArray","useMemo","defaultColors","CHART_COLORS","defaultSymbols","seriesWithColors","series","index","gridColor","plotData","tickOptions","titleOptions","useEffect","layout","config","Plotly","plotElement","jsx"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react/jsx-runtime"),P=require("plotly.js-dist"),h=require("react"),B=require("../ChartTooltip/ChartTooltip.cjs"),E=require("../../../hooks/use-plotly-theme.cjs"),F=require("../../../utils/colors.cjs");;/* empty css */const O=-.5,T=n=>n.reduce((e,a)=>e+a,0)/n.length,_=(n,l)=>{const a=n.map(s=>Math.pow(s-l,2)).reduce((s,u)=>s+u,0)/n.length;return Math.sqrt(a)},S=(n,l,e,a,s=100)=>{const u=[],x=[],f=(a-e)/(s-1);for(let r=0;r<s;r++){const o=e+r*f;u.push(o);const M=O*Math.pow((o-n)/l,2),v=1/(l*Math.sqrt(2*Math.PI))*Math.exp(M);x.push(v)}return{x:u,y:x}},H=(n,l,e)=>{const a=Math.ceil((e.end-e.start)/e.size),s=Array(a).fill(0);l.forEach(r=>{if(r>=e.start&&r<=e.end){const o=Math.floor((r-e.start)/e.size);s[o]++}});const u=Math.max(...s),x=Math.max(...n),f=u/x;return n.map(r=>r*f)},W=({dataSeries:n,width:l=480,height:e=480,title:a="Histogram",xTitle:s="X Axis",yTitle:u="Frequency",bargap:x=.2,showDistributionLine:f=!1})=>{const r=h.useRef(null),o=E.usePlotlyTheme(),{bindTooltip:M,tooltipElement:v}=B.useChartTooltip({xLabel:s,yLabel:u}),b=h.useMemo(()=>Array.isArray(n)?n:[n],[n]),j=h.useMemo(()=>b.length>1?"stack":void 0,[b.length]),w=F.CHART_COLORS,p=h.useMemo(()=>b.map((t,d)=>{const m=typeof t.showDistributionLine>"u"?f:t.showDistributionLine;return{...t,color:t.color||w[d%w.length],opacity:m?.5:t.opacity||1,showDistributionLine:m,lineWidth:t.lineWidth||3}}),[b,f,w]),C=o.gridColor,q=h.useMemo(()=>p.map(t=>({type:"histogram",x:t.x,name:t.name,marker:{color:t.color,line:{color:o.paperBg,width:1},opacity:t.opacity},autobinx:t.autobinx,xbins:t.xbins,hoverinfo:"none"})),[p,o]),N=h.useMemo(()=>p.filter(t=>t.showDistributionLine).map(t=>{const d=T(t.x),m=_(t.x,d),g=Math.min(...t.x),c=Math.max(...t.x),y=c-g,D=g-y*.1,L=c+y*.1,R=t.xbins||{start:D,end:L,size:y/10},z=S(d,m,D,L,100),A=H(z.y,t.x,R);return{type:"scatter",x:z.x,y:A,mode:"lines",name:`${t.name} Distribution`,line:{color:t.color,width:t.lineWidth},hoverinfo:"none"}}),[p]),k=h.useMemo(()=>[...q,...N],[q,N]);h.useEffect(()=>{if(!r.current)return;const t={width:l,height:e,font:{family:"Inter, sans-serif"},showlegend:!1,margin:{l:90,r:40,b:80,t:40},xaxis:{title:{text:s,font:{size:16,color:o.textSecondary,family:"Inter, sans-serif",weight:400},standoff:20},gridcolor:C,tickcolor:o.tickColor,ticklen:8,tickwidth:1,ticks:"outside",linecolor:o.lineColor,linewidth:1,zeroline:!1},yaxis:{title:{text:u,font:{size:16,color:o.textSecondary,family:"Inter, sans-serif",weight:400},standoff:20},gridcolor:C,tickcolor:o.tickColor,ticklen:8,tickwidth:1,ticks:"outside",linecolor:o.lineColor,linewidth:1,zeroline:!1,rangemode:"tozero"},barmode:j,bargap:x,paper_bgcolor:o.paperBg,plot_bgcolor:o.plotBg},d={responsive:!0,displayModeBar:!1,displaylogo:!1};P.newPlot(r.current,k,t,d),M(r.current);const m=r.current;return()=>{m&&P.purge(m)}},[l,e,s,u,x,k,j,C,o,M]);const I=({series:t})=>{const d=t.map((c,y)=>i.jsx(h.Fragment,{children:i.jsxs("div",{className:"legend-item",children:[i.jsx("span",{className:"color-box",style:{background:c.color}}),c.name,y<t.length-1&&i.jsx("span",{className:"divider"})]})},c.name)),m=[],g=6;for(let c=0;c<d.length;c+=g)m.push(i.jsx("div",{className:"legend-row",children:d.slice(c,c+g)},c));return i.jsx("div",{className:"legend-container",children:m})};return i.jsxs("div",{className:"histogram-container relative",style:{width:l},children:[i.jsxs("div",{className:"chart-container",children:[a&&i.jsx("div",{className:"title-container",children:i.jsx("h2",{className:"title",children:a})}),i.jsx("div",{ref:r,style:{width:"100%",height:"100%",margin:"0"}}),i.jsx(I,{series:p})]}),v]})};exports.Histogram=W;
|
|
2
2
|
//# sourceMappingURL=Histogram.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Histogram.cjs","sources":["../../../../src/components/charts/Histogram/Histogram.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { CHART_COLORS } from \"@/utils/colors\";\nimport \"./Histogram.scss\";\n\n/** Exponent coefficient for normal distribution calculation */\nconst NORMAL_DISTRIBUTION_EXPONENT_COEFF = -0.5;\n\ninterface HistogramDataSeries {\n x: number[];\n name: string;\n color?: string;\n autobinx?: boolean;\n xbins?: {\n start: number;\n end: number;\n size: number;\n };\n opacity?: number;\n showDistributionLine?: boolean;\n lineWidth?: number;\n}\n\ntype HistogramProps = {\n dataSeries: HistogramDataSeries | HistogramDataSeries[];\n width?: number;\n height?: number;\n title?: string;\n xTitle?: string;\n yTitle?: string;\n bargap?: number;\n showDistributionLine?: boolean;\n};\n\nconst calculateMean = (data: number[]): number => {\n const sum = data.reduce((acc, val) => acc + val, 0);\n return sum / data.length;\n};\n\nconst calculateStdDev = (data: number[], mean: number): number => {\n const squaredDiffs = data.map((value) => Math.pow(value - mean, 2));\n const variance =\n squaredDiffs.reduce((acc, val) => acc + val, 0) / data.length;\n return Math.sqrt(variance);\n};\n\nconst generateNormalDistributionPoints = (\n mean: number,\n stdDev: number,\n start: number,\n end: number,\n points = 100\n): { x: number[]; y: number[] } => {\n const xValues: number[] = [];\n const yValues: number[] = [];\n\n const step = (end - start) / (points - 1);\n\n for (let i = 0; i < points; i++) {\n const x = start + i * step;\n xValues.push(x);\n\n const exponent = NORMAL_DISTRIBUTION_EXPONENT_COEFF * Math.pow((x - mean) / stdDev, 2);\n const y = (1 / (stdDev * Math.sqrt(2 * Math.PI))) * Math.exp(exponent);\n yValues.push(y);\n }\n\n return { x: xValues, y: yValues };\n};\n\nconst scaleDistributionCurve = (\n yValues: number[],\n histogramData: number[],\n bins: { start: number; end: number; size: number }\n): number[] => {\n const binCount = Math.ceil((bins.end - bins.start) / bins.size);\n const binFrequencies = Array(binCount).fill(0);\n\n histogramData.forEach((value) => {\n if (value >= bins.start && value <= bins.end) {\n const binIndex = Math.floor((value - bins.start) / bins.size);\n binFrequencies[binIndex]++;\n }\n });\n\n const maxBinFrequency = Math.max(...binFrequencies);\n const maxCurveValue = Math.max(...yValues);\n\n const scaleFactor = maxBinFrequency / maxCurveValue;\n\n return yValues.map((y) => y * scaleFactor);\n};\n\nconst Histogram: React.FC<HistogramProps> = ({\n dataSeries,\n width = 480,\n height = 480,\n title = \"Histogram\",\n xTitle = \"X Axis\",\n yTitle = \"Frequency\",\n bargap = 0.2,\n showDistributionLine = false,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const seriesArray = useMemo(\n () => (Array.isArray(dataSeries) ? dataSeries : [dataSeries]),\n [dataSeries],\n );\n const effectiveBarMode = useMemo<\n \"stack\" | \"group\" | \"overlay\" | \"relative\" | undefined\n >(() => (seriesArray.length > 1 ? \"stack\" : undefined), [seriesArray.length]);\n\n const defaultColors = CHART_COLORS;\n\n const seriesWithColors = useMemo(() => {\n return seriesArray.map((series, index) => {\n const hasDistributionLine =\n typeof series.showDistributionLine === \"undefined\"\n ? showDistributionLine\n : series.showDistributionLine;\n\n return {\n ...series,\n color: series.color || defaultColors[index % defaultColors.length],\n opacity: hasDistributionLine ? 0.5 : series.opacity || 1,\n showDistributionLine: hasDistributionLine,\n lineWidth: series.lineWidth || 3,\n };\n });\n }, [seriesArray, showDistributionLine, defaultColors]);\n\n const gridColor = theme.gridColor;\n\n const histogramData = useMemo(\n () =>\n seriesWithColors.map((series) => ({\n type: \"histogram\" as const,\n x: series.x,\n name: series.name,\n marker: {\n color: series.color,\n line: {\n color: theme.paperBg,\n width: 1,\n },\n opacity: series.opacity,\n },\n autobinx: series.autobinx,\n xbins: series.xbins,\n hovertemplate: `${xTitle}: %{x}<br>${yTitle}: %{y}<extra>${series.name}</extra>`,\n })),\n [seriesWithColors, xTitle, yTitle, theme],\n );\n\n const distributionLines = useMemo(\n () =>\n seriesWithColors\n .filter((series) => series.showDistributionLine)\n .map((series) => {\n const mean = calculateMean(series.x);\n const stdDev = calculateStdDev(series.x, mean);\n\n const min = Math.min(...series.x);\n const max = Math.max(...series.x);\n const range = max - min;\n const start = min - range * 0.1;\n const end = max + range * 0.1;\n\n const bins = series.xbins || {\n start: start,\n end: end,\n size: range / 10,\n };\n\n const curvePoints = generateNormalDistributionPoints(\n mean,\n stdDev,\n start,\n end,\n 100,\n );\n\n const scaledYValues = scaleDistributionCurve(\n curvePoints.y,\n series.x,\n bins,\n );\n\n return {\n type: \"scatter\" as const,\n x: curvePoints.x,\n y: scaledYValues,\n mode: \"lines\" as const,\n name: `${series.name} Distribution`,\n line: {\n color: series.color,\n width: series.lineWidth,\n },\n hoverinfo: \"none\" as const,\n };\n }),\n [seriesWithColors],\n );\n\n const plotData = useMemo(\n () => [...histogramData, ...distributionLines],\n [histogramData, distributionLines],\n );\n\n useEffect(() => {\n if (!plotRef.current) return;\n\n const layout = {\n width,\n height,\n font: {\n family: \"Inter, sans-serif\",\n },\n showlegend: false,\n margin: { l: 90, r: 40, b: 80, t: 40 },\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: 20,\n },\n gridcolor: gridColor,\n tickcolor: theme.tickColor,\n ticklen: 8,\n tickwidth: 1,\n ticks: \"outside\" as const,\n linecolor: theme.lineColor,\n linewidth: 1,\n zeroline: false,\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: 20,\n },\n gridcolor: gridColor,\n tickcolor: theme.tickColor,\n ticklen: 8,\n tickwidth: 1,\n ticks: \"outside\" as const,\n linecolor: theme.lineColor,\n linewidth: 1,\n zeroline: false,\n rangemode: \"tozero\" as const,\n },\n barmode: effectiveBarMode,\n bargap: bargap,\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, plotData, layout, config);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [width, height, xTitle, yTitle, bargap, plotData, effectiveBarMode, gridColor, theme]);\n\n const ChartLegend: React.FC<{\n series: Array<{ name: string; color: string }>;\n }> = ({ series }) => {\n const items = series.map((item, i) => (\n <React.Fragment key={item.name}>\n <div className=\"legend-item\">\n <span className=\"color-box\" style={{ background: item.color }} />\n {item.name}\n {i < series.length - 1 && <span className=\"divider\" />}\n </div>\n </React.Fragment>\n ));\n\n const rows = [];\n const rowSize = 6;\n for (let i = 0; i < items.length; i += rowSize) {\n rows.push(\n <div className=\"legend-row\" key={i}>\n {items.slice(i, i + rowSize)}\n </div>\n );\n }\n\n return <div className=\"legend-container\">{rows}</div>;\n };\n\n return (\n <div className=\"histogram-container\" style={{ width: width }}>\n <div className=\"chart-container\">\n {title && (\n <div className=\"title-container\">\n <h2 className=\"title\">{title}</h2>\n </div>\n )}\n <div\n ref={plotRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n margin: \"0\",\n }}\n />\n <ChartLegend series={seriesWithColors} />\n </div>\n </div>\n );\n};\n\nexport { Histogram };\nexport type { HistogramDataSeries, HistogramProps };\n"],"names":["NORMAL_DISTRIBUTION_EXPONENT_COEFF","calculateMean","data","acc","val","calculateStdDev","mean","variance","value","generateNormalDistributionPoints","stdDev","start","end","points","xValues","yValues","step","i","x","exponent","y","scaleDistributionCurve","histogramData","bins","binCount","binFrequencies","binIndex","maxBinFrequency","maxCurveValue","scaleFactor","Histogram","dataSeries","width","height","title","xTitle","yTitle","bargap","showDistributionLine","plotRef","useRef","theme","usePlotlyTheme","seriesArray","useMemo","effectiveBarMode","defaultColors","CHART_COLORS","seriesWithColors","series","index","hasDistributionLine","gridColor","distributionLines","min","max","range","curvePoints","scaledYValues","plotData","useEffect","layout","config","Plotly","plotElement","ChartLegend","items","item","jsx","React","jsxs","rows","rowSize"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Histogram.cjs","sources":["../../../../src/components/charts/Histogram/Histogram.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 \"./Histogram.scss\";\n\n/** Exponent coefficient for normal distribution calculation */\nconst NORMAL_DISTRIBUTION_EXPONENT_COEFF = -0.5;\n\ninterface HistogramDataSeries {\n x: number[];\n name: string;\n color?: string;\n autobinx?: boolean;\n xbins?: {\n start: number;\n end: number;\n size: number;\n };\n opacity?: number;\n showDistributionLine?: boolean;\n lineWidth?: number;\n}\n\ntype HistogramProps = {\n dataSeries: HistogramDataSeries | HistogramDataSeries[];\n width?: number;\n height?: number;\n title?: string;\n xTitle?: string;\n yTitle?: string;\n bargap?: number;\n showDistributionLine?: boolean;\n};\n\nconst calculateMean = (data: number[]): number => {\n const sum = data.reduce((acc, val) => acc + val, 0);\n return sum / data.length;\n};\n\nconst calculateStdDev = (data: number[], mean: number): number => {\n const squaredDiffs = data.map((value) => Math.pow(value - mean, 2));\n const variance =\n squaredDiffs.reduce((acc, val) => acc + val, 0) / data.length;\n return Math.sqrt(variance);\n};\n\nconst generateNormalDistributionPoints = (\n mean: number,\n stdDev: number,\n start: number,\n end: number,\n points = 100\n): { x: number[]; y: number[] } => {\n const xValues: number[] = [];\n const yValues: number[] = [];\n\n const step = (end - start) / (points - 1);\n\n for (let i = 0; i < points; i++) {\n const x = start + i * step;\n xValues.push(x);\n\n const exponent = NORMAL_DISTRIBUTION_EXPONENT_COEFF * Math.pow((x - mean) / stdDev, 2);\n const y = (1 / (stdDev * Math.sqrt(2 * Math.PI))) * Math.exp(exponent);\n yValues.push(y);\n }\n\n return { x: xValues, y: yValues };\n};\n\nconst scaleDistributionCurve = (\n yValues: number[],\n histogramData: number[],\n bins: { start: number; end: number; size: number }\n): number[] => {\n const binCount = Math.ceil((bins.end - bins.start) / bins.size);\n const binFrequencies = Array(binCount).fill(0);\n\n histogramData.forEach((value) => {\n if (value >= bins.start && value <= bins.end) {\n const binIndex = Math.floor((value - bins.start) / bins.size);\n binFrequencies[binIndex]++;\n }\n });\n\n const maxBinFrequency = Math.max(...binFrequencies);\n const maxCurveValue = Math.max(...yValues);\n\n const scaleFactor = maxBinFrequency / maxCurveValue;\n\n return yValues.map((y) => y * scaleFactor);\n};\n\nconst Histogram: React.FC<HistogramProps> = ({\n dataSeries,\n width = 480,\n height = 480,\n title = \"Histogram\",\n xTitle = \"X Axis\",\n yTitle = \"Frequency\",\n bargap = 0.2,\n showDistributionLine = false,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const { bindTooltip, tooltipElement } = useChartTooltip({ xLabel: xTitle, yLabel: yTitle });\n const seriesArray = useMemo(\n () => (Array.isArray(dataSeries) ? dataSeries : [dataSeries]),\n [dataSeries],\n );\n const effectiveBarMode = useMemo<\n \"stack\" | \"group\" | \"overlay\" | \"relative\" | undefined\n >(() => (seriesArray.length > 1 ? \"stack\" : undefined), [seriesArray.length]);\n\n const defaultColors = CHART_COLORS;\n\n const seriesWithColors = useMemo(() => {\n return seriesArray.map((series, index) => {\n const hasDistributionLine =\n typeof series.showDistributionLine === \"undefined\"\n ? showDistributionLine\n : series.showDistributionLine;\n\n return {\n ...series,\n color: series.color || defaultColors[index % defaultColors.length],\n opacity: hasDistributionLine ? 0.5 : series.opacity || 1,\n showDistributionLine: hasDistributionLine,\n lineWidth: series.lineWidth || 3,\n };\n });\n }, [seriesArray, showDistributionLine, defaultColors]);\n\n const gridColor = theme.gridColor;\n\n const histogramData = useMemo(\n () =>\n seriesWithColors.map((series) => ({\n type: \"histogram\" as const,\n x: series.x,\n name: series.name,\n marker: {\n color: series.color,\n line: {\n color: theme.paperBg,\n width: 1,\n },\n opacity: series.opacity,\n },\n autobinx: series.autobinx,\n xbins: series.xbins,\n hoverinfo: \"none\" as const,\n })),\n [seriesWithColors, theme],\n );\n\n const distributionLines = useMemo(\n () =>\n seriesWithColors\n .filter((series) => series.showDistributionLine)\n .map((series) => {\n const mean = calculateMean(series.x);\n const stdDev = calculateStdDev(series.x, mean);\n\n const min = Math.min(...series.x);\n const max = Math.max(...series.x);\n const range = max - min;\n const start = min - range * 0.1;\n const end = max + range * 0.1;\n\n const bins = series.xbins || {\n start: start,\n end: end,\n size: range / 10,\n };\n\n const curvePoints = generateNormalDistributionPoints(\n mean,\n stdDev,\n start,\n end,\n 100,\n );\n\n const scaledYValues = scaleDistributionCurve(\n curvePoints.y,\n series.x,\n bins,\n );\n\n return {\n type: \"scatter\" as const,\n x: curvePoints.x,\n y: scaledYValues,\n mode: \"lines\" as const,\n name: `${series.name} Distribution`,\n line: {\n color: series.color,\n width: series.lineWidth,\n },\n hoverinfo: \"none\" as const,\n };\n }),\n [seriesWithColors],\n );\n\n const plotData = useMemo(\n () => [...histogramData, ...distributionLines],\n [histogramData, distributionLines],\n );\n\n useEffect(() => {\n if (!plotRef.current) return;\n\n const layout = {\n width,\n height,\n font: {\n family: \"Inter, sans-serif\",\n },\n showlegend: false,\n margin: { l: 90, r: 40, b: 80, t: 40 },\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: 20,\n },\n gridcolor: gridColor,\n tickcolor: theme.tickColor,\n ticklen: 8,\n tickwidth: 1,\n ticks: \"outside\" as const,\n linecolor: theme.lineColor,\n linewidth: 1,\n zeroline: false,\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: 20,\n },\n gridcolor: gridColor,\n tickcolor: theme.tickColor,\n ticklen: 8,\n tickwidth: 1,\n ticks: \"outside\" as const,\n linecolor: theme.lineColor,\n linewidth: 1,\n zeroline: false,\n rangemode: \"tozero\" as const,\n },\n barmode: effectiveBarMode,\n bargap: bargap,\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, plotData, layout, config);\n bindTooltip(plotRef.current);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [width, height, xTitle, yTitle, bargap, plotData, effectiveBarMode, gridColor, theme, bindTooltip]);\n\n const ChartLegend: React.FC<{\n series: Array<{ name: string; color: string }>;\n }> = ({ series }) => {\n const items = series.map((item, i) => (\n <React.Fragment key={item.name}>\n <div className=\"legend-item\">\n <span className=\"color-box\" style={{ background: item.color }} />\n {item.name}\n {i < series.length - 1 && <span className=\"divider\" />}\n </div>\n </React.Fragment>\n ));\n\n const rows = [];\n const rowSize = 6;\n for (let i = 0; i < items.length; i += rowSize) {\n rows.push(\n <div className=\"legend-row\" key={i}>\n {items.slice(i, i + rowSize)}\n </div>\n );\n }\n\n return <div className=\"legend-container\">{rows}</div>;\n };\n\n return (\n <div className=\"histogram-container relative\" style={{ width: width }}>\n <div className=\"chart-container\">\n {title && (\n <div className=\"title-container\">\n <h2 className=\"title\">{title}</h2>\n </div>\n )}\n <div\n ref={plotRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n margin: \"0\",\n }}\n />\n <ChartLegend series={seriesWithColors} />\n </div>\n {tooltipElement}\n </div>\n );\n};\n\nexport { Histogram };\nexport type { HistogramDataSeries, HistogramProps };\n"],"names":["NORMAL_DISTRIBUTION_EXPONENT_COEFF","calculateMean","data","acc","val","calculateStdDev","mean","variance","value","generateNormalDistributionPoints","stdDev","start","end","points","xValues","yValues","step","i","x","exponent","y","scaleDistributionCurve","histogramData","bins","binCount","binFrequencies","binIndex","maxBinFrequency","maxCurveValue","scaleFactor","Histogram","dataSeries","width","height","title","xTitle","yTitle","bargap","showDistributionLine","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","seriesArray","useMemo","effectiveBarMode","defaultColors","CHART_COLORS","seriesWithColors","series","index","hasDistributionLine","gridColor","distributionLines","min","max","range","curvePoints","scaledYValues","plotData","useEffect","layout","config","Plotly","plotElement","ChartLegend","items","item","jsx","React","jsxs","rows","rowSize"],"mappings":"0UAUA,MAAMA,EAAqC,IA4BrCC,EAAiBC,GACTA,EAAK,OAAO,CAACC,EAAKC,IAAQD,EAAMC,EAAK,CAAC,EACrCF,EAAK,OAGdG,EAAkB,CAACH,EAAgBI,IAAyB,CAEhE,MAAMC,EADeL,EAAK,IAAKM,GAAU,KAAK,IAAIA,EAAQF,EAAM,CAAC,CAAC,EAEnD,OAAO,CAACH,EAAKC,IAAQD,EAAMC,EAAK,CAAC,EAAIF,EAAK,OACzD,OAAO,KAAK,KAAKK,CAAQ,CAC3B,EAEME,EAAmC,CACvCH,EACAI,EACAC,EACAC,EACAC,EAAS,MACwB,CACjC,MAAMC,EAAoB,CAAA,EACpBC,EAAoB,CAAA,EAEpBC,GAAQJ,EAAMD,IAAUE,EAAS,GAEvC,QAASI,EAAI,EAAGA,EAAIJ,EAAQI,IAAK,CAC/B,MAAMC,EAAIP,EAAQM,EAAID,EACtBF,EAAQ,KAAKI,CAAC,EAEd,MAAMC,EAAWnB,EAAqC,KAAK,KAAKkB,EAAIZ,GAAQI,EAAQ,CAAC,EAC/EU,EAAK,GAAKV,EAAS,KAAK,KAAK,EAAI,KAAK,EAAE,GAAM,KAAK,IAAIS,CAAQ,EACrEJ,EAAQ,KAAKK,CAAC,CAChB,CAEA,MAAO,CAAE,EAAGN,EAAS,EAAGC,CAAA,CAC1B,EAEMM,EAAyB,CAC7BN,EACAO,EACAC,IACa,CACb,MAAMC,EAAW,KAAK,MAAMD,EAAK,IAAMA,EAAK,OAASA,EAAK,IAAI,EACxDE,EAAiB,MAAMD,CAAQ,EAAE,KAAK,CAAC,EAE7CF,EAAc,QAASd,GAAU,CAC/B,GAAIA,GAASe,EAAK,OAASf,GAASe,EAAK,IAAK,CAC5C,MAAMG,EAAW,KAAK,OAAOlB,EAAQe,EAAK,OAASA,EAAK,IAAI,EAC5DE,EAAeC,CAAQ,GACzB,CACF,CAAC,EAED,MAAMC,EAAkB,KAAK,IAAI,GAAGF,CAAc,EAC5CG,EAAgB,KAAK,IAAI,GAAGb,CAAO,EAEnCc,EAAcF,EAAkBC,EAEtC,OAAOb,EAAQ,IAAKK,GAAMA,EAAIS,CAAW,CAC3C,EAEMC,EAAsC,CAAC,CAC3C,WAAAC,EACA,MAAAC,EAAQ,IACR,OAAAC,EAAS,IACT,MAAAC,EAAQ,YACR,OAAAC,EAAS,SACT,OAAAC,EAAS,YACT,OAAAC,EAAS,GACT,qBAAAC,EAAuB,EACzB,IAAM,CACJ,MAAMC,EAAUC,EAAAA,OAAuB,IAAI,EACrCC,EAAQC,EAAAA,eAAA,EACR,CAAE,YAAAC,EAAa,eAAAC,CAAA,EAAmBC,EAAAA,gBAAgB,CAAE,OAAQV,EAAQ,OAAQC,EAAQ,EACpFU,EAAcC,EAAAA,QAClB,IAAO,MAAM,QAAQhB,CAAU,EAAIA,EAAa,CAACA,CAAU,EAC3D,CAACA,CAAU,CAAA,EAEPiB,EAAmBD,EAAAA,QAEvB,IAAOD,EAAY,OAAS,EAAI,QAAU,OAAY,CAACA,EAAY,MAAM,CAAC,EAEtEG,EAAgBC,EAAAA,aAEhBC,EAAmBJ,EAAAA,QAAQ,IACxBD,EAAY,IAAI,CAACM,EAAQC,IAAU,CACxC,MAAMC,EACJ,OAAOF,EAAO,qBAAyB,IACnCd,EACAc,EAAO,qBAEb,MAAO,CACL,GAAGA,EACH,MAAOA,EAAO,OAASH,EAAcI,EAAQJ,EAAc,MAAM,EACjE,QAASK,EAAsB,GAAMF,EAAO,SAAW,EACvD,qBAAsBE,EACtB,UAAWF,EAAO,WAAa,CAAA,CAEnC,CAAC,EACA,CAACN,EAAaR,EAAsBW,CAAa,CAAC,EAE/CM,EAAYd,EAAM,UAElBnB,EAAgByB,EAAAA,QACpB,IACEI,EAAiB,IAAKC,IAAY,CAChC,KAAM,YACN,EAAGA,EAAO,EACV,KAAMA,EAAO,KACb,OAAQ,CACN,MAAOA,EAAO,MACd,KAAM,CACJ,MAAOX,EAAM,QACb,MAAO,CAAA,EAET,QAASW,EAAO,OAAA,EAElB,SAAUA,EAAO,SACjB,MAAOA,EAAO,MACd,UAAW,MAAA,EACX,EACJ,CAACD,EAAkBV,CAAK,CAAA,EAGpBe,EAAoBT,EAAAA,QACxB,IACEI,EACG,OAAQC,GAAWA,EAAO,oBAAoB,EAC9C,IAAKA,GAAW,CACf,MAAM9C,EAAOL,EAAcmD,EAAO,CAAC,EAC7B1C,EAASL,EAAgB+C,EAAO,EAAG9C,CAAI,EAEvCmD,EAAM,KAAK,IAAI,GAAGL,EAAO,CAAC,EAC1BM,EAAM,KAAK,IAAI,GAAGN,EAAO,CAAC,EAC1BO,EAAQD,EAAMD,EACd9C,EAAQ8C,EAAME,EAAQ,GACtB/C,EAAM8C,EAAMC,EAAQ,GAEpBpC,EAAO6B,EAAO,OAAS,CAC3B,MAAAzC,EACA,IAAAC,EACA,KAAM+C,EAAQ,EAAA,EAGVC,EAAcnD,EAClBH,EACAI,EACAC,EACAC,EACA,GAAA,EAGIiD,EAAgBxC,EACpBuC,EAAY,EACZR,EAAO,EACP7B,CAAA,EAGF,MAAO,CACL,KAAM,UACN,EAAGqC,EAAY,EACf,EAAGC,EACH,KAAM,QACN,KAAM,GAAGT,EAAO,IAAI,gBACpB,KAAM,CACJ,MAAOA,EAAO,MACd,MAAOA,EAAO,SAAA,EAEhB,UAAW,MAAA,CAEf,CAAC,EACL,CAACD,CAAgB,CAAA,EAGbW,EAAWf,EAAAA,QACf,IAAM,CAAC,GAAGzB,EAAe,GAAGkC,CAAiB,EAC7C,CAAClC,EAAekC,CAAiB,CAAA,EAGnCO,EAAAA,UAAU,IAAM,CACd,GAAI,CAACxB,EAAQ,QAAS,OAEtB,MAAMyB,EAAS,CACb,MAAAhC,EACA,OAAAC,EACA,KAAM,CACJ,OAAQ,mBAAA,EAEV,WAAY,GACZ,OAAQ,CAAE,EAAG,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,EAAA,EAClC,MAAO,CACL,MAAO,CACL,KAAME,EACN,KAAM,CACJ,KAAM,GACN,MAAOM,EAAM,cACb,OAAQ,oBACR,OAAQ,GAAA,EAEV,SAAU,EAAA,EAEZ,UAAWc,EACX,UAAWd,EAAM,UACjB,QAAS,EACT,UAAW,EACX,MAAO,UACP,UAAWA,EAAM,UACjB,UAAW,EACX,SAAU,EAAA,EAEZ,MAAO,CACL,MAAO,CACL,KAAML,EACN,KAAM,CACJ,KAAM,GACN,MAAOK,EAAM,cACb,OAAQ,oBACR,OAAQ,GAAA,EAEV,SAAU,EAAA,EAEZ,UAAWc,EACX,UAAWd,EAAM,UACjB,QAAS,EACT,UAAW,EACX,MAAO,UACP,UAAWA,EAAM,UACjB,UAAW,EACX,SAAU,GACV,UAAW,QAAA,EAEb,QAASO,EACT,OAAAX,EACA,cAAeI,EAAM,QACrB,aAAcA,EAAM,MAAA,EAGhBwB,EAAS,CACb,WAAY,GACZ,eAAgB,GAChB,YAAa,EAAA,EAGfC,EAAO,QAAQ3B,EAAQ,QAASuB,EAAUE,EAAQC,CAAM,EACxDtB,EAAYJ,EAAQ,OAAO,EAG3B,MAAM4B,EAAc5B,EAAQ,QAE5B,MAAO,IAAM,CACP4B,GACFD,EAAO,MAAMC,CAAW,CAE5B,CACF,EAAG,CAACnC,EAAOC,EAAQE,EAAQC,EAAQC,EAAQyB,EAAUd,EAAkBO,EAAWd,EAAOE,CAAW,CAAC,EAErG,MAAMyB,EAED,CAAC,CAAE,OAAAhB,KAAa,CACnB,MAAMiB,EAAQjB,EAAO,IAAI,CAACkB,EAAMrD,IAC9BsD,MAACC,EAAM,SAAN,CACC,SAAAC,OAAC,MAAA,CAAI,UAAU,cACb,SAAA,CAAAF,MAAC,OAAA,CAAK,UAAU,YAAY,MAAO,CAAE,WAAYD,EAAK,OAAS,EAC9DA,EAAK,KACLrD,EAAImC,EAAO,OAAS,GAAKmB,EAAAA,IAAC,OAAA,CAAK,UAAU,SAAA,CAAU,CAAA,CAAA,CACtD,CAAA,EALmBD,EAAK,IAM1B,CACD,EAEKI,EAAO,CAAA,EACPC,EAAU,EAChB,QAAS1D,EAAI,EAAGA,EAAIoD,EAAM,OAAQpD,GAAK0D,EACrCD,EAAK,KACHH,EAAAA,IAAC,MAAA,CAAI,UAAU,aACZ,SAAAF,EAAM,MAAMpD,EAAGA,EAAI0D,CAAO,CAAA,EADI1D,CAEjC,CAAA,EAIJ,OAAOsD,EAAAA,IAAC,MAAA,CAAI,UAAU,mBAAoB,SAAAG,EAAK,CACjD,EAEA,cACG,MAAA,CAAI,UAAU,+BAA+B,MAAO,CAAE,MAAA1C,GACrD,SAAA,CAAAyC,EAAAA,KAAC,MAAA,CAAI,UAAU,kBACZ,SAAA,CAAAvC,GACCqC,EAAAA,IAAC,OAAI,UAAU,kBACb,eAAC,KAAA,CAAG,UAAU,QAAS,SAAArC,CAAA,CAAM,CAAA,CAC/B,EAEFqC,EAAAA,IAAC,MAAA,CACC,IAAKhC,EACL,MAAO,CACL,MAAO,OACP,OAAQ,OACR,OAAQ,GAAA,CACV,CAAA,EAEFgC,EAAAA,IAACH,EAAA,CAAY,OAAQjB,CAAA,CAAkB,CAAA,EACzC,EACCP,CAAA,EACH,CAEJ"}
|